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.23 by tdb, Sat May 18 18:16:01 2002 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines