/* * JBoss, Home of Professional Open Source. * Copyright 2008, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package javax.ejb; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.ejb.spi.EJBContainerProvider; import javax.naming.Context; import org.jboss.ejb3.api.spi.EJBContainerWrapper; /** * Used to execute an EJB application in an embeddable container. * * @author Carlo de Wolf * @version $Revision: $ * @since 3.1 */ public abstract class EJBContainer { public static final String EMBEDDABLE_INITIAL = "javax.ejb.embeddable.initial"; public static final String EMBEDDABLE_MODULES_PROPERTY = "javax.ejb.embeddable.modules"; private static EJBContainerWrapper currentEJBContainer; private static final Pattern nonCommentPattern = Pattern.compile("^([^#]+)"); private static List factories = new ArrayList(); static { findAllFactories(); } /** * Shutdown an embeddable EJBContainer instance. */ public abstract void close(); /** * Create and initialize an embeddable EJB container. * JVM classpath is searched for all ejb-jars or exploded ejb-jars in directory format. * * @return EJBContainer instance * @throws EJBException Thrown if the container or application could not * be successfully initialized. */ public static EJBContainer createEJBContainer() throws EJBException { return createEJBContainer(null); } /** * Create and initialize an embeddable EJB container with an * set of configuration properties and names of modules to be initialized. * * @param properties One or more spec-defined or vendor-specific properties. * The spec reserves the prefix "javax.ejb." for spec-defined properties. * @return EJBContainer instance * @throws EJBException Thrown if the container or application could not * be successfully initialized. */ public static EJBContainer createEJBContainer(Map properties) throws EJBException { for(EJBContainerProvider factory : factories) { EJBContainer container = factory.createEJBContainer(properties); if(container != null) { currentEJBContainer = new EJBContainerWrapper(container); return currentEJBContainer; } } throw new EJBException("Unable to instantiate container with factories " + factories); } private static List factoryNamesFromReader(BufferedReader reader) throws IOException { List names = new ArrayList(); String line; while ((line = reader.readLine()) != null) { line = line.trim(); Matcher m = nonCommentPattern.matcher(line); if (m.find()) { names.add(m.group().trim()); } } return names; } private static void findAllFactories() { try { ClassLoader loader = Thread.currentThread().getContextClassLoader(); Enumeration resources = loader.getResources("META-INF/services/" + EJBContainerProvider.class.getName()); Set names = new HashSet(); while (resources.hasMoreElements()) { URL url = resources.nextElement(); InputStream is = url.openStream(); try { names.addAll(factoryNamesFromReader(new BufferedReader(new InputStreamReader(is)))); } finally { is.close(); } } for (String s : names) { Class factoryClass = loader.loadClass(s); factories.add(EJBContainerProvider.class.cast(factoryClass.newInstance())); } } catch (IOException e) { throw new EJBException(e); } catch (InstantiationException e) { throw new EJBException(e); } catch (IllegalAccessException e) { throw new EJBException(e); } catch (ClassNotFoundException e) { throw new EJBException(e); } } /** * Retrieve the last EJBContainer instance to be successfully returned * from an invocation to a createEJBContainer method. * @return EJBContainer instance, or null if none exists or if the last EJBContainer * instance has been closed. */ public static EJBContainer getCurrentEJBContainer() { if(currentEJBContainer != null && currentEJBContainer.isClosed()) return null; return currentEJBContainer; } /** * Retrieve a naming context for looking up references to session beans executing in * the embeddable container. * * @return The naming context. */ public Context getContext() { throw new UnsupportedOperationException(this + " does not support a naming context"); } }