Package org.apache.openejb.junit

Source Code of org.apache.openejb.junit.ApplicationComposer$DeployApplication

/**
* 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.junit;

import org.apache.openejb.DeploymentInfo;
import org.apache.openejb.InjectionProcessor;
import org.apache.openejb.OpenEJBException;
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.EjbModule;
import org.apache.openejb.config.PersistenceModule;
import org.apache.openejb.core.CoreDeploymentInfo;
import org.apache.openejb.core.Operation;
import org.apache.openejb.core.ThreadContext;
import org.apache.openejb.core.ivm.naming.InitContextFactory;
import org.apache.openejb.jee.Application;
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.SystemInstance;
import org.apache.openejb.spi.ContainerSystem;
import org.apache.openejb.util.Join;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import org.apache.openejb.util.OptionsLog;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
import org.junit.runners.model.TestClass;

import javax.naming.Context;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
* @version $Rev$ $Date$
*/
public class ApplicationComposer extends BlockJUnit4ClassRunner {

    private final TestClass testClass;

    public ApplicationComposer(Class<?> klass) throws InitializationError {
        super(klass);
        testClass = new TestClass(klass);
        validate();
    }

    private void validate() throws InitializationError {
        List<Throwable> errors = new ArrayList<Throwable>();

        final List<FrameworkMethod> configs = testClass.getAnnotatedMethods(Configuration.class);
        if (configs.size() > 1) {
            final String gripe = "Test class should have no more than one @Configuration method";
            errors.add(new Exception(gripe));
        }

        for (FrameworkMethod method : configs) {
            final Class<?> type = method.getMethod().getReturnType();
            if (!Properties.class.isAssignableFrom(type)) {
                final String gripe = "@Configuration method must return " + Properties.class.getName();
                errors.add(new Exception(gripe));
            }
        }

        int appModules = 0;
        int modules = 0;
        Class[] moduleTypes = {EjbJar.class, EnterpriseBean.class, Persistence.class, PersistenceUnit.class, Connector.class};
        for (FrameworkMethod method : testClass.getAnnotatedMethods(Module.class)) {

            modules++;

            final Class<?> type = method.getMethod().getReturnType();

            if (Application.class.isAssignableFrom(type)) {

                appModules++;

            } else if (!isValidModuleType(type, moduleTypes)) {
                final String gripe = "@Module method must return " + Join.join(" or ", moduleTypes).replaceAll("(class|interface) ", "");
                errors.add(new Exception(gripe));
            }
        }

        if (appModules > 1) {
            final String gripe = "Test class should have no more than one @Module method that returns " + Application.class.getName();
            errors.add(new Exception(gripe));
        }

        if (modules < 1) {
            final String gripe = "Test class should have at least one @Module method";
            errors.add(new Exception(gripe));
        }

        if (!errors.isEmpty()) {
            throw new InitializationError(errors);
        }
    }

    private boolean isValidModuleType(Class<?> type, Class[] moduleTypes) {
        for (Class moduleType : moduleTypes) {
            if (moduleType.isAssignableFrom(type)) return true;
        }
        return false;
    }

    @Override
    protected Statement withAfters(FrameworkMethod method, Object target, Statement statement) {
        statement = super.withAfters(method, target, statement);
        statement = new DeployApplication(target, statement);
        return statement;
    }

    public class DeployApplication extends Statement {

        // The TestCase instance
        private final Object testInstance;

        private final Statement next;

        public DeployApplication(Object testInstance, Statement next) {
            this.testInstance = testInstance;
            this.next = next;
        }

        @Override
        public void evaluate() throws Throwable {
            final Class<?> javaClass = testClass.getJavaClass();
            final ClassLoader loader = javaClass.getClassLoader();
            AppModule appModule = new AppModule(loader, javaClass.getSimpleName());

            // Add the test case as an @ManagedBean
            {
                final EjbJar ejbJar = new EjbJar();
                final OpenejbJar openejbJar = new OpenejbJar();
                final ManagedBean bean = ejbJar.addEnterpriseBean(new ManagedBean(javaClass));
                bean.setTransactionType(TransactionType.BEAN);

                final EjbDeployment ejbDeployment = openejbJar.addEjbDeployment(bean);
                ejbDeployment.setDeploymentId(javaClass.getName());

                appModule.getEjbModules().add(new EjbModule(ejbJar, openejbJar));
            }

            Application application = null;

            // Invoke the @Module producer methods to build out the AppModule
            for (FrameworkMethod method : testClass.getAnnotatedMethods(Module.class)) {

                final Object obj = method.invokeExplosively(testInstance);

                if (obj instanceof EjbJar) {

                    final EjbJar ejbJar = (EjbJar) obj;
                    appModule.getEjbModules().add(new EjbModule(ejbJar));

                } else if (obj instanceof EnterpriseBean) {

                    final EnterpriseBean bean = (EnterpriseBean) obj;
                    final EjbJar ejbJar = new EjbJar();
                    ejbJar.addEnterpriseBean(bean);
                    appModule.getEjbModules().add(new EjbModule(ejbJar));

                } else if (obj instanceof Connector) {

                    final Connector connector = (Connector) obj;
                    appModule.getResourceModules().add(new ConnectorModule(connector));

                } else if (obj instanceof Persistence) {

                    final Persistence persistence = (Persistence) obj;
                    appModule.getPersistenceModules().add(new PersistenceModule("", persistence));

                } else if (obj instanceof PersistenceUnit) {

                    final PersistenceUnit unit = (PersistenceUnit) obj;
                    appModule.getPersistenceModules().add(new PersistenceModule("", new Persistence(unit)));

                }
            }

            // For the moment we just take the first @Configuration method
            // maybe later we can add something fancy to allow multiple configurations using a qualifier
            // as a sort of altDD/altConfig concept.  Say for example the altDD prefix might be "foo",
            // we can then imagine something like this:
            // @Foo @Configuration public Properties alternateConfig(){...}
            // @Foo @Module  public Properties alternateModule(){...}
            // anyway, one thing at a time ....

            final Properties configuration = new Properties();
            configuration.put("openejb.deployments.classpath", "false");

            final List<FrameworkMethod> methods = testClass.getAnnotatedMethods(Configuration.class);
            for (FrameworkMethod method : methods) {
                final Object o = method.invokeExplosively(testInstance);
                if (o instanceof Properties) {
                    Properties properties = (Properties) o;
                    configuration.putAll(properties);
                }
                break;
            }

            if (SystemInstance.isInitialized()) SystemInstance.reset();

            SystemInstance.init(configuration);
            SystemInstance.get().setProperty("openejb.embedded", "true");
            Logger.configure();
            OptionsLog.install();
            try {
                ConfigurationFactory config = new ConfigurationFactory();
                config.init(SystemInstance.get().getProperties());

                Assembler assembler = new Assembler();
                assembler.buildContainerSystem(config.getOpenEjbConfiguration());

                final AppInfo appInfo = config.configureApplication(appModule);

                assembler.createApplication(appInfo);

                try {
                    final ContainerSystem containerSystem = SystemInstance.get().getComponent(ContainerSystem.class);
                    final CoreDeploymentInfo context = (CoreDeploymentInfo) containerSystem.getDeploymentInfo(javaClass.getName());

                    Context jndi = (Context) context.getJndiEnc().lookup("comp/env");
                   
                    InjectionProcessor processor = new InjectionProcessor(testInstance, context.getInjections(), jndi);

                    processor.createInstance();

                    System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, InitContextFactory.class.getName());

                    final ThreadContext previous = ThreadContext.enter(new ThreadContext(context, null, Operation.BUSINESS));
                    try {
                        next.evaluate();
                    } finally {
                        ThreadContext.exit(previous);
                    }

                } finally {
//                    assembler.destroyApplication(appInfo.jarPath);
                }
            } finally {
                SystemInstance.reset();
            }
        }
    }
}
TOP

Related Classes of org.apache.openejb.junit.ApplicationComposer$DeployApplication

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.