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.4
Committed: Tue Nov 21 23:48:55 2000 UTC (23 years, 5 months ago) by ajm
Branch: MAIN
Changes since 1.3: +48 -11 lines
Log Message:
added support to detect circular includes
also fixed problem of not passing the system.conf as a file to check for updates

initial checkin of CircularIncludeException....oooo....

File Contents

# Content
1 //---PACKAGE DECLARATION---
2
3 //---IMPORTS---
4 import uk.ac.ukc.iscream.core.*;
5 import java.util.*;
6 import java.io.*;
7 import org.omg.CORBA.*;
8 import org.omg.PortableServer.*;
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 * @author $Author: ajm4 $
22 * @version $Id: ConfigurationManagerServant.java,v 1.3 2000/11/21 21:58:52 ajm4 Exp $
23 */
24 class ConfigurationManagerServant extends ConfigurationManagerPOA {
25
26 //---FINAL ATTRIBUTES---
27
28 /**
29 * The current CVS revision of this class
30 */
31 public final String REVISION = "$Revision: 1.3 $";
32
33 //---STATIC METHODS---
34
35 //---CONSTRUCTORS---
36
37 /**
38 * Creates a new ConfiguratorServant
39 * This class uses the System.properties to set internal values
40 *
41 * @param rootPOARef a reference to the RootPOA
42 * @param logRef a reference to the Logger
43 */
44 ConfigurationManagerServant(POA rootPOARef, Logger logRef) {
45 // assign some local variables
46 _rootPOARef = rootPOARef;
47 _logRef = logRef;
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 _logRef.write(this.toString(), Logger.SYSINIT, "started");
56 _logRef.write(this.toString(), Logger.SYSMSG, "configuration location - " + _configPath);
57 _logRef.write(this.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 _logRef.write(this.toString(), Logger.SYSMSG, "got request for " + source);
83 Configuration config = null;
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 _logRef.write(this.toString(), Logger.SYSMSG, "system config changed");
89 loadSystemConfig();
90 }
91
92 // we look for this entry in the systemConfig
93 String configFile = _systemConfig.getProperty("config." + source);
94 _logRef.write(this.toString(), Logger.DEBUG, "looking for config tree in - " + configFile);
95
96 // if there is an entry
97 if (configFile != null) {
98 try {
99 // get the file list of includes etc + the system config
100 String fileList = _systemConfigFile + ";" + getIncludedFiles(configFile, "");
101 _logRef.write(this.toString(), Logger.DEBUG, "config tree - " + fileList);
102
103 // build the properites here from the filelist....
104 StringTokenizer st = new StringTokenizer(fileList, ";");
105
106 // some holders for variables
107 File currentFile;
108 long lastModified, newLastModified;
109 Properties properties, prevProperties;
110
111 // the root of all configurations will be the system config
112 // so we need to open the properties of that
113 Properties defaultProperties = new Properties();
114 currentFile = new File(_configPath, _systemConfigFile);
115 lastModified = currentFile.lastModified();
116 defaultProperties.load(new FileInputStream(currentFile));
117
118 // This loop then iterates over the file list
119 // creates the properties to be passed to the
120 // Configuration constructor
121 do {
122 properties = new Properties(defaultProperties);
123 currentFile = new File(_configPath, st.nextToken());
124 newLastModified = currentFile.lastModified();
125 if (newLastModified > lastModified) {
126 lastModified = newLastModified;
127 }
128 properties.load(new FileInputStream(currentFile));
129 defaultProperties = properties;
130 } while (st.hasMoreTokens());
131
132 // this creates the configuration, all nice, ready to be returned
133 ConfigurationServant ref = new ConfigurationServant(properties, fileList, lastModified, _logRef);
134 org.omg.CORBA.Object objRef = _rootPOARef.servant_to_reference(ref);
135 config = ConfigurationHelper.narrow(objRef);
136
137 } catch (Exception e) {
138 // not sure what to do here
139 System.err.println("CONFIGURATION MANAGER ERROR: " + e);
140 e.printStackTrace(System.out);
141 }
142
143 // if there isn't an entry for the requested config
144 } else {
145 _logRef.write(this.toString(), Logger.DEBUG, "no configured config, returning " + _systemConfigFile);
146 config = _systemConfig;
147 }
148
149 // if this is null at this point, then there will have been an error
150 return config;
151 }
152
153
154 /**
155 * When passed a file list and a current value for the lastModified
156 * of the current configuration, this method compares the value
157 * to the actual value of the configuration files to determine
158 * whether or not the configuration has been modified.
159 *
160 * @param fileList a list of files that the caller uses for configuration
161 * @param lastModified the last modified date of the callers configuration
162 *
163 * @return whether or not the configuration has been modified
164 */
165 public boolean isModified(String fileList, long lastModified) {
166 StringTokenizer st = new StringTokenizer(fileList, ";");
167 long newLastModified;
168 File currentFile;
169 while (st.hasMoreTokens()) {
170 currentFile = new File(_configPath, st.nextToken());
171 newLastModified = currentFile.lastModified();
172 if (newLastModified > lastModified) {
173 return true;
174 }
175 }
176 return false;
177 }
178
179 /**
180 * Overrides the {@link java.lang.Object#toString() Object.toString()}
181 * method to provide clean logging (every class should have this).
182 *
183 * @return the name of this class and its CVS revision
184 */
185 public String toString() {
186 return this.getClass().getName() + "(" + REVISION.substring(11, REVISION.length() - 2) + ")";
187 }
188
189 //---PRIVATE METHODS---
190
191 /**
192 * This is a recursive function private to this class.
193 * It constructs a hierarchy of files as a ";" serperated
194 * string which can be used to read in the configuration.
195 * This function calls itself.
196 *
197 * @param currentFile the current file to be processed
198 * @param readFiles used for recursion purposes only, these are the files it has read so far
199 *
200 * @return the current list that has been constructed
201 *
202 * @throws IOException if there is trouble reading the file
203 * @throws FileNotFoundException is there is trouble finding the file
204 * @throws CircularIncludeException this is if a circular include is detected
205 */
206 private String getIncludedFiles(String currentFile, String readFiles) throws IOException, FileNotFoundException, Exception {
207
208 // check for circular include here
209 if (hasDuplicate(currentFile, readFiles) || currentFile.equals(_systemConfigFile)) {
210 throw new CircularIncludeException(currentFile + " is included more than once");
211 }
212
213 // if there wasn't, we're gonna use this file, so make a note of it as read
214 // (note the use of the ";", this is for the hasDuplicate, function)
215 readFiles = readFiles + currentFile + ";";
216
217 Properties properties = new Properties();
218 properties.load(new FileInputStream(new File(_configPath, currentFile)));
219
220 // get the include property
221 String includes = properties.getProperty("include");
222
223 // if we're the last file with no includes, return our name
224 if (includes == null) {
225 return currentFile;
226
227 // otherwise, recurse over our includes
228 } else {
229 StringTokenizer st = new StringTokenizer(includes, ";");
230 String returnList= "";
231 while (st.hasMoreTokens()) {
232 returnList = getIncludedFiles(st.nextToken(), readFiles) + ";" + returnList;
233 }
234
235 return returnList + currentFile;
236 }
237 }
238
239 /**
240 * This simple method checks to see if a given
241 * file exists in the given list.
242 *
243 * @param file the file to check the list for
244 * @param fileList the list to check
245 *
246 * @return if the given file appeard in the list
247 */
248 private boolean hasDuplicate(String file, String fileList) {
249 StringTokenizer st = new StringTokenizer(fileList, ";");
250 while (st.hasMoreTokens()) {
251 if (file.equals(st.nextToken())) {
252 return true;
253 }
254 }
255 return false;
256 }
257
258 /**
259 * Opens and loads the system configuration into the
260 * local reference _systemConfig
261 */
262 private void loadSystemConfig() {
263 _logRef.write(this.toString(), Logger.SYSMSG, "reloading " + _systemConfigFile);
264 // get a reference to the system config and store it
265 try {
266 // create the properties for the configuration
267 File systemConfigFile = new File(_configPath, _systemConfigFile);
268 Properties systemConfigHolder = new Properties();
269 systemConfigHolder.load(new FileInputStream(systemConfigFile));
270
271 // create the servant
272 ConfigurationServant ref = new ConfigurationServant(systemConfigHolder, _systemConfigFile, systemConfigFile.lastModified(), _logRef);
273 org.omg.CORBA.Object objRef = _rootPOARef.servant_to_reference(ref);
274
275 // narrow it to a Configuration
276 _systemConfig = ConfigurationHelper.narrow(objRef);
277
278 } catch (Exception e) {
279 _logRef.write(this.toString(), Logger.FATAL, "ERROR: " + e.getMessage());
280 }
281 }
282
283 //---ACCESSOR/MUTATOR METHODS---
284
285 //---ATTRIBUTES---
286
287 /**
288 * Local storage of the RootPOA
289 */
290 private POA _rootPOARef;
291
292 /**
293 * Local storage of the Logger
294 */
295 private Logger _logRef;
296
297 /**
298 * The root path to all configurations
299 */
300 private String _configPath;
301
302 /**
303 * The name of the file that contains the system configuration
304 */
305 private String _systemConfigFile;
306
307 /**
308 * An instance of the system config
309 */
310 private Configuration _systemConfig;
311
312 //---STATIC ATTRIBUTES---
313
314 }