/* * JBoss, Home of Professional Open Source * Copyright 2012, 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.arquillian.warp.impl.client.deployment; import java.io.InputStream; import java.util.Collection; import org.jboss.arquillian.container.spi.client.deployment.Validate; import org.jboss.arquillian.container.test.spi.RemoteLoadableExtension; import org.jboss.arquillian.container.test.spi.TestDeployment; import org.jboss.arquillian.container.test.spi.client.deployment.ProtocolArchiveProcessor; import org.jboss.arquillian.core.api.Instance; import org.jboss.arquillian.core.api.annotation.Inject; import org.jboss.arquillian.core.spi.ServiceLoader; import org.jboss.arquillian.test.spi.TestClass; import org.jboss.arquillian.warp.Inspection; import org.jboss.arquillian.warp.WarpRemoteExtension; import org.jboss.arquillian.warp.impl.client.commandBus.RemoteSuiteLifecyclePropagation.FireAfterSuiteOnServer; import org.jboss.arquillian.warp.impl.client.commandBus.RemoteSuiteLifecyclePropagation.FireBeforeSuiteOnServer; import org.jboss.arquillian.warp.impl.client.execution.DefaultHttpRequestEnrichmentService.RegisterPayloadRemotely; import org.jboss.arquillian.warp.impl.client.execution.DefaultResponseDeenrichmentService.RetrievePayloadFromServer; import org.jboss.arquillian.warp.impl.server.commandBus.CommandBusOnServer; import org.jboss.arquillian.warp.impl.server.delegation.RequestDelegationService; import org.jboss.arquillian.warp.impl.server.lifecycle.LifecycleManagerStoreImpl; import org.jboss.arquillian.warp.servlet.AfterServlet; import org.jboss.arquillian.warp.servlet.BeforeServlet; import org.jboss.arquillian.warp.spi.LifecycleManagerStore; import org.jboss.arquillian.warp.spi.WarpCommons; import org.jboss.arquillian.warp.spi.WarpDeploymentEnrichmentExtension; import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.ArchivePath; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.asset.Asset; import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.jboss.shrinkwrap.api.spec.WebArchive; /** * Adds all required resources into web archive * * @author Lukas Fryc */ public class DeploymentEnricher implements ProtocolArchiveProcessor { static String[] REQUIRED_WARP_PACKAGES = new String[] { // SPI "org.jboss.arquillian.warp.spi", "org.jboss.arquillian.warp.spi.context", "org.jboss.arquillian.warp.spi.event", "org.jboss.arquillian.warp.spi.exception", "org.jboss.arquillian.warp.spi.servlet.event", // Implementation "org.jboss.arquillian.warp.impl.server.inspection", "org.jboss.arquillian.warp.impl.server.enrichment", "org.jboss.arquillian.warp.impl.server.event", "org.jboss.arquillian.warp.impl.server.manager", "org.jboss.arquillian.warp.impl.server.execution", "org.jboss.arquillian.warp.impl.server.lifecycle", "org.jboss.arquillian.warp.impl.server.provider", "org.jboss.arquillian.warp.impl.server.request", "org.jboss.arquillian.warp.impl.server.test", "org.jboss.arquillian.warp.impl.server.commandBus", "org.jboss.arquillian.warp.impl.server.delegation", "org.jboss.arquillian.warp.impl.server.remote", "org.jboss.arquillian.warp.impl.shared", "org.jboss.arquillian.warp.impl.shared.command", "org.jboss.arquillian.warp.impl.utils", // Servlet Extension "org.jboss.arquillian.warp.servlet.event", "org.jboss.arquillian.warp.servlet.provider" }; static final String WARP_FILTER_CLASS_FQN = "org.jboss.arquillian.warp.impl.server.execution.WarpFilter"; static Class<?>[] REQUIRED_WARP_INNER_CLASSES = new Class<?>[] { FireBeforeSuiteOnServer.class, FireAfterSuiteOnServer.class, RegisterPayloadRemotely.class, RetrievePayloadFromServer.class }; @Inject private Instance<ServiceLoader> serviceLoader; @Inject private Instance<TestClass> testClass; /** * Adds Warp archive to the protocol archive to make it available for WARs and EARs. */ @Override public void process(TestDeployment testDeployment, Archive<?> protocolArchive) { final TestClass testClass = this.testClass.get(); final Archive<?> applicationArchive = testDeployment.getApplicationArchive(); if (WarpCommons.isWarpTest(testClass.getJavaClass())) { if (!Validate.isArchiveOfType(WebArchive.class, protocolArchive)) { throw new IllegalArgumentException("Protocol archives of type " + protocolArchive.getClass() + " not supported by Warp. Please use the Servlet 3.0 protocol."); } addWarpPackageToDeployment(protocolArchive.as(WebArchive.class)); addWarpExtensionsDeployment(protocolArchive.as(WebArchive.class)); removeTestClassFromDeployment(applicationArchive, testClass); } } /** * Adds the JAR package required by Warp core to the archive */ private void addWarpPackageToDeployment(WebArchive archive) { archive.addAsLibrary(createWarpArchive()); } /** * Adds all Warp lifecycle extension packages to the archive */ private void addWarpExtensionsDeployment(WebArchive archive) { final Collection<WarpDeploymentEnrichmentExtension> lifecycleExtensions = serviceLoader.get().all( WarpDeploymentEnrichmentExtension.class); for (WarpDeploymentEnrichmentExtension extension : lifecycleExtensions) { JavaArchive library = extension.getEnrichmentLibrary(); if (library != null) { archive.addAsLibrary(library); } extension.enrichWebArchive(archive); } } /** * removes test class from web archive (test class will be replaced by transformed assertions) */ private void removeTestClassFromDeployment(Archive<?> archive, TestClass testClass) { for (ArchivePath archivePath : archive.getContent().keySet()) { String path = archivePath.get(); String classPath = testClass.getName().replace(".", "/"); // remove TestClass and its anonymous classes - do not remove static inner classes if (path.matches("/WEB-INF/classes/" + classPath + "(\\$[0-9]*)?\\.class")) { archive.delete(archivePath); } } } /** * creates a {@link JavaArchive} as composition of resources required by Warp runtime in a container */ JavaArchive createWarpArchive() { JavaArchive archive = ShrinkWrap.create(JavaArchive.class, "arquillian-warp.jar"); // API archive.addClass(Inspection.class); archive.addClasses(BeforeServlet.class, AfterServlet.class); for (String packageName : REQUIRED_WARP_PACKAGES) { archive.addPackage(packageName); } archive.addAsManifestResource(getWebFragmentAsset(), "web-fragment.xml"); archive.addClasses(REQUIRED_WARP_INNER_CLASSES); // register remote extension archive.addClass(WarpRemoteExtension.class); archive.addAsServiceProvider(RemoteLoadableExtension.class.getName(), WarpRemoteExtension.class.getName(), "!org.jboss.arquillian.protocol.servlet.runner.ServletRemoteExtension"); archive.addAsServiceProvider(LifecycleManagerStore.class, LifecycleManagerStoreImpl.class); // register RequestProcessingDelegationService archive.addAsServiceProvider(RequestDelegationService.class, CommandBusOnServer.class); return archive; } private Asset getWebFragmentAsset() { return new Asset() { @Override public InputStream openStream() { return ClassLoader.getSystemResourceAsStream("META-INF/web-fragment-warp.xml"); } }; } }