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
(Generate patch)

Comparing projects/cms/source/server/uk/org/iscream/cms/server/core/ConfigurationManagerServant.java (file contents):
Revision 1.1 by ajm, Mon Nov 20 17:11:44 2000 UTC vs.
Revision 1.22 by tdb, Tue Dec 11 17:52:35 2001 UTC

# Line 1 | Line 1
1   //---PACKAGE DECLARATION---
2 + package uk.org.iscream.cms.server.core;
3  
4   //---IMPORTS---
5 < import uk.ac.ukc.iscream.core.*;
5 > import uk.org.iscream.cms.server.util.*;
6 > import uk.org.iscream.cms.server.componentmanager.*;
7 > import java.net.InetAddress;
8 > import java.net.UnknownHostException;
9   import java.util.*;
10   import java.io.*;
7 import org.omg.CORBA.*;
8 import org.omg.PortableServer.*;
11  
12   /**
13   * This class is essentially a Configuration factory.
# Line 16 | Line 18 | import org.omg.PortableServer.*;
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   * @author  $Author$
24   * @version $Id$
25   */
# Line 34 | Line 38 | class ConfigurationManagerServant extends Configuratio
38  
39      /**
40       * Creates a new ConfiguratorServant
41 <     *
38 <     * @param rootPOARef a reference to the RootPOA
39 <     * @param logRef a reference to the Logger
41 >     * This class uses the System.properties to set internal values
42       */
43 <    ConfigurationManagerServant(POA rootPOARef, Logger logRef) {
44 <        try {
45 <            _configPath = System.getProperty("uk.ac.ukc.iscream.ConfigurationLocation");
46 <            _systemConfigFile = System.getProperty("uk.ac.ukc.iscream.SystemConfigurationFile");
47 <            Properties systemConfigHolder = new Properties();
48 <            File systemConfigFile = new File(_configPath, _systemConfigFile);
49 <            systemConfigHolder.load(new FileInputStream(systemConfigFile));
50 <            ConfigurationServant ref = new ConfigurationServant(systemConfigHolder,systemConfigFile.lastModified(), _logRef);
51 <            org.omg.CORBA.Object objRef = _rootPOARef.servant_to_reference(ref);
52 <            _systemConfig = ConfigurationHelper.narrow(objRef);
53 <            _rootPOARef = rootPOARef;
54 <            _logRef = logRef;
53 <            _logRef.write(this.toString(), Logger.SYSINIT, "started");
54 <            _logRef.write(this.toString(), Logger.SYSMSG, "configuration location - " + _configPath);
55 <            _logRef.write(this.toString(), Logger.SYSMSG, "system configuration file - " + _systemConfigFile);
56 <        } catch (Exception e) {
57 <            // not sure what to do here
58 <            System.err.println("CONFIGURATION MANAGER ERROR: " + e);
59 <            e.printStackTrace(System.out);
60 <        
61 <        }
43 >    ConfigurationManagerServant() {
44 >        // assign some local variables
45 >        _configPath = System.getProperty("uk.org.iscream.cms.server.ConfigurationLocation");
46 >        _systemConfigFile = System.getProperty("uk.org.iscream.cms.server.SystemConfigurationFile");
47 >
48 >        // load the system config
49 >        loadSystemConfig();
50 >
51 >        // log our status
52 >        _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      }
56  
57   //---PUBLIC METHODS---
# Line 68 | Line 61 | class ConfigurationManagerServant extends Configuratio
61       * the configuration data requested by the calling
62       * object.
63       *
64 <     * If this method returns a null, that is an indication
65 <     * that no configuration currently exists for the requested
66 <     * source.  The caller should handle appropriately.
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 <        _logRef.write(this.toString(), Logger.SYSMSG, "got request for " + source);
79 >        _logger.write(toString(), Logger.SYSMSG, "got request for " + source);
80 >
81          
82 <        Configuration config = null;
83 <        String configFile = _systemConfig.getProperty(source);
84 <        if (configFile != null) {
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 >            _logger.write(toString(), Logger.SYSMSG, "system config changed");
86 >            loadSystemConfig();
87 >        }
88 >
89 >        // search config for group membership
90 >        // 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 >        
95 >        // this list will be used to compile the groupings
96 >        LinkedList groups = new LinkedList();
97 >                    
98 >        // 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 >        LinkedList ipGroups = null;
102 >        if (source.startsWith("Host.")) {
103 >            // hostname is after Host.
104 >            String hostname = source.substring(5);
105              try {
106 <                String fileList = getIncludedFiles(configFile, configFile);            
107 <              
108 <            // build the properites here from the filelist....
109 <            StringTokenizer st = new StringTokenizer(fileList, ",");
110 <            } catch (Exception e) {
111 <                // not sure what to do here
112 <                System.err.println("CONFIGURATION MANAGER ERROR: " + e);
92 <                e.printStackTrace(System.out);
106 >                String ip = "Host." + InetAddress.getByName(hostname).getHostAddress();
107 >                ipGroups = getGroupMembership(ip);
108 >                ipGroups.addFirst(ip);
109 >                // add to our list of groups
110 >                groups.addAll(ipGroups);
111 >            } catch (UnknownHostException e) {
112 >                _logger.write(toString(), Logger.ERROR, "could not resolve hostname - " + hostname);
113              }
94            
95            // on error...config remains null
96        } else {
97            config = _systemConfig;
114          }
99        return config;
100    }
101    
102    private String getIncludedFiles(String currentFile, String fileList) throws IOException, FileNotFoundException {
103        Properties properties = new Properties();
104        properties.load(new FileInputStream(new File(_configPath, currentFile)));
105        String includes = properties.getProperty("include");
106        StringTokenizer st = new StringTokenizer(includes, ",");
107        String returnList = "";
108        while (st.hasMoreTokens()) {
109            String nextFile = st.nextToken();
110            returnList += getIncludedFiles(nextFile, nextFile + "," + fileList );
111        }
112        return returnList;
113    }
114     /*  
115        // get the requested config file
116        File configurationFile = new File(_configPath, getFileName(source));
115          
116 <        try {
117 <            // if we can't read it, we return null
118 <            if (configurationFile.canRead() == false) {
119 <                // do nothing, then we return null.
120 <            
121 <            // otherwise we return the Configuration
122 <            } else {
123 <                // create the servant for it
124 <                ConfigurationServant ref = new ConfigurationServant(configurationFile, _logRef);
125 <        
126 <                // narrow and return the Configuration
116 >        // add the rest of the groups to the end        
117 >        groups.addAll(nameGroups);
118 >
119 >        Iterator i = groups.iterator();
120 >        String fileList = "";
121 >        while (i.hasNext()) {
122 >            String groupName = (String) i.next();
123 >            _logger.write(toString(), Logger.DEBUG, "looking for config entry for - " + groupName);
124 >            // we look for this entry in the systemConfig
125 >            String configFile = _systemConfig.getProperty("config." + groupName);
126 >            // 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 <                    org.omg.CORBA.Object objRef = _rootPOARef.servant_to_reference(ref);
131 <                    configuration = ConfigurationHelper.narrow(objRef);
132 <                    
133 >                    groupFileList = getIncludedFiles(configFile, "") + ";";
134                  } catch (Exception e) {
135                      // not sure what to do here
136 <                    System.err.println("ERROR: " + e);
137 <                    e.printStackTrace(System.out);
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              }
139        
140        // if a SecurityManager is in place and it denies
141        // read access, then we just want to return false
142        } catch (SecurityException e) {
143            // do nothing it will return null
145          }
146 +        // add the system config as the final check
147 +        fileList = _systemConfigFile + ";" + fileList;
148 +        _logger.write(toString(), Logger.DEBUG, "config tree - " + fileList);
149          
150 <        return configuration;
150 >        // build the configuration
151 >        Configuration config = buildConfiguration(fileList);
152 >        
153 >        // if this is null at this point, then there will have been an error
154 >        return config;
155      }
156 <   */
156 >    
157 >    
158      /**
159 <     * When passed a source and a current value for the lastModified
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 file to determine
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 source, long currentLastModified) {
170 <        return new File(getFileName(source)).lastModified() > currentLastModified;
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 <    
182 >
183      /**
184       * Overrides the {@link java.lang.Object#toString() Object.toString()}
185       * method to provide clean logging (every class should have this).
186       *
187 +     * This uses the uk.org.iscream.cms.server.util.FormatName class
188 +     * to format the toString()
189 +     *
190       * @return the name of this class and its CVS revision
191       */
192      public String toString() {
193 <        return this.getClass().getName() + "(" + REVISION.substring(11, REVISION.length() - 2) + ")";
193 >        return FormatName.getName(
194 >            _name,
195 >            getClass().getName(),
196 >            REVISION);
197      }
198 +
199   //---PRIVATE METHODS---
200  
201      /**
202 <     * Constructs the name of a configuration file from a
203 <     * configuration source that is passed to it.
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 >     * @param readFiles used for recursion purposes only, these are the files it has read so far
209       *
210 <     * @param source the source name
211 <     * @return the filename for the sources configuration
210 >     * @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 >     * @throws CircularIncludeException this is if a circular include is detected
215       */
216 <    private String getFileName(String source) {
217 <        return source + ".properties";
216 >    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 >        Properties properties = new Properties();
228 >        properties.load(new FileInputStream(new File(_configPath, currentFile)));
229 >        
230 >        // get the include property
231 >        String includes = properties.getProperty("include");
232 >
233 >        // if we're the last file with no includes, return our name
234 >        if (includes == null) {
235 >            return currentFile;
236 >        
237 >        // otherwise, recurse over our includes
238 >        } else {
239 >            StringTokenizer st = new StringTokenizer(includes, ";");
240 >            String returnList= "";
241 >            while (st.hasMoreTokens()) {
242 >                returnList = getIncludedFiles(st.nextToken(), readFiles) + ";" + returnList;
243 >            }
244 >            
245 >            return returnList + currentFile;
246 >        }
247      }
248  
249 +    /**
250 +     * 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 +     * Opens and loads the system configuration into the
270 +     * local reference _systemConfig
271 +     */
272 +    private void loadSystemConfig() {
273 +        _logger.write(this.toString(), Logger.SYSMSG, "reloading " + _systemConfigFile);
274 +        // 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 +            _systemConfigHolder = new Properties();
279 +            _systemConfigHolder.load(new FileInputStream(systemConfigFile));
280 +            
281 +            // create the servant
282 +            ConfigurationServant ref = new ConfigurationServant(_systemConfigHolder, _systemConfigFile, systemConfigFile.lastModified());
283 +            org.omg.CORBA.Object objRef = _refman.getRootPOA().servant_to_reference(ref);
284 +            
285 +            // narrow it to a Configuration
286 +            _systemConfig = ConfigurationHelper.narrow(objRef);
287 +            
288 +        } catch (Exception e) {
289 +            _logger.write(toString(), Logger.FATAL, "ERROR: " + e.getMessage());
290 +        }
291 +    }
292 +
293 +    /**
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 +        _logger.write(toString(), Logger.DEBUG, "searching groups for - " + source);
306 +        LinkedList groupMembership = new LinkedList();        
307 +        Iterator i = new TreeSet(_systemConfigHolder.keySet()).iterator();
308 +        while(i.hasNext()) {
309 +            String key = (String) i.next();
310 +            // look for a key that's a group entry
311 +            if (key.startsWith("group.")) {
312 +                // get the list of hosts in the group
313 +                String group = _systemConfig.getProperty(key);
314 +                if(groupMatch(source, group)) {
315 +                    groupMembership.add(key.substring(6));
316 +                    _logger.write(toString(), Logger.DEBUG, "group match found for - " + source + " in group - " + key);
317 +                }
318 +            }  
319 +        }
320 +        return groupMembership;
321 +    }
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 +    }
352 +
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 +        if (!fileList.equals("")) {
366 +            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 +                long lastModified = 0, newLastModified = 0;
374 +                Properties properties = null, prevProperties = null;
375 +                
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 +                while (st.hasMoreTokens()) {
384 +                    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 +                }
393 +
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 +                _logger.write(toString(), Logger.DEBUG, "returning built configuration");
399 +            } catch (Exception e) {
400 +                // not sure what to do here
401 +                // so we just log the error
402 +                _logger.write(toString(), Logger.ERROR, "ERROR - " + e);
403 +            }
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   //---ACCESSOR/MUTATOR METHODS---
414  
415   //---ATTRIBUTES---
416  
417      /**
418 <     * Local storage of the RootPOA
418 >     * 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 POA _rootPOARef;
426 >    private String _name = Core.NAME;
427 >
428 >    /**
429 >     * This holds a reference to the
430 >     * system logger that is being used.
431 >     */
432 >    private Logger _logger = ReferenceManager.getInstance().getLogger();
433      
434      /**
435 <     * Local storage of the Logger
435 >     * A reference to the reference manager in use
436       */
437 <    private Logger _logRef;
437 >    private ReferenceManager _refman = ReferenceManager.getInstance();
438      
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 +    
454 +    /**
455 +     * The system config file represented by a
456 +     * properties object.
457 +     */
458 +    private Properties _systemConfigHolder;
459      
460   //---STATIC ATTRIBUTES---
461      

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines