Skip to content

Commit

Permalink
ARQ-397 Add support for sunResourcesXML deployment during container s…
Browse files Browse the repository at this point in the history
…tartup

* Fix EAR WebModule deployment scanning for Servlet ProtocolMetadata discovery
  • Loading branch information
aslakknutsen committed Jun 27, 2011
1 parent 81f36d5 commit 2dc49ca
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 20 deletions.
Expand Up @@ -18,11 +18,17 @@

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import javax.servlet.ServletRegistration;

import org.apache.catalina.Container;
import org.glassfish.embeddable.BootstrapProperties;
import org.glassfish.embeddable.CommandResult;
import org.glassfish.embeddable.CommandRunner;
import org.glassfish.embeddable.GlassFish;
import org.glassfish.embeddable.GlassFishException;
import org.glassfish.embeddable.GlassFishProperties;
Expand All @@ -38,6 +44,11 @@
import org.jboss.arquillian.container.spi.client.protocol.metadata.ProtocolMetaData;
import org.jboss.arquillian.container.spi.client.protocol.metadata.Servlet;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ArchivePath;
import org.jboss.shrinkwrap.api.Filters;
import org.jboss.shrinkwrap.api.Node;
import org.jboss.shrinkwrap.api.spec.EnterpriseArchive;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.descriptor.api.Descriptor;

import com.sun.enterprise.web.WebModule;
Expand All @@ -50,6 +61,10 @@
*/
public class GlassFishContainer implements DeployableContainer<GlassFishConfiguration>
{
private static final Logger log = Logger.getLogger(GlassFishContainer.class.getName());

private static final String COMMAND_ADD_RESOURCES = "add-resources";

// TODO: open configuration up for bind address
private static final String ADDRESS = "localhost";

Expand Down Expand Up @@ -110,7 +125,6 @@ public void setup(GlassFishConfiguration configuration)
}
serverProps.setConfigFileReadOnly(configuration.isConfigurationReadOnly());
serverProps.setPort("http-listener", configuration.getBindHttpPort());

try
{
glassfish = glassfishRuntime.newGlassFish(serverProps);
Expand All @@ -134,7 +148,18 @@ public void start() throws LifecycleException
{
throw new LifecycleException("Could not start GlassFish Embedded", e);
}

// Server needs to be started before we can deploy resources
if(configuration.getSunResourcesXml() != null)
{
try
{
executeCommand(COMMAND_ADD_RESOURCES, this.configuration.getSunResourcesXml());
}
catch (Throwable e)
{
throw new RuntimeException("Could not deploy sun-reosurces file: " + configuration.getSunResourcesXml(), e);
}
}
}

/* (non-Javadoc)
Expand Down Expand Up @@ -175,7 +200,7 @@ public ProtocolMetaData deploy(Archive<?> archive) throws DeploymentException
ADDRESS,
configuration.getBindHttpPort());

findServlets(httpContext, deploymentName);
findServlets(httpContext, resolveWebArchiveNames(archive));

return new ProtocolMetaData()
.addContext(httpContext);
Expand All @@ -186,6 +211,29 @@ public ProtocolMetaData deploy(Archive<?> archive) throws DeploymentException
}
}

/**
* @param archive
* @return
*/
private String[] resolveWebArchiveNames(Archive<?> archive)
{
if(archive instanceof WebArchive)
{
return new String[] {createDeploymentName(archive.getName())};
}
else if(archive instanceof EnterpriseArchive)
{
Map<ArchivePath, Node> webArchives = archive.getContent(Filters.include(".*\\.war"));
List<String> deploymentNames = new ArrayList<String>();
for(ArchivePath path : webArchives.keySet())
{
deploymentNames.add(createDeploymentName(path.get()));
}
return deploymentNames.toArray(new String[0]);
}
return new String[0];
}

/* (non-Javadoc)
* @see org.jboss.arquillian.spi.client.container.DeployableContainer#undeploy(org.jboss.shrinkwrap.api.Archive)
*/
Expand Down Expand Up @@ -219,28 +267,72 @@ public void undeploy(Descriptor descriptor) throws DeploymentException

private String createDeploymentName(String archiveName)
{
return archiveName.substring(0, archiveName.lastIndexOf("."));
String correctedName = archiveName;
if(correctedName.startsWith("/"))
{
correctedName = correctedName.substring(1);
}
if(correctedName.indexOf(".") != -1)
{
correctedName = correctedName.substring(0, archiveName.lastIndexOf(".")-1);
}
return correctedName;
}

public void findServlets(HTTPContext httpContext, String deploymentName) throws GlassFishException
public void findServlets(HTTPContext httpContext, String[] webArchiveNames) throws GlassFishException
{
WebContainer webContainer = glassfish.getService(WebContainer.class);
for(VirtualServer server : webContainer.getVirtualServers())
for(String deploymentName : webArchiveNames)
{
for(Context context : server.getContexts())
for(VirtualServer server : webContainer.getVirtualServers())
{
if(context instanceof WebModule)
WebModule webModule = null;

for(Context serverContext : server.getContexts())
{
if(serverContext instanceof WebModule)
{
if(((WebModule)serverContext).getID().startsWith(deploymentName))
{
webModule = (WebModule)serverContext;
}
}
}
if(webModule == null)
{
if(!((WebModule)context).getID().startsWith(deploymentName))
if(server instanceof com.sun.enterprise.web.VirtualServer)
{
continue;
Container child = ((com.sun.enterprise.web.VirtualServer)server).findChild("/" + deploymentName);
if(child instanceof WebModule)
{
webModule = (WebModule)child;
}
}
}
for(Map.Entry<String, ? extends ServletRegistration> servletRegistration : context.getServletRegistrations().entrySet())
if(webModule != null)
{
httpContext.add(new Servlet(servletRegistration.getKey(), context.getContextPath()));
for(Map.Entry<String, ? extends ServletRegistration> servletRegistration : webModule.getServletRegistrations().entrySet())
{
httpContext.add(new Servlet(servletRegistration.getKey(), webModule.getContextPath()));
}
}
}
}
}

private void executeCommand(String command, String... parameterList) throws Throwable
{
CommandRunner runner = glassfish.getCommandRunner();
CommandResult result = runner.run(command, parameterList);

switch(result.getExitStatus())
{
case FAILURE:
case WARNING:
throw result.getFailureCause();
case SUCCESS:
log.info("command " + command + " result: " + result.getOutput());
break;
}
}
}
Expand Up @@ -26,7 +26,7 @@
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.EnterpriseArchive;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Ignore;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Test;
import org.junit.runner.RunWith;

Expand All @@ -36,7 +36,6 @@
* @author <a href="mailto:aslak@redhat.com">Aslak Knutsen</a>
* @version $Revision: $
*/
@Ignore // GlassFish bug, can't Inject @EJB from a ejb module in a war ?
@RunWith(Arquillian.class)
public class IntegrationEarTestCase
{
Expand All @@ -49,7 +48,11 @@ public static EnterpriseArchive createDeployment() throws Exception
.addClasses(
NoInterfaceEJB.class,
NameProvider.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"));
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"))
.addAsModule(
ShrinkWrap.create(WebArchive.class)
.addClass(IntegrationEarTestCase.class)
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"));
}

@EJB
Expand Down
@@ -0,0 +1,51 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2010, 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.container.glassfish.embedded_3_1.app;

import java.io.IOException;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

/**
* TestServlet
*
* @author <a href="mailto:aslak@redhat.com">Aslak Knutsen</a>
* @version $Revision: $
*/
@WebServlet(urlPatterns = MyServlet.URL_PATTERN)
public class MyServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;

public static final String URL_PATTERN = "/Test";

public static final String MESSAGE = "hello";

@Resource(name = "jdbc/arquillian") private DataSource arquillianDS;

@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
response.getWriter().append(arquillianDS != null ? MESSAGE : "#fail");
}
}
@@ -0,0 +1,80 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2010, 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.container.glassfish.embedded_3_1.app;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;

import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
* GlassFishEmbeddedContainerTestCase
*
* @author <a href="mailto:aslak@redhat.com">Aslak Knutsen</a>
* @version $Revision: $
*/
@RunWith(Arquillian.class)
public class ResourceXmlClientTestCase
{
/**
* Deployment for the test
* @return
*/
@Deployment(testable = false)
public static WebArchive getDeployment()
{
return ShrinkWrap.create(WebArchive.class).addClass(MyServlet.class);
}

@Test
public void shouldBeAbleToDeployWebArchive(@ArquillianResource(MyServlet.class) URL baseURL) throws Exception
{
String body = readAllAndClose(
new URL(baseURL, "Test").openStream());

Assert.assertEquals(
"Verify that the servlet was deployed and returns expected result",
MyServlet.MESSAGE,
body);
}

private String readAllAndClose(InputStream is) throws Exception
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
try
{
int read;
while( (read = is.read()) != -1)
{
out.write(read);
}
}
finally
{
try { is.close(); } catch (Exception e) { }
}
return out.toString();
}
}
15 changes: 10 additions & 5 deletions glassfish-embedded-3.1/src/test/resources/arquillian.xml
@@ -1,8 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian-1.0.xsd">
<arquillian
xmlns="http://jboss.org/schema/arquillian"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">

<engine>
<property name="deploymentExportPath">target/</property>
</engine>
<container qualifier="glassfish" default="true">
<configuration>
<property name="sunResourcesXml">src/test/resources/sun-resources.xml</property>
<property name="bindHttpPort">7070</property>
</configuration>
</container>
</arquillian>
19 changes: 19 additions & 0 deletions glassfish-embedded-3.1/src/test/resources/sun-resources.xml
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 Resource Definitions //EN"
"http://www.sun.com/software/appserver/dtds/sun-resources_1_4.dtd">
<resources>
<jdbc-resource pool-name="ArquillianEmbeddedDerbyPool"
jndi-name="jdbc/arquillian"/>
<jdbc-connection-pool name="ArquillianEmbeddedDerbyPool"
res-type="javax.sql.DataSource"
datasource-classname="org.apache.derby.jdbc.EmbeddedDataSource"
is-isolation-level-guaranteed="false">
<property name="databaseName" value="target/databases/derby"/>
<property name="createDatabase" value="create"/>
</jdbc-connection-pool>
<!--
<custom-resource res-type="java.lang.String" jndi-name="message" factory-class="org.glassfish.resources.custom.factory.PrimitivesAndStringFactory" enabled="true">
<property name="value" value="hello"/>
</custom-resource>
-->
</resources>

0 comments on commit 2dc49ca

Please sign in to comment.