[Bug 404508] enable overlay deployer

This commit is contained in:
Jesse McConnell 2013-05-20 09:20:28 -05:00
parent 6cfd33a71b
commit b959a742d0
96 changed files with 3664 additions and 7 deletions

View File

@ -0,0 +1,63 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.0.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-overlay-deployer</artifactId>
<name>Jetty :: Overlay Deployer</name>
<description>Overlayed deployer</description>
<properties>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>${basedir}/src/main/assembly/config.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-deploy</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-plus</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>javax.transaction</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<reporting>
</reporting>
</project>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<assembly>
<id>config</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>jar</format>
</formats>
<fileSets>
<fileSet>
<directory>src/main/config</directory>
<outputDirectory></outputDirectory>
<includes>
<include>etc/**</include>
<include>overlays/**</include>
</includes>
</fileSet>
</fileSets>
</assembly>

View File

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<!-- =============================================================== -->
<!-- Add a ContextProvider to the deployment manager -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- This scans the webapps directory for war files and directories -->
<!-- to deploy. -->
<!-- This configuration must be used with jetty-deploy.xml, which -->
<!-- creates the deployment manager instance -->
<!-- =============================================================== -->
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<Ref id="DeploymentManager">
<Call name="addAppProvider">
<Arg>
<New id="OverlayedAppProvider" class="org.eclipse.jetty.overlays.OverlayedAppProvider">
<Set name="scanDir"><Property name="jetty.home" default="." />/overlays</Set>
<Set name="nodeName"><Property name="node.name" default="nonameNode"/></Set>
<Set name="scanInterval">1</Set>
</New>
</Arg>
</Call>
</Ref>
</Configure>

View File

@ -0,0 +1,27 @@
Cloudtide instance
===================
This directory contains overlays (as directories or jars) that
are define instances of templates to be deployed.
An instance filename consists of a template name, the '=' character (or '--' string)
and then an instance identifier. For example:
mytemplate=redInstance
This defines a instance called redInstance using the template called mytemplate.
An overlay is structed as a WAR, but also may contain:
* WEB-INF/lib-overlay directory, which can contain jar files made available to
the overlay.xml configuration (unlike any overlayed WEB-INF/lib jars).
* A WEB-INF/overlay.xml file, which is an XmlConfiguration format file used to
inject the ContextHandler instance.
* A WEB-INF/web-overlay.xml fragment that is applied as an override descriptor
* Static content that overlays the static content of the webapp, node and template.
* WEB-INF/classes and WEB-INF/lib that overlays the code of the webapp, node and template.

View File

@ -0,0 +1,20 @@
Cloudtide nodes
===============
This directory contains overlays (as directories or jars) that
are applied to all instances for a given node.
An overlay is structed as a WAR, but also may contain:
* WEB-INF/lib-overlay directory, which can contain jar files made available to
the overlay.xml configuration (unlike any overlayed WEB-INF/lib jars).
* A WEB-INF/overlay.xml file, which is an XmlConfiguration format file used to
inject the ContextHandler instance.
* A WEB-INF/web-overlay.xml fragment that is applied as an override descriptor
* Static content that overlays the static content of the webapp, node and template.
* WEB-INF/classes and WEB-INF/lib that overlays the code of the webapp, node and template.

View File

@ -0,0 +1,32 @@
Cloudtide templates
===================
This directory contains overlays (as directories or jars) that
are applied to webapps to create templates. Templates are not directly
deployed, but are used by overlays in the instances directory.
A Template filename consists of a template name, the '=' character and
then the webapp name. For example:
mytemplate=mywebapp-1.2.3
This defines a template called mytemplate that overlays either the mywebapp-1.2.3.war
file or the mywebapp-1.2.3 directory in cloudtide/webapps.
An overlay is structed as a WAR, and may contain:
* WEB-INF/template.xml a XmlConfiguration formatted file that is applied to a shared
instance of TemplateContext to provide the common classloader and resource cache to
all instances of the template.
* WEB-INF/lib-overlay directory, which can contain jar files made available to
the overlay.xml configuration (unlike any overlayed WEB-INF/lib jars).
* A WEB-INF/overlay.xml file, which is an XmlConfiguration format file used to
inject the ContextHandler instance.
* A WEB-INF/web-overlay.xml fragment that is applied as an override descriptor
* Static content that overlays the static content of the webapp, node and template.
* WEB-INF/classes and WEB-INF/lib that overlays the code of the webapp, node and template.

View File

@ -0,0 +1,6 @@
Cloudtide webapplication
------------------------
This directory contains webapplication directories or war files that are used by the
cloudtide templates

View File

@ -0,0 +1,290 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.overlays;
import java.io.IOException;
import java.security.PermissionCollection;
import java.util.Map;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.ResourceCache;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.Destroyable;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.ClasspathPattern;
import org.eclipse.jetty.webapp.WebAppClassLoader;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
/**
* A Cloudtide template context.
* <p>
* This class is configured by the template.xml files and is used to control the
* shared resource cache and classloader.
* <p>
* This class is an AggregateLifeCycle, so dependent beans may be added to the template and will be started, stopped and destroyed with the template.
* The template is started after the template.xml file have been applied. It is stopped and destroyed after the last instance using the template is undeployed.
*/
public class TemplateContext extends ContainerLifeCycle implements WebAppClassLoader.Context, Destroyable
{
private final ClassLoader _libLoader;
private final Resource _baseResource;
private final ResourceCache _resourceCache;
private final Server _server;
private final MimeTypes _mimeTypes;
private final WebAppClassLoader _webappLoader;
private ClasspathPattern _systemClasses;
private ClasspathPattern _serverClasses;
private PermissionCollection _permissions;
private boolean _parentLoaderPriority;
private String _extraClasspath;
private Map<String, Object> _idMap;
public ClassLoader getLibLoader()
{
return _libLoader;
}
public TemplateContext()
{
_server=null;
_baseResource=null;
_mimeTypes=new MimeTypes();
_resourceCache=null;
_webappLoader=null;
_libLoader=null;
}
public TemplateContext(String key, Server server,Resource baseResource, ClassLoader libLoader) throws IOException
{
_server=server;
_baseResource=baseResource;
_mimeTypes=new MimeTypes();
_resourceCache=new ResourceCache(null,baseResource,_mimeTypes,false,false);
String[] patterns = (String[])_server.getAttribute(WebAppContext.SERVER_SRV_CLASSES);
_serverClasses=new ClasspathPattern(patterns==null?WebAppContext.__dftServerClasses:patterns);
patterns = (String[])_server.getAttribute(WebAppContext.SERVER_SYS_CLASSES);
_systemClasses=new ClasspathPattern(patterns==null?WebAppContext.__dftSystemClasses:patterns);
_libLoader=libLoader;
// Is this a webapp or a normal context
Resource classes=getBaseResource().addPath("WEB-INF/classes/");
Resource lib=getBaseResource().addPath("WEB-INF/lib/");
if (classes.exists() && classes.isDirectory() || lib.exists() && lib.isDirectory())
{
_webappLoader=new WebAppClassLoader(_libLoader,this);
_webappLoader.setName(key);
if (classes.exists())
_webappLoader.addClassPath(classes);
if (lib.exists())
_webappLoader.addJars(lib);
}
else
_webappLoader=null;
}
/* ------------------------------------------------------------ */
public Resource getBaseResource()
{
return _baseResource;
}
/* ------------------------------------------------------------ */
/**
* @return Comma or semicolon separated path of filenames or URLs
* pointing to directories or jar files. Directories should end
* with '/'.
*/
public String getExtraClasspath()
{
return _extraClasspath;
}
/* ------------------------------------------------------------ */
public MimeTypes getMimeTypes()
{
return _mimeTypes;
}
/* ------------------------------------------------------------ */
public PermissionCollection getPermissions()
{
return _permissions;
}
/* ------------------------------------------------------------ */
public ResourceCache getResourceCache()
{
return _resourceCache;
}
/* ------------------------------------------------------------ */
public Server getServer()
{
return _server;
}
/* ------------------------------------------------------------ */
WebAppClassLoader getWebappLoader()
{
return _webappLoader;
}
/* ------------------------------------------------------------ */
public boolean isParentLoaderPriority()
{
return _parentLoaderPriority;
}
/* ------------------------------------------------------------ */
public boolean isServerClass(String clazz)
{
return _serverClasses.match(clazz);
}
/* ------------------------------------------------------------ */
public boolean isSystemClass(String clazz)
{
return _systemClasses.match(clazz);
}
/* ------------------------------------------------------------ */
public Resource newResource(String urlOrPath) throws IOException
{
return Resource.newResource(urlOrPath);
}
/* ------------------------------------------------------------ */
/**
* @param extraClasspath Comma or semicolon separated path of filenames or URLs
* pointing to directories or jar files. Directories should end
* with '/'.
*/
public void setExtraClasspath(String extraClasspath)
{
_extraClasspath=extraClasspath;
}
/* ------------------------------------------------------------ */
/**
* @param java2compliant The java2compliant to set.
*/
public void setParentLoaderPriority(boolean java2compliant)
{
_parentLoaderPriority = java2compliant;
}
/* ------------------------------------------------------------ */
/**
* @param permissions The permissions to set.
*/
public void setPermissions(PermissionCollection permissions)
{
_permissions = permissions;
}
/* ------------------------------------------------------------ */
/**
* Set the server classes patterns.
* <p>
* Server classes/packages are classes used to implement the server and are hidden
* from the context. If the context needs to load these classes, it must have its
* own copy of them in WEB-INF/lib or WEB-INF/classes.
* A class pattern is a string of one of the forms:<dl>
* <dt>org.package.Classname</dt><dd>Match a specific class</dd>
* <dt>org.package.</dt><dd>Match a specific package hierarchy</dd>
* <dt>-org.package.Classname</dt><dd>Exclude a specific class</dd>
* <dt>-org.package.</dt><dd>Exclude a specific package hierarchy</dd>
* </dl>
* @param serverClasses The serverClasses to set.
*/
public void setServerClasses(String[] serverClasses)
{
_serverClasses = new ClasspathPattern(serverClasses);
}
/* ------------------------------------------------------------ */
/**
* Set the system classes patterns.
* <p>
* System classes/packages are classes provided by the JVM and that
* cannot be replaced by classes of the same name from WEB-INF,
* regardless of the value of {@link #setParentLoaderPriority(boolean)}.
* A class pattern is a string of one of the forms:<dl>
* <dt>org.package.Classname</dt><dd>Match a specific class</dd>
* <dt>org.package.</dt><dd>Match a specific package hierarchy</dd>
* <dt>-org.package.Classname</dt><dd>Exclude a specific class</dd>
* <dt>-org.package.</dt><dd>Exclude a specific package hierarchy</dd>
* </dl>
* @param systemClasses The systemClasses to set.
*/
public void setSystemClasses(String[] systemClasses)
{
_systemClasses = new ClasspathPattern(systemClasses);
}
/* ------------------------------------------------------------ */
public void addSystemClass(String classname)
{
_systemClasses.addPattern(classname);
}
/* ------------------------------------------------------------ */
public void addServerClass(String classname)
{
_serverClasses.addPattern(classname);
}
/* ------------------------------------------------------------ */
public void destroy()
{
if (_baseResource!=null)
_baseResource.release();
if (_resourceCache!=null)
_resourceCache.flushCache();
if(_idMap!=null)
_idMap.clear();
}
/* ------------------------------------------------------------ */
public void setIdMap(Map<String, Object> idMap)
{
_idMap=idMap;
}
/* ------------------------------------------------------------ */
public Map<String, Object> getIdMap()
{
return _idMap;
}
}

View File

@ -0,0 +1,100 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.overlays;
import java.io.File;
import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.jndi.NamingUtil;
import org.eclipse.jetty.overlays.OverlayedAppProvider;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.server.handler.StatisticsHandler;
public class OverlayServer
{
public static void main(String[] args) throws Exception
{
// NamingUtil.__log.setDebugEnabled(true);
String jetty_home = System.getProperty("jetty.home","target/test-classes/home");
System.setProperty("jetty.home",jetty_home);
Server server = new Server();
server.setAttribute("org.eclipse.jetty.webapp.configuration",
new String[]
{
org.eclipse.jetty.webapp.WebInfConfiguration.class.getCanonicalName(),
org.eclipse.jetty.webapp.WebXmlConfiguration.class.getCanonicalName(),
org.eclipse.jetty.webapp.MetaInfConfiguration.class.getCanonicalName(),
org.eclipse.jetty.webapp.FragmentConfiguration.class.getCanonicalName(),
org.eclipse.jetty.plus.webapp.EnvConfiguration.class.getCanonicalName(),
org.eclipse.jetty.plus.webapp.PlusConfiguration.class.getCanonicalName(),
org.eclipse.jetty.webapp.JettyWebXmlConfiguration.class.getCanonicalName(),
org.eclipse.jetty.webapp.TagLibConfiguration.class.getCanonicalName()
}
);
// Setup Connectors
ServerConnector connector = new ServerConnector(server);
connector.setPort(8080);
server.addConnector(connector);
HandlerCollection handlers = new HandlerCollection();
ContextHandlerCollection contexts = new ContextHandlerCollection();
RequestLogHandler requestLogHandler = new RequestLogHandler();
handlers.setHandlers(new Handler[]
{ contexts, new DefaultHandler(), requestLogHandler });
StatisticsHandler stats = new StatisticsHandler();
stats.setHandler(handlers);
server.setHandler(stats);
// Setup deployers
DeploymentManager deployer = new DeploymentManager();
deployer.setContexts(contexts);
server.addBean(deployer);
OverlayedAppProvider provider = new OverlayedAppProvider();
provider.setNodeName("nodeA");
provider.setScanDir(new File(jetty_home + "/overlays"));
provider.setScanInterval(2);
deployer.addAppProvider(provider);
server.setStopAtShutdown(true);
//server.setSendServerVersion(true);
// Uncomment to work with JNDI examples
// new org.eclipse.jetty.plus.jndi.Transaction(new com.atomikos.icatch.jta.UserTransactionImp());
server.start();
server.join();
}
}

View File

@ -0,0 +1,589 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.overlays;
import java.io.File;
import java.io.FileOutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.util.IO;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class OverlayedAppProviderTest
{
File _tmp;
File _scan;
File _webapps;
File _templates;
File _nodes;
File _instances;
@Before
public void before() throws Exception
{
_tmp=File.createTempFile("OAPTest",null);
if (_tmp.exists())
IO.delete(_tmp);
_tmp.mkdir();
_scan = new File(_tmp,"scan").getCanonicalFile();
_webapps = new File(_scan,OverlayedAppProvider.WEBAPPS);
_templates = new File(_scan,OverlayedAppProvider.TEMPLATES);
_nodes = new File(_scan,OverlayedAppProvider.NODES);
_instances = new File(_scan,OverlayedAppProvider.INSTANCES);
_webapps.mkdirs();
_templates.mkdir();
_nodes.mkdir();
_instances.mkdir();
}
@After
public void after() throws Exception
{
if (_tmp.exists())
IO.delete(_tmp);
}
@Test
public void testScanForWars() throws Exception
{
final ConcurrentLinkedQueue<Set<String>> scanned = new ConcurrentLinkedQueue<Set<String>>();
OverlayedAppProvider provider = new OverlayedAppProvider()
{
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.overlays.OverlayedAppProvider#updateLayers(java.util.Set)
*/
@Override
protected void updateLayers(Set<String> filenames)
{
scanned.offer(filenames);
}
};
provider.setScanInterval(0);
provider.setScanDir(_scan);
provider.start();
provider.scan();
provider.scan();
assertTrue(scanned.isEmpty());
// Check scanning for archives
File war = new File(_webapps,"foo-1.2.3.war");
touch(war);
File template = new File(_templates,"foo=foo-1.2.3.war");
touch(template);
File node = new File(_nodes,"nodeA.war");
touch(node);
File instance = new File(_instances,"foo=instance.war");
touch(instance);
provider.scan();
provider.scan();
Set<String> results = scanned.poll();
assertTrue(results!=null);
assertEquals(4,results.size());
assertTrue(results.contains("webapps/foo-1.2.3.war"));
assertTrue(results.contains("templates/foo=foo-1.2.3.war"));
assertTrue(results.contains("nodes/nodeA.war"));
assertTrue(results.contains("instances/foo=instance.war"));
provider.scan();
provider.scan();
assertTrue(scanned.isEmpty());
IO.delete(war);
IO.delete(template);
IO.delete(node);
IO.delete(instance);
provider.scan();
provider.scan();
results = scanned.poll();
assertTrue(results!=null);
assertEquals(4,results.size());
assertTrue(results.contains("webapps/foo-1.2.3.war"));
assertTrue(results.contains("templates/foo=foo-1.2.3.war"));
assertTrue(results.contains("nodes/nodeA.war"));
assertTrue(results.contains("instances/foo=instance.war"));
}
@Test
public void testScanForDirs() throws Exception
{
final ConcurrentLinkedQueue<Set<String>> scanned = new ConcurrentLinkedQueue<Set<String>>();
OverlayedAppProvider provider = new OverlayedAppProvider()
{
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.overlays.OverlayedAppProvider#updateLayers(java.util.Set)
*/
@Override
protected void updateLayers(Set<String> filenames)
{
scanned.offer(filenames);
}
};
provider.setScanInterval(0);
provider.setScanDir(_scan);
provider.start();
provider.scan();
assertTrue(scanned.isEmpty());
// Check scanning for directories
File war = new File(_webapps,"foo-1.2.3");
war.mkdir();
File template = new File(_templates,"foo=foo-1.2.3");
template.mkdir();
File node = new File(_nodes,"nodeA");
node.mkdir();
File instance = new File(_instances,"foo=instance");
instance.mkdir();
for (File f : new File[] { war,template,node,instance } )
{
File webinf = new File(f,"WEB-INF");
webinf.mkdir();
touch(webinf,"web.xml");
}
provider.scan();
provider.scan();
Set<String> results = scanned.poll();
assertTrue(results!=null);
assertEquals(4,results.size());
assertTrue(results.contains("webapps/foo-1.2.3"));
assertTrue(results.contains("templates/foo=foo-1.2.3"));
assertTrue(results.contains("nodes/nodeA"));
assertTrue(results.contains("instances/foo=instance"));
provider.scan();
provider.scan();
assertTrue(scanned.isEmpty());
// Touch everything
touch(war,"WEB-INF/web.xml");
touch(war,"WEB-INF/spring.XML");
touch(war,"WEB-INF/other");
touch(war,"WEB-INF/lib/bar.jar");
touch(war,"WEB-INF/classes/bar.class");
for (File d : new File[]{template,node,instance})
{
touch(d,"WEB-INF/web-fragment.xml");
touch(d,"WEB-INF/overlay.xml");
touch(d,"WEB-INF/other");
touch(d,"WEB-INF/lib/bar.jar");
}
provider.scan();
provider.scan();
results = scanned.poll();
assertTrue(results!=null);
assertEquals(4,results.size());
assertTrue(results.contains("webapps/foo-1.2.3"));
assertTrue(results.contains("templates/foo=foo-1.2.3"));
assertTrue(results.contains("nodes/nodeA"));
assertTrue(results.contains("instances/foo=instance"));
// Touch xml
Thread.sleep(1000); // needed so last modified is different
for (File d : new File[]{war,template,node,instance})
touch(d,"WEB-INF/web.xml");
provider.scan();
provider.scan();
results = scanned.poll();
assertTrue(results!=null);
assertEquals(4,results.size());
assertTrue(results.contains("webapps/foo-1.2.3"));
assertTrue(results.contains("templates/foo=foo-1.2.3"));
assertTrue(results.contains("nodes/nodeA"));
assertTrue(results.contains("instances/foo=instance"));
// Touch XML
Thread.sleep(1000);
for (File d : new File[]{war,template,node,instance})
touch(d,"WEB-INF/spring.XML");
provider.scan();
provider.scan();
results = scanned.poll();
assertTrue(results!=null);
assertEquals(4,results.size());
assertTrue(results.contains("webapps/foo-1.2.3"));
assertTrue(results.contains("templates/foo=foo-1.2.3"));
assertTrue(results.contains("nodes/nodeA"));
assertTrue(results.contains("instances/foo=instance"));
// Touch unrelated
for (File d : new File[]{war,template,node,instance})
touch(d,"index.html");
provider.scan();
provider.scan();
results = scanned.poll();
assertEquals(null,results);
// Touch jar
Thread.sleep(1000);
for (File d : new File[]{war,template,node,instance})
touch(d,"WEB-INF/lib/bar.jar");
provider.scan();
provider.scan();
results = scanned.poll();
assertTrue(results!=null);
assertEquals(4,results.size());
assertTrue(results.contains("webapps/foo-1.2.3"));
assertTrue(results.contains("templates/foo=foo-1.2.3"));
assertTrue(results.contains("nodes/nodeA"));
assertTrue(results.contains("instances/foo=instance"));
// touch other class
Thread.sleep(1000);
for (File d : new File[]{war,template,node,instance})
touch(d,"index.html");
provider.scan();
provider.scan();
results = scanned.poll();
assertTrue(scanned.isEmpty());
// delete all
IO.delete(war);
IO.delete(template);
IO.delete(node);
IO.delete(instance);
provider.scan();
provider.scan();
results = scanned.poll();
assertTrue(results!=null);
assertEquals(4,results.size());
assertTrue(results.contains("webapps/foo-1.2.3"));
assertTrue(results.contains("templates/foo=foo-1.2.3"));
assertTrue(results.contains("nodes/nodeA"));
assertTrue(results.contains("instances/foo=instance"));
}
@Test
public void testTriageURI() throws Exception
{
final BlockingQueue<String> scanned = new LinkedBlockingQueue<String>();
OverlayedAppProvider provider = new OverlayedAppProvider()
{
protected void removeInstance(String name)
{
scanned.add("removeInstance "+name);
}
protected Instance loadInstance(String name, File origin)
{
scanned.add("loadInstance "+name);
scanned.add(origin.getAbsolutePath());
return null;
}
protected void removeNode()
{
scanned.add("removeNode");
}
protected Node loadNode(File origin)
{
scanned.add("loadNode");
scanned.add(origin.getAbsolutePath());
return null;
}
protected void removeTemplate(String name)
{
scanned.add("removeTemplate "+name);
}
protected Template loadTemplate(String name, File origin)
{
scanned.add("loadTemplate "+name);
scanned.add(origin.getAbsolutePath());
return null;
}
protected void removeWebapp(String name)
{
scanned.add("removeWebapp "+name);
}
protected Webapp loadWebapp(String name, File origin)
{
scanned.add("loadWebapp "+name);
scanned.add(origin.getAbsolutePath());
return null;
}
protected void redeploy()
{
}
};
provider.setScanInterval(0);
provider.setNodeName("nodeA");
provider.setScanDir(_scan);
provider.start();
provider.scan();
assertTrue(scanned.isEmpty());
// Add a war
File war = new File(_webapps,"foo-1.2.3.war");
touch(war);
provider.scan();
provider.scan();
assertEquals("loadWebapp foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS));
assertEquals(war.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS));
// Add a template
File template = new File(_templates,"foo=foo-1.2.3.war");
touch(template);
provider.scan();
provider.scan();
assertEquals("loadTemplate foo=foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS));
assertEquals(template.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS));
// Add a node
File nodeA = new File(_nodes,"nodeA.war");
touch(nodeA);
provider.scan();
provider.scan();
assertEquals("loadNode",scanned.poll(1,TimeUnit.SECONDS));
assertEquals(nodeA.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS));
// Add another node
File nodeB = new File(_nodes,"nodeB.war");
provider.scan();
provider.scan();
assertTrue(scanned.isEmpty());
// Add an instance
File instance = new File(_instances,"foo=instance.war");
touch(instance);
provider.scan();
provider.scan();
assertEquals("loadInstance foo=instance",scanned.poll(1,TimeUnit.SECONDS));
assertEquals(instance.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS));
// Add a war dir
File warDir = new File(_webapps,"foo-1.2.3");
warDir.mkdir();
File warDirWI = new File(warDir,"WEB-INF");
warDirWI.mkdir();
touch(warDirWI,"web.xml");
provider.scan();
provider.scan();
assertEquals("loadWebapp foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS));
assertEquals(warDir.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS));
// Add a template dir
File templateDir = new File(_templates,"foo=foo-1.2.3");
templateDir.mkdir();
File templateDirWI = new File(templateDir,"WEB-INF");
templateDirWI.mkdir();
touch(templateDirWI,"web.xml");
provider.scan();
provider.scan();
assertEquals("loadTemplate foo=foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS));
assertEquals(templateDir.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS));
// Add a node dir
File nodeADir = new File(_nodes,"nodeA");
nodeADir.mkdir();
File nodeADirWI = new File(nodeADir,"WEB-INF");
nodeADirWI.mkdir();
touch(nodeADirWI,"web.xml");
provider.scan();
provider.scan();
assertEquals("loadNode",scanned.poll(1,TimeUnit.SECONDS));
assertEquals(nodeADir.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS));
// Add another node dir
File nodeBDir = new File(_nodes,"nodeB");
nodeBDir.mkdir();
File nodeBDirWI = new File(nodeBDir,"WEB-INF");
nodeBDirWI.mkdir();
touch(nodeBDirWI,"web.xml");
provider.scan();
provider.scan();
assertTrue(scanned.isEmpty());
// Add an instance dir
File instanceDir = new File(_instances,"foo=instance");
instanceDir.mkdir();
File instanceDirWI = new File(instanceDir,"WEB-INF");
instanceDirWI.mkdir();
touch(instanceDirWI,"web.xml");
provider.scan();
provider.scan();
assertEquals("loadInstance foo=instance",scanned.poll(1,TimeUnit.SECONDS));
assertEquals(instanceDir.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS));
// touch archives will be ignored.
Thread.sleep(1000);
touch(war);
touch(template);
touch(nodeA);
touch(nodeB);
touch(instance);
provider.scan();
provider.scan();
assertTrue(scanned.isEmpty());
// Touch directories
for (File d : new File[]{warDir,templateDir,nodeADir,nodeBDir,instanceDir})
touch(d,"WEB-INF/web.xml");
provider.scan();
provider.scan();
assertEquals(8,scanned.size());
scanned.clear();
// Remove web dir
IO.delete(warDir);
provider.scan();
provider.scan();
assertEquals("removeWebapp foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS));
assertEquals("loadWebapp foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS));
assertEquals(war.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS));
// Remove template dir
IO.delete(templateDir);
provider.scan();
provider.scan();
assertEquals("removeTemplate foo=foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS));
assertEquals("loadTemplate foo=foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS));
assertEquals(template.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS));
// Remove nodeA dir
IO.delete(nodeADir);
provider.scan();
provider.scan();
assertEquals("removeNode",scanned.poll(1,TimeUnit.SECONDS));
assertEquals("loadNode",scanned.poll(1,TimeUnit.SECONDS));
assertEquals(nodeA.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS));
// Remove nodeB dir
IO.delete(nodeBDir);
provider.scan();
provider.scan();
assertTrue(scanned.isEmpty());
// Remove instance dir
IO.delete(instanceDir);
provider.scan();
provider.scan();
assertEquals("removeInstance foo=instance",scanned.poll(1,TimeUnit.SECONDS));
assertEquals("loadInstance foo=instance",scanned.poll(1,TimeUnit.SECONDS));
assertEquals(instance.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS));
// Remove web
IO.delete(war);
provider.scan();
provider.scan();
assertEquals("removeWebapp foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS));
// Remove template
IO.delete(template);
provider.scan();
provider.scan();
assertEquals("removeTemplate foo=foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS));
// Remove nodeA dir
IO.delete(nodeA);
provider.scan();
provider.scan();
assertEquals("removeNode",scanned.poll(1,TimeUnit.SECONDS));
// Remove nodeB dir
IO.delete(nodeB);
provider.scan();
provider.scan();
assertTrue(scanned.isEmpty());
// Remove instance dir
IO.delete(instance);
provider.scan();
provider.scan();
assertEquals("removeInstance foo=instance",scanned.poll(1,TimeUnit.SECONDS));
provider.scan();
provider.scan();
assertTrue(scanned.isEmpty());
}
private void touch(File base,String path)
{
try
{
File target = new File(new URI(base.toURI().toString()+path));
target.getParentFile().mkdirs();
touch(target);
}
catch (URISyntaxException e)
{
e.printStackTrace();
}
}
private void touch(File file)
{
try
{
IO.delete(file);
FileOutputStream out = new FileOutputStream(file,false);
out.write("<h1>Hello</h1>".getBytes());
out.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}

View File

@ -0,0 +1 @@
instance myfoo=blue WEB-INF classes

View File

@ -0,0 +1 @@
instance myfoo=blue WEB-INF classes

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/blue</Set>
<!--
<Set name="virtualHosts">
<Array type="String">
<Item>blue.myVirtualDomain.com</Item>
</Array>
</Set>
-->
</Configure>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Blue Test WebApp</display-name>
<context-param>
<param-name>overlay</param-name>
<param-value>instances/myfoo=blue/web.xml</param-value>
</context-param>
<context-param>
<param-name>instance</param-name>
<param-value>instances/myfoo=blue/web.xml</param-value>
</context-param>
</web-app>

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Created-By: 1.6.0_20 (Sun Microsystems Inc.)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1 @@
instance myfoo=blue WEB-INF classes

View File

@ -0,0 +1 @@
instance myfoo=blue WEB-INF classes

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1 @@
instance myfoo=green WEB-INF classes

View File

@ -0,0 +1 @@
instance myfoo=green WEB-INF classes

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/green</Set>
<!--
<Set name="virtualHosts">
<Array type="String">
<Item>green.myVirtualDomain.com</Item>
</Array>
</Set>
-->
</Configure>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Green Test WebApp</display-name>
<context-param>
<param-name>overlay</param-name>
<param-value>instances/myfoo=green/web.xml</param-value>
</context-param>
<context-param>
<param-name>instance</param-name>
<param-value>instances/myfoo=green/web.xml</param-value>
</context-param>
</web-app>

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Created-By: 1.6.0_20 (Sun Microsystems Inc.)

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1 @@
instance myfoo=green WEB-INF classes

View File

@ -0,0 +1 @@
instance myfoo=green WEB-INF classes

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1 @@
instance myfoo=red WEB-INF classes

View File

@ -0,0 +1 @@
instance myfoo=red WEB-INF classes

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/red</Set>
<!--
<Set name="virtualHosts">
<Array type="String">
<Item>red.myVirtualDomain.com</Item>
</Array>
</Set>
-->
</Configure>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Red Test WebApp</display-name>
<context-param>
<param-name>overlay</param-name>
<param-value>instances/myfoo=red/web.xml</param-value>
</context-param>
<context-param>
<param-name>instance</param-name>
<param-value>instances/myfoo=red/web.xml</param-value>
</context-param>
</web-app>

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Created-By: 1.6.0_20 (Sun Microsystems Inc.)

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -0,0 +1 @@
instance myfoo=red WEB-INF classes

View File

@ -0,0 +1 @@
instance myfoo=red WEB-INF classes

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure class="org.eclipse.jetty.server.handler.ContextHandler">
<!--
<Set name="virtualHosts">
<Array type="String">
<Item>red.myVirtualDomain.com</Item>
</Array>
</Set>
-->
</Configure>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<context-param>
<param-name>overlay</param-name>
<param-value>nodes/nodeA/web.xml</param-value>
</context-param>
<context-param>
<param-name>node</param-name>
<param-value>nodes/nodeA/web.xml</param-value>
</context-param>
</web-app>

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Created-By: 1.6.0_20 (Sun Microsystems Inc.)

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Created-By: 1.6.0_20 (Sun Microsystems Inc.)

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<context-param>
<param-name>overlay</param-name>
<param-value>nodes/nodeB/web.xml</param-value>
</context-param>
<context-param>
<param-name>node</param-name>
<param-value>nodes/nodeB/web.xml</param-value>
</context-param>
</web-app>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Call class="org.eclipse.jetty.util.log.Log" name="info"><Arg>Executing jetty-web.xml for <Property name="overlay.instance"/></Arg></Call>
</Configure>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure class="org.eclipse.jetty.overlays.TemplateContext">
<Set name="parentLoaderPriority" type="boolean">false</Set>
<Get name="resourceCache">
<Set name="useFileMappedBuffer">true</Set>
<Set name="maxCachedFileSize">10000000</Set>
<Set name="maxCachedFiles">1000</Set>
<Set name="maxCacheSize">64000000</Set>
</Get>
<Get name="mimeTypes">
<Call name="addMimeMapping">
<Arg>bogus</Arg>
<Arg>application/bogon</Arg>
</Call>
</Get>
</Configure>

View File

@ -0,0 +1,482 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- ===================================================================== -->
<!-- This file contains the default descriptor for web applications. -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- The intent of this descriptor is to include jetty specific or common -->
<!-- configuration for all webapps. If a context has a webdefault.xml -->
<!-- descriptor, it is applied before the contexts own web.xml file -->
<!-- -->
<!-- A context may be assigned a default descriptor by: -->
<!-- + Calling WebApplicationContext.setDefaultsDescriptor -->
<!-- + Passed an arg to addWebApplications -->
<!-- -->
<!-- This file is used both as the resource within the jetty.jar (which is -->
<!-- used as the default if no explicit defaults descriptor is set) and it -->
<!-- is copied to the etc directory of the Jetty distro and explicitly -->
<!-- by the jetty.xml file. -->
<!-- -->
<!-- ===================================================================== -->
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
metadata-complete="true"
version="2.5"
>
<description>
Default web.xml file.
This file is applied to a Web application before it's own WEB_INF/web.xml file
</description>
<!-- ==================================================================== -->
<!-- Context params to control Session Cookies -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!--
UNCOMMENT TO ACTIVATE <context-param> <param-name>org.eclipse.jetty.servlet.SessionDomain</param-name> <param-value>127.0.0.1</param-value> </context-param> <context-param>
<param-name>org.eclipse.jetty.servlet.SessionPath</param-name> <param-value>/</param-value> </context-param> <context-param> <param-name>org.eclipse.jetty.servlet.MaxAge</param-name>
<param-value>-1</param-value> </context-param>
-->
<!-- ==================================================================== -->
<!-- The default servlet. -->
<!-- This servlet, normally mapped to /, provides the handling for static -->
<!-- content, OPTIONS and TRACE methods for the context. -->
<!-- The following initParameters are supported: -->
<!--
* acceptRanges If true, range requests and responses are
* supported
*
* dirAllowed If true, directory listings are returned if no
* welcome file is found. Else 403 Forbidden.
*
* welcomeServlets If true, attempt to dispatch to welcome files
* that are servlets, but only after no matching static
* resources could be found. If false, then a welcome
* file must exist on disk. If "exact", then exact
* servlet matches are supported without an existing file.
* Default is true.
*
* This must be false if you want directory listings,
* but have index.jsp in your welcome file list.
*
* redirectWelcome If true, welcome files are redirected rather than
* forwarded to.
*
* gzip If set to true, then static content will be served as
* gzip content encoded if a matching resource is
* found ending with ".gz"
*
* resourceBase Set to replace the context resource base
*
* resourceCache If set, this is a context attribute name, which the servlet
* will use to look for a shared ResourceCache instance.
*
* relativeResourceBase
* Set with a pathname relative to the base of the
* servlet context root. Useful for only serving static content out
* of only specific subdirectories.
*
* aliases If True, aliases of resources are allowed (eg. symbolic
* links and caps variations). May bypass security constraints.
*
* maxCacheSize The maximum total size of the cache or 0 for no cache.
* maxCachedFileSize The maximum size of a file to cache
* maxCachedFiles The maximum number of files to cache
*
* useFileMappedBuffer
* If set to true, it will use mapped file buffer to serve static content
* when using NIO connector. Setting this value to false means that
* a direct buffer will be used instead of a mapped file buffer.
* By default, this is set to true.
*
* cacheControl If set, all static content will have this value set as the cache-control
* header.
-->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
<init-param>
<param-name>aliases</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>acceptRanges</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>dirAllowed</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>welcomeServlets</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>redirectWelcome</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>maxCacheSize</param-name>
<param-value>256000000</param-value>
</init-param>
<init-param>
<param-name>maxCachedFileSize</param-name>
<param-value>10000000</param-value>
</init-param>
<init-param>
<param-name>maxCachedFiles</param-name>
<param-value>2048</param-value>
</init-param>
<init-param>
<param-name>gzip</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>useFileMappedBuffer</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>resourceCache</param-name>
<param-value>org.eclipse.jetty.server.ResourceCache</param-value>
</init-param>
<!--
<init-param>
<param-name>cacheControl</param-name>
<param-value>max-age=3600,public</param-value>
</init-param>
-->
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- ==================================================================== -->
<!-- JSP Servlet -->
<!-- This is the jasper JSP servlet from the jakarta project -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- The JSP page compiler and execution servlet, which is the mechanism -->
<!-- used by Glassfish to support JSP pages. Traditionally, this servlet -->
<!-- is mapped to URL patterh "*.jsp". This servlet supports the -->
<!-- following initialization parameters (default values are in square -->
<!-- brackets): -->
<!-- -->
<!-- checkInterval If development is false and reloading is true, -->
<!-- background compiles are enabled. checkInterval -->
<!-- is the time in seconds between checks to see -->
<!-- if a JSP page needs to be recompiled. [300] -->
<!-- -->
<!-- compiler Which compiler Ant should use to compile JSP -->
<!-- pages. See the Ant documenation for more -->
<!-- information. [javac] -->
<!-- -->
<!-- classdebuginfo Should the class file be compiled with -->
<!-- debugging information? [true] -->
<!-- -->
<!-- classpath What class path should I use while compiling -->
<!-- generated servlets? [Created dynamically -->
<!-- based on the current web application] -->
<!-- Set to ? to make the container explicitly set -->
<!-- this parameter. -->
<!-- -->
<!-- development Is Jasper used in development mode (will check -->
<!-- for JSP modification on every access)? [true] -->
<!-- -->
<!-- enablePooling Determines whether tag handler pooling is -->
<!-- enabled [true] -->
<!-- -->
<!-- fork Tell Ant to fork compiles of JSP pages so that -->
<!-- a separate JVM is used for JSP page compiles -->
<!-- from the one Tomcat is running in. [true] -->
<!-- -->
<!-- ieClassId The class-id value to be sent to Internet -->
<!-- Explorer when using <jsp:plugin> tags. -->
<!-- [clsid:8AD9C840-044E-11D1-B3E9-00805F499D93] -->
<!-- -->
<!-- javaEncoding Java file encoding to use for generating java -->
<!-- source files. [UTF-8] -->
<!-- -->
<!-- keepgenerated Should we keep the generated Java source code -->
<!-- for each page instead of deleting it? [true] -->
<!-- -->
<!-- logVerbosityLevel The level of detailed messages to be produced -->
<!-- by this servlet. Increasing levels cause the -->
<!-- generation of more messages. Valid values are -->
<!-- FATAL, ERROR, WARNING, INFORMATION, and DEBUG. -->
<!-- [WARNING] -->
<!-- -->
<!-- mappedfile Should we generate static content with one -->
<!-- print statement per input line, to ease -->
<!-- debugging? [false] -->
<!-- -->
<!-- -->
<!-- reloading Should Jasper check for modified JSPs? [true] -->
<!-- -->
<!-- suppressSmap Should the generation of SMAP info for JSR45 -->
<!-- debugging be suppressed? [false] -->
<!-- -->
<!-- dumpSmap Should the SMAP info for JSR45 debugging be -->
<!-- dumped to a file? [false] -->
<!-- False if suppressSmap is true -->
<!-- -->
<!-- scratchdir What scratch directory should we use when -->
<!-- compiling JSP pages? [default work directory -->
<!-- for the current web application] -->
<!-- -->
<!-- tagpoolMaxSize The maximum tag handler pool size [5] -->
<!-- -->
<!-- xpoweredBy Determines whether X-Powered-By response -->
<!-- header is added by generated servlet [false] -->
<!-- -->
<!-- If you wish to use Jikes to compile JSP pages: -->
<!-- Set the init parameter "compiler" to "jikes". Define -->
<!-- the property "-Dbuild.compiler.emacs=true" when starting Jetty -->
<!-- to cause Jikes to emit error messages in a format compatible with -->
<!-- Jasper. -->
<!-- If you get an error reporting that jikes can't use UTF-8 encoding, -->
<!-- try setting the init parameter "javaEncoding" to "ISO-8859-1". -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<servlet
id="jsp"
>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>logVerbosityLevel</param-name>
<param-value>DEBUG</param-value>
</init-param>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<!--
<init-param>
<param-name>classpath</param-name>
<param-value>?</param-value>
</init-param>
-->
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspf</url-pattern>
<url-pattern>*.jspx</url-pattern>
<url-pattern>*.xsp</url-pattern>
<url-pattern>*.JSP</url-pattern>
<url-pattern>*.JSPF</url-pattern>
<url-pattern>*.JSPX</url-pattern>
<url-pattern>*.XSP</url-pattern>
</servlet-mapping>
<!-- ==================================================================== -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<!-- ==================================================================== -->
<!-- Default MIME mappings -->
<!-- The default MIME mappings are provided by the mime.properties -->
<!-- resource in the org.eclipse.jetty.server.jar file. Additional or modified -->
<!-- mappings may be specified here -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- UNCOMMENT TO ACTIVATE
<mime-mapping>
<extension>mysuffix</extension>
<mime-type>mymime/type</mime-type>
</mime-mapping>
-->
<!-- ==================================================================== -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>
<!-- ==================================================================== -->
<locale-encoding-mapping-list>
<locale-encoding-mapping>
<locale>ar</locale>
<encoding>ISO-8859-6</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>be</locale>
<encoding>ISO-8859-5</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>bg</locale>
<encoding>ISO-8859-5</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>ca</locale>
<encoding>ISO-8859-1</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>cs</locale>
<encoding>ISO-8859-2</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>da</locale>
<encoding>ISO-8859-1</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>de</locale>
<encoding>ISO-8859-1</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>el</locale>
<encoding>ISO-8859-7</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>en</locale>
<encoding>ISO-8859-1</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>es</locale>
<encoding>ISO-8859-1</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>et</locale>
<encoding>ISO-8859-1</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>fi</locale>
<encoding>ISO-8859-1</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>fr</locale>
<encoding>ISO-8859-1</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>hr</locale>
<encoding>ISO-8859-2</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>hu</locale>
<encoding>ISO-8859-2</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>is</locale>
<encoding>ISO-8859-1</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>it</locale>
<encoding>ISO-8859-1</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>iw</locale>
<encoding>ISO-8859-8</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>ja</locale>
<encoding>Shift_JIS</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>ko</locale>
<encoding>EUC-KR</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>lt</locale>
<encoding>ISO-8859-2</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>lv</locale>
<encoding>ISO-8859-2</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>mk</locale>
<encoding>ISO-8859-5</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>nl</locale>
<encoding>ISO-8859-1</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>no</locale>
<encoding>ISO-8859-1</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>pl</locale>
<encoding>ISO-8859-2</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>pt</locale>
<encoding>ISO-8859-1</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>ro</locale>
<encoding>ISO-8859-2</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>ru</locale>
<encoding>ISO-8859-5</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>sh</locale>
<encoding>ISO-8859-5</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>sk</locale>
<encoding>ISO-8859-2</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>sl</locale>
<encoding>ISO-8859-2</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>sq</locale>
<encoding>ISO-8859-2</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>sr</locale>
<encoding>ISO-8859-5</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>sv</locale>
<encoding>ISO-8859-1</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>tr</locale>
<encoding>ISO-8859-9</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>uk</locale>
<encoding>ISO-8859-5</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>zh</locale>
<encoding>GB2312</encoding>
</locale-encoding-mapping>
<locale-encoding-mapping>
<locale>zh_TW</locale>
<encoding>Big5</encoding>
</locale-encoding-mapping>
</locale-encoding-mapping-list>
<security-constraint>
<web-resource-collection>
<web-resource-name>Disable TRACE</web-resource-name>
<url-pattern>/</url-pattern>
<http-method>TRACE</http-method>
</web-resource-collection>
<auth-constraint/>
</security-constraint>
</web-app>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Templated Test WebApp</display-name>
<context-param>
<param-name>overlay</param-name>
<param-value>templates/myfoo/web.xml</param-value>
</context-param>
<context-param>
<param-name>template</param-name>
<param-value>templates/myfoo/web.xml</param-value>
</context-param>
<context-param>
<param-name>overlay.template</param-name>
<param-value>${overlay.template}</param-value>
</context-param>
<context-param>
<param-name>overlay.template.name</param-name>
<param-value>${overlay.template.name}</param-value>
</context-param>
<context-param>
<param-name>overlay.template.classifier</param-name>
<param-value>${overlay.template.classifier}</param-value>
</context-param>
<context-param>
<param-name>overlay.instance.classifier</param-name>
<param-value>${overlay.instance.classifier}</param-value>
</context-param>
<context-param>
<param-name>overlay.instance</param-name>
<param-value>${overlay.instance}</param-value>
</context-param>
</web-app>

View File

@ -0,0 +1,10 @@
<h1>Template foo webapp</h1>
<img src=logo.png></img>
Should see index.jsp instead of this!!!
<p>
<a href="/red">Red</a>,
<a href="/blue">Blue</a>,
<a href="/green">Green</a>

View File

@ -0,0 +1,54 @@
<%@page import="java.io.BufferedReader"%>
<%@page import="java.io.InputStreamReader"%>
<%@page import="java.util.Enumeration"%>
<h1><%=application.getServletContextName()%></h1>
<img src=logo.png></img>
<p>
<a href="/red">Red</a>,
<a href="/blue">Blue</a>,
<a href="/green">Green</a>
<p>
<h3>Overlays</h3>
webapp=<%=application.getInitParameter("webapp")%><br/>
template=<%=application.getInitParameter("template")%><br/>
node=<%=application.getInitParameter("node")%><br/>
instance=<%=application.getInitParameter("instance")%><br/>
<h3>Init Parameters</h3>
<%
Enumeration e=application.getInitParameterNames();
while (e.hasMoreElements())
{
String name=e.nextElement().toString();
String value=application.getInitParameter(name);
out.println(name+": "+value+"<br/>");
}
%>
<h3>Attributes</h3>
<%
e=application.getAttributeNames();
while (e.hasMoreElements())
{
String name=e.nextElement().toString();
String value=String.valueOf(application.getAttribute(name));
out.println(name+": "+value+"<br/>");
}
%>
<h3>Resources</h3>
<%
ClassLoader loader = Thread.currentThread().getContextClassLoader();
%>
resourceA.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceA.txt").openStream())).readLine()%><br/>
resourceB.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceB.txt").openStream())).readLine()%><br/>
resourceC.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceC.txt").openStream())).readLine()%><br/>
resourceD.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceD.txt").openStream())).readLine()%><br/>
resourceE.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceE.txt").openStream())).readLine()%><br/>
resourceF.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceF.txt").openStream())).readLine()%><br/>
resourceG.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceG.txt").openStream())).readLine()%><br/>
resourceH.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceH.txt").openStream())).readLine()%><br/>
resourceI.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceI.txt").openStream())).readLine()%><br/>
resourceJ.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceJ.txt").openStream())).readLine()%><br/>
resourceK.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceK.txt").openStream())).readLine()%><br/>

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Created-By: 1.6.0_20 (Sun Microsystems Inc.)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,10 @@
<h1>Template foo webapp</h1>
<img src=logo.png></img>
Should see index.jsp instead of this!!!
<p>
<a href="/red">Red</a>,
<a href="/blue">Blue</a>,
<a href="/green">Green</a>

View File

@ -0,0 +1,54 @@
<%@page import="java.io.BufferedReader"%>
<%@page import="java.io.InputStreamReader"%>
<%@page import="java.util.Enumeration"%>
<h1><%=application.getServletContextName()%></h1>
<img src=logo.png></img>
<p>
<a href="/red">Red</a>,
<a href="/blue">Blue</a>,
<a href="/green">Green</a>
<p>
<h3>Overlays</h3>
webapp=<%=application.getInitParameter("webapp")%><br/>
template=<%=application.getInitParameter("template")%><br/>
node=<%=application.getInitParameter("node")%><br/>
instance=<%=application.getInitParameter("instance")%><br/>
<h3>Init Parameters</h3>
<%
Enumeration e=application.getInitParameterNames();
while (e.hasMoreElements())
{
String name=e.nextElement().toString();
String value=application.getInitParameter(name);
out.println(name+": "+value+"<br/>");
}
%>
<h3>Attributes</h3>
<%
e=application.getAttributeNames();
while (e.hasMoreElements())
{
String name=e.nextElement().toString();
String value=String.valueOf(application.getAttribute(name));
out.println(name+": "+value+"<br/>");
}
%>
<h3>Resources</h3>
<%
ClassLoader loader = Thread.currentThread().getContextClassLoader();
%>
resourceA.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceA.txt").openStream())).readLine()%><br/>
resourceB.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceB.txt").openStream())).readLine()%><br/>
resourceC.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceC.txt").openStream())).readLine()%><br/>
resourceD.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceD.txt").openStream())).readLine()%><br/>
resourceE.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceE.txt").openStream())).readLine()%><br/>
resourceF.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceF.txt").openStream())).readLine()%><br/>
resourceG.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceG.txt").openStream())).readLine()%><br/>
resourceH.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceH.txt").openStream())).readLine()%><br/>
resourceI.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceI.txt").openStream())).readLine()%><br/>
resourceJ.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceJ.txt").openStream())).readLine()%><br/>
resourceK.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceK.txt").openStream())).readLine()%><br/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.eclipse.org/configure.dtd">
<Configure class="org.eclipse.jetty.server.handler.ContextHandler">
<Set name="contextPath">/</Set>
<Set name="handler">
<New class="org.eclipse.jetty.server.handler.ResourceHandler">
<Set name="welcomeFiles">
<Array type="String">
<Item>index.html</Item>
</Array>
</Set>
<Set name="cacheControl">max-age=3600,public</Set>
</New>
</Set>
</Configure>

View File

@ -0,0 +1,7 @@
<h1>Cloudtide Deployer Demo</h1>
<p>
<a href="/red">Red</a>,
<a href="/blue">Blue</a>,
<a href="/green">Green</a>

View File

@ -0,0 +1,7 @@
<h1>Cloudtide Deployer Demo</h1>
<p>
<a href="/red">Red</a>,
<a href="/blue">Blue</a>,
<a href="/green">Green</a>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Test WebApp</display-name>
<context-param>
<param-name>overlay</param-name>
<param-value>webapps/foo/WEB-INF/web.xml</param-value>
</context-param>
<context-param>
<param-name>webapp</param-name>
<param-value>webapps/foo-INF/web.xml</param-value>
</context-param>
</web-app>

View File

@ -0,0 +1,2 @@
<h1>foo webapp</h1>

View File

@ -68,6 +68,7 @@ import org.eclipse.jetty.toolchain.test.annotation.Slow;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.StdErrLog;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Assert;
@ -233,6 +234,17 @@ public class ProxyServletTest
public void testProxyWithResponseContent() throws Exception
{
prepareProxy(new ProxyServlet());
HttpClient result = new HttpClient();
result.setProxyConfiguration(new ProxyConfiguration("localhost", proxyConnector.getLocalPort()));
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setName("foo");
threadPool.setMaxThreads(2);
result.setExecutor(threadPool);
result.start();
ContentResponse[] responses = new ContentResponse[10];
final byte[] content = new byte[1024];
Arrays.fill(content, (byte)'A');
prepareServer(new HttpServlet()
@ -246,14 +258,22 @@ public class ProxyServletTest
}
});
// Request is for the target server
ContentResponse response = client.newRequest("localhost", serverConnector.getLocalPort())
.timeout(5, TimeUnit.SECONDS)
.send();
for ( int i = 0; i < 10; ++i )
{
// Request is for the target server
responses[i] = result.newRequest("localhost", serverConnector.getLocalPort())
.timeout(5, TimeUnit.SECONDS)
.send();
}
for ( int i = 0; i < 10; ++i )
{
Assert.assertEquals(200, response.getStatus());
Assert.assertTrue(response.getHeaders().containsKey(PROXIED_HEADER));
Assert.assertArrayEquals(content, response.getContent());
Assert.assertEquals(200, responses[i].getStatus());
Assert.assertTrue(responses[i].getHeaders().containsKey(PROXIED_HEADER));
Assert.assertArrayEquals(content, responses[i].getContent());
}
}
@Test

View File

@ -456,6 +456,7 @@
<module>jetty-rhttp</module>
<module>jetty-http-spi</module>
-->
<module>jetty-overlay-deployer</module>
</modules>
<dependencyManagement>
<dependencies>