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.21
Committed: Tue Dec 11 14:56:12 2001 UTC (22 years, 5 months ago) by tdb
Branch: MAIN
Changes since 1.20: +2 -7 lines
Log Message:
Removed note about not cleaning up Configuration objects - that's handled
elsewhere now.

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.20 2001/12/10 22:49:19 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.20 $";
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 if (key.startsWith("group.")) {
311 String group = _systemConfig.getProperty(key);
312 // if it is in the group
313 if (group.indexOf(source) != -1) {
314 groupMembership.add(key.substring(6));
315 _logger.write(toString(), Logger.DEBUG, "group match found for - " + source + " in - " + key);
316
317 // if there are wildcards in the group
318 } else if (group.indexOf("*") != -1) {
319 // check the wildcards apply to this srce
320 if(StringUtils.wildcardCheck(source, group)) {
321 groupMembership.add(key.substring(6));
322 _logger.write(toString(), Logger.DEBUG, "wildcard group match found for - " + source + " in - " + key);
323 }
324 }
325
326 }
327 }
328 return groupMembership;
329 }
330
331 /**
332 * Build the properties as a Configuration to be
333 * returned to the caller
334 *
335 * @param fileList the list of files to build the configuration from
336 *
337 * @return the built Configuration
338 */
339 private Configuration buildConfiguration(String fileList) {
340 Configuration config = null;
341
342 // if there is an entry
343 if (!fileList.equals("")) {
344 try {
345
346 // build the properites here from the filelist....
347 StringTokenizer st = new StringTokenizer(fileList, ";");
348
349 // some holders for variables
350 File currentFile;
351 long lastModified = 0, newLastModified = 0;
352 Properties properties = null, prevProperties = null;
353
354 // the root of all configurations will be the system config
355 // so we need to open the properties of that
356 Properties defaultProperties = new Properties();
357
358 // This loop then iterates over the file list
359 // creates the properties to be passed to the
360 // Configuration constructor
361 while (st.hasMoreTokens()) {
362 properties = new Properties(defaultProperties);
363 currentFile = new File(_configPath, st.nextToken());
364 newLastModified = currentFile.lastModified();
365 if (newLastModified > lastModified) {
366 lastModified = newLastModified;
367 }
368 properties.load(new FileInputStream(currentFile));
369 defaultProperties = properties;
370 }
371
372 // this creates the configuration, all nice, ready to be returned
373 ConfigurationServant ref = new ConfigurationServant(properties, fileList, lastModified);
374 org.omg.CORBA.Object objRef = _refman.getRootPOA().servant_to_reference(ref);
375 config = ConfigurationHelper.narrow(objRef);
376 _logger.write(toString(), Logger.DEBUG, "returning built configuration");
377 } catch (Exception e) {
378 // not sure what to do here
379 // so we just log the error
380 _logger.write(toString(), Logger.ERROR, "ERROR - " + e);
381 }
382
383 // if there isn't an entry for the requested config
384 } else {
385 _logger.write(toString(), Logger.DEBUG, "no configured config, returning " + _systemConfigFile);
386 config = _systemConfig;
387 }
388 return config;
389 }
390
391 //---ACCESSOR/MUTATOR METHODS---
392
393 //---ATTRIBUTES---
394
395 /**
396 * This is the friendly identifier of the
397 * component this class is running in.
398 * eg, a Filter may be called "filter1",
399 * If this class does not have an owning
400 * component, a name from the configuration
401 * can be placed here. This name could also
402 * be changed to null for utility classes.
403 */
404 private String _name = Core.NAME;
405
406 /**
407 * This holds a reference to the
408 * system logger that is being used.
409 */
410 private Logger _logger = ReferenceManager.getInstance().getLogger();
411
412 /**
413 * A reference to the reference manager in use
414 */
415 private ReferenceManager _refman = ReferenceManager.getInstance();
416
417 /**
418 * The root path to all configurations
419 */
420 private String _configPath;
421
422 /**
423 * The name of the file that contains the system configuration
424 */
425 private String _systemConfigFile;
426
427 /**
428 * An instance of the system config
429 */
430 private Configuration _systemConfig;
431
432 /**
433 * The system config file represented by a
434 * properties object.
435 */
436 private Properties _systemConfigHolder;
437
438 //---STATIC ATTRIBUTES---
439
440 }