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.20
Committed: Mon Dec 10 22:49:19 2001 UTC (22 years, 5 months ago) by tdb
Branch: MAIN
Changes since 1.19: +7 -83 lines
Log Message:
Pulled out the wildcardCheck method because it's rather more generic than
it's use in the ConfigurationManagerServant. I still need to tidy some of
the comments and variable names to abstract it a bit more, and I might also
remove it taking a semi-colon seperated list - that's more behaviour of the
configuration system. It's a start, and I'll remember to do the rest when I
read this commit message tomorrow :)

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