Package org.ops4j.pax.exam.glassfish.embedded

Source Code of org.ops4j.pax.exam.glassfish.embedded.EmbeddedGlassFishTestContainer

/*
* Copyright 2012 Harald Wellmann
*
* Licensed 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.ops4j.pax.exam.glassfish.embedded;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Stack;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.glassfish.embeddable.Deployer;
import org.glassfish.embeddable.GlassFish;
import org.glassfish.embeddable.GlassFishException;
import org.glassfish.embeddable.GlassFishProperties;
import org.glassfish.embeddable.GlassFishRuntime;
import org.ops4j.io.StreamUtils;
import org.ops4j.pax.exam.ConfigurationManager;
import org.ops4j.pax.exam.ExamSystem;
import org.ops4j.pax.exam.ProbeInvoker;
import org.ops4j.pax.exam.ProbeInvokerFactory;
import org.ops4j.pax.exam.TestAddress;
import org.ops4j.pax.exam.TestContainer;
import org.ops4j.pax.exam.TestContainerException;
import org.ops4j.pax.exam.TestDirectory;
import org.ops4j.pax.exam.TestInstantiationInstruction;
import org.ops4j.pax.exam.options.UrlDeploymentOption;
import org.ops4j.pax.exam.options.WarProbeOption;
import org.ops4j.spi.ServiceProviderFinder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

/**
* A {@link TestContainer} for the GlassFish 3.1 Java EE 6 application server.
* <p>
* This container uses Embedded GlassFish and only Java EE mode, but not OSGi mode. You deploy WAR
* modules via Pax Exam options (but no OSGi bundles).
* <p>
* The test probe is a WAR built on the fly from the classpath contents with some default
* exclusions.
* <p>
* GlassFish logging is redirected from java.util.logging to SLF4J. The necessary artifacts are
* provisioned by this container automatically.
*
* @author Harald Wellmann
* @since 3.0.0
*/
public class EmbeddedGlassFishTestContainer implements TestContainer {

    /**
     * Configuration property key for GlassFish installation configuration file directory. The files
     * contained in this directory will be copied to the config directory of the GlassFish instance.
     */
    public static final String GLASSFISH_CONFIG_DIR_KEY = "pax.exam.glassfish.config.dir";

    private static final Logger LOG = LoggerFactory.getLogger(EmbeddedGlassFishTestContainer.class);

    /**
     * Name of the probe web application (in Java EE mode).
     */
    private static final String PROBE_APPLICATION_NAME = "Pax-Exam-Probe";

    /**
     * XPath to read the HTTP port from the domain.xml configuration file.
     */
    private static final String HTTP_PORT_XPATH = "/domain/configs/config/network-config/network-listeners/network-listener[@name='http-listener-1']/@port";

    /**
     * Stack of deployed modules. On shutdown, the modules are undeployed in reverse order.
     */
    private Stack<String> deployed = new Stack<String>();
   
    private String warProbe;

    /**
     * Pax Exam system with configuration options.
     */
    private ExamSystem system;

    /**
     * GlassFish OSGi service.
     */
    private GlassFish glassFish;

    /**
     * Test directory which tracks all tests in the current suite. We need to register the context
     * URL of the probe web app as access point.
     */
    private TestDirectory testDirectory;

    private String configDirName;

    /**
     * Creates a GlassFish container, running on top of an OSGi framework.
     *
     * @param system
     *            Pax Exam system configuration
     */
    public EmbeddedGlassFishTestContainer(ExamSystem system) {
        this.system = system;
        this.testDirectory = TestDirectory.getInstance();
    }

    /**
     * Calls a test with the given address. In Java EE mode, we lookup the test from the test
     * directory and invoke it via probe invoker obtained from the Java SE service loader. (This
     * invoker uses a servlet bridge,)
     */
    public synchronized void call(TestAddress address) {
        TestInstantiationInstruction instruction = testDirectory.lookup(address);
        ProbeInvokerFactory probeInvokerFactory = ServiceProviderFinder
            .loadUniqueServiceProvider(ProbeInvokerFactory.class);
        ProbeInvoker invoker = probeInvokerFactory.createProbeInvoker(null, instruction.toString());
        invoker.call(address.arguments());
    }

    /**
     * Installs a probe in the test container.
     * <p>
     * In Java EE mode, the probe is a WAR, enriched by the Pax Exam servlet bridge which allows us
     * to invoke tests running within the container via an HTTP client.
     *
     * @param location
     *            bundle location, not used for WAR probes
     * @param stream
     *            input stream containing probe
     * @return bundle ID, or -1 for WAR
     */
    public synchronized long install(String location, InputStream stream) {
        try {
            // just make sure we don't get an "option not recognized" warning
            system.getOptions(WarProbeOption.class);

            LOG.info("deploying probe");
            Deployer deployer = glassFish.getDeployer();

            /*
             * FIXME The following should work, but does not. For some reason, we cannot directly
             * deploy from a stream. As a workaround, we copy the stream to a temp file and deploy
             * the file.
             *
             * deployer.deploy( stream, "--name", "Pax-Exam-Probe", "--contextroot",
             * "Pax-Exam-Probe" );
             */

            File tempFile = File.createTempFile("pax-exam", ".war");
            tempFile.deleteOnExit();
            StreamUtils.copyStream(stream, new FileOutputStream(tempFile), true);
            deployer.deploy(tempFile, "--name", PROBE_APPLICATION_NAME, "--contextroot",
                PROBE_APPLICATION_NAME);
            deployed.push(PROBE_APPLICATION_NAME);
        }
        catch (GlassFishException exc) {
            throw new TestContainerException(exc);
        }
        catch (IOException exc) {
            throw new TestContainerException(exc);
        }
        return -1;
    }

    public synchronized long install(InputStream stream) {
        return install("local", stream);
    }

    /**
     * Deploys all Java EE modules defined in Pax Exam options. For options without an explicit
     * application name, names app1, app2 etc. are generated on the fly. The context root defaults
     * to the application name if not set in the option.
     */
    public void deployModules() {
        UrlDeploymentOption[] deploymentOptions = system.getOptions(UrlDeploymentOption.class);
        int numModules = 0;
        for (UrlDeploymentOption option : deploymentOptions) {
            numModules++;
            if (option.getName() == null) {
                option.name("app" + numModules);
            }
            deployModule(option);
        }
    }

    /**
     * Deploys the module specified by the given option.
     *
     * @param option
     *            deployment option
     */
    private void deployModule(UrlDeploymentOption option) {
        try {
            String url = option.getURL();
            LOG.info("deploying module {}", url);
            URI uri = new URL(url).toURI();
            String applicationName = option.getName();
            String contextRoot = option.getContextRoot();
            if (contextRoot == null) {
                contextRoot = applicationName;
            }
            Deployer deployer = glassFish.getDeployer();
            deployer.deploy(uri, "--name", applicationName, "--contextroot", applicationName);
            deployed.push(applicationName);
            LOG.info("deployed module {}", url);
        }
        catch (IOException exc) {
            throw new TestContainerException(exc);
        }
        catch (GlassFishException exc) {
            throw new TestContainerException(exc);
        }
        catch (URISyntaxException exc) {
            throw new TestContainerException(exc);
        }
    }

    /**
     * Undeploys all modules and shuts down the GlassFish runtime.
     */
    public synchronized void cleanup() {
        undeployModules();
        try {
            glassFish.stop();
        }
        catch (GlassFishException exc) {
            throw new TestContainerException(exc);
        }
    }

    /**
     * Undeploys all deployed modules in reverse order.
     */
    private void undeployModules() {
        try {
            Deployer deployer = glassFish.getDeployer();
            while (!deployed.isEmpty()) {
                String applicationName = deployed.pop();
                deployer.undeploy(applicationName);
            }
        }
        catch (GlassFishException exc) {
            throw new TestContainerException(exc);
        }
    }

    /**
     * Starts the GlassFish container.
     */
    public TestContainer start() {
        System.setProperty("java.protocol.handler.pkgs", "org.ops4j.pax.url");
        ConfigurationManager cm = new ConfigurationManager();
        configDirName = cm.getProperty(GLASSFISH_CONFIG_DIR_KEY,
            "src/test/resources/glassfish-config");
        File domainConfig = new File(configDirName, "domain.xml");
        GlassFishProperties gfProps = new GlassFishProperties();
        if (domainConfig.exists()) {
            gfProps.setConfigFileURI(domainConfig.toURI().toString());
        }

        try {
            glassFish = GlassFishRuntime.bootstrap().newGlassFish(gfProps);
            glassFish.start();

            // set access point in test directory
            String portNumber = getPortNumber(domainConfig);
            testDirectory.setAccessPoint(new URI("http://localhost:" + portNumber
                + "/Pax-Exam-Probe/"));

            deployModules();
        }
        catch (GlassFishException e) {
            throw new TestContainerException("Problem starting test container.", e);
        }
        catch (URISyntaxException e) {
            throw new TestContainerException("Problem starting test container.", e);
        }
        return this;
    }

    /**
     * Reads the first port number from the domain.xml configuration.
     *
     * @param domainConfig
     * @return port number as string
     */
    private String getPortNumber(File domainConfig) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder;
            builder = factory.newDocumentBuilder();
            Document doc = builder.parse(domainConfig);
            XPathFactory xpf = XPathFactory.newInstance();
            XPath xPath = xpf.newXPath();
            String port = xPath.evaluate(HTTP_PORT_XPATH, doc);
            return port;
        }
        catch (ParserConfigurationException exc) {
            throw new IllegalArgumentException(exc);
        }
        catch (SAXException exc) {
            throw new IllegalArgumentException(exc);
        }
        catch (IOException exc) {
            throw new IllegalArgumentException(exc);
        }
        catch (XPathExpressionException exc) {
            throw new IllegalArgumentException(exc);
        }
    }

    /**
     * Stops the test container gracefully, undeploying all modules and uninstalling all bundles.
     */
    public TestContainer stop() {
        if (glassFish != null) {
            cleanup();
            system.clear();
        }
        else {
            LOG.warn("Framework does not exist. Called start() before ? ");
        }
        return this;
    }

    @Override
    public String toString() {
        return "EmbeddedGlassFish";
    }

    @Override
    public long installProbe(InputStream stream) {
        install(stream);
        this.warProbe = deployed.pop();
        return -1;
    }

    @Override
    public void uninstallProbe() {
        try {
            glassFish.getDeployer().undeploy(warProbe);
            this.warProbe = null;
        }
        catch (GlassFishException exc) {
            throw new TestContainerException(exc);
        }       
    }
}
TOP

Related Classes of org.ops4j.pax.exam.glassfish.embedded.EmbeddedGlassFishTestContainer

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.