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.11
Committed: Thu Mar 1 19:42:20 2001 UTC (23 years, 3 months ago) by ajm
Branch: MAIN
Changes since 1.10: +21 -17 lines
Log Message:
now handles nulls better.
also prints group debugging information.

File Contents

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