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

# Content
1 //---PACKAGE DECLARATION---
2 package uk.org.iscream.cms.server.core;
3
4 //---IMPORTS---
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.*;
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 * @author $Author: tdb $
24 * @version $Id: ConfigurationManagerServant.java,v 1.21 2001/12/11 14:56:12 tdb Exp $
25 */
26 class ConfigurationManagerServant extends ConfigurationManagerPOA {
27
28 //---FINAL ATTRIBUTES---
29
30 /**
31 * The current CVS revision of this class
32 */
33 public final String REVISION = "$Revision: 1.21 $";
34
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 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---
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 _logger.write(toString(), Logger.SYSMSG, "got request for " + source);
80
81
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 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 }
114 }
115
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 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 }
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 // 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
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
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 FormatName.getName(
194 _name,
195 getClass().getName(),
196 REVISION);
197 }
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 * @param readFiles used for recursion purposes only, these are the files it has read so far
209 *
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 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 * 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 */
432 private Logger _logger = ReferenceManager.getInstance().getLogger();
433
434 /**
435 * A reference to the reference manager in use
436 */
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
462 }