Search in sources :

Example 1 with RandomPort

use of org.apache.openejb.testing.RandomPort in project tomee by apache.

the class TomEEEmbeddedApplicationRunner method start.

public synchronized void start(final Class<?> marker, final Properties config, final String... args) throws Exception {
    if (started) {
        return;
    }
    ensureAppInit(marker);
    started = true;
    final Class<?> appClass = app.getClass();
    final AnnotationFinder finder = new AnnotationFinder(new ClassesArchive(ancestors(appClass)));
    // setup the container config reading class annotation, using a randome http port and deploying the classpath
    final Configuration configuration = new Configuration();
    final ContainerProperties props = appClass.getAnnotation(ContainerProperties.class);
    if (props != null) {
        final Properties runnerProperties = new Properties();
        for (final ContainerProperties.Property p : props.value()) {
            final String name = p.name();
            if (name.startsWith("tomee.embedded.application.runner.")) {
                // allow to tune the Configuration
                // no need to filter there since it is done in loadFromProperties()
                runnerProperties.setProperty(name.substring("tomee.embedded.application.runner.".length()), p.value());
            } else {
                configuration.property(name, StrSubstitutor.replaceSystemProperties(p.value()));
            }
        }
        if (!runnerProperties.isEmpty()) {
            configuration.loadFromProperties(runnerProperties);
        }
    }
    // overrides, note that some config are additive by design
    configuration.loadFromProperties(System.getProperties());
    final List<Method> annotatedMethods = finder.findAnnotatedMethods(org.apache.openejb.testing.Configuration.class);
    if (annotatedMethods.size() > 1) {
        throw new IllegalArgumentException("Only one @Configuration is supported: " + annotatedMethods);
    }
    for (final Method m : annotatedMethods) {
        final Object o = m.invoke(app);
        if (Properties.class.isInstance(o)) {
            final Properties properties = Properties.class.cast(o);
            if (configuration.getProperties() == null) {
                configuration.setProperties(new Properties());
            }
            configuration.getProperties().putAll(properties);
        } else {
            throw new IllegalArgumentException("Unsupported " + o + " for @Configuration");
        }
    }
    final Collection<org.apache.tomee.embedded.LifecycleTask> lifecycleTasks = new ArrayList<>();
    final Collection<Closeable> postTasks = new ArrayList<>();
    final LifecycleTasks tasks = appClass.getAnnotation(LifecycleTasks.class);
    if (tasks != null) {
        for (final Class<? extends org.apache.tomee.embedded.LifecycleTask> type : tasks.value()) {
            final org.apache.tomee.embedded.LifecycleTask lifecycleTask = type.newInstance();
            lifecycleTasks.add(lifecycleTask);
            postTasks.add(lifecycleTask.beforeContainerStartup());
        }
    }
    final Map<String, Field> ports = new HashMap<>();
    {
        Class<?> type = appClass;
        while (type != null && type != Object.class) {
            for (final Field f : type.getDeclaredFields()) {
                final RandomPort annotation = f.getAnnotation(RandomPort.class);
                final String value = annotation == null ? null : annotation.value();
                if (value != null && value.startsWith("http")) {
                    f.setAccessible(true);
                    ports.put(value, f);
                }
            }
            type = type.getSuperclass();
        }
    }
    if (ports.containsKey("http")) {
        configuration.randomHttpPort();
    }
    // at least after LifecycleTasks to inherit from potential states (system properties to get a port etc...)
    final Configurers configurers = appClass.getAnnotation(Configurers.class);
    if (configurers != null) {
        for (final Class<? extends Configurer> type : configurers.value()) {
            type.newInstance().configure(configuration);
        }
    }
    final Classes classes = appClass.getAnnotation(Classes.class);
    String context = classes != null ? classes.context() : "";
    context = !context.isEmpty() && context.startsWith("/") ? context.substring(1) : context;
    Archive archive = null;
    if (classes != null && classes.value().length > 0) {
        archive = new ClassesArchive(classes.value());
    }
    final Jars jars = appClass.getAnnotation(Jars.class);
    final List<URL> urls;
    if (jars != null) {
        final Collection<File> files = ApplicationComposers.findFiles(jars);
        urls = new ArrayList<>(files.size());
        for (final File f : files) {
            urls.add(f.toURI().toURL());
        }
    } else {
        urls = null;
    }
    final WebResource resources = appClass.getAnnotation(WebResource.class);
    if (resources != null && resources.value().length > 1) {
        throw new IllegalArgumentException("Only one docBase is supported for now using @WebResource");
    }
    String webResource = null;
    if (resources != null && resources.value().length > 0) {
        webResource = resources.value()[0];
    } else {
        final File webapp = new File("src/main/webapp");
        if (webapp.isDirectory()) {
            webResource = "src/main/webapp";
        }
    }
    if (config != null) {
        // override other config from annotations
        configuration.loadFromProperties(config);
    }
    final Container container = new Container(configuration);
    SystemInstance.get().setComponent(TomEEEmbeddedArgs.class, new TomEEEmbeddedArgs(args, null));
    SystemInstance.get().setComponent(LifecycleTaskAccessor.class, new LifecycleTaskAccessor(lifecycleTasks));
    container.deploy(new Container.DeploymentRequest(context, // call ClasspathSearcher that lazily since container needs to be started to not preload logging
    urls == null ? new DeploymentsResolver.ClasspathSearcher().loadUrls(Thread.currentThread().getContextClassLoader()).getUrls() : urls, webResource != null ? new File(webResource) : null, true, null, archive));
    for (final Map.Entry<String, Field> f : ports.entrySet()) {
        switch(f.getKey()) {
            case "http":
                setPortField(f.getKey(), f.getValue(), configuration, context, app);
                break;
            case "https":
                break;
            default:
                throw new IllegalArgumentException("port " + f.getKey() + " not yet supported");
        }
    }
    SystemInstance.get().addObserver(app);
    composerInject(app);
    final AnnotationFinder appFinder = new AnnotationFinder(new ClassesArchive(appClass));
    for (final Method mtd : appFinder.findAnnotatedMethods(PostConstruct.class)) {
        if (mtd.getParameterTypes().length == 0) {
            if (!mtd.isAccessible()) {
                mtd.setAccessible(true);
            }
            mtd.invoke(app);
        }
    }
    hook = new Thread() {

        @Override
        public void run() {
            // ensure to log errors but not fail there
            for (final Method mtd : appFinder.findAnnotatedMethods(PreDestroy.class)) {
                if (mtd.getParameterTypes().length == 0) {
                    if (!mtd.isAccessible()) {
                        mtd.setAccessible(true);
                    }
                    try {
                        mtd.invoke(app);
                    } catch (final IllegalAccessException e) {
                        throw new IllegalStateException(e);
                    } catch (final InvocationTargetException e) {
                        throw new IllegalStateException(e.getCause());
                    }
                }
            }
            try {
                container.close();
            } catch (final Exception e) {
                e.printStackTrace();
            }
            for (final Closeable c : postTasks) {
                try {
                    c.close();
                } catch (final IOException e) {
                    e.printStackTrace();
                }
            }
            postTasks.clear();
            app = null;
            try {
                SHUTDOWN_TASKS.remove(this);
            } catch (final Exception e) {
            // no-op: that's ok at that moment if not called manually
            }
        }
    };
    SHUTDOWN_TASKS.put(hook, hook);
}
Also used : FileArchive(org.apache.xbean.finder.archive.FileArchive) ClassesArchive(org.apache.xbean.finder.archive.ClassesArchive) Archive(org.apache.xbean.finder.archive.Archive) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Closeable(java.io.Closeable) ArrayList(java.util.ArrayList) WebResource(org.apache.openejb.testing.WebResource) ContainerProperties(org.apache.openejb.testing.ContainerProperties) DeploymentsResolver(org.apache.openejb.config.DeploymentsResolver) Classes(org.apache.openejb.testing.Classes) Method(java.lang.reflect.Method) InvocationTargetException(java.lang.reflect.InvocationTargetException) RandomPort(org.apache.openejb.testing.RandomPort) PreDestroy(javax.annotation.PreDestroy) File(java.io.File) HashMap(java.util.HashMap) ConcurrentMap(java.util.concurrent.ConcurrentMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) AnnotationFinder(org.apache.xbean.finder.AnnotationFinder) TomEEEmbeddedArgs(org.apache.tomee.embedded.component.TomEEEmbeddedArgs) ContainerProperties(org.apache.openejb.testing.ContainerProperties) Properties(java.util.Properties) URL(java.net.URL) Field(java.lang.reflect.Field) IOException(java.io.IOException) IOException(java.io.IOException) InvocationTargetException(java.lang.reflect.InvocationTargetException) ClassesArchive(org.apache.xbean.finder.archive.ClassesArchive) Jars(org.apache.openejb.testing.Jars)

Example 2 with RandomPort

use of org.apache.openejb.testing.RandomPort in project tomee by apache.

the class TomEEEmbeddedApplicationRunner method composerInject.

public void composerInject(final Object target) throws IllegalAccessException {
    WebBeansContext webBeansContext = null;
    try {
        webBeansContext = WebBeansContext.currentInstance();
    } catch (final IllegalStateException ise) {
    // no-op
    }
    if (webBeansContext != null) {
        OWBInjector.inject(webBeansContext.getBeanManagerImpl(), target, null);
    }
    Class<?> aClass = target.getClass();
    while (aClass != null && aClass != Object.class) {
        for (final Field f : aClass.getDeclaredFields()) {
            final RandomPort randomPort = f.getAnnotation(RandomPort.class);
            if (randomPort != null) {
                for (final Field field : app.getClass().getDeclaredFields()) {
                    final RandomPort appPort = field.getAnnotation(RandomPort.class);
                    if (field.getType() == f.getType() && appPort != null && appPort.value().equals(randomPort.value())) {
                        if (!field.isAccessible()) {
                            field.setAccessible(true);
                        }
                        if (!f.isAccessible()) {
                            f.setAccessible(true);
                        }
                        final Object value = field.get(app);
                        f.set(target, value);
                        break;
                    }
                }
            } else if (f.isAnnotationPresent(Application.class)) {
                if (!f.isAccessible()) {
                    f.setAccessible(true);
                }
                f.set(target, app);
            } else if (f.isAnnotationPresent(LifecycleTask.class)) {
                if (!f.isAccessible()) {
                    f.setAccessible(true);
                }
                final LifecycleTaskAccessor accessor = SystemInstance.get().getComponent(LifecycleTaskAccessor.class);
                final Class type = f.getType();
                final Object taskByType = accessor.getTaskByType(type);
                f.set(target, taskByType);
            } else if (f.isAnnotationPresent(Args.class)) {
                if (String[].class != f.getType()) {
                    throw new IllegalArgumentException("@Args can only be used for String[] field, not on " + f.getType());
                }
                if (!f.isAccessible()) {
                    f.setAccessible(true);
                }
                final TomEEEmbeddedArgs args = SystemInstance.get().getComponent(TomEEEmbeddedArgs.class);
                f.set(target, args == null ? new String[0] : args.getArgs());
            }
        }
        aClass = aClass.getSuperclass();
    }
    SystemInstance.get().fireEvent(new TomEEEmbeddedApplicationRunnerInjection(target));
}
Also used : TomEEEmbeddedArgs(org.apache.tomee.embedded.component.TomEEEmbeddedArgs) TomEEEmbeddedArgs(org.apache.tomee.embedded.component.TomEEEmbeddedArgs) RandomPort(org.apache.openejb.testing.RandomPort) Field(java.lang.reflect.Field) TomEEEmbeddedApplicationRunnerInjection(org.apache.tomee.embedded.event.TomEEEmbeddedApplicationRunnerInjection) WebBeansContext(org.apache.webbeans.config.WebBeansContext) Application(org.apache.openejb.testing.Application)

Aggregations

Field (java.lang.reflect.Field)2 RandomPort (org.apache.openejb.testing.RandomPort)2 TomEEEmbeddedArgs (org.apache.tomee.embedded.component.TomEEEmbeddedArgs)2 Closeable (java.io.Closeable)1 File (java.io.File)1 IOException (java.io.IOException)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Method (java.lang.reflect.Method)1 URL (java.net.URL)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 Properties (java.util.Properties)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 ConcurrentMap (java.util.concurrent.ConcurrentMap)1 PreDestroy (javax.annotation.PreDestroy)1 DeploymentsResolver (org.apache.openejb.config.DeploymentsResolver)1 Application (org.apache.openejb.testing.Application)1 Classes (org.apache.openejb.testing.Classes)1 ContainerProperties (org.apache.openejb.testing.ContainerProperties)1