KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > invicta > process > ConfigurationManager


1 package net.sf.invicta.process;
2
3 import java.io.File JavaDoc;
4 import java.io.FileInputStream JavaDoc;
5 import java.io.FileNotFoundException JavaDoc;
6 import java.io.FileOutputStream JavaDoc;
7 import java.io.IOException JavaDoc;
8 import java.util.HashMap JavaDoc;
9 import java.util.Map JavaDoc;
10 import java.util.Properties JavaDoc;
11
12 import net.sf.invicta.InvictaConstants;
13 import net.sf.invicta.InvictaException;
14 import net.sf.invicta.Logger;
15
16 /**
17  * The manager of Invicta configuration properties.
18  * Properties are read from an optional properties file
19  * ('invicta.properties' in default) or as Java system properties.
20  *
21  * This class is used for getting values of properties. It also checks if
22  * the values of properties were changed since the previous Invicta execution.
23  * A temporary output file is used to store the current value of properties.
24  * A setOutputProperty method is available for writing additional values
25  * to the temporary output file (used mainly for last modification time of
26  * files).
27  *
28  **/

29 public class ConfigurationManager {
30     private boolean forceRun = false;
31     private Properties JavaDoc props;
32     private Properties JavaDoc previousProps = new Properties JavaDoc();
33     private Properties JavaDoc outputProps = new Properties JavaDoc();
34     private Map JavaDoc requestedProperties = new HashMap JavaDoc();
35     private String JavaDoc outputPropsFileName;
36
37     /**
38      *
39      */

40     public ConfigurationManager() throws InvictaException {
41         super();
42         readProperties();
43     }
44     /**
45      * Sets the value of a property to write to the temporary output file.
46      *
47      * @param propertyName
48      * @param propertyValue
49      */

50     public void setOutputProperty(String JavaDoc propertyName, String JavaDoc propertyValue) throws InvictaProcessException {
51         this.outputProps.setProperty(propertyName, propertyValue);
52         checkPropertyChange(propertyName);
53     }
54     
55     /**
56      * Sets the value of an output property to be the last modification time
57      * of the given file.
58      *
59      * @param propertyPrefix
60      * @param file
61      * @throws InvictaProcessException
62      */

63     public void setOutputTimestampProperty(String JavaDoc propertyPrefix, File JavaDoc file) throws InvictaProcessException {
64         String JavaDoc propertyName =
65             propertyPrefix
66             + InvictaConstants.PROPERTY_SEPARATOR
67             + getPropertyPath(file.getAbsolutePath());
68         
69         String JavaDoc timestamp = String.valueOf(file.lastModified());
70         
71         setOutputProperty(propertyName, timestamp);
72     }
73     
74     
75     /**
76      * Returns the value of a property with the given name.
77      * Throws an exception if this property is not defined.
78      *
79      * @param propertyName
80      * @return String
81      * @throws InvictaProcessException
82      */

83     public String JavaDoc getRequiredProperty(String JavaDoc propertyName) throws InvictaProcessException {
84         String JavaDoc value = getProperty(propertyName);
85
86         // Check if this property is not defined.
87
if (value == null)
88             throw InvictaProcessException.propertyUndefined(propertyName);
89
90         return value;
91     }
92     
93     /**
94      * Returns the value of a property with the given name.
95      *
96      * @param propertyName
97      * @return String
98      * @throws InvictaProcessException
99      */

100     public String JavaDoc getProperty(String JavaDoc propertyName) throws InvictaProcessException {
101         // Check if the current getProperty call has a cycle of property referecnes.
102
if (this.requestedProperties.containsKey(propertyName))
103             throw InvictaProcessException.propertyVariableCycle(propertyName);
104
105         // Add the name of the current property for preventing cycles.
106
this.requestedProperties.put(propertyName, propertyName);
107
108         // Get the value of a system property with this name.
109
String JavaDoc value = System.getProperty(propertyName);
110         
111         // If the system property is not defined, get the property from the
112
// properties read from the file.
113
if ((value == null) && (this.props != null))
114             value = this.props.getProperty(propertyName);
115
116         // Parse the value of the property. It's used for replacing
117
// ${propname} string with the value of a property with the name 'propname'.
118
if (value != null) {
119         
120             value = parseProperty(value);
121             // Add the value of the property to the output properties.
122
this.outputProps.setProperty(propertyName, value);
123         }
124         
125         checkPropertyChange(propertyName);
126
127         // Remove the processed property name from the map of cycle recognition.
128
this.requestedProperties.remove(propertyName);
129         return value;
130     }
131     
132     /**
133      * Get the value of a property from the previous temporary output file.
134      *
135      * @param propertyName
136      * @return String
137      */

138     public String JavaDoc getPreviousProperty(String JavaDoc propertyName) throws InvictaException {
139         return this.previousProps.getProperty(propertyName);
140     }
141     
142     /**
143      * Get the value of a property from the new (future) temporary output
144      * properties.
145      *
146      * @param propertyName
147      * @return String
148      */

149     public String JavaDoc getOutputProperty(String JavaDoc propertyName) throws InvictaException {
150         return this.outputProps.getProperty(propertyName);
151     }
152     
153     /**
154      * Returns whether Invicta should process. Returns true if the property
155      * invicta.force.run is true or if a value of a property (input or
156      * file timestamp) was changed.
157      * @return
158      */

159     public boolean forceRun() {
160         String JavaDoc forceRunProperty =
161             this.props.getProperty(InvictaConstants.PROPERTY_FORCE_RUN);
162         if ((forceRunProperty != null) &&
163              (Boolean.valueOf(forceRunProperty).booleanValue()))
164             return true;
165         
166         return this.forceRun;
167     }
168
169     /**
170      *
171      * @throws InvictaProcessException
172      */

173     public void writeOutputProperties() throws InvictaProcessException {
174         try {
175             this.outputProps.store(new FileOutputStream JavaDoc(this.outputPropsFileName),
176                 "Invicta temporary output properties for checking whether Invicta should run.");
177         } catch (Exception JavaDoc e) {
178             throw InvictaProcessException.fileIOError(this.outputPropsFileName, e);
179         }
180     }
181
182     /**
183      * Convert a file path to a nice looking property key.
184      * @param path
185      * @return
186      */

187     private String JavaDoc getPropertyPath(String JavaDoc path) {
188         path = path.replace('/', '.');
189         path = path.replace('\\', '.');
190         return path;
191     }
192
193     /**
194      * Reads the input properties file (if exists) and also the previous
195      * temporary output properties file (if exists).
196      *
197      * @throws InvictaProcessException
198      */

199     private void readProperties() throws InvictaProcessException {
200             
201         String JavaDoc propsFile = InvictaConstants.DEFAULT_PROPERTIES_FILE;
202         
203         // Get the name of the properties file.
204
if (System.getProperty(InvictaConstants.PROPERTIES_FILE_NAME_PROPERTY) != null) {
205             propsFile =
206                 System.getProperty(InvictaConstants.PROPERTIES_FILE_NAME_PROPERTY);
207         }
208         
209         // Load the input properties
210
this.props = new Properties JavaDoc();
211         try {
212             props.load(new FileInputStream JavaDoc(new File JavaDoc(propsFile)));
213         } catch (FileNotFoundException JavaDoc e) {
214             Logger.warn(
215                 "Properties file not found (" + propsFile + ")");
216             props = null;
217         } catch (IOException JavaDoc e) {
218             throw InvictaProcessException.fileIOError(propsFile, e);
219         }
220
221         // Get the name of the temporary output file.
222
String JavaDoc previousPropsFile =
223             InvictaConstants.DEFAULT_OUTPUT_PROPERTIES_FILE;
224         if (System.getProperty(InvictaConstants.OUTPUT_PROPERTIES_FILE_NAME_PROPERTY) != null)
225             previousPropsFile =
226                 System.getProperty(InvictaConstants.OUTPUT_PROPERTIES_FILE_NAME_PROPERTY);
227
228         this.outputPropsFileName = previousPropsFile;
229
230         // Load the previous output properties from the file.
231
try {
232             previousProps.load(
233                 new FileInputStream JavaDoc(new File JavaDoc(previousPropsFile)));
234         } catch (FileNotFoundException JavaDoc e) {
235             Logger.info(
236                 "Note: Previous output properties file not found. " +
237                 "Forcing Invicta execution.");
238             this.forceRun = true;
239         } catch (IOException JavaDoc e) {
240             throw InvictaProcessException.fileIOError(previousPropsFile, e);
241         }
242     }
243
244     /**
245      * Parse a property value. Replace all variables (${var}) with the
246      * value of a matching property.
247      *
248      * @param value
249      * @return String
250      * @throws InvictaProcessException
251      */

252     private String JavaDoc parseProperty(String JavaDoc value) throws InvictaProcessException {
253         String JavaDoc resolvedValue = "";
254         int varStartPos;
255         int currentStartPos = 0;
256         // Look for variables ('${varname}), and replace the variable with
257
// the value of a property of that variable.
258
while ((varStartPos = value.indexOf(InvictaConstants.PROPERTY_VARIABLE_PREFIX, currentStartPos))
259             != -1) {
260             // Add to the resolved value the non-variable string.
261
if (varStartPos > currentStartPos)
262                 resolvedValue += value.substring(currentStartPos, varStartPos);
263
264             // Keep the start position of the name.
265
int varNameStartPos = varStartPos + InvictaConstants.PROPERTY_VARIABLE_PREFIX.length();
266
267             // Find the end position of the variable.
268
int varEndPos = value.indexOf(InvictaConstants.PROPERTY_VARIABLE_SUFFIX, varNameStartPos);
269
270             // Check if no end character was found.
271
if (varEndPos == -1)
272                 throw InvictaProcessException.propertyVariableSyntaxError();
273                 
274             // Get the variable name.
275
String JavaDoc varName = value.substring(varNameStartPos, varEndPos);
276
277             // Get the property value of this variable.
278
String JavaDoc varValue = getRequiredProperty(varName);
279
280             // Add the property value to the resolved value.
281
resolvedValue += varValue;
282
283             // Move the current position to be after the replaced variable.
284
currentStartPos = varEndPos + 1;
285         }
286
287         // Add the rest of the value.
288
if (currentStartPos >= 0)
289             resolvedValue += value.substring(currentStartPos);
290         return resolvedValue;
291     }
292
293     /**
294      * Set the forceRun flag to true if the value of the given property name
295      * was changed between this and the previous Invicta execution.
296      *
297      * @param propertyName
298      */

299     private void checkPropertyChange(String JavaDoc propertyName) {
300         if (this.forceRun)
301             return;
302             
303         String JavaDoc oldValue = this.previousProps.getProperty(propertyName);
304         String JavaDoc newValue = this.outputProps.getProperty(propertyName);
305         if (!equals(oldValue, newValue)) {
306             Logger.info(
307                 "Note: Property '"
308                     + propertyName
309                     + "' was changed. Forcing Invicta execution.");
310             this.forceRun = true;
311         }
312     }
313
314     /**
315      * Compares two given objects while handling null cases.
316      *
317      * @param o1
318      * @param o2
319      * @return
320      */

321     private boolean equals(Object JavaDoc o1, Object JavaDoc o2) {
322         if ((o1 == null) && (o2 == null))
323             return true;
324         if ((o1 == null) || (o2 == null))
325             return false;
326         return o1.equals(o2);
327     }
328
329     
330 }
331
Popular Tags