001: /*
002: * ====================================================================
003: * JAFFA - Java Application Framework For All
004: *
005: * Copyright (C) 2002 JAFFA Development Group
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: * Redistribution and use of this software and associated documentation ("Software"),
022: * with or without modification, are permitted provided that the following conditions are met:
023: * 1. Redistributions of source code must retain copyright statements and notices.
024: * Redistributions must also contain a copy of this document.
025: * 2. Redistributions in binary form must reproduce the above copyright notice,
026: * this list of conditions and the following disclaimer in the documentation
027: * and/or other materials provided with the distribution.
028: * 3. The name "JAFFA" must not be used to endorse or promote products derived from
029: * this Software without prior written permission. For written permission,
030: * please contact mail to: jaffagroup@yahoo.com.
031: * 4. Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
032: * appear in their names without prior written permission.
033: * 5. Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
034: *
035: * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: */
049:
050: /*
051: * Factory.java
052: *
053: * Created on November 9, 2001, 11:02 AM
054: */
055:
056: package org.jaffa.middleware;
057:
058: import org.jaffa.config.Config;
059: import org.apache.log4j.Logger;
060: import java.util.PropertyResourceBundle;
061: import java.util.MissingResourceException;
062:
063: /**
064: * Factory used by component managers to get a handle on the correct Implementation of the
065: * Transaction Controller to use.
066: * There is a System Setting in the framework.properties file that controls which implementation
067: * the factory returns. This setting is either 1, 2 or 3
068: *
069: * Setting 1 - This means that the Factory is in test mode, this means that it will go to an additional
070: * properties file (middleware_test.properties) where it will look for a property with the
071: * same (full) name as the interface class.
072: * It expects to find a setting here to give the 'real' setting for the factory. If there is
073: * no property or any other error, it assumes a '2-Tier' setting. If there is a propery
074: * it must have the value 1, 2 or 3
075: * Setting 2 - This means the Factory is in 2-tier Mode for all Interfaces
076: * Setting 3 - This means the Factory is in 3-tier Mode for all Interfaces
077: *
078: * How do the different Modes Work? Assuming the interface is in package XXX and is called IYYY.java
079: * Test Mode - This assumes there is an implementing class called XXX.test.YYYTx.java.
080: * This class should have fake implementations for all transaction methods such
081: * that the presentation tier for the component can be fully tested.
082: * 2-Tier Mode - This assumes there is an implementing class called XXX.tx.YYYTx.java. This
083: * implementing class should be the full implementation, and will be executed in
084: * the presentation tier.
085: * 3-Tier Mode - This assumes there is an implementing class called XXX.ejb.YYYPx.java. This
086: * implementing class is a Proxy to the real Transaction Controller. The proxy will
087: * communicate with a Session Bean which will wrapper the real tranaction class
088: * (normally called XXX.tx.YYYTx.java)
089: *
090: * @author GautamJ/PaulE
091: * @version 2.0
092: */
093: public class Factory {
094: private static final Logger log = Logger.getLogger(Factory.class);
095:
096: private static final byte TIER_TEST = 1;
097: private static final byte TIER2 = 2;
098: private static final byte TIER3 = 3;
099:
100: private static final String MIDDLEWARE_RESOURCE = "middleware_test";
101:
102: private static Byte c_tier = null;
103:
104: /** Creates the Real Transaction Controller Object To Be Used
105: * Based on the configuration settings. The real
106: * object may be either a Test Rig, a Local Implemntation or a Proxy
107: * @param interfaceClass The name of the interface that the transaction controller bust be implementing
108: * @throws CreateServiceException Thrown if the correct object could not be created
109: * @return Returns the specified obejct that implements the
110: * reqiured interface. This object on return should be
111: * casted back to the interface name that was passed in,
112: * not to a specific object instance.
113: */
114: public static Object createObject(Class interfaceClass)
115: throws CreateServiceException {
116:
117: Byte tier = null;
118: String className = null;
119: try {
120: // Make sure that an interface is passed in
121: if (!interfaceClass.isInterface()) {
122: log
123: .error("The Input Should be an Interface For A Component Transaction Controller");
124: throw new CreateServiceException(
125: CreateServiceException.NOT_AN_INTERFACE,
126: new Object[] { interfaceClass.getName() });
127: }
128:
129: // Extract the componentName & packageName from the input
130: String componentName = extractComponentName(interfaceClass);
131: String packageName = extractPackageName(interfaceClass);
132:
133: // Read the Tier property
134: if (c_tier == null)
135: c_tier = readTier();
136:
137: // If this is 'TIER_TEST', then the real tier should be read from the 'middleware_test.properties' file
138: if (c_tier.byteValue() == TIER_TEST) {
139: tier = readTestTier(interfaceClass.getName());
140: if (log.isDebugEnabled())
141: log.debug("Test Tier Setting Is " + tier);
142: } else
143: // The tier to be used should be in the static varaiable
144: tier = c_tier;
145:
146: // Determine the class to instantiate based on the tier property
147: if (tier.byteValue() == TIER2) {
148: className = (packageName == null ? "tx." : packageName
149: + ".tx.")
150: + componentName + "Tx";
151: } else if (tier.byteValue() == TIER3) {
152: className = (packageName == null ? "ejb." : packageName
153: + ".ejb.")
154: + componentName + "Px";
155: } else {
156: // Assume it is a test tier
157: className = (packageName == null ? "test."
158: : packageName + ".test.")
159: + componentName + "Tx";
160: }
161:
162: if (log.isDebugEnabled())
163: log.debug("Middleware Factory: Setting=" + c_tier
164: + ", Using Mode=" + tier + ", Use Class="
165: + className);
166:
167: // instantiate the class
168: return (Class.forName(className)).newInstance();
169:
170: } catch (Exception e) {
171: log.error(
172: "Cannot instantiate the Transaction controller : "
173: + className, e);
174: throw new CreateServiceException(
175: CreateServiceException.INSTANTIATION_FAILED,
176: new Object[] { className }, e);
177: }
178: }
179:
180: private static String extractComponentName(Class interfaceClass)
181: throws CreateServiceException {
182: String componentName = interfaceClass.getName();
183: int i = componentName.lastIndexOf('.');
184: if (i >= 0 && ++i < componentName.length())
185: componentName = componentName.substring(i);
186: if (componentName.startsWith("I") && componentName.length() > 1)
187: componentName = componentName.substring(1);
188: else {
189: log.error("The interface " + componentName
190: + " should be prefixed by an 'I'");
191: throw new CreateServiceException(
192: CreateServiceException.INVALID_INPUT,
193: new Object[] { componentName });
194: }
195:
196: return componentName;
197: }
198:
199: private static String extractPackageName(Class interfaceClass) {
200: // the getPackage() doesnt work under a web-server
201: // String packageName = null;
202: // Package p = interfaceClass.getPackage();
203: // if (p != null) {
204: // packageName = p.getName();
205: // if ( packageName != null && packageName.equals("") )
206: // packageName = null;
207: // }
208: // return packageName;
209:
210: String packageName = null;
211: String className = interfaceClass.getName();
212: int i = className.lastIndexOf('.');
213: if (i >= 0)
214: packageName = className.substring(0, i);
215: return packageName;
216: }
217:
218: private static Byte readTier() {
219: String tier = (String) Config.getProperty(Config.PROP_TIER, ""
220: + TIER2);
221: if (log.isDebugEnabled())
222: log.debug("Initialize Middleware Factory: Setting=" + tier);
223: return new Byte(tier);
224: }
225:
226: /** Read the tier setting from the middleware_test.properties file */
227: private static Byte readTestTier(String className) {
228: PropertyResourceBundle prop = null;
229: try {
230: prop = (PropertyResourceBundle) PropertyResourceBundle
231: .getBundle(MIDDLEWARE_RESOURCE);
232: } catch (MissingResourceException e) {
233: log
234: .warn(
235: "Factory Set To Test Mode, But Config File Is Missing!, Mode 2 will be assumed! ",
236: e);
237: return new Byte(TIER2);
238: }
239:
240: try {
241: String tier = (String) prop.getObject(className);
242: if (tier == null || "123".indexOf(tier) == -1) {
243: log.info("Factory Test Mode For Interface '"
244: + className + "' Not Valid. Value is " + tier
245: + ", Mode 2 will be assumed! ");
246: tier = "" + TIER2;
247: }
248: return new Byte(tier);
249: } catch (MissingResourceException e) {
250: log
251: .info("Factory Set To Test Mode, But Definition For Interface '"
252: + className
253: + "' not found, Mode 2 will be assumed! ");
254: return new Byte(TIER2);
255: }
256: }
257: }
|