org.eclipse.ecr.testlib.runner.RuntimeFeature.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.ecr.testlib.runner.RuntimeFeature.java

Source

/*
 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     bstefanescu
 */
package org.eclipse.ecr.testlib.runner;

import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Name;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.ecr.runtime.api.DataSourceHelper;
import org.eclipse.ecr.runtime.api.Framework;
import org.eclipse.ecr.testlib.NXRuntimeTestCase;

import com.google.inject.Binder;
import com.google.inject.Provider;
import com.google.inject.Scopes;

/**
 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
 *
 */
public class RuntimeFeature extends SimpleFeature {

    private static final Log log = LogFactory.getLog(RuntimeFeature.class);

    protected RuntimeHarness harness;

    protected final DeploymentSet deploy;

    /**
     * Providers contributed by other features to override the default service provider
     * used for a nuxeo service.
     */
    protected final Map<Class<?>, Provider<?>> serviceProviders;

    public RuntimeFeature() {
        harness = new NXRuntimeTestCase();
        deploy = new DeploymentSet();
        serviceProviders = new HashMap<Class<?>, Provider<?>>();
    }

    public <T> void addServiceProvider(Class<T> clazz, Provider<T> provider) {
        serviceProviders.put(clazz, provider);
    }

    public RuntimeHarness getHarness() {
        return harness;
    }

    public DeploymentSet deployments() {
        return deploy;
    }

    private void scanDeployments(FeaturesRunner runner) {
        List<RunnerFeature> features = runner.getFeatures();
        if (features == null) {
            throw new IllegalStateException("Cannot call scanDeployments until features are not loaded");
        }
        for (RunnerFeature feature : features) {
            deploy.load(FeaturesRunner.getScanner(), feature.getClass());
        }
        // load deployments from class to run
        deploy.load(FeaturesRunner.getScanner(), runner.getTestClass().getJavaClass());
    }

    public String[] getDeployments() {
        return deploy.getDeployments().toArray(new String[deploy.getDeployments().size()]);
    }

    public String[] getLocalDeployments() {
        return deploy.getLocalDeployments().toArray(new String[deploy.getLocalDeployments().size()]);
    }

    /**
     * Deploys bundles specified in the @Bundles annotation.
     */
    protected void deployTestClassBundles() throws Exception {
        String[] bundles = getDeployments();
        if (bundles.length > 0) {
            harness = getHarness();
            for (String bundle : bundles) {
                try {
                    int p = bundle.indexOf(':');
                    if (p == -1) {
                        harness.deployBundle(bundle);
                    } else {
                        harness.deployContrib(bundle.substring(0, p), bundle.substring(p + 1));
                    }
                } catch (Exception e) {
                    log.error("Unable to deploy artifact: " + bundle, e);
                }
            }
        }
        String[] localResources = getLocalDeployments();
        if (localResources.length > 0) {
            harness = getHarness();
            for (String bundle : localResources) {
                try {
                    int p = bundle.indexOf(':');
                    if (p == -1) {
                        throw new IllegalArgumentException(
                                "Local resources must specify a traget bundle. " + bundle);
                    } else {
                        URL url = getClass().getClassLoader().getResource(bundle.substring(p + 1));
                        harness.deployTestContrib(bundle.substring(0, p), url);
                    }
                } catch (Exception e) {
                    log.error("Unable to deploy artifact: " + bundle, e);
                }
            }
        }
        harness.fireFrameworkStarted();
    }

    @Override
    public void initialize(FeaturesRunner runner) throws Exception {
        scanDeployments(runner);
    }

    @Override
    public void start(FeaturesRunner runner) throws Exception {
        // Starts Nuxeo Runtime
        if (!harness.isStarted()) {
            harness.start();
        }
        // Deploy bundles
        deployTestClassBundles();
    }

    @Override
    public void stop(FeaturesRunner runner) throws Exception {
        // Stops the harness if needed
        if (harness.isStarted()) {
            harness.stop();
            //harness = null;
        }
    }

    //TODO this is not ok. we should not force 2 modules layers - we should be able to load any number of module layers.
    @SuppressWarnings("unchecked")
    @Override
    public void configure(FeaturesRunner runner, Binder binder) {
        for (String svc : Framework.getRuntime().getComponentManager().getServices()) {
            try {
                Class clazz = Class.forName(svc);
                Provider provider = serviceProviders.get(clazz);
                if (provider == null) {
                    bind0(binder, clazz);
                } else {
                    bind0(binder, clazz, provider);
                }
            } catch (Exception e) {
                throw new RuntimeException("Failed to bind service: " + svc, e);
            }
        }
        binder.bind(RuntimeHarness.class).toInstance(getHarness());
        //        binder.bind(FeaturesRunner.class).toInstance(runner);
        //        binder.bind(NuxeoRunner.class).toInstance(runner);
    }

    protected <T> void bind0(Binder binder, Class<T> type) {
        binder.bind(type).toProvider(new ServiceProvider<T>(type)).in(Scopes.SINGLETON);
    }

    protected <T> void bind0(Binder binder, Class<T> type, Provider<T> provider) {
        binder.bind(type).toProvider(provider).in(Scopes.SINGLETON);
    }

    public static void bindDatasource(String key, DataSource ds) throws Exception {
        InitialContext initialCtx = new InitialContext();
        String dsName = DataSourceHelper.getDataSourceJNDIName(key);
        rebind(initialCtx, dsName, ds);
    }

    public static void rebind(Context ctx, String key, Object value) throws NamingException {
        Name name = ctx.getNameParser("").parse(key);
        int depth = name.size() - 1;
        for (int i = 0; i < depth; i++) {
            String segment = name.get(i);
            try {
                ctx = (Context) ctx.lookup(segment);
            } catch (NameNotFoundException e) {
                ctx = ctx.createSubcontext(segment);
            }
        }
        ctx.rebind(name.get(depth), value);
    }

}