001: /*
002: * Copyright (c) JForum Team
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms,
006: * with or without modification, are permitted provided
007: * that the following conditions are met:
008: *
009: * 1) Redistributions of source code must retain the above
010: * copyright notice, this list of conditions and the
011: * following disclaimer.
012: * 2) Redistributions in binary form must reproduce the
013: * above copyright notice, this list of conditions and
014: * the following disclaimer in the documentation and/or
015: * other materials provided with the distribution.
016: * 3) Neither the name of "Rafael Steil" nor
017: * the names of its contributors may be used to endorse
018: * or promote products derived from this software without
019: * specific prior written permission.
020: *
021: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
022: * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
023: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
024: * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
025: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR
026: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
027: * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
028: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
029: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES
030: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
031: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
032: * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
033: * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
034: * IN CONTRACT, STRICT LIABILITY, OR TORT
035: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
036: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
037: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
038: *
039: * This file creating date: Feb 24, 2003 / 8:25:35 PM
040: * The JForum Project
041: * http://www.jforum.net
042: */
043: package net.jforum.util.preferences;
044:
045: import java.io.File;
046: import java.io.FileInputStream;
047: import java.io.FileOutputStream;
048: import java.io.IOException;
049: import java.security.InvalidParameterException;
050: import java.util.ArrayList;
051: import java.util.Collections;
052: import java.util.Enumeration;
053: import java.util.HashMap;
054: import java.util.Iterator;
055: import java.util.List;
056: import java.util.Map;
057: import java.util.Properties;
058: import java.util.Vector;
059:
060: import net.jforum.ConfigLoader;
061: import net.jforum.exceptions.ForumException;
062:
063: import org.apache.log4j.Logger;
064:
065: /**
066: * <p>Store global configurations used in the system.
067: * This is an helper class used to access the values
068: * defined at SystemGlobals.properties and related
069: * config files.</p>
070: *
071: * <p>
072: * Transient values are stored in a special place, and are not
073: * modified when you change a regular key's value.
074: * </p>
075: *
076: * @author Rafael Steil
077: * @author Pieter Olivier
078: * @version $Id: SystemGlobals.java,v 1.35 2007/09/02 15:51:04 andowson Exp $
079: */
080: public class SystemGlobals implements VariableStore {
081: private static SystemGlobals globals = new SystemGlobals();
082:
083: private String defaultConfig;
084: private String installationConfig;
085:
086: private Properties defaults = new Properties();
087: private Properties installation = new Properties();
088: private Map objectProperties = new HashMap();
089: private static List additionalDefaultsList = new ArrayList();
090: private static Properties queries = new Properties();
091: private static Properties transientValues = new Properties();
092:
093: private VariableExpander expander = new VariableExpander(this ,
094: "${", "}");
095:
096: private static final Logger logger = Logger
097: .getLogger(SystemGlobals.class);
098:
099: private SystemGlobals() {
100: }
101:
102: /**
103: * Initialize the global configuration
104: * @param appPath The application path (normally the path to the webapp base dir
105: * @param mainConfigurationFile The file containing system defaults (when null, defaults to <appPath>/WEB-INF/config/default.conf)
106: */
107: public static void initGlobals(String appPath,
108: String mainConfigurationFile) {
109: globals = new SystemGlobals();
110: globals.buildSystem(appPath, mainConfigurationFile);
111: }
112:
113: public static void reset() {
114: globals.defaults.clear();
115: globals.installation.clear();
116: additionalDefaultsList.clear();
117: queries.clear();
118: transientValues.clear();
119: }
120:
121: private void buildSystem(String appPath,
122: String mainConfigurationFile) {
123: if (mainConfigurationFile == null) {
124: throw new InvalidParameterException(
125: "defaultConfig could not be null");
126: }
127:
128: this .defaultConfig = mainConfigurationFile;
129: this .defaults = new Properties();
130:
131: this .defaults.put(ConfigKeys.APPLICATION_PATH, appPath);
132: this .defaults.put(ConfigKeys.DEFAULT_CONFIG,
133: mainConfigurationFile);
134:
135: SystemGlobals.loadDefaults();
136:
137: this .installation = new Properties();
138: this .installationConfig = getVariableValue(ConfigKeys.INSTALLATION_CONFIG);
139:
140: for (Iterator iter = additionalDefaultsList.iterator(); iter
141: .hasNext();) {
142: loadAdditionalDefaults((String) iter.next());
143: }
144:
145: if (new File(this .installationConfig).exists()) {
146: loadAdditionalDefaults(this .installationConfig);
147: }
148: }
149:
150: /**
151: * Sets a value for some property
152: *
153: * @param field The property name
154: * @param value The property value
155: * @see #getVariableValue(String)
156: * */
157: public static void setValue(String field, String value) {
158: globals.installation.put(field, value);
159: globals.expander.clearCache();
160: }
161:
162: public static void setObjectValue(String field, Object value) {
163: globals.objectProperties.put(field, value);
164: }
165:
166: public static Object getObjectValue(String field) {
167: return globals.objectProperties.get(field);
168: }
169:
170: /**
171: * Set a transient configuration value (a value that will not be saved)
172: * @param field The name of the configuration option
173: * @param value The value of the configuration option
174: */
175: public static void setTransientValue(String field, String value) {
176: transientValues.put(field, value);
177: }
178:
179: /**
180: * Load system defaults
181: */
182: public static void loadDefaults() {
183: try {
184: FileInputStream input = new FileInputStream(
185: globals.defaultConfig);
186: globals.defaults.load(input);
187: input.close();
188: globals.expander.clearCache();
189: } catch (IOException e) {
190: throw new ForumException(e);
191: }
192: }
193:
194: /**
195: * Merge additional configuration defaults
196: *
197: * @param file File from which to load the additional defaults
198: */
199: public static void loadAdditionalDefaults(String file) {
200: if (!new File(file).exists()) {
201: logger
202: .info("Cannot find file " + file
203: + ". Will ignore it");
204: return;
205: }
206:
207: try {
208: FileInputStream input = new FileInputStream(file);
209: globals.installation.load(input);
210: input.close();
211: } catch (IOException e) {
212: throw new ForumException(e);
213: }
214:
215: if (!additionalDefaultsList.contains(file)) {
216: additionalDefaultsList.add(file);
217: }
218: }
219:
220: /**
221: * Save installation defaults
222: */
223: public static void saveInstallation() {
224: // We need this temporary "p" because, when
225: // new FileOutputStream() is called, it will
226: // raise an event to the TimerTask who is listen
227: // for file modifications, which then reloads the
228: // configurations from the filesystem, overwriting
229: // our new keys.
230: class SortedProperties extends Properties {
231: public synchronized Enumeration keys() {
232: Enumeration keysEnum = super .keys();
233: Vector keyList = new Vector();
234: while (keysEnum.hasMoreElements()) {
235: keyList.add(keysEnum.nextElement());
236: }
237: Collections.sort(keyList);
238: return keyList.elements();
239: }
240: }
241:
242: Properties p = new SortedProperties();
243: p.putAll(globals.installation);
244:
245: try {
246: FileOutputStream out = new FileOutputStream(
247: globals.installationConfig);
248: p.store(out, "Installation specific configuration options");
249: out.close();
250: } catch (IOException e) {
251: throw new ForumException(e);
252: }
253:
254: ConfigLoader.listenInstallationConfig();
255: }
256:
257: /**
258: * Gets the value of some property
259: *
260: * @param field The property name to retrieve the value
261: * @return String with the value, or <code>null</code> if not found
262: * @see #setValue(String, String)
263: * */
264: public static String getValue(String field) {
265: return globals.getVariableValue(field);
266: }
267:
268: public static String getTransientValue(String field) {
269: return transientValues.getProperty(field);
270: }
271:
272: /**
273: * Retrieve an integer-valued configuration field
274: *
275: * @param field Name of the configuration option
276: * @return The value of the configuration option
277: * @exception NullPointerException when the field does not exists
278: */
279: public static int getIntValue(String field) {
280: return Integer.parseInt(getValue(field));
281: }
282:
283: /**
284: * Retrieve an boolean-values configuration field
285: *
286: * @param field name of the configuration option
287: * @return The value of the configuration option
288: * @exception NullPointerException when the field does not exists
289: */
290: public static boolean getBoolValue(String field) {
291: return "true".equals(getValue(field));
292: }
293:
294: /**
295: * Return the value of a configuration value as a variable. Variable expansion is performe
296: * on the result.
297: *
298: * @param field The field name to retrieve
299: * @return The value of the field if present or null if not
300: */
301:
302: public String getVariableValue(String field) {
303: String preExpansion = globals.installation.getProperty(field);
304:
305: if (preExpansion == null) {
306: preExpansion = this .defaults.getProperty(field);
307:
308: if (preExpansion == null) {
309: return null;
310: }
311: }
312:
313: return expander.expandVariables(preExpansion);
314: }
315:
316: /**
317: * Sets the application's root directory
318: *
319: * @param ap String containing the complete path to the root dir
320: * @see #getApplicationPath
321: * */
322: public static void setApplicationPath(String ap) {
323: setValue(ConfigKeys.APPLICATION_PATH, ap);
324: }
325:
326: /**
327: * Getst the complete path to the application's root dir
328: *
329: * @return String with the path
330: * @see #setApplicationPath
331: * */
332: public static String getApplicationPath() {
333: return getValue(ConfigKeys.APPLICATION_PATH);
334: }
335:
336: /**
337: * Gets the path to the resource's directory.
338: * This method returns the directory name where the config
339: * files are stored.
340: * Caso queira saber o caminho absoluto do diretorio, voce precisa
341: * usar
342: * Note that this method does not return the complete path. If you
343: * want the full path, you must use
344: * <blockquote><pre>SystemGlobals.getApplicationPath() + SystemGlobals.getApplicationResourcedir()</pre></blockquote>
345: *
346: * @return String with the name of the resource dir, relative
347: * to application's root dir.
348: * @see #getApplicationPath()
349: * */
350: public static String getApplicationResourceDir() {
351: return getValue(ConfigKeys.RESOURCE_DIR);
352: }
353:
354: /**
355: * Load the SQL queries
356: *
357: * @param queryFile Complete path to the SQL queries file.
358: **/
359: public static void loadQueries(String queryFile) {
360: FileInputStream fis = null;
361:
362: try {
363: fis = new FileInputStream(queryFile);
364: queries.load(fis);
365: } catch (IOException e) {
366: throw new ForumException(e);
367: } finally {
368: if (fis != null) {
369: try {
370: fis.close();
371: } catch (Exception e) {
372: }
373: }
374: }
375: }
376:
377: /**
378: * Gets some SQL statement.
379: *
380: * @param sql The query's name, as defined in the file loaded by
381: * {@link #loadQueries(String)}
382: * @return The SQL statement, or <code>null</code> if not found.
383: * */
384: public static String getSql(String sql) {
385: return queries.getProperty(sql);
386: }
387:
388: /**
389: * Retrieve an iterator that iterates over all known configuration keys
390: *
391: * @return An iterator that iterates over all known configuration keys
392: */
393: public static Iterator fetchConfigKeyIterator() {
394: return globals.defaults.keySet().iterator();
395: }
396:
397: public static Properties getConfigData() {
398: return new Properties(globals.defaults);
399: }
400: }
|