001: /*
002: * MCS Media Computer Software Copyright (c) 2006 by MCS
003: * -------------------------------------- Created on 31.12.2006 by w.klaas
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
006: * use this file except in compliance with the License. You may obtain a copy of
007: * the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014: * License for the specific language governing permissions and limitations under
015: * the License.
016: */
017: /**
018: *
019: */package de.mcs.jmeasurement;
020:
021: import java.io.File;
022: import java.io.IOException;
023: import java.io.InputStream;
024: import java.net.MalformedURLException;
025: import java.net.URISyntaxException;
026: import java.net.URL;
027: import java.util.InvalidPropertiesFormatException;
028: import java.util.Properties;
029: import java.util.Timer;
030: import java.util.TimerTask;
031:
032: /**
033: * This class hold's all configuration settings for the MeasureFactory. It can
034: * load the configuration from a property file (with automatic file change
035: * checking) or an xml file. (Standard format) All defined options are declared
036: * as constants. All settings could be overridden by program, so they will not
037: * be reload automatically again. The simpelst configuration is to call the
038: * configure methode of the MeasureFactory. The property file will be searched
039: * automatically in the classpath and loaded. The class can save the actual
040: * settings to an property or xml file, too.<br/> Here is an example of a
041: * jmconfig.properties file:
042: *
043: * <pre><code>
044: * OPTION_BACKGROUND_TIME=10000
045: * OPTION_ENABLE_AUTOSNAPSHOT=true
046: * OPTION_ENABLE_MEMORY_SAVINGS=true
047: * OPTION_POINT_IDLETIME=60000
048: * OPTION_WORKINGPATH=e\:\\temp\\data\\
049: * OPTION_EXCEPTION_HANDLING =2
050: * OPTION_ENABLE_MEASUREMENT=true
051: * OPTION_CONFIG_AUTOFILE=true
052: * OPTION_DISABLE_DEVIATION=false
053: * </code></pre>
054: *
055: * @author w.klaas
056: *
057: */
058: public class JMConfig {
059: /** constant for deviation disabling. */
060: public static final String OPTION_ENABLE_MEASUREMENT = "OPTION_ENABLE_MEASUREMENT";
061:
062: /** automatically reload the config file. */
063: public static final String OPTION_CONFIG_AUTOFILE = "OPTION_CONFIG_AUTOFILE";
064:
065: /** constant for deviation disabling. */
066: public static final String OPTION_DISABLE_DEVIATION = "OPTION_DISABLE_DEVIATION";
067:
068: /** Enable the automatic snapshot system. */
069: public static final String OPTION_ENABLE_AUTOSNAPSHOT = "OPTION_ENABLE_AUTOSNAPSHOT";
070:
071: /** Time (in msec) to process background thread. */
072: public static final String OPTION_BACKGROUND_TIME = "OPTION_BACKGROUND_TIME";
073:
074: /** Enable the automatic memory saving system. */
075: public static final String OPTION_ENABLE_MEMORY_SAVINGS = "OPTION_ENABLE_MEMORY_SAVINGS";
076:
077: /** Enable the automatic memory saving system. */
078: public static final String OPTION_POINT_IDLETIME = "OPTION_POINT_IDLETIME";
079:
080: /** Path where to store the measuredata. */
081: public static final String OPTION_WORKINGPATH = "OPTION_WORKINGPATH";
082:
083: /** Name of the application under test. */
084: public static final String OPTION_APPLICATION_NAME = "OPTION_APPLICATION_NAME";
085:
086: /** exception handling. */
087: public static final String OPTION_EXCEPTION_HANDLING = "OPTION_EXCEPTION_HANDLING";
088:
089: /** constants for exception handling. Only counting. */
090: public static final int EXCEPTION_COUNT = 0;
091:
092: /** constants for exception handling. Counting and activation and name. */
093: public static final int EXCEPTION_NAME = 1;
094:
095: /** constants for exception handling. Full stacktrace. */
096: public static final int EXCEPTION_TRACE = 2;
097:
098: /**
099: * this class will hold a simple default value for a setting. (needed for
100: * the defaults array)
101: *
102: * @author w.klaas
103: *
104: */
105: static class JMDefault {
106: /** name of the setting. */
107: private String name;
108:
109: /** default vallue of the setting. */
110: private String value;
111:
112: /**
113: * constructor.
114: *
115: * @param aName
116: * name of the setting.
117: * @param aValue
118: * default value of this setting.
119: */
120: JMDefault(final String aName, final String aValue) {
121: this .name = aName;
122: this .value = aValue;
123: }
124: }
125:
126: /** the defaults array, with all default values for the JMeasureFactory. */
127: private static final JMDefault[] DEFAULTS = {
128: new JMDefault(OPTION_ENABLE_MEASUREMENT, "true"),
129: new JMDefault(OPTION_CONFIG_AUTOFILE, "false"),
130: new JMDefault(OPTION_WORKINGPATH, System
131: .getProperty("java.io.tmpdir")),
132: new JMDefault(OPTION_ENABLE_AUTOSNAPSHOT, "false"),
133: new JMDefault(OPTION_ENABLE_MEMORY_SAVINGS, "false"),
134: new JMDefault(OPTION_POINT_IDLETIME, "90000"),
135: new JMDefault(OPTION_DISABLE_DEVIATION, "false"),
136: new JMDefault(OPTION_APPLICATION_NAME, ""),
137: new JMDefault(OPTION_EXCEPTION_HANDLING, "0"),
138: new JMDefault(OPTION_BACKGROUND_TIME, "0") };
139:
140: /** this will hold the configuration. */
141: private Properties config;
142:
143: /** this will hold the overriding settings. */
144: private Properties override;
145:
146: /** the timestamp for the properties or xml file. */
147: private long fileTimeStamp = 0;
148:
149: /** the timer for the background process. */
150: private Timer backgroundtimer;
151:
152: /** the url to the input file for reloading. */
153: private URL inputURL;
154:
155: /** cached value of the measurement enabling, for faster access. */
156: private boolean enableMeasurement;
157:
158: /**
159: * This is the background task for checking the file periodically.
160: *
161: * @author w.klaas
162: *
163: */
164: class ConfigTask extends TimerTask {
165:
166: /**
167: * This method will be called everytime the file must be checked for
168: * differences.
169: */
170: @Override
171: public void run() {
172: if (inputURL != null) {
173: long newFileTimeStamp = 0;
174: try {
175: newFileTimeStamp = new File(inputURL.toURI())
176: .lastModified();
177: } catch (URISyntaxException e) {
178: e.printStackTrace();
179: }
180: if (fileTimeStamp != 0) {
181: if (fileTimeStamp < newFileTimeStamp) {
182: load();
183: fileTimeStamp = newFileTimeStamp;
184: }
185: }
186: }
187: }
188: }
189:
190: /**
191: * constructing a new configuration with default values.
192: *
193: */
194: public JMConfig() {
195: config = new Properties();
196: override = new Properties();
197: initDefaults();
198: }
199:
200: /** initialise the default values. */
201: private void initDefaults() {
202: for (int i = 0; i < DEFAULTS.length; i++) {
203: JMDefault element = DEFAULTS[i];
204: config.setProperty(element.name, element.value);
205: }
206: processConfig();
207: }
208:
209: /**
210: * load configuration from jmconfig.properties file in the classpath.
211: *
212: * @return <code>true</code> if the file could be loaded, otherwise
213: * <code>false</code>.
214: */
215: public final boolean configure() {
216: inputURL = getClass().getClassLoader().getResource(
217: "jmconfig.properties");
218: if (inputURL == null) {
219: inputURL = getClass().getClassLoader().getResource(
220: "jmconfig.xml");
221:
222: if (inputURL == null) {
223: return false;
224: }
225: }
226: if (inputURL.getProtocol().equalsIgnoreCase("file")) {
227: try {
228: fileTimeStamp = new File(inputURL.toURI())
229: .lastModified();
230: } catch (URISyntaxException e) {
231: e.printStackTrace();
232: }
233: }
234: return load();
235: }
236:
237: /**
238: * load configuration from the given file.
239: *
240: * @param jmConfig
241: * the config file to load.
242: * @return <code>true</code> if the file could be loaded, otherwise
243: * <code>false</code>.
244: */
245: public final boolean configure(final File jmConfig) {
246: try {
247: inputURL = jmConfig.toURI().toURL();
248: if (inputURL.getProtocol().equalsIgnoreCase("file")) {
249: try {
250: fileTimeStamp = new File(inputURL.toURI())
251: .lastModified();
252: } catch (URISyntaxException e) {
253: e.printStackTrace();
254: }
255: }
256: } catch (MalformedURLException e1) {
257: // TODO Auto-generated catch block
258: e1.printStackTrace();
259: }
260: return load();
261: }
262:
263: /**
264: * loading the configuration from a file. This method will differe between
265: * the loading of a property file or xml file.
266: *
267: * @return <code>true</code> if the file could be readed and processed
268: * right, otherwise <code>false</code>
269: */
270: private boolean load() {
271: InputStream input;
272: try {
273: input = inputURL.openStream();
274: try {
275: if (inputURL.getFile().toLowerCase().endsWith(".xml")) {
276: return loadFromXML(input);
277: } else {
278: return loadFromFile(input);
279: }
280: } finally {
281: input.close();
282: }
283: } catch (IOException e) {
284: e.printStackTrace();
285: }
286: return false;
287: }
288:
289: /**
290: * Loading configuration from input stream as a property file.
291: *
292: * @param input
293: * the stream to read from
294: * @return <code>true</code> if the file could be readed and processed
295: * right, otherwise <code>false</code>
296: */
297: private boolean loadFromFile(final InputStream input) {
298: try {
299: config.load(input);
300: processConfig();
301: return true;
302: } catch (IOException e) {
303: e.printStackTrace();
304: }
305: return false;
306: }
307:
308: /**
309: * Loading configuration from input stream as a xml file.
310: *
311: * @param input
312: * the stream to read from
313: * @return <code>true</code> if the file could be readed and processed
314: * right, otherwise <code>false</code>
315: */
316: private boolean loadFromXML(final InputStream input) {
317: try {
318: config.loadFromXML(input);
319: processConfig();
320: return true;
321: } catch (InvalidPropertiesFormatException e) {
322: e.printStackTrace();
323: } catch (IOException e) {
324: e.printStackTrace();
325: }
326: return false;
327: }
328:
329: /**
330: * processing the configuration. This will check, if an automatic file
331: * watcher will be established or not.
332: *
333: */
334: private void processConfig() {
335: if (getBoolean(JMConfig.OPTION_CONFIG_AUTOFILE)) {
336: if (backgroundtimer != null) {
337: if (backgroundtimer != null) {
338: backgroundtimer.cancel();
339: backgroundtimer.purge();
340: backgroundtimer = null;
341: }
342: }
343: backgroundtimer = new Timer(
344: "JMeasurement Config Background Timer", true);
345: long period = getLong(JMConfig.OPTION_BACKGROUND_TIME);
346: backgroundtimer.scheduleAtFixedRate(new ConfigTask(),
347: period, period);
348: }
349: // here we are actualising the cache value
350: enableMeasurement = getBoolean(OPTION_ENABLE_MEASUREMENT);
351:
352: // now setting the background timing in factory
353: if (getLong(JMConfig.OPTION_BACKGROUND_TIME) > 0) {
354: if (MeasureFactory.isBackgroundProcessing()) {
355: MeasureFactory.setBackgroundProcessing(false);
356: }
357: MeasureFactory.setBackgroundProcessing(true);
358: }
359: }
360:
361: /**
362: * setting a string setting.
363: *
364: * @param key
365: * name of the setting
366: * @param value
367: * value of the setting
368: */
369: public final void setProperty(final String key, final String value) {
370: override.setProperty(key, value);
371: processConfig();
372: }
373:
374: /**
375: * setting a integer setting.
376: *
377: * @param key
378: * name of the setting
379: * @param value
380: * value of the setting
381: */
382: public final void setInteger(final String key, final int value) {
383: setProperty(key, Integer.toString(value));
384: }
385:
386: /**
387: * setting a boolean setting.
388: *
389: * @param key
390: * name of the setting
391: * @param value
392: * value of the setting
393: */
394: public final void setBoolean(final String key, final boolean value) {
395: setProperty(key, Boolean.toString(value));
396: }
397:
398: /**
399: * setting a long setting.
400: *
401: * @param key
402: * name of the setting
403: * @param value
404: * value of the setting
405: */
406: public final void setLong(final String key, final long value) {
407: setProperty(key, Long.toString(value));
408: }
409:
410: /**
411: * getting a boolean setting.
412: *
413: * @param key
414: * name of the setting
415: * @return value value of the setting
416: */
417: public final boolean getBoolean(final String key) {
418: return Boolean.parseBoolean(getProperty(key));
419: }
420:
421: /**
422: * getting a integer setting.
423: *
424: * @param key
425: * name of the setting
426: * @return value value of the setting
427: */
428: public final int getInteger(final String key) {
429: return Integer.parseInt(getProperty(key));
430: }
431:
432: /**
433: * getting a string setting.
434: *
435: * @param key
436: * name of the setting
437: * @return value value of the setting
438: */
439: public final String getProperty(final String key) {
440: if (override.containsKey(key)) {
441: return override.getProperty(key);
442: }
443: return config.getProperty(key);
444: }
445:
446: /**
447: * getting a long setting.
448: *
449: * @param key
450: * name of the setting
451: * @return value value of the setting
452: */
453: public final long getLong(final String key) {
454: return Long.parseLong(getProperty(key));
455: }
456:
457: /**
458: * removes the setting with the name as an overridden setting. So from now
459: * on the setting will be used as in the config file or as the default
460: * value.
461: *
462: * @param key
463: * name of the setting to remove from the override setting list.
464: */
465: public final void remove(final String key) {
466: if (override.containsKey(key)) {
467: override.remove(key);
468: }
469: }
470:
471: /**
472: * @return the enableMeasurement
473: */
474: public final boolean isEnableMeasurement() {
475: return enableMeasurement;
476: }
477:
478: /**
479: * @param value
480: * the enableMeasurement to set
481: */
482: public final void setEnableMeasurement(final boolean value) {
483: setBoolean(OPTION_ENABLE_MEASUREMENT, value);
484: }
485:
486: }
|