Merge remote-tracking branch 'origin/master' into servlet-3.1-api
Conflicts: jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
This commit is contained in:
commit
942f8a5c40
55
VERSION.txt
55
VERSION.txt
|
@ -1,3 +1,5 @@
|
|||
jetty-9.0.4-SNAPSHOT
|
||||
|
||||
jetty-9.0.3.v20130506 06 May 2013
|
||||
+ 404010 fix cast exception in mongodb session manager
|
||||
+ 404911 WebSocketCloseTest fails spuriously
|
||||
|
@ -164,6 +166,34 @@ jetty-9.0.0.v20130308 - 08 March 2013
|
|||
+ 402757 WebSocket client module can't be used with WebSocket server module in
|
||||
the same WAR
|
||||
|
||||
jetty-8.1.11.v20130520 - 20 May 2013
|
||||
+ 402844 STOP.PORT & STOP.KEY behaviour has changed
|
||||
+ 403281 jetty.sh waits for started or failure before returning
|
||||
+ 403513 jetty:run goal cannot be executed twice during the maven build
|
||||
+ 403570 Asynchronous Request Logging
|
||||
+ 404010 fix cast exception in mongodb session manager
|
||||
+ 404128 Add Vary headers rather than set them
|
||||
+ 404283 org.eclipse.jetty.util.Scanner.scanFile() dies with an NPE if
|
||||
listFiles() returns null
|
||||
+ 404325 data constraint redirection does send default port
|
||||
+ 404517 Close connection if request received after half close
|
||||
+ 404789 Support IPv6 addresses in DoSFilter white list.
|
||||
+ 404958 Fixed Resource.newSystemResource striped / handling
|
||||
+ 405281 allow filemappedbuffers to not be used
|
||||
+ 405537 NPE in rendering JSP using SPDY and wrapped ServletRequest
|
||||
+ 406437 Digest Auth supports out of order nc
|
||||
+ 406618 Jetty startup in OSGi Equinox fails when using option
|
||||
jetty.home.bundle=org.eclipse.jetty.osgi.boot
|
||||
+ 406923 CR line termination
|
||||
+ 407136 @PreDestroy called after Servlet.destroy()
|
||||
+ 407173 java.lang.IllegalStateException: null when using JDBCSessionManager
|
||||
+ 407931 Add toggle for failing on servlet availability
|
||||
+ 407976 JDBCSessionIdManager potentially leaves server in bad state after
|
||||
startup
|
||||
+ 408077 HashSessionManager leaves file handles open after being stopped
|
||||
+ 408446 Multipart parsing issue with boundry and charset in ContentType
|
||||
header
|
||||
|
||||
jetty-8.1.10.v20130312 - 12 March 2013
|
||||
+ 376273 Early EOF because of SSL Protocol Error on
|
||||
https://api-3t.paypal.com/nvp.
|
||||
|
@ -200,6 +230,31 @@ jetty-8.1.10.v20130312 - 12 March 2013
|
|||
+ 402833 Test harness for global error page and hide exception message from
|
||||
reason string
|
||||
|
||||
jetty-7.6.11.v20130520 - 20 May 2013
|
||||
+ 402844 STOP.PORT & STOP.KEY behaviour has changed
|
||||
+ 403281 jetty.sh waits for started or failure before returning
|
||||
+ 403513 jetty:run goal cannot be executed twice during the maven build
|
||||
+ 403570 Asynchronous Request Logging
|
||||
+ 404010 fix cast exception in mongodb session manager
|
||||
+ 404128 Add Vary headers rather than set them
|
||||
+ 404283 org.eclipse.jetty.util.Scanner.scanFile() dies with an NPE if
|
||||
listFiles() returns null
|
||||
+ 404325 data constraint redirection does send default port
|
||||
+ 404517 Close connection if request received after half close
|
||||
+ 404789 Support IPv6 addresses in DoSFilter white list.
|
||||
+ 404958 Fixed Resource.newSystemResource striped / handling
|
||||
+ 405281 allow filemappedbuffers to not be used
|
||||
+ 405537 NPE in rendering JSP using SPDY and wrapped ServletRequest
|
||||
+ 406437 Digest Auth supports out of order nc
|
||||
+ 406923 CR line termination
|
||||
+ 407136 @PreDestroy called after Servlet.destroy()
|
||||
+ 407173 java.lang.IllegalStateException: null when using JDBCSessionManager
|
||||
+ 407976 JDBCSessionIdManager potentially leaves server in bad state after
|
||||
startup
|
||||
+ 408077 HashSessionManager leaves file handles open after being stopped
|
||||
+ 408446 Multipart parsing issue with boundry and charset in ContentType
|
||||
header
|
||||
|
||||
jetty-7.6.10.v20130312 - 12 March 2013
|
||||
+ 376273 Early EOF because of SSL Protocol Error on
|
||||
https://api-3t.paypal.com/nvp.
|
||||
|
|
|
@ -21,11 +21,20 @@ package org.eclipse.jetty.ant;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Array;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.security.CodeSource;
|
||||
import java.security.PermissionCollection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
|
@ -44,6 +53,8 @@ import org.eclipse.jetty.server.handler.ContextHandler;
|
|||
import org.eclipse.jetty.servlet.Holder;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.webapp.Configuration;
|
||||
import org.eclipse.jetty.webapp.FragmentConfiguration;
|
||||
|
@ -65,6 +76,8 @@ import org.eclipse.jetty.xml.XmlConfiguration;
|
|||
*/
|
||||
public class AntWebAppContext extends WebAppContext
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WebAppContext.class);
|
||||
|
||||
public final AntWebInfConfiguration antWebInfConfiguration = new AntWebInfConfiguration();
|
||||
public final WebXmlConfiguration webXmlConfiguration = new WebXmlConfiguration();
|
||||
public final MetaInfConfiguration metaInfConfiguration = new MetaInfConfiguration();
|
||||
|
@ -142,6 +155,184 @@ public class AntWebAppContext extends WebAppContext
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* AntURLClassLoader
|
||||
*
|
||||
* Adapt the AntClassLoader which is not a URLClassLoader - this is needed for
|
||||
* jsp to be able to search the classpath.
|
||||
*/
|
||||
public static class AntURLClassLoader extends URLClassLoader
|
||||
{
|
||||
private AntClassLoader antLoader;
|
||||
|
||||
public AntURLClassLoader(AntClassLoader antLoader)
|
||||
{
|
||||
super(new URL[] {}, antLoader);
|
||||
this.antLoader = antLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResourceAsStream(String name)
|
||||
{
|
||||
return super.getResourceAsStream(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
super.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addURL(URL url)
|
||||
{
|
||||
super.addURL(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL[] getURLs()
|
||||
{
|
||||
Set<URL> urls = new HashSet<URL>();
|
||||
|
||||
//convert urls from antLoader
|
||||
String[] paths = antLoader.getClasspath().split(new String(new char[]{File.pathSeparatorChar}));
|
||||
if (paths != null)
|
||||
{
|
||||
for (String p:paths)
|
||||
{
|
||||
File f = new File(p);
|
||||
try
|
||||
{
|
||||
urls.add(f.toURI().toURL());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.ignore(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//add in any that may have been added to us as a URL directly
|
||||
URL[] ourURLS = super.getURLs();
|
||||
if (ourURLS != null)
|
||||
{
|
||||
for (URL u:ourURLS)
|
||||
urls.add(u);
|
||||
}
|
||||
|
||||
return urls.toArray(new URL[urls.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException
|
||||
{
|
||||
return super.findClass(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Package definePackage(String name, Manifest man, URL url) throws IllegalArgumentException
|
||||
{
|
||||
return super.definePackage(name, man, url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL findResource(String name)
|
||||
{
|
||||
return super.findResource(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<URL> findResources(String name) throws IOException
|
||||
{
|
||||
return super.findResources(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PermissionCollection getPermissions(CodeSource codesource)
|
||||
{
|
||||
return super.getPermissions(codesource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException
|
||||
{
|
||||
return super.loadClass(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
|
||||
{
|
||||
return super.loadClass(name, resolve);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getClassLoadingLock(String className)
|
||||
{
|
||||
return super.getClassLoadingLock(className);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getResource(String name)
|
||||
{
|
||||
return super.getResource(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<URL> getResources(String name) throws IOException
|
||||
{
|
||||
return super.getResources(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Package definePackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion,
|
||||
String implVendor, URL sealBase) throws IllegalArgumentException
|
||||
{
|
||||
return super.definePackage(name, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, sealBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Package getPackage(String name)
|
||||
{
|
||||
return super.getPackage(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Package[] getPackages()
|
||||
{
|
||||
return super.getPackages();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String findLibrary(String libname)
|
||||
{
|
||||
return super.findLibrary(libname);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultAssertionStatus(boolean enabled)
|
||||
{
|
||||
super.setDefaultAssertionStatus(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPackageAssertionStatus(String packageName, boolean enabled)
|
||||
{
|
||||
super.setPackageAssertionStatus(packageName, enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClassAssertionStatus(String className, boolean enabled)
|
||||
{
|
||||
super.setClassAssertionStatus(className, enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAssertionStatus()
|
||||
{
|
||||
super.clearAssertionStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* AntServletHolder
|
||||
|
@ -180,31 +371,6 @@ public class AntWebAppContext extends WebAppContext
|
|||
super(name, servlet);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void initJspServlet() throws Exception
|
||||
{
|
||||
//super.initJspServlet();
|
||||
|
||||
ContextHandler ch = ContextHandler.getContextHandler(getServletHandler().getServletContext());
|
||||
|
||||
/* Set the webapp's classpath for Jasper */
|
||||
ch.setAttribute("org.apache.catalina.jsp_classpath", ch.getClassPath());
|
||||
|
||||
/* Set the system classpath for Jasper */
|
||||
String sysClassPath = getSystemClassPath(ch.getClassLoader().getParent());
|
||||
setInitParameter("com.sun.appserv.jsp.classpath", sysClassPath);
|
||||
|
||||
/* Set up other classpath attribute */
|
||||
if ("?".equals(getInitParameter("classpath")))
|
||||
{
|
||||
String classpath = ch.getClassPath();
|
||||
if (classpath != null)
|
||||
setInitParameter("classpath", classpath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected String getSystemClassPath (ClassLoader loader) throws Exception
|
||||
{
|
||||
StringBuilder classpath=new StringBuilder();
|
||||
|
@ -465,7 +631,7 @@ public class AntWebAppContext extends WebAppContext
|
|||
|
||||
|
||||
/**
|
||||
* @see WebApplicationProxy#start()
|
||||
*
|
||||
*/
|
||||
public void doStart()
|
||||
{
|
||||
|
@ -474,7 +640,12 @@ public class AntWebAppContext extends WebAppContext
|
|||
TaskLog.logWithTimestamp("Starting web application "+this.getDescriptor());
|
||||
if (jettyEnvXml != null && jettyEnvXml.exists())
|
||||
envConfiguration.setJettyEnvXml(Resource.toURL(jettyEnvXml));
|
||||
setClassLoader(new WebAppClassLoader(this.getClass().getClassLoader(), this));
|
||||
|
||||
ClassLoader parentLoader = this.getClass().getClassLoader();
|
||||
if (parentLoader instanceof AntClassLoader)
|
||||
parentLoader = new AntURLClassLoader((AntClassLoader)parentLoader);
|
||||
|
||||
setClassLoader(new WebAppClassLoader(parentLoader, this));
|
||||
if (attributes != null && attributes.getAttributes() != null)
|
||||
{
|
||||
for (Attribute a:attributes.getAttributes())
|
||||
|
|
|
@ -278,6 +278,7 @@ public class ServerProxyImpl implements ServerProxy
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
@ -351,11 +352,14 @@ public class ServerProxyImpl implements ServerProxy
|
|||
return;
|
||||
|
||||
configured = true;
|
||||
|
||||
ShutdownMonitor monitor = ShutdownMonitor.getInstance();
|
||||
monitor.setPort(stopPort);
|
||||
monitor.setKey(stopKey);
|
||||
monitor.setExitVm(false);
|
||||
|
||||
if(stopPort>0 && stopKey!=null)
|
||||
{
|
||||
ShutdownMonitor monitor = ShutdownMonitor.getInstance();
|
||||
monitor.setPort(stopPort);
|
||||
monitor.setKey(stopKey);
|
||||
monitor.setExitVm(false);
|
||||
}
|
||||
|
||||
if (tempDirectory != null && !tempDirectory.exists())
|
||||
tempDirectory.mkdirs();
|
||||
|
|
|
@ -7,11 +7,10 @@
|
|||
<!-- To use: -->
|
||||
<!-- * mkdir test-jetty-ant -->
|
||||
<!-- * cp this file to test-jetty-ant -->
|
||||
<!-- * cd test-jetty-ant; mkdir jetty-lib; mkdir war; mkdir jetty-temp -->
|
||||
<!-- * cd test-jetty-ant; mkdir jetty-lib; mkdir jetty-temp -->
|
||||
<!-- * copy all jars from $JETTY_HOME/lib and all subdirs flatly into ./jetty-lib -->
|
||||
<!-- * unjar the test.war from $JETTY_HOME/webapps dir into ./war -->
|
||||
<!-- * cp $JETTY_HOME/etc/webdefaults.xml to . -->
|
||||
<!-- * cp $JETTY_HOME/etc/realm.properties to . -->
|
||||
<!-- * copy the jetty-ant jar into ./jetty-lib -->
|
||||
<!-- * copy the test.war from $JETTY_HOME/webapps.demo dir -->
|
||||
<!-- -->
|
||||
<!-- To run: -->
|
||||
<!-- ant jetty.run -->
|
||||
|
@ -30,12 +29,12 @@
|
|||
<loginServices>
|
||||
<hashLoginService name="Test Realm" config="realm.properties"/>
|
||||
</loginServices>
|
||||
<webApp name="test"
|
||||
warfile="war"
|
||||
webDefaultXmlFile="webdefault.xml"
|
||||
<webApp
|
||||
war="test.war"
|
||||
contextpath="/test" >
|
||||
<attributes>
|
||||
<attribute name="org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern" value=".*/.*jsp-api-[^/]*\.jar$|.*/.*jsp-[^/]*\.jar$|.*/.*taglibs[^/]*\.jar$"/>
|
||||
<attribute name="org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern" value=".*/servlet-api-[^/]*\.jar$"/>
|
||||
|
||||
</attributes>
|
||||
</webApp>
|
||||
</jetty.run>
|
||||
|
|
|
@ -30,8 +30,7 @@ import org.junit.Test;
|
|||
public class JettyAntTaskTest
|
||||
{
|
||||
|
||||
@Ignore
|
||||
//@Test
|
||||
@Test
|
||||
public void testConnectorTask() throws Exception
|
||||
{
|
||||
AntBuild build = new AntBuild(MavenTestingUtils.getTestResourceFile("connector-test.xml").getAbsolutePath());
|
||||
|
@ -51,7 +50,6 @@ public class JettyAntTaskTest
|
|||
|
||||
|
||||
@Test
|
||||
@Ignore("need to update connector")
|
||||
public void testWebApp () throws Exception
|
||||
{
|
||||
AntBuild build = new AntBuild(MavenTestingUtils.getTestResourceFile("webapp-test.xml").getAbsolutePath());
|
||||
|
|
|
@ -25,7 +25,7 @@ import java.util.Enumeration;
|
|||
import java.util.LinkedHashSet;
|
||||
|
||||
import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
|
||||
import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
|
||||
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelperFactory;
|
||||
import org.eclipse.jetty.osgi.boot.utils.internal.DefaultFileLocatorHelper;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -115,24 +115,24 @@ public class TagLibOSGiConfiguration extends TagLibConfiguration
|
|||
{
|
||||
atLeastOneTldFound = true;
|
||||
URL oriUrl = en.nextElement();
|
||||
URL url = BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(oriUrl);
|
||||
Resource tldResource;
|
||||
try
|
||||
{
|
||||
URL url = BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(oriUrl);
|
||||
Resource tldResource;
|
||||
tldResource = Resource.newResource(url);
|
||||
tlds.add(tldResource);
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new IllegalArgumentException("Unable to locate the " + "tld resource in '"
|
||||
+ url.toString()
|
||||
+ "' in the bundle '"
|
||||
+ bs[0].getSymbolicName()
|
||||
+ "' while registering the "
|
||||
+ OSGiWebappConstants.REQUIRE_TLD_BUNDLE
|
||||
+ " of the manifest of "
|
||||
+ bundle.getSymbolicName(), e);
|
||||
+ oriUrl.toString()
|
||||
+ "' in the bundle '"
|
||||
+ bs[0].getSymbolicName()
|
||||
+ "' while registering the "
|
||||
+ OSGiWebappConstants.REQUIRE_TLD_BUNDLE
|
||||
+ " of the manifest of "
|
||||
+ bundle.getSymbolicName(), e);
|
||||
}
|
||||
tlds.add(tldResource);
|
||||
}
|
||||
if (!atLeastOneTldFound)
|
||||
{
|
||||
|
|
|
@ -12,6 +12,15 @@
|
|||
<Arg>
|
||||
<New class="org.eclipse.jetty.server.ServerConnector">
|
||||
<Arg><Ref refid="Server" /></Arg>
|
||||
<Arg name="factories">
|
||||
<Array type="org.eclipse.jetty.server.ConnectionFactory">
|
||||
<Item>
|
||||
<New class="org.eclipse.jetty.server.HttpConnectionFactory">
|
||||
<Arg name="config"><Ref refid="httpConfig" /></Arg>
|
||||
</New>
|
||||
</Item>
|
||||
</Array>
|
||||
</Arg>
|
||||
<Set name="host"><Property name="jetty.host" /></Set>
|
||||
<Set name="port"><Property name="jetty.port" default="8080"/></Set>
|
||||
<Set name="idleTimeout">300000</Set>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<!-- =========================================================== -->
|
||||
<!-- Server Thread Pool -->
|
||||
<!-- =========================================================== -->
|
||||
<Arg name="threadPool">
|
||||
<Arg name="threadpool">
|
||||
<!-- Default queued blocking threadpool -->
|
||||
<New class="org.eclipse.jetty.util.thread.QueuedThreadPool">
|
||||
<Set name="minThreads">10</Set>
|
||||
|
@ -44,6 +44,17 @@
|
|||
</New>
|
||||
</Set>
|
||||
|
||||
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
|
||||
<Set name="secureScheme">https</Set>
|
||||
<Set name="securePort"><Property name="jetty.secure.port" default="8443" /></Set>
|
||||
<Set name="outputBufferSize">32768</Set>
|
||||
<Set name="requestHeaderSize">8192</Set>
|
||||
<Set name="responseHeaderSize">8192</Set>
|
||||
<Set name="sendServerVersion">true</Set>
|
||||
<Set name="sendDateHeader">false</Set>
|
||||
<Set name="headerCacheSize">512</Set>
|
||||
</New>
|
||||
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- extra options -->
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.eclipse.jetty.deploy.App;
|
|||
import org.eclipse.jetty.deploy.AppProvider;
|
||||
import org.eclipse.jetty.deploy.DeploymentManager;
|
||||
import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
|
||||
import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
|
||||
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelperFactory;
|
||||
import org.eclipse.jetty.osgi.boot.utils.OSGiClassLoader;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
|
@ -214,7 +214,7 @@ public abstract class AbstractContextProvider extends AbstractLifeCycle implemen
|
|||
//put the server instance in
|
||||
properties.put("Server", getServerInstanceWrapper().getServer());
|
||||
//put in the location of the bundle root
|
||||
properties.put("bundle.root", rootResource.toString());
|
||||
properties.put(OSGiWebappConstants.JETTY_BUNDLE_ROOT, rootResource.toString());
|
||||
|
||||
// insert the bundle's location as a property.
|
||||
xmlConfiguration.getProperties().putAll(properties);
|
||||
|
|
|
@ -28,12 +28,14 @@ import org.eclipse.jetty.deploy.App;
|
|||
import org.eclipse.jetty.deploy.AppProvider;
|
||||
import org.eclipse.jetty.deploy.DeploymentManager;
|
||||
import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
|
||||
import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
|
||||
import org.eclipse.jetty.osgi.boot.internal.webapp.OSGiWebappClassLoader;
|
||||
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelperFactory;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.resource.JarResource;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.xml.XmlConfiguration;
|
||||
import org.osgi.framework.Bundle;
|
||||
|
@ -195,7 +197,15 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement
|
|||
? BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(_bundle)
|
||||
: new File(overrideBundleInstallLocation));
|
||||
URL url = null;
|
||||
|
||||
Resource rootResource = Resource.newResource(BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(bundleInstallLocation.toURI().toURL()));
|
||||
//try and make sure the rootResource is useable - if its a jar then make it a jar file url
|
||||
if (rootResource.exists()&& !rootResource.isDirectory() && !rootResource.toString().startsWith("jar:"))
|
||||
{
|
||||
Resource jarResource = JarResource.newJarResource(rootResource);
|
||||
if (jarResource.exists() && jarResource.isDirectory())
|
||||
rootResource = jarResource;
|
||||
}
|
||||
|
||||
//if the path wasn't set or it was ., then it is the root of the bundle's installed location
|
||||
if (_webAppPath == null || _webAppPath.length() == 0 || ".".equals(_webAppPath))
|
||||
{
|
||||
|
@ -227,6 +237,7 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement
|
|||
+ (bundleInstallLocation != null ? bundleInstallLocation.getAbsolutePath() : "unlocated bundle '" + _bundle.getSymbolicName()+ "'"));
|
||||
}
|
||||
|
||||
//Sets the location of the war file
|
||||
// converts bundleentry: protocol if necessary
|
||||
_webApp.setWar(BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(url).toString());
|
||||
|
||||
|
@ -283,7 +294,7 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement
|
|||
|
||||
// apply any META-INF/context.xml file that is found to configure
|
||||
// the webapp first
|
||||
applyMetaInfContextXml();
|
||||
applyMetaInfContextXml(rootResource);
|
||||
|
||||
// pass the value of the require tld bundle so that the TagLibOSGiConfiguration
|
||||
// can pick it up.
|
||||
|
@ -341,7 +352,7 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement
|
|||
}
|
||||
|
||||
|
||||
protected void applyMetaInfContextXml()
|
||||
protected void applyMetaInfContextXml(Resource rootResource)
|
||||
throws Exception
|
||||
{
|
||||
if (_bundle == null) return;
|
||||
|
@ -365,6 +376,7 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement
|
|||
XmlConfiguration xmlConfiguration = new XmlConfiguration(contextXmlUrl);
|
||||
HashMap properties = new HashMap();
|
||||
properties.put("Server", getDeploymentManager().getServer());
|
||||
properties.put(OSGiWebappConstants.JETTY_BUNDLE_ROOT, rootResource.toString());
|
||||
xmlConfiguration.getProperties().putAll(properties);
|
||||
xmlConfiguration.configure(_webApp);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import java.util.ArrayList;
|
|||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
|
||||
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelperFactory;
|
||||
import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
|
|
@ -27,7 +27,7 @@ import java.util.StringTokenizer;
|
|||
import java.util.TreeMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
|
||||
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelperFactory;
|
||||
import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
|
|
@ -79,6 +79,10 @@ public class OSGiWebappConstants
|
|||
public static final String JETTY_WAR_PATCH_FRAGMENT_FOLDER_PATH = "Jetty-WarPatchFragmentFolderPath";
|
||||
|
||||
|
||||
/** installation path of webapp bundle
|
||||
*
|
||||
*/
|
||||
public static final String JETTY_BUNDLE_ROOT = "bundle.root";
|
||||
/**
|
||||
* web app context path
|
||||
* @deprecated see RFC66_WEB_CONTEXTPATH
|
||||
|
|
|
@ -20,18 +20,25 @@ package org.eclipse.jetty.osgi.boot.internal.serverfactory;
|
|||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Dictionary;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator;
|
||||
import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
|
||||
import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
|
||||
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelperFactory;
|
||||
import org.eclipse.jetty.osgi.boot.utils.OSGiClassLoader;
|
||||
import org.eclipse.jetty.osgi.boot.utils.Util;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.resource.JarResource;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.osgi.framework.Bundle;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
|
@ -63,7 +70,7 @@ public class DefaultJettyAtJettyHomeHelper
|
|||
/**
|
||||
* Default location within bundle of a jetty home dir.
|
||||
*/
|
||||
public static final String DEFAULT_JETTYHOME = "/jettyhome/";
|
||||
public static final String DEFAULT_JETTYHOME = "/jettyhome";
|
||||
|
||||
|
||||
|
||||
|
@ -80,9 +87,7 @@ public class DefaultJettyAtJettyHomeHelper
|
|||
* In both cases reads the system property 'jetty.etc.config.urls' to locate
|
||||
* the configuration files for the deployed jetty. It is a comma separated
|
||||
* list of URLs or relative paths inside the bundle or folder to the config
|
||||
* files. If undefined it defaults to 'etc/jetty.xml'. In the case of the jetty.home.bundle,
|
||||
* if no etc/jetty.xml file is found in the bundle, it will look for
|
||||
* /jettyhome/etc/jetty-osgi-default.xml
|
||||
* files.
|
||||
* </p>
|
||||
* <p>
|
||||
* In both cases the system properties jetty.host, jetty.port and
|
||||
|
@ -94,30 +99,33 @@ public class DefaultJettyAtJettyHomeHelper
|
|||
{
|
||||
String jettyHomeSysProp = System.getProperty(OSGiServerConstants.JETTY_HOME);
|
||||
String jettyHomeBundleSysProp = System.getProperty(OSGiServerConstants.JETTY_HOME_BUNDLE);
|
||||
File jettyHome = null;
|
||||
File jettyHomeDir = null;
|
||||
Bundle jettyHomeBundle = null;
|
||||
|
||||
Dictionary<String,String> properties = new Hashtable<String,String>();
|
||||
if (jettyHomeSysProp != null)
|
||||
{
|
||||
jettyHomeSysProp = resolvePropertyValue(jettyHomeSysProp);
|
||||
jettyHomeSysProp = Util.resolvePropertyValue(jettyHomeSysProp);
|
||||
// bug 329621
|
||||
if (jettyHomeSysProp.startsWith("\"") && jettyHomeSysProp.endsWith("\"") || (jettyHomeSysProp.startsWith("'") && jettyHomeSysProp.endsWith("'")))
|
||||
{
|
||||
jettyHomeSysProp = jettyHomeSysProp.substring(1, jettyHomeSysProp.length() - 1);
|
||||
}
|
||||
|
||||
if (jettyHomeBundleSysProp != null)
|
||||
{
|
||||
LOG.warn("Both jetty.home and jetty.home.bundle property defined: jetty.home.bundle ignored.");
|
||||
}
|
||||
jettyHome = new File(jettyHomeSysProp);
|
||||
if (!jettyHome.exists() || !jettyHome.isDirectory())
|
||||
|
||||
jettyHomeDir = new File(jettyHomeSysProp);
|
||||
if (!jettyHomeDir.exists() || !jettyHomeDir.isDirectory())
|
||||
{
|
||||
LOG.warn("Unable to locate the jetty.home folder " + jettyHomeSysProp);
|
||||
return null;
|
||||
}
|
||||
|
||||
//set jetty.home
|
||||
Util.setProperty(properties, OSGiServerConstants.JETTY_HOME, jettyHomeDir.getAbsolutePath());
|
||||
}
|
||||
else if (jettyHomeBundleSysProp != null)
|
||||
{
|
||||
jettyHomeBundleSysProp = resolvePropertyValue(jettyHomeBundleSysProp);
|
||||
jettyHomeBundleSysProp = Util.resolvePropertyValue(jettyHomeBundleSysProp);
|
||||
for (Bundle b : bundleContext.getBundles())
|
||||
{
|
||||
if (b.getSymbolicName().equals(jettyHomeBundleSysProp))
|
||||
|
@ -131,38 +139,52 @@ public class DefaultJettyAtJettyHomeHelper
|
|||
LOG.warn("Unable to find the jetty.home.bundle named " + jettyHomeSysProp);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
if (jettyHome == null && jettyHomeBundle == null)
|
||||
|
||||
if (jettyHomeDir == null && jettyHomeBundle == null)
|
||||
{
|
||||
LOG.warn("No default jetty created.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Server server = new Server();
|
||||
Dictionary<String,String> properties = new Hashtable<String,String>();
|
||||
properties.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME);
|
||||
|
||||
String configURLs = jettyHome != null ? getJettyConfigurationURLs(jettyHome) : getJettyConfigurationURLs(jettyHomeBundle);
|
||||
properties.put(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS, configURLs);
|
||||
|
||||
LOG.info("Configuring the default jetty server with " + configURLs);
|
||||
|
||||
// these properties usually are the ones passed to this type of
|
||||
// configuration.
|
||||
setProperty(properties, OSGiServerConstants.JETTY_HOME, System.getProperty(OSGiServerConstants.JETTY_HOME));
|
||||
setProperty(properties, OSGiServerConstants.JETTY_HOST, System.getProperty(OSGiServerConstants.JETTY_HOST));
|
||||
setProperty(properties, OSGiServerConstants.JETTY_PORT, System.getProperty(OSGiServerConstants.JETTY_PORT));
|
||||
setProperty(properties, OSGiServerConstants.JETTY_PORT_SSL, System.getProperty(OSGiServerConstants.JETTY_PORT_SSL));
|
||||
|
||||
//Register the default Server instance as an OSGi service.
|
||||
//The JettyServerServiceTracker will notice it and configure it.
|
||||
bundleContext.registerService(Server.class.getName(), server, properties);
|
||||
|
||||
return server;
|
||||
|
||||
|
||||
//configure the server here rather than letting the JettyServerServiceTracker do it, because we want to be able to
|
||||
//configure the ThreadPool, which can only be done via the constructor, ie from within the xml configuration processing
|
||||
List<URL> configURLs = jettyHomeDir != null ? getJettyConfigurationURLs(jettyHomeDir) : getJettyConfigurationURLs(jettyHomeBundle, properties);
|
||||
|
||||
LOG.info("Configuring the default jetty server with {}",configURLs);
|
||||
LOG.info("JETTY.HOME="+properties.get(OSGiServerConstants.JETTY_HOME));
|
||||
ClassLoader contextCl = Thread.currentThread().getContextClassLoader();
|
||||
try
|
||||
{
|
||||
Thread.currentThread().setContextClassLoader(JettyBootstrapActivator.class.getClassLoader());
|
||||
|
||||
// these properties usually are the ones passed to this type of
|
||||
// configuration.
|
||||
properties.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME);
|
||||
Util.setProperty(properties, OSGiServerConstants.JETTY_HOST, System.getProperty(OSGiServerConstants.JETTY_HOST));
|
||||
Util.setProperty(properties, OSGiServerConstants.JETTY_PORT, System.getProperty(OSGiServerConstants.JETTY_PORT));
|
||||
Util.setProperty(properties, OSGiServerConstants.JETTY_PORT_SSL, System.getProperty(OSGiServerConstants.JETTY_PORT_SSL));
|
||||
|
||||
Server server = ServerInstanceWrapper.configure(null, configURLs, properties);
|
||||
//ensure jetty.home is set
|
||||
server.setAttribute(OSGiServerConstants.JETTY_HOME, properties.get(OSGiServerConstants.JETTY_HOME));
|
||||
|
||||
//Register the default Server instance as an OSGi service.
|
||||
//The JettyServerServiceTracker will notice it and set it up to deploy bundles as wars etc
|
||||
bundleContext.registerService(Server.class.getName(), server, properties);
|
||||
LOG.info("Default jetty server configured");
|
||||
return server;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Thread.currentThread().setContextClassLoader(contextCl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
@ -173,33 +195,26 @@ public class DefaultJettyAtJettyHomeHelper
|
|||
*
|
||||
* @param jettyhome
|
||||
* @return
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
private static String getJettyConfigurationURLs(File jettyhome)
|
||||
private static List<URL> getJettyConfigurationURLs(File jettyhome)
|
||||
throws MalformedURLException
|
||||
{
|
||||
List<URL> configURLs = new ArrayList<URL>();
|
||||
String jettyetc = System.getProperty(JETTY_ETC_FILES, DEFAULT_JETTY_ETC_FILES);
|
||||
StringTokenizer tokenizer = new StringTokenizer(jettyetc, ";,", false);
|
||||
StringBuilder res = new StringBuilder();
|
||||
while (tokenizer.hasMoreTokens())
|
||||
{
|
||||
String next = tokenizer.nextToken().trim();
|
||||
if (!next.startsWith("/") && next.indexOf(':') == -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
next = new File(jettyhome, next).toURI().toURL().toString();
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
appendToCommaSeparatedList(res, next);
|
||||
//etc files can either be relative to jetty.home or absolute disk locations
|
||||
if (!next.startsWith("/") && (next.indexOf(':') == -1))
|
||||
configURLs.add(new File(jettyhome, next).toURI().toURL());
|
||||
else
|
||||
configURLs.add(new URL(next));
|
||||
}
|
||||
return res.toString();
|
||||
return configURLs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Minimum setup for the location of the configuration files given a
|
||||
|
@ -210,118 +225,90 @@ public class DefaultJettyAtJettyHomeHelper
|
|||
* @param jettyhome
|
||||
* @return
|
||||
*/
|
||||
private static String getJettyConfigurationURLs(Bundle configurationBundle)
|
||||
private static List<URL> getJettyConfigurationURLs(Bundle configurationBundle, Dictionary properties)
|
||||
throws Exception
|
||||
{
|
||||
String files = System.getProperty(JETTY_ETC_FILES, DEFAULT_JETTY_ETC_FILES);
|
||||
|
||||
List<URL> configURLs = new ArrayList<URL>();
|
||||
String files = System.getProperty(JETTY_ETC_FILES, DEFAULT_JETTY_ETC_FILES);
|
||||
StringTokenizer tokenizer = new StringTokenizer(files, ";,", false);
|
||||
StringBuilder res = new StringBuilder();
|
||||
|
||||
while (tokenizer.hasMoreTokens())
|
||||
{
|
||||
String etcFile = tokenizer.nextToken().trim();
|
||||
|
||||
//file path is absolute
|
||||
if (etcFile.startsWith("/") || etcFile.indexOf(":") != -1)
|
||||
configURLs.add(new URL(etcFile));
|
||||
else //relative file path
|
||||
{
|
||||
//file path is absolute
|
||||
appendToCommaSeparatedList(res, etcFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
//relative file path
|
||||
Enumeration<URL> enUrls = BundleFileLocatorHelperFactory.getFactory().getHelper().findEntries(configurationBundle, etcFile);
|
||||
|
||||
|
||||
String home = null;
|
||||
// default for org.eclipse.osgi.boot where we look inside
|
||||
// jettyhome for the default embedded configuration.
|
||||
// default inside jettyhome. this way fragments to the bundle
|
||||
// can define their own configuration.
|
||||
// jettyhome/ for the default embedded configuration.
|
||||
if ((enUrls == null || !enUrls.hasMoreElements()))
|
||||
{
|
||||
home = DEFAULT_JETTYHOME;
|
||||
String tmp = DEFAULT_JETTYHOME+(DEFAULT_JETTYHOME.endsWith("/")?"":"/")+etcFile;
|
||||
enUrls = BundleFileLocatorHelperFactory.getFactory().getHelper().findEntries(configurationBundle, tmp);
|
||||
LOG.info("Configuring jetty from bundle: "
|
||||
+ configurationBundle.getSymbolicName()
|
||||
+ " with "+tmp);
|
||||
LOG.info("Configuring jetty from bundle: {} with {}", configurationBundle.getSymbolicName(),tmp);
|
||||
}
|
||||
|
||||
//lazily ensure jetty.home value is set based on location of etc files
|
||||
if (properties.get(OSGiServerConstants.JETTY_HOME) == null)
|
||||
{
|
||||
Resource res = findDir(configurationBundle, home);
|
||||
if (res != null)
|
||||
properties.put(OSGiServerConstants.JETTY_HOME, res.toString());
|
||||
}
|
||||
|
||||
if (enUrls == null || !enUrls.hasMoreElements())
|
||||
{
|
||||
throw new IllegalStateException ("Unable to locate a jetty configuration file for " + etcFile);
|
||||
}
|
||||
if (enUrls != null)
|
||||
{
|
||||
while (enUrls.hasMoreElements())
|
||||
{
|
||||
URL url = BundleFileLocatorHelperFactory.getFactory().getHelper().getFileURL(enUrls.nextElement());
|
||||
appendToCommaSeparatedList(res, url.toString());
|
||||
}
|
||||
}
|
||||
|
||||
URL url = BundleFileLocatorHelperFactory.getFactory().getHelper().getFileURL(enUrls.nextElement());
|
||||
configURLs.add(url);
|
||||
|
||||
}
|
||||
}
|
||||
return res.toString();
|
||||
return configURLs;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private static void appendToCommaSeparatedList(StringBuilder buffer, String value)
|
||||
{
|
||||
if (buffer.length() != 0)
|
||||
{
|
||||
buffer.append(",");
|
||||
}
|
||||
buffer.append(value);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private static void setProperty(Dictionary<String,String> properties, String key, String value)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
properties.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* recursively substitute the ${sysprop} by their actual system property.
|
||||
* ${sysprop,defaultvalue} will use 'defaultvalue' as the value if no
|
||||
* sysprop is defined. Not the most efficient code but we are shooting for
|
||||
* simplicity and speed of development here.
|
||||
*
|
||||
* @param value
|
||||
* Get a resource representing a directory inside a bundle. If the dir is null,
|
||||
* return a resource representing the installation location of the bundle.
|
||||
* @param bundle
|
||||
* @param dir
|
||||
* @return
|
||||
*/
|
||||
public static String resolvePropertyValue(String value)
|
||||
public static Resource findDir (Bundle bundle, String dir)
|
||||
{
|
||||
int ind = value.indexOf("${");
|
||||
if (ind == -1) { return value; }
|
||||
int ind2 = value.indexOf('}', ind);
|
||||
if (ind2 == -1) { return value; }
|
||||
String sysprop = value.substring(ind + 2, ind2);
|
||||
String defaultValue = null;
|
||||
int comma = sysprop.indexOf(',');
|
||||
if (comma != -1 && comma + 1 != sysprop.length())
|
||||
{
|
||||
defaultValue = sysprop.substring(comma + 1);
|
||||
defaultValue = resolvePropertyValue(defaultValue);
|
||||
sysprop = sysprop.substring(0, comma);
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultValue = "${" + sysprop + "}";
|
||||
}
|
||||
if (bundle == null)
|
||||
return null;
|
||||
|
||||
String v = System.getProperty(sysprop);
|
||||
|
||||
String reminder = value.length() > ind2 + 1 ? value.substring(ind2 + 1) : "";
|
||||
reminder = resolvePropertyValue(reminder);
|
||||
if (v != null)
|
||||
try
|
||||
{
|
||||
return value.substring(0, ind) + v + reminder;
|
||||
File f = BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(bundle);
|
||||
URL u = f.toURI().toURL();
|
||||
u = BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(u);
|
||||
Resource res = Resource.newResource(u);
|
||||
String s = res.toString();
|
||||
|
||||
//check if it is an unarchived bundle
|
||||
if (s.endsWith(".jar") && s.startsWith("file:"))
|
||||
res = JarResource.newJarResource(res);
|
||||
|
||||
//if looking for a directory
|
||||
if (dir != null)
|
||||
res = res.addPath(dir);
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
else
|
||||
catch (Exception e)
|
||||
{
|
||||
return value.substring(0, ind) + defaultValue + reminder;
|
||||
LOG.warn("Bad bundle location" , e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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.osgi.boot.internal.serverfactory;
|
||||
|
||||
/**
|
||||
* Keeps track of the running jetty servers. They are named.
|
||||
*/
|
||||
public interface IManagedJettyServerRegistry
|
||||
{
|
||||
|
||||
/**
|
||||
* @param managedServerName The server name
|
||||
* @return the corresponding jetty server wrapped with its deployment
|
||||
* properties.
|
||||
*/
|
||||
public ServerInstanceWrapper getServerInstanceWrapper(String managedServerName);
|
||||
|
||||
}
|
|
@ -38,15 +38,10 @@ import org.osgi.framework.ServiceReference;
|
|||
* webapps or ContextHandlers discovered from the OSGi environment.
|
||||
*
|
||||
*/
|
||||
public class JettyServerServiceTracker implements ServiceListener, IManagedJettyServerRegistry
|
||||
public class JettyServerServiceTracker implements ServiceListener
|
||||
{
|
||||
private static Logger LOG = Log.getLogger(JettyServerServiceTracker.class.getName());
|
||||
|
||||
/**
|
||||
* Servers indexed by PIDs. PIDs are generated by the ConfigurationAdmin
|
||||
* service.
|
||||
*/
|
||||
private Map<String, ServerInstanceWrapper> _serversIndexedByName = new HashMap<String, ServerInstanceWrapper>();
|
||||
|
||||
/** The context-handler to deactivate indexed by ServerInstanceWrapper */
|
||||
private Map<ServiceReference, ServerInstanceWrapper> _indexByServiceReference = new HashMap<ServiceReference, ServerInstanceWrapper>();
|
||||
|
@ -56,8 +51,7 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
|
|||
*/
|
||||
public void stop()
|
||||
{
|
||||
// not sure that this is really useful but here we go.
|
||||
for (ServerInstanceWrapper wrapper : _serversIndexedByName.values())
|
||||
for (ServerInstanceWrapper wrapper : _indexByServiceReference.values())
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -136,7 +130,6 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
|
|||
if (name == null) { throw new IllegalArgumentException("The property " + OSGiServerConstants.MANAGED_JETTY_SERVER_NAME + " is mandatory"); }
|
||||
ServerInstanceWrapper wrapper = new ServerInstanceWrapper(name);
|
||||
_indexByServiceReference.put(sr, wrapper);
|
||||
_serversIndexedByName.put(name, wrapper);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
|
@ -151,25 +144,10 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
|
|||
ServerInstanceWrapper handler = _indexByServiceReference.remove(sr);
|
||||
if (handler == null)
|
||||
{
|
||||
// a warning?
|
||||
LOG.warn("Unknown Jetty Server ServiceReference: ", sr);
|
||||
return null;
|
||||
}
|
||||
String name = handler.getManagedServerName();
|
||||
if (name != null)
|
||||
{
|
||||
_serversIndexedByName.remove(name);
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param managedServerName The server name
|
||||
* @return the corresponding jetty server wrapped with its deployment
|
||||
* properties.
|
||||
*/
|
||||
public ServerInstanceWrapper getServerInstanceWrapper(String managedServerName)
|
||||
{
|
||||
return _serversIndexedByName.get(managedServerName == null ? OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME : managedServerName);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -45,10 +45,11 @@ import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
|
|||
import org.eclipse.jetty.osgi.boot.OSGiUndeployer;
|
||||
import org.eclipse.jetty.osgi.boot.ServiceContextProvider;
|
||||
import org.eclipse.jetty.osgi.boot.ServiceWebAppProvider;
|
||||
import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
|
||||
import org.eclipse.jetty.osgi.boot.internal.webapp.LibExtClassLoaderHelper;
|
||||
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelperFactory;
|
||||
import org.eclipse.jetty.osgi.boot.utils.FakeURLClassLoader;
|
||||
import org.eclipse.jetty.osgi.boot.utils.TldBundleDiscoverer;
|
||||
import org.eclipse.jetty.osgi.boot.utils.Util;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
|
@ -112,6 +113,87 @@ public class ServerInstanceWrapper
|
|||
return __containerTldBundleDiscoverers;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static Server configure(Server server, List<URL> jettyConfigurations, Dictionary props) throws Exception
|
||||
{
|
||||
|
||||
if (jettyConfigurations == null || jettyConfigurations.isEmpty()) { return server; }
|
||||
|
||||
Map<String, Object> id_map = new HashMap<String, Object>();
|
||||
if (server != null)
|
||||
{
|
||||
//Put in a mapping for the id "Server" and the name of the server as the instance being configured
|
||||
id_map.put("Server", server);
|
||||
id_map.put((String)props.get(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME), server);
|
||||
}
|
||||
|
||||
Map<String, String> properties = new HashMap<String, String>();
|
||||
if (props != null)
|
||||
{
|
||||
Enumeration<Object> en = props.keys();
|
||||
while (en.hasMoreElements())
|
||||
{
|
||||
Object key = en.nextElement();
|
||||
Object value = props.get(key);
|
||||
String keyStr = String.valueOf(key);
|
||||
String valStr = String.valueOf(value);
|
||||
properties.put(keyStr, valStr);
|
||||
if (server != null) server.setAttribute(keyStr, valStr);
|
||||
}
|
||||
}
|
||||
|
||||
for (URL jettyConfiguration : jettyConfigurations)
|
||||
{
|
||||
InputStream is = null;
|
||||
try
|
||||
{
|
||||
// Execute a Jetty configuration file
|
||||
Resource r = Resource.newResource(jettyConfiguration);
|
||||
if (!r.exists())
|
||||
{
|
||||
LOG.warn("File does not exist "+r);
|
||||
throw new IllegalStateException("No such jetty server config file: "+r);
|
||||
}
|
||||
is = r.getInputStream();
|
||||
XmlConfiguration config = new XmlConfiguration(is);
|
||||
config.getIdMap().putAll(id_map);
|
||||
config.getProperties().putAll(properties);
|
||||
|
||||
// #334062 compute the URL of the folder that contains the
|
||||
// conf file and set it as a property so we can compute relative paths
|
||||
// from it.
|
||||
String urlPath = jettyConfiguration.toString();
|
||||
int lastSlash = urlPath.lastIndexOf('/');
|
||||
if (lastSlash > 4)
|
||||
{
|
||||
urlPath = urlPath.substring(0, lastSlash);
|
||||
config.getProperties().put(PROPERTY_THIS_JETTY_XML_FOLDER_URL, urlPath);
|
||||
}
|
||||
|
||||
Object o = config.configure();
|
||||
if (server == null)
|
||||
server = (Server)o;
|
||||
|
||||
id_map = config.getIdMap();
|
||||
}
|
||||
catch (SAXParseException saxparse)
|
||||
{
|
||||
LOG.warn("Unable to configure the jetty/etc file " + jettyConfiguration, saxparse);
|
||||
throw saxparse;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IO.close(is);
|
||||
}
|
||||
}
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -182,13 +264,16 @@ public class ServerInstanceWrapper
|
|||
String sharedURLs = (String) props.get(OSGiServerConstants.MANAGED_JETTY_SHARED_LIB_FOLDER_URLS);
|
||||
|
||||
List<File> shared = sharedURLs != null ? extractFiles(sharedURLs) : null;
|
||||
libExtClassLoader = LibExtClassLoaderHelper.createLibExtClassLoader(shared, null, server, JettyBootstrapActivator.class.getClassLoader());
|
||||
libExtClassLoader = LibExtClassLoaderHelper.createLibExtClassLoader(shared, null,JettyBootstrapActivator.class.getClassLoader());
|
||||
|
||||
if (LOG.isDebugEnabled()) LOG.debug("LibExtClassLoader = "+libExtClassLoader);
|
||||
|
||||
Thread.currentThread().setContextClassLoader(libExtClassLoader);
|
||||
|
||||
configure(server, props);
|
||||
String jettyConfigurationUrls = (String) props.get(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS);
|
||||
List<URL> jettyConfigurations = jettyConfigurationUrls != null ? Util.fileNamesAsURLs(jettyConfigurationUrls, Util.DEFAULT_DELIMS) : null;
|
||||
|
||||
_server = configure(server, jettyConfigurations, props);
|
||||
|
||||
init();
|
||||
|
||||
|
@ -259,80 +344,6 @@ public class ServerInstanceWrapper
|
|||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private void configure(Server server, Dictionary props) throws Exception
|
||||
{
|
||||
String jettyConfigurationUrls = (String) props.get(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS);
|
||||
List<URL> jettyConfigurations = jettyConfigurationUrls != null ? extractResources(jettyConfigurationUrls) : null;
|
||||
if (jettyConfigurations == null || jettyConfigurations.isEmpty()) { return; }
|
||||
Map<String, Object> id_map = new HashMap<String, Object>();
|
||||
|
||||
//Put in a mapping for the id "Server" and the name of the server as the instance being configured
|
||||
id_map.put("Server", server);
|
||||
id_map.put((String)props.get(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME), server);
|
||||
|
||||
Map<String, String> properties = new HashMap<String, String>();
|
||||
Enumeration<Object> en = props.keys();
|
||||
while (en.hasMoreElements())
|
||||
{
|
||||
Object key = en.nextElement();
|
||||
Object value = props.get(key);
|
||||
String keyStr = String.valueOf(key);
|
||||
String valStr = String.valueOf(value);
|
||||
properties.put(keyStr, valStr);
|
||||
server.setAttribute(keyStr, valStr);
|
||||
}
|
||||
|
||||
for (URL jettyConfiguration : jettyConfigurations)
|
||||
{
|
||||
InputStream is = null;
|
||||
try
|
||||
{
|
||||
// Execute a Jetty configuration file
|
||||
Resource r = Resource.newResource(jettyConfiguration);
|
||||
if (!r.exists())
|
||||
{
|
||||
LOG.warn("File does not exist "+r);
|
||||
continue;
|
||||
}
|
||||
is = r.getInputStream();
|
||||
XmlConfiguration config = new XmlConfiguration(is);
|
||||
config.getIdMap().putAll(id_map);
|
||||
|
||||
// #334062 compute the URL of the folder that contains the
|
||||
// jetty.xml conf file
|
||||
// and set it as a property so we can compute relative paths
|
||||
// from it.
|
||||
String urlPath = jettyConfiguration.toString();
|
||||
int lastSlash = urlPath.lastIndexOf('/');
|
||||
if (lastSlash > 4)
|
||||
{
|
||||
urlPath = urlPath.substring(0, lastSlash);
|
||||
Map<String, String> properties2 = new HashMap<String, String>(properties);
|
||||
properties2.put(PROPERTY_THIS_JETTY_XML_FOLDER_URL, urlPath);
|
||||
config.getProperties().putAll(properties2);
|
||||
}
|
||||
else
|
||||
{
|
||||
config.getProperties().putAll(properties);
|
||||
}
|
||||
config.configure();
|
||||
id_map = config.getIdMap();
|
||||
}
|
||||
catch (SAXParseException saxparse)
|
||||
{
|
||||
LOG.warn("Unable to configure the jetty/etc file " + jettyConfiguration, saxparse);
|
||||
throw saxparse;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IO.close(is);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Must be called after the server is configured.
|
||||
|
@ -432,54 +443,8 @@ public class ServerInstanceWrapper
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return The default folder in which the context files of the osgi bundles
|
||||
* are located and watched. Or null when the system property
|
||||
* "jetty.osgi.contexts.home" is not defined. If the configuration
|
||||
* file defines the OSGiAppProvider's context. This will not be
|
||||
* taken into account.
|
||||
*/
|
||||
File getDefaultOSGiContextsHome(File jettyHome)
|
||||
{
|
||||
String jettyContextsHome = System.getProperty("jetty.osgi.contexts.home");
|
||||
if (jettyContextsHome != null)
|
||||
{
|
||||
File contextsHome = new File(jettyContextsHome);
|
||||
if (!contextsHome.exists() || !contextsHome.isDirectory())
|
||||
{
|
||||
throw new IllegalArgumentException("the ${jetty.osgi.contexts.home} '"
|
||||
+ jettyContextsHome
|
||||
+ " must exist and be a folder");
|
||||
}
|
||||
return contextsHome;
|
||||
}
|
||||
return new File(jettyHome, "/contexts");
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return the urls in this string.
|
||||
*/
|
||||
private List<URL> extractResources(String propertyValue)
|
||||
{
|
||||
StringTokenizer tokenizer = new StringTokenizer(propertyValue, ",;", false);
|
||||
List<URL> urls = new ArrayList<URL>();
|
||||
while (tokenizer.hasMoreTokens())
|
||||
{
|
||||
String tok = tokenizer.nextToken();
|
||||
try
|
||||
{
|
||||
urls.add(BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(new URL(tok)));
|
||||
}
|
||||
catch (Throwable mfe)
|
||||
{
|
||||
LOG.warn(mfe);
|
||||
}
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -84,7 +84,7 @@ public class LibExtClassLoaderHelper
|
|||
* is the JettyBootStrapper (an osgi classloader.
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
public static ClassLoader createLibEtcClassLoader(File jettyHome, Server server, ClassLoader parentClassLoader) throws MalformedURLException
|
||||
public static ClassLoader createLibEtcClassLoader(File jettyHome, ClassLoader parentClassLoader) throws MalformedURLException
|
||||
{
|
||||
if (jettyHome == null) { return parentClassLoader; }
|
||||
ArrayList<URL> urls = new ArrayList<URL>();
|
||||
|
@ -141,7 +141,7 @@ public class LibExtClassLoaderHelper
|
|||
* extra jars to insert, then just return the parentClassLoader.
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
public static ClassLoader createLibExtClassLoader(List<File> jarsContainerOrJars, List<URL> otherJarsOrFolder, Server server, ClassLoader parentClassLoader)
|
||||
public static ClassLoader createLibExtClassLoader(List<File> jarsContainerOrJars, List<URL> otherJarsOrFolder, ClassLoader parentClassLoader)
|
||||
throws MalformedURLException
|
||||
{
|
||||
if (jarsContainerOrJars == null && otherJarsOrFolder == null) { return parentClassLoader; }
|
||||
|
|
|
@ -185,7 +185,6 @@ public class ServiceWatcher implements ServiceListener
|
|||
try
|
||||
{
|
||||
added = e.getValue().serviceAdded(sr, contextHandler);
|
||||
System.err.println(serverName+" deployed "+contextHandler+": "+added);
|
||||
if (added && LOG.isDebugEnabled())
|
||||
LOG.debug("Provider "+e.getValue()+" deployed "+contextHandler);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.osgi.boot.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
|
||||
|
@ -103,7 +104,7 @@ public interface BundleFileLocatorHelper
|
|||
*
|
||||
* @return a URL to the bundle entry that uses a common protocol
|
||||
*/
|
||||
public URL getLocalURL(URL url);
|
||||
public URL getLocalURL(URL url) throws Exception;
|
||||
|
||||
/**
|
||||
* Only useful for equinox: on felix we get the file:// url already. Other
|
||||
|
@ -116,7 +117,9 @@ public interface BundleFileLocatorHelper
|
|||
* @return a URL to the content of the bundle entry that uses the file:
|
||||
* protocol
|
||||
* </p>
|
||||
* @throws IOException
|
||||
* @throws Exception
|
||||
*/
|
||||
public URL getFileURL(URL url);
|
||||
public URL getFileURL(URL url) throws Exception;
|
||||
|
||||
}
|
||||
|
|
|
@ -16,9 +16,8 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.osgi.boot.internal.webapp;
|
||||
package org.eclipse.jetty.osgi.boot.utils;
|
||||
|
||||
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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.osgi.boot.utils;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Dictionary;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* Util
|
||||
*
|
||||
* Various useful functions used widely.
|
||||
*/
|
||||
public class Util
|
||||
{
|
||||
public static final String DEFAULT_DELIMS = ",;";
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Treating the string as a separated list of filenames,
|
||||
* convert and return the list of urls.
|
||||
*
|
||||
* @param val the separated list
|
||||
* @param delims the separators (default is ,;)
|
||||
* @return
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
public static List<URL> fileNamesAsURLs(String val, String delims)
|
||||
throws Exception
|
||||
{
|
||||
String separators = DEFAULT_DELIMS;
|
||||
if (delims == null)
|
||||
delims = separators;
|
||||
|
||||
StringTokenizer tokenizer = new StringTokenizer(val, delims, false);
|
||||
List<URL> urls = new ArrayList<URL>();
|
||||
while (tokenizer.hasMoreTokens())
|
||||
{
|
||||
urls.add(BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(new URL(tokenizer.nextToken())));
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static void setProperty(Dictionary<String,String> properties, String key, String value)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
properties.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* recursively substitute the ${sysprop} by their actual system property.
|
||||
* ${sysprop,defaultvalue} will use 'defaultvalue' as the value if no
|
||||
* sysprop is defined. Not the most efficient code but we are shooting for
|
||||
* simplicity and speed of development here.
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public static String resolvePropertyValue(String value)
|
||||
{
|
||||
int ind = value.indexOf("${");
|
||||
if (ind == -1) { return value; }
|
||||
int ind2 = value.indexOf('}', ind);
|
||||
if (ind2 == -1) { return value; }
|
||||
String sysprop = value.substring(ind + 2, ind2);
|
||||
String defaultValue = null;
|
||||
int comma = sysprop.indexOf(',');
|
||||
if (comma != -1 && comma + 1 != sysprop.length())
|
||||
{
|
||||
defaultValue = sysprop.substring(comma + 1);
|
||||
defaultValue = resolvePropertyValue(defaultValue);
|
||||
sysprop = sysprop.substring(0, comma);
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultValue = "${" + sysprop + "}";
|
||||
}
|
||||
|
||||
String v = System.getProperty(sysprop);
|
||||
|
||||
String reminder = value.length() > ind2 + 1 ? value.substring(ind2 + 1) : "";
|
||||
reminder = resolvePropertyValue(reminder);
|
||||
if (v != null)
|
||||
{
|
||||
return value.substring(0, ind) + v + reminder;
|
||||
}
|
||||
else
|
||||
{
|
||||
return value.substring(0, ind) + defaultValue + reminder;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.osgi.boot.utils.internal;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
|
@ -301,25 +302,19 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
* @return a URL to the bundle entry that uses a common protocol
|
||||
*/
|
||||
public URL getLocalURL(URL url)
|
||||
throws Exception
|
||||
{
|
||||
if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol()))
|
||||
{
|
||||
try
|
||||
|
||||
URLConnection conn = url.openConnection();
|
||||
conn.setDefaultUseCaches(Resource.getDefaultUseCaches());
|
||||
if (BUNDLE_URL_CONNECTION_getLocalURL == null && conn.getClass().getName().equals("org.eclipse.osgi.framework.internal.core.BundleURLConnection"))
|
||||
{
|
||||
URLConnection conn = url.openConnection();
|
||||
conn.setDefaultUseCaches(Resource.getDefaultUseCaches());
|
||||
if (BUNDLE_URL_CONNECTION_getLocalURL == null && conn.getClass().getName().equals("org.eclipse.osgi.framework.internal.core.BundleURLConnection"))
|
||||
{
|
||||
BUNDLE_URL_CONNECTION_getLocalURL = conn.getClass().getMethod("getLocalURL", null);
|
||||
BUNDLE_URL_CONNECTION_getLocalURL.setAccessible(true);
|
||||
}
|
||||
if (BUNDLE_URL_CONNECTION_getLocalURL != null) { return (URL) BUNDLE_URL_CONNECTION_getLocalURL.invoke(conn, null); }
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
System.err.println("Unable to locate the OSGi url: '" + url + "'.");
|
||||
t.printStackTrace();
|
||||
BUNDLE_URL_CONNECTION_getLocalURL = conn.getClass().getMethod("getLocalURL", null);
|
||||
BUNDLE_URL_CONNECTION_getLocalURL.setAccessible(true);
|
||||
}
|
||||
if (BUNDLE_URL_CONNECTION_getLocalURL != null) { return (URL) BUNDLE_URL_CONNECTION_getLocalURL.invoke(conn, null); }
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
@ -335,26 +330,23 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
* @return a URL to the content of the bundle entry that uses the file:
|
||||
* protocol
|
||||
* </p>
|
||||
* @throws IOException
|
||||
*/
|
||||
public URL getFileURL(URL url)
|
||||
public URL getFileURL(URL url) throws Exception
|
||||
|
||||
{
|
||||
if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol()))
|
||||
{
|
||||
try
|
||||
|
||||
URLConnection conn = url.openConnection();
|
||||
conn.setDefaultUseCaches(Resource.getDefaultUseCaches());
|
||||
if (BUNDLE_URL_CONNECTION_getFileURL == null && conn.getClass().getName().equals("org.eclipse.osgi.framework.internal.core.BundleURLConnection"))
|
||||
{
|
||||
URLConnection conn = url.openConnection();
|
||||
conn.setDefaultUseCaches(Resource.getDefaultUseCaches());
|
||||
if (BUNDLE_URL_CONNECTION_getFileURL == null && conn.getClass().getName().equals("org.eclipse.osgi.framework.internal.core.BundleURLConnection"))
|
||||
{
|
||||
BUNDLE_URL_CONNECTION_getFileURL = conn.getClass().getMethod("getFileURL", null);
|
||||
BUNDLE_URL_CONNECTION_getFileURL.setAccessible(true);
|
||||
}
|
||||
if (BUNDLE_URL_CONNECTION_getFileURL != null) { return (URL) BUNDLE_URL_CONNECTION_getFileURL.invoke(conn, null); }
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
t.printStackTrace();
|
||||
BUNDLE_URL_CONNECTION_getFileURL = conn.getClass().getMethod("getFileURL", null);
|
||||
BUNDLE_URL_CONNECTION_getFileURL.setAccessible(true);
|
||||
}
|
||||
if (BUNDLE_URL_CONNECTION_getFileURL != null) { return (URL) BUNDLE_URL_CONNECTION_getFileURL.invoke(conn, null); }
|
||||
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
|
|
@ -46,11 +46,30 @@ public class Activator implements BundleActivator
|
|||
*/
|
||||
public void start(BundleContext context) throws Exception
|
||||
{
|
||||
String serverName = "defaultJettyServer";
|
||||
|
||||
/* Uncomment to create a different server instance to deploy to. Also change
|
||||
* TestJettyOSGiBootWebAppAsService to use the port 9999
|
||||
|
||||
Server server = new Server();
|
||||
//do any setup on Server in here
|
||||
serverName = "fooServer";
|
||||
Dictionary serverProps = new Hashtable();
|
||||
//define the unique name of the server instance
|
||||
serverProps.put("managedServerName", serverName);
|
||||
serverProps.put("jetty.port", "9999");
|
||||
//let Jetty apply some configuration files to the Server instance
|
||||
serverProps.put("jetty.etc.config.urls", "file:/opt/jetty/etc/jetty.xml,file:/opt/jetty/etc/jetty-selector.xml,file:/opt/jetty/etc/jetty-deployer.xml");
|
||||
//register as an OSGi Service for Jetty to find
|
||||
context.registerService(Server.class.getName(), server, serverProps);
|
||||
*/
|
||||
|
||||
//Create a webapp context as a Service and target it at the Server created above
|
||||
WebAppContext webapp = new WebAppContext();
|
||||
Dictionary props = new Hashtable();
|
||||
props.put("war",".");
|
||||
props.put("contextPath","/acme");
|
||||
//uiProps.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, serverName);
|
||||
props.put("managedServerName", serverName);
|
||||
context.registerService(ContextHandler.class.getName(),webapp,props);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- Configure a HTTPS connector. -->
|
||||
<!-- This configuration must be used in conjunction with jetty.xml -->
|
||||
<!-- and jetty-ssl.xml. -->
|
||||
<!-- ============================================================= -->
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- Add a HTTPS Connector. -->
|
||||
<!-- Configure an o.e.j.server.ServerConnector with connection -->
|
||||
<!-- factories for TLS (aka SSL) and HTTP to provide HTTPS. -->
|
||||
<!-- All accepted TLS connections are wired to a HTTP connection.-->
|
||||
<!-- -->
|
||||
<!-- Consult the javadoc of o.e.j.server.ServerConnector, -->
|
||||
<!-- o.e.j.server.SslConnectionFactory and -->
|
||||
<!-- o.e.j.server.HttpConnectionFactory for all configuration -->
|
||||
<!-- that may be set here. -->
|
||||
<!-- =========================================================== -->
|
||||
<Call id="httpsConnector" name="addConnector">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.server.ServerConnector">
|
||||
<Arg name="server"><Ref refid="Server" /></Arg>
|
||||
<Arg name="factories">
|
||||
<Array type="org.eclipse.jetty.server.ConnectionFactory">
|
||||
<Item>
|
||||
<New class="org.eclipse.jetty.server.SslConnectionFactory">
|
||||
<Arg name="next">http/1.1</Arg>
|
||||
<Arg name="sslContextFactory"><Ref refid="sslContextFactory"/></Arg>
|
||||
</New>
|
||||
</Item>
|
||||
<Item>
|
||||
<New class="org.eclipse.jetty.server.HttpConnectionFactory">
|
||||
<Arg name="config"><Ref refid="sslHttpConfig"/></Arg>
|
||||
</New>
|
||||
</Item>
|
||||
</Array>
|
||||
</Arg>
|
||||
<Set name="host"><Property name="jetty.host" /></Set>
|
||||
<Set name="port"><Property name="jetty.https.port" default="8443" /></Set>
|
||||
<Set name="idleTimeout">30000</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
</Configure>
|
|
@ -12,6 +12,15 @@
|
|||
<Arg>
|
||||
<New class="org.eclipse.jetty.server.ServerConnector">
|
||||
<Arg><Ref refid="Server" /></Arg>
|
||||
<Arg name="factories">
|
||||
<Array type="org.eclipse.jetty.server.ConnectionFactory">
|
||||
<Item>
|
||||
<New class="org.eclipse.jetty.server.HttpConnectionFactory">
|
||||
<Arg name="config"><Ref refid="httpConfig" /></Arg>
|
||||
</New>
|
||||
</Item>
|
||||
</Array>
|
||||
</Arg>
|
||||
<Set name="host"><Property name="jetty.host" /></Set>
|
||||
<Set name="port"><Property name="jetty.port" default="8080"/></Set>
|
||||
<Set name="idleTimeout">300000</Set>
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- Configure a TLS (SSL) Context Factory -->
|
||||
<!-- This configuration must be used in conjunction with jetty.xml -->
|
||||
<!-- and either jetty-https.xml or jetty-spdy.xml (but not both) -->
|
||||
<!-- ============================================================= -->
|
||||
<Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
|
||||
<Set name="KeyStorePath"><Property name="jetty.home" default="." />/<Property name="jetty.keystore" default="etc/keystore"/></Set>
|
||||
<Set name="KeyStorePassword"><Property name="jetty.keystore.password" default="OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"/></Set>
|
||||
<Set name="KeyManagerPassword"><Property name="jetty.keymanager.password" default="OBF:1u2u1wml1z7s1z7a1wnl1u2g"/></Set>
|
||||
<Set name="TrustStorePath"><Property name="jetty.home" default="." />/<Property name="jetty.truststore" default="etc/keystore"/></Set>
|
||||
<Set name="TrustStorePassword"><Property name="jetty.truststore.password" default="OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"/></Set>
|
||||
<Set name="EndpointIdentificationAlgorithm"></Set>
|
||||
<Set name="ExcludeCipherSuites">
|
||||
<Array type="String">
|
||||
<Item>SSL_RSA_WITH_DES_CBC_SHA</Item>
|
||||
<Item>SSL_DHE_RSA_WITH_DES_CBC_SHA</Item>
|
||||
<Item>SSL_DHE_DSS_WITH_DES_CBC_SHA</Item>
|
||||
<Item>SSL_RSA_EXPORT_WITH_RC4_40_MD5</Item>
|
||||
<Item>SSL_RSA_EXPORT_WITH_DES40_CBC_SHA</Item>
|
||||
<Item>SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA</Item>
|
||||
<Item>SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- Create a TLS specific HttpConfiguration based on the -->
|
||||
<!-- common HttpConfiguration defined in jetty.xml -->
|
||||
<!-- Add a SecureRequestCustomizer to extract certificate and -->
|
||||
<!-- session information -->
|
||||
<!-- =========================================================== -->
|
||||
<New id="sslHttpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
|
||||
<Arg><Ref refid="httpConfig"/></Arg>
|
||||
<Call name="addCustomizer">
|
||||
<Arg><New class="org.eclipse.jetty.server.SecureRequestCustomizer"/></Arg>
|
||||
</Call>
|
||||
</New>
|
||||
|
||||
</Configure>
|
|
@ -14,7 +14,7 @@
|
|||
<!-- =========================================================== -->
|
||||
<!-- Server Thread Pool -->
|
||||
<!-- =========================================================== -->
|
||||
<Arg name="threadPool">
|
||||
<Arg name="threadpool">
|
||||
<!-- Default queued blocking threadpool -->
|
||||
<New class="org.eclipse.jetty.util.thread.QueuedThreadPool">
|
||||
<Set name="minThreads">10</Set>
|
||||
|
@ -44,6 +44,17 @@
|
|||
</New>
|
||||
</Set>
|
||||
|
||||
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
|
||||
<Set name="secureScheme">https</Set>
|
||||
<Set name="securePort"><Property name="jetty.secure.port" default="8443" /></Set>
|
||||
<Set name="outputBufferSize">32768</Set>
|
||||
<Set name="requestHeaderSize">8192</Set>
|
||||
<Set name="responseHeaderSize">8192</Set>
|
||||
<Set name="sendServerVersion">true</Set>
|
||||
<Set name="sendDateHeader">false</Set>
|
||||
<Set name="headerCacheSize">512</Set>
|
||||
</New>
|
||||
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- extra options -->
|
||||
|
@ -57,6 +68,20 @@
|
|||
<!-- =========================================================== -->
|
||||
<!-- jetty-jndi by default -->
|
||||
<!-- =========================================================== -->
|
||||
<Call class="org.eclipse.jetty.webapp.Configuration$ClassList" name="setServerDefault">
|
||||
<Arg><Ref refid="Server" /></Arg>
|
||||
<Call name="addAfter">
|
||||
<Arg name="afterClass">org.eclipse.jetty.webapp.FragmentConfiguration</Arg>
|
||||
<Arg>
|
||||
<Array type="String">
|
||||
<Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item>
|
||||
<Item>org.eclipse.jetty.plus.webapp.PlusConfiguration</Item>
|
||||
<Item>org.eclipse.jetty.annotations.AnnotationConfiguration</Item>
|
||||
</Array>
|
||||
</Arg>
|
||||
</Call>
|
||||
</Call>
|
||||
|
||||
<Call class="java.lang.System" name="setProperty">
|
||||
<Arg>java.naming.factory.initial</Arg>
|
||||
<Arg><Property name="java.naming.factory.initial" default="org.eclipse.jetty.jndi.InitialContextFactory"/></Arg>
|
||||
|
|
|
@ -62,7 +62,7 @@ public class TestJettyOSGiBootCore
|
|||
}
|
||||
|
||||
public static List<Option> provisionCoreJetty()
|
||||
{
|
||||
{
|
||||
List<Option> res = new ArrayList<Option>();
|
||||
// get the jetty home config from the osgi boot bundle.
|
||||
res.add(CoreOptions.systemProperty("jetty.port").value(String.valueOf(DEFAULT_JETTY_HTTP_PORT)));
|
||||
|
@ -96,7 +96,6 @@ public class TestJettyOSGiBootCore
|
|||
res.add(mavenBundle().groupId( "org.eclipse.jetty.websocket" ).artifactId( "websocket-common" ).versionAsInProject().noStart());
|
||||
res.add(mavenBundle().groupId( "org.eclipse.jetty.websocket" ).artifactId( "websocket-servlet" ).versionAsInProject().noStart());
|
||||
res.add(mavenBundle().groupId( "org.eclipse.jetty.websocket" ).artifactId( "websocket-server" ).versionAsInProject().noStart());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -61,8 +61,9 @@ public class TestJettyOSGiBootSpdy
|
|||
|
||||
TestOSGiUtil.addMoreOSGiContainers(options);
|
||||
|
||||
options.addAll(TestJettyOSGiBootCore.provisionCoreJetty());
|
||||
|
||||
options.addAll(TestJettyOSGiBootWithJsp.configureJettyHomeAndPort("jetty-spdy.xml"));
|
||||
options.addAll(TestJettyOSGiBootCore.coreJettyDependencies());
|
||||
options.add(CoreOptions.junitBundles());
|
||||
options.addAll(TestJettyOSGiBootCore.httpServiceJetty());
|
||||
options.addAll(spdyJettyDependencies());
|
||||
|
|
|
@ -148,7 +148,6 @@ public class TestJettyOSGiBootWebAppAsService
|
|||
@Test
|
||||
public void testBundle() throws Exception
|
||||
{
|
||||
|
||||
// now test the jsp/dump.jsp
|
||||
HttpClient client = new HttpClient();
|
||||
try
|
||||
|
|
|
@ -118,9 +118,14 @@ public class TestJettyOSGiBootWithJsp
|
|||
+ jettySelectorFileName
|
||||
+ ";"
|
||||
+ etc
|
||||
+ "/jetty-ssl.xml;"
|
||||
+ etc
|
||||
+ "/jetty-https.xml;"
|
||||
+ etc
|
||||
+ "/jetty-deployer.xml;"
|
||||
+ etc
|
||||
+ "/jetty-testrealm.xml";
|
||||
|
||||
options.add(systemProperty(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS).value(xmlConfigs));
|
||||
options.add(systemProperty("jetty.port").value(String.valueOf(TestJettyOSGiBootCore.DEFAULT_JETTY_HTTP_PORT)));
|
||||
options.add(systemProperty("jetty.home").value(etcFolder.getParentFile().getAbsolutePath()));
|
||||
|
|
|
@ -50,13 +50,15 @@ public class TestOSGiUtil
|
|||
* Note: this will run many more tests. TODO: find a better way to control
|
||||
* this and use non-deprecated methods.
|
||||
*
|
||||
* @param options
|
||||
* @param opti
|
||||
*/
|
||||
protected static void addMoreOSGiContainers(List<Option> options)
|
||||
{
|
||||
options.add(CoreOptions.equinox().version("3.6.1"));
|
||||
options.add(CoreOptions.equinox().version("3.7.0"));
|
||||
options.add(CoreOptions.felix().version("3.2.2"));
|
||||
//Uncomment to run more containers - these have been commented out
|
||||
//to improve speed of builds.
|
||||
//options.add(CoreOptions.equinox().version("3.6.1"));
|
||||
//options.add(CoreOptions.equinox().version("3.7.0"));
|
||||
// options.add(CoreOptions.felix().version("3.2.2"));
|
||||
options.add(CoreOptions.felix().version("4.0.2"));
|
||||
}
|
||||
|
||||
|
|
|
@ -623,6 +623,7 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
|
|||
|
||||
protected boolean sendResponse(ResponseInfo info, ByteBuffer content, boolean complete, final Callback callback)
|
||||
{
|
||||
// TODO check that complete only set true once by changing _committed to AtomicRef<Enum>
|
||||
boolean committing = _committed.compareAndSet(false, true);
|
||||
if (committing)
|
||||
{
|
||||
|
|
|
@ -106,6 +106,17 @@ write completed - - - ASYNC READY->owp
|
|||
public boolean isAllContentWritten()
|
||||
{
|
||||
return _channel.getResponse().isAllContentWritten(_written);
|
||||
{
|
||||
try
|
||||
{
|
||||
_channel.getResponse().closeOutput();
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
_channel.getEndPoint().shutdownOutput();
|
||||
LOG.ignore(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -305,6 +316,8 @@ write completed - - - ASYNC READY->owp
|
|||
// write any remaining content in the buffer directly
|
||||
if (len>0)
|
||||
_channel.write(ByteBuffer.wrap(b, off, len), complete);
|
||||
else if (complete)
|
||||
_channel.write(BufferUtil.EMPTY_BUFFER,complete);
|
||||
|
||||
if (complete)
|
||||
{
|
||||
|
@ -441,9 +454,23 @@ write completed - - - ASYNC READY->owp
|
|||
* @param content The content to send
|
||||
* @param callback The callback to use to notify success or failure
|
||||
*/
|
||||
public void sendContent(ByteBuffer content, Callback callback)
|
||||
public void sendContent(ByteBuffer content, final Callback callback)
|
||||
{
|
||||
_channel.write(content,true,callback);
|
||||
_channel.write(content,true,new Callback()
|
||||
{
|
||||
@Override
|
||||
public void succeeded()
|
||||
{
|
||||
closed();
|
||||
callback.succeeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable x)
|
||||
{
|
||||
callback.failed(x);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -493,7 +520,6 @@ write completed - - - ASYNC READY->owp
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ByteBuffer buffer= _channel.useDirectBuffers()?httpContent.getDirectBuffer():null;
|
||||
if (buffer == null)
|
||||
buffer = httpContent.getIndirectBuffer();
|
||||
|
@ -750,6 +776,7 @@ write completed - - - ASYNC READY->owp
|
|||
int len=_in.read(_buffer.array(),0,_buffer.capacity());
|
||||
if (len==-1)
|
||||
{
|
||||
closed();
|
||||
_channel.getByteBufferPool().release(_buffer);
|
||||
return true;
|
||||
}
|
||||
|
@ -808,6 +835,7 @@ write completed - - - ASYNC READY->owp
|
|||
int len=_in.read(_buffer);
|
||||
if (len==-1)
|
||||
{
|
||||
closed();
|
||||
_channel.getByteBufferPool().release(_buffer);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -547,7 +547,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
|||
_contextAttributeListeners.clear();
|
||||
_requestListeners.clear();
|
||||
_requestAttributeListeners.clear();
|
||||
|
||||
_eventListeners.clear();
|
||||
|
||||
if (eventListeners!=null)
|
||||
for (EventListener listener : eventListeners)
|
||||
addEventListener(listener);
|
||||
|
|
|
@ -66,22 +66,31 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
|||
doCompress();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Reset buffer.
|
||||
*/
|
||||
public void resetBuffer()
|
||||
{
|
||||
if (_response.isCommitted())
|
||||
if (_response.isCommitted() || _compressedOutputStream!=null )
|
||||
throw new IllegalStateException("Committed");
|
||||
_closed = false;
|
||||
_out = null;
|
||||
_bOut = null;
|
||||
if (_compressedOutputStream != null)
|
||||
_response.setHeader("Content-Encoding",null);
|
||||
_compressedOutputStream = null;
|
||||
_doNotCompress = false;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setBufferSize(int bufferSize)
|
||||
{
|
||||
if (_bOut!=null && _bOut.getBuf().length<bufferSize)
|
||||
{
|
||||
ByteArrayOutputStream2 b = new ByteArrayOutputStream2(bufferSize);
|
||||
b.write(_bOut.getBuf(),0,_bOut.size());
|
||||
_bOut=b;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setContentLength()
|
||||
{
|
||||
|
@ -171,7 +180,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
|||
if (_out == null || _bOut != null)
|
||||
{
|
||||
long length=_wrapper.getContentLength();
|
||||
if (length > 0 && length < _wrapper.getMinCompressSize())
|
||||
if (length<0 && _bOut==null || length >= 0 && length < _wrapper.getMinCompressSize())
|
||||
doNotCompress(false);
|
||||
else
|
||||
doCompress();
|
||||
|
@ -375,4 +384,5 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
|||
*/
|
||||
protected abstract DeflaterOutputStream createStream() throws IOException;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -108,6 +108,8 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
public void setBufferSize(int bufferSize)
|
||||
{
|
||||
_bufferSize = bufferSize;
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.setBufferSize(bufferSize);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -128,7 +130,7 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
{
|
||||
super.setContentType(ct);
|
||||
|
||||
if (_compressedStream==null || _compressedStream.getOutputStream()==null)
|
||||
if (!_noCompression && (_compressedStream==null || _compressedStream.getOutputStream()==null))
|
||||
{
|
||||
if (ct!=null)
|
||||
{
|
||||
|
@ -174,7 +176,10 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
@Override
|
||||
public void setContentLength(int length)
|
||||
{
|
||||
setContentLength((long)length);
|
||||
if (_noCompression)
|
||||
super.setContentLength(length);
|
||||
else
|
||||
setContentLength((long)length);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -312,6 +317,8 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
*/
|
||||
public void noCompression()
|
||||
{
|
||||
if (!_noCompression)
|
||||
setDeferredHeaders();
|
||||
_noCompression=true;
|
||||
if (_compressedStream!=null)
|
||||
{
|
||||
|
@ -336,6 +343,25 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
_writer.flush();
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.finish();
|
||||
else
|
||||
setDeferredHeaders();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private void setDeferredHeaders()
|
||||
{
|
||||
if (!isCommitted())
|
||||
{
|
||||
if (_contentLength>=0)
|
||||
{
|
||||
if (_contentLength < Integer.MAX_VALUE)
|
||||
super.setContentLength((int)_contentLength);
|
||||
else
|
||||
super.setHeader("Content-Length",Long.toString(_contentLength));
|
||||
}
|
||||
if(_etag!=null)
|
||||
super.setHeader("ETag",_etag);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -345,7 +371,9 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
@Override
|
||||
public void setHeader(String name, String value)
|
||||
{
|
||||
if ("content-length".equalsIgnoreCase(name))
|
||||
if (_noCompression)
|
||||
super.setHeader(name,value);
|
||||
else if ("content-length".equalsIgnoreCase(name))
|
||||
{
|
||||
setContentLength(Long.parseLong(value));
|
||||
}
|
||||
|
@ -371,7 +399,7 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
@Override
|
||||
public boolean containsHeader(String name)
|
||||
{
|
||||
if ("etag".equalsIgnoreCase(name) && _etag!=null)
|
||||
if (!_noCompression && "etag".equalsIgnoreCase(name) && _etag!=null)
|
||||
return true;
|
||||
return super.containsHeader(name);
|
||||
}
|
||||
|
@ -386,10 +414,7 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
if (_compressedStream==null)
|
||||
{
|
||||
if (getResponse().isCommitted() || _noCompression)
|
||||
{
|
||||
setContentLength(_contentLength);
|
||||
return getResponse().getOutputStream();
|
||||
}
|
||||
|
||||
_compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse());
|
||||
}
|
||||
|
@ -412,10 +437,7 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
throw new IllegalStateException("getOutputStream() called");
|
||||
|
||||
if (getResponse().isCommitted() || _noCompression)
|
||||
{
|
||||
setContentLength(_contentLength);
|
||||
return getResponse().getWriter();
|
||||
}
|
||||
|
||||
_compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse());
|
||||
_writer=newWriter(_compressedStream,getCharacterEncoding());
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.util.List;
|
|||
import javax.servlet.Servlet;
|
||||
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.HttpTester;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlets.gzip.CompressedResponseWrapper;
|
||||
import org.eclipse.jetty.servlets.gzip.GzipTester;
|
||||
|
@ -35,6 +36,8 @@ import org.eclipse.jetty.servlets.gzip.TestServletStreamTypeLengthWrite;
|
|||
import org.eclipse.jetty.servlets.gzip.TestServletTypeLengthStreamWrite;
|
||||
import org.eclipse.jetty.servlets.gzip.TestServletTypeStreamLengthWrite;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
@ -132,7 +135,8 @@ public class GzipFilterContentLengthTest
|
|||
try
|
||||
{
|
||||
tester.start();
|
||||
tester.assertIsResponseNotGzipCompressed("GET",testfile.getName(),filesize,HttpStatus.OK_200);
|
||||
HttpTester.Response response = tester.assertIsResponseNotGzipCompressed("GET",testfile.getName(),filesize,HttpStatus.OK_200);
|
||||
Assert.assertThat(response.get("ETAG"),Matchers.startsWith("W/etag-"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -140,6 +144,15 @@ public class GzipFilterContentLengthTest
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests gzip compression of a small size file
|
||||
*/
|
||||
@Test
|
||||
public void testEmpty() throws Exception
|
||||
{
|
||||
assertIsNotGzipCompressed("empty.txt",0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests gzip compression of a small size file
|
||||
*/
|
||||
|
|
|
@ -79,6 +79,7 @@ public class GzipFilterDefaultTest
|
|||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
|
||||
{
|
||||
resp.setStatus(_status);
|
||||
resp.setHeader("ETag","W/\"204\"");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -141,11 +142,40 @@ public class GzipFilterDefaultTest
|
|||
@Override
|
||||
public void service(HttpServletRequest req, HttpServletResponse resp) throws IOException,ServletException
|
||||
{
|
||||
String uri=req.getRequestURI();
|
||||
if (uri.endsWith(".deferred"))
|
||||
{
|
||||
System.err.println("type for "+uri.substring(0,uri.length()-9)+" is "+getServletContext().getMimeType(uri.substring(0,uri.length()-9)));
|
||||
resp.setContentType(getServletContext().getMimeType(uri.substring(0,uri.length()-9)));
|
||||
}
|
||||
|
||||
doGet(req,resp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testIsGzipCompressedEmpty() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
// Test content that is smaller than the buffer.
|
||||
tester.prepareServerFile("empty.txt",0);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(org.eclipse.jetty.servlet.DefaultServlet.class);
|
||||
holder.setInitParameter("mimeTypes","text/plain");
|
||||
|
||||
try
|
||||
{
|
||||
tester.start();
|
||||
HttpTester.Response http = tester.assertIsResponseNotGzipCompressed("GET","empty.txt",0,200);
|
||||
}
|
||||
finally
|
||||
{
|
||||
tester.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsGzipCompressedTiny() throws Exception
|
||||
|
@ -267,7 +297,7 @@ public class GzipFilterDefaultTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testIsNotGzipCompressed() throws Exception
|
||||
public void testIsNotGzipCompressedByContentType() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
|
@ -289,6 +319,29 @@ public class GzipFilterDefaultTest
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsNotGzipCompressedByDeferredContentType() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
int filesize = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
|
||||
tester.prepareServerFile("file.mp3.deferred",filesize);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(GetServlet.class);
|
||||
holder.setInitParameter("mimeTypes","text/plain");
|
||||
|
||||
try
|
||||
{
|
||||
tester.start();
|
||||
HttpTester.Response http = tester.assertIsResponseNotGzipCompressed("GET","file.mp3.deferred", filesize, HttpStatus.OK_200);
|
||||
Assert.assertNull(http.get("Vary"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
tester.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsNotGzipCompressedHttpStatus() throws Exception
|
||||
{
|
||||
|
|
|
@ -1,258 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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.servlets;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.security.DigestOutputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.Inflater;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
|
||||
import org.eclipse.jetty.server.NetworkConnector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.DefaultServlet;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.servlets.gzip.Hex;
|
||||
import org.eclipse.jetty.servlets.gzip.NoOpOutputStream;
|
||||
import org.eclipse.jetty.toolchain.test.IO;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
/**
|
||||
* Test the effects of Gzip filtering when in the context of HTTP/1.1 Pipelining.
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class GzipWithPipeliningTest
|
||||
{
|
||||
@Parameters
|
||||
public static Collection<String[]> data()
|
||||
{
|
||||
// Test different Content-Encoding header combinations. So implicitly testing that gzip is preferred oder deflate
|
||||
String[][] data = new String[][]
|
||||
{
|
||||
{ GzipFilter.GZIP },
|
||||
{ GzipFilter.DEFLATE + ", " + GzipFilter.GZIP },
|
||||
{ GzipFilter.GZIP + ", " + GzipFilter.DEFLATE },
|
||||
{ GzipFilter.DEFLATE }
|
||||
};
|
||||
|
||||
return Arrays.asList(data);
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestingDir testingdir = new TestingDir();
|
||||
|
||||
private Server server;
|
||||
private URI serverUri;
|
||||
private String encodingHeader;
|
||||
|
||||
|
||||
public GzipWithPipeliningTest(String encodingHeader)
|
||||
{
|
||||
this.encodingHeader = encodingHeader;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void startServer() throws Exception
|
||||
{
|
||||
// Configure Server
|
||||
server = new Server(0);
|
||||
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setContextPath("/");
|
||||
|
||||
DefaultServlet servlet = new DefaultServlet();
|
||||
ServletHolder holder = new ServletHolder(servlet);
|
||||
holder.setInitParameter("resourceBase",MavenTestingUtils.getTestResourcesDir().getAbsolutePath());
|
||||
context.addServlet(holder,"/");
|
||||
|
||||
FilterHolder filter = context.addFilter(GzipFilter.class,"/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
filter.setInitParameter("mimeTypes","text/plain");
|
||||
|
||||
server.setHandler(context);
|
||||
|
||||
// Start Server
|
||||
server.start();
|
||||
|
||||
serverUri = server.getURI();
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGzipThenImagePipelining() throws Exception
|
||||
{
|
||||
testingdir.ensureEmpty();
|
||||
File outputDir = testingdir.getDir();
|
||||
|
||||
PipelineHelper client = new PipelineHelper(serverUri, encodingHeader);
|
||||
|
||||
try
|
||||
{
|
||||
File txtFile = MavenTestingUtils.getTestResourceFile("lots-of-fantasy-names.txt");
|
||||
File pngFile = MavenTestingUtils.getTestResourceFile("jetty_logo.png");
|
||||
|
||||
// Size of content, as it exists on disk, without gzip compression.
|
||||
long rawsize = txtFile.length() + pngFile.length();
|
||||
assertThat("Ensure that we have sufficient file size to trigger chunking",rawsize,greaterThan(300000L));
|
||||
|
||||
String respHeader;
|
||||
|
||||
client.connect();
|
||||
|
||||
// Request text that will be gzipped + chunked in the response
|
||||
client.issueGET("/lots-of-fantasy-names.txt",true, false);
|
||||
|
||||
respHeader = client.readResponseHeader();
|
||||
//System.out.println("Response Header #1 --\n" + respHeader);
|
||||
String expectedEncodingHeader = encodingHeader.equals(GzipFilter.DEFLATE) ? GzipFilter.DEFLATE : GzipFilter.GZIP;
|
||||
assertThat("Content-Encoding should be gzipped",respHeader,containsString("Content-Encoding: " + expectedEncodingHeader + "\r\n"));
|
||||
assertThat("Transfer-Encoding should be chunked",respHeader,containsString("Transfer-Encoding: chunked\r\n"));
|
||||
|
||||
// Raw output / gzipped, writted to disk (checked for sha1sum later)
|
||||
File rawOutputFile = new File(outputDir, "response-1.gz");
|
||||
FileOutputStream rawOutputStream = new FileOutputStream(rawOutputFile);
|
||||
|
||||
long chunkSize = client.readChunkSize();
|
||||
//System.out.println("Chunk Size: " + chunkSize);
|
||||
|
||||
// Read only 20% - intentionally a partial read.
|
||||
//System.out.println("Attempting to read partial content ...");
|
||||
int readBytes = client.readBody(rawOutputStream,(int)(chunkSize * 0.20f));
|
||||
//System.out.printf("Read %,d bytes%n",readBytes);
|
||||
|
||||
// Issue another request
|
||||
client.issueGET("/jetty_logo.png",true, false);
|
||||
|
||||
// Finish reading chunks
|
||||
//System.out.println("Finish reading remaining chunks ...");
|
||||
String line;
|
||||
chunkSize = chunkSize - readBytes;
|
||||
while (chunkSize > 0)
|
||||
{
|
||||
readBytes = client.readBody(rawOutputStream,(int)chunkSize);
|
||||
//System.out.printf("Read %,d bytes%n",readBytes);
|
||||
line = client.readLine();
|
||||
assertThat("Chunk delim should be an empty line with CR+LF",line,is(""));
|
||||
chunkSize = client.readChunkSize();
|
||||
//System.out.printf("Next Chunk: (0x%X) %,d bytes%n",chunkSize,chunkSize);
|
||||
}
|
||||
|
||||
// Inter-pipeline delim
|
||||
line = client.readLine();
|
||||
assertThat("Inter-pipeline delim should be an empty line with CR+LF",line,is(""));
|
||||
|
||||
// Sha1tracking for 1st Request
|
||||
MessageDigest digestTxt = MessageDigest.getInstance("SHA1");
|
||||
DigestOutputStream digesterTxt = new DigestOutputStream(new NoOpOutputStream(),digestTxt);
|
||||
|
||||
// Decompress 1st request and calculate sha1sum
|
||||
IO.close(rawOutputStream);
|
||||
FileInputStream rawInputStream = new FileInputStream(rawOutputFile);
|
||||
InputStream uncompressedStream = null;
|
||||
if (GzipFilter.DEFLATE.equals(encodingHeader))
|
||||
{
|
||||
uncompressedStream = new InflaterInputStream(rawInputStream, new Inflater(true));
|
||||
}
|
||||
else
|
||||
{
|
||||
uncompressedStream = new GZIPInputStream(rawInputStream);
|
||||
}
|
||||
|
||||
IO.copy(uncompressedStream, digesterTxt);
|
||||
|
||||
// Read 2nd request http response header
|
||||
respHeader = client.readResponseHeader();
|
||||
//System.out.println("Response Header #2 --\n" + respHeader);
|
||||
assertThat("Content-Encoding should NOT be gzipped",respHeader,not(containsString("Content-Encoding: gzip\r\n")));
|
||||
assertThat("Transfer-Encoding should NOT be chunked",respHeader,not(containsString("Transfer-Encoding: chunked\r\n")));
|
||||
|
||||
// Sha1tracking for 2nd Request
|
||||
MessageDigest digestImg = MessageDigest.getInstance("SHA1");
|
||||
DigestOutputStream digesterImg = new DigestOutputStream(new NoOpOutputStream(),digestImg);
|
||||
|
||||
// Read 2nd request body
|
||||
int contentLength = client.getContentLength(respHeader);
|
||||
assertThat("Image Content Length",(long)contentLength,is(pngFile.length()));
|
||||
client.readBody(digesterImg,contentLength);
|
||||
|
||||
// Validate checksums
|
||||
IO.close(rawOutputStream);
|
||||
assertChecksum("lots-of-fantasy-names.txt",digestTxt);
|
||||
IO.close(digesterImg);
|
||||
assertChecksum("jetty_logo.png",digestImg);
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private void assertChecksum(String testResourceFile, MessageDigest digest) throws IOException
|
||||
{
|
||||
String expectedSha1 = loadSha1sum(testResourceFile + ".sha1");
|
||||
String actualSha1 = Hex.asHex(digest.digest());
|
||||
assertEquals(testResourceFile + " / SHA1Sum of content",expectedSha1,actualSha1);
|
||||
}
|
||||
|
||||
private String loadSha1sum(String testResourceSha1Sum) throws IOException
|
||||
{
|
||||
File sha1File = MavenTestingUtils.getTestResourceFile(testResourceSha1Sum);
|
||||
String contents = IO.readToString(sha1File);
|
||||
Pattern pat = Pattern.compile("^[0-9A-Fa-f]*");
|
||||
Matcher mat = pat.matcher(contents);
|
||||
assertTrue("Should have found HEX code in SHA1 file: " + sha1File,mat.find());
|
||||
return mat.group();
|
||||
}
|
||||
|
||||
}
|
|
@ -55,6 +55,7 @@ import org.eclipse.jetty.servlets.GzipFilter;
|
|||
import org.eclipse.jetty.toolchain.test.IO;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
|
||||
public class GzipTester
|
||||
|
@ -105,6 +106,8 @@ public class GzipTester
|
|||
else
|
||||
Assert.assertThat("Response.header[Content-Encoding]", response.get("Content-Encoding"),containsString(compressionType.substring(0,qindex)));
|
||||
|
||||
Assert.assertThat(response.get("ETag"),Matchers.startsWith("W/"));
|
||||
|
||||
// Assert that the decompressed contents are what we expect.
|
||||
File serverFile = testdir.getFile(serverFilename);
|
||||
String expected = IO.readToString(serverFile);
|
||||
|
@ -182,6 +185,8 @@ public class GzipTester
|
|||
Assert.assertThat(prefix + ".header[Content-Type] (should have a Content-Type associated with it)",response.get("Content-Type"),notNullValue());
|
||||
Assert.assertThat(prefix + ".header[Content-Type]",response.get("Content-Type"),is(expectedContentType));
|
||||
|
||||
Assert.assertThat(response.get("ETAG"),Matchers.startsWith("W/"));
|
||||
|
||||
ByteArrayInputStream bais = null;
|
||||
DigestOutputStream digester = null;
|
||||
try
|
||||
|
@ -308,6 +313,10 @@ public class GzipTester
|
|||
int serverLength = Integer.parseInt(response.get("Content-Length"));
|
||||
Assert.assertEquals(serverLength,expectedFilesize);
|
||||
}
|
||||
|
||||
if (status>=200 && status<300)
|
||||
Assert.assertThat(response.get("ETAG"),Matchers.startsWith("W/"));
|
||||
|
||||
}
|
||||
Assert.assertThat("Response.header[Content-Encoding]",response.get("Content-Encoding"),not(containsString(compressionType)));
|
||||
}
|
||||
|
@ -337,11 +346,11 @@ public class GzipTester
|
|||
ByteArrayOutputStream out = null;
|
||||
try
|
||||
{
|
||||
in = new ByteArrayInputStream(response.getContentBytes());
|
||||
out = new ByteArrayOutputStream();
|
||||
IO.copy(in,out);
|
||||
|
||||
actual = out.toString(encoding);
|
||||
byte[] content=response.getContentBytes();
|
||||
if (content!=null)
|
||||
actual=new String(response.getContentBytes(),encoding);
|
||||
else
|
||||
actual="";
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -424,7 +433,7 @@ public class GzipTester
|
|||
finally
|
||||
{
|
||||
IO.close(in);
|
||||
IO.close(fos);
|
||||
IO.close(fos);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -456,6 +465,7 @@ public class GzipTester
|
|||
tester.setResourceBase(testdir.getDir().getCanonicalPath());
|
||||
ServletHolder servletHolder = tester.addServlet(servletClass,"/");
|
||||
servletHolder.setInitParameter("baseDir",testdir.getDir().getAbsolutePath());
|
||||
servletHolder.setInitParameter("etags","true");
|
||||
FilterHolder holder = tester.addFilter(gzipFilterClass,"/*",EnumSet.allOf(DispatcherType.class));
|
||||
holder.setInitParameter("vary","Accept-Encoding");
|
||||
return holder;
|
||||
|
|
|
@ -50,6 +50,7 @@ public class TestMinGzipSizeServlet extends TestDirContentServlet
|
|||
byte[] dataBytes = loadContentFileBytes(fileName);
|
||||
|
||||
response.setContentLength(dataBytes.length);
|
||||
response.setHeader("ETag","W/etag-"+fileName);
|
||||
if (fileName.endsWith(".js"))
|
||||
{
|
||||
// intentionally long-form content type to test ";" splitting in code
|
||||
|
|
|
@ -59,6 +59,7 @@ public class TestServletLengthStreamTypeWrite extends TestDirContentServlet
|
|||
response.setContentType("text/plain");
|
||||
else if (fileName.endsWith("mp3"))
|
||||
response.setContentType("audio/mpeg");
|
||||
response.setHeader("ETag","W/etag-"+fileName);
|
||||
|
||||
out.write(dataBytes);
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ public class TestServletLengthTypeStreamWrite extends TestDirContentServlet
|
|||
response.setContentType("text/plain");
|
||||
else if (fileName.endsWith("mp3"))
|
||||
response.setContentType("audio/mpeg");
|
||||
response.setHeader("ETag","W/etag-"+fileName);
|
||||
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
out.write(dataBytes);
|
||||
|
|
|
@ -59,6 +59,7 @@ public class TestServletStreamLengthTypeWrite extends TestDirContentServlet
|
|||
response.setContentType("text/plain");
|
||||
else if (fileName.endsWith("mp3"))
|
||||
response.setContentType("audio/mpeg");
|
||||
response.setHeader("ETag","W/etag-"+fileName);
|
||||
|
||||
out.write(dataBytes);
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ public class TestServletStreamTypeLengthWrite extends TestDirContentServlet
|
|||
response.setContentType("text/plain");
|
||||
else if (fileName.endsWith("mp3"))
|
||||
response.setContentType("audio/mpeg");
|
||||
response.setHeader("ETag","W/etag-"+fileName);
|
||||
|
||||
response.setContentLength(dataBytes.length);
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ public class TestServletTypeLengthStreamWrite extends TestDirContentServlet
|
|||
response.setContentType("text/plain");
|
||||
else if (fileName.endsWith("mp3"))
|
||||
response.setContentType("audio/mpeg");
|
||||
response.setHeader("ETag","W/etag-"+fileName);
|
||||
|
||||
response.setContentLength(dataBytes.length);
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ public class TestServletTypeStreamLengthWrite extends TestDirContentServlet
|
|||
response.setContentType("text/plain");
|
||||
else if (fileName.endsWith("mp3"))
|
||||
response.setContentType("audio/mpeg");
|
||||
response.setHeader("ETag","W/etag-"+fileName);
|
||||
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ public class TestStaticMimeTypeServlet extends TestDirContentServlet
|
|||
byte[] dataBytes = loadContentFileBytes(fileName);
|
||||
|
||||
response.setContentLength(dataBytes.length);
|
||||
response.setHeader("ETag","W/etag-"+fileName);
|
||||
|
||||
String mime = mimeTypes.getMimeByExtension(fileName);
|
||||
if (mime == null)
|
||||
|
|
Loading…
Reference in New Issue