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.22
Committed: Tue Dec 11 17:52:35 2001 UTC (22 years, 5 months ago) by tdb
Branch: MAIN
Branch point for: SERVER_PIRCBOT
Changes since 1.21: +36 -14 lines
Log Message:
A slight tidy up. Changes to reflect the alterations in the StringUtils
util class. Also some tidying up of the code. Still logically does the same
thing as it did before, I hope ;)

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