Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.apache.openejb.OpenEjbContainer Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.openejb;
import org.apache.openejb.assembler.classic.AppInfo;
import org.apache.openejb.assembler.classic.Assembler;
import org.apache.openejb.config.AppModule;
import org.apache.openejb.config.ConfigurationFactory;
import org.apache.openejb.config.ConnectorModule;
import org.apache.openejb.config.DeploymentLoader;
import org.apache.openejb.config.EjbModule;
import org.apache.openejb.config.NewLoaderLogic;
import org.apache.openejb.config.PersistenceModule;
import org.apache.openejb.config.ValidationFailedException;
import org.apache.openejb.core.ParentClassLoaderFinder;
import org.apache.openejb.core.ProvidedClassLoaderFinder;
import org.apache.openejb.jee.Application;
import org.apache.openejb.jee.Beans;
import org.apache.openejb.jee.Connector;
import org.apache.openejb.jee.EjbJar;
import org.apache.openejb.jee.EnterpriseBean;
import org.apache.openejb.jee.ManagedBean;
import org.apache.openejb.jee.TransactionType;
import org.apache.openejb.jee.jpa.unit.Persistence;
import org.apache.openejb.jee.jpa.unit.PersistenceUnit;
import org.apache.openejb.jee.oejb3.EjbDeployment;
import org.apache.openejb.jee.oejb3.OpenejbJar;
import org.apache.openejb.loader.Options;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.util.Exceptions;
import org.apache.openejb.util.JavaSecurityManagers;
import org.apache.openejb.util.Join;
import org.apache.openejb.util.JuliLogStreamFactory;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import org.apache.openejb.util.OptionsLog;
import org.apache.openejb.util.ServiceManagerProxy;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.web.lifecycle.test.MockHttpSession;
import org.apache.webbeans.web.lifecycle.test.MockServletContext;
import org.apache.xbean.naming.context.ContextFlyweight;
import javax.ejb.EJBException;
import javax.ejb.embeddable.EJBContainer;
import javax.ejb.spi.EJBContainerProvider;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.validation.ValidationException;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.logging.LogManager;
import static org.apache.openejb.cdi.ScopeHelper.startContexts;
import static org.apache.openejb.cdi.ScopeHelper.stopContexts;
/**
* @version $Rev$ $Date$
*/
public final class OpenEjbContainer extends EJBContainer {
static {
// if tomee embedded was ran we'll lost log otherwise
final String logManger = JavaSecurityManagers.getSystemProperty("java.util.logging.manager");
if (logManger != null) {
try {
Thread.currentThread().getContextClassLoader().loadClass(logManger);
} catch (final Exception ignored) {
final Field field;
try {
field = LogManager.class.getDeclaredField("manager");
field.setAccessible(true);
field.set(null, new JuliLogStreamFactory.OpenEJBLogManager());
} catch (final Exception ignore) {
// ignore
}
}
}
}
public static final String OPENEJB_EMBEDDED_REMOTABLE = "openejb.embedded.remotable";
public static final String OPENEJB_EJBCONTAINER_CLOSE = "openejb.ejbcontainer.close";
public static final String OPENEJB_EJBCONTAINER_CLOSE_SINGLE = "single-jvm";
private static OpenEjbContainer instance;
private static Logger logger; // initialized lazily to get the logging config from properties
private ServiceManagerProxy serviceManager;
private final Options options;
private final OpenEjbContainer.GlobalContext globalJndiContext;
private final WebBeansContext webBeanContext;
private volatile ServletContext servletContext;
private volatile HttpSession session;
private OpenEjbContainer(final Map, ?> map, final AppContext appContext) {
webBeanContext = appContext.getWebBeansContext();
globalJndiContext = new GlobalContext(appContext.getGlobalJndiContext());
final Properties properties = new Properties();
properties.putAll(map);
options = new Options(properties);
startNetworkServices();
if (webBeanContext != null) {
servletContext = new MockServletContext();
session = new MockHttpSession();
try {
startContexts(webBeanContext.getContextsService(), servletContext, session);
} catch (final Exception e) {
logger().warning("can't start all CDI contexts", e);
}
}
}
@Override
public void close() {
if (isSingleClose()) {
return;
}
doClose();
}
private static boolean isSingleClose() {
return OPENEJB_EJBCONTAINER_CLOSE_SINGLE.equals(SystemInstance.get().getProperty(OPENEJB_EJBCONTAINER_CLOSE, "by-invocation"));
}
private synchronized void doClose() {
if (instance == null) {
return;
}
if (serviceManager != null) {
serviceManager.stop();
}
try {
globalJndiContext.close();
} catch (final NamingException e) {
throw new IllegalStateException(e);
}
final Assembler assembler = SystemInstance.get().getComponent(Assembler.class);
if (assembler != null) {
for (final AppInfo info : assembler.getDeployedApplications()) {
try {
assembler.destroyApplication(info);
} catch (final UndeployException e) {
logger().error(e.getMessage(), e);
}
}
}
if (webBeanContext != null) {
try {
stopContexts(webBeanContext.getContextsService(), servletContext, session);
} catch (final Exception e) {
logger().warning("can't stop all CDI contexts", e);
}
}
logger().info("Destroying OpenEJB container");
OpenEJB.destroy();
instance = null;
}
@Override
public Context getContext() {
return globalJndiContext;
}
private void startNetworkServices() {
if (!options.get(OPENEJB_EMBEDDED_REMOTABLE, false)) {
return;
}
try {
serviceManager = new ServiceManagerProxy();
serviceManager.start();
} catch (final ServiceManagerProxy.AlreadyStartedException e) {
logger().debug("Network services already started. Ignoring option " + OPENEJB_EMBEDDED_REMOTABLE);
}
}
private static Logger logger() { // don't trigger init too eagerly to be sure to be configured
if (logger == null) {
logger = Logger.getInstance(LogCategory.OPENEJB_STARTUP, OpenEjbContainer.class);
}
return logger;
}
public static class Provider implements EJBContainerProvider {
public static final String OPENEJB_ADDITIONNAL_CALLERS_KEY = "openejb.additionnal.callers";
@Override
public EJBContainer createEJBContainer(Map, ?> map) {
if (map == null) { // JBoss EJB API pass null when calling EJBContainer.createEJBContainer()
map = new HashMap();
}
if (isOtherProvider(map)) {
return null;
}
if (instance != null || OpenEJB.isInitialized()) {
if (!isSingleClose()) {
logger().info("EJBContainer already initialized. Call ejbContainer.close() to allow reinitialization");
}
return instance;
}
try {
// reset to be able to run this container then tomee one etc...
if (JavaSecurityManagers.getSystemProperty(Context.URL_PKG_PREFIXES) != null) {
JavaSecurityManagers.removeSystemProperty(Context.URL_PKG_PREFIXES);
}
final Properties properties = new Properties();
properties.putAll(map);
SystemInstance.reset();
SystemInstance.init(properties);
SystemInstance.get().setProperty("openejb.embedded", "true");
SystemInstance.get().setProperty(EJBContainer.class.getName(), "true");
if (SystemInstance.get().getComponent(ParentClassLoaderFinder.class) == null) {
ClassLoader tccl = Thread.currentThread().getContextClassLoader();
if (tccl == null) {
tccl = OpenEjbContainer.class.getClassLoader();
}
SystemInstance.get().setComponent(ParentClassLoaderFinder.class, new ProvidedClassLoaderFinder(tccl));
}
OptionsLog.install();
OpenEJB.init(properties);
Core.warmup(); // don't do it too eagerly to avoid to not have properties
DeploymentLoader.reloadAltDD(); // otherwise hard to use multiple altdd with several start/stop in the same JVM
final ConfigurationFactory configurationFactory = new ConfigurationFactory();
final AppModule appModule = load(map, configurationFactory);
final Set callers;
if (map.containsKey(OPENEJB_ADDITIONNAL_CALLERS_KEY)) {
callers = new LinkedHashSet();
callers.addAll(Arrays.asList(((String) map.get(OPENEJB_ADDITIONNAL_CALLERS_KEY)).split(",")));
} else {
callers = NewLoaderLogic.callers();
}
final EjbJar ejbJar = new EjbJar();
final OpenejbJar openejbJar = new OpenejbJar();
for (final String caller : callers) {
if (!isValid(caller)) {
continue;
}
String name = caller;
if (name.contains("$")) {
name = caller.replace("$", "_");
}
final ManagedBean bean = ejbJar.addEnterpriseBean(new ManagedBean(name, caller, true));
bean.localBean();
// set it to bean so it can get UserTransaction injection
bean.setTransactionType(TransactionType.BEAN);
final EjbDeployment ejbDeployment = openejbJar.addEjbDeployment(bean);
// important in case any other deploment id formats are specified
ejbDeployment.setDeploymentId(name);
}
final EjbModule ejbModule = new EjbModule(ejbJar, openejbJar);
ejbModule.getProperties().setProperty("openejb.cdi.activated", "false"); // BeanManagerImpl will likely be empty
ejbModule.setBeans(new Beans()); // avoid warnings but not effectvely used
appModule.getEjbModules().add(ejbModule);
final AppInfo appInfo;
try {
appInfo = configurationFactory.configureApplication(appModule);
} catch (final ValidationFailedException e) {
logger().warning("configureApplication.loadFailed", appModule.getModuleId(), e.getMessage()); // DO not include the stacktrace in the message
throw new InvalidApplicationException(e);
} catch (final OpenEJBException e) {
// DO NOT REMOVE THE EXCEPTION FROM THIS LOG MESSAGE
// removing this message causes NO messages to be printed when embedded
logger().warning("configureApplication.loadFailed", e, appModule.getModuleId(), e.getMessage());
throw new ConfigureApplicationException(e);
}
final Assembler assembler = SystemInstance.get().getComponent(Assembler.class);
final AppContext appContext;
try {
appContext = assembler.createApplication(appInfo, appModule.getClassLoader());
} catch (final ValidationException ve) {
throw ve;
} catch (final Exception e) {
throw new AssembleApplicationException(e);
}
final OpenEjbContainer openEjbContainer = instance = new OpenEjbContainer(map, appContext);
if (isSingleClose()) {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
if (instance != null) {
instance.doClose();
}
}
});
}
return openEjbContainer;
} catch (final OpenEJBException | MalformedURLException e) {
throw new EJBException(e);
} catch (final ValidationException ve) {
throw ve;
} catch (final Exception e) {
if (e instanceof EJBException) {
throw (EJBException) e;
}
throw new InitializationException(e);
} finally {
if (instance == null && OpenEJB.isInitialized()) {
try {
OpenEJB.destroy();
} catch (final Exception e) {
// no-op
}
}
}
}
private boolean isValid(final String caller) {
try {
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
final Class> clazz = loader.loadClass(caller);
final int modifiers = clazz.getModifiers();
return !clazz.isEnum() && !clazz.isInterface() && !Modifier.isAbstract(modifiers);
} catch (final ClassNotFoundException e) {
return false;
}
}
private AppModule load(final Map, ?> map, final ConfigurationFactory configurationFactory) throws MalformedURLException, OpenEJBException {
final List moduleLocations;
final String appId = (String) map.get(EJBContainer.APP_NAME);
final Object modules = map.get(EJBContainer.MODULES);
// will be updated if needed
// ClassLoader classLoader = getClass().getClassLoader();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (modules instanceof String) {
moduleLocations = configurationFactory.getModulesFromClassPath(null, classLoader);
for (final Iterator i = moduleLocations.iterator(); i.hasNext(); ) {
final File file = i.next();
if (!match((String) modules, file)) {
i.remove();
}
}
} else if (modules instanceof String[]) {
// TODO Optimize this so we look specifically for modules by name
moduleLocations = configurationFactory.getModulesFromClassPath(null, classLoader);
int matched = 0;
for (final Iterator i = moduleLocations.iterator(); i.hasNext(); ) {
final File file = i.next();
boolean remove = true;
for (final String s : (String[]) modules) {
if (match(s, file)) {
remove = false;
matched++;
break;
}
}
if (remove) {
i.remove();
}
}
if (matched != ((String[]) modules).length) {
throw specifiedModulesNotFound();
}
} else if (modules instanceof File) {
final URL url = ((File) modules).toURI().toURL();
classLoader = new URLClassLoader(new URL[]{url}, classLoader);
moduleLocations = Collections.singletonList((File) modules);
} else if (modules instanceof File[]) {
final File[] files = (File[]) modules;
final URL[] urls = new URL[files.length];
for (int i = 0; i < urls.length; i++) {
urls[i] = files[i].toURI().toURL();
}
classLoader = new URLClassLoader(urls, classLoader);
moduleLocations = Arrays.asList((File[]) modules);
} else if (modules == null) {
moduleLocations = configurationFactory.getModulesFromClassPath(null, classLoader);
} else {
final AppModule appModule = load(map);
if (appModule != null) {
return appModule;
}
throw invalidModulesValue(modules);
}
if (moduleLocations.isEmpty()) {
throw Exceptions.newNoModulesFoundException();
}
// TODO With this load method we can finally do some checking on module ids to really implement EJBContainer.MODULES String/String[]
return configurationFactory.loadApplication(classLoader, appId, moduleLocations);
}
private AppModule load(final Map, ?> map) {
final String appId = (String) map.get(EJBContainer.APP_NAME);
final Object modules = map.get(EJBContainer.MODULES);
map.size();
final AppModule m;
{
Application application = null;
AppModule appModule = new AppModule(this.getClass().getClassLoader(), appId);
{
if (modules instanceof EjbJar) {
final EjbJar ejbJar = (EjbJar) modules;
appModule.getEjbModules().add(new EjbModule(ejbJar));
} else if (modules instanceof EnterpriseBean) {
final EnterpriseBean bean = (EnterpriseBean) modules;
final EjbJar ejbJar = new EjbJar();
ejbJar.addEnterpriseBean(bean);
appModule.getEjbModules().add(new EjbModule(ejbJar));
} else if (modules instanceof Application) {
application = (Application) modules;
} else if (modules instanceof Connector) {
final Connector connector = (Connector) modules;
appModule.getConnectorModules().add(new ConnectorModule(connector));
} else if (modules instanceof Persistence) {
final Persistence persistence = (Persistence) modules;
appModule.addPersistenceModule(new PersistenceModule(appModule, "", persistence));
} else if (modules instanceof PersistenceUnit) {
final PersistenceUnit unit = (PersistenceUnit) modules;
appModule.addPersistenceModule(new PersistenceModule(appModule, "", new Persistence(unit)));
} else if (modules instanceof Beans) {
final Beans beans = (Beans) modules;
final EjbModule ejbModule = new EjbModule(new EjbJar());
ejbModule.setBeans(beans);
appModule.getEjbModules().add(ejbModule);
}
}
// Application is final in AppModule, which is fine, so we'll create a new one and move everything
if (application != null) {
final AppModule newModule = new AppModule(appModule.getClassLoader(), appModule.getModuleId(), application, false);
newModule.getClientModules().addAll(appModule.getClientModules());
newModule.addPersistenceModules(appModule.getPersistenceModules());
newModule.getEjbModules().addAll(appModule.getEjbModules());
newModule.getConnectorModules().addAll(appModule.getConnectorModules());
appModule = newModule;
}
m = appModule;
}
return m;
}
// TODO, report some information
private EJBException specifiedModulesNotFound() {
return new NoSuchModuleException("some modules not matched on classpath");
}
private InvalidModulesPropertyException invalidModulesValue(final Object value) {
final String[] spec = {"java.lang.String", "java.lang.String[]", "java.io.File", "java.io.File[]"};
// TODO
// String[] vendor = {"java.lang.Class","java.lang.Class[]", "java.net.URL", "java.io.URL[]"};
final String type = value == null ? null : value.getClass().getName();
return new InvalidModulesPropertyException(String.format("Invalid '%s' value '%s'. Valid values are: %s", EJBContainer.MODULES, type, Join.join(", ", spec)));
}
private static boolean isOtherProvider(final Map, ?> properties) {
final Object provider = properties.get(EJBContainer.PROVIDER);
return provider != null && !provider.equals(OpenEjbContainer.class) && !provider.equals(OpenEjbContainer.class.getName())
&& !"openejb".equals(provider);
}
private boolean match(final String s, final File file) {
final String s2 = file.getName();
final String s3 = file.getAbsolutePath();
final boolean matches;
if (file.isDirectory()) {
matches = s2.equals(s) || s2.equals(s + ".jar") || s3.equals(s);
} else {
matches = s2.equals(s + ".jar");
}
// TODO if (!matches) { /* look for ejb-jar.xml with matching module name */ }
return matches;
}
}
private class GlobalContext extends ContextFlyweight {
private final Context globalJndiContext;
public GlobalContext(final Context globalJndiContext) {
this.globalJndiContext = globalJndiContext;
}
@Override
protected Context getContext() throws NamingException {
return globalJndiContext;
}
@Override
protected Name getName(Name name) throws NamingException {
String first = name.get(0);
if (!first.startsWith("java:")) {
throw new NameNotFoundException("Name must be in java: namespace");
}
first = first.substring("java:".length());
name = name.getSuffix(1);
return name.add(0, first);
}
@Override
protected String getName(final String name) throws NamingException {
if ("inject".equals(name)) {
return name;
}
if (!name.startsWith("java:")) {
throw new NameNotFoundException("Name must be in java: namespace");
}
return name.substring("java:".length());
}
@Override
public void bind(final Name name, final Object obj) throws NamingException {
if (name.size() == 1 && "inject".equals(name.get(0))) {
Injector.inject(obj);
} else {
super.bind(name, obj);
}
}
@Override
public void bind(final String name, final Object obj) throws NamingException {
if (name != null && "inject".equals(name)) {
Injector.inject(obj);
} else {
super.bind(name, obj);
}
}
@Override
public void unbind(final Name name) throws NamingException {
if (!(name.size() == 1 && "inject".equals(name.get(0)))) {
super.unbind(name);
}
}
@Override
public void unbind(final String name) throws NamingException {
if (!(name != null && "inject".equals(name))) {
super.unbind(name);
}
}
}
public static class InitializationException extends EJBException {
public InitializationException(final String s) {
super(s);
}
public InitializationException(final Exception cause) {
super(cause);
}
}
@SuppressWarnings("UnusedDeclaration")
public static class InvalidModulesPropertyException extends InitializationException {
public InvalidModulesPropertyException(final String s) {
super(s);
}
}
public static class NoSuchModuleException extends InitializationException {
public NoSuchModuleException(final String s) {
super(s);
}
}
public static class NoModulesFoundException extends InitializationException {
public NoModulesFoundException(final String s) {
super(s);
}
}
public static class ConfigureApplicationException extends InitializationException {
public ConfigureApplicationException(final Exception cause) {
super(cause);
}
}
public static class AssembleApplicationException extends InitializationException {
public AssembleApplicationException(final Exception cause) {
super(cause);
}
}
public static class InvalidApplicationException extends InitializationException {
public InvalidApplicationException(final Exception cause) {
super(cause);
}
}
}