/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source 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, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * Free SoftwareFoundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Emil Ong */ package com.caucho.ejb.embeddable; import java.io.File; import java.io.IOException; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.ejb.EJBException; import javax.ejb.embeddable.EJBContainer; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import com.caucho.java.WorkDir; import com.caucho.vfs.JarPath; import com.caucho.vfs.Path; import com.caucho.vfs.Vfs; import com.caucho.xml.stream.XMLStreamReaderImpl; public class EJBContainerProvider implements javax.ejb.spi.EJBContainerProvider { public static final String WORK_DIR = "com.caucho.ejb.embeddable.workDir"; private static final Logger log = Logger.getLogger(EJBContainerProvider.class.getName()); @Override public EJBContainer createEJBContainer(Map<?,?> properties) throws EJBException { EJBContainerImpl container = null; if (properties == null) { container = new EJBContainerImpl(); addModulesFromClasspath(container, null); setWorkDir(); } else { String provider = (String) properties.get(EJBContainer.PROVIDER); // This is the EJBContainer implementation class and not the // EJBContainerProvider implementation for some reason. The spec // is ambiguous, but the TCK is not. if (provider != null && ! EJBContainerImpl.class.getName().equals(provider)) return null; String name = (String) properties.get(EJBContainer.APP_NAME); container = new EJBContainerImpl(name, properties); // FYI: only a single module is required for web profile addModules(container, properties.get(EJBContainer.MODULES)); setWorkDir(properties.get(WORK_DIR)); } container.start(); return container; } private String scanEjbJarXml(Path ejbJarXml) { // XXX use Config.configure once com.caucho.ejb.cfg allows configuration // without a live EjbManager try { XMLStreamReaderImpl reader = new XMLStreamReaderImpl(ejbJarXml.openRead()); while (reader.hasNext()) { if (reader.next() == XMLStreamReader.START_ELEMENT && "module-name".equals(reader.getLocalName())) return reader.getElementText(); } } catch (IOException e) { log.log(Level.FINE, e.toString(), e); } catch (XMLStreamException e) { log.log(Level.FINE, e.toString(), e); } return null; } private String getModuleName(String classpathComponent) { Path path = Vfs.lookup(classpathComponent); String tail = path.getTail(); String moduleName = classpathComponent; if (classpathComponent.endsWith(".jar") || classpathComponent.endsWith(".war")) { moduleName = tail.substring(0, tail.length() - ".jar".length()); path = JarPath.create(path); } Path ejbJarXml = path.lookup("META-INF/ejb-jar.xml"); if (ejbJarXml.canRead()) { String ejbJarModuleName = scanEjbJarXml(ejbJarXml); if (ejbJarModuleName != null) moduleName = ejbJarModuleName; } return moduleName; } private void addModulesFromClasspath(EJBContainerImpl container, Set<String> modules) { String classpath = System.getProperty("java.class.path"); String[] components = classpath.split(System.getProperty("path.separator")); for (String component : components) { String moduleName = getModuleName(component); if (moduleName.equals("")) continue; if (modules == null || modules.contains(moduleName)) { container.addModule(Vfs.lookup(component)); } } } private void addModules(EJBContainerImpl container, Object modulesValue) throws EJBException { if (modulesValue == null) { addModulesFromClasspath(container, null); } else if (modulesValue instanceof String) { HashSet<String> modules = new HashSet<String>(); modules.add((String) modulesValue); addModulesFromClasspath(container, modules); } else if (modulesValue instanceof String[]) { HashSet<String> modules = new HashSet<String>(); for (String module : (String []) modulesValue) { modules.add(module); } addModulesFromClasspath(container, modules); } else if (modulesValue instanceof File) { File file = (File) modulesValue; container.addModule(Vfs.lookup(file.getPath())); } else if (modulesValue instanceof File[]) { File []files = (File []) modulesValue; for (File file : files ) { container.addModule(Vfs.lookup(file.getPath())); } } else throw new EJBException("Value of '" + EJBContainer.MODULES + "' (EJBContainer.MODULES) must be one of the types String, String[], java.io.File, or java.io.File[]"); } private void setWorkDir() { setWorkDir(null); } private void setWorkDir(Object workDirValue) throws EJBException { if (workDirValue != null) { Path workDir = null; if (workDirValue instanceof String) { workDir = Vfs.lookup((String) workDirValue); } else if (workDirValue instanceof File) { workDir = Vfs.lookup(((File) workDirValue).getPath()); } else { throw new EJBException("Value of '" + WORK_DIR + "' must be either a String or java.io.File"); } WorkDir.setLocalWorkDir(workDir); } else { Path tmpDir = Vfs.lookup(System.getProperty("java.io.tmpdir")); String userName = System.getProperty("user.name"); Path workDir = tmpDir.lookup(userName).lookup("caucho-ejb"); WorkDir.setLocalWorkDir(workDir); } } }