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.26
Committed: Sun Aug 1 10:40:54 2004 UTC (19 years, 9 months ago) by tdb
Branch: MAIN
CVS Tags: HEAD
Changes since 1.25: +3 -3 lines
Log Message:
Catch a lot of old URL's and update them. Also remove a couple of old files
that aren't used.

File Contents

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