001: /*
002: $Header: /cvsroot/xorm/xorm/src/org/xorm/util/AppConfigFactory.java,v 1.2 2003/05/08 22:55:38 wbiggs Exp $
003:
004: This file is part of XORM.
005:
006: XORM is free software; you can redistribute it and/or modify
007: it under the terms of the GNU General Public License as published by
008: the Free Software Foundation; either version 2 of the License, or
009: (at your option) any later version.
010:
011: XORM is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: GNU General Public License for more details.
015:
016: You should have received a copy of the GNU General Public License
017: along with XORM; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020:
021: package org.xorm.util;
022:
023: import java.util.logging.Logger;
024: import javax.naming.InitialContext;
025: import javax.naming.Context;
026: import javax.naming.NamingException;
027:
028: /** Base class for deriving custom AppConfig factories. This object provides
029: the core support for loading AppConfig objects from well-known set places.
030: All you have to do when subclassing this object is to pass in the
031: appropriate settings in the constructor. The rest is handled by this
032: object.
033: <p>
034: For example, here is the code for a singleton implementation:
035: <p>
036: <pre>package com.myapp;
037:
038: import org.xorm.util.AppConfigFactory;
039:
040: public final class MyConfigFactory extends AppConfigFactory {
041: private static MyConfigFactory singleton;
042: static {
043: singleton = new MyConfigFactory();
044: }
045:
046: public static MyConfigFactory getInstance() {
047: return singleton;
048: }
049:
050: private MyConfigFactory() {
051: super("myapp/config",
052: "com.myapp.configFile",
053: "/myapp.properties");
054: }
055: }</pre>
056: <p>
057: The example above would look for application configuration in the following
058: places:
059: <ol>
060: <li>It looks for a <code>"myapp/config"</code> JNDI resource, which you
061: could set up under your servlet engine (i.e. Tomcat) or webapp
062: configuration. If you choose to configure your application via JNDI,
063: you should make sure the resource points to an AppConfig object.
064: <li>It looks at the <code>"com.myapp.configFile"</code> system property,
065: which would specify the resource or file where the application properties
066: live.
067: <li>It falls back on a default resource or file
068: <code>"/myapp.properties"</code> which can live either on the classpath
069: or on the file system. Generally you are encouraged to build a default
070: property file into your application's JAR or class files...in the case
071: above named myapp.properties.
072: </ol>
073: <p>
074: Then, in your application code, whenever you need to access properties
075: or get a PersistenceManager instance, simply do this:
076: <p>
077: <pre>package com.myapp;
078:
079: import javax.jdo.PersistenceManager;
080: import org.xorm.util.AppConfig;
081:
082: public class Example {
083: public void main(String[] args) {
084: AppConfig appConfig = MyAppConfigFactory.getInstance().getAppConfig();
085: PersistenceManager mgr = appConfig.getPersistenceManager();
086: String prop = appConfig.getProperty("someProperty");
087: }
088: }</pre>
089:
090: @author Dan Checkoway
091: @see AppConfig
092: */
093: public class AppConfigFactory {
094: protected String jndiConfigResource;
095: protected String configFileSystemProperty;
096: protected String defaultConfigFile;
097: protected Class appConfigClass;
098: protected Logger logger;
099: protected AppConfig config = null;
100:
101: /** Constructor
102: @param jndiConfigResource the resource path (under "jndi:comp/env")
103: where the first attempt to load the configuration should look
104: @param configFileSystemProperty the name of a system property that
105: may have been defined as a second-level fallback, pointing to a file
106: or resource where the configuration should be loaded
107: @param defaultConfigFile the path of a file or resource where the
108: last ditch attempt to find the configuration will look
109: */
110: protected AppConfigFactory(String jndiConfigResource,
111: String configFileSystemProperty, String defaultConfigFile) {
112: this (jndiConfigResource, configFileSystemProperty,
113: defaultConfigFile, AppConfig.class);
114: }
115:
116: protected AppConfigFactory(String jndiConfigResource,
117: String configFileSystemProperty, String defaultConfigFile,
118: Class appConfigClass) {
119: this .jndiConfigResource = jndiConfigResource;
120: this .configFileSystemProperty = configFileSystemProperty;
121: this .defaultConfigFile = defaultConfigFile;
122: this .appConfigClass = appConfigClass;
123: logger = Logger.getLogger(this .getClass().getName());
124: }
125:
126: /** Get the AppConfig associated with this factory. This factory loads
127: a single instance of AppConfig and keeps it around for subsequent
128: calls. Only that one instance is ever created.
129: @return the respective AppConfig object
130: @see AppConfig
131: */
132: public AppConfig getAppConfig() {
133: if (config == null) {
134: synchronized (this ) {
135: if (config == null) {
136: config = loadAppConfig();
137: }
138: }
139: }
140: return config;
141: }
142:
143: /** Load the AppConfig from the specified locations. This method will
144: first try to load the config from the specified JNDI resource. Then
145: it will look at the specified system property value, falling back on
146: the default path.
147: @return a new instance of a freshly loaded AppConfig
148: */
149: protected AppConfig loadAppConfig() {
150: // First check to see if there's already a pre-set JNDI resource
151: AppConfig config = loadAppConfigFromJNDI();
152: if (config != null) {
153: logger.info("Found JNDI resource: " + jndiConfigResource);
154: return config;
155: } else {
156: logger.info("Unable to find JNDI resource: "
157: + jndiConfigResource);
158: }
159:
160: // Create a new AppConfig using the file specified in the system
161: // property, falling back to the default file.
162: try {
163: config = (AppConfig) appConfigClass.newInstance();
164: } catch (InstantiationException e) {
165: logger.severe("AppConfig class " + appConfigClass.getName()
166: + " could not be instantiated");
167: } catch (ClassCastException e) {
168: logger.severe("AppConfig class " + appConfigClass.getName()
169: + " could not be cast to org.xorm.util.AppConfig");
170: } catch (IllegalAccessException e) {
171: logger
172: .severe("AppConfig class "
173: + appConfigClass.getName()
174: + " could not be instantiated (is constructor public?)");
175: }
176: String propFile = System.getProperty(configFileSystemProperty);
177: if (propFile == null) {
178: //logger.info(configFileSystemProperty + " system property not set");
179: propFile = defaultConfigFile;
180: }
181: logger.info("Using properties file or resource: " + propFile);
182: config.loadProperties(propFile);
183: return config;
184: }
185:
186: /** Load the AppConfig as a JNDI resource
187: @return any AppConfig instance configured under the specified resource
188: path, if found; otherwise null
189: */
190: protected AppConfig loadAppConfigFromJNDI() {
191: try {
192: Context initCtx = new InitialContext();
193: Context envCtx = (Context) initCtx.lookup("java:comp/env");
194: AppConfig config = (AppConfig) envCtx
195: .lookup(jndiConfigResource);
196: if (config != null) {
197: return config;
198: }
199: } catch (NamingException ignored) {
200: }
201: return null;
202: }
203: }
|