001: /*
002: * Copyright (c) 2002-2003 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.webwork.config;
006:
007: import com.opensymphony.xwork.ObjectFactory;
008: import com.opensymphony.webwork.WebWorkConstants;
009: import org.apache.commons.logging.Log;
010: import org.apache.commons.logging.LogFactory;
011:
012: import java.util.Iterator;
013: import java.util.Locale;
014: import java.util.StringTokenizer;
015:
016: /**
017: * Handles all WebWork2 config properties. Implementation of this class is pluggable (the
018: * default implementation is {@link DefaultConfiguration}). This gives developers to ability to customize how
019: * WebWork2 properties are set and retrieved. As an example, a developer may wish to check a separate property
020: * store before delegating to the WebWork one. <p>
021: * <p/>
022: * Key methods: <ul>
023: * <p/>
024: * <li>{@link #getLocale()}</li>
025: * <li>{@link #getString(String)}</li>
026: * <li>{@link #set(String, Object)}</li>
027: * <li>{@link #list()}</li></ul>
028: * <p/>
029: * Key methods for subclassers: <ul>
030: * <p/>
031: * <li>{@link #getImpl(String)}</li>
032: * <li>{@link #setImpl(String, Object)}</li>
033: * <li>{@link #listImpl()}</li>
034: * <li>{@link #isSetImpl(String)}</li></ul>
035: *
036: * @author Rickard �berg
037: * @author Jason Carreira
038: * @author Bill Lynch (docs)
039: */
040: public class Configuration {
041:
042: static Configuration configurationImpl;
043: static Configuration defaultImpl;
044: static Locale locale; // Cached locale
045: private static final Log LOG = LogFactory
046: .getLog(Configuration.class);
047:
048: /**
049: * Sets the current configuration implementation. Can only be called once.
050: *
051: * @param config a Configuration implementation
052: * @throws IllegalStateException if an error occurs when setting the configuration implementation.
053: */
054: public static void setConfiguration(Configuration config)
055: throws IllegalStateException {
056: configurationImpl = config;
057: locale = null; // Reset cached locale
058: }
059:
060: /**
061: * Gets the current configuration implementation.
062: *
063: * @return the current configuration implementation.
064: */
065: public static Configuration getConfiguration() {
066: return (configurationImpl == null) ? getDefaultConfiguration()
067: : configurationImpl;
068: }
069:
070: /**
071: * Returns the WebWork2 locale. Keys off the property <tt>webwork.locale</tt> which should be set
072: * as the Java {@link java.util.Locale#toString() toString()} representation of a Locale object (i.e.,
073: * "en", "de_DE", "_GB", "en_US_WIN", "de__POSIX", "fr_MAC", etc). <p>
074: * <p/>
075: * If no locale is specified then the default VM locale is used ({@link java.util.Locale#getDefault()}).
076: *
077: * @return the WebWork2 locale if specified or the VM default locale.
078: */
079: public static Locale getLocale() {
080: if (locale == null) {
081: try {
082: StringTokenizer localeTokens = new StringTokenizer(
083: getString(WebWorkConstants.WEBWORK_LOCALE), "_");
084: String lang = null;
085: String country = null;
086:
087: if (localeTokens.hasMoreTokens()) {
088: lang = localeTokens.nextToken();
089: }
090:
091: if (localeTokens.hasMoreTokens()) {
092: country = localeTokens.nextToken();
093: }
094:
095: locale = new Locale(lang, country);
096: } catch (Throwable t) {
097: // Default
098: LOG.warn("Setting locale to the default locale");
099: locale = Locale.getDefault();
100: }
101: }
102:
103: return locale;
104: }
105:
106: /**
107: * Determines whether or not a value has been set. Useful for testing for the existance of parameter without
108: * throwing an IllegalArgumentException.
109: *
110: * @param name the name of the property to test.
111: * @return <tt>true</tt> if the property exists and has a value, <tt>false</tt> otherwise.
112: */
113: public static boolean isSet(String name) {
114: return getConfiguration().isSetImpl(name);
115: }
116:
117: /**
118: * Returns a property as a String. This will throw an <tt>IllegalArgumentException</tt> if an error occurs
119: * while retrieveing the property or if the property doesn't exist.
120: *
121: * @param name the name of the property to get.
122: * @return the property as a String
123: * @throws IllegalArgumentException if an error occurs retrieveing the property or the property does not exist.
124: */
125: public static String getString(String name)
126: throws IllegalArgumentException {
127: String val = get(name).toString();
128:
129: return val;
130: }
131:
132: /**
133: * Returns a property as an Object. This will throw an <tt>IllegalArgumentException</tt> if an error occurs
134: * while retrieveing the property or if the property doesn't exist.
135: *
136: * @param name the name of the property to get.
137: * @return the property as an Object.
138: * @throws IllegalArgumentException if an error occurs retrieveing the property or the property does not exist.
139: */
140: public static Object get(String name)
141: throws IllegalArgumentException {
142: Object val = getConfiguration().getImpl(name);
143:
144: return val;
145: }
146:
147: /**
148: * Returns an Iterator of all properties names.
149: *
150: * @return an Iterator of all properties names.
151: */
152: public static Iterator list() {
153: return getConfiguration().listImpl();
154: }
155:
156: /**
157: * Implementation of the {@link #isSet(String)} method.
158: *
159: * @see #isSet(String)
160: */
161: public boolean isSetImpl(String name) {
162: // this is dumb.. maybe it should just throw an unsupported op like the rest of the *Impl
163: // methods in this class.
164: return false;
165: }
166:
167: /**
168: * Sets a property. Throws an exception if an error occurs when setting the property or if the
169: * Configuration implementation does not support setting properties.
170: *
171: * @param name the name of the property to set.
172: * @param value the property to set.
173: * @throws IllegalArgumentException if an error occurs when setting the property.
174: * @throws UnsupportedOperationException if the config implementation does not support setting properties.
175: */
176: public static void set(String name, Object value)
177: throws IllegalArgumentException,
178: UnsupportedOperationException {
179: getConfiguration().setImpl(name, value);
180: }
181:
182: /**
183: * Implementation of the {@link #set(String, Object)} method.
184: *
185: * @see #set(String, Object)
186: */
187: public void setImpl(String name, Object value)
188: throws IllegalArgumentException,
189: UnsupportedOperationException {
190: throw new UnsupportedOperationException(
191: "This configuration does not support updating a setting");
192: }
193:
194: /**
195: * Implementation of the {@link #get(String)} method.
196: *
197: * @see #get(String)
198: */
199: public Object getImpl(String aName) throws IllegalArgumentException {
200: return null;
201: }
202:
203: /**
204: * Implementation of the {@link #list()} method.
205: *
206: * @see #list()
207: */
208: public Iterator listImpl() {
209: throw new UnsupportedOperationException(
210: "This configuration does not support listing the settings");
211: }
212:
213: private static Configuration getDefaultConfiguration() {
214: if (defaultImpl == null) {
215: // Create bootstrap implementation
216: defaultImpl = new DefaultConfiguration();
217:
218: // Create default implementation
219: try {
220: String className = getString(WebWorkConstants.WEBWORK_CONFIGURATION);
221:
222: if (!className.equals(defaultImpl.getClass().getName())) {
223: try {
224: // singleton instances shouldn't be built accessing request or session-specific context data
225: defaultImpl = (Configuration) ObjectFactory
226: .getObjectFactory()
227: .buildBean(
228: Thread
229: .currentThread()
230: .getContextClassLoader()
231: .loadClass(className),
232: null);
233: } catch (Exception e) {
234: LOG.error(
235: "Could not instantiate configuration",
236: e);
237: }
238: }
239: } catch (IllegalArgumentException ex) {
240: // ignore
241: }
242: }
243:
244: return defaultImpl;
245: }
246:
247: public static void reset() {
248: defaultImpl = null;
249: configurationImpl = null;
250: }
251: }
|