/*
* JBoss, Home of Professional Open Source
* Copyright 2014, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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.jboss.aerogear.test.arquillian.container;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.arquillian.container.spi.ConfigurationException;
import org.jboss.arquillian.container.spi.client.container.DeployableContainer;
import org.jboss.arquillian.container.spi.client.container.DeploymentException;
import org.jboss.arquillian.container.spi.client.container.LifecycleException;
import org.jboss.arquillian.container.spi.client.protocol.ProtocolDescription;
import org.jboss.arquillian.container.spi.client.protocol.metadata.HTTPContext;
import org.jboss.arquillian.container.spi.client.protocol.metadata.ProtocolMetaData;
import org.jboss.arquillian.container.spi.client.protocol.metadata.Servlet;
import org.jboss.arquillian.core.api.Instance;
import org.jboss.arquillian.core.api.InstanceProducer;
import org.jboss.arquillian.core.api.annotation.ApplicationScoped;
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.core.spi.ServiceLoader;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.descriptor.api.Descriptor;
import org.json.JSONObject;
/**
* Arquillian non-deploying container. With this container you can run your Arquillian tests against already deployed
* application.
*
* <p>
* See {@link NonDeployingConfiguration} for required configuration.
* </p>
*
* @author <a href="mailto:kpiwko@redhat.com">Karel Piwko</a>
* @author <a href="mailto:ecervena@redhat.com">Emil Cervenan</a>
*
*/
public class NonDeployingContainer implements DeployableContainer<NonDeployingConfiguration> {
private static final Logger log = Logger.getLogger(NonDeployingContainer.class.getName());
@Inject
@ApplicationScoped
private InstanceProducer<NonDeployingConfiguration> configuration;
@Inject
private Instance<ServiceLoader> serviceLoader;
@Override
public ProtocolDescription getDefaultProtocol() {
return new ProtocolDescription("Servlet 3.0");
}
@Override
public Class<NonDeployingConfiguration> getConfigurationClass() {
return NonDeployingConfiguration.class;
}
@Override
public void setup(NonDeployingConfiguration configuration) {
this.configuration.set(configuration);
}
@Override
public void start() throws LifecycleException {
log.log(Level.INFO, "Assuming that remote deployment is ready at {0}", getAppURI());
}
@Override
public void stop() throws LifecycleException {
log.log(Level.INFO, "NonDeploying container stops effectively nothing.");
}
@Override
public ProtocolMetaData deploy(Archive<?> archive) throws DeploymentException {
// get path based on archive name
String contextPath = getContextPathFromArchive(archive);
// check for root
if ("ROOT".equalsIgnoreCase(contextPath)) {
contextPath = "/";
}
// try remapping contextPath from JSON map
JSONObject contextRootRemap = getContextRootRemapAsJSON();
if (contextRootRemap != null) {
String remappedContextPath = contextRootRemap.optString(contextPath);
if (remappedContextPath.length() != 0) {
log.log(Level.INFO, "Applying contextPath remap from {0} to {1}", new Object[] {
contextPath,
remappedContextPath
});
contextPath = remappedContextPath;
}
}
log.log(Level.INFO,
"Pretending deployment of archive {0} to {1}", new Object[] {
archive.getName(),
buildUrl(getAppURI(), contextPath)
});
URI contextURI = getAppURI();
HTTPContext context = new HTTPContext("openshift", contextURI.getHost(), getPort(contextURI));
Servlet servlet = new Servlet("deployment", contextPath);
context.add(servlet);
ProtocolMetaData metaData = new ProtocolMetaData();
metaData.addContext(context);
return metaData;
}
@Override
public void undeploy(Archive<?> archive) throws DeploymentException {
log.log(Level.INFO, "NonDeploying container undeploys effectively nothing.");
}
@Override
public void deploy(Descriptor descriptor) throws DeploymentException {
}
@Override
public void undeploy(Descriptor descriptor) throws DeploymentException {
}
private URL buildUrl(URI uri, String contextPath) throws DeploymentException {
try {
return new URL(uri.toURL(), contextPath);
} catch (MalformedURLException e) {
throw new DeploymentException("Unable to construct URL for deployment", e);
}
}
/**
*
* @param archive archive to get context path from
* @return context path of archive
*/
private String getContextPathFromArchive(Archive<?> archive) {
String contextPath = archive.getName();
String[] types = { ".war", ".jar", ".ear" };
if (contextPath != null) {
for (String type : types) {
if (contextPath.endsWith(type)) {
contextPath = contextPath.substring(0, contextPath.length() - type.length());
break;
}
}
}
return contextPath;
}
/**
*
* @return context root remap from configuration as a JSON object
*/
private JSONObject getContextRootRemapAsJSON() {
if (configuration.get().getContextRootRemap() == null) {
return null;
}
return new JSONObject(configuration.get().getContextRootRemap());
}
/**
*
* @return URI of application form configuration
*/
private URI getAppURI() {
URI uri = null;
try {
uri = new URI(configuration.get().getBaseURI());
} catch (URISyntaxException e) {
throw new ConfigurationException("Parameter \"baseURI\" does not represent a valid URI", e);
}
return uri;
}
/**
* When {@code contextURI} does not have a port, {@code defaultPort} will be used. When it is not specified, 80 is used.
*
* @param contextURI uri to get port from
* @param defaultPort other default port then 80
* @return port from {@code contextURI}
*/
private int getPort(URI contextURI, int... defaultPort) {
final int DEFAULT_PORT = 80;
int port = contextURI.getPort();
if (port == -1) {
if (defaultPort.length == 1) {
port = defaultPort[0];
} else {
port = DEFAULT_PORT;
}
}
return port;
}
}