ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/server/uk/org/iscream/cms/server/core/ConfigurationManagerServant.java
Revision: 1.20
Committed: Mon Dec 10 22:49:19 2001 UTC (22 years, 5 months ago) by tdb
Branch: MAIN
Changes since 1.19: +7 -83 lines
Log Message:
Pulled out the wildcardCheck method because it's rather more generic than
it's use in the ConfigurationManagerServant. I still need to tidy some of
the comments and variable names to abstract it a bit more, and I might also
remove it taking a semi-colon seperated list - that's more behaviour of the
configuration system. It's a start, and I'll remember to do the rest when I
read this commit message tomorrow :)

File Contents

# User Rev Content
1 ajm 1.3 //---PACKAGE DECLARATION---
2 tdb 1.18 package uk.org.iscream.cms.server.core;
3 ajm 1.3
4     //---IMPORTS---
5 tdb 1.18 import uk.org.iscream.cms.server.util.*;
6     import uk.org.iscream.cms.server.componentmanager.*;
7 ajm 1.15 import java.net.InetAddress;
8     import java.net.UnknownHostException;
9 ajm 1.3 import java.util.*;
10     import java.io.*;
11    
12     /**
13     * This class is essentially a Configuration factory.
14     * This class implements the Configurator IDL and allows
15     * other classes in the system ot obtain their Configuration
16     *
17     * On construction it requires a reference to the RootPOA
18     * to allow it to create Configuration objects to be
19     * returned.
20     *
21     * It also relies on the System.properties to set internal values.
22     *
23 ajm 1.6 * ###
24     * A point to note is that this class does NOT yet manage
25     * created configurations which may cause memory problems!
26     * ###
27     *
28 tdb 1.20 * @author $Author: tdb $
29     * @version $Id: ConfigurationManagerServant.java,v 1.19 2001/12/10 22:20:23 tdb Exp $
30 ajm 1.3 */
31     class ConfigurationManagerServant extends ConfigurationManagerPOA {
32    
33     //---FINAL ATTRIBUTES---
34    
35     /**
36     * The current CVS revision of this class
37     */
38 tdb 1.20 public final String REVISION = "$Revision: 1.19 $";
39 ajm 1.3
40     //---STATIC METHODS---
41    
42     //---CONSTRUCTORS---
43    
44     /**
45     * Creates a new ConfiguratorServant
46     * This class uses the System.properties to set internal values
47     */
48 ajm 1.6 ConfigurationManagerServant() {
49 ajm 1.3 // assign some local variables
50 tdb 1.18 _configPath = System.getProperty("uk.org.iscream.cms.server.ConfigurationLocation");
51     _systemConfigFile = System.getProperty("uk.org.iscream.cms.server.SystemConfigurationFile");
52 ajm 1.3
53     // load the system config
54     loadSystemConfig();
55    
56     // log our status
57 ajm 1.6 _logger.write(toString(), Logger.SYSINIT, "started");
58     _logger.write(toString(), Logger.SYSMSG, "configuration location - " + _configPath);
59     _logger.write(toString(), Logger.SYSMSG, "system configuration file - " + _systemConfigFile);
60 ajm 1.3 }
61    
62     //---PUBLIC METHODS---
63    
64     /**
65     * Returns a Configuration object which contains
66     * the configuration data requested by the calling
67     * object.
68     *
69     * This method will look in the systemConfig file
70     * for an entry for this "source", if there is no
71     * entry it returns a refernce to the system
72     * config. If there are any errors in reading the
73     * configuration, it returns null, the caller is
74     * expected to be able to handle this.
75     *
76     * This method also checks to see if the system.conf
77     * file has been updated and reloads its reference if
78     * needed.
79     *
80     * @param source the configuration required
81     * @return the Configuration
82     */
83     public Configuration getConfiguration(String source) {
84 ajm 1.6 _logger.write(toString(), Logger.SYSMSG, "got request for " + source);
85 ajm 1.8
86 ajm 1.3
87     // check to see if we need to reload the system config
88     // because it has changed
89     if (isModified(_systemConfig.getFileList(), _systemConfig.getLastModified())) {
90 ajm 1.6 _logger.write(toString(), Logger.SYSMSG, "system config changed");
91 ajm 1.3 loadSystemConfig();
92     }
93    
94 ajm 1.8 // search config for group membership
95 tdb 1.17 // and obain a list of groups by name
96     LinkedList nameGroups = getGroupMembership(source);
97     // add the hosts individual config to the start of the list
98     nameGroups.addFirst(source);
99 ajm 1.15
100 tdb 1.17 // this list will be used to compile the groupings
101     LinkedList groups = new LinkedList();
102    
103 ajm 1.15 // if we are dealing with a Host.<hostname> request, then we also
104     // want to look for ip address details, as configuration entries may relate to it
105     // if we can't resolve it, we don't look.
106 tdb 1.17 LinkedList ipGroups = null;
107 ajm 1.15 if (source.startsWith("Host.")) {
108     // hostname is after Host.
109     String hostname = source.substring(5);
110     try {
111     String ip = "Host." + InetAddress.getByName(hostname).getHostAddress();
112 tdb 1.17 ipGroups = getGroupMembership(ip);
113     ipGroups.addFirst(ip);
114     // add to our list of groups
115 ajm 1.15 groups.addAll(ipGroups);
116     } catch (UnknownHostException e) {
117     _logger.write(toString(), Logger.ERROR, "could not resolve hostname - " + hostname);
118     }
119     }
120 tdb 1.17
121     // add the rest of the groups to the end
122     groups.addAll(nameGroups);
123 ajm 1.3
124 ajm 1.8 Iterator i = groups.iterator();
125     String fileList = "";
126     while (i.hasNext()) {
127     String groupName = (String) i.next();
128 ajm 1.11 _logger.write(toString(), Logger.DEBUG, "looking for config entry for - " + groupName);
129 ajm 1.8 // we look for this entry in the systemConfig
130     String configFile = _systemConfig.getProperty("config." + groupName);
131 ajm 1.11 // if there is a config entry then
132     if (configFile != null) {
133     _logger.write(toString(), Logger.DEBUG, "looking for config tree in - " + configFile);
134    
135     // get the file list of includes etc + the system config
136     String groupFileList = null;
137     try {
138     groupFileList = getIncludedFiles(configFile, "") + ";";
139     } catch (Exception e) {
140     // not sure what to do here
141     // so we just log the error
142     _logger.write(toString(), Logger.ERROR, "ERROR - " + e);
143     }
144     if (groupFileList != null) {
145     fileList += groupFileList;
146     }
147     } else {
148     _logger.write(toString(), Logger.DEBUG, "no config entry for - " + groupName);
149 tdb 1.12 }
150 ajm 1.3 }
151 ajm 1.8 // add the system config as the final check
152 tdb 1.13 fileList = _systemConfigFile + ";" + fileList;
153 ajm 1.8 _logger.write(toString(), Logger.DEBUG, "config tree - " + fileList);
154    
155     // build the configuration
156     Configuration config = buildConfiguration(fileList);
157 ajm 1.3
158     // if this is null at this point, then there will have been an error
159     return config;
160     }
161    
162    
163     /**
164     * When passed a file list and a current value for the lastModified
165     * of the current configuration, this method compares the value
166     * to the actual value of the configuration files to determine
167     * whether or not the configuration has been modified.
168     *
169     * @param fileList a list of files that the caller uses for configuration
170     * @param lastModified the last modified date of the callers configuration
171     *
172     * @return whether or not the configuration has been modified
173     */
174     public boolean isModified(String fileList, long lastModified) {
175     StringTokenizer st = new StringTokenizer(fileList, ";");
176     long newLastModified;
177     File currentFile;
178     while (st.hasMoreTokens()) {
179     currentFile = new File(_configPath, st.nextToken());
180     newLastModified = currentFile.lastModified();
181     if (newLastModified > lastModified) {
182     return true;
183     }
184     }
185     return false;
186     }
187 ajm 1.6
188 ajm 1.3 /**
189     * Overrides the {@link java.lang.Object#toString() Object.toString()}
190     * method to provide clean logging (every class should have this).
191     *
192 tdb 1.18 * This uses the uk.org.iscream.cms.server.util.FormatName class
193 ajm 1.6 * to format the toString()
194     *
195 ajm 1.3 * @return the name of this class and its CVS revision
196     */
197     public String toString() {
198 ajm 1.6 return FormatName.getName(
199     _name,
200     getClass().getName(),
201     REVISION);
202 ajm 1.3 }
203    
204     //---PRIVATE METHODS---
205    
206     /**
207     * This is a recursive function private to this class.
208     * It constructs a hierarchy of files as a ";" serperated
209     * string which can be used to read in the configuration.
210     * This function calls itself.
211     *
212     * @param currentFile the current file to be processed
213 ajm 1.4 * @param readFiles used for recursion purposes only, these are the files it has read so far
214     *
215 ajm 1.3 * @return the current list that has been constructed
216     *
217     * @throws IOException if there is trouble reading the file
218     * @throws FileNotFoundException is there is trouble finding the file
219 ajm 1.4 * @throws CircularIncludeException this is if a circular include is detected
220 ajm 1.3 */
221 ajm 1.4 private String getIncludedFiles(String currentFile, String readFiles) throws IOException, FileNotFoundException, Exception {
222    
223     // check for circular include here
224     if (hasDuplicate(currentFile, readFiles) || currentFile.equals(_systemConfigFile)) {
225     throw new CircularIncludeException(currentFile + " is included more than once");
226     }
227    
228     // if there wasn't, we're gonna use this file, so make a note of it as read
229     // (note the use of the ";", this is for the hasDuplicate, function)
230     readFiles = readFiles + currentFile + ";";
231    
232 ajm 1.3 Properties properties = new Properties();
233     properties.load(new FileInputStream(new File(_configPath, currentFile)));
234 ajm 1.4
235     // get the include property
236 ajm 1.3 String includes = properties.getProperty("include");
237 ajm 1.4
238     // if we're the last file with no includes, return our name
239 ajm 1.3 if (includes == null) {
240     return currentFile;
241 ajm 1.4
242     // otherwise, recurse over our includes
243 ajm 1.3 } else {
244     StringTokenizer st = new StringTokenizer(includes, ";");
245     String returnList= "";
246     while (st.hasMoreTokens()) {
247 ajm 1.4 returnList = getIncludedFiles(st.nextToken(), readFiles) + ";" + returnList;
248 ajm 1.3 }
249 ajm 1.4
250 ajm 1.3 return returnList + currentFile;
251     }
252     }
253    
254     /**
255 ajm 1.4 * This simple method checks to see if a given
256     * file exists in the given list.
257     *
258     * @param file the file to check the list for
259     * @param fileList the list to check
260     *
261     * @return if the given file appeard in the list
262     */
263     private boolean hasDuplicate(String file, String fileList) {
264     StringTokenizer st = new StringTokenizer(fileList, ";");
265     while (st.hasMoreTokens()) {
266     if (file.equals(st.nextToken())) {
267     return true;
268     }
269     }
270     return false;
271     }
272    
273     /**
274 ajm 1.3 * Opens and loads the system configuration into the
275     * local reference _systemConfig
276     */
277     private void loadSystemConfig() {
278 ajm 1.6 _logger.write(this.toString(), Logger.SYSMSG, "reloading " + _systemConfigFile);
279 ajm 1.3 // get a reference to the system config and store it
280     try {
281     // create the properties for the configuration
282     File systemConfigFile = new File(_configPath, _systemConfigFile);
283 ajm 1.8 _systemConfigHolder = new Properties();
284     _systemConfigHolder.load(new FileInputStream(systemConfigFile));
285    
286 ajm 1.3 // create the servant
287 ajm 1.8 ConfigurationServant ref = new ConfigurationServant(_systemConfigHolder, _systemConfigFile, systemConfigFile.lastModified());
288 ajm 1.6 org.omg.CORBA.Object objRef = _refman.getRootPOA().servant_to_reference(ref);
289 ajm 1.3
290     // narrow it to a Configuration
291     _systemConfig = ConfigurationHelper.narrow(objRef);
292    
293     } catch (Exception e) {
294 ajm 1.6 _logger.write(toString(), Logger.FATAL, "ERROR: " + e.getMessage());
295 ajm 1.3 }
296     }
297    
298 ajm 1.8 /**
299     * Parses the system configuration file
300     * for group membership entries.
301     *
302     * It looks for all entries of group.<name>
303     * which contain the given source name
304     *
305     * @param source the source to find membership for
306     *
307     * @return the list of groups that this source is a member of
308     */
309     private LinkedList getGroupMembership(String source) {
310 tdb 1.20 _logger.write(toString(), Logger.DEBUG, "searching groups for - " + source);
311 ajm 1.8 LinkedList groupMembership = new LinkedList();
312     Iterator i = new TreeSet(_systemConfigHolder.keySet()).iterator();
313     while(i.hasNext()) {
314     String key = (String) i.next();
315     if (key.startsWith("group.")) {
316     String group = _systemConfig.getProperty(key);
317 ajm 1.15 // if it is in the group
318 ajm 1.8 if (group.indexOf(source) != -1) {
319     groupMembership.add(key.substring(6));
320 tdb 1.20 _logger.write(toString(), Logger.DEBUG, "group match found for - " + source + " in - " + key);
321 ajm 1.15
322     // if there are wildcards in the group
323     } else if (group.indexOf("*") != -1) {
324     // check the wildcards apply to this srce
325 tdb 1.20 if(StringUtils.wildcardCheck(source, group)) {
326 ajm 1.15 groupMembership.add(key.substring(6));
327 tdb 1.20 _logger.write(toString(), Logger.DEBUG, "wildcard group match found for - " + source + " in - " + key);
328 ajm 1.15 }
329 ajm 1.8 }
330 ajm 1.15
331 ajm 1.8 }
332     }
333     return groupMembership;
334 ajm 1.15 }
335 ajm 1.8
336     /**
337     * Build the properties as a Configuration to be
338     * returned to the caller
339     *
340     * @param fileList the list of files to build the configuration from
341     *
342     * @return the built Configuration
343     */
344     private Configuration buildConfiguration(String fileList) {
345     Configuration config = null;
346    
347     // if there is an entry
348 ajm 1.10 if (!fileList.equals("")) {
349 ajm 1.8 try {
350    
351     // build the properites here from the filelist....
352     StringTokenizer st = new StringTokenizer(fileList, ";");
353    
354     // some holders for variables
355     File currentFile;
356 tdb 1.14 long lastModified = 0, newLastModified = 0;
357     Properties properties = null, prevProperties = null;
358 ajm 1.8
359     // the root of all configurations will be the system config
360     // so we need to open the properties of that
361     Properties defaultProperties = new Properties();
362    
363     // This loop then iterates over the file list
364     // creates the properties to be passed to the
365     // Configuration constructor
366 tdb 1.13 while (st.hasMoreTokens()) {
367 ajm 1.8 properties = new Properties(defaultProperties);
368     currentFile = new File(_configPath, st.nextToken());
369     newLastModified = currentFile.lastModified();
370     if (newLastModified > lastModified) {
371     lastModified = newLastModified;
372     }
373     properties.load(new FileInputStream(currentFile));
374     defaultProperties = properties;
375 tdb 1.13 }
376 ajm 1.8
377     // this creates the configuration, all nice, ready to be returned
378     ConfigurationServant ref = new ConfigurationServant(properties, fileList, lastModified);
379     org.omg.CORBA.Object objRef = _refman.getRootPOA().servant_to_reference(ref);
380     config = ConfigurationHelper.narrow(objRef);
381 tdb 1.13 _logger.write(toString(), Logger.DEBUG, "returning built configuration");
382 ajm 1.8 } catch (Exception e) {
383     // not sure what to do here
384     // so we just log the error
385 ajm 1.10 _logger.write(toString(), Logger.ERROR, "ERROR - " + e);
386 ajm 1.8 }
387    
388     // if there isn't an entry for the requested config
389     } else {
390     _logger.write(toString(), Logger.DEBUG, "no configured config, returning " + _systemConfigFile);
391     config = _systemConfig;
392     }
393     return config;
394     }
395    
396 ajm 1.3 //---ACCESSOR/MUTATOR METHODS---
397    
398     //---ATTRIBUTES---
399    
400     /**
401 ajm 1.6 * This is the friendly identifier of the
402     * component this class is running in.
403     * eg, a Filter may be called "filter1",
404     * If this class does not have an owning
405     * component, a name from the configuration
406     * can be placed here. This name could also
407     * be changed to null for utility classes.
408     */
409     private String _name = Core.NAME;
410    
411     /**
412     * This holds a reference to the
413     * system logger that is being used.
414 ajm 1.3 */
415 ajm 1.6 private Logger _logger = ReferenceManager.getInstance().getLogger();
416 ajm 1.3
417     /**
418 ajm 1.6 * A reference to the reference manager in use
419 ajm 1.3 */
420 ajm 1.6 private ReferenceManager _refman = ReferenceManager.getInstance();
421 ajm 1.3
422     /**
423     * The root path to all configurations
424     */
425     private String _configPath;
426    
427     /**
428     * The name of the file that contains the system configuration
429     */
430     private String _systemConfigFile;
431    
432     /**
433     * An instance of the system config
434     */
435     private Configuration _systemConfig;
436 ajm 1.8
437     /**
438     * The system config file represented by a
439     * properties object.
440     */
441     private Properties _systemConfigHolder;
442 ajm 1.3
443     //---STATIC ATTRIBUTES---
444    
445     }