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.api.LocalClient;
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.Operation;
import org.apache.openejb.core.ParentClassLoaderFinder;
import org.apache.openejb.core.ProvidedClassLoaderFinder;
import org.apache.openejb.core.ThreadContext;
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.spi.ContainerSystem;
import org.apache.openejb.util.Exceptions;
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.inject.OWBInjector;
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 class OpenEjbContainer extends EJBContainer {
static {
// if tomee embedded was ran we'll lost log otherwise
final String logManger = System.getProperty("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";
private static OpenEjbContainer instance;
private static Logger logger = null; // initialized lazily to get the logging config from properties
private ServiceManagerProxy serviceManager;
private Options options;
private OpenEjbContainer.GlobalContext globalJndiContext;
private WebBeansContext webBeanContext;
private ServletContext servletContext;
private HttpSession session;
private OpenEjbContainer(Map, ?> map, AppContext appContext) {
webBeanContext = appContext.getWebBeansContext();
globalJndiContext = new GlobalContext(appContext.getGlobalJndiContext());
final Properties properties = new Properties();
properties.putAll(map);
options = new Options(properties);
startNetworkServices();
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 (serviceManager != null) {
serviceManager.stop();
}
try {
globalJndiContext.close();
} catch (NamingException e) {
throw new IllegalStateException(e);
}
final Assembler assembler = SystemInstance.get().getComponent(Assembler.class);
if (assembler != null) {
for (AppInfo info : assembler.getDeployedApplications()) {
try {
assembler.destroyApplication(info);
} catch (UndeployException e) {
logger().error(e.getMessage(), e);
}
}
}
try {
stopContexts(webBeanContext.getContextsService(), servletContext, session);
} catch (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;
}
public T inject(T object) {
assert object != null;
final Class> clazz = object.getClass();
final BeanContext context = resolve(clazz);
if (context != null) { // found the test class directly
final InjectionProcessor processor = new InjectionProcessor(object, context.getInjections(), context.getJndiContext());
cdiInjections(context, object);
try {
return (T) processor.createInstance();
} catch (OpenEJBException e) {
throw new InjectionException(clazz.getName(), e);
}
} else if (!isAnnotatedLocalClient(clazz)) { // nothing to do
throw new NoInjectionMetaDataException(clazz.getName());
}
// the test class was not found in beans (OpenEJB ran from parent) but was annotated @LocalClient
try {
final InjectionProcessor> processor = ClientInjections.clientInjector(object);
cdiInjections(null, object);
return (T) processor.createInstance();
} catch (OpenEJBException e) {
throw new NoInjectionMetaDataException("Injection failed", e);
}
}
private void cdiInjections(final BeanContext context, final T object) {
ThreadContext oldContext = null;
if (context != null) {
final ThreadContext callContext = new ThreadContext(context, null, Operation.INJECTION);
oldContext = ThreadContext.enter(callContext);
}
try {
OWBInjector.inject(webBeanContext.getBeanManagerImpl(), object, null);
} catch (Throwable t) {
logger().warning("an error occured while injecting the class '" + object.getClass().getName() + "': " + t.getMessage());
} finally {
if (context != null) {
ThreadContext.exit(oldContext);
}
}
}
private boolean isAnnotatedLocalClient(final Class> clazz) {
Class> current = clazz;
while (current != null && current != Object.class) {
if (current.getAnnotation(LocalClient.class) != null) {
return true;
}
current = current.getSuperclass();
}
return false;
}
private BeanContext resolve(Class> clazz) {
final ContainerSystem containerSystem = SystemInstance.get().getComponent(ContainerSystem.class);
while (clazz != null && clazz != Object.class) {
{
final BeanContext context = containerSystem.getBeanContext(clazz.getName());
if (context != null) return context;
}
for (BeanContext context : containerSystem.deployments()) {
if (clazz == context.getBeanClass()) return context;
}
clazz = clazz.getSuperclass();
}
return null;
}
private void startNetworkServices() {
if (!options.get(OPENEJB_EMBEDDED_REMOTABLE, false)) {
return;
}
try {
serviceManager = new ServiceManagerProxy();
serviceManager.start();
} catch (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 NoInjectionMetaDataException extends IllegalStateException {
public NoInjectionMetaDataException(final String s) {
this(s, null);
}
public NoInjectionMetaDataException(final String s, final Exception e) {
super(String.format("%s : Annotate the class with @%s so it can be discovered in the application scanning process", s, javax.annotation.ManagedBean.class.getName()), e);
}
}
public static class InjectionException extends IllegalStateException {
public InjectionException(String message, Throwable cause) {
super(message, cause);
}
}
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
© 2015 - 2024 Weber Informatics LLC | Privacy Policy