001: /* ====================================================================
002: * The LateralNZ Software License, Version 1.0
003: *
004: * Copyright (c) 2003 LateralNZ. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by
021: * LateralNZ (http://www.lateralnz.org/) and other third parties."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. The names "LateralNZ" must not be used to endorse or promote
026: * products derived from this software without prior written
027: * permission. For written permission, please
028: * contact oss@lateralnz.org.
029: *
030: * 5. Products derived from this software may not be called "Panther",
031: * or "Lateral" or "LateralNZ", nor may "PANTHER" or "LATERAL" or
032: * "LATERALNZ" appear in their name, without prior written
033: * permission of LateralNZ.
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: * This software consists of voluntary contributions made by many
050: * individuals on behalf of LateralNZ. For more
051: * information on Lateral, please see http://www.lateralnz.com/ or
052: * http://www.lateralnz.org
053: *
054: */
055: package org.lateralnz.panther.container;
056:
057: import java.io.File;
058: import java.lang.reflect.Constructor;
059: import java.util.ArrayList;
060: import java.util.HashMap;
061: import java.util.Iterator;
062: import java.util.jar.JarFile;
063: import java.util.List;
064: import java.util.Map;
065: import java.util.Properties;
066:
067: import javax.naming.Reference;
068: import javax.naming.Referenceable;
069:
070: import org.apache.log4j.Logger;
071:
072: import org.w3c.dom.Document;
073:
074: import org.lateralnz.common.util.Constants;
075: import org.lateralnz.common.util.StringUtils;
076: import org.lateralnz.common.util.SystemUtils;
077: import org.lateralnz.panther.deploy.SessionDescriptor;
078: import org.lateralnz.panther.deploy.EJBJarUtils;
079: import org.lateralnz.panther.util.EJBConstants;
080: import org.lateralnz.panther.wrapper.EJBMetaDataWrapper;
081: import org.lateralnz.panther.wrapper.KeyedPoolableBeanObjectFactory;
082: import org.lateralnz.panther.wrapper.SessionBeanHome;
083:
084: import org.apache.commons.pool.impl.GenericKeyedObjectPool;
085:
086: /**
087: *
088: * @author J R Briggs
089: */
090: public class SSBContainer extends Container implements Constants,
091: Referenceable {
092: private static final Logger log = Logger
093: .getLogger(SSBContainer.class.getName());
094: private static Reference REF = new Reference(SSBContainer.class
095: .getName());
096:
097: private Map ssbeans = new HashMap(); // a map of the beans in this container
098: private GenericKeyedObjectPool pool = null;
099: private KeyedPoolableBeanObjectFactory kpbof = null;
100:
101: /**
102: *
103: */
104: public SSBContainer(Properties props, Object parent)
105: throws Exception {
106: super (props, parent);
107:
108: kpbof = new KeyedPoolableBeanObjectFactory();
109: //pool = new GenericKeyedObjectPool(kpbof, 200, GenericKeyedObjectPool.WHEN_EXHAUSTED_BLOCK, 50000, 20);
110: pool = new GenericKeyedObjectPool(kpbof, -1);
111:
112: if (log.isInfoEnabled()) {
113: log.info("deploy dir " + pantherHome + deployDir);
114: }
115:
116: // deploy ejb-jars
117: String[] filelist = SystemUtils.getFileList(pantherHome
118: + deployDir, ".*\\.jar$");
119: if (log.isInfoEnabled()) {
120: log.info(deployDir + " file list: " + filelist.length);
121: }
122: for (int i = 0; i < filelist.length; i++) {
123: if (log.isDebugEnabled()) {
124: log.debug("evaluating: " + filelist[i]);
125: }
126: deploy(pantherHome + deployDir + filelist[i]);
127: }
128:
129: System.gc();
130: if (log.isInfoEnabled()) {
131: log.info("ssbc initialisation complete");
132: }
133: }
134:
135: /**
136: * shutdown and cleanup the server
137: */
138: public void shutdown() {
139: ssbeans.clear();
140: }
141:
142: /**
143: * deploy an ejb jar file. First checks if it is an ejb jar file (i.e. does it contain
144: * ejb-jar.xml?), then parses the contents
145: */
146: private void deploy(String filename) throws Exception {
147: File f = new File(filename);
148: JarFile jar = new JarFile(f, true, JarFile.OPEN_READ);
149: Document doc = EJBJarUtils.getEJBJarXML(jar);
150:
151: // not an ejb jar file
152: if (doc == null) {
153: if (log.isInfoEnabled()) {
154: log.info("no ejb-jar.xml file found");
155: }
156: return;
157: } else if (log.isInfoEnabled()) {
158: log.info("found ejb-jar.xml");
159: }
160:
161: if (log.isInfoEnabled()) {
162: log.info("checking for session bean descriptors");
163: }
164:
165: // various lists needed during the parse
166: List ejbwrappers = new ArrayList();
167: List rmicfiles = new ArrayList();
168: List wrapperClasses = new ArrayList();
169:
170: // work through the session descriptors
171: List l = EJBJarUtils.getSessionDescriptors(doc);
172: Iterator iter = l.iterator();
173: while (iter.hasNext()) {
174: SessionDescriptor sd = (SessionDescriptor) iter.next();
175:
176: // get the remote, ejb and home classes
177: Class remote = Class.forName(sd.getEJBRemoteClass());
178: Class home = Class.forName(sd.getEJBHomeClass());
179: Class ejb = Class.forName(sd.getEJBClass());
180:
181: String packageName = sd.getEJBRemoteClass().substring(0,
182: sd.getEJBRemoteClass().lastIndexOf('.'));
183: String packageDir = StringUtils.replace(packageName, DOT,
184: FILE_SEPARATOR);
185: String[] tmp = StringUtils.toArray(remote.getName(), DOT);
186:
187: // this is what we'll call our ejb wrapper
188: String wrapperName = tmp[tmp.length - 1] + "Impl";
189: String homeName = tmp[tmp.length - 1] + "HomeImpl";
190: //String wrapperFullName = StringUtils.replace(packageDir, FILE_SEPARATOR, UNDERSCORE) + UNDERSCORE + wrapperName;
191: String ejbNameResolved = StringUtils.replace(sd
192: .getEJBName(), FILE_SEPARATOR, UNDERSCORE);
193:
194: // now we load the env-entry parameters from the ejb-jar
195: if (log.isInfoEnabled()) {
196: log.info("loading environment entries " + envContext);
197: }
198: Map env = sd.getEnvEntries();
199: Iterator enviter = env.keySet().iterator();
200: while (enviter.hasNext()) {
201: String key = (String) enviter.next();
202: if (log.isInfoEnabled()) {
203: log.info("binding " + ejbNameResolved + UNDERSCORE
204: + key + " with value " + env.get(key));
205: }
206: envContext.rebind(ejbNameResolved + UNDERSCORE + key,
207: env.get(key));
208: }
209:
210: Class wrapperClass = Class.forName(remote.getPackage()
211: .getName()
212: + DOT + wrapperName);
213: Class homeClass = Class.forName(remote.getPackage()
214: .getName()
215: + DOT + homeName);
216: kpbof.setWrapperClass(ejbNameResolved, wrapperClass);
217:
218: Constructor cons = homeClass.getConstructor(new Class[] {
219: String.class, GenericKeyedObjectPool.class });
220: SessionBeanHome beanhome = (SessionBeanHome) cons
221: .newInstance(new Object[] { ejbNameResolved, pool });
222: beanhome
223: .setEJBMetaData(new EJBMetaDataWrapper(
224: beanhome,
225: homeClass,
226: remote,
227: (sd.getSessionType().equals(
228: EJBConstants.STATEFUL) ? EJBConstants.STATEFUL_SESSION_BEAN
229: : EJBConstants.STATELESS_SESSION_BEAN)));
230: String[] sub = StringUtils.toArray(sd.getEJBName(),
231: FORWARD_SLASH);
232: try {
233: initContext.createSubcontext(sub[0]);
234: } catch (Exception e) {
235: }
236: if (log.isInfoEnabled()) {
237: log.info("binding " + sd.getEJBName());
238: }
239: initContext.rebind(sd.getEJBName(), beanhome);
240: ejbwrappers.add(beanhome);
241: ssbeans.put(sd.getEJBName(), beanhome);
242: }
243:
244: if (log.isInfoEnabled()) {
245: log.info("initialising ejbs...");
246: }
247:
248: }
249:
250: /**
251: * get a reference to this container
252: */
253: public Reference getReference() {
254: return REF;
255: }
256:
257: /**
258: * a wrapper for ejb data (classname, filename, ejb name)
259: */
260: private class EJBData {
261: public String className;
262: public String classFilename;
263: public String ejbName;
264:
265: EJBData(String className, String classFilename, String ejbName) {
266: this.className = className;
267: this.classFilename = classFilename;
268: this.ejbName = ejbName;
269: }
270: }
271: }
|