Merge branch 'jetty-8' into release-8
This commit is contained in:
commit
70d41f3a52
|
@ -38,3 +38,4 @@ target/
|
|||
|
||||
#maven
|
||||
*.versionsBackup
|
||||
*.releaseBackup
|
||||
|
|
|
@ -29,7 +29,11 @@ public class OneWebApp
|
|||
server.setConnectors(new Connector[]
|
||||
{ connector });
|
||||
|
||||
String war = args.length > 0?args[0]: "../test-jetty-webapp/target/test-jetty-webapp-" + Server.getVersion();
|
||||
|
||||
//If you're running this from inside Eclipse, then Server.getVersion will not provide
|
||||
//the correct number as there is no manifest. Use the command line instead to provide the path to the
|
||||
//test webapp
|
||||
String war = args.length > 0?args[0]: "../test-jetty-webapp/target/test-jetty-webapp-"+Server.getVersion();
|
||||
String path = args.length > 1?args[1]:"/";
|
||||
|
||||
System.err.println(war + " " + path);
|
||||
|
@ -37,6 +41,15 @@ public class OneWebApp
|
|||
WebAppContext webapp = new WebAppContext();
|
||||
webapp.setContextPath(path);
|
||||
webapp.setWar(war);
|
||||
|
||||
//If the webapp contains security constraints, you will need to configure a LoginService
|
||||
if (war.contains("test-jetty-webapp"))
|
||||
{
|
||||
org.eclipse.jetty.security.HashLoginService loginService = new org.eclipse.jetty.security.HashLoginService();
|
||||
loginService.setName("Test Realm");
|
||||
loginService.setConfig("src/test/resources/realm.properties");
|
||||
webapp.getSecurityHandler().setLoginService(loginService);
|
||||
}
|
||||
|
||||
server.setHandler(webapp);
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<version>8.1.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.aggregate</groupId>
|
||||
<artifactId>jetty-all-server</artifactId>
|
||||
<name>Jetty :: Aggregate :: All Server</name>
|
||||
<properties>
|
||||
|
@ -80,6 +79,8 @@
|
|||
!org.eclipse.jetty*,
|
||||
javax.annotation;version="1.0.0";resolution:=optional,
|
||||
javax.servlet;version="2.6.0",
|
||||
javax.servlet.annotation;version="2.6.0",
|
||||
javax.servlet.descriptor;version="2.6.0",
|
||||
javax.servlet.http;version="2.6.0",
|
||||
javax.mail;version="1.4.0";resolution:=optional,
|
||||
javax.mail.event;version="1.4.0";resolution:=optional,
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<version>8.1.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.aggregate</groupId>
|
||||
<artifactId>jetty-client</artifactId>
|
||||
<name>Jetty :: Aggregate :: HTTP Client</name>
|
||||
|
||||
|
|
|
@ -36,10 +36,10 @@ public class Ajp13SocketConnector extends SocketConnector
|
|||
static boolean __allowShutdown = false;
|
||||
public Ajp13SocketConnector()
|
||||
{
|
||||
super.setRequestHeaderSize(Ajp13Packet.MAX_DATA_SIZE);
|
||||
super.setResponseHeaderSize(Ajp13Packet.MAX_DATA_SIZE);
|
||||
super.setRequestBufferSize(Ajp13Packet.MAX_DATA_SIZE);
|
||||
super.setResponseBufferSize(Ajp13Packet.MAX_DATA_SIZE);
|
||||
super.setRequestHeaderSize(Ajp13Packet.MAX_PACKET_SIZE);
|
||||
super.setResponseHeaderSize(Ajp13Packet.MAX_PACKET_SIZE);
|
||||
super.setRequestBufferSize(Ajp13Packet.MAX_PACKET_SIZE);
|
||||
super.setResponseBufferSize(Ajp13Packet.MAX_PACKET_SIZE);
|
||||
// IN AJP protocol the socket stay open, so
|
||||
// by default the time out is set to 0 seconds
|
||||
super.setMaxIdleTime(0);
|
||||
|
|
|
@ -171,7 +171,7 @@ public class HttpClient extends AggregateLifeCycle implements HttpBuffers, Attri
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the ThreadPool.
|
||||
* The threadpool passed is added via {@link #addBean(Object)} so that
|
||||
* The threadpool passed is added via {@link #addBean(Object)} so that
|
||||
* it's lifecycle may be managed as a {@link AggregateLifeCycle}.
|
||||
* @param threadPool the threadPool to set
|
||||
*/
|
||||
|
@ -878,7 +878,7 @@ public class HttpClient extends AggregateLifeCycle implements HttpBuffers, Attri
|
|||
@Deprecated
|
||||
public void setProvider(String provider)
|
||||
{
|
||||
setProvider(provider);
|
||||
_sslContextFactory.setProvider(provider);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -475,10 +475,12 @@ public class HttpDestination implements Dumpable
|
|||
HttpEventListener elistener = (HttpEventListener)constructor.newInstance(this, ex);
|
||||
ex.setEventListener(elistener);
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (final Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
throw new IOException("Unable to instantiate registered listener for destination: " + listenerClass);
|
||||
throw new IOException("Unable to instantiate registered listener for destination: " + listenerClass)
|
||||
{
|
||||
{initCause(e);}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -276,6 +276,11 @@ class SelectConnector extends AggregateLifeCycle implements HttpClient.Connector
|
|||
_endp.shutdownOutput();
|
||||
}
|
||||
|
||||
public void dispatch()
|
||||
{
|
||||
_endp.asyncDispatch();
|
||||
}
|
||||
|
||||
public void asyncDispatch()
|
||||
{
|
||||
_endp.asyncDispatch();
|
||||
|
|
|
@ -104,8 +104,7 @@ public class DigestAuthentication implements Authentication
|
|||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,8 +118,7 @@ public class DigestAuthentication implements Authentication
|
|||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
package org.eclipse.jetty.continuation;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletRequestWrapper;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
@ -36,7 +35,7 @@ public class ContinuationSupport
|
|||
static
|
||||
{
|
||||
boolean servlet3Support=false;
|
||||
Constructor<?>s3cc=null;
|
||||
Constructor<? extends Continuation>s3cc=null;
|
||||
try
|
||||
{
|
||||
boolean servlet3=ServletRequest.class.getMethod("startAsync")!=null;
|
||||
|
@ -52,11 +51,11 @@ public class ContinuationSupport
|
|||
finally
|
||||
{
|
||||
__servlet3=servlet3Support;
|
||||
__newServlet3Continuation=(Constructor<? extends Continuation>)s3cc;
|
||||
__newServlet3Continuation=s3cc;
|
||||
}
|
||||
|
||||
|
||||
boolean jetty6Support=false;
|
||||
Constructor<?>j6cc=null;
|
||||
Constructor<? extends Continuation>j6cc=null;
|
||||
try
|
||||
{
|
||||
Class<?> jetty6ContinuationClass = ContinuationSupport.class.getClassLoader().loadClass("org.mortbay.util.ajax.Continuation");
|
||||
|
@ -73,9 +72,9 @@ public class ContinuationSupport
|
|||
finally
|
||||
{
|
||||
__jetty6=jetty6Support;
|
||||
__newJetty6Continuation=(Constructor<? extends Continuation>)j6cc;
|
||||
__newJetty6Continuation=j6cc;
|
||||
}
|
||||
|
||||
|
||||
Class<?> waiting=null;
|
||||
try
|
||||
{
|
||||
|
@ -93,12 +92,12 @@ public class ContinuationSupport
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Get a Continuation. The type of the Continuation returned may
|
||||
* vary depending on the container in which the application is
|
||||
* vary depending on the container in which the application is
|
||||
* deployed. It may be an implementation native to the container (eg
|
||||
* org.eclipse.jetty.server.AsyncContinuation) or one of the utility
|
||||
* implementations provided such as an internal <code>FauxContinuation</code>
|
||||
* or a real implementation like {@link org.eclipse.jetty.continuation.Servlet3Continuation}.
|
||||
* @param request The request
|
||||
* @param request The request
|
||||
* @return a Continuation instance
|
||||
*/
|
||||
public static Continuation getContinuation(ServletRequest request)
|
||||
|
@ -106,10 +105,10 @@ public class ContinuationSupport
|
|||
Continuation continuation = (Continuation) request.getAttribute(Continuation.ATTRIBUTE);
|
||||
if (continuation!=null)
|
||||
return continuation;
|
||||
|
||||
|
||||
while (request instanceof ServletRequestWrapper)
|
||||
request=((ServletRequestWrapper)request).getRequest();
|
||||
|
||||
|
||||
if (__servlet3 )
|
||||
{
|
||||
try
|
||||
|
|
|
@ -3,7 +3,6 @@ package org.eclipse.jetty.continuation;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.AsyncEvent;
|
||||
import javax.servlet.AsyncListener;
|
||||
|
@ -16,7 +15,7 @@ import javax.servlet.ServletResponseWrapper;
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* This implementation of Continuation is used by {@link ContinuationSupport}
|
||||
* when it detects that the application has been deployed in a non-jetty Servlet 3
|
||||
* when it detects that the application has been deployed in a non-jetty Servlet 3
|
||||
* server.
|
||||
*/
|
||||
public class Servlet3Continuation implements Continuation
|
||||
|
@ -24,11 +23,11 @@ public class Servlet3Continuation implements Continuation
|
|||
// Exception reused for all continuations
|
||||
// Turn on debug in ContinuationFilter to see real stack trace.
|
||||
private final static ContinuationThrowable __exception = new ContinuationThrowable();
|
||||
|
||||
|
||||
private final ServletRequest _request;
|
||||
private ServletResponse _response;
|
||||
private AsyncContext _context;
|
||||
private List<AsyncListener> _listeners=new ArrayList<AsyncListener>();
|
||||
private List<AsyncListener> _listeners=new ArrayList<AsyncListener>();
|
||||
private volatile boolean _initial=true;
|
||||
private volatile boolean _resumed=false;
|
||||
private volatile boolean _expired=false;
|
||||
|
@ -59,7 +58,6 @@ public class Servlet3Continuation implements Continuation
|
|||
public void onTimeout(AsyncEvent event) throws IOException
|
||||
{
|
||||
_initial=false;
|
||||
System.err.println("Doing dispatch on timed out continuation for "+_request.getAttribute("FOO"));
|
||||
event.getAsyncContext().dispatch();
|
||||
}
|
||||
});
|
||||
|
@ -91,7 +89,7 @@ public class Servlet3Continuation implements Continuation
|
|||
listener.onTimeout(Servlet3Continuation.this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
if (_context!=null)
|
||||
_context.addListener(wrapped);
|
||||
else
|
||||
|
@ -171,7 +169,7 @@ public class Servlet3Continuation implements Continuation
|
|||
_expired=false;
|
||||
_context=_request.startAsync();
|
||||
_context.setTimeout(_timeoutMs);
|
||||
|
||||
|
||||
for (AsyncListener listener:_listeners)
|
||||
_context.addListener(listener);
|
||||
_listeners.clear();
|
||||
|
@ -184,7 +182,7 @@ public class Servlet3Continuation implements Continuation
|
|||
_expired=false;
|
||||
_context=_request.startAsync();
|
||||
_context.setTimeout(_timeoutMs);
|
||||
|
||||
|
||||
for (AsyncListener listener:_listeners)
|
||||
_context.addListener(listener);
|
||||
_listeners.clear();
|
||||
|
|
|
@ -103,6 +103,16 @@
|
|||
<outputDirectory>${assembly-directory}/webapps</outputDirectory>
|
||||
<destFileName>test.war</destFileName>
|
||||
</artifactItem>
|
||||
<artifactItem>
|
||||
<groupId>org.eclipse.jetty.spdy</groupId>
|
||||
<artifactId>spdy-jetty-http-webapp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>war</type>
|
||||
<overWrite>true</overWrite>
|
||||
<includes>**</includes>
|
||||
<outputDirectory>${assembly-directory}/webapps</outputDirectory>
|
||||
<destFileName>spdy.war</destFileName>
|
||||
</artifactItem>
|
||||
<artifactItem>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-start</artifactId>
|
||||
|
@ -124,12 +134,24 @@
|
|||
</goals>
|
||||
<configuration>
|
||||
<includeGroupIds>org.eclipse.jetty</includeGroupIds>
|
||||
<excludeGroupIds>org.eclipse.jetty.orbit</excludeGroupIds>
|
||||
<excludeGroupIds>org.eclipse.jetty.orbit,org.eclipse.jetty.spdy</excludeGroupIds>
|
||||
<excludeArtifactIds>jetty-all,jetty-start,jetty-monitor,jetty-jsp</excludeArtifactIds>
|
||||
<includeTypes>jar</includeTypes>
|
||||
<outputDirectory>${assembly-directory}/lib</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-lib-spdy-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<includeGroupIds>org.eclipse.jetty.spdy</includeGroupIds>
|
||||
<includeTypes>jar</includeTypes>
|
||||
<outputDirectory>${assembly-directory}/lib/spdy</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-orbit-servlet-api-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
|
@ -222,7 +244,7 @@
|
|||
<goal>unpack-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<includeGroupIds>org.eclipse.jetty</includeGroupIds>
|
||||
<includeGroupIds>org.eclipse.jetty,org.eclipse.jetty.spdy</includeGroupIds>
|
||||
<classifier>config</classifier>
|
||||
<failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
|
||||
<excludes>META-INF/**</excludes>
|
||||
|
@ -398,6 +420,27 @@
|
|||
<artifactId>jetty-overlay-deployer</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.spdy</groupId>
|
||||
<artifactId>spdy-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.spdy</groupId>
|
||||
<artifactId>spdy-jetty</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.spdy</groupId>
|
||||
<artifactId>spdy-jetty-http</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.spdy</groupId>
|
||||
<artifactId>spdy-jetty-http-webapp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.aggregate</groupId>
|
||||
<artifactId>jetty-all</artifactId>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
|
|
|
@ -295,7 +295,6 @@ public class HttpFields
|
|||
/* -------------------------------------------------------------- */
|
||||
private final ArrayList<Field> _fields = new ArrayList<Field>(20);
|
||||
private final HashMap<Buffer,Field> _names = new HashMap<Buffer,Field>(32);
|
||||
private final int _maxCookieVersion;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
@ -303,19 +302,8 @@ public class HttpFields
|
|||
*/
|
||||
public HttpFields()
|
||||
{
|
||||
_maxCookieVersion=1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public HttpFields(int maxCookieVersion)
|
||||
{
|
||||
_maxCookieVersion=maxCookieVersion;
|
||||
}
|
||||
|
||||
|
||||
// TODO externalize this cache so it can be configurable
|
||||
private static ConcurrentMap<String, Buffer> __cache = new ConcurrentHashMap<String, Buffer>();
|
||||
private static int __cacheSize = Integer.getInteger("org.eclipse.jetty.http.HttpFields.CACHE",2000);
|
||||
|
@ -971,7 +959,7 @@ public class HttpFields
|
|||
final boolean isHttpOnly,
|
||||
int version)
|
||||
{
|
||||
String delim=_maxCookieVersion==0?"":__COOKIE_DELIM;
|
||||
String delim=__COOKIE_DELIM;
|
||||
|
||||
// Check arguments
|
||||
if (name == null || name.length() == 0)
|
||||
|
@ -980,29 +968,18 @@ public class HttpFields
|
|||
// Format value and params
|
||||
StringBuilder buf = new StringBuilder(128);
|
||||
String name_value_params;
|
||||
boolean quoted = QuotedStringTokenizer.quoteIfNeeded(buf, name, delim);
|
||||
QuotedStringTokenizer.quoteIfNeeded(buf, name, delim);
|
||||
buf.append('=');
|
||||
String start=buf.toString();
|
||||
if (value != null && value.length() > 0)
|
||||
quoted|=QuotedStringTokenizer.quoteIfNeeded(buf, value, delim);
|
||||
|
||||
// upgrade to version 1 cookies if quoted.
|
||||
if (quoted&&version==0 && _maxCookieVersion>=1)
|
||||
version=1;
|
||||
QuotedStringTokenizer.quoteIfNeeded(buf, value, delim);
|
||||
|
||||
if (version>_maxCookieVersion)
|
||||
version=_maxCookieVersion;
|
||||
|
||||
if (version > 0)
|
||||
if (comment != null && comment.length() > 0)
|
||||
{
|
||||
buf.append(";Version=");
|
||||
buf.append(version);
|
||||
if (comment != null && comment.length() > 0)
|
||||
{
|
||||
buf.append(";Comment=");
|
||||
QuotedStringTokenizer.quoteIfNeeded(buf, comment, delim);
|
||||
}
|
||||
buf.append(";Comment=");
|
||||
QuotedStringTokenizer.quoteIfNeeded(buf, comment, delim);
|
||||
}
|
||||
|
||||
if (path != null && path.length() > 0)
|
||||
{
|
||||
buf.append(";Path=");
|
||||
|
@ -1019,23 +996,19 @@ public class HttpFields
|
|||
|
||||
if (maxAge >= 0)
|
||||
{
|
||||
// Always add the expires param as some browsers still don't handle max-age
|
||||
buf.append(";Expires=");
|
||||
if (maxAge == 0)
|
||||
buf.append(__01Jan1970_COOKIE);
|
||||
else
|
||||
formatCookieDate(buf, System.currentTimeMillis() + 1000L * maxAge);
|
||||
|
||||
// Always add the expires param as some browsers still don't handle max-age
|
||||
buf.append(";Expires=");
|
||||
if (maxAge == 0)
|
||||
buf.append(__01Jan1970_COOKIE);
|
||||
else
|
||||
formatCookieDate(buf, System.currentTimeMillis() + 1000L * maxAge);
|
||||
|
||||
if (version >0)
|
||||
{
|
||||
buf.append(";Max-Age=");
|
||||
buf.append(maxAge);
|
||||
}
|
||||
}
|
||||
else if (version > 0)
|
||||
{
|
||||
buf.append(";Discard");
|
||||
}
|
||||
|
||||
if (isSecure)
|
||||
buf.append(";Secure");
|
||||
|
|
|
@ -260,7 +260,6 @@ public class HttpParser implements Parser
|
|||
{
|
||||
_state=STATE_END;
|
||||
_handler.messageComplete(_contentPosition);
|
||||
returnBuffers();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -326,7 +325,6 @@ public class HttpParser implements Parser
|
|||
if (!isComplete() && !isIdle())
|
||||
throw new EofException();
|
||||
|
||||
returnBuffers();
|
||||
return -1;
|
||||
}
|
||||
length=_buffer.length();
|
||||
|
@ -440,7 +438,6 @@ public class HttpParser implements Parser
|
|||
_state=STATE_SEEKING_EOF;
|
||||
_handler.headerComplete();
|
||||
_handler.messageComplete(_contentPosition);
|
||||
returnBuffers();
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
@ -470,7 +467,6 @@ public class HttpParser implements Parser
|
|||
_state=STATE_SEEKING_EOF;
|
||||
_handler.headerComplete();
|
||||
_handler.messageComplete(_contentPosition);
|
||||
returnBuffers();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -634,7 +630,6 @@ public class HttpParser implements Parser
|
|||
_handler.headerComplete();
|
||||
_state=_persistent||(_responseStatus>=100&&_responseStatus<200)?STATE_END:STATE_SEEKING_EOF;
|
||||
_handler.messageComplete(_contentPosition);
|
||||
returnBuffers();
|
||||
return 1;
|
||||
|
||||
default:
|
||||
|
@ -840,7 +835,6 @@ public class HttpParser implements Parser
|
|||
{
|
||||
_state=_persistent?STATE_END:STATE_SEEKING_EOF;
|
||||
_handler.messageComplete(_contentPosition);
|
||||
returnBuffers();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -860,7 +854,6 @@ public class HttpParser implements Parser
|
|||
{
|
||||
_state=_persistent?STATE_END:STATE_SEEKING_EOF;
|
||||
_handler.messageComplete(_contentPosition);
|
||||
returnBuffers();
|
||||
}
|
||||
// TODO adjust the _buffer to keep unconsumed content
|
||||
return 1;
|
||||
|
@ -895,7 +888,6 @@ public class HttpParser implements Parser
|
|||
_eol=_buffer.get();
|
||||
_state=_persistent?STATE_END:STATE_SEEKING_EOF;
|
||||
_handler.messageComplete(_contentPosition);
|
||||
returnBuffers();
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
@ -926,7 +918,6 @@ public class HttpParser implements Parser
|
|||
_eol=_buffer.get();
|
||||
_state=_persistent?STATE_END:STATE_SEEKING_EOF;
|
||||
_handler.messageComplete(_contentPosition);
|
||||
returnBuffers();
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -0,0 +1,345 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009-2009 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.http.gzip;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.util.ByteArrayOutputStream2;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Skeletal implementation of a CompressedStream. This class adds compression features to a ServletOutputStream and takes care of setting response headers, etc.
|
||||
* Major work and configuration is done here. Subclasses using different kinds of compression only have to implement the abstract methods doCompress() and
|
||||
* setContentEncoding() using the desired compression and setting the appropriate Content-Encoding header string.
|
||||
*/
|
||||
public abstract class AbstractCompressedStream extends ServletOutputStream
|
||||
{
|
||||
private final String _encoding;
|
||||
protected HttpServletRequest _request;
|
||||
protected HttpServletResponse _response;
|
||||
protected OutputStream _out;
|
||||
protected ByteArrayOutputStream2 _bOut;
|
||||
protected DeflaterOutputStream _compressedOutputStream;
|
||||
protected boolean _closed;
|
||||
protected int _bufferSize;
|
||||
protected int _minCompressSize;
|
||||
protected long _contentLength;
|
||||
protected boolean _doNotCompress;
|
||||
|
||||
/**
|
||||
* Instantiates a new compressed stream.
|
||||
*
|
||||
* @param request
|
||||
* the request
|
||||
* @param response
|
||||
* the response
|
||||
* @param contentLength
|
||||
* the content length
|
||||
* @param bufferSize
|
||||
* the buffer size
|
||||
* @param minCompressSize
|
||||
* the min compress size
|
||||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public AbstractCompressedStream(String encoding,HttpServletRequest request, HttpServletResponse response, long contentLength, int bufferSize, int minCompressSize)
|
||||
throws IOException
|
||||
{
|
||||
_encoding=encoding;
|
||||
_request = request;
|
||||
_response = response;
|
||||
_contentLength = contentLength;
|
||||
_bufferSize = bufferSize;
|
||||
_minCompressSize = minCompressSize;
|
||||
if (minCompressSize == 0)
|
||||
doCompress();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset buffer.
|
||||
*/
|
||||
public void resetBuffer()
|
||||
{
|
||||
if (_response.isCommitted())
|
||||
throw new IllegalStateException("Committed");
|
||||
_closed = false;
|
||||
_out = null;
|
||||
_bOut = null;
|
||||
if (_compressedOutputStream != null)
|
||||
_response.setHeader("Content-Encoding",null);
|
||||
_compressedOutputStream = null;
|
||||
_doNotCompress = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content length.
|
||||
*
|
||||
* @param length
|
||||
* the new content length
|
||||
*/
|
||||
public void setContentLength(long length)
|
||||
{
|
||||
_contentLength = length;
|
||||
if (_doNotCompress && length >= 0)
|
||||
{
|
||||
if (_contentLength < Integer.MAX_VALUE)
|
||||
_response.setContentLength((int)_contentLength);
|
||||
else
|
||||
_response.setHeader("Content-Length",Long.toString(_contentLength));
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#flush()
|
||||
*/
|
||||
@Override
|
||||
public void flush() throws IOException
|
||||
{
|
||||
if (_out == null || _bOut != null)
|
||||
{
|
||||
if (_contentLength > 0 && _contentLength < _minCompressSize)
|
||||
doNotCompress();
|
||||
else
|
||||
doCompress();
|
||||
}
|
||||
|
||||
_out.flush();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#close()
|
||||
*/
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
if (_closed)
|
||||
return;
|
||||
|
||||
if (_request.getAttribute("javax.servlet.include.request_uri") != null)
|
||||
flush();
|
||||
else
|
||||
{
|
||||
if (_bOut != null)
|
||||
{
|
||||
if (_contentLength < 0)
|
||||
_contentLength = _bOut.getCount();
|
||||
if (_contentLength < _minCompressSize)
|
||||
doNotCompress();
|
||||
else
|
||||
doCompress();
|
||||
}
|
||||
else if (_out == null)
|
||||
{
|
||||
doNotCompress();
|
||||
}
|
||||
|
||||
if (_compressedOutputStream != null)
|
||||
_compressedOutputStream.close();
|
||||
else
|
||||
_out.close();
|
||||
_closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish.
|
||||
*
|
||||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public void finish() throws IOException
|
||||
{
|
||||
if (!_closed)
|
||||
{
|
||||
if (_out == null || _bOut != null)
|
||||
{
|
||||
if (_contentLength > 0 && _contentLength < _minCompressSize)
|
||||
doNotCompress();
|
||||
else
|
||||
doCompress();
|
||||
}
|
||||
|
||||
if (_compressedOutputStream != null && !_closed)
|
||||
{
|
||||
_closed = true;
|
||||
_compressedOutputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#write(int)
|
||||
*/
|
||||
@Override
|
||||
public void write(int b) throws IOException
|
||||
{
|
||||
checkOut(1);
|
||||
_out.write(b);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#write(byte[])
|
||||
*/
|
||||
@Override
|
||||
public void write(byte b[]) throws IOException
|
||||
{
|
||||
checkOut(b.length);
|
||||
_out.write(b);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#write(byte[], int, int)
|
||||
*/
|
||||
@Override
|
||||
public void write(byte b[], int off, int len) throws IOException
|
||||
{
|
||||
checkOut(len);
|
||||
_out.write(b,off,len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do compress.
|
||||
*
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public void doCompress() throws IOException
|
||||
{
|
||||
if (_compressedOutputStream==null)
|
||||
{
|
||||
if (_response.isCommitted())
|
||||
throw new IllegalStateException();
|
||||
|
||||
setHeader("Content-Encoding", _encoding);
|
||||
|
||||
if (_response.containsHeader("Content-Encoding"))
|
||||
{
|
||||
_out=_compressedOutputStream=createStream();
|
||||
|
||||
if (_bOut!=null)
|
||||
{
|
||||
_out.write(_bOut.getBuf(),0,_bOut.getCount());
|
||||
_bOut=null;
|
||||
}
|
||||
}
|
||||
else
|
||||
doNotCompress();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not compress.
|
||||
*
|
||||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public void doNotCompress() throws IOException
|
||||
{
|
||||
if (_compressedOutputStream != null)
|
||||
throw new IllegalStateException();
|
||||
if (_out == null || _bOut != null)
|
||||
{
|
||||
_doNotCompress = true;
|
||||
|
||||
_out = _response.getOutputStream();
|
||||
setContentLength(_contentLength);
|
||||
|
||||
if (_bOut != null)
|
||||
_out.write(_bOut.getBuf(),0,_bOut.getCount());
|
||||
_bOut = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check out.
|
||||
*
|
||||
* @param length
|
||||
* the length
|
||||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
private void checkOut(int length) throws IOException
|
||||
{
|
||||
if (_closed)
|
||||
throw new IOException("CLOSED");
|
||||
|
||||
if (_out == null)
|
||||
{
|
||||
if (_response.isCommitted() || (_contentLength >= 0 && _contentLength < _minCompressSize))
|
||||
doNotCompress();
|
||||
else if (length > _minCompressSize)
|
||||
doCompress();
|
||||
else
|
||||
_out = _bOut = new ByteArrayOutputStream2(_bufferSize);
|
||||
}
|
||||
else if (_bOut != null)
|
||||
{
|
||||
if (_response.isCommitted() || (_contentLength >= 0 && _contentLength < _minCompressSize))
|
||||
doNotCompress();
|
||||
else if (length >= (_bOut.getBuf().length - _bOut.getCount()))
|
||||
doCompress();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedStream#getOutputStream()
|
||||
*/
|
||||
public OutputStream getOutputStream()
|
||||
{
|
||||
return _out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedStream#isClosed()
|
||||
*/
|
||||
public boolean isClosed()
|
||||
{
|
||||
return _closed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows derived implementations to replace PrintWriter implementation.
|
||||
*/
|
||||
protected PrintWriter newWriter(OutputStream out, String encoding) throws UnsupportedEncodingException
|
||||
{
|
||||
return encoding == null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
|
||||
}
|
||||
|
||||
protected void setHeader(String name,String value)
|
||||
{
|
||||
_response.setHeader(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the stream fitting to the underlying compression type.
|
||||
*
|
||||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
protected abstract DeflaterOutputStream createStream() throws IOException;
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) Webtide LLC
|
||||
// Copyright (c) 2009-2009 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
|
||||
|
@ -11,7 +11,6 @@
|
|||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
|
||||
package org.eclipse.jetty.http.gzip;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -28,42 +27,34 @@ import javax.servlet.http.HttpServletResponseWrapper;
|
|||
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*------------------------------------------------------------ */
|
||||
/**
|
||||
*/
|
||||
public class GzipResponseWrapper extends HttpServletResponseWrapper
|
||||
public abstract class CompressedResponseWrapper extends HttpServletResponseWrapper
|
||||
{
|
||||
public static final int DEFAULT_BUFFER_SIZE = 8192;
|
||||
public static final int DEFAULT_MIN_GZIP_SIZE = 256;
|
||||
|
||||
private HttpServletRequest _request;
|
||||
public static final int DEFAULT_BUFFER_SIZE = 8192;
|
||||
public static final int DEFAULT_MIN_COMPRESS_SIZE = 256;
|
||||
|
||||
private Set<String> _mimeTypes;
|
||||
private int _bufferSize=DEFAULT_BUFFER_SIZE;
|
||||
private int _minGzipSize=DEFAULT_MIN_GZIP_SIZE;
|
||||
private int _minCompressSize=DEFAULT_MIN_COMPRESS_SIZE;
|
||||
protected HttpServletRequest _request;
|
||||
|
||||
private PrintWriter _writer;
|
||||
private GzipStream _gzStream;
|
||||
private AbstractCompressedStream _compressedStream;
|
||||
private long _contentLength=-1;
|
||||
private boolean _noGzip;
|
||||
private boolean _noCompression;
|
||||
|
||||
/**
|
||||
* Instantiates a new gzip response wrapper.
|
||||
*
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
*/
|
||||
public GzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
public CompressedResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
super(response);
|
||||
_request=request;
|
||||
_request = request;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Sets the mime types.
|
||||
*
|
||||
* @param mimeTypes the new mime types
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setMimeTypes(java.util.Set)
|
||||
*/
|
||||
public void setMimeTypes(Set<String> mimeTypes)
|
||||
{
|
||||
|
@ -72,8 +63,9 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#setBufferSize(int)
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setBufferSize(int)
|
||||
*/
|
||||
@Override
|
||||
public void setBufferSize(int bufferSize)
|
||||
{
|
||||
_bufferSize = bufferSize;
|
||||
|
@ -81,64 +73,66 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Sets the min gzip size.
|
||||
*
|
||||
* @param minGzipSize the new min gzip size
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setMinCompressSize(int)
|
||||
*/
|
||||
public void setMinGzipSize(int minGzipSize)
|
||||
public void setMinCompressSize(int minCompressSize)
|
||||
{
|
||||
_minGzipSize = minGzipSize;
|
||||
_minCompressSize = minCompressSize;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#setContentType(java.lang.String)
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setContentType(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void setContentType(String ct)
|
||||
{
|
||||
super.setContentType(ct);
|
||||
|
||||
|
||||
if (ct!=null)
|
||||
{
|
||||
int colon=ct.indexOf(";");
|
||||
if (colon>0)
|
||||
ct=ct.substring(0,colon);
|
||||
}
|
||||
|
||||
if ((_gzStream==null || _gzStream._out==null) &&
|
||||
|
||||
if ((_compressedStream==null || _compressedStream.getOutputStream()==null) &&
|
||||
(_mimeTypes==null && ct!=null && ct.contains("gzip") ||
|
||||
_mimeTypes!=null && (ct==null||!_mimeTypes.contains(StringUtil.asciiToLowerCase(ct)))))
|
||||
{
|
||||
noGzip();
|
||||
noCompression();
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#setStatus(int, java.lang.String)
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setStatus(int, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void setStatus(int sc, String sm)
|
||||
{
|
||||
super.setStatus(sc,sm);
|
||||
if (sc<200 || sc==204 || sc==205 || sc>=300)
|
||||
noGzip();
|
||||
noCompression();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#setStatus(int)
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setStatus(int)
|
||||
*/
|
||||
@Override
|
||||
public void setStatus(int sc)
|
||||
{
|
||||
super.setStatus(sc);
|
||||
if (sc<200 || sc==204 || sc==205 ||sc>=300)
|
||||
noGzip();
|
||||
noCompression();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#setContentLength(int)
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setContentLength(int)
|
||||
*/
|
||||
@Override
|
||||
public void setContentLength(int length)
|
||||
{
|
||||
setContentLength((long)length);
|
||||
|
@ -148,9 +142,9 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
|
|||
protected void setContentLength(long length)
|
||||
{
|
||||
_contentLength=length;
|
||||
if (_gzStream!=null)
|
||||
_gzStream.setContentLength(length);
|
||||
else if (_noGzip && _contentLength>=0)
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.setContentLength(length);
|
||||
else if (_noCompression && _contentLength>=0)
|
||||
{
|
||||
HttpServletResponse response = (HttpServletResponse)getResponse();
|
||||
if(_contentLength<Integer.MAX_VALUE)
|
||||
|
@ -166,15 +160,16 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#addHeader(java.lang.String, java.lang.String)
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#addHeader(java.lang.String, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void addHeader(String name, String value)
|
||||
{
|
||||
if ("content-length".equalsIgnoreCase(name))
|
||||
{
|
||||
_contentLength=Long.parseLong(value);
|
||||
if (_gzStream!=null)
|
||||
_gzStream.setContentLength(_contentLength);
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.setContentLength(_contentLength);
|
||||
}
|
||||
else if ("content-type".equalsIgnoreCase(name))
|
||||
{
|
||||
|
@ -185,7 +180,7 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
|
|||
super.addHeader(name,value);
|
||||
if (!isCommitted())
|
||||
{
|
||||
noGzip();
|
||||
noCompression();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -194,8 +189,119 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#setHeader(java.lang.String, java.lang.String)
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#flushBuffer()
|
||||
*/
|
||||
@Override
|
||||
public void flushBuffer() throws IOException
|
||||
{
|
||||
if (_writer!=null)
|
||||
_writer.flush();
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.finish();
|
||||
else
|
||||
getResponse().flushBuffer();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#reset()
|
||||
*/
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
super.reset();
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.resetBuffer();
|
||||
_writer=null;
|
||||
_compressedStream=null;
|
||||
_noCompression=false;
|
||||
_contentLength=-1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#resetBuffer()
|
||||
*/
|
||||
@Override
|
||||
public void resetBuffer()
|
||||
{
|
||||
super.resetBuffer();
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.resetBuffer();
|
||||
_writer=null;
|
||||
_compressedStream=null;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#sendError(int, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void sendError(int sc, String msg) throws IOException
|
||||
{
|
||||
resetBuffer();
|
||||
super.sendError(sc,msg);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#sendError(int)
|
||||
*/
|
||||
@Override
|
||||
public void sendError(int sc) throws IOException
|
||||
{
|
||||
resetBuffer();
|
||||
super.sendError(sc);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#sendRedirect(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void sendRedirect(String location) throws IOException
|
||||
{
|
||||
resetBuffer();
|
||||
super.sendRedirect(location);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#noCompression()
|
||||
*/
|
||||
public void noCompression()
|
||||
{
|
||||
_noCompression=true;
|
||||
if (_compressedStream!=null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_compressedStream.doNotCompress();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#finish()
|
||||
*/
|
||||
public void finish() throws IOException
|
||||
{
|
||||
if (_writer!=null && !_compressedStream.isClosed())
|
||||
_writer.flush();
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.finish();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setHeader(java.lang.String, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void setHeader(String name, String value)
|
||||
{
|
||||
if ("content-length".equalsIgnoreCase(name))
|
||||
|
@ -211,197 +317,77 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
|
|||
super.setHeader(name,value);
|
||||
if (!isCommitted())
|
||||
{
|
||||
noGzip();
|
||||
noCompression();
|
||||
}
|
||||
}
|
||||
else
|
||||
super.setHeader(name,value);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#setIntHeader(java.lang.String, int)
|
||||
*/
|
||||
public void setIntHeader(String name, int value)
|
||||
{
|
||||
if ("content-length".equalsIgnoreCase(name))
|
||||
{
|
||||
_contentLength=value;
|
||||
if (_gzStream!=null)
|
||||
_gzStream.setContentLength(_contentLength);
|
||||
}
|
||||
else
|
||||
super.setIntHeader(name,value);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#flushBuffer()
|
||||
*/
|
||||
public void flushBuffer() throws IOException
|
||||
{
|
||||
if (_writer!=null)
|
||||
_writer.flush();
|
||||
if (_gzStream!=null)
|
||||
_gzStream.finish();
|
||||
else
|
||||
getResponse().flushBuffer();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#reset()
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
super.reset();
|
||||
if (_gzStream!=null)
|
||||
_gzStream.resetBuffer();
|
||||
_writer=null;
|
||||
_gzStream=null;
|
||||
_noGzip=false;
|
||||
_contentLength=-1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#resetBuffer()
|
||||
*/
|
||||
public void resetBuffer()
|
||||
{
|
||||
super.resetBuffer();
|
||||
if (_gzStream!=null)
|
||||
_gzStream.resetBuffer();
|
||||
_writer=null;
|
||||
_gzStream=null;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#sendError(int, java.lang.String)
|
||||
*/
|
||||
public void sendError(int sc, String msg) throws IOException
|
||||
{
|
||||
resetBuffer();
|
||||
super.sendError(sc,msg);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#sendError(int)
|
||||
*/
|
||||
public void sendError(int sc) throws IOException
|
||||
{
|
||||
resetBuffer();
|
||||
super.sendError(sc);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#sendRedirect(java.lang.String)
|
||||
*/
|
||||
public void sendRedirect(String location) throws IOException
|
||||
{
|
||||
resetBuffer();
|
||||
super.sendRedirect(location);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#getOutputStream()
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#getOutputStream()
|
||||
*/
|
||||
@Override
|
||||
public ServletOutputStream getOutputStream() throws IOException
|
||||
{
|
||||
if (_gzStream==null)
|
||||
if (_compressedStream==null)
|
||||
{
|
||||
if (getResponse().isCommitted() || _noGzip)
|
||||
if (getResponse().isCommitted() || _noCompression)
|
||||
{
|
||||
setContentLength(_contentLength);
|
||||
return getResponse().getOutputStream();
|
||||
}
|
||||
|
||||
_gzStream=newGzipStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minGzipSize);
|
||||
_compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minCompressSize);
|
||||
}
|
||||
else if (_writer!=null)
|
||||
throw new IllegalStateException("getWriter() called");
|
||||
|
||||
return _gzStream;
|
||||
return (ServletOutputStream)_compressedStream;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#getWriter()
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#getWriter()
|
||||
*/
|
||||
@Override
|
||||
public PrintWriter getWriter() throws IOException
|
||||
{
|
||||
if (_writer==null)
|
||||
{
|
||||
if (_gzStream!=null)
|
||||
if (_compressedStream!=null)
|
||||
throw new IllegalStateException("getOutputStream() called");
|
||||
|
||||
if (getResponse().isCommitted() || _noGzip)
|
||||
if (getResponse().isCommitted() || _noCompression)
|
||||
{
|
||||
setContentLength(_contentLength);
|
||||
return getResponse().getWriter();
|
||||
}
|
||||
|
||||
_gzStream=newGzipStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minGzipSize);
|
||||
_writer=newWriter(_gzStream,getCharacterEncoding());
|
||||
_compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minCompressSize);
|
||||
_writer=newWriter((OutputStream)_compressedStream,getCharacterEncoding());
|
||||
}
|
||||
return _writer;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* No gzip.
|
||||
*/
|
||||
public void noGzip()
|
||||
{
|
||||
_noGzip=true;
|
||||
if (_gzStream!=null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_gzStream.doNotGzip();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Finish.
|
||||
*
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setIntHeader(java.lang.String, int)
|
||||
*/
|
||||
public void finish() throws IOException
|
||||
@Override
|
||||
public void setIntHeader(String name, int value)
|
||||
{
|
||||
if (_writer!=null && !_gzStream._closed)
|
||||
_writer.flush();
|
||||
if (_gzStream!=null)
|
||||
_gzStream.finish();
|
||||
if ("content-length".equalsIgnoreCase(name))
|
||||
{
|
||||
_contentLength=value;
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.setContentLength(_contentLength);
|
||||
}
|
||||
else
|
||||
super.setIntHeader(name,value);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Allows derived implementations to replace GzipStream implementation.
|
||||
*
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
* @param contentLength the content length
|
||||
* @param bufferSize the buffer size
|
||||
* @param minGzipSize the min gzip size
|
||||
* @return the gzip stream
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
protected GzipStream newGzipStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minGzipSize) throws IOException
|
||||
{
|
||||
return new GzipStream(request,response,contentLength,bufferSize,minGzipSize);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Allows derived implementations to replace PrintWriter implementation.
|
||||
|
@ -415,5 +401,11 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
|
|||
{
|
||||
return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*@return the underlying CompressedStream implementation
|
||||
*/
|
||||
protected abstract AbstractCompressedStream newCompressedStream(HttpServletRequest _request, HttpServletResponse response, long _contentLength2, int _bufferSize2, int _minCompressedSize2) throws IOException;
|
||||
|
||||
}
|
|
@ -1,305 +0,0 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) Webtide LLC
|
||||
// ------------------------------------------------------------------------
|
||||
// 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.http.gzip;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.util.ByteArrayOutputStream2;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*/
|
||||
public class GzipStream extends ServletOutputStream
|
||||
{
|
||||
protected HttpServletRequest _request;
|
||||
protected HttpServletResponse _response;
|
||||
protected OutputStream _out;
|
||||
protected ByteArrayOutputStream2 _bOut;
|
||||
protected GZIPOutputStream _gzOut;
|
||||
protected boolean _closed;
|
||||
protected int _bufferSize;
|
||||
protected int _minGzipSize;
|
||||
protected long _contentLength;
|
||||
protected boolean _doNotGzip;
|
||||
|
||||
/**
|
||||
* Instantiates a new gzip stream.
|
||||
*
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
* @param contentLength the content length
|
||||
* @param bufferSize the buffer size
|
||||
* @param minGzipSize the min gzip size
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public GzipStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minGzipSize) throws IOException
|
||||
{
|
||||
_request=request;
|
||||
_response=response;
|
||||
_contentLength=contentLength;
|
||||
_bufferSize=bufferSize;
|
||||
_minGzipSize=minGzipSize;
|
||||
if (minGzipSize==0)
|
||||
doGzip();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset buffer.
|
||||
*/
|
||||
public void resetBuffer()
|
||||
{
|
||||
if (_response.isCommitted())
|
||||
throw new IllegalStateException("Committed");
|
||||
_closed=false;
|
||||
_out=null;
|
||||
_bOut=null;
|
||||
if (_gzOut!=null)
|
||||
_response.setHeader("Content-Encoding",null);
|
||||
_gzOut=null;
|
||||
_doNotGzip=false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content length.
|
||||
*
|
||||
* @param length the new content length
|
||||
*/
|
||||
public void setContentLength(long length)
|
||||
{
|
||||
_contentLength=length;
|
||||
if (_doNotGzip && length>=0)
|
||||
{
|
||||
if(_contentLength<Integer.MAX_VALUE)
|
||||
_response.setContentLength((int)_contentLength);
|
||||
else
|
||||
_response.setHeader("Content-Length",Long.toString(_contentLength));
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#flush()
|
||||
*/
|
||||
public void flush() throws IOException
|
||||
{
|
||||
if (_out==null || _bOut!=null)
|
||||
{
|
||||
if (_contentLength>0 && _contentLength<_minGzipSize)
|
||||
doNotGzip();
|
||||
else
|
||||
doGzip();
|
||||
}
|
||||
|
||||
_out.flush();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#close()
|
||||
*/
|
||||
public void close() throws IOException
|
||||
{
|
||||
if (_closed)
|
||||
return;
|
||||
|
||||
if (_request.getAttribute("javax.servlet.include.request_uri")!=null)
|
||||
flush();
|
||||
else
|
||||
{
|
||||
if (_bOut!=null)
|
||||
{
|
||||
if (_contentLength<0)
|
||||
_contentLength=_bOut.getCount();
|
||||
if (_contentLength<_minGzipSize)
|
||||
doNotGzip();
|
||||
else
|
||||
doGzip();
|
||||
}
|
||||
else if (_out==null)
|
||||
{
|
||||
doNotGzip();
|
||||
}
|
||||
|
||||
if (_gzOut!=null)
|
||||
_gzOut.close();
|
||||
else
|
||||
_out.close();
|
||||
_closed=true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish.
|
||||
*
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public void finish() throws IOException
|
||||
{
|
||||
if (!_closed)
|
||||
{
|
||||
if (_out==null || _bOut!=null)
|
||||
{
|
||||
if (_contentLength>0 && _contentLength<_minGzipSize)
|
||||
doNotGzip();
|
||||
else
|
||||
doGzip();
|
||||
}
|
||||
|
||||
if (_gzOut!=null && !_closed)
|
||||
{
|
||||
_closed=true;
|
||||
_gzOut.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#write(int)
|
||||
*/
|
||||
public void write(int b) throws IOException
|
||||
{
|
||||
checkOut(1);
|
||||
_out.write(b);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#write(byte[])
|
||||
*/
|
||||
public void write(byte b[]) throws IOException
|
||||
{
|
||||
checkOut(b.length);
|
||||
_out.write(b);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#write(byte[], int, int)
|
||||
*/
|
||||
public void write(byte b[], int off, int len) throws IOException
|
||||
{
|
||||
checkOut(len);
|
||||
_out.write(b,off,len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content encoding gzip.
|
||||
*
|
||||
* @return true, if successful
|
||||
*/
|
||||
protected boolean setContentEncodingGzip()
|
||||
{
|
||||
_response.setHeader("Content-Encoding", "gzip");
|
||||
return _response.containsHeader("Content-Encoding");
|
||||
}
|
||||
|
||||
/**
|
||||
* Do gzip.
|
||||
*
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public void doGzip() throws IOException
|
||||
{
|
||||
if (_gzOut==null)
|
||||
{
|
||||
if (_response.isCommitted())
|
||||
throw new IllegalStateException();
|
||||
|
||||
if (setContentEncodingGzip())
|
||||
{
|
||||
_out=_gzOut=new GZIPOutputStream(_response.getOutputStream(),_bufferSize);
|
||||
|
||||
if (_bOut!=null)
|
||||
{
|
||||
_out.write(_bOut.getBuf(),0,_bOut.getCount());
|
||||
_bOut=null;
|
||||
}
|
||||
}
|
||||
else
|
||||
doNotGzip();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not gzip.
|
||||
*
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public void doNotGzip() throws IOException
|
||||
{
|
||||
if (_gzOut!=null)
|
||||
throw new IllegalStateException();
|
||||
if (_out==null || _bOut!=null )
|
||||
{
|
||||
_doNotGzip = true;
|
||||
|
||||
_out=_response.getOutputStream();
|
||||
setContentLength(_contentLength);
|
||||
|
||||
if (_bOut!=null)
|
||||
_out.write(_bOut.getBuf(),0,_bOut.getCount());
|
||||
_bOut=null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check out.
|
||||
*
|
||||
* @param length the length
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
private void checkOut(int length) throws IOException
|
||||
{
|
||||
if (_closed)
|
||||
throw new IOException("CLOSED");
|
||||
|
||||
if (_out==null)
|
||||
{
|
||||
if (_response.isCommitted() || (_contentLength>=0 && _contentLength<_minGzipSize))
|
||||
doNotGzip();
|
||||
else if (length>_minGzipSize)
|
||||
doGzip();
|
||||
else
|
||||
_out=_bOut=new ByteArrayOutputStream2(_bufferSize);
|
||||
}
|
||||
else if (_bOut!=null)
|
||||
{
|
||||
if (_response.isCommitted() || (_contentLength>=0 && _contentLength<_minGzipSize))
|
||||
doNotGzip();
|
||||
else if (length>=(_bOut.getBuf().length -_bOut.getCount()))
|
||||
doGzip();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows derived implementations to replace PrintWriter implementation.
|
||||
*/
|
||||
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
|
||||
{
|
||||
return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
|
||||
}
|
||||
}
|
||||
|
|
@ -361,28 +361,18 @@ public class HttpFieldsTest
|
|||
fields.clear();
|
||||
fields.addSetCookie("everything","wrong","wrong","wrong",0,"to be replaced",true,true,0);
|
||||
fields.addSetCookie("everything","value","domain","path",0,"comment",true,true,0);
|
||||
assertEquals("everything=value;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",fields.getStringField("Set-Cookie"));
|
||||
assertEquals("everything=value;Comment=comment;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",fields.getStringField("Set-Cookie"));
|
||||
Enumeration<String> e =fields.getValues("Set-Cookie");
|
||||
assertTrue(e.hasMoreElements());
|
||||
assertEquals("everything=value;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
|
||||
assertEquals("everything=value;Comment=comment;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
|
||||
assertFalse(e.hasMoreElements());
|
||||
assertEquals("Thu, 01 Jan 1970 00:00:00 GMT",fields.getStringField("Expires"));
|
||||
|
||||
assertEquals("Thu, 01 Jan 1970 00:00:00 GMT",fields.getStringField("Expires"));
|
||||
|
||||
fields.clear();
|
||||
fields.addSetCookie("ev erything","va lue","do main","pa th",1,"co mment",true,true,2);
|
||||
String setCookie=fields.getStringField("Set-Cookie");
|
||||
assertTrue(setCookie.startsWith("\"ev erything\"=\"va lue\";Version=1;Comment=\"co mment\";Path=\"pa th\";Domain=\"do main\";Expires="));
|
||||
assertTrue(setCookie.startsWith("\"ev erything\"=\"va lue\";Comment=\"co mment\";Path=\"pa th\";Domain=\"do main\";Expires="));
|
||||
assertTrue(setCookie.endsWith("GMT;Max-Age=1;Secure;HttpOnly"));
|
||||
|
||||
fields.clear();
|
||||
fields.addSetCookie("name","value",null,null,-1,null,false,false,0);
|
||||
setCookie=fields.getStringField("Set-Cookie");
|
||||
assertEquals(-1,setCookie.indexOf("Version="));
|
||||
fields.clear();
|
||||
fields.addSetCookie("name","v a l u e",null,null,-1,null,false,false,0);
|
||||
setCookie=fields.getStringField("Set-Cookie");
|
||||
assertEquals(17,setCookie.indexOf("Version=1"));
|
||||
|
||||
fields.clear();
|
||||
fields.addSetCookie("json","{\"services\":[\"cwa\", \"aa\"]}",null,null,-1,null,false,false,-1);
|
||||
|
@ -401,12 +391,6 @@ public class HttpFieldsTest
|
|||
e=fields.getValues("Set-Cookie");
|
||||
assertEquals("name=more;Domain=domain",e.nextElement());
|
||||
assertEquals("foo=bob;Domain=domain",e.nextElement());
|
||||
|
||||
fields=new HttpFields(0);
|
||||
fields.addSetCookie("name","value==",null,null,-1,null,false,false,0);
|
||||
setCookie=fields.getStringField("Set-Cookie");
|
||||
assertEquals("name=value==",setCookie);
|
||||
|
||||
}
|
||||
|
||||
private Set<String> enum2set(Enumeration<String> e)
|
||||
|
|
|
@ -13,9 +13,6 @@
|
|||
|
||||
package org.eclipse.jetty.http;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
|
@ -28,6 +25,9 @@ import org.eclipse.jetty.io.SimpleBuffers;
|
|||
import org.eclipse.jetty.io.View;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class HttpGeneratorClientTest
|
||||
{
|
||||
public final static String CONTENT="The quick brown fox jumped over the lazy dog.\nNow is the time for all good men to come to the aid of the party\nThe moon is blue to a fish in love.\n";
|
||||
|
@ -52,7 +52,7 @@ public class HttpGeneratorClientTest
|
|||
|
||||
generator.completeHeader(fields,false);
|
||||
|
||||
generator.addContent(new ByteArrayBuffer(content),true);
|
||||
generator.addContent(new ByteArrayBuffer(content).asMutableBuffer(),true);
|
||||
generator.flushBuffer();
|
||||
generator.complete();
|
||||
generator.flushBuffer();
|
||||
|
@ -77,7 +77,7 @@ public class HttpGeneratorClientTest
|
|||
|
||||
String content = "The quick brown fox jumped over the lazy dog";
|
||||
|
||||
generator.addContent(new ByteArrayBuffer(content),true);
|
||||
generator.addContent(new ByteArrayBuffer(content).asMutableBuffer(),true);
|
||||
generator.completeHeader(fields,true);
|
||||
|
||||
generator.flushBuffer();
|
||||
|
@ -106,7 +106,7 @@ public class HttpGeneratorClientTest
|
|||
|
||||
generator.completeHeader(fields,false);
|
||||
|
||||
generator.addContent(new ByteArrayBuffer(content),false);
|
||||
generator.addContent(new ByteArrayBuffer(content).asMutableBuffer(),false);
|
||||
generator.flushBuffer();
|
||||
generator.complete();
|
||||
generator.flushBuffer();
|
||||
|
@ -120,7 +120,7 @@ public class HttpGeneratorClientTest
|
|||
* screw up the chunking by leaving out the second chunk header.
|
||||
*/
|
||||
@Test
|
||||
public void testChunkedWithBackPressure() throws Exception
|
||||
public void testChunkedWithBackPressure() throws Exception
|
||||
{
|
||||
final AtomicInteger availableChannelBytes = new AtomicInteger(500);
|
||||
ByteArrayEndPoint endp = new ByteArrayEndPoint(new byte[0],4096)
|
||||
|
|
|
@ -19,7 +19,14 @@ public interface AsyncEndPoint extends ConnectedEndPoint
|
|||
{
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Dispatch the endpoint to a thread to attend to it.
|
||||
* Dispatch the endpoint if it is not already dispatched
|
||||
*
|
||||
*/
|
||||
public void dispatch();
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Dispatch the endpoint. If it is already dispatched, schedule a redispatch
|
||||
*
|
||||
*/
|
||||
public void asyncDispatch();
|
||||
|
|
|
@ -352,7 +352,8 @@ public class ByteArrayBuffer extends AbstractBuffer
|
|||
throws IOException
|
||||
{
|
||||
out.write(_bytes,getIndex(),length());
|
||||
clear();
|
||||
if (!isImmutable())
|
||||
clear();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -246,7 +246,8 @@ public class ByteArrayEndPoint implements ConnectedEndPoint
|
|||
}
|
||||
}
|
||||
int len = _out.put(buffer);
|
||||
buffer.skip(len);
|
||||
if (!buffer.isImmutable())
|
||||
buffer.skip(len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
|
@ -157,7 +157,8 @@ public class StreamEndPoint implements EndPoint
|
|||
int length=buffer.length();
|
||||
if (length>0)
|
||||
buffer.writeTo(_out);
|
||||
buffer.clear();
|
||||
if (!buffer.isImmutable())
|
||||
buffer.clear();
|
||||
return length;
|
||||
}
|
||||
|
||||
|
|
|
@ -70,10 +70,12 @@ public class StringEndPoint extends StreamEndPoint
|
|||
_bout.reset();
|
||||
return s;
|
||||
}
|
||||
catch(Exception e)
|
||||
catch(final Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
throw new IllegalStateException(_encoding+": "+e.toString());
|
||||
throw new IllegalStateException(_encoding)
|
||||
{
|
||||
{initCause(e);}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -280,24 +280,17 @@ public class ChannelEndPoint implements EndPoint
|
|||
if (buf instanceof NIOBuffer)
|
||||
{
|
||||
final NIOBuffer nbuf = (NIOBuffer)buf;
|
||||
final ByteBuffer bbuf=nbuf.getByteBuffer();
|
||||
|
||||
//noinspection SynchronizationOnLocalVariableOrMethodParameter
|
||||
synchronized(bbuf)
|
||||
final ByteBuffer bbuf=nbuf.getByteBuffer().asReadOnlyBuffer();
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
bbuf.position(buffer.getIndex());
|
||||
bbuf.limit(buffer.putIndex());
|
||||
len=_channel.write(bbuf);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (len>0)
|
||||
buffer.skip(len);
|
||||
bbuf.position(0);
|
||||
bbuf.limit(bbuf.capacity());
|
||||
}
|
||||
bbuf.position(buffer.getIndex());
|
||||
bbuf.limit(buffer.putIndex());
|
||||
len=_channel.write(bbuf);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (len>0)
|
||||
buffer.skip(len);
|
||||
}
|
||||
}
|
||||
else if (buf instanceof RandomAccessFileBuffer)
|
||||
|
@ -363,52 +356,29 @@ public class ChannelEndPoint implements EndPoint
|
|||
|
||||
synchronized(this)
|
||||
{
|
||||
// We must sync because buffers may be shared (eg nbuf1 is likely to be cached content).
|
||||
//noinspection SynchronizationOnLocalVariableOrMethodParameter
|
||||
synchronized(bbuf0)
|
||||
// Adjust position indexs of buf0 and buf1
|
||||
bbuf0=bbuf0.asReadOnlyBuffer();
|
||||
bbuf0.position(header.getIndex());
|
||||
bbuf0.limit(header.putIndex());
|
||||
bbuf1=bbuf1.asReadOnlyBuffer();
|
||||
bbuf1.position(buffer.getIndex());
|
||||
bbuf1.limit(buffer.putIndex());
|
||||
|
||||
_gather2[0]=bbuf0;
|
||||
_gather2[1]=bbuf1;
|
||||
|
||||
// do the gathering write.
|
||||
length=(int)((GatheringByteChannel)_channel).write(_gather2);
|
||||
|
||||
int hl=header.length();
|
||||
if (length>hl)
|
||||
{
|
||||
//noinspection SynchronizationOnLocalVariableOrMethodParameter
|
||||
synchronized(bbuf1)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Adjust position indexs of buf0 and buf1
|
||||
bbuf0.position(header.getIndex());
|
||||
bbuf0.limit(header.putIndex());
|
||||
bbuf1.position(buffer.getIndex());
|
||||
bbuf1.limit(buffer.putIndex());
|
||||
|
||||
_gather2[0]=bbuf0;
|
||||
_gather2[1]=bbuf1;
|
||||
|
||||
// do the gathering write.
|
||||
length=(int)((GatheringByteChannel)_channel).write(_gather2);
|
||||
|
||||
int hl=header.length();
|
||||
if (length>hl)
|
||||
{
|
||||
header.clear();
|
||||
buffer.skip(length-hl);
|
||||
}
|
||||
else if (length>0)
|
||||
{
|
||||
header.skip(length);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// adjust buffer 0 and 1
|
||||
if (!header.isImmutable())
|
||||
header.setGetIndex(bbuf0.position());
|
||||
if (!buffer.isImmutable())
|
||||
buffer.setGetIndex(bbuf1.position());
|
||||
|
||||
bbuf0.position(0);
|
||||
bbuf1.position(0);
|
||||
bbuf0.limit(bbuf0.capacity());
|
||||
bbuf1.limit(bbuf1.capacity());
|
||||
}
|
||||
}
|
||||
header.clear();
|
||||
buffer.skip(length-hl);
|
||||
}
|
||||
else if (length>0)
|
||||
{
|
||||
header.skip(length);
|
||||
}
|
||||
}
|
||||
return length;
|
||||
|
|
|
@ -37,6 +37,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
|
|||
{
|
||||
public static final Logger LOG=Log.getLogger("org.eclipse.jetty.io.nio");
|
||||
|
||||
private final boolean WORK_AROUND_JVM_BUG_6346658 = System.getProperty("os.name").toLowerCase().contains("win");
|
||||
private final SelectorManager.SelectSet _selectSet;
|
||||
private final SelectorManager _manager;
|
||||
private SelectionKey _key;
|
||||
|
@ -208,11 +209,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
|
|||
{
|
||||
synchronized(this)
|
||||
{
|
||||
if (_dispatched)
|
||||
{
|
||||
throw new IllegalStateException("dispatched");
|
||||
}
|
||||
else
|
||||
if (!_dispatched)
|
||||
{
|
||||
_dispatched = true;
|
||||
boolean dispatched = _manager.dispatch(_handler);
|
||||
|
@ -685,15 +682,23 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
|
|||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
try
|
||||
// On unix systems there is a JVM issue that if you cancel before closing, it can
|
||||
// cause the selector to block waiting for a channel to close and that channel can
|
||||
// block waiting for the remote end. But on windows, if you don't cancel before a
|
||||
// close, then the selector can block anyway!
|
||||
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=357318
|
||||
if (WORK_AROUND_JVM_BUG_6346658)
|
||||
{
|
||||
SelectionKey key = _key;
|
||||
if (key!=null)
|
||||
key.cancel();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
LOG.ignore(e);
|
||||
try
|
||||
{
|
||||
SelectionKey key = _key;
|
||||
if (key!=null)
|
||||
key.cancel();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
LOG.ignore(e);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
|
|
|
@ -237,6 +237,9 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
/* ------------------------------------------------------------ */
|
||||
public void onClose()
|
||||
{
|
||||
Connection connection = _sslEndPoint.getConnection();
|
||||
if (connection != null && connection != this)
|
||||
connection.onClose();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -408,8 +411,8 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
}
|
||||
|
||||
// If we are reading into the temp buffer and it has some content, then we should be dispatched.
|
||||
if (toFill==_unwrapBuf && _unwrapBuf.hasContent())
|
||||
_aEndp.asyncDispatch();
|
||||
if (toFill==_unwrapBuf && _unwrapBuf.hasContent() && !_connection.isSuspended())
|
||||
_aEndp.dispatch();
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -550,7 +553,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
break;
|
||||
|
||||
case BUFFER_OVERFLOW:
|
||||
_logger.debug("{} unwrap {} {}->{}",_session,result.getStatus(),_inbound.toDetailString(),buffer.toDetailString());
|
||||
if (_logger.isDebugEnabled()) _logger.debug("{} unwrap {} {}->{}",_session,result.getStatus(),_inbound.toDetailString(),buffer.toDetailString());
|
||||
break;
|
||||
|
||||
case OK:
|
||||
|
@ -718,6 +721,11 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
process(null, null);
|
||||
}
|
||||
|
||||
public void dispatch()
|
||||
{
|
||||
_aEndp.dispatch();
|
||||
}
|
||||
|
||||
public void asyncDispatch()
|
||||
{
|
||||
_aEndp.asyncDispatch();
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
-->
|
||||
<!--
|
||||
<Call name="createRegistry" class="java.rmi.registry.LocateRegistry">
|
||||
<Arg type="java.lang.Integer">1099</Arg>
|
||||
<Arg type="java.lang.Integer"><SystemProperty name="jetty.jmxrmiport" default="1099"/></Arg>
|
||||
<Call name="sleep" class="java.lang.Thread">
|
||||
<Arg type="java.lang.Integer">1000</Arg>
|
||||
</Call>
|
||||
|
@ -91,11 +91,11 @@
|
|||
<New class="javax.management.remote.JMXServiceURL">
|
||||
<Arg type="java.lang.String">rmi</Arg>
|
||||
<Arg type="java.lang.String" />
|
||||
<Arg type="java.lang.Integer">0</Arg>
|
||||
<Arg type="java.lang.String">/jndi/rmi://localhost:1099/jettyjmx</Arg>
|
||||
<Arg type="java.lang.Integer"><SystemProperty name="jetty.jmxrmiport" default="1099"/></Arg>
|
||||
<Arg type="java.lang.String">/jndi/rmi://<SystemProperty name="jetty.jmxrmihost" default="localhost"/>:<SystemProperty name="jetty.jmxrmiport" default="1099"/>/jmxrmi</Arg>
|
||||
</New>
|
||||
</Arg>
|
||||
<Arg>org.eclipse.jetty:name=rmiconnectorserver</Arg>
|
||||
<Arg>org.eclipse.jetty.jmx:name=rmiconnectorserver</Arg>
|
||||
<Call name="start" />
|
||||
</New>
|
||||
-->
|
||||
|
|
|
@ -245,21 +245,37 @@ public class MongoSessionManager extends NoSqlSessionManager
|
|||
{
|
||||
for (String name : attrs.keySet())
|
||||
{
|
||||
if ( __METADATA.equals(name) )
|
||||
if (__METADATA.equals(name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
String attr = decodeName(name);
|
||||
Object value = decodeValue(attrs.get(name));
|
||||
session.doPutOrRemove(attr,value);
|
||||
session.bindValue(attr,value);
|
||||
|
||||
if (attrs.keySet().contains(name))
|
||||
{
|
||||
session.doPutOrRemove(attr,value);
|
||||
session.bindValue(attr,value);
|
||||
}
|
||||
else
|
||||
{
|
||||
session.doPutOrRemove(attr,value);
|
||||
}
|
||||
}
|
||||
// cleanup, remove values from session, that don't exist in data anymore:
|
||||
for (String name : session.getNames())
|
||||
{
|
||||
if (!attrs.keySet().contains(name))
|
||||
{
|
||||
session.doPutOrRemove(name,null);
|
||||
session.unbindValue(name,session.getAttribute(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
session.didActivate();
|
||||
|
||||
|
||||
|
||||
return version;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -348,7 +364,7 @@ public class MongoSessionManager extends NoSqlSessionManager
|
|||
BasicDBObject remove = new BasicDBObject();
|
||||
BasicDBObject unsets = new BasicDBObject();
|
||||
unsets.put(getContextKey(),1);
|
||||
remove.put("$unsets",unsets);
|
||||
remove.put("$unset",unsets);
|
||||
_sessions.update(key,remove);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -2,13 +2,35 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>8.1.3-SNAPSHOT</version>
|
||||
<artifactId>jetty-parent</artifactId>
|
||||
<version>19</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.npn</groupId>
|
||||
<artifactId>npn-api</artifactId>
|
||||
<version>1.0.1-SNAPSHOT</version>
|
||||
<name>Jetty :: Next Protocol Negotiation :: API</name>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:http://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project.git</connection>
|
||||
<developerConnection>scm:git:ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project.git</developerConnection>
|
||||
<url>http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/jetty-npn</url>
|
||||
</scm>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<configuration>
|
||||
<useReleaseProfile>false</useReleaseProfile>
|
||||
<goals>deploy</goals>
|
||||
<arguments>-Peclipse-release</arguments>
|
||||
<preparationGoals>clean install</preparationGoals>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
|
@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
|
|||
Bundle-Name: Jetty-OSGi-Jasper integration
|
||||
Fragment-Host: org.eclipse.jetty.osgi.boot
|
||||
Bundle-SymbolicName: org.eclipse.jetty.osgi.boot.jsp
|
||||
Bundle-Version: 8.1.2.qualifier
|
||||
Bundle-Version: 8.1.3.qualifier
|
||||
Bundle-Vendor: Mort Bay Consulting
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Import-Package: com.sun.el;version="2.2.0";resolution:=optional,
|
||||
|
@ -16,7 +16,7 @@ Import-Package: com.sun.el;version="2.2.0";resolution:=optional,
|
|||
javax.servlet.jsp.jstl.tlv;version="1.2.0";resolution:=optional,
|
||||
javax.servlet.jsp.resources;version="2.1.0",
|
||||
javax.servlet.jsp.tagext;version="2.1.0",
|
||||
javax.servlet.resources;version="2.5.0",
|
||||
javax.servlet.resources;version="2.6.0",
|
||||
org.apache.jasper;version="2.2.2";resolution:=optional,
|
||||
org.apache.jasper.compiler;version="2.2.2";resolution:=optional,
|
||||
org.apache.jasper.compiler.tagplugin;version="2.2.2";resolution:=optional,
|
||||
|
|
|
@ -28,98 +28,106 @@ import org.osgi.framework.Bundle;
|
|||
import org.osgi.framework.FrameworkUtil;
|
||||
|
||||
/**
|
||||
* Plug bundles that contains tld files so that jasper will discover them
|
||||
* and set them up in jetty.
|
||||
* Plug bundles that contains tld files so that jasper will discover them and
|
||||
* set them up in jetty.
|
||||
*
|
||||
* For example: -Dorg.eclipse.jetty.osgi.tldbundles=org.springframework.web.servlet,com.opensymphony.module.sitemesh
|
||||
* Otherwise use an attribute to the WebAppDeployer
|
||||
* <New class="org.eclipse.jetty.deploy.providers.WebAppProvider">
|
||||
* ....
|
||||
* <Set name="tldBundles"><Property name="org.eclipse.jetty.osgi.tldsbundles" default="" /></Set>
|
||||
* <New>
|
||||
* For example:
|
||||
* -Dorg.eclipse.jetty.osgi.tldbundles=org.springframework.web.servlet
|
||||
* ,com.opensymphony.module.sitemesh Otherwise use an attribute to the
|
||||
* WebAppDeployer <New
|
||||
* class="org.eclipse.jetty.deploy.providers.WebAppProvider"> .... <Set
|
||||
* name="tldBundles"><Property name="org.eclipse.jetty.osgi.tldsbundles"
|
||||
* default="" /></Set> <New>
|
||||
*/
|
||||
public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistrationCustomizer
|
||||
{
|
||||
/**
|
||||
* To plug into jasper bundles that contain tld files
|
||||
* please use a list of bundle's symbolic names:
|
||||
* -Djetty.osgi.tldbundles=org.springframework.web.servlet,com.opensymphony.module.sitemesh
|
||||
*/
|
||||
public static final String SYS_PROP_TLD_BUNDLES = "org.eclipse.jetty.osgi.tldbundles";
|
||||
|
||||
/**
|
||||
* Union of the tld bundles defined system wide and the one defines as an attribute of the AppProvider.
|
||||
* @param provider
|
||||
* @return
|
||||
*/
|
||||
private static Collection<String> getTldBundles(OSGiAppProvider provider)
|
||||
{
|
||||
String sysprop = System.getProperty(SYS_PROP_TLD_BUNDLES);
|
||||
String att = (String)provider.getTldBundles();
|
||||
if (sysprop == null && att == null)
|
||||
{
|
||||
return Collections.emptySet();
|
||||
}
|
||||
if (att == null)
|
||||
{
|
||||
att = sysprop;
|
||||
}
|
||||
else if (sysprop != null)
|
||||
{
|
||||
att = att + "," + sysprop;
|
||||
}
|
||||
|
||||
Collection<String> tldbundles = new HashSet<String>();
|
||||
StringTokenizer tokenizer = new StringTokenizer(att, ", \n\r\t", false);
|
||||
while (tokenizer.hasMoreTokens())
|
||||
{
|
||||
tldbundles.add(tokenizer.nextToken());
|
||||
}
|
||||
return tldbundles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The location of the jars that contain tld files.
|
||||
* Jasper will discover them.
|
||||
*/
|
||||
/**
|
||||
* To plug into jasper bundles that contain tld files please use a list of
|
||||
* bundle's symbolic names:
|
||||
* -Djetty.osgi.tldbundles=org.springframework.web.servlet
|
||||
* ,com.opensymphony.module.sitemesh
|
||||
*/
|
||||
public static final String SYS_PROP_TLD_BUNDLES = "org.eclipse.jetty.osgi.tldbundles";
|
||||
|
||||
/**
|
||||
* Union of the tld bundles defined system wide and the one defines as an
|
||||
* attribute of the AppProvider.
|
||||
*
|
||||
* @param provider
|
||||
* @return
|
||||
*/
|
||||
private static Collection<String> getTldBundles(OSGiAppProvider provider)
|
||||
{
|
||||
String sysprop = System.getProperty(SYS_PROP_TLD_BUNDLES);
|
||||
String att = (String) provider.getTldBundles();
|
||||
if (sysprop == null && att == null) { return Collections.emptySet(); }
|
||||
if (att == null)
|
||||
{
|
||||
att = sysprop;
|
||||
}
|
||||
else if (sysprop != null)
|
||||
{
|
||||
att = att + "," + sysprop;
|
||||
}
|
||||
|
||||
Collection<String> tldbundles = new HashSet<String>();
|
||||
StringTokenizer tokenizer = new StringTokenizer(att, ", \n\r\t", false);
|
||||
while (tokenizer.hasMoreTokens())
|
||||
{
|
||||
tldbundles.add(tokenizer.nextToken());
|
||||
}
|
||||
return tldbundles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The location of the jars that contain tld files. Jasper will
|
||||
* discover them.
|
||||
*/
|
||||
public URL[] getJarsWithTlds(OSGiAppProvider provider, BundleFileLocatorHelper locatorHelper) throws Exception
|
||||
{
|
||||
List<URL> urls = new ArrayList<URL>();
|
||||
//naive way of finding those bundles.
|
||||
//lots of assumptions: for example we assume a single version of each bundle that would contain tld files.
|
||||
//this is probably good enough as those tlds are loaded system-wide on jetty.
|
||||
//to do better than this we need to do it on a per webapp basis.
|
||||
//probably using custom properties in the ContextHandler service
|
||||
//and mirroring those in the MANIFEST.MF
|
||||
|
||||
Bundle[] bundles = FrameworkUtil.getBundle(PluggableWebAppRegistrationCustomizerImpl.class).getBundleContext().getBundles();
|
||||
Collection<String> tldbundles = getTldBundles(provider);
|
||||
for (Bundle bundle : bundles)
|
||||
{
|
||||
if (tldbundles.contains(bundle.getSymbolicName()))
|
||||
{
|
||||
registerTldBundle(locatorHelper, bundle, urls);
|
||||
}
|
||||
}
|
||||
|
||||
return urls.toArray(new URL[urls.size()]);
|
||||
List<URL> urls = new ArrayList<URL>();
|
||||
// naive way of finding those bundles.
|
||||
// lots of assumptions: for example we assume a single version of each
|
||||
// bundle that would contain tld files.
|
||||
// this is probably good enough as those tlds are loaded system-wide on
|
||||
// jetty.
|
||||
// to do better than this we need to do it on a per webapp basis.
|
||||
// probably using custom properties in the ContextHandler service
|
||||
// and mirroring those in the MANIFEST.MF
|
||||
|
||||
Bundle[] bundles = FrameworkUtil.getBundle(PluggableWebAppRegistrationCustomizerImpl.class).getBundleContext().getBundles();
|
||||
Collection<String> tldbundles = getTldBundles(provider);
|
||||
for (Bundle bundle : bundles)
|
||||
{
|
||||
if (tldbundles.contains(bundle.getSymbolicName()))
|
||||
{
|
||||
registerTldBundle(locatorHelper, bundle, urls);
|
||||
}
|
||||
}
|
||||
|
||||
return urls.toArray(new URL[urls.size()]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolves the bundle that contains tld files as a set of URLs that will be
|
||||
* passed to jasper as a URLClassLoader later on.
|
||||
* Usually that would be a single URL per bundle.
|
||||
* But we do some more work if there are jars embedded in the bundle.
|
||||
* passed to jasper as a URLClassLoader later on. Usually that would be a
|
||||
* single URL per bundle. But we do some more work if there are jars
|
||||
* embedded in the bundle.
|
||||
*
|
||||
* The jasper TldScanner expects a URLClassloader to parse a jar for the /META-INF/*.tld it may contain. We place the bundles that we know contain such
|
||||
* tag-libraries. Please note that it will work if and only if the bundle is a jar (!) Currently we just hardcode the bundle that contains the jstl
|
||||
* implemenation.
|
||||
* The jasper TldScanner expects a URLClassloader to parse a jar for the
|
||||
* /META-INF/*.tld it may contain. We place the bundles that we know contain
|
||||
* such tag-libraries. Please note that it will work if and only if the
|
||||
* bundle is a jar (!) Currently we just hardcode the bundle that contains
|
||||
* the jstl implemenation.
|
||||
*
|
||||
* A workaround when the tld cannot be parsed with this method is to copy and paste it inside the WEB-INF of the webapplication where it is used.
|
||||
* A workaround when the tld cannot be parsed with this method is to copy
|
||||
* and paste it inside the WEB-INF of the webapplication where it is used.
|
||||
*
|
||||
* Support only 2 types of packaging for the bundle: - the bundle is a jar (recommended for runtime.) - the bundle is a folder and contain jars in the root
|
||||
* and/or in the lib folder (nice for PDE developement situations) Unsupported: the bundle is a jar that embeds more jars.
|
||||
* Support only 2 types of packaging for the bundle: - the bundle is a jar
|
||||
* (recommended for runtime.) - the bundle is a folder and contain jars in
|
||||
* the root and/or in the lib folder (nice for PDE developement situations)
|
||||
* Unsupported: the bundle is a jar that embeds more jars.
|
||||
*
|
||||
* @param locatorHelper
|
||||
* @param bundle
|
||||
|
@ -152,9 +160,9 @@ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistra
|
|||
}
|
||||
else
|
||||
{
|
||||
urls.add(jasperLocation.toURI().toURL());
|
||||
urls.add(jasperLocation.toURI().toURL());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -36,48 +36,52 @@ import org.xml.sax.InputSource;
|
|||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Fix various shortcomings with the way jasper parses the tld files.
|
||||
* Plugs the JSTL tlds assuming that they are packaged with the bundle that contains the JSTL classes.
|
||||
* Fix various shortcomings with the way jasper parses the tld files. Plugs the
|
||||
* JSTL tlds assuming that they are packaged with the bundle that contains the
|
||||
* JSTL classes.
|
||||
* <p>
|
||||
* Pluggable tlds at the server level are handled by {@link PluggableWebAppRegistrationCustomizerImpl}.
|
||||
* Pluggable tlds at the server level are handled by
|
||||
* {@link PluggableWebAppRegistrationCustomizerImpl}.
|
||||
* </p>
|
||||
*/
|
||||
public class WebappRegistrationCustomizerImpl implements WebappRegistrationCustomizer
|
||||
{
|
||||
|
||||
/**
|
||||
* Default name of a class that belongs to the jstl bundle.
|
||||
* From that class we locate the corresponding bundle and register it
|
||||
* as a bundle that contains tld files.
|
||||
*/
|
||||
private static String DEFAULT_JSTL_BUNDLE_CLASS = "org.apache.taglibs.standard.tag.el.core.WhenTag";
|
||||
//used to be "org.apache.jasper.runtime.JspFactoryImpl" but now
|
||||
//the standard tag library implementation are stored in a separate bundle.
|
||||
|
||||
//DISABLED please use the tld bundle argument for the OSGiAppProvider
|
||||
// /**
|
||||
// * Default name of a class that belongs to the bundle where the Java server Faces tld files are defined.
|
||||
// * This is the sun's reference implementation.
|
||||
// */
|
||||
// private static String DEFAUT_JSF_IMPL_CLASS = "com.sun.faces.config.ConfigureListener";
|
||||
|
||||
/**
|
||||
* Default jsp factory implementation.
|
||||
* Idally jasper is osgified and we can use services.
|
||||
* In the mean time we statically set the jsp factory implementation.
|
||||
* bug #299733
|
||||
*/
|
||||
private static String DEFAULT_JSP_FACTORY_IMPL_CLASS = "org.apache.jasper.runtime.JspFactoryImpl";
|
||||
|
||||
/**
|
||||
* Default name of a class that belongs to the jstl bundle. From that class
|
||||
* we locate the corresponding bundle and register it as a bundle that
|
||||
* contains tld files.
|
||||
*/
|
||||
private static String DEFAULT_JSTL_BUNDLE_CLASS = "org.apache.taglibs.standard.tag.el.core.WhenTag";
|
||||
|
||||
// used to be "org.apache.jasper.runtime.JspFactoryImpl" but now
|
||||
// the standard tag library implementation are stored in a separate bundle.
|
||||
|
||||
// DISABLED please use the tld bundle argument for the OSGiAppProvider
|
||||
// /**
|
||||
// * Default name of a class that belongs to the bundle where the Java
|
||||
// server Faces tld files are defined.
|
||||
// * This is the sun's reference implementation.
|
||||
// */
|
||||
// private static String DEFAUT_JSF_IMPL_CLASS =
|
||||
// "com.sun.faces.config.ConfigureListener";
|
||||
|
||||
/**
|
||||
* Default jsp factory implementation. Idally jasper is osgified and we can
|
||||
* use services. In the mean time we statically set the jsp factory
|
||||
* implementation. bug #299733
|
||||
*/
|
||||
private static String DEFAULT_JSP_FACTORY_IMPL_CLASS = "org.apache.jasper.runtime.JspFactoryImpl";
|
||||
|
||||
public WebappRegistrationCustomizerImpl()
|
||||
{
|
||||
fixupDtdResolution();
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
//sanity check:
|
||||
// sanity check:
|
||||
Class cl = getClass().getClassLoader().loadClass("org.apache.jasper.servlet.JspServlet");
|
||||
//System.err.println("found the jsp servlet: " + cl.getName());
|
||||
// System.err.println("found the jsp servlet: " + cl.getName());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -87,18 +91,18 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
|
|||
}
|
||||
try
|
||||
{
|
||||
//bug #299733
|
||||
// bug #299733
|
||||
JspFactory fact = JspFactory.getDefaultFactory();
|
||||
if (fact == null)
|
||||
{ //bug #299733
|
||||
//JspFactory does a simple Class.getForName("org.apache.jasper.runtime.JspFactoryImpl")
|
||||
//however its bundles does not import the jasper package
|
||||
//so it fails. let's help things out:
|
||||
fact = (JspFactory)JettyBootstrapActivator.class.getClassLoader()
|
||||
.loadClass(DEFAULT_JSP_FACTORY_IMPL_CLASS).newInstance();
|
||||
{ // bug #299733
|
||||
// JspFactory does a simple
|
||||
// Class.getForName("org.apache.jasper.runtime.JspFactoryImpl")
|
||||
// however its bundles does not import the jasper package
|
||||
// so it fails. let's help things out:
|
||||
fact = (JspFactory) JettyBootstrapActivator.class.getClassLoader().loadClass(DEFAULT_JSP_FACTORY_IMPL_CLASS).newInstance();
|
||||
JspFactory.setDefaultFactory(fact);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -106,84 +110,90 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
|
|||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The jasper TldScanner expects a URLClassloader to parse a jar for the /META-INF/*.tld it may contain. We place the bundles that we know contain such
|
||||
* tag-libraries. Please note that it will work if and only if the bundle is a jar (!) Currently we just hardcode the bundle that contains the jstl
|
||||
* implemenation.
|
||||
* The jasper TldScanner expects a URLClassloader to parse a jar for the
|
||||
* /META-INF/*.tld it may contain. We place the bundles that we know contain
|
||||
* such tag-libraries. Please note that it will work if and only if the
|
||||
* bundle is a jar (!) Currently we just hardcode the bundle that contains
|
||||
* the jstl implemenation.
|
||||
*
|
||||
* A workaround when the tld cannot be parsed with this method is to copy and paste it inside the WEB-INF of the webapplication where it is used.
|
||||
* A workaround when the tld cannot be parsed with this method is to copy
|
||||
* and paste it inside the WEB-INF of the webapplication where it is used.
|
||||
*
|
||||
* Support only 2 types of packaging for the bundle: - the bundle is a jar (recommended for runtime.) - the bundle is a folder and contain jars in the root
|
||||
* and/or in the lib folder (nice for PDE developement situations) Unsupported: the bundle is a jar that embeds more jars.
|
||||
* Support only 2 types of packaging for the bundle: - the bundle is a jar
|
||||
* (recommended for runtime.) - the bundle is a folder and contain jars in
|
||||
* the root and/or in the lib folder (nice for PDE developement situations)
|
||||
* Unsupported: the bundle is a jar that embeds more jars.
|
||||
*
|
||||
* @return array of URLs
|
||||
* @throws Exception
|
||||
*/
|
||||
public URL[] getJarsWithTlds(OSGiAppProvider provider, BundleFileLocatorHelper locatorHelper) throws Exception
|
||||
{
|
||||
|
||||
HashSet<Class<?>> classesToAddToTheTldBundles = new HashSet<Class<?>>();
|
||||
|
||||
//Look for the jstl bundle
|
||||
//We assume the jstl's tlds are defined there.
|
||||
//We assume that the jstl bundle is imported by this bundle
|
||||
//So we can look for this class using this bundle's classloader:
|
||||
Class<?> jstlClass = WebappRegistrationCustomizerImpl.class.getClassLoader().loadClass(DEFAULT_JSTL_BUNDLE_CLASS);
|
||||
|
||||
classesToAddToTheTldBundles.add(jstlClass);
|
||||
|
||||
// Look for the jstl bundle
|
||||
// We assume the jstl's tlds are defined there.
|
||||
// We assume that the jstl bundle is imported by this bundle
|
||||
// So we can look for this class using this bundle's classloader:
|
||||
Class<?> jstlClass = WebappRegistrationCustomizerImpl.class.getClassLoader().loadClass(DEFAULT_JSTL_BUNDLE_CLASS);
|
||||
|
||||
classesToAddToTheTldBundles.add(jstlClass);
|
||||
|
||||
ArrayList<URL> urls = new ArrayList<URL>();
|
||||
for (Class<?> cl : classesToAddToTheTldBundles)
|
||||
{
|
||||
Bundle tldBundle = FrameworkUtil.getBundle(cl);
|
||||
File tldBundleLocation = locatorHelper.getBundleInstallLocation(tldBundle);
|
||||
if (tldBundleLocation != null && tldBundleLocation.isDirectory())
|
||||
{
|
||||
// try to find the jar files inside this folder
|
||||
for (File f : tldBundleLocation.listFiles())
|
||||
{
|
||||
if (f.getName().endsWith(".jar") && f.isFile())
|
||||
{
|
||||
urls.add(f.toURI().toURL());
|
||||
}
|
||||
else if (f.isDirectory() && f.getName().equals("lib"))
|
||||
{
|
||||
for (File f2 : tldBundleLocation.listFiles())
|
||||
{
|
||||
if (f2.getName().endsWith(".jar") && f2.isFile())
|
||||
{
|
||||
urls.add(f2.toURI().toURL());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (tldBundleLocation != null)
|
||||
{
|
||||
urls.add(tldBundleLocation.toURI().toURL());
|
||||
}
|
||||
}
|
||||
return urls.toArray(new URL[urls.size()]);
|
||||
for (Class<?> cl : classesToAddToTheTldBundles)
|
||||
{
|
||||
Bundle tldBundle = FrameworkUtil.getBundle(cl);
|
||||
File tldBundleLocation = locatorHelper.getBundleInstallLocation(tldBundle);
|
||||
if (tldBundleLocation != null && tldBundleLocation.isDirectory())
|
||||
{
|
||||
// try to find the jar files inside this folder
|
||||
for (File f : tldBundleLocation.listFiles())
|
||||
{
|
||||
if (f.getName().endsWith(".jar") && f.isFile())
|
||||
{
|
||||
urls.add(f.toURI().toURL());
|
||||
}
|
||||
else if (f.isDirectory() && f.getName().equals("lib"))
|
||||
{
|
||||
for (File f2 : tldBundleLocation.listFiles())
|
||||
{
|
||||
if (f2.getName().endsWith(".jar") && f2.isFile())
|
||||
{
|
||||
urls.add(f2.toURI().toURL());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (tldBundleLocation != null)
|
||||
{
|
||||
urls.add(tldBundleLocation.toURI().toURL());
|
||||
}
|
||||
}
|
||||
return urls.toArray(new URL[urls.size()]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Jasper resolves the dtd when it parses a taglib descriptor.
|
||||
* It uses this code to do that: ParserUtils.getClass().getResourceAsStream(resourcePath); where
|
||||
* resourcePath is for example: /javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd Unfortunately,
|
||||
* the dtd file is not in the exact same classloader as
|
||||
* ParserUtils class and the dtds are packaged in 2 separate bundles.
|
||||
* OSGi does not look in the dependencies' classloader when a resource is searched.
|
||||
* Jasper resolves the dtd when it parses a taglib descriptor. It uses this
|
||||
* code to do that:
|
||||
* ParserUtils.getClass().getResourceAsStream(resourcePath); where
|
||||
* resourcePath is for example:
|
||||
* /javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd Unfortunately, the
|
||||
* dtd file is not in the exact same classloader as ParserUtils class and
|
||||
* the dtds are packaged in 2 separate bundles. OSGi does not look in the
|
||||
* dependencies' classloader when a resource is searched.
|
||||
* <p>
|
||||
* The workaround consists of setting the entity resolver. That is a patch
|
||||
* added to the version of glassfish-jasper-jetty. IT is also present in the latest
|
||||
* version of glassfish jasper. Could not use introspection to set new value
|
||||
* on a static friendly field :(
|
||||
* The workaround consists of setting the entity resolver. That is a patch
|
||||
* added to the version of glassfish-jasper-jetty. IT is also present in the
|
||||
* latest version of glassfish jasper. Could not use introspection to set
|
||||
* new value on a static friendly field :(
|
||||
* </p>
|
||||
*/
|
||||
void fixupDtdResolution()
|
||||
void fixupDtdResolution()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -198,29 +208,23 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
|
|||
}
|
||||
|
||||
/**
|
||||
* Instead of using the ParserUtil's classloader, we use a class that is indeed next to the resource for sure.
|
||||
* Instead of using the ParserUtil's classloader, we use a class that is
|
||||
* indeed next to the resource for sure.
|
||||
*/
|
||||
static class MyFixedupEntityResolver implements EntityResolver
|
||||
{
|
||||
/**
|
||||
* Same values than in ParserUtils...
|
||||
*/
|
||||
static final String[] CACHED_DTD_PUBLIC_IDS =
|
||||
{ Constants.TAGLIB_DTD_PUBLIC_ID_11, Constants.TAGLIB_DTD_PUBLIC_ID_12,
|
||||
Constants.WEBAPP_DTD_PUBLIC_ID_22, Constants.WEBAPP_DTD_PUBLIC_ID_23, };
|
||||
static final String[] CACHED_DTD_PUBLIC_IDS = { Constants.TAGLIB_DTD_PUBLIC_ID_11, Constants.TAGLIB_DTD_PUBLIC_ID_12,
|
||||
Constants.WEBAPP_DTD_PUBLIC_ID_22, Constants.WEBAPP_DTD_PUBLIC_ID_23, };
|
||||
|
||||
static final String[] CACHED_DTD_RESOURCE_PATHS =
|
||||
{ Constants.TAGLIB_DTD_RESOURCE_PATH_11,
|
||||
Constants.TAGLIB_DTD_RESOURCE_PATH_12,
|
||||
Constants.WEBAPP_DTD_RESOURCE_PATH_22,
|
||||
Constants.WEBAPP_DTD_RESOURCE_PATH_23, };
|
||||
static final String[] CACHED_DTD_RESOURCE_PATHS = { Constants.TAGLIB_DTD_RESOURCE_PATH_11, Constants.TAGLIB_DTD_RESOURCE_PATH_12,
|
||||
Constants.WEBAPP_DTD_RESOURCE_PATH_22, Constants.WEBAPP_DTD_RESOURCE_PATH_23, };
|
||||
|
||||
static final String[] CACHED_SCHEMA_RESOURCE_PATHS = { Constants.TAGLIB_SCHEMA_RESOURCE_PATH_20, Constants.TAGLIB_SCHEMA_RESOURCE_PATH_21,
|
||||
Constants.WEBAPP_SCHEMA_RESOURCE_PATH_24, Constants.WEBAPP_SCHEMA_RESOURCE_PATH_25, };
|
||||
|
||||
static final String[] CACHED_SCHEMA_RESOURCE_PATHS = {
|
||||
Constants.TAGLIB_SCHEMA_RESOURCE_PATH_20,
|
||||
Constants.TAGLIB_SCHEMA_RESOURCE_PATH_21,
|
||||
Constants.WEBAPP_SCHEMA_RESOURCE_PATH_24,
|
||||
Constants.WEBAPP_SCHEMA_RESOURCE_PATH_25,
|
||||
};
|
||||
public InputSource resolveEntity(String publicId, String systemId) throws SAXException
|
||||
{
|
||||
for (int i = 0; i < CACHED_DTD_PUBLIC_IDS.length; i++)
|
||||
|
@ -241,10 +245,7 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
|
|||
input = this.getClass().getResourceAsStream(resourcePath);
|
||||
}
|
||||
}
|
||||
if (input == null)
|
||||
{
|
||||
throw new SAXException(Localizer.getMessage("jsp.error.internal.filenotfound",resourcePath));
|
||||
}
|
||||
if (input == null) { throw new SAXException(Localizer.getMessage("jsp.error.internal.filenotfound", resourcePath)); }
|
||||
InputSource isrc = new InputSource(input);
|
||||
return isrc;
|
||||
}
|
||||
|
@ -253,5 +254,5 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -19,15 +19,14 @@ import org.osgi.framework.BundleActivator;
|
|||
import org.osgi.framework.BundleContext;
|
||||
|
||||
/**
|
||||
* Pseudo fragment activator.
|
||||
* Called by the main org.eclipse.jetty.osgi.boot bundle.
|
||||
* Please note: this is not a real BundleActivator. Simply something called back by
|
||||
* the host bundle.
|
||||
* Pseudo fragment activator. Called by the main org.eclipse.jetty.osgi.boot
|
||||
* bundle. Please note: this is not a real BundleActivator. Simply something
|
||||
* called back by the host bundle.
|
||||
* <p>
|
||||
* It must be placed in the org.eclipse.jetty.osgi.boot.jsp package:
|
||||
* this is because org.eclipse.jetty.osgi.boot.jsp is the sympbolic-name
|
||||
* of this fragment. From that name, the PackageadminTracker will call
|
||||
* this class. IN a different package it won't be called.
|
||||
* It must be placed in the org.eclipse.jetty.osgi.boot.jsp package: this is
|
||||
* because org.eclipse.jetty.osgi.boot.jsp is the sympbolic-name of this
|
||||
* fragment. From that name, the PackageadminTracker will call this class. IN a
|
||||
* different package it won't be called.
|
||||
* </p>
|
||||
*/
|
||||
public class FragmentActivator implements BundleActivator
|
||||
|
@ -35,8 +34,9 @@ public class FragmentActivator implements BundleActivator
|
|||
/**
|
||||
*
|
||||
*/
|
||||
public void start(BundleContext context) throws Exception {
|
||||
System.setProperty("org.apache.jasper.compiler.disablejsr199", Boolean.TRUE.toString());
|
||||
public void start(BundleContext context) throws Exception
|
||||
{
|
||||
System.setProperty("org.apache.jasper.compiler.disablejsr199", Boolean.TRUE.toString());
|
||||
WebBundleDeployerHelper.JSP_REGISTRATION_HELPERS.add(new WebappRegistrationCustomizerImpl());
|
||||
WebBundleDeployerHelper.JSP_REGISTRATION_HELPERS.add(new PluggableWebAppRegistrationCustomizerImpl());
|
||||
}
|
||||
|
@ -44,7 +44,8 @@ public class FragmentActivator implements BundleActivator
|
|||
/**
|
||||
*
|
||||
*/
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
|
||||
public void stop(BundleContext context) throws Exception
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,123 +35,120 @@ import org.osgi.util.tracker.ServiceTracker;
|
|||
* Replacement for {@link TagLibConfiguration} for the OSGi integration.
|
||||
* </p>
|
||||
* <p>
|
||||
* In the case of a WAB, tlds can be located in OSGi bundles that are dependencies
|
||||
* of the WAB.
|
||||
* It is expected that each WAB lists the symbolic-names of the bundles that contain
|
||||
* tld files. The list is defined as the value of the header 'Require-TldBundle'
|
||||
* In the case of a WAB, tlds can be located in OSGi bundles that are
|
||||
* dependencies of the WAB. It is expected that each WAB lists the
|
||||
* symbolic-names of the bundles that contain tld files. The list is defined as
|
||||
* the value of the header 'Require-TldBundle'
|
||||
* </p>
|
||||
* <p>
|
||||
* Discussions about this are logged in https://bugs.eclipse.org/bugs/show_bug.cgi?id=306971
|
||||
* Discussions about this are logged in
|
||||
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=306971
|
||||
* </p>
|
||||
*/
|
||||
public class TagLibOSGiConfiguration extends TagLibConfiguration
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(TagLibOSGiConfiguration.class);
|
||||
|
||||
private ServiceTracker packageAdminServiceTracker = null;
|
||||
|
||||
/**
|
||||
* Override the preConfigure; locates the bundles that contain
|
||||
* tld files according to the value of the manifest header Require-TldBundle.
|
||||
* <p>
|
||||
* Set or add to the property TldProcessor.TLDResources the list of located jars
|
||||
* so that the super class will scan those.
|
||||
* </p>
|
||||
*/
|
||||
private ServiceTracker packageAdminServiceTracker = null;
|
||||
|
||||
/**
|
||||
* Override the preConfigure; locates the bundles that contain tld files
|
||||
* according to the value of the manifest header Require-TldBundle.
|
||||
* <p>
|
||||
* Set or add to the property TldProcessor.TLDResources the list of located
|
||||
* jars so that the super class will scan those.
|
||||
* </p>
|
||||
*/
|
||||
public void preConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
String requireTldBundle = (String)context.getAttribute(OSGiWebappConstants.REQUIRE_TLD_BUNDLE);
|
||||
if (requireTldBundle != null)
|
||||
{
|
||||
Collection<Resource> resources = getRequireTldBundleAsJettyResources(context, requireTldBundle);
|
||||
if (resources != null && !resources.isEmpty())
|
||||
{
|
||||
Collection<Resource> previouslySet = (Collection<Resource>)
|
||||
context.getAttribute(TagLibConfiguration.TLD_RESOURCES);
|
||||
if (previouslySet != null)
|
||||
{
|
||||
resources.addAll(previouslySet);
|
||||
}
|
||||
context.setAttribute(TagLibConfiguration.TLD_RESOURCES, resources);
|
||||
}
|
||||
}
|
||||
super.preConfigure(context);
|
||||
String requireTldBundle = (String) context.getAttribute(OSGiWebappConstants.REQUIRE_TLD_BUNDLE);
|
||||
if (requireTldBundle != null)
|
||||
{
|
||||
Collection<Resource> resources = getRequireTldBundleAsJettyResources(context, requireTldBundle);
|
||||
if (resources != null && !resources.isEmpty())
|
||||
{
|
||||
Collection<Resource> previouslySet = (Collection<Resource>) context.getAttribute(TagLibConfiguration.TLD_RESOURCES);
|
||||
if (previouslySet != null)
|
||||
{
|
||||
resources.addAll(previouslySet);
|
||||
}
|
||||
context.setAttribute(TagLibConfiguration.TLD_RESOURCES, resources);
|
||||
}
|
||||
}
|
||||
super.preConfigure(context);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param requireTldBundle The comma separated list of bundles' symbolic names
|
||||
* that contain tld for this osgi webapp.
|
||||
* @param requireTldBundle The comma separated list of bundles' symbolic
|
||||
* names that contain tld for this osgi webapp.
|
||||
* @return The collection of jars or folders that match those bundles.
|
||||
*/
|
||||
private Collection<Resource> getRequireTldBundleAsJettyResources(
|
||||
WebAppContext context, String requireTldBundle)
|
||||
private Collection<Resource> getRequireTldBundleAsJettyResources(WebAppContext context, String requireTldBundle)
|
||||
{
|
||||
Bundle bundle = (Bundle)
|
||||
context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE);
|
||||
PackageAdmin packAdmin = getBundleAdmin();
|
||||
String[] symbNames = requireTldBundle.split(", ");
|
||||
Collection<Resource> tlds = new LinkedHashSet<Resource>();
|
||||
for (String symbName : symbNames)
|
||||
{
|
||||
Bundle[] bs = packAdmin.getBundles(symbName, null);
|
||||
if (bs == null || bs.length == 0)
|
||||
{
|
||||
throw new IllegalArgumentException("Unable to locate the bundle '"
|
||||
+ symbName + "' specified in the "
|
||||
+ OSGiWebappConstants.REQUIRE_TLD_BUNDLE
|
||||
+ " of the manifest of "
|
||||
+ bundle.getSymbolicName());
|
||||
}
|
||||
//take the first one as it is the most recent version?
|
||||
Enumeration<URL> en = bs[0].findEntries("META-INF", "*.tld", false);
|
||||
boolean atLeastOneTldFound = false;
|
||||
while (en.hasMoreElements())
|
||||
{
|
||||
atLeastOneTldFound = true;
|
||||
URL oriUrl = en.nextElement();
|
||||
URL url = DefaultFileLocatorHelper.getLocalURL(oriUrl);
|
||||
Resource tldResource;
|
||||
try
|
||||
{
|
||||
tldResource = Resource.newResource(url);
|
||||
}
|
||||
catch (IOException 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);
|
||||
}
|
||||
tlds.add(tldResource);
|
||||
}
|
||||
if (!atLeastOneTldFound)
|
||||
{
|
||||
LOG.warn("No '/META-INF/*.tld' resources were found "
|
||||
+ " in the bundle '" + bs[0].getSymbolicName()
|
||||
+ "' while registering the "
|
||||
+ OSGiWebappConstants.REQUIRE_TLD_BUNDLE
|
||||
+ " of the manifest of "
|
||||
+ bundle.getSymbolicName());
|
||||
}
|
||||
}
|
||||
return tlds;
|
||||
Bundle bundle = (Bundle) context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE);
|
||||
PackageAdmin packAdmin = getBundleAdmin();
|
||||
String[] symbNames = requireTldBundle.split(", ");
|
||||
Collection<Resource> tlds = new LinkedHashSet<Resource>();
|
||||
for (String symbName : symbNames)
|
||||
{
|
||||
Bundle[] bs = packAdmin.getBundles(symbName, null);
|
||||
if (bs == null || bs.length == 0)
|
||||
{
|
||||
throw new IllegalArgumentException("Unable to locate the bundle '" + symbName
|
||||
+ "' specified in the "
|
||||
+ OSGiWebappConstants.REQUIRE_TLD_BUNDLE
|
||||
+ " of the manifest of "
|
||||
+ bundle.getSymbolicName());
|
||||
}
|
||||
// take the first one as it is the most recent version?
|
||||
Enumeration<URL> en = bs[0].findEntries("META-INF", "*.tld", false);
|
||||
boolean atLeastOneTldFound = false;
|
||||
while (en.hasMoreElements())
|
||||
{
|
||||
atLeastOneTldFound = true;
|
||||
URL oriUrl = en.nextElement();
|
||||
URL url = DefaultFileLocatorHelper.getLocalURL(oriUrl);
|
||||
Resource tldResource;
|
||||
try
|
||||
{
|
||||
tldResource = Resource.newResource(url);
|
||||
}
|
||||
catch (IOException 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);
|
||||
}
|
||||
tlds.add(tldResource);
|
||||
}
|
||||
if (!atLeastOneTldFound)
|
||||
{
|
||||
LOG.warn("No '/META-INF/*.tld' resources were found " + " in the bundle '"
|
||||
+ bs[0].getSymbolicName()
|
||||
+ "' while registering the "
|
||||
+ OSGiWebappConstants.REQUIRE_TLD_BUNDLE
|
||||
+ " of the manifest of "
|
||||
+ bundle.getSymbolicName());
|
||||
}
|
||||
}
|
||||
return tlds;
|
||||
}
|
||||
|
||||
private PackageAdmin getBundleAdmin()
|
||||
{
|
||||
if (packageAdminServiceTracker == null)
|
||||
{
|
||||
Bundle bootBundle = ((BundleReference)OSGiWebappConstants.class.getClassLoader()).getBundle();
|
||||
packageAdminServiceTracker = new ServiceTracker(bootBundle.getBundleContext(),
|
||||
PackageAdmin.class.getName(), null);
|
||||
packageAdminServiceTracker.open();
|
||||
}
|
||||
return (PackageAdmin) packageAdminServiceTracker.getService();
|
||||
}
|
||||
|
||||
|
||||
private PackageAdmin getBundleAdmin()
|
||||
{
|
||||
if (packageAdminServiceTracker == null)
|
||||
{
|
||||
Bundle bootBundle = ((BundleReference) OSGiWebappConstants.class.getClassLoader()).getBundle();
|
||||
packageAdminServiceTracker = new ServiceTracker(bootBundle.getBundleContext(), PackageAdmin.class.getName(), null);
|
||||
packageAdminServiceTracker.open();
|
||||
}
|
||||
return (PackageAdmin) packageAdminServiceTracker.getService();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
|
|||
Bundle-Name: Jetty-OSGi-Logback integration
|
||||
Fragment-Host: org.eclipse.jetty.osgi.boot
|
||||
Bundle-SymbolicName: org.eclipse.jetty.osgi.boot.logback;singleton:=true
|
||||
Bundle-Version: 8.1.2.qualifier
|
||||
Bundle-Version: 8.1.3.qualifier
|
||||
Bundle-Vendor: Mort Bay Consulting
|
||||
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
||||
Import-Package: ch.qos.logback.classic,
|
||||
|
|
|
@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
|||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Support for rfc66 war url scheme
|
||||
Bundle-SymbolicName: org.eclipse.jetty.osgi.boot.warurl;singleton:=true
|
||||
Bundle-Version: 8.1.2.qualifier
|
||||
Bundle-Version: 8.1.3.qualifier
|
||||
Bundle-Activator: org.eclipse.jetty.osgi.boot.warurl.WarUrlActivator
|
||||
Bundle-Vendor: Mort Bay Consulting
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
|
|
|
@ -24,12 +24,13 @@ import java.util.jar.Manifest;
|
|||
import org.eclipse.jetty.osgi.boot.warurl.internal.WarBundleManifestGenerator;
|
||||
import org.eclipse.jetty.osgi.boot.warurl.internal.WarURLConnection;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.osgi.service.url.AbstractURLStreamHandlerService;
|
||||
|
||||
/**
|
||||
* RFC-66: support for the "war" protocol
|
||||
* We are reusing the parsing of the query string from jetty.
|
||||
* If we wanted to not depend on jetty at all we could duplicate that method here
|
||||
* RFC-66: support for the "war" protocol We are reusing the parsing of the
|
||||
* query string from jetty. If we wanted to not depend on jetty at all we could
|
||||
* duplicate that method here
|
||||
*/
|
||||
public class WarUrlStreamHandler extends AbstractURLStreamHandlerService
|
||||
{
|
||||
|
@ -40,11 +41,11 @@ public class WarUrlStreamHandler extends AbstractURLStreamHandlerService
|
|||
@Override
|
||||
public URLConnection openConnection(URL url) throws IOException
|
||||
{
|
||||
//remove the war scheme.
|
||||
// remove the war scheme.
|
||||
URL actual = new URL(url.toString().substring("war:".length()));
|
||||
|
||||
//let's do some basic tests: see if this is a folder or not.
|
||||
//if it is a folder. we will try to support it.
|
||||
|
||||
// let's do some basic tests: see if this is a folder or not.
|
||||
// if it is a folder. we will try to support it.
|
||||
if (actual.getProtocol().equals("file"))
|
||||
{
|
||||
File file = new File(URIUtil.encodePath(actual.getPath()));
|
||||
|
@ -52,34 +53,48 @@ public class WarUrlStreamHandler extends AbstractURLStreamHandlerService
|
|||
{
|
||||
if (file.isDirectory())
|
||||
{
|
||||
//TODO (not mandatory for rfc66 though)
|
||||
// TODO (not mandatory for rfc66 though)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if (actual.toString().startsWith("file:/") && ! actual.to)
|
||||
|
||||
// if (actual.toString().startsWith("file:/") && ! actual.to)
|
||||
URLConnection ori = (URLConnection) actual.openConnection();
|
||||
ori.setDefaultUseCaches(Resource.getDefaultUseCaches());
|
||||
JarURLConnection jarOri = null;
|
||||
try {
|
||||
try
|
||||
{
|
||||
if (ori instanceof JarURLConnection)
|
||||
{
|
||||
jarOri = (JarURLConnection)ori;
|
||||
jarOri = (JarURLConnection) ori;
|
||||
}
|
||||
else
|
||||
{
|
||||
jarOri = (JarURLConnection) new URL("jar:"+actual.toString() + "!/").openConnection();
|
||||
jarOri = (JarURLConnection) new URL("jar:" + actual.toString() + "!/").openConnection();
|
||||
jarOri.setDefaultUseCaches(Resource.getDefaultUseCaches());
|
||||
}
|
||||
Manifest mf = WarBundleManifestGenerator.createBundleManifest(
|
||||
jarOri.getManifest(), url, jarOri.getJarFile());
|
||||
try { jarOri.getJarFile().close(); jarOri = null; } catch (Throwable t) {}
|
||||
return new WarURLConnection(actual,mf);
|
||||
Manifest mf = WarBundleManifestGenerator.createBundleManifest(jarOri.getManifest(), url, jarOri.getJarFile());
|
||||
try
|
||||
{
|
||||
jarOri.getJarFile().close();
|
||||
jarOri = null;
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
}
|
||||
return new WarURLConnection(actual, mf);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (jarOri != null) try { jarOri.getJarFile().close(); } catch (Throwable t) {}
|
||||
if (jarOri != null) try
|
||||
{
|
||||
jarOri.getJarFile().close();
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import java.util.jar.Manifest;
|
|||
import java.util.zip.ZipEntry;
|
||||
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
||||
/**
|
||||
* Facade for a URLConnection that will read a jar and substitute its
|
||||
|
@ -106,6 +107,7 @@ public class WarURLConnection extends URLConnection
|
|||
{
|
||||
super(url);
|
||||
_conn = url.openConnection();
|
||||
_conn.setDefaultUseCaches(Resource.getDefaultUseCaches());
|
||||
_mf = mf;
|
||||
}
|
||||
@Override
|
||||
|
|
|
@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
|
|||
Bundle-Name: Jetty OSGi bootstrap
|
||||
Bundle-SymbolicName: org.eclipse.jetty.osgi.boot
|
||||
Bundle-Vendor: Mort Bay Consulting
|
||||
Bundle-Version: 8.1.2.qualifier
|
||||
Bundle-Version: 8.1.3.qualifier
|
||||
Bundle-Activator: org.eclipse.jetty.osgi.boot.JettyBootstrapActivator
|
||||
Import-Package: javax.mail;version="1.4.0";resolution:=optional,
|
||||
javax.mail.event;version="1.4.0";resolution:=optional,
|
||||
|
@ -14,20 +14,20 @@ Import-Package: javax.mail;version="1.4.0";resolution:=optional,
|
|||
javax.servlet.http;version="2.6",
|
||||
javax.transaction;version="1.1.0";resolution:=optional,
|
||||
javax.transaction.xa;version="1.1.0";resolution:=optional,
|
||||
org.eclipse.jetty.annotations;version="8.1.2";resolution:=optional,
|
||||
org.eclipse.jetty.deploy;version="8.1.2",
|
||||
org.eclipse.jetty.deploy.providers;version="8.1.2",
|
||||
org.eclipse.jetty.http;version="8.1.2",
|
||||
org.eclipse.jetty.nested;version="8.1.2";resolution:=optional,
|
||||
org.eclipse.jetty.server;version="8.1.2",
|
||||
org.eclipse.jetty.server.handler;version="8.1.2",
|
||||
org.eclipse.jetty.servlet;version="8.1.2",
|
||||
org.eclipse.jetty.util;version="8.1.2",
|
||||
org.eclipse.jetty.util.component;version="8.1.2",
|
||||
org.eclipse.jetty.util.log;version="8.1.2",
|
||||
org.eclipse.jetty.util.resource;version="8.1.2",
|
||||
org.eclipse.jetty.webapp;version="8.1.2",
|
||||
org.eclipse.jetty.xml;version="8.1.2",
|
||||
org.eclipse.jetty.annotations;version="8.1.3";resolution:=optional,
|
||||
org.eclipse.jetty.deploy;version="8.1.3",
|
||||
org.eclipse.jetty.deploy.providers;version="8.1.3",
|
||||
org.eclipse.jetty.http;version="8.1.3",
|
||||
org.eclipse.jetty.nested;version="8.1.3";resolution:=optional,
|
||||
org.eclipse.jetty.server;version="8.1.3",
|
||||
org.eclipse.jetty.server.handler;version="8.1.3",
|
||||
org.eclipse.jetty.servlet;version="8.1.3",
|
||||
org.eclipse.jetty.util;version="8.1.3",
|
||||
org.eclipse.jetty.util.component;version="8.1.3",
|
||||
org.eclipse.jetty.util.log;version="8.1.3",
|
||||
org.eclipse.jetty.util.resource;version="8.1.3",
|
||||
org.eclipse.jetty.webapp;version="8.1.3",
|
||||
org.eclipse.jetty.xml;version="8.1.3",
|
||||
org.osgi.framework,
|
||||
org.osgi.service.cm;version="1.2.0",
|
||||
org.osgi.service.packageadmin,
|
||||
|
@ -41,8 +41,8 @@ Import-Package: javax.mail;version="1.4.0";resolution:=optional,
|
|||
org.xml.sax.helpers
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Bundle-Classpath: .
|
||||
Export-Package: org.eclipse.jetty.osgi.boot;version="8.1.2",
|
||||
org.eclipse.jetty.osgi.nested;version="8.1.2",
|
||||
org.eclipse.jetty.osgi.boot.utils;version="8.1.2",
|
||||
org.eclipse.jetty.osgi.annotations;version="8.1.2"
|
||||
Export-Package: org.eclipse.jetty.osgi.boot;version="8.1.3",
|
||||
org.eclipse.jetty.osgi.nested;version="8.1.3",
|
||||
org.eclipse.jetty.osgi.boot.utils;version="8.1.3",
|
||||
org.eclipse.jetty.osgi.annotations;version="8.1.3"
|
||||
DynamicImport-Package: org.eclipse.jetty.*;version="[8.1,9)"
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
<New class="org.eclipse.jetty.util.thread.QueuedThreadPool">
|
||||
<Set name="minThreads">10</Set>
|
||||
<Set name="maxThreads">200</Set>
|
||||
<Set name="detailedDump">false</Set>
|
||||
</New>
|
||||
</Set>
|
||||
|
||||
|
@ -45,19 +46,6 @@
|
|||
</Arg>
|
||||
</Call>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<!-- To add a HTTP blocking connector -->
|
||||
<!-- mixin jetty-bio.xml: -->
|
||||
<!-- java -jar start.jar etc/jetty-bio.xml -->
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<!-- To allow Jetty to be started from xinetd -->
|
||||
<!-- mixin jetty-xinetd.xml: -->
|
||||
<!-- java -jar start.jar etc/jetty-xinetd.xml -->
|
||||
<!-- -->
|
||||
<!-- See jetty-xinetd.xml for further instructions. -->
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- Set handler Collection Structure -->
|
||||
|
@ -82,10 +70,6 @@
|
|||
|
||||
<!-- =========================================================== -->
|
||||
<!-- Configure the deployment manager -->
|
||||
<!-- -->
|
||||
<!-- Sets up 2 monitored dir app providers that are configured -->
|
||||
<!-- to behave in a similaraly to the legacy ContextDeployer -->
|
||||
<!-- and WebAppDeployer from previous versions of Jetty. -->
|
||||
<!-- =========================================================== -->
|
||||
<Call name="addBean">
|
||||
<Arg>
|
||||
|
@ -95,7 +79,7 @@
|
|||
</Set>
|
||||
<Call name="setContextAttribute">
|
||||
<Arg>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</Arg>
|
||||
<Arg>.*/jsp-api-[^/]*\.jar$|.*/jsp-[^/]*\.jar$</Arg>
|
||||
<Arg>.*/servlet-api-[^/]*\.jar$</Arg>
|
||||
</Call>
|
||||
<!-- Providers of OSGi Apps -->
|
||||
<Call name="addAppProvider">
|
||||
|
@ -126,8 +110,12 @@
|
|||
<Set name="sendServerVersion">true</Set>
|
||||
<Set name="sendDateHeader">true</Set>
|
||||
<Set name="gracefulShutdown">1000</Set>
|
||||
<Set name="dumpAfterStart">false</Set>
|
||||
<Set name="dumpBeforeStop">false</Set>
|
||||
|
||||
<!-- jetty-jndi by default -->
|
||||
<!-- =========================================================== -->
|
||||
<!-- Configure Jetty's JNDI impl by default -->
|
||||
<!-- =========================================================== -->
|
||||
<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>
|
||||
|
|
|
@ -54,10 +54,6 @@
|
|||
|
||||
<!-- =========================================================== -->
|
||||
<!-- Configure the deployment manager -->
|
||||
<!-- -->
|
||||
<!-- Sets up 2 monitored dir app providers that are configured -->
|
||||
<!-- to behave in a similaraly to the legacy ContextDeployer -->
|
||||
<!-- and WebAppDeployer from previous versions of Jetty. -->
|
||||
<!-- =========================================================== -->
|
||||
<Call name="addBean">
|
||||
<Arg>
|
||||
|
@ -67,7 +63,7 @@
|
|||
</Set>
|
||||
<Call name="setContextAttribute">
|
||||
<Arg>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</Arg>
|
||||
<Arg>.*/jsp-api-[^/]*\.jar$|.*/jsp-[^/]*\.jar$</Arg>
|
||||
<Arg>.*/servlet-api-[^/]*\.jar$</Arg>
|
||||
</Call>
|
||||
<!-- Providers of OSGi Apps -->
|
||||
<Call name="addAppProvider">
|
||||
|
@ -82,7 +78,7 @@
|
|||
contain custom tag libraries (*.tld files)
|
||||
if those bundles don't exist or can't be loaded no errors or warning will be issued!
|
||||
this default value is to plug the tld files of the reference implementation of JSF -->
|
||||
<Set name="tldBundles"><Property name="org.eclipse.jetty.osgi.tldsbundles"
|
||||
<Set name="tldBundles"><Property name="org.eclipse.jetty.osgi.tldbundles"
|
||||
default="javax.faces.jsf-impl" /></Set>
|
||||
</New>
|
||||
</Arg>
|
||||
|
@ -99,8 +95,12 @@
|
|||
<Set name="sendServerVersion">true</Set>
|
||||
<Set name="sendDateHeader">true</Set>
|
||||
<Set name="gracefulShutdown">1000</Set>
|
||||
<Set name="dumpAfterStart">false</Set>
|
||||
<Set name="dumpBeforeStop">false</Set>
|
||||
|
||||
<!-- jetty-jndi by default -->
|
||||
<!-- =========================================================== -->
|
||||
<!-- Configure Jetty's JNDI impl by default -->
|
||||
<!-- =========================================================== -->
|
||||
<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>
|
||||
|
|
|
@ -66,15 +66,19 @@ public class JettyBootstrapActivator implements BundleActivator
|
|||
}
|
||||
|
||||
private ServiceRegistration _registeredServer;
|
||||
|
||||
private Server _server;
|
||||
|
||||
private JettyContextHandlerServiceTracker _jettyContextHandlerTracker;
|
||||
|
||||
private PackageAdminServiceTracker _packageAdminServiceTracker;
|
||||
|
||||
private BundleTracker _webBundleTracker;
|
||||
|
||||
private BundleContext _bundleContext;
|
||||
|
||||
// private ServiceRegistration _jettyServerFactoryService;
|
||||
|
||||
// private ServiceRegistration _jettyServerFactoryService;
|
||||
private JettyServerServiceTracker _jettyServerServiceTracker;
|
||||
|
||||
|
||||
/**
|
||||
* Setup a new jetty Server, registers it as a service. Setup the Service
|
||||
|
@ -93,30 +97,31 @@ public class JettyBootstrapActivator implements BundleActivator
|
|||
// should activate.
|
||||
_packageAdminServiceTracker = new PackageAdminServiceTracker(context);
|
||||
|
||||
_jettyServerServiceTracker = new JettyServerServiceTracker();
|
||||
context.addServiceListener(_jettyServerServiceTracker,"(objectclass=" + Server.class.getName() + ")");
|
||||
_jettyServerServiceTracker = new JettyServerServiceTracker();
|
||||
context.addServiceListener(_jettyServerServiceTracker, "(objectclass=" + Server.class.getName() + ")");
|
||||
|
||||
// Register the Jetty Server Factory as a ManagedServiceFactory:
|
||||
// Properties jettyServerMgdFactoryServiceProps = new Properties();
|
||||
// jettyServerMgdFactoryServiceProps.put("pid",
|
||||
// OSGiWebappConstants.MANAGED_JETTY_SERVER_FACTORY_PID);
|
||||
// _jettyServerFactoryService = context.registerService(
|
||||
// ManagedServiceFactory.class.getName(), new
|
||||
// JettyServersManagedFactory(),
|
||||
// jettyServerMgdFactoryServiceProps);
|
||||
|
||||
//Register the Jetty Server Factory as a ManagedServiceFactory:
|
||||
// Properties jettyServerMgdFactoryServiceProps = new Properties();
|
||||
// jettyServerMgdFactoryServiceProps.put("pid", OSGiWebappConstants.MANAGED_JETTY_SERVER_FACTORY_PID);
|
||||
// _jettyServerFactoryService = context.registerService(
|
||||
// ManagedServiceFactory.class.getName(), new JettyServersManagedFactory(),
|
||||
// jettyServerMgdFactoryServiceProps);
|
||||
|
||||
_jettyContextHandlerTracker = new JettyContextHandlerServiceTracker(_jettyServerServiceTracker);
|
||||
|
||||
// the tracker in charge of the actual deployment
|
||||
// and that will configure and start the jetty server.
|
||||
context.addServiceListener(_jettyContextHandlerTracker,"(objectclass=" + ContextHandler.class.getName() + ")");
|
||||
context.addServiceListener(_jettyContextHandlerTracker, "(objectclass=" + ContextHandler.class.getName() + ")");
|
||||
|
||||
//see if we shoult start a default jetty instance right now.
|
||||
// see if we shoult start a default jetty instance right now.
|
||||
DefaultJettyAtJettyHomeHelper.startJettyAtJettyHome(context);
|
||||
|
||||
// now ready to support the Extender pattern:
|
||||
_webBundleTracker = new BundleTracker(context,
|
||||
Bundle.ACTIVE | Bundle.STOPPING, new WebBundleTrackerCustomizer());
|
||||
|
||||
// now ready to support the Extender pattern:
|
||||
_webBundleTracker = new BundleTracker(context, Bundle.ACTIVE | Bundle.STOPPING, new WebBundleTrackerCustomizer());
|
||||
_webBundleTracker.open();
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -129,12 +134,12 @@ public class JettyBootstrapActivator implements BundleActivator
|
|||
{
|
||||
try
|
||||
{
|
||||
|
||||
if (_webBundleTracker != null)
|
||||
{
|
||||
_webBundleTracker.close();
|
||||
_webBundleTracker = null;
|
||||
}
|
||||
|
||||
if (_webBundleTracker != null)
|
||||
{
|
||||
_webBundleTracker.close();
|
||||
_webBundleTracker = null;
|
||||
}
|
||||
if (_jettyContextHandlerTracker != null)
|
||||
{
|
||||
_jettyContextHandlerTracker.stop();
|
||||
|
@ -143,7 +148,7 @@ public class JettyBootstrapActivator implements BundleActivator
|
|||
}
|
||||
if (_jettyServerServiceTracker != null)
|
||||
{
|
||||
_jettyServerServiceTracker.stop();
|
||||
_jettyServerServiceTracker.stop();
|
||||
context.removeServiceListener(_jettyServerServiceTracker);
|
||||
_jettyServerServiceTracker = null;
|
||||
}
|
||||
|
@ -165,31 +170,31 @@ public class JettyBootstrapActivator implements BundleActivator
|
|||
}
|
||||
finally
|
||||
{
|
||||
_registeredServer = null;
|
||||
_registeredServer = null;
|
||||
}
|
||||
}
|
||||
// if (_jettyServerFactoryService != null)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// _jettyServerFactoryService.unregister();
|
||||
// }
|
||||
// catch (IllegalArgumentException ill)
|
||||
// {
|
||||
// // already unregistered.
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// _jettyServerFactoryService = null;
|
||||
// }
|
||||
// }
|
||||
// if (_jettyServerFactoryService != null)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// _jettyServerFactoryService.unregister();
|
||||
// }
|
||||
// catch (IllegalArgumentException ill)
|
||||
// {
|
||||
// // already unregistered.
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// _jettyServerFactoryService = null;
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_server != null)
|
||||
{
|
||||
_server.stop();
|
||||
_server.stop();
|
||||
}
|
||||
INSTANCE = null;
|
||||
}
|
||||
|
@ -200,27 +205,25 @@ public class JettyBootstrapActivator implements BundleActivator
|
|||
* registers it as an OSGi service. The tracker
|
||||
* {@link JettyContextHandlerServiceTracker} will do the actual deployment.
|
||||
*
|
||||
* @param contributor
|
||||
* The bundle
|
||||
* @param webappFolderPath
|
||||
* The path to the root of the webapp. Must be a path relative to
|
||||
* bundle; either an absolute path.
|
||||
* @param contextPath
|
||||
* The context path. Must start with "/"
|
||||
* @param contributor The bundle
|
||||
* @param webappFolderPath The path to the root of the webapp. Must be a
|
||||
* path relative to bundle; either an absolute path.
|
||||
* @param contextPath The context path. Must start with "/"
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void registerWebapplication(Bundle contributor, String webappFolderPath, String contextPath) throws Exception
|
||||
{
|
||||
checkBundleActivated();
|
||||
WebAppContext contextHandler = new WebAppContext();
|
||||
checkBundleActivated();
|
||||
WebAppContext contextHandler = new WebAppContext();
|
||||
Dictionary dic = new Hashtable();
|
||||
dic.put(OSGiWebappConstants.SERVICE_PROP_WAR,webappFolderPath);
|
||||
dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH,contextPath);
|
||||
String requireTldBundle = (String)contributor.getHeaders().get(OSGiWebappConstants.REQUIRE_TLD_BUNDLE);
|
||||
if (requireTldBundle != null) {
|
||||
dic.put(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE, requireTldBundle);
|
||||
dic.put(OSGiWebappConstants.SERVICE_PROP_WAR, webappFolderPath);
|
||||
dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH, contextPath);
|
||||
String requireTldBundle = (String) contributor.getHeaders().get(OSGiWebappConstants.REQUIRE_TLD_BUNDLE);
|
||||
if (requireTldBundle != null)
|
||||
{
|
||||
dic.put(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE, requireTldBundle);
|
||||
}
|
||||
contributor.getBundleContext().registerService(ContextHandler.class.getName(),contextHandler,dic);
|
||||
contributor.getBundleContext().registerService(ContextHandler.class.getName(), contextHandler, dic);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -228,24 +231,20 @@ public class JettyBootstrapActivator implements BundleActivator
|
|||
* registers it as an OSGi service. The tracker
|
||||
* {@link JettyContextHandlerServiceTracker} will do the actual deployment.
|
||||
*
|
||||
* @param contributor
|
||||
* The bundle
|
||||
* @param webappFolderPath
|
||||
* The path to the root of the webapp. Must be a path relative to
|
||||
* bundle; either an absolute path.
|
||||
* @param contextPath
|
||||
* The context path. Must start with "/"
|
||||
* @param dic
|
||||
* TODO: parameter description
|
||||
* @param contributor The bundle
|
||||
* @param webappFolderPath The path to the root of the webapp. Must be a
|
||||
* path relative to bundle; either an absolute path.
|
||||
* @param contextPath The context path. Must start with "/"
|
||||
* @param dic TODO: parameter description
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void registerWebapplication(Bundle contributor, String webappFolderPath, String contextPath, Dictionary<String, String> dic) throws Exception
|
||||
{
|
||||
checkBundleActivated();
|
||||
checkBundleActivated();
|
||||
WebAppContext contextHandler = new WebAppContext();
|
||||
dic.put(OSGiWebappConstants.SERVICE_PROP_WAR,webappFolderPath);
|
||||
dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH,contextPath);
|
||||
contributor.getBundleContext().registerService(ContextHandler.class.getName(),contextHandler,dic);
|
||||
dic.put(OSGiWebappConstants.SERVICE_PROP_WAR, webappFolderPath);
|
||||
dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH, contextPath);
|
||||
contributor.getBundleContext().registerService(ContextHandler.class.getName(), contextHandler, dic);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -253,16 +252,14 @@ public class JettyBootstrapActivator implements BundleActivator
|
|||
* registers it as an OSGi service. The tracker
|
||||
* {@link JettyContextHandlerServiceTracker} will do the actual deployment.
|
||||
*
|
||||
* @param contributor
|
||||
* The bundle that registers a new context
|
||||
* @param contextFilePath
|
||||
* The path to the file inside the bundle that defines the
|
||||
* context.
|
||||
* @param contributor The bundle that registers a new context
|
||||
* @param contextFilePath The path to the file inside the bundle that
|
||||
* defines the context.
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void registerContext(Bundle contributor, String contextFilePath) throws Exception
|
||||
{
|
||||
registerContext(contributor,contextFilePath,new Hashtable<String, String>());
|
||||
registerContext(contributor, contextFilePath, new Hashtable<String, String>());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -270,33 +267,30 @@ public class JettyBootstrapActivator implements BundleActivator
|
|||
* registers it as an OSGi service. The tracker
|
||||
* {@link JettyContextHandlerServiceTracker} will do the actual deployment.
|
||||
*
|
||||
* @param contributor
|
||||
* The bundle that registers a new context
|
||||
* @param contextFilePath
|
||||
* The path to the file inside the bundle that defines the
|
||||
* context.
|
||||
* @param dic
|
||||
* TODO: parameter description
|
||||
* @param contributor The bundle that registers a new context
|
||||
* @param contextFilePath The path to the file inside the bundle that
|
||||
* defines the context.
|
||||
* @param dic TODO: parameter description
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void registerContext(Bundle contributor, String contextFilePath, Dictionary<String, String> dic) throws Exception
|
||||
{
|
||||
checkBundleActivated();
|
||||
checkBundleActivated();
|
||||
ContextHandler contextHandler = new ContextHandler();
|
||||
dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH,contextFilePath);
|
||||
dic.put(IWebBundleDeployerHelper.INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE,Boolean.TRUE.toString());
|
||||
contributor.getBundleContext().registerService(ContextHandler.class.getName(),contextHandler,dic);
|
||||
dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH, contextFilePath);
|
||||
dic.put(IWebBundleDeployerHelper.INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE, Boolean.TRUE.toString());
|
||||
contributor.getBundleContext().registerService(ContextHandler.class.getName(), contextHandler, dic);
|
||||
}
|
||||
|
||||
public static void unregister(String contextPath)
|
||||
{
|
||||
// todo
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Since org.eclipse.jetty.osgi.boot does not have a lazy activation policy
|
||||
* when one fo the static methods to register a webapp is called we should make sure that
|
||||
* the bundle is started.
|
||||
* when one fo the static methods to register a webapp is called we should
|
||||
* make sure that the bundle is started.
|
||||
*/
|
||||
private static void checkBundleActivated()
|
||||
{
|
||||
|
@ -313,7 +307,7 @@ public class JettyBootstrapActivator implements BundleActivator
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return The bundle context for this bundle.
|
||||
*/
|
||||
|
@ -322,6 +316,5 @@ public class JettyBootstrapActivator implements BundleActivator
|
|||
checkBundleActivated();
|
||||
return INSTANCE._bundleContext;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -348,7 +348,7 @@ public class OSGiAppProvider extends ScanningAppProvider implements AppProvider
|
|||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
LOG.warn(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -369,11 +369,11 @@ public class OSGiAppProvider extends ScanningAppProvider implements AppProvider
|
|||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
LOG.warn(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isExtract()
|
||||
{
|
||||
return _extractWars;
|
||||
|
|
|
@ -39,7 +39,7 @@ import org.osgi.framework.BundleContext;
|
|||
public class DefaultJettyAtJettyHomeHelper {
|
||||
private static final Logger LOG = Log.getLogger(DefaultJettyAtJettyHomeHelper.class);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* contains a comma separated list of pathes to the etc/jetty-*.xml files
|
||||
* used to configure jetty. By default the value is 'etc/jetty.xml' when the
|
||||
|
@ -69,7 +69,7 @@ public class DefaultJettyAtJettyHomeHelper {
|
|||
* Usual system property used as the port for https for a typical jetty configuration.
|
||||
*/
|
||||
public static final String SYS_PROP_JETTY_PORT_SSL = "jetty.port.ssl";
|
||||
|
||||
|
||||
/**
|
||||
* Called by the JettyBootStrapActivator.
|
||||
* If the system property jetty.home is defined and points to a folder,
|
||||
|
@ -88,81 +88,76 @@ public class DefaultJettyAtJettyHomeHelper {
|
|||
* that might use them as part of their properties.
|
||||
* </p>
|
||||
*/
|
||||
public static void startJettyAtJettyHome(BundleContext bundleContext)
|
||||
public static void startJettyAtJettyHome(BundleContext bundleContext) throws Exception
|
||||
{
|
||||
String jettyHomeSysProp = System.getProperty(SYS_PROP_JETTY_HOME);
|
||||
String jettyHomeBundleSysProp = System.getProperty(SYS_PROP_JETTY_HOME_BUNDLE);
|
||||
File jettyHome = null;
|
||||
Bundle jettyHomeBundle = null;
|
||||
if (jettyHomeSysProp != null)
|
||||
{
|
||||
jettyHomeSysProp = 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 the jetty.home property and the jetty.home.bundle property are defined."
|
||||
+ " jetty.home.bundle is not taken into account.");
|
||||
}
|
||||
jettyHome = new File(jettyHomeSysProp);
|
||||
if (!jettyHome.exists() || !jettyHome.isDirectory())
|
||||
{
|
||||
LOG.warn("Unable to locate the jetty.home folder " + jettyHomeSysProp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (jettyHomeBundleSysProp != null)
|
||||
{
|
||||
jettyHomeBundleSysProp = resolvePropertyValue(jettyHomeBundleSysProp);
|
||||
for (Bundle b : bundleContext.getBundles())
|
||||
{
|
||||
if (b.getSymbolicName().equals(jettyHomeBundleSysProp))
|
||||
{
|
||||
jettyHomeBundle = b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (jettyHomeBundle == null)
|
||||
{
|
||||
LOG.warn("Unable to find the jetty.home.bundle named " + jettyHomeSysProp);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
if (jettyHome == null && jettyHomeBundle == null)
|
||||
{
|
||||
LOG.warn("No default jetty started.");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
Server server = new Server();
|
||||
Dictionary properties = new Hashtable();
|
||||
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);
|
||||
String jettyHomeSysProp = System.getProperty(SYS_PROP_JETTY_HOME);
|
||||
String jettyHomeBundleSysProp = System.getProperty(SYS_PROP_JETTY_HOME_BUNDLE);
|
||||
File jettyHome = null;
|
||||
Bundle jettyHomeBundle = null;
|
||||
if (jettyHomeSysProp != null)
|
||||
{
|
||||
jettyHomeSysProp = 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 the jetty.home property and the jetty.home.bundle property are defined."
|
||||
+ " jetty.home.bundle is not taken into account.");
|
||||
}
|
||||
jettyHome = new File(jettyHomeSysProp);
|
||||
if (!jettyHome.exists() || !jettyHome.isDirectory())
|
||||
{
|
||||
LOG.warn("Unable to locate the jetty.home folder " + jettyHomeSysProp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (jettyHomeBundleSysProp != null)
|
||||
{
|
||||
jettyHomeBundleSysProp = resolvePropertyValue(jettyHomeBundleSysProp);
|
||||
for (Bundle b : bundleContext.getBundles())
|
||||
{
|
||||
if (b.getSymbolicName().equals(jettyHomeBundleSysProp))
|
||||
{
|
||||
jettyHomeBundle = b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (jettyHomeBundle == null)
|
||||
{
|
||||
LOG.warn("Unable to find the jetty.home.bundle named " + jettyHomeSysProp);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG.info("Configuring the default jetty server with " + configURLs);
|
||||
|
||||
//these properties usually are the ones passed to this type of configuration.
|
||||
setProperty(properties,SYS_PROP_JETTY_HOME,System.getProperty(SYS_PROP_JETTY_HOME));
|
||||
setProperty(properties,SYS_PROP_JETTY_HOST,System.getProperty(SYS_PROP_JETTY_HOST));
|
||||
setProperty(properties,SYS_PROP_JETTY_PORT,System.getProperty(SYS_PROP_JETTY_PORT));
|
||||
setProperty(properties,SYS_PROP_JETTY_PORT_SSL,System.getProperty(SYS_PROP_JETTY_PORT_SSL));
|
||||
}
|
||||
if (jettyHome == null && jettyHomeBundle == null)
|
||||
{
|
||||
LOG.warn("No default jetty started.");
|
||||
return;
|
||||
}
|
||||
|
||||
Server server = new Server();
|
||||
Dictionary properties = new Hashtable();
|
||||
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,SYS_PROP_JETTY_HOME,System.getProperty(SYS_PROP_JETTY_HOME));
|
||||
setProperty(properties,SYS_PROP_JETTY_HOST,System.getProperty(SYS_PROP_JETTY_HOST));
|
||||
setProperty(properties,SYS_PROP_JETTY_PORT,System.getProperty(SYS_PROP_JETTY_PORT));
|
||||
setProperty(properties,SYS_PROP_JETTY_PORT_SSL,System.getProperty(SYS_PROP_JETTY_PORT_SSL));
|
||||
|
||||
bundleContext.registerService(Server.class.getName(), server, properties);
|
||||
// hookNestedConnectorToBridgeServlet(server);
|
||||
|
||||
bundleContext.registerService(Server.class.getName(), server, properties);
|
||||
// hookNestedConnectorToBridgeServlet(server);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Minimum setup for the location of the configuration files given a jettyhome folder.
|
||||
* Reads the system property jetty.etc.config.urls and look for the corresponding jetty
|
||||
|
@ -172,22 +167,25 @@ public class DefaultJettyAtJettyHomeHelper {
|
|||
*/
|
||||
private static String getJettyConfigurationURLs(File jettyhome)
|
||||
{
|
||||
String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES,"etc/jetty.xml");
|
||||
StringTokenizer tokenizer = new StringTokenizer(jettyetc,";,", false);
|
||||
String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES, "etc/jetty.xml");
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
appendToCommaSeparatedList(res, next);
|
||||
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);
|
||||
}
|
||||
return res.toString();
|
||||
}
|
||||
|
@ -202,108 +200,108 @@ public class DefaultJettyAtJettyHomeHelper {
|
|||
*/
|
||||
private static String getJettyConfigurationURLs(Bundle configurationBundle)
|
||||
{
|
||||
String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES,"etc/jetty.xml");
|
||||
String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES,"etc/jetty.xml");
|
||||
StringTokenizer tokenizer = new StringTokenizer(jettyetc,";,", false);
|
||||
StringBuilder res = new StringBuilder();
|
||||
|
||||
|
||||
while (tokenizer.hasMoreTokens())
|
||||
{
|
||||
String etcFile = tokenizer.nextToken().trim();
|
||||
if (etcFile.startsWith("/") || etcFile.indexOf(":") != -1)
|
||||
{
|
||||
appendToCommaSeparatedList(res, etcFile);
|
||||
appendToCommaSeparatedList(res, etcFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
Enumeration<URL> enUrls = BundleFileLocatorHelper.DEFAULT
|
||||
.findEntries(configurationBundle, etcFile);
|
||||
|
||||
//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.
|
||||
if ((enUrls == null || !enUrls.hasMoreElements()) && etcFile.endsWith("etc/jetty.xml"))
|
||||
{
|
||||
enUrls = BundleFileLocatorHelper.DEFAULT
|
||||
.findEntries(configurationBundle, "/jettyhome/etc/jetty-osgi-default.xml");
|
||||
System.err.println("Configuring jetty with the default embedded configuration:" +
|
||||
"bundle: " + configurationBundle.getSymbolicName() +
|
||||
" config: /jettyhome/etc/jetty-osgi-default.xml");
|
||||
}
|
||||
if (enUrls == null || !enUrls.hasMoreElements())
|
||||
{
|
||||
System.err.println("Unable to locate a jetty configuration file for " + etcFile);
|
||||
}
|
||||
if (enUrls != null)
|
||||
{
|
||||
while (enUrls.hasMoreElements())
|
||||
{
|
||||
appendToCommaSeparatedList(res, enUrls.nextElement().toString());
|
||||
}
|
||||
}
|
||||
Enumeration<URL> enUrls = BundleFileLocatorHelper.DEFAULT
|
||||
.findEntries(configurationBundle, etcFile);
|
||||
|
||||
//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.
|
||||
if ((enUrls == null || !enUrls.hasMoreElements()) && etcFile.endsWith("etc/jetty.xml"))
|
||||
{
|
||||
enUrls = BundleFileLocatorHelper.DEFAULT
|
||||
.findEntries(configurationBundle, "/jettyhome/etc/jetty-osgi-default.xml");
|
||||
System.err.println("Configuring jetty with the default embedded configuration:" +
|
||||
"bundle: " + configurationBundle.getSymbolicName() +
|
||||
" config: /jettyhome/etc/jetty-osgi-default.xml");
|
||||
}
|
||||
if (enUrls == null || !enUrls.hasMoreElements())
|
||||
{
|
||||
LOG.warn("Unable to locate a jetty configuration file for " + etcFile);
|
||||
}
|
||||
if (enUrls != null)
|
||||
{
|
||||
while (enUrls.hasMoreElements())
|
||||
{
|
||||
appendToCommaSeparatedList(res, enUrls.nextElement().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
private static void appendToCommaSeparatedList(StringBuilder buffer, String value)
|
||||
{
|
||||
if (buffer.length() != 0)
|
||||
{
|
||||
buffer.append(",");
|
||||
}
|
||||
buffer.append(value);
|
||||
}
|
||||
|
||||
private static void setProperty(Dictionary 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;
|
||||
}
|
||||
}
|
||||
|
||||
private static void appendToCommaSeparatedList(StringBuilder buffer, String value)
|
||||
{
|
||||
if (buffer.length() != 0)
|
||||
{
|
||||
buffer.append(",");
|
||||
}
|
||||
buffer.append(value);
|
||||
}
|
||||
|
||||
private static void setProperty(Dictionary 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,50 +18,53 @@ import java.util.Properties;
|
|||
|
||||
import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.osgi.framework.Bundle;
|
||||
import org.osgi.framework.ServiceEvent;
|
||||
import org.osgi.framework.ServiceListener;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
|
||||
/**
|
||||
* Deploy the jetty server instances when they are registered as an OSGi service.
|
||||
* Deploy the jetty server instances when they are registered as an OSGi
|
||||
* service.
|
||||
*/
|
||||
public class JettyServerServiceTracker implements ServiceListener, IManagedJettyServerRegistry
|
||||
{
|
||||
|
||||
private static Logger LOG = Log.getLogger(JettyServerServiceTracker.class.getName());
|
||||
|
||||
/**
|
||||
* Servers indexed by PIDs. PIDs are generated by the ConfigurationAdmin service.
|
||||
* 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>();
|
||||
|
||||
|
||||
/**
|
||||
* Stops each one of the registered servers.
|
||||
*/
|
||||
public void stop()
|
||||
{
|
||||
//not sure that this is really useful but here we go.
|
||||
for (ServerInstanceWrapper wrapper : _serversIndexedByName.values())
|
||||
{
|
||||
try
|
||||
{
|
||||
wrapper.stop();
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
// not sure that this is really useful but here we go.
|
||||
for (ServerInstanceWrapper wrapper : _serversIndexedByName.values())
|
||||
{
|
||||
try
|
||||
{
|
||||
wrapper.stop();
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
LOG.warn(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Receives notification that a service has had a lifecycle change.
|
||||
*
|
||||
* @param ev
|
||||
* The <code>ServiceEvent</code> object.
|
||||
* @param ev The <code>ServiceEvent</code> object.
|
||||
*/
|
||||
public void serviceChanged(ServiceEvent ev)
|
||||
{
|
||||
|
@ -71,17 +74,16 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
|
|||
case ServiceEvent.MODIFIED:
|
||||
case ServiceEvent.UNREGISTERING:
|
||||
{
|
||||
ServerInstanceWrapper instance = unregisterInIndex(ev.getServiceReference());
|
||||
ServerInstanceWrapper instance = unregisterInIndex(ev.getServiceReference());
|
||||
if (instance != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
instance.stop();
|
||||
instance.stop();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,32 +98,35 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
|
|||
}
|
||||
case ServiceEvent.REGISTERED:
|
||||
{
|
||||
Bundle contributor = sr.getBundle();
|
||||
Server server = (Server)contributor.getBundleContext().getService(sr);
|
||||
ServerInstanceWrapper wrapper = registerInIndex(server, sr);
|
||||
Properties props = new Properties();
|
||||
for (String key : sr.getPropertyKeys())
|
||||
{
|
||||
Object value = sr.getProperty(key);
|
||||
props.put(key, value);
|
||||
}
|
||||
wrapper.start(server, props);
|
||||
break;
|
||||
try
|
||||
{
|
||||
Bundle contributor = sr.getBundle();
|
||||
Server server = (Server) contributor.getBundleContext().getService(sr);
|
||||
ServerInstanceWrapper wrapper = registerInIndex(server, sr);
|
||||
Properties props = new Properties();
|
||||
for (String key : sr.getPropertyKeys())
|
||||
{
|
||||
Object value = sr.getProperty(key);
|
||||
props.put(key, value);
|
||||
}
|
||||
wrapper.start(server, props);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ServerInstanceWrapper registerInIndex(Server server, ServiceReference sr)
|
||||
{
|
||||
String name = (String)sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
|
||||
if (name == null)
|
||||
{
|
||||
throw new IllegalArgumentException("The property " +
|
||||
OSGiServerConstants.MANAGED_JETTY_SERVER_NAME + " is mandatory");
|
||||
}
|
||||
String name = (String) sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
|
||||
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);
|
||||
_indexByServiceReference.put(sr, wrapper);
|
||||
_serversIndexedByName.put(name, wrapper);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
|
@ -133,7 +138,7 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
|
|||
*/
|
||||
private ServerInstanceWrapper unregisterInIndex(ServiceReference sr)
|
||||
{
|
||||
ServerInstanceWrapper handler = _indexByServiceReference.remove(sr);
|
||||
ServerInstanceWrapper handler = _indexByServiceReference.remove(sr);
|
||||
if (handler == null)
|
||||
{
|
||||
// a warning?
|
||||
|
@ -149,13 +154,12 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
|
|||
|
||||
/**
|
||||
* @param managedServerName The server name
|
||||
* @return the corresponding jetty server wrapped with its deployment properties.
|
||||
* @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);
|
||||
return _serversIndexedByName.get(managedServerName == null ? OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME : managedServerName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -99,14 +99,21 @@ public class JettyServersManagedFactory implements ManagedServiceFactory, IManag
|
|||
String name = (String)properties.get(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
|
||||
if (name == null)
|
||||
{
|
||||
throw new ConfigurationException(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME,
|
||||
"The name of the server is mandatory");
|
||||
throw new ConfigurationException(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME,
|
||||
"The name of the server is mandatory");
|
||||
}
|
||||
serverInstanceWrapper = new ServerInstanceWrapper(name);
|
||||
_serversIndexedByPID.put(pid, serverInstanceWrapper);
|
||||
_serversNameIndexedByPID.put(pid, name);
|
||||
_serversPIDIndexedByName.put(name, pid);
|
||||
serverInstanceWrapper.start(new Server(), properties);
|
||||
try
|
||||
{
|
||||
serverInstanceWrapper.start(new Server(), properties);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ConfigurationException(null, "Error starting jetty server instance", e);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void deleted(String pid)
|
||||
|
|
|
@ -44,28 +44,29 @@ import org.eclipse.jetty.util.resource.Resource;
|
|||
import org.eclipse.jetty.xml.XmlConfiguration;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
|
||||
/**
|
||||
* Exposes a Jetty Server to be managed by an OSGi ManagedServiceFactory
|
||||
* Configure and start it.
|
||||
* Can also be used from the ManagedServiceFactory
|
||||
* Configure and start it. Can also be used from the ManagedServiceFactory
|
||||
*/
|
||||
public class ServerInstanceWrapper {
|
||||
public class ServerInstanceWrapper
|
||||
{
|
||||
|
||||
/** The value of this property points to the parent director of
|
||||
* the jetty.xml configuration file currently executed.
|
||||
* Everything is passed as a URL to support the
|
||||
* case where the bundle is zipped. */
|
||||
/**
|
||||
* The value of this property points to the parent director of the jetty.xml
|
||||
* configuration file currently executed. Everything is passed as a URL to
|
||||
* support the case where the bundle is zipped.
|
||||
*/
|
||||
public static final String PROPERTY_THIS_JETTY_XML_FOLDER_URL = "this.jetty.xml.parent.folder.url";
|
||||
|
||||
private static Logger __logger = Log.getLogger(ServerInstanceWrapper.class.getName());
|
||||
|
||||
private static Logger LOG = Log.getLogger(ServerInstanceWrapper.class.getName());
|
||||
|
||||
private final String _managedServerName;
|
||||
|
||||
|
||||
/**
|
||||
* The managed jetty server
|
||||
*/
|
||||
private Server _server;
|
||||
|
||||
private ContextHandlerCollection _ctxtHandler;
|
||||
|
||||
/**
|
||||
|
@ -74,32 +75,34 @@ public class ServerInstanceWrapper {
|
|||
* let the TldScanner find the jars where the tld files are.
|
||||
*/
|
||||
private ClassLoader _commonParentClassLoaderForWebapps;
|
||||
|
||||
private DeploymentManager _deploymentManager;
|
||||
|
||||
private OSGiAppProvider _provider;
|
||||
|
||||
|
||||
private WebBundleDeployerHelper _webBundleDeployerHelper;
|
||||
|
||||
|
||||
|
||||
public ServerInstanceWrapper(String managedServerName)
|
||||
{
|
||||
_managedServerName = managedServerName;
|
||||
}
|
||||
|
||||
|
||||
public String getManagedServerName()
|
||||
{
|
||||
return _managedServerName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The classloader that should be the parent classloader for
|
||||
* each webapp deployed on this server.
|
||||
* The classloader that should be the parent classloader for each webapp
|
||||
* deployed on this server.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ClassLoader getParentClassLoaderForWebapps()
|
||||
{
|
||||
return _commonParentClassLoaderForWebapps;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return The deployment manager registered on this server.
|
||||
*/
|
||||
|
@ -107,7 +110,7 @@ public class ServerInstanceWrapper {
|
|||
{
|
||||
return _deploymentManager;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return The app provider registered on this server.
|
||||
*/
|
||||
|
@ -115,19 +118,17 @@ public class ServerInstanceWrapper {
|
|||
{
|
||||
return _provider;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Server getServer()
|
||||
{
|
||||
return _server;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public WebBundleDeployerHelper getWebBundleDeployerHelp()
|
||||
{
|
||||
return _webBundleDeployerHelper;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return The collection of context handlers
|
||||
*/
|
||||
|
@ -136,8 +137,7 @@ public class ServerInstanceWrapper {
|
|||
return _ctxtHandler;
|
||||
}
|
||||
|
||||
|
||||
public void start(Server server, Dictionary props)
|
||||
public void start(Server server, Dictionary props) throws Exception
|
||||
{
|
||||
_server = server;
|
||||
ClassLoader contextCl = Thread.currentThread().getContextClassLoader();
|
||||
|
@ -146,62 +146,61 @@ public class ServerInstanceWrapper {
|
|||
// passing this bundle's classloader as the context classlaoder
|
||||
// makes sure there is access to all the jetty's bundles
|
||||
ClassLoader libExtClassLoader = null;
|
||||
String sharedURLs = (String)props.get(OSGiServerConstants.MANAGED_JETTY_SHARED_LIB_FOLDER_URLS);
|
||||
try
|
||||
{
|
||||
List<File> shared = sharedURLs != null ? extractFiles(sharedURLs) : null;
|
||||
libExtClassLoader = LibExtClassLoaderHelper.createLibExtClassLoader(
|
||||
shared, null, server, JettyBootstrapActivator.class.getClassLoader());
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
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());
|
||||
|
||||
Thread.currentThread().setContextClassLoader(libExtClassLoader);
|
||||
|
||||
|
||||
configure(server, props);
|
||||
|
||||
init();
|
||||
|
||||
//now that we have an app provider we can call the registration customizer.
|
||||
try
|
||||
{
|
||||
URL[] jarsWithTlds = getJarsWithTlds();
|
||||
_commonParentClassLoaderForWebapps = jarsWithTlds == null
|
||||
? libExtClassLoader
|
||||
:new TldLocatableURLClassloader(libExtClassLoader,jarsWithTlds);
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
// now that we have an app provider we can call the registration
|
||||
// customizer.
|
||||
|
||||
URL[] jarsWithTlds = getJarsWithTlds();
|
||||
_commonParentClassLoaderForWebapps = jarsWithTlds == null ? libExtClassLoader : new TldLocatableURLClassloader(libExtClassLoader, jarsWithTlds);
|
||||
|
||||
|
||||
server.start();
|
||||
_webBundleDeployerHelper = new WebBundleDeployerHelper(this);
|
||||
}
|
||||
catch (Throwable t)
|
||||
catch (Exception e)
|
||||
{
|
||||
t.printStackTrace();
|
||||
if (server != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
LOG.ignore(x);
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Thread.currentThread().setContextClassLoader(contextCl);
|
||||
}
|
||||
_webBundleDeployerHelper = new WebBundleDeployerHelper(this);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void stop()
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
if (_server.isRunning())
|
||||
{
|
||||
_server.stop();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,14 +228,13 @@ public class ServerInstanceWrapper {
|
|||
private URL[] getJarsWithTlds() throws Exception
|
||||
{
|
||||
ArrayList<URL> res = new ArrayList<URL>();
|
||||
WebBundleDeployerHelper.staticInit();//that is not looking great.
|
||||
WebBundleDeployerHelper.staticInit();// that is not looking great.
|
||||
for (WebappRegistrationCustomizer regCustomizer : WebBundleDeployerHelper.JSP_REGISTRATION_HELPERS)
|
||||
{
|
||||
URL[] urls = regCustomizer.getJarsWithTlds(_provider, WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER);
|
||||
for (URL url : urls)
|
||||
{
|
||||
if (!res.contains(url))
|
||||
res.add(url);
|
||||
if (!res.contains(url)) res.add(url);
|
||||
}
|
||||
}
|
||||
if (!res.isEmpty())
|
||||
|
@ -244,19 +242,15 @@ public class ServerInstanceWrapper {
|
|||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
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>();
|
||||
id_map.put("Server",server);
|
||||
Map<String,String> properties = new HashMap<String,String>();
|
||||
List<URL> jettyConfigurations = jettyConfigurationUrls != null ? extractResources(jettyConfigurationUrls) : null;
|
||||
if (jettyConfigurations == null || jettyConfigurations.isEmpty()) { return; }
|
||||
Map<String, Object> id_map = new HashMap<String, Object>();
|
||||
id_map.put("Server", server);
|
||||
Map<String, String> properties = new HashMap<String, String>();
|
||||
Enumeration<Object> en = props.keys();
|
||||
while (en.hasMoreElements())
|
||||
{
|
||||
|
@ -275,15 +269,17 @@ public class ServerInstanceWrapper {
|
|||
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.
|
||||
|
||||
// #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);
|
||||
Map<String, String> properties2 = new HashMap<String, String>(properties);
|
||||
properties2.put(PROPERTY_THIS_JETTY_XML_FOLDER_URL, urlPath);
|
||||
config.getProperties().putAll(properties2);
|
||||
}
|
||||
|
@ -292,11 +288,11 @@ public class ServerInstanceWrapper {
|
|||
config.getProperties().putAll(properties);
|
||||
}
|
||||
config.configure();
|
||||
id_map=config.getIdMap();
|
||||
id_map = config.getIdMap();
|
||||
}
|
||||
catch (SAXParseException saxparse)
|
||||
{
|
||||
__logger.warn("Unable to configure the jetty/etc file " + jettyConfiguration,saxparse);
|
||||
LOG.warn("Unable to configure the jetty/etc file " + jettyConfiguration, saxparse);
|
||||
throw saxparse;
|
||||
}
|
||||
finally
|
||||
|
@ -306,8 +302,7 @@ public class ServerInstanceWrapper {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Must be called after the server is configured.
|
||||
*
|
||||
|
@ -319,50 +314,48 @@ public class ServerInstanceWrapper {
|
|||
private void init()
|
||||
{
|
||||
// Get the context handler
|
||||
_ctxtHandler = (ContextHandlerCollection)_server.getChildHandlerByClass(ContextHandlerCollection.class);
|
||||
|
||||
_ctxtHandler = (ContextHandlerCollection) _server.getChildHandlerByClass(ContextHandlerCollection.class);
|
||||
|
||||
// get a deployerManager
|
||||
List<DeploymentManager> deployers = _server.getBeans(DeploymentManager.class);
|
||||
if (deployers != null && !deployers.isEmpty())
|
||||
{
|
||||
_deploymentManager = deployers.get(0);
|
||||
|
||||
|
||||
for (AppProvider provider : _deploymentManager.getAppProviders())
|
||||
{
|
||||
if (provider instanceof OSGiAppProvider)
|
||||
{
|
||||
_provider=(OSGiAppProvider)provider;
|
||||
_provider = (OSGiAppProvider) provider;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (_provider == null)
|
||||
{
|
||||
//create it on the fly with reasonable default values.
|
||||
// create it on the fly with reasonable default values.
|
||||
try
|
||||
{
|
||||
_provider = new OSGiAppProvider();
|
||||
_provider.setMonitoredDirResource(
|
||||
Resource.newResource(getDefaultOSGiContextsHome(
|
||||
new File(System.getProperty("jetty.home"))).toURI()));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
_provider.setMonitoredDirResource(Resource.newResource(getDefaultOSGiContextsHome(new File(System.getProperty("jetty.home"))).toURI()));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
_deploymentManager.addAppProvider(_provider);
|
||||
}
|
||||
}
|
||||
|
||||
if (_ctxtHandler == null || _provider==null)
|
||||
throw new IllegalStateException("ERROR: No ContextHandlerCollection or OSGiAppProvider configured");
|
||||
|
||||
if (_ctxtHandler == null || _provider == null) throw new IllegalStateException("ERROR: No ContextHandlerCollection or OSGiAppProvider configured");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* "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)
|
||||
{
|
||||
|
@ -370,20 +363,19 @@ public class ServerInstanceWrapper {
|
|||
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");
|
||||
}
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
File getOSGiContextsHome()
|
||||
{
|
||||
return _provider.getContextXmlDirAsFile();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the urls in this string.
|
||||
*/
|
||||
|
@ -396,19 +388,19 @@ public class ServerInstanceWrapper {
|
|||
String tok = tokenizer.nextToken();
|
||||
try
|
||||
{
|
||||
urls.add(((DefaultFileLocatorHelper) WebBundleDeployerHelper
|
||||
.BUNDLE_FILE_LOCATOR_HELPER).getLocalURL(new URL(tok)));
|
||||
urls.add(((DefaultFileLocatorHelper) WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER).getLocalURL(new URL(tok)));
|
||||
}
|
||||
catch (Throwable mfe)
|
||||
{
|
||||
|
||||
LOG.warn(mfe);
|
||||
}
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the folders that might contain jars for the legacy J2EE shared libraries
|
||||
* Get the folders that might contain jars for the legacy J2EE shared
|
||||
* libraries
|
||||
*/
|
||||
private List<File> extractFiles(String propertyValue)
|
||||
{
|
||||
|
@ -420,8 +412,7 @@ public class ServerInstanceWrapper {
|
|||
try
|
||||
{
|
||||
URL url = new URL(tok);
|
||||
url = ((DefaultFileLocatorHelper) WebBundleDeployerHelper
|
||||
.BUNDLE_FILE_LOCATOR_HELPER).getFileURL(url);
|
||||
url = ((DefaultFileLocatorHelper) WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER).getFileURL(url);
|
||||
if (url.getProtocol().equals("file"))
|
||||
{
|
||||
Resource res = Resource.newResource(url);
|
||||
|
@ -434,11 +425,10 @@ public class ServerInstanceWrapper {
|
|||
}
|
||||
catch (Throwable mfe)
|
||||
{
|
||||
|
||||
LOG.warn(mfe);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ import org.eclipse.jetty.osgi.boot.internal.serverfactory.DefaultJettyAtJettyHom
|
|||
import org.eclipse.jetty.osgi.boot.internal.serverfactory.IManagedJettyServerRegistry;
|
||||
import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.Scanner;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.osgi.framework.Bundle;
|
||||
|
@ -52,15 +54,17 @@ import org.osgi.framework.ServiceReference;
|
|||
*/
|
||||
public class JettyContextHandlerServiceTracker implements ServiceListener
|
||||
{
|
||||
|
||||
/** New style: ability to manage multiple jetty instances */
|
||||
private final IManagedJettyServerRegistry _registry;
|
||||
private static Logger __logger = Log.getLogger(WebBundleDeployerHelper.class.getName());
|
||||
|
||||
/** New style: ability to manage multiple jetty instances */
|
||||
private final IManagedJettyServerRegistry _registry;
|
||||
|
||||
/** The context-handler to deactivate indexed by context handler */
|
||||
private Map<ServiceReference, ContextHandler> _indexByServiceReference = new HashMap<ServiceReference, ContextHandler>();
|
||||
|
||||
/**
|
||||
* The index is the bundle-symbolic-name/path/to/context/file when there is such thing
|
||||
* The index is the bundle-symbolic-name/path/to/context/file when there is
|
||||
* such thing
|
||||
*/
|
||||
private Map<String, ServiceReference> _indexByContextFile = new HashMap<String, ServiceReference>();
|
||||
|
||||
|
@ -72,7 +76,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
|
|||
*/
|
||||
public JettyContextHandlerServiceTracker(IManagedJettyServerRegistry registry) throws Exception
|
||||
{
|
||||
_registry = registry;
|
||||
_registry = registry;
|
||||
}
|
||||
|
||||
public void stop() throws Exception
|
||||
|
@ -85,19 +89,16 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
|
|||
// nothing to stop in the WebappRegistrationHelper
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param contextHome Parent folder where the context files can override the context files
|
||||
* defined in the web bundles: equivalent to the contexts folder in a traditional
|
||||
* jetty installation.
|
||||
* when null, just do nothing.
|
||||
* @param contextHome Parent folder where the context files can override the
|
||||
* context files defined in the web bundles: equivalent to the
|
||||
* contexts folder in a traditional jetty installation. when
|
||||
* null, just do nothing.
|
||||
*/
|
||||
protected void setupContextHomeScanner(File contextHome) throws IOException
|
||||
{
|
||||
if (contextHome == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (contextHome == null) { return; }
|
||||
final String osgiContextHomeFolderCanonicalPath = contextHome.getCanonicalPath();
|
||||
_scanner = new Scanner();
|
||||
_scanner.setRecursive(true);
|
||||
|
@ -132,8 +133,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
|
|||
/**
|
||||
* Receives notification that a service has had a lifecycle change.
|
||||
*
|
||||
* @param ev
|
||||
* The <code>ServiceEvent</code> object.
|
||||
* @param ev The <code>ServiceEvent</code> object.
|
||||
*/
|
||||
public void serviceChanged(ServiceEvent ev)
|
||||
{
|
||||
|
@ -148,12 +148,11 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
|
|||
{
|
||||
try
|
||||
{
|
||||
getWebBundleDeployerHelp(sr).unregister(ctxtHandler);
|
||||
getWebBundleDeployerHelp(sr).unregister(ctxtHandler);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
__logger.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,30 +169,32 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
|
|||
{
|
||||
Bundle contributor = sr.getBundle();
|
||||
BundleContext context = FrameworkUtil.getBundle(JettyBootstrapActivator.class).getBundleContext();
|
||||
ContextHandler contextHandler = (ContextHandler)context.getService(sr);
|
||||
ContextHandler contextHandler = (ContextHandler) context.getService(sr);
|
||||
if (contextHandler.getServer() != null)
|
||||
{
|
||||
// is configured elsewhere.
|
||||
return;
|
||||
}
|
||||
String contextFilePath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH);
|
||||
String contextFilePath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH);
|
||||
if (contextHandler instanceof WebAppContext && contextFilePath == null)
|
||||
//it could be a web-application that will in fact be configured via a context file.
|
||||
//that case is identified by the fact that the contextFilePath is not null
|
||||
//in that case we must use the register context methods.
|
||||
// it could be a web-application that will in fact be configured
|
||||
// via a context file.
|
||||
// that case is identified by the fact that the contextFilePath
|
||||
// is not null
|
||||
// in that case we must use the register context methods.
|
||||
{
|
||||
WebAppContext webapp = (WebAppContext)contextHandler;
|
||||
String contextPath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH);
|
||||
WebAppContext webapp = (WebAppContext) contextHandler;
|
||||
String contextPath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH);
|
||||
if (contextPath == null)
|
||||
{
|
||||
contextPath = webapp.getContextPath();
|
||||
}
|
||||
String webXmlPath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_WEB_XML_PATH);
|
||||
String webXmlPath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_WEB_XML_PATH);
|
||||
if (webXmlPath == null)
|
||||
{
|
||||
webXmlPath = webapp.getDescriptor();
|
||||
}
|
||||
String defaultWebXmlPath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_DEFAULT_WEB_XML_PATH);
|
||||
String defaultWebXmlPath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_DEFAULT_WEB_XML_PATH);
|
||||
if (defaultWebXmlPath == null)
|
||||
{
|
||||
String jettyHome = System.getProperty(DefaultJettyAtJettyHomeHelper.SYS_PROP_JETTY_HOME);
|
||||
|
@ -202,7 +203,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
|
|||
File etc = new File(jettyHome, "etc");
|
||||
if (etc.exists() && etc.isDirectory())
|
||||
{
|
||||
File webDefault = new File (etc, "webdefault.xml");
|
||||
File webDefault = new File(etc, "webdefault.xml");
|
||||
if (webDefault.exists())
|
||||
defaultWebXmlPath = webDefault.getAbsolutePath();
|
||||
else
|
||||
|
@ -212,83 +213,80 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
|
|||
defaultWebXmlPath = webapp.getDefaultsDescriptor();
|
||||
}
|
||||
}
|
||||
String war = (String)sr.getProperty("war");
|
||||
String war = (String) sr.getProperty("war");
|
||||
try
|
||||
{
|
||||
IWebBundleDeployerHelper deployerHelper = getWebBundleDeployerHelp(sr);
|
||||
if (deployerHelper == null)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
WebAppContext handler = deployerHelper
|
||||
.registerWebapplication(contributor,war,contextPath,
|
||||
(String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_EXTRA_CLASSPATH),
|
||||
(String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE),
|
||||
(String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE),
|
||||
webXmlPath,defaultWebXmlPath,webapp);
|
||||
IWebBundleDeployerHelper deployerHelper = getWebBundleDeployerHelp(sr);
|
||||
if (deployerHelper == null)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
WebAppContext handler = deployerHelper.registerWebapplication(contributor,
|
||||
war,
|
||||
contextPath,
|
||||
(String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_EXTRA_CLASSPATH),
|
||||
(String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE),
|
||||
(String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE),
|
||||
webXmlPath, defaultWebXmlPath, webapp);
|
||||
if (handler != null)
|
||||
{
|
||||
registerInIndex(handler,sr);
|
||||
registerInIndex(handler, sr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
__logger.warn(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// consider this just an empty skeleton:
|
||||
if (contextFilePath == null)
|
||||
{
|
||||
throw new IllegalArgumentException("the property contextFilePath is required");
|
||||
}
|
||||
if (contextFilePath == null) { throw new IllegalArgumentException("the property contextFilePath is required"); }
|
||||
try
|
||||
{
|
||||
IWebBundleDeployerHelper deployerHelper = getWebBundleDeployerHelp(sr);
|
||||
if (deployerHelper == null)
|
||||
{
|
||||
//more warnings?
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Boolean.TRUE.toString().equals(sr.getProperty(
|
||||
IWebBundleDeployerHelper.INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE)))
|
||||
{
|
||||
contextHandler = null;
|
||||
}
|
||||
ContextHandler handler = deployerHelper.registerContext(contributor,contextFilePath,
|
||||
(String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_EXTRA_CLASSPATH),
|
||||
(String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE),
|
||||
(String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE),
|
||||
contextHandler);
|
||||
if (handler != null)
|
||||
{
|
||||
registerInIndex(handler,sr);
|
||||
}
|
||||
}
|
||||
IWebBundleDeployerHelper deployerHelper = getWebBundleDeployerHelp(sr);
|
||||
if (deployerHelper == null)
|
||||
{
|
||||
// more warnings?
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Boolean.TRUE.toString().equals(sr.getProperty(IWebBundleDeployerHelper.INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE)))
|
||||
{
|
||||
contextHandler = null;
|
||||
}
|
||||
ContextHandler handler = deployerHelper.registerContext(contributor,
|
||||
contextFilePath,
|
||||
(String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_EXTRA_CLASSPATH),
|
||||
(String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE),
|
||||
(String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE),
|
||||
contextHandler);
|
||||
if (handler != null)
|
||||
{
|
||||
registerInIndex(handler, sr);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
__logger.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void registerInIndex(ContextHandler handler, ServiceReference sr)
|
||||
{
|
||||
_indexByServiceReference.put(sr,handler);
|
||||
_indexByServiceReference.put(sr, handler);
|
||||
String key = getSymbolicNameAndContextFileKey(sr);
|
||||
if (key != null)
|
||||
{
|
||||
_indexByContextFile.put(key,sr);
|
||||
_indexByContextFile.put(key, sr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -320,11 +318,8 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
|
|||
*/
|
||||
private String getSymbolicNameAndContextFileKey(ServiceReference sr)
|
||||
{
|
||||
String contextFilePath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH);
|
||||
if (contextFilePath != null)
|
||||
{
|
||||
return sr.getBundle().getSymbolicName() + "/" + contextFilePath;
|
||||
}
|
||||
String contextFilePath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH);
|
||||
if (contextFilePath != null) { return sr.getBundle().getSymbolicName() + "/" + contextFilePath; }
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -336,17 +331,14 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
|
|||
public void reloadJettyContextHandler(String canonicalNameOfFileChanged, String osgiContextHomeFolderCanonicalPath)
|
||||
{
|
||||
String key = getNormalizedRelativePath(canonicalNameOfFileChanged, osgiContextHomeFolderCanonicalPath);
|
||||
if (key == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (key == null) { return; }
|
||||
ServiceReference sr = _indexByContextFile.get(key);
|
||||
if (sr == null)
|
||||
{
|
||||
// nothing to do?
|
||||
return;
|
||||
}
|
||||
serviceChanged(new ServiceEvent(ServiceEvent.MODIFIED,sr));
|
||||
serviceChanged(new ServiceEvent(ServiceEvent.MODIFIED, sr));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -362,36 +354,31 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
|
|||
// warning?
|
||||
return null;
|
||||
}
|
||||
return canFilename.substring(osgiContextHomeFolderCanonicalPath.length()).replace('\\','/');
|
||||
return canFilename.substring(osgiContextHomeFolderCanonicalPath.length()).replace('\\', '/');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return The server on which this webapp is meant to be deployed
|
||||
*/
|
||||
private ServerInstanceWrapper getServerInstanceWrapper(String managedServerName)
|
||||
{
|
||||
if (_registry == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (managedServerName == null)
|
||||
{
|
||||
managedServerName = OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME;
|
||||
}
|
||||
ServerInstanceWrapper wrapper = _registry.getServerInstanceWrapper(managedServerName);
|
||||
//System.err.println("Returning " + managedServerName + " = " + wrapper);
|
||||
return wrapper;
|
||||
if (_registry == null) { return null; }
|
||||
if (managedServerName == null)
|
||||
{
|
||||
managedServerName = OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME;
|
||||
}
|
||||
ServerInstanceWrapper wrapper = _registry.getServerInstanceWrapper(managedServerName);
|
||||
// System.err.println("Returning " + managedServerName + " = " +
|
||||
// wrapper);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
|
||||
private IWebBundleDeployerHelper getWebBundleDeployerHelp(ServiceReference sr)
|
||||
{
|
||||
if (_registry == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String managedServerName = (String)sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
|
||||
ServerInstanceWrapper wrapper = getServerInstanceWrapper(managedServerName);
|
||||
return wrapper != null ? wrapper.getWebBundleDeployerHelp() : null;
|
||||
if (_registry == null) { return null; }
|
||||
String managedServerName = (String) sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
|
||||
ServerInstanceWrapper wrapper = getServerInstanceWrapper(managedServerName);
|
||||
return wrapper != null ? wrapper.getWebBundleDeployerHelp() : null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -247,7 +247,7 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
|
|||
catch (IOException e)
|
||||
{
|
||||
// nevermind. just trying our best
|
||||
e.printStackTrace();
|
||||
__logger.ignore(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
|
|||
catch (Throwable t)
|
||||
{
|
||||
// humf that will hurt if it does not work.
|
||||
t.printStackTrace();
|
||||
__logger.warn("Unable to set webappcontext", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,13 +78,14 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
private static Logger __logger = Log.getLogger(WebBundleDeployerHelper.class.getName());
|
||||
|
||||
private static boolean INITIALIZED = false;
|
||||
|
||||
|
||||
/**
|
||||
* By default set to: {@link DefaultBundleClassLoaderHelper}. It supports
|
||||
* equinox and apache-felix fragment bundles that are specific to an OSGi
|
||||
* implementation should set a different implementation.
|
||||
*/
|
||||
public static BundleClassLoaderHelper BUNDLE_CLASS_LOADER_HELPER = null;
|
||||
|
||||
/**
|
||||
* By default set to: {@link DefaultBundleClassLoaderHelper}. It supports
|
||||
* equinox and apache-felix fragment bundles that are specific to an OSGi
|
||||
|
@ -97,8 +98,9 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
* equinox and apache-felix fragment bundles that are specific to an OSGi
|
||||
* implementation should set a different implementation.
|
||||
* <p>
|
||||
* Several of those objects can be added here: For example we could have an optional fragment that setups
|
||||
* a specific implementation of JSF for the whole of jetty-osgi.
|
||||
* Several of those objects can be added here: For example we could have an
|
||||
* optional fragment that setups a specific implementation of JSF for the
|
||||
* whole of jetty-osgi.
|
||||
* </p>
|
||||
*/
|
||||
public static Collection<WebappRegistrationCustomizer> JSP_REGISTRATION_HELPERS = new ArrayList<WebappRegistrationCustomizer>();
|
||||
|
@ -127,7 +129,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
// setup the custom BundleClassLoaderHelper
|
||||
try
|
||||
{
|
||||
BUNDLE_CLASS_LOADER_HELPER = (BundleClassLoaderHelper)Class.forName(BundleClassLoaderHelper.CLASS_NAME).newInstance();
|
||||
BUNDLE_CLASS_LOADER_HELPER = (BundleClassLoaderHelper) Class.forName(BundleClassLoaderHelper.CLASS_NAME).newInstance();
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
|
@ -137,7 +139,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
// setup the custom FileLocatorHelper
|
||||
try
|
||||
{
|
||||
BUNDLE_FILE_LOCATOR_HELPER = (BundleFileLocatorHelper)Class.forName(BundleFileLocatorHelper.CLASS_NAME).newInstance();
|
||||
BUNDLE_FILE_LOCATOR_HELPER = (BundleFileLocatorHelper) Class.forName(BundleFileLocatorHelper.CLASS_NAME).newInstance();
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
|
@ -150,34 +152,28 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
/**
|
||||
* Deploy a new web application on the jetty server.
|
||||
*
|
||||
* @param bundle
|
||||
* The bundle
|
||||
* @param webappFolderPath
|
||||
* The path to the root of the webapp. Must be a path relative to
|
||||
* bundle; either an absolute path.
|
||||
* @param contextPath
|
||||
* The context path. Must start with "/"
|
||||
* @param bundle The bundle
|
||||
* @param webappFolderPath The path to the root of the webapp. Must be a
|
||||
* path relative to bundle; either an absolute path.
|
||||
* @param contextPath The context path. Must start with "/"
|
||||
* @param extraClasspath
|
||||
* @param overrideBundleInstallLocation
|
||||
* @param requireTldBundle The list of bundles's symbolic names that contain
|
||||
* tld files that are required by this WAB.
|
||||
* tld files that are required by this WAB.
|
||||
* @param webXmlPath
|
||||
* @param defaultWebXmlPath
|
||||
* TODO: parameter description
|
||||
* @param defaultWebXmlPath TODO: parameter description
|
||||
* @return The contexthandler created and started
|
||||
* @throws Exception
|
||||
*/
|
||||
public WebAppContext registerWebapplication(Bundle bundle,
|
||||
String webappFolderPath, String contextPath, String extraClasspath,
|
||||
String overrideBundleInstallLocation,
|
||||
String requireTldBundle, String webXmlPath,
|
||||
String defaultWebXmlPath, WebAppContext webAppContext) throws Exception
|
||||
public WebAppContext registerWebapplication(Bundle bundle, String webappFolderPath, String contextPath, String extraClasspath,
|
||||
String overrideBundleInstallLocation, String requireTldBundle, String webXmlPath, String defaultWebXmlPath,
|
||||
WebAppContext webAppContext) throws Exception
|
||||
{
|
||||
File bundleInstall = overrideBundleInstallLocation == null?BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(bundle):new File(
|
||||
overrideBundleInstallLocation);
|
||||
File bundleInstall = overrideBundleInstallLocation == null ? BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(bundle) : new File(
|
||||
overrideBundleInstallLocation);
|
||||
File webapp = null;
|
||||
URL baseWebappInstallURL = null;
|
||||
|
||||
|
||||
if (webappFolderPath != null && webappFolderPath.length() != 0 && !webappFolderPath.equals("."))
|
||||
{
|
||||
if (webappFolderPath.startsWith("/") || webappFolderPath.startsWith("file:"))
|
||||
|
@ -186,7 +182,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
}
|
||||
else if (bundleInstall != null && bundleInstall.isDirectory())
|
||||
{
|
||||
webapp = new File(bundleInstall,webappFolderPath);
|
||||
webapp = new File(bundleInstall, webappFolderPath);
|
||||
}
|
||||
else if (bundleInstall != null)
|
||||
{
|
||||
|
@ -201,37 +197,48 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
{
|
||||
webapp = bundleInstall;
|
||||
}
|
||||
if (baseWebappInstallURL == null && (webapp == null || !webapp.exists()))
|
||||
{
|
||||
throw new IllegalArgumentException("Unable to locate " + webappFolderPath + " inside "
|
||||
+ (bundleInstall != null?bundleInstall.getAbsolutePath():"unlocated bundle '" + bundle.getSymbolicName() + "'"));
|
||||
}
|
||||
if (baseWebappInstallURL == null && (webapp == null || !webapp.exists())) { throw new IllegalArgumentException(
|
||||
"Unable to locate " + webappFolderPath
|
||||
+ " inside "
|
||||
+ (bundleInstall != null ? bundleInstall.getAbsolutePath() : "unlocated bundle '" + bundle.getSymbolicName()
|
||||
+ "'")); }
|
||||
if (baseWebappInstallURL == null && webapp != null)
|
||||
{
|
||||
baseWebappInstallURL = webapp.toURI().toURL();
|
||||
}
|
||||
return registerWebapplication(bundle,webappFolderPath,baseWebappInstallURL,contextPath,
|
||||
extraClasspath,bundleInstall,requireTldBundle,webXmlPath,defaultWebXmlPath,webAppContext);
|
||||
return registerWebapplication(bundle, webappFolderPath, baseWebappInstallURL, contextPath, extraClasspath, bundleInstall, requireTldBundle, webXmlPath,
|
||||
defaultWebXmlPath, webAppContext);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#registerWebapplication(org.osgi.framework.Bundle, java.lang.String, java.io.File, java.lang.String, java.lang.String, java.io.File, java.lang.String, java.lang.String)
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#
|
||||
* registerWebapplication(org.osgi.framework.Bundle, java.lang.String,
|
||||
* java.io.File, java.lang.String, java.lang.String, java.io.File,
|
||||
* java.lang.String, java.lang.String)
|
||||
*/
|
||||
private WebAppContext registerWebapplication(Bundle contributor, String pathInBundleToWebApp,
|
||||
URL baseWebappInstallURL, String contextPath, String extraClasspath, File bundleInstall,
|
||||
String requireTldBundle, String webXmlPath, String defaultWebXmlPath, WebAppContext context)
|
||||
throws Exception
|
||||
private WebAppContext registerWebapplication(Bundle contributor, String pathInBundleToWebApp, URL baseWebappInstallURL, String contextPath,
|
||||
String extraClasspath, File bundleInstall, String requireTldBundle, String webXmlPath,
|
||||
String defaultWebXmlPath, WebAppContext context) throws Exception
|
||||
{
|
||||
|
||||
ClassLoader contextCl = Thread.currentThread().getContextClassLoader();
|
||||
String[] oldServerClasses = null;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
|
||||
//apply any META-INF/context.xml file that is found to configure the webapp first
|
||||
applyMetaInfContextXml (contributor, context);
|
||||
|
||||
// make sure we provide access to all the jetty bundles by going
|
||||
// through this bundle.
|
||||
OSGiWebappClassLoader composite = createWebappClassLoader(contributor);
|
||||
// configure with access to all jetty classes and also all the classes
|
||||
// configure with access to all jetty classes and also all the
|
||||
// classes
|
||||
// that the contributor gives access to.
|
||||
Thread.currentThread().setContextClassLoader(composite);
|
||||
|
||||
|
@ -248,7 +255,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
}
|
||||
else
|
||||
{
|
||||
webXml = new File(bundleInstall,webXmlPath);
|
||||
webXml = new File(bundleInstall, webXmlPath);
|
||||
}
|
||||
if (webXml.exists())
|
||||
{
|
||||
|
@ -258,7 +265,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
|
||||
if (defaultWebXmlPath == null || defaultWebXmlPath.length() == 0)
|
||||
{
|
||||
//use the one defined by the OSGiAppProvider.
|
||||
// use the one defined by the OSGiAppProvider.
|
||||
defaultWebXmlPath = _wrapper.getOSGiAppProvider().getDefaultsDescriptor();
|
||||
}
|
||||
if (defaultWebXmlPath != null && defaultWebXmlPath.length() != 0)
|
||||
|
@ -270,20 +277,19 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
}
|
||||
else
|
||||
{
|
||||
defaultWebXml = new File(bundleInstall,defaultWebXmlPath);
|
||||
defaultWebXml = new File(bundleInstall, defaultWebXmlPath);
|
||||
}
|
||||
if (defaultWebXml.exists())
|
||||
{
|
||||
context.setDefaultsDescriptor(defaultWebXml.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
//other parameters that might be defines on the OSGiAppProvider:
|
||||
|
||||
// other parameters that might be defines on the OSGiAppProvider:
|
||||
context.setParentLoaderPriority(_wrapper.getOSGiAppProvider().isParentLoaderPriority());
|
||||
|
||||
configureWebappClassLoader(contributor,context,composite, requireTldBundle);
|
||||
configureWebAppContext(context,contributor,requireTldBundle);
|
||||
|
||||
configureWebappClassLoader(contributor, context, composite, requireTldBundle);
|
||||
configureWebAppContext(context, contributor, requireTldBundle);
|
||||
|
||||
// @see
|
||||
// org.eclipse.jetty.webapp.JettyWebXmlConfiguration#configure(WebAppContext)
|
||||
|
@ -292,36 +298,36 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
// through the webapp classloader.
|
||||
oldServerClasses = context.getServerClasses();
|
||||
context.setServerClasses(null);
|
||||
|
||||
_wrapper.getOSGiAppProvider().addContext(contributor,pathInBundleToWebApp,context);
|
||||
|
||||
//support for patch resources. ideally this should be done inside a configurator.
|
||||
List<Resource> patchResources =
|
||||
(List<Resource>)context.getAttribute(WebInfConfiguration.RESOURCE_URLS+".patch");
|
||||
|
||||
_wrapper.getOSGiAppProvider().addContext(contributor, pathInBundleToWebApp, context);
|
||||
|
||||
// support for patch resources. ideally this should be done inside a
|
||||
// configurator.
|
||||
List<Resource> patchResources = (List<Resource>) context.getAttribute(WebInfConfiguration.RESOURCE_URLS + ".patch");
|
||||
if (patchResources != null)
|
||||
{
|
||||
LinkedList<Resource> resourcesPath = new LinkedList<Resource>();
|
||||
//place the patch resources at the beginning of the lookup path.
|
||||
resourcesPath.addAll(patchResources);
|
||||
//then place the ones from the host web bundle.
|
||||
Resource hostResources = context.getBaseResource();
|
||||
if (hostResources instanceof ResourceCollection)
|
||||
{
|
||||
for (Resource re : ((ResourceCollection)hostResources).getResources())
|
||||
{
|
||||
resourcesPath.add(re);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
resourcesPath.add(hostResources);
|
||||
}
|
||||
|
||||
ResourceCollection rc = new ResourceCollection(resourcesPath.toArray(
|
||||
new Resource[resourcesPath.size()]));
|
||||
context.setBaseResource(rc);
|
||||
LinkedList<Resource> resourcesPath = new LinkedList<Resource>();
|
||||
// place the patch resources at the beginning of the lookup
|
||||
// path.
|
||||
resourcesPath.addAll(patchResources);
|
||||
// then place the ones from the host web bundle.
|
||||
Resource hostResources = context.getBaseResource();
|
||||
if (hostResources instanceof ResourceCollection)
|
||||
{
|
||||
for (Resource re : ((ResourceCollection) hostResources).getResources())
|
||||
{
|
||||
resourcesPath.add(re);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
resourcesPath.add(hostResources);
|
||||
}
|
||||
|
||||
ResourceCollection rc = new ResourceCollection(resourcesPath.toArray(new Resource[resourcesPath.size()]));
|
||||
context.setBaseResource(rc);
|
||||
}
|
||||
|
||||
|
||||
return context;
|
||||
}
|
||||
finally
|
||||
|
@ -335,38 +341,41 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#unregister(org.eclipse.jetty.server.handler.ContextHandler)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#
|
||||
* unregister(org.eclipse.jetty.server.handler.ContextHandler)
|
||||
*/
|
||||
public void unregister(ContextHandler contextHandler) throws Exception
|
||||
{
|
||||
_wrapper.getOSGiAppProvider().removeContext(contextHandler);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#registerContext(org.osgi.framework.Bundle, java.lang.String, java.lang.String, java.lang.String)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#
|
||||
* registerContext(org.osgi.framework.Bundle, java.lang.String,
|
||||
* java.lang.String, java.lang.String)
|
||||
*/
|
||||
public ContextHandler registerContext(Bundle contributor, String contextFileRelativePath, String extraClasspath,
|
||||
String overrideBundleInstallLocation, String requireTldBundle, ContextHandler handler)
|
||||
throws Exception
|
||||
public ContextHandler registerContext(Bundle contributor, String contextFileRelativePath, String extraClasspath, String overrideBundleInstallLocation,
|
||||
String requireTldBundle, ContextHandler handler) throws Exception
|
||||
{
|
||||
File contextsHome = _wrapper.getOSGiAppProvider().getContextXmlDirAsFile();
|
||||
if (contextsHome != null)
|
||||
{
|
||||
File prodContextFile = new File(contextsHome,contributor.getSymbolicName() + "/" + contextFileRelativePath);
|
||||
if (prodContextFile.exists())
|
||||
{
|
||||
return registerContext(contributor,contextFileRelativePath,prodContextFile,extraClasspath,
|
||||
overrideBundleInstallLocation,requireTldBundle,handler);
|
||||
}
|
||||
File prodContextFile = new File(contextsHome, contributor.getSymbolicName() + "/" + contextFileRelativePath);
|
||||
if (prodContextFile.exists()) { return registerContext(contributor, contextFileRelativePath, prodContextFile, extraClasspath,
|
||||
overrideBundleInstallLocation, requireTldBundle, handler); }
|
||||
}
|
||||
File rootFolder = overrideBundleInstallLocation != null
|
||||
? Resource.newResource(overrideBundleInstallLocation).getFile()
|
||||
: BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(contributor);
|
||||
File contextFile = rootFolder != null?new File(rootFolder,contextFileRelativePath):null;
|
||||
File rootFolder = overrideBundleInstallLocation != null ? Resource.newResource(overrideBundleInstallLocation).getFile() : BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(contributor);
|
||||
File contextFile = rootFolder != null ? new File(rootFolder, contextFileRelativePath) : null;
|
||||
if (contextFile != null && contextFile.exists())
|
||||
{
|
||||
return registerContext(contributor,contextFileRelativePath,contextFile,extraClasspath,overrideBundleInstallLocation,requireTldBundle,handler);
|
||||
return registerContext(contributor, contextFileRelativePath, contextFile, extraClasspath, overrideBundleInstallLocation, requireTldBundle, handler);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -378,15 +387,19 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
{
|
||||
contextFileRelativePath = "/" + contextFileRelativePath;
|
||||
}
|
||||
|
||||
|
||||
URL contextURL = contributor.getEntry(contextFileRelativePath);
|
||||
if (contextURL != null)
|
||||
{
|
||||
Resource r = Resource.newResource(contextURL);
|
||||
return registerContext(contributor,contextFileRelativePath,r.getInputStream(),extraClasspath,overrideBundleInstallLocation,requireTldBundle,handler);
|
||||
Resource r = Resource.newResource(contextURL);
|
||||
return registerContext(contributor, contextFileRelativePath, r.getInputStream(), extraClasspath, overrideBundleInstallLocation,
|
||||
requireTldBundle, handler);
|
||||
}
|
||||
throw new IllegalArgumentException("Could not find the context " + "file " + contextFileRelativePath + " for the bundle "
|
||||
+ contributor.getSymbolicName() + (overrideBundleInstallLocation != null?" using the install location " + overrideBundleInstallLocation:""));
|
||||
throw new IllegalArgumentException("Could not find the context " + "file "
|
||||
+ contextFileRelativePath
|
||||
+ " for the bundle "
|
||||
+ contributor.getSymbolicName()
|
||||
+ (overrideBundleInstallLocation != null ? " using the install location " + overrideBundleInstallLocation : ""));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,22 +413,20 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
* @param classInBundle
|
||||
* @throws Exception
|
||||
*/
|
||||
private ContextHandler registerContext(Bundle contributor, String pathInBundle, File contextFile,
|
||||
String extraClasspath, String overrideBundleInstallLocation,
|
||||
String requireTldBundle, ContextHandler handler) throws Exception
|
||||
private ContextHandler registerContext(Bundle contributor, String pathInBundle, File contextFile, String extraClasspath,
|
||||
String overrideBundleInstallLocation, String requireTldBundle, ContextHandler handler) throws Exception
|
||||
{
|
||||
InputStream contextFileInputStream = null;
|
||||
try
|
||||
{
|
||||
contextFileInputStream = new BufferedInputStream(new FileInputStream(contextFile));
|
||||
return registerContext(contributor, pathInBundle, contextFileInputStream,
|
||||
extraClasspath,overrideBundleInstallLocation,requireTldBundle,handler);
|
||||
return registerContext(contributor, pathInBundle, contextFileInputStream, extraClasspath, overrideBundleInstallLocation, requireTldBundle, handler);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IO.close(contextFileInputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param contributor
|
||||
|
@ -424,11 +435,8 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
* happen.
|
||||
* @throws Exception
|
||||
*/
|
||||
private ContextHandler registerContext(Bundle contributor,
|
||||
String pathInsideBundle, InputStream contextFileInputStream,
|
||||
String extraClasspath, String overrideBundleInstallLocation,
|
||||
String requireTldBundle, ContextHandler handler)
|
||||
throws Exception
|
||||
private ContextHandler registerContext(Bundle contributor, String pathInsideBundle, InputStream contextFileInputStream, String extraClasspath,
|
||||
String overrideBundleInstallLocation, String requireTldBundle, ContextHandler handler) throws Exception
|
||||
{
|
||||
ClassLoader contextCl = Thread.currentThread().getContextClassLoader();
|
||||
String[] oldServerClasses = null;
|
||||
|
@ -442,24 +450,23 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
// classes
|
||||
// that the contributor gives access to.
|
||||
Thread.currentThread().setContextClassLoader(composite);
|
||||
ContextHandler context = createContextHandler(handler, contributor,
|
||||
contextFileInputStream,extraClasspath,
|
||||
overrideBundleInstallLocation,requireTldBundle);
|
||||
if (context == null)
|
||||
{
|
||||
ContextHandler context = createContextHandler(handler, contributor, contextFileInputStream, extraClasspath, overrideBundleInstallLocation,
|
||||
requireTldBundle);
|
||||
if (context == null)
|
||||
{
|
||||
return null;// did not happen
|
||||
}
|
||||
|
||||
// ok now register this webapp. we checked when we started jetty
|
||||
// that there
|
||||
// was at least one such handler for webapps.
|
||||
//the actual registration must happen via the new Deployment API.
|
||||
// _ctxtHandler.addHandler(context);
|
||||
// the actual registration must happen via the new Deployment API.
|
||||
// _ctxtHandler.addHandler(context);
|
||||
|
||||
configureWebappClassLoader(contributor,context,composite, requireTldBundle);
|
||||
configureWebappClassLoader(contributor, context, composite, requireTldBundle);
|
||||
if (context instanceof WebAppContext)
|
||||
{
|
||||
webAppContext = (WebAppContext)context;
|
||||
webAppContext = (WebAppContext) context;
|
||||
// @see
|
||||
// org.eclipse.jetty.webapp.JettyWebXmlConfiguration#configure(WebAppContext)
|
||||
oldServerClasses = webAppContext.getServerClasses();
|
||||
|
@ -485,60 +492,58 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
* @see {WebAppDeployer#scan} around the comment
|
||||
* <code>// configure it</code>
|
||||
*/
|
||||
protected void configureWebAppContext(ContextHandler wah, Bundle contributor,
|
||||
String requireTldBundle) throws IOException
|
||||
protected void configureWebAppContext(ContextHandler wah, Bundle contributor, String requireTldBundle) throws IOException
|
||||
{
|
||||
// rfc66
|
||||
wah.setAttribute(OSGiWebappConstants.RFC66_OSGI_BUNDLE_CONTEXT,contributor.getBundleContext());
|
||||
wah.setAttribute(OSGiWebappConstants.RFC66_OSGI_BUNDLE_CONTEXT, contributor.getBundleContext());
|
||||
|
||||
//spring-dm-1.2.1 looks for the BundleContext as a different attribute.
|
||||
//not a spec... but if we want to support
|
||||
//org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext
|
||||
//then we need to do this to:
|
||||
wah.setAttribute("org.springframework.osgi.web." + BundleContext.class.getName(),
|
||||
contributor.getBundleContext());
|
||||
|
||||
//also pass the bundle directly. sometimes a bundle does not have a bundlecontext.
|
||||
//it is still useful to have access to the Bundle from the servlet context.
|
||||
// spring-dm-1.2.1 looks for the BundleContext as a different attribute.
|
||||
// not a spec... but if we want to support
|
||||
// org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext
|
||||
// then we need to do this to:
|
||||
wah.setAttribute("org.springframework.osgi.web." + BundleContext.class.getName(), contributor.getBundleContext());
|
||||
|
||||
// also pass the bundle directly. sometimes a bundle does not have a
|
||||
// bundlecontext.
|
||||
// it is still useful to have access to the Bundle from the servlet
|
||||
// context.
|
||||
wah.setAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE, contributor);
|
||||
|
||||
//pass the value of the require tld bundle so that the TagLibOSGiConfiguration
|
||||
//can pick it up.
|
||||
|
||||
// pass the value of the require tld bundle so that the
|
||||
// TagLibOSGiConfiguration
|
||||
// can pick it up.
|
||||
wah.setAttribute(OSGiWebappConstants.REQUIRE_TLD_BUNDLE, requireTldBundle);
|
||||
|
||||
if (wah instanceof WebAppContext)
|
||||
{
|
||||
if (_wrapper.getOSGiAppProvider().getConfigurationClasses() != null)
|
||||
{
|
||||
((WebAppContext)wah).setConfigurationClasses(_wrapper.getOSGiAppProvider().getConfigurationClasses());
|
||||
}
|
||||
}
|
||||
|
||||
Bundle[] fragments = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles(contributor);
|
||||
if (fragments != null && fragments.length != 0)
|
||||
{
|
||||
//sorted extra resource base found in the fragments.
|
||||
//the resources are either overriding the resourcebase found in the web-bundle
|
||||
//or appended.
|
||||
//amongst each resource we sort them according to the alphabetical order
|
||||
//of the name of the internal folder and the symbolic name of the fragment.
|
||||
//this is useful to make sure that the lookup path of those
|
||||
//resource base defined by fragments is always the same.
|
||||
//This natural order could be abused to define the order in which the base resources are
|
||||
//looked up.
|
||||
TreeMap<String,Resource> patchResourcesPath = new TreeMap<String,Resource>();
|
||||
TreeMap<String,Resource> appendedResourcesPath = new TreeMap<String,Resource>();
|
||||
for (Bundle frag : fragments) {
|
||||
String fragFolder = (String)frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_FRAGMENT_FOLDER_PATH);
|
||||
String patchFragFolder = (String)frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_PATCH_FRAGMENT_FOLDER_PATH);
|
||||
// sorted extra resource base found in the fragments.
|
||||
// the resources are either overriding the resourcebase found in the
|
||||
// web-bundle
|
||||
// or appended.
|
||||
// amongst each resource we sort them according to the alphabetical
|
||||
// order
|
||||
// of the name of the internal folder and the symbolic name of the
|
||||
// fragment.
|
||||
// this is useful to make sure that the lookup path of those
|
||||
// resource base defined by fragments is always the same.
|
||||
// This natural order could be abused to define the order in which
|
||||
// the base resources are
|
||||
// looked up.
|
||||
TreeMap<String, Resource> patchResourcesPath = new TreeMap<String, Resource>();
|
||||
TreeMap<String, Resource> appendedResourcesPath = new TreeMap<String, Resource>();
|
||||
for (Bundle frag : fragments)
|
||||
{
|
||||
String fragFolder = (String) frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_FRAGMENT_FOLDER_PATH);
|
||||
String patchFragFolder = (String) frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_PATCH_FRAGMENT_FOLDER_PATH);
|
||||
if (fragFolder != null)
|
||||
{
|
||||
URL fragUrl = frag.getEntry(fragFolder);
|
||||
if (fragUrl == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Unable to locate " + fragFolder + " inside "
|
||||
+ " the fragment '" + frag.getSymbolicName() + "'");
|
||||
}
|
||||
if (fragUrl == null) { throw new IllegalArgumentException("Unable to locate " + fragFolder
|
||||
+ " inside "
|
||||
+ " the fragment '"
|
||||
+ frag.getSymbolicName()
|
||||
+ "'"); }
|
||||
fragUrl = DefaultFileLocatorHelper.getLocalURL(fragUrl);
|
||||
String key = fragFolder.startsWith("/") ? fragFolder.substring(1) : fragFolder;
|
||||
appendedResourcesPath.put(key + ";" + frag.getSymbolicName(), Resource.newResource(fragUrl));
|
||||
|
@ -546,11 +551,11 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
if (patchFragFolder != null)
|
||||
{
|
||||
URL patchFragUrl = frag.getEntry(patchFragFolder);
|
||||
if (patchFragUrl == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Unable to locate " + patchFragUrl + " inside "
|
||||
+ " the fragment '" + frag.getSymbolicName() + "'");
|
||||
}
|
||||
if (patchFragUrl == null) { throw new IllegalArgumentException("Unable to locate " + patchFragUrl
|
||||
+ " inside "
|
||||
+ " the fragment '"
|
||||
+ frag.getSymbolicName()
|
||||
+ "'"); }
|
||||
patchFragUrl = DefaultFileLocatorHelper.getLocalURL(patchFragUrl);
|
||||
String key = patchFragFolder.startsWith("/") ? patchFragFolder.substring(1) : patchFragFolder;
|
||||
patchResourcesPath.put(key + ";" + frag.getSymbolicName(), Resource.newResource(patchFragUrl));
|
||||
|
@ -558,92 +563,92 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
}
|
||||
if (!appendedResourcesPath.isEmpty())
|
||||
{
|
||||
wah.setAttribute(WebInfConfiguration.RESOURCE_URLS, new ArrayList<Resource>(appendedResourcesPath.values()));
|
||||
wah.setAttribute(WebInfConfiguration.RESOURCE_URLS, new ArrayList<Resource>(appendedResourcesPath.values()));
|
||||
}
|
||||
if (!patchResourcesPath.isEmpty())
|
||||
{
|
||||
wah.setAttribute(WebInfConfiguration.RESOURCE_URLS + ".patch", new ArrayList<Resource>(patchResourcesPath.values()));
|
||||
wah.setAttribute(WebInfConfiguration.RESOURCE_URLS + ".patch", new ArrayList<Resource>(patchResourcesPath.values()));
|
||||
}
|
||||
|
||||
|
||||
if (wah instanceof WebAppContext)
|
||||
{
|
||||
//This is the equivalent of what MetaInfConfiguration does. For OSGi bundles without the JarScanner
|
||||
WebAppContext webappCtxt = (WebAppContext)wah;
|
||||
//take care of the web-fragments, meta-inf resources and tld resources:
|
||||
//similar to what MetaInfConfiguration does.
|
||||
List<Resource> frags = (List<Resource>)wah.getAttribute(FragmentConfiguration.FRAGMENT_RESOURCES);
|
||||
List<Resource> resfrags = (List<Resource>)wah.getAttribute(WebInfConfiguration.RESOURCE_URLS);
|
||||
List<Resource> tldfrags = (List<Resource>)wah.getAttribute(TagLibConfiguration.TLD_RESOURCES);
|
||||
for (Bundle frag : fragments)
|
||||
{
|
||||
URL webFrag = frag.getEntry("/META-INF/web-fragment.xml");
|
||||
Enumeration<URL> resEnum = frag.findEntries("/META-INF/resources", "*", true);
|
||||
Enumeration<URL> tldEnum = frag.findEntries("/META-INF", "*.tld", false);
|
||||
if (webFrag != null || (resEnum != null && resEnum.hasMoreElements())
|
||||
|| (tldEnum != null && tldEnum.hasMoreElements()))
|
||||
{
|
||||
try
|
||||
{
|
||||
File fragFile = BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(frag);
|
||||
//add it to the webinf jars collection:
|
||||
//no need to check that it was not there yet: it was not there yet for sure.
|
||||
Resource fragFileAsResource = Resource.newResource(fragFile.toURI());
|
||||
webappCtxt.getMetaData().addWebInfJar(fragFileAsResource);
|
||||
|
||||
if (webFrag != null)
|
||||
{
|
||||
if (frags == null)
|
||||
{
|
||||
frags = new ArrayList<Resource>();
|
||||
wah.setAttribute(FragmentConfiguration.FRAGMENT_RESOURCES, frags);
|
||||
}
|
||||
frags.add(fragFileAsResource);
|
||||
}
|
||||
if (resEnum != null && resEnum.hasMoreElements())
|
||||
{
|
||||
URL resourcesEntry = frag.getEntry("/META-INF/resources/");
|
||||
if (resourcesEntry == null)
|
||||
{
|
||||
//probably we found some fragments to a bundle.
|
||||
//those are already contributed.
|
||||
//so we skip this.
|
||||
}
|
||||
else
|
||||
{
|
||||
if (resfrags == null)
|
||||
{
|
||||
resfrags = new ArrayList<Resource>();
|
||||
wah.setAttribute(WebInfConfiguration.RESOURCE_URLS, resfrags);
|
||||
}
|
||||
resfrags.add(Resource.newResource(
|
||||
DefaultFileLocatorHelper.getLocalURL(resourcesEntry)));
|
||||
}
|
||||
}
|
||||
if (tldEnum != null && tldEnum.hasMoreElements())
|
||||
{
|
||||
if (tldfrags == null)
|
||||
{
|
||||
tldfrags = new ArrayList<Resource>();
|
||||
wah.setAttribute(TagLibConfiguration.TLD_RESOURCES, tldfrags);
|
||||
}
|
||||
while (tldEnum.hasMoreElements())
|
||||
{
|
||||
URL tldUrl = tldEnum.nextElement();
|
||||
tldfrags.add(Resource.newResource(
|
||||
DefaultFileLocatorHelper.getLocalURL(tldUrl)));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
__logger.warn("Unable to locate the bundle " + frag.getBundleId(),e);
|
||||
}
|
||||
}
|
||||
}
|
||||
// This is the equivalent of what MetaInfConfiguration does. For
|
||||
// OSGi bundles without the JarScanner
|
||||
WebAppContext webappCtxt = (WebAppContext) wah;
|
||||
// take care of the web-fragments, meta-inf resources and tld
|
||||
// resources:
|
||||
// similar to what MetaInfConfiguration does.
|
||||
List<Resource> frags = (List<Resource>) wah.getAttribute(FragmentConfiguration.FRAGMENT_RESOURCES);
|
||||
List<Resource> resfrags = (List<Resource>) wah.getAttribute(WebInfConfiguration.RESOURCE_URLS);
|
||||
List<Resource> tldfrags = (List<Resource>) wah.getAttribute(TagLibConfiguration.TLD_RESOURCES);
|
||||
for (Bundle frag : fragments)
|
||||
{
|
||||
URL webFrag = frag.getEntry("/META-INF/web-fragment.xml");
|
||||
Enumeration<URL> resEnum = frag.findEntries("/META-INF/resources", "*", true);
|
||||
Enumeration<URL> tldEnum = frag.findEntries("/META-INF", "*.tld", false);
|
||||
if (webFrag != null || (resEnum != null && resEnum.hasMoreElements()) || (tldEnum != null && tldEnum.hasMoreElements()))
|
||||
{
|
||||
try
|
||||
{
|
||||
File fragFile = BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(frag);
|
||||
// add it to the webinf jars collection:
|
||||
// no need to check that it was not there yet: it
|
||||
// was not there yet for sure.
|
||||
Resource fragFileAsResource = Resource.newResource(fragFile.toURI());
|
||||
webappCtxt.getMetaData().addWebInfJar(fragFileAsResource);
|
||||
|
||||
if (webFrag != null)
|
||||
{
|
||||
if (frags == null)
|
||||
{
|
||||
frags = new ArrayList<Resource>();
|
||||
wah.setAttribute(FragmentConfiguration.FRAGMENT_RESOURCES, frags);
|
||||
}
|
||||
frags.add(fragFileAsResource);
|
||||
}
|
||||
if (resEnum != null && resEnum.hasMoreElements())
|
||||
{
|
||||
URL resourcesEntry = frag.getEntry("/META-INF/resources/");
|
||||
if (resourcesEntry == null)
|
||||
{
|
||||
// probably we found some fragments to a
|
||||
// bundle.
|
||||
// those are already contributed.
|
||||
// so we skip this.
|
||||
}
|
||||
else
|
||||
{
|
||||
if (resfrags == null)
|
||||
{
|
||||
resfrags = new ArrayList<Resource>();
|
||||
wah.setAttribute(WebInfConfiguration.RESOURCE_URLS, resfrags);
|
||||
}
|
||||
resfrags.add(Resource.newResource(DefaultFileLocatorHelper.getLocalURL(resourcesEntry)));
|
||||
}
|
||||
}
|
||||
if (tldEnum != null && tldEnum.hasMoreElements())
|
||||
{
|
||||
if (tldfrags == null)
|
||||
{
|
||||
tldfrags = new ArrayList<Resource>();
|
||||
wah.setAttribute(TagLibConfiguration.TLD_RESOURCES, tldfrags);
|
||||
}
|
||||
while (tldEnum.hasMoreElements())
|
||||
{
|
||||
URL tldUrl = tldEnum.nextElement();
|
||||
tldfrags.add(Resource.newResource(DefaultFileLocatorHelper.getLocalURL(tldUrl)));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
__logger.warn("Unable to locate the bundle " + frag.getBundleId(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -651,19 +656,17 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
* @param contextFile
|
||||
* @return
|
||||
*/
|
||||
protected ContextHandler createContextHandler(ContextHandler handlerToConfigure,
|
||||
Bundle bundle, File contextFile, String extraClasspath,
|
||||
String overrideBundleInstallLocation, String requireTldBundle)
|
||||
protected ContextHandler createContextHandler(ContextHandler handlerToConfigure, Bundle bundle, File contextFile, String extraClasspath,
|
||||
String overrideBundleInstallLocation, String requireTldBundle)
|
||||
{
|
||||
try
|
||||
{
|
||||
return createContextHandler(handlerToConfigure,bundle,
|
||||
new BufferedInputStream(new FileInputStream(contextFile)),
|
||||
extraClasspath,overrideBundleInstallLocation,requireTldBundle);
|
||||
return createContextHandler(handlerToConfigure, bundle, new BufferedInputStream(new FileInputStream(contextFile)), extraClasspath,
|
||||
overrideBundleInstallLocation, requireTldBundle);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
__logger.warn(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -674,9 +677,8 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ContextHandler createContextHandler(ContextHandler handlerToConfigure,
|
||||
Bundle bundle, InputStream contextInputStream, String extraClasspath,
|
||||
String overrideBundleInstallLocation, String requireTldBundle)
|
||||
protected ContextHandler createContextHandler(ContextHandler handlerToConfigure, Bundle bundle, InputStream contextInputStream, String extraClasspath,
|
||||
String overrideBundleInstallLocation, String requireTldBundle)
|
||||
{
|
||||
/*
|
||||
* Do something identical to what the ContextProvider would have done:
|
||||
|
@ -693,30 +695,30 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
{
|
||||
XmlConfiguration xmlConfiguration = new XmlConfiguration(contextInputStream);
|
||||
HashMap properties = new HashMap();
|
||||
properties.put("Server",_wrapper.getServer());
|
||||
|
||||
properties.put("Server", _wrapper.getServer());
|
||||
|
||||
// insert the bundle's location as a property.
|
||||
setThisBundleHomeProperty(bundle,properties,overrideBundleInstallLocation);
|
||||
setThisBundleHomeProperty(bundle, properties, overrideBundleInstallLocation);
|
||||
xmlConfiguration.getProperties().putAll(properties);
|
||||
|
||||
ContextHandler context = null;
|
||||
if (handlerToConfigure == null)
|
||||
{
|
||||
context = (ContextHandler)xmlConfiguration.configure();
|
||||
context = (ContextHandler) xmlConfiguration.configure();
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlConfiguration.configure(handlerToConfigure);
|
||||
context = handlerToConfigure;
|
||||
}
|
||||
|
||||
|
||||
if (context instanceof WebAppContext)
|
||||
{
|
||||
((WebAppContext)context).setExtraClasspath(extraClasspath);
|
||||
((WebAppContext)context).setParentLoaderPriority(_wrapper.getOSGiAppProvider().isParentLoaderPriority());
|
||||
((WebAppContext) context).setExtraClasspath(extraClasspath);
|
||||
((WebAppContext) context).setParentLoaderPriority(_wrapper.getOSGiAppProvider().isParentLoaderPriority());
|
||||
if (_wrapper.getOSGiAppProvider().getDefaultsDescriptor() != null && _wrapper.getOSGiAppProvider().getDefaultsDescriptor().length() != 0)
|
||||
{
|
||||
((WebAppContext)context).setDefaultsDescriptor(_wrapper.getOSGiAppProvider().getDefaultsDescriptor());
|
||||
((WebAppContext) context).setDefaultsDescriptor(_wrapper.getOSGiAppProvider().getDefaultsDescriptor());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -729,18 +731,15 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
__logger.warn(e);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
__logger.warn(e);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
__logger.warn(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -782,13 +781,12 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
{
|
||||
if (context instanceof WebAppContext)
|
||||
{
|
||||
WebAppContext webappCtxt = (WebAppContext)context;
|
||||
WebAppContext webappCtxt = (WebAppContext) context;
|
||||
context.setClassLoader(webappClassLoader);
|
||||
webappClassLoader.setWebappContext(webappCtxt);
|
||||
|
||||
String pathsToRequiredBundles = getPathsToRequiredBundles(context, requireTldBundle);
|
||||
if (pathsToRequiredBundles != null)
|
||||
webappClassLoader.addClassPath(pathsToRequiredBundles);
|
||||
if (pathsToRequiredBundles != null) webappClassLoader.addClassPath(pathsToRequiredBundles);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -804,23 +802,48 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
// we use a temporary WebAppContext object.
|
||||
// if this is a real webapp we will set it on it a bit later: once we
|
||||
// know.
|
||||
OSGiWebappClassLoader webappClassLoader = new OSGiWebappClassLoader(
|
||||
_wrapper.getParentClassLoaderForWebapps(),new WebAppContext(),contributor,BUNDLE_CLASS_LOADER_HELPER);
|
||||
/* DEBUG
|
||||
try {
|
||||
Class c = webappClassLoader.loadClass("org.glassfish.jsp.api.ResourceInjector");
|
||||
System.err.println("LOADED org.glassfish.jsp.api.ResourceInjector from "+c.getClassLoader());
|
||||
}
|
||||
catch (Exception e) {e.printStackTrace();}
|
||||
try {
|
||||
Class c = webappClassLoader.loadClass("org.apache.jasper.xmlparser.ParserUtils");
|
||||
System.err.println("LOADED org.apache.jasper.xmlparser.ParserUtils from "+c.getClassLoader());
|
||||
}
|
||||
catch (Exception e) {e.printStackTrace();}
|
||||
*/
|
||||
OSGiWebappClassLoader webappClassLoader = new OSGiWebappClassLoader(_wrapper.getParentClassLoaderForWebapps(), new WebAppContext(), contributor,
|
||||
BUNDLE_CLASS_LOADER_HELPER);
|
||||
return webappClassLoader;
|
||||
}
|
||||
|
||||
|
||||
protected void applyMetaInfContextXml (Bundle bundle, ContextHandler contextHandler)
|
||||
throws Exception
|
||||
{
|
||||
if (bundle == null)
|
||||
return;
|
||||
if (contextHandler == null)
|
||||
return;
|
||||
|
||||
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||
__logger.info("Context classloader = "+cl);
|
||||
try
|
||||
{
|
||||
Thread.currentThread().setContextClassLoader(_wrapper.getParentClassLoaderForWebapps());
|
||||
|
||||
//find if there is a META-INF/context.xml file
|
||||
URL contextXmlUrl = bundle.getEntry("/META-INF/jetty-webapp-context.xml");
|
||||
if (contextXmlUrl == null)
|
||||
return;
|
||||
|
||||
//Apply it just as the standard jetty ContextProvider would do
|
||||
__logger.info("Applying "+contextXmlUrl+" to "+contextHandler);
|
||||
|
||||
XmlConfiguration xmlConfiguration = new XmlConfiguration(contextXmlUrl);
|
||||
HashMap properties = new HashMap();
|
||||
properties.put("Server", _wrapper.getServer());
|
||||
xmlConfiguration.getProperties().putAll(properties);
|
||||
xmlConfiguration.configure(contextHandler);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Thread.currentThread().setContextClassLoader(cl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the property "this.bundle.install" to point to the location
|
||||
* of the bundle. Useful when <SystemProperty name="this.bundle.home"/> is
|
||||
|
@ -830,10 +853,9 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
{
|
||||
try
|
||||
{
|
||||
File location = overrideBundleInstallLocation != null?new File(overrideBundleInstallLocation):BUNDLE_FILE_LOCATOR_HELPER
|
||||
.getBundleInstallLocation(bundle);
|
||||
properties.put("this.bundle.install",location.getCanonicalPath());
|
||||
properties.put("this.bundle.install.url",bundle.getEntry("/").toString());
|
||||
File location = overrideBundleInstallLocation != null ? new File(overrideBundleInstallLocation) : BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(bundle);
|
||||
properties.put("this.bundle.install", location.getCanonicalPath());
|
||||
properties.put("this.bundle.install.url", bundle.getEntry("/").toString());
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
|
@ -841,36 +863,30 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private String getPathsToRequiredBundles (ContextHandler context, String requireTldBundle) throws Exception
|
||||
private String getPathsToRequiredBundles(ContextHandler context, String requireTldBundle) throws Exception
|
||||
{
|
||||
if (requireTldBundle == null)
|
||||
return null;
|
||||
if (requireTldBundle == null) return null;
|
||||
|
||||
StringBuilder paths = new StringBuilder();
|
||||
Bundle bundle = (Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE);
|
||||
Bundle bundle = (Bundle) context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE);
|
||||
PackageAdmin packAdmin = getBundleAdmin();
|
||||
DefaultFileLocatorHelper fileLocatorHelper = new DefaultFileLocatorHelper();
|
||||
|
||||
|
||||
String[] symbNames = requireTldBundle.split(", ");
|
||||
|
||||
for (String symbName : symbNames)
|
||||
{
|
||||
Bundle[] bs = packAdmin.getBundles(symbName, null);
|
||||
if (bs == null || bs.length == 0)
|
||||
{
|
||||
throw new IllegalArgumentException("Unable to locate the bundle '"
|
||||
+ symbName + "' specified in the "
|
||||
+ OSGiWebappConstants.REQUIRE_TLD_BUNDLE
|
||||
+ " of the manifest of "
|
||||
+ bundle.getSymbolicName());
|
||||
}
|
||||
if (bs == null || bs.length == 0) { throw new IllegalArgumentException("Unable to locate the bundle '" + symbName
|
||||
+ "' specified in the "
|
||||
+ OSGiWebappConstants.REQUIRE_TLD_BUNDLE
|
||||
+ " of the manifest of "
|
||||
+ bundle.getSymbolicName()); }
|
||||
|
||||
|
||||
File f = fileLocatorHelper.getBundleInstallLocation(bs[0]);
|
||||
if (paths.length() > 0)
|
||||
if (paths.length() > 0)
|
||||
paths.append(", ");
|
||||
System.err.println("getPathsToRequiredBundles: bundle path="+bs[0].getLocation()+" uri="+f.toURI());
|
||||
__logger.debug("getPathsToRequiredBundles: bundle path=" + bs[0].getLocation() + " uri=" + f.toURI());
|
||||
paths.append(f.toURI().toURL().toString());
|
||||
}
|
||||
|
||||
|
@ -879,13 +895,12 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
|
||||
private PackageAdmin getBundleAdmin()
|
||||
{
|
||||
Bundle bootBundle = ((BundleReference)OSGiWebappConstants.class.getClassLoader()).getBundle();
|
||||
Bundle bootBundle = ((BundleReference) OSGiWebappConstants.class.getClassLoader()).getBundle();
|
||||
ServiceTracker serviceTracker = new ServiceTracker(bootBundle.getBundleContext(), PackageAdmin.class.getName(), null);
|
||||
serviceTracker.open();
|
||||
|
||||
return (PackageAdmin) serviceTracker.getService();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ import org.osgi.framework.BundleEvent;
|
|||
import org.osgi.util.tracker.BundleTracker;
|
||||
import org.osgi.util.tracker.BundleTrackerCustomizer;
|
||||
|
||||
|
||||
/**
|
||||
* Support bundles that declare the webapp directly through headers in their
|
||||
* manifest.
|
||||
|
@ -49,133 +48,131 @@ import org.osgi.util.tracker.BundleTrackerCustomizer;
|
|||
*
|
||||
* @author hmalphettes
|
||||
*/
|
||||
public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer {
|
||||
public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WebBundleTrackerCustomizer.class);
|
||||
|
||||
|
||||
/**
|
||||
* A bundle is being added to the <code>BundleTracker</code>.
|
||||
*
|
||||
* <p>
|
||||
* This method is called before a bundle which matched the search parameters
|
||||
* of the <code>BundleTracker</code> is added to the
|
||||
* <code>BundleTracker</code>. This method should return the object to be
|
||||
* tracked for the specified <code>Bundle</code>. The returned object is
|
||||
* stored in the <code>BundleTracker</code> and is available from the
|
||||
* {@link BundleTracker#getObject(Bundle) getObject} method.
|
||||
*
|
||||
* @param bundle The <code>Bundle</code> being added to the
|
||||
* <code>BundleTracker</code>.
|
||||
* @param event The bundle event which caused this customizer method to be
|
||||
* called or <code>null</code> if there is no bundle event
|
||||
* associated with the call to this method.
|
||||
* @return The object to be tracked for the specified <code>Bundle</code>
|
||||
* object or <code>null</code> if the specified <code>Bundle</code>
|
||||
* object should not be tracked.
|
||||
*/
|
||||
public Object addingBundle(Bundle bundle, BundleEvent event)
|
||||
{
|
||||
if (bundle.getState() == Bundle.ACTIVE)
|
||||
{
|
||||
boolean isWebBundle = register(bundle);
|
||||
return isWebBundle ? bundle : null;
|
||||
}
|
||||
else if (bundle.getState() == Bundle.STOPPING)
|
||||
{
|
||||
unregister(bundle);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we should not be called in that state as
|
||||
// we are registered only for ACTIVE and STOPPING
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A bundle is being added to the <code>BundleTracker</code>.
|
||||
*
|
||||
* <p>
|
||||
* This method is called before a bundle which matched the search parameters
|
||||
* of the <code>BundleTracker</code> is added to the
|
||||
* <code>BundleTracker</code>. This method should return the object to be
|
||||
* tracked for the specified <code>Bundle</code>. The returned object is
|
||||
* stored in the <code>BundleTracker</code> and is available from the
|
||||
* {@link BundleTracker#getObject(Bundle) getObject} method.
|
||||
*
|
||||
* @param bundle The <code>Bundle</code> being added to the
|
||||
* <code>BundleTracker</code>.
|
||||
* @param event The bundle event which caused this customizer method to be
|
||||
* called or <code>null</code> if there is no bundle event associated
|
||||
* with the call to this method.
|
||||
* @return The object to be tracked for the specified <code>Bundle</code>
|
||||
* object or <code>null</code> if the specified <code>Bundle</code>
|
||||
* object should not be tracked.
|
||||
*/
|
||||
public Object addingBundle(Bundle bundle, BundleEvent event)
|
||||
{
|
||||
if (bundle.getState() == Bundle.ACTIVE)
|
||||
{
|
||||
boolean isWebBundle = register(bundle);
|
||||
return isWebBundle ? bundle : null;
|
||||
}
|
||||
else if (bundle.getState() == Bundle.STOPPING)
|
||||
{
|
||||
unregister(bundle);
|
||||
}
|
||||
else
|
||||
{
|
||||
//we should not be called in that state as
|
||||
//we are registered only for ACTIVE and STOPPING
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* A bundle tracked by the <code>BundleTracker</code> has been modified.
|
||||
*
|
||||
* <p>
|
||||
* This method is called when a bundle being tracked by the
|
||||
* <code>BundleTracker</code> has had its state modified.
|
||||
*
|
||||
* @param bundle The <code>Bundle</code> whose state has been modified.
|
||||
* @param event The bundle event which caused this customizer method to be
|
||||
* called or <code>null</code> if there is no bundle event
|
||||
* associated with the call to this method.
|
||||
* @param object The tracked object for the specified bundle.
|
||||
*/
|
||||
public void modifiedBundle(Bundle bundle, BundleEvent event, Object object)
|
||||
{
|
||||
// nothing the web-bundle was already track. something changed.
|
||||
// we only reload the webapps if the bundle is stopped and restarted.
|
||||
if (bundle.getState() == Bundle.STOPPING || bundle.getState() == Bundle.ACTIVE)
|
||||
{
|
||||
unregister(bundle);
|
||||
}
|
||||
if (bundle.getState() == Bundle.ACTIVE)
|
||||
{
|
||||
register(bundle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A bundle tracked by the <code>BundleTracker</code> has been modified.
|
||||
*
|
||||
* <p>
|
||||
* This method is called when a bundle being tracked by the
|
||||
* <code>BundleTracker</code> has had its state modified.
|
||||
*
|
||||
* @param bundle The <code>Bundle</code> whose state has been modified.
|
||||
* @param event The bundle event which caused this customizer method to be
|
||||
* called or <code>null</code> if there is no bundle event associated
|
||||
* with the call to this method.
|
||||
* @param object The tracked object for the specified bundle.
|
||||
*/
|
||||
public void modifiedBundle(Bundle bundle, BundleEvent event,
|
||||
Object object)
|
||||
{
|
||||
//nothing the web-bundle was already track. something changed.
|
||||
//we only reload the webapps if the bundle is stopped and restarted.
|
||||
// System.err.println(bundle.getSymbolicName());
|
||||
if (bundle.getState() == Bundle.STOPPING || bundle.getState() == Bundle.ACTIVE)
|
||||
{
|
||||
unregister(bundle);
|
||||
}
|
||||
if (bundle.getState() == Bundle.ACTIVE)
|
||||
{
|
||||
register(bundle);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* A bundle tracked by the <code>BundleTracker</code> has been removed.
|
||||
*
|
||||
* <p>
|
||||
* This method is called after a bundle is no longer being tracked by the
|
||||
* <code>BundleTracker</code>.
|
||||
*
|
||||
* @param bundle The <code>Bundle</code> that has been removed.
|
||||
* @param event The bundle event which caused this customizer method to be
|
||||
* called or <code>null</code> if there is no bundle event
|
||||
* associated with the call to this method.
|
||||
* @param object The tracked object for the specified bundle.
|
||||
*/
|
||||
public void removedBundle(Bundle bundle, BundleEvent event, Object object)
|
||||
{
|
||||
unregister(bundle);
|
||||
}
|
||||
|
||||
/**
|
||||
* A bundle tracked by the <code>BundleTracker</code> has been removed.
|
||||
*
|
||||
* <p>
|
||||
* This method is called after a bundle is no longer being tracked by the
|
||||
* <code>BundleTracker</code>.
|
||||
*
|
||||
* @param bundle The <code>Bundle</code> that has been removed.
|
||||
* @param event The bundle event which caused this customizer method to be
|
||||
* called or <code>null</code> if there is no bundle event associated
|
||||
* with the call to this method.
|
||||
* @param object The tracked object for the specified bundle.
|
||||
*/
|
||||
public void removedBundle(Bundle bundle, BundleEvent event,
|
||||
Object object)
|
||||
{
|
||||
unregister(bundle);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param bundle
|
||||
* @return true if this bundle in indeed a web-bundle.
|
||||
*/
|
||||
/**
|
||||
* @param bundle
|
||||
* @return true if this bundle in indeed a web-bundle.
|
||||
*/
|
||||
private boolean register(Bundle bundle)
|
||||
{
|
||||
Dictionary<?, ?> dic = bundle.getHeaders();
|
||||
String warFolderRelativePath = (String)dic.get(OSGiWebappConstants.JETTY_WAR_FOLDER_PATH);
|
||||
String warFolderRelativePath = (String) dic.get(OSGiWebappConstants.JETTY_WAR_FOLDER_PATH);
|
||||
if (warFolderRelativePath != null)
|
||||
{
|
||||
String contextPath = (String)dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
|
||||
String contextPath = getWebContextPath(bundle, dic, false);// (String)dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
|
||||
if (contextPath == null || !contextPath.startsWith("/"))
|
||||
{
|
||||
LOG.warn("The manifest header '" + OSGiWebappConstants.JETTY_WAR_FOLDER_PATH +
|
||||
": " + warFolderRelativePath + "' in the bundle " + bundle.getSymbolicName() +
|
||||
" is not valid: there is no Web-ContextPath defined in the manifest.");
|
||||
return false;
|
||||
LOG.warn("The manifest header '" + OSGiWebappConstants.JETTY_WAR_FOLDER_PATH
|
||||
+ ": "
|
||||
+ warFolderRelativePath
|
||||
+ "' in the bundle "
|
||||
+ bundle.getSymbolicName()
|
||||
+ " is not valid: there is no Web-ContextPath defined in the manifest.");
|
||||
return false;
|
||||
}
|
||||
// create the corresponding service and publish it in the context of
|
||||
// the contributor bundle.
|
||||
try
|
||||
{
|
||||
JettyBootstrapActivator.registerWebapplication(bundle,warFolderRelativePath,contextPath);
|
||||
JettyBootstrapActivator.registerWebapplication(bundle, warFolderRelativePath, contextPath);
|
||||
return true;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
LOG.warn("Starting the web-bundle " + bundle.getSymbolicName() + " threw an exception.", e);
|
||||
return true;//maybe it did not work maybe it did. safer to track this bundle.
|
||||
LOG.warn("Starting the web-bundle " + bundle.getSymbolicName() + " threw an exception.", e);
|
||||
return true;// maybe it did not work maybe it did. safer to track this bundle.
|
||||
}
|
||||
}
|
||||
else if (dic.get(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH) != null)
|
||||
{
|
||||
String contextFileRelativePath = (String)dic.get(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH);
|
||||
String contextFileRelativePath = (String) dic.get(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH);
|
||||
if (contextFileRelativePath == null)
|
||||
{
|
||||
// nothing to register here.
|
||||
|
@ -187,12 +184,11 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer {
|
|||
{
|
||||
try
|
||||
{
|
||||
JettyBootstrapActivator.registerContext(bundle,path.trim());
|
||||
JettyBootstrapActivator.registerContext(bundle, path.trim());
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -203,8 +199,8 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer {
|
|||
// (draft) of the spec: just a couple of posts on the
|
||||
// world-wide-web.
|
||||
URL rfc66Webxml = bundle.getEntry("/WEB-INF/web.xml");
|
||||
if (rfc66Webxml == null && dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH) == null)
|
||||
{
|
||||
if (rfc66Webxml == null && dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH) == null)
|
||||
{
|
||||
return false;// no webapp in here
|
||||
}
|
||||
// this is risky: should we make sure that there is no classes and
|
||||
|
@ -215,39 +211,39 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer {
|
|||
// pointing to files and folders inside WEB-INF. We should
|
||||
// filter-out
|
||||
// META-INF too
|
||||
String rfc66ContextPath = getWebContextPath(bundle,dic);
|
||||
String rfc66ContextPath = getWebContextPath(bundle, dic, rfc66Webxml == null);
|
||||
try
|
||||
{
|
||||
JettyBootstrapActivator.registerWebapplication(bundle,".",rfc66ContextPath);
|
||||
JettyBootstrapActivator.registerWebapplication(bundle, ".", rfc66ContextPath);
|
||||
return true;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
return true;//maybe it did not work maybe it did. safer to track this bundle.
|
||||
LOG.warn(e);
|
||||
return true;// maybe it did not work maybe it did. safer to track this bundle.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getWebContextPath(Bundle bundle, Dictionary<?, ?> dic)
|
||||
private String getWebContextPath(Bundle bundle, Dictionary<?, ?> dic, boolean webinfWebxmlExists)
|
||||
{
|
||||
String rfc66ContextPath = (String)dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
|
||||
String rfc66ContextPath = (String) dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
|
||||
if (rfc66ContextPath == null)
|
||||
{
|
||||
if (!webinfWebxmlExists) { return null; }
|
||||
// extract from the last token of the bundle's location:
|
||||
// (really ?
|
||||
// could consider processing the symbolic name as an alternative
|
||||
// the location will often reflect the version.
|
||||
// maybe this is relevant when the file is a war)
|
||||
String location = bundle.getLocation();
|
||||
String toks[] = location.replace('\\','/').split("/");
|
||||
String toks[] = location.replace('\\', '/').split("/");
|
||||
rfc66ContextPath = toks[toks.length - 1];
|
||||
// remove .jar, .war etc:
|
||||
int lastDot = rfc66ContextPath.lastIndexOf('.');
|
||||
if (lastDot != -1)
|
||||
{
|
||||
rfc66ContextPath = rfc66ContextPath.substring(0,lastDot);
|
||||
rfc66ContextPath = rfc66ContextPath.substring(0, lastDot);
|
||||
}
|
||||
}
|
||||
if (!rfc66ContextPath.startsWith("/"))
|
||||
|
@ -265,7 +261,4 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer {
|
|||
// webapps registered in that bundle.
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.util.zip.ZipFile;
|
|||
|
||||
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.util.resource.FileResource;
|
||||
import org.osgi.framework.Bundle;
|
||||
|
||||
|
@ -43,11 +44,13 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
// The url nuxeo and felix return is created directly from the File so it
|
||||
// should work.
|
||||
private static Field BUNDLE_ENTRY_FIELD = null;
|
||||
|
||||
private static Field FILE_FIELD = null;
|
||||
|
||||
private static Field BUNDLE_FILE_FIELD_FOR_DIR_ZIP_BUNDLE_ENTRY = null;// ZipBundleFile
|
||||
// inside
|
||||
// DirZipBundleEntry
|
||||
|
||||
// inside
|
||||
// DirZipBundleEntry
|
||||
|
||||
private static Field ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE = null;// ZipFile
|
||||
|
||||
|
@ -56,8 +59,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
* spirit of OSGi but quite necessary to support self-contained webapps and
|
||||
* other situations.
|
||||
*
|
||||
* @param bundle
|
||||
* The bundle
|
||||
* @param bundle The bundle
|
||||
* @return Its installation location as a file.
|
||||
* @throws Exception
|
||||
*/
|
||||
|
@ -67,11 +69,12 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
// grab the MANIFEST.MF's url
|
||||
// and then do what it takes.
|
||||
URL url = bundle.getEntry("/META-INF/MANIFEST.MF");
|
||||
// System.err.println(url.toString() + " " + url.toURI() + " " + url.getProtocol());
|
||||
|
||||
if (url.getProtocol().equals("file"))
|
||||
{
|
||||
// some osgi frameworks do use the file protocole directly in some
|
||||
// situations. Do use the FileResource to transform the URL into a File: URL#toURI is broken
|
||||
// situations. Do use the FileResource to transform the URL into a
|
||||
// File: URL#toURI is broken
|
||||
return new FileResource(url).getFile().getParentFile().getParentFile();
|
||||
}
|
||||
else if (url.getProtocol().equals("bundleentry"))
|
||||
|
@ -79,7 +82,10 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
// say hello to equinox who has its own protocol.
|
||||
// we use introspection like there is no tomorrow to get access to
|
||||
// the File
|
||||
|
||||
URLConnection con = url.openConnection();
|
||||
con.setUseCaches(Resource.getDefaultUseCaches()); //work around problems where url connections cache references to jars
|
||||
|
||||
if (BUNDLE_ENTRY_FIELD == null)
|
||||
{
|
||||
BUNDLE_ENTRY_FIELD = con.getClass().getDeclaredField("bundleEntry");
|
||||
|
@ -93,13 +99,16 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
FILE_FIELD = bundleEntry.getClass().getDeclaredField("file");
|
||||
FILE_FIELD.setAccessible(true);
|
||||
}
|
||||
File f = (File)FILE_FIELD.get(bundleEntry);
|
||||
File f = (File) FILE_FIELD.get(bundleEntry);
|
||||
return f.getParentFile().getParentFile();
|
||||
}
|
||||
else if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.ZipBundleEntry"))
|
||||
{
|
||||
url = bundle.getEntry("/");
|
||||
|
||||
con = url.openConnection();
|
||||
con.setDefaultUseCaches(Resource.getDefaultUseCaches());
|
||||
|
||||
if (BUNDLE_ENTRY_FIELD == null)
|
||||
{// this one will be a DirZipBundleEntry
|
||||
BUNDLE_ENTRY_FIELD = con.getClass().getDeclaredField("bundleEntry");
|
||||
|
@ -117,7 +126,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE = zipBundleFile.getClass().getDeclaredField("zipFile");
|
||||
ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE.setAccessible(true);
|
||||
}
|
||||
ZipFile zipFile = (ZipFile)ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE.get(zipBundleFile);
|
||||
ZipFile zipFile = (ZipFile) ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE.get(zipBundleFile);
|
||||
return new File(zipFile.getName());
|
||||
}
|
||||
else if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.DirZipBundleEntry"))
|
||||
|
@ -130,7 +139,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
{
|
||||
// observed this on felix-2.0.0
|
||||
String location = bundle.getLocation();
|
||||
// System.err.println("location " + location);
|
||||
// System.err.println("location " + location);
|
||||
if (location.startsWith("file:/"))
|
||||
{
|
||||
URI uri = new URI(URIUtil.encodePath(location));
|
||||
|
@ -138,27 +147,32 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
}
|
||||
else if (location.startsWith("file:"))
|
||||
{
|
||||
//location defined in the BundleArchive m_bundleArchive
|
||||
//it is relative to relative to the BundleArchive's m_archiveRootDir
|
||||
File res = new File(location.substring("file:".length()));
|
||||
if (!res.exists())
|
||||
{
|
||||
return null;
|
||||
// Object bundleArchive = getFelixBundleArchive(bundle);
|
||||
// File archiveRoot = getFelixBundleArchiveRootDir(bundleArchive);
|
||||
// String currentLocation = getFelixBundleArchiveCurrentLocation(bundleArchive);
|
||||
// System.err.println("Got the archive root " + archiveRoot.getAbsolutePath()
|
||||
// + " current location " + currentLocation + " is directory ?");
|
||||
// res = new File(archiveRoot, currentLocation != null
|
||||
// ? currentLocation : location.substring("file:".length()));
|
||||
}
|
||||
return res;
|
||||
// location defined in the BundleArchive m_bundleArchive
|
||||
// it is relative to relative to the BundleArchive's
|
||||
// m_archiveRootDir
|
||||
File res = new File(location.substring("file:".length()));
|
||||
if (!res.exists())
|
||||
{
|
||||
return null;
|
||||
// Object bundleArchive = getFelixBundleArchive(bundle);
|
||||
// File archiveRoot =
|
||||
// getFelixBundleArchiveRootDir(bundleArchive);
|
||||
// String currentLocation =
|
||||
// getFelixBundleArchiveCurrentLocation(bundleArchive);
|
||||
// System.err.println("Got the archive root " +
|
||||
// archiveRoot.getAbsolutePath()
|
||||
// + " current location " + currentLocation +
|
||||
// " is directory ?");
|
||||
// res = new File(archiveRoot, currentLocation != null
|
||||
// ? currentLocation : location.substring("file:".length()));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
else if (location.startsWith("reference:file:"))
|
||||
{
|
||||
location = URLDecoder.decode(location.substring("reference:".length()), "UTF-8");
|
||||
File file = new File(location.substring("file:".length()));
|
||||
return file;
|
||||
location = URLDecoder.decode(location.substring("reference:".length()), "UTF-8");
|
||||
File file = new File(location.substring("file:".length()));
|
||||
return file;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -179,37 +193,40 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
path = path.substring(1);
|
||||
}
|
||||
File bundleInstall = getBundleInstallLocation(bundle);
|
||||
File webapp = path != null && path.length() != 0?new File(bundleInstall,path):bundleInstall;
|
||||
if (!webapp.exists())
|
||||
{
|
||||
throw new IllegalArgumentException("Unable to locate " + path + " inside " + bundle.getSymbolicName() + " ("
|
||||
+ (bundleInstall != null?bundleInstall.getAbsolutePath():" no_bundle_location ") + ")");
|
||||
File webapp = path != null && path.length() != 0 ? new File(bundleInstall, path) : bundleInstall;
|
||||
if (!webapp.exists())
|
||||
{
|
||||
throw new IllegalArgumentException("Unable to locate " + path
|
||||
+ " inside "
|
||||
+ bundle.getSymbolicName()
|
||||
+ " ("
|
||||
+ (bundleInstall != null ? bundleInstall.getAbsolutePath() : " no_bundle_location ")
|
||||
+ ")");
|
||||
}
|
||||
return webapp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper method equivalent to Bundle#getEntry(String entryPath) except that
|
||||
* it searches for entries in the fragments by using the Bundle#findEntries method.
|
||||
*
|
||||
* @param bundle
|
||||
* @param entryPath
|
||||
* @return null or all the entries found for that path.
|
||||
*/
|
||||
public Enumeration<URL> findEntries(Bundle bundle, String entryPath)
|
||||
{
|
||||
int last = entryPath.lastIndexOf('/');
|
||||
String path = last != -1 && last < entryPath.length() -2
|
||||
? entryPath.substring(0, last) : "/";
|
||||
if (!path.startsWith("/"))
|
||||
{
|
||||
path = "/" + path;
|
||||
}
|
||||
String pattern = last != -1 && last < entryPath.length() -2
|
||||
? entryPath.substring(last+1) : entryPath;
|
||||
Enumeration<URL> enUrls = bundle.findEntries(path, pattern, false);
|
||||
return enUrls;
|
||||
}
|
||||
* Helper method equivalent to Bundle#getEntry(String entryPath) except that
|
||||
* it searches for entries in the fragments by using the Bundle#findEntries
|
||||
* method.
|
||||
*
|
||||
* @param bundle
|
||||
* @param entryPath
|
||||
* @return null or all the entries found for that path.
|
||||
*/
|
||||
public Enumeration<URL> findEntries(Bundle bundle, String entryPath)
|
||||
{
|
||||
int last = entryPath.lastIndexOf('/');
|
||||
String path = last != -1 && last < entryPath.length() - 2 ? entryPath.substring(0, last) : "/";
|
||||
if (!path.startsWith("/"))
|
||||
{
|
||||
path = "/" + path;
|
||||
}
|
||||
String pattern = last != -1 && last < entryPath.length() - 2 ? entryPath.substring(last + 1) : entryPath;
|
||||
Enumeration<URL> enUrls = bundle.findEntries(path, pattern, false);
|
||||
return enUrls;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the bundle is a jar, returns the jar. If the bundle is a folder, look
|
||||
|
@ -256,76 +273,84 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
|
|||
return new File[] { jasperLocation };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//introspection on equinox to invoke the getLocalURL method on BundleURLConnection
|
||||
//equivalent to using the FileLocator without depending on an equinox class.
|
||||
private static Method BUNDLE_URL_CONNECTION_getLocalURL = null;
|
||||
private static Method BUNDLE_URL_CONNECTION_getFileURL = null;
|
||||
/**
|
||||
* Only useful for equinox: on felix we get the file:// or jar:// url already.
|
||||
* Other OSGi implementations have not been tested
|
||||
* <p>
|
||||
* Get a URL to the bundle entry that uses a common protocol (i.e. file:
|
||||
* jar: or http: etc.).
|
||||
* </p>
|
||||
* @return a URL to the bundle entry that uses a common protocol
|
||||
*/
|
||||
public static URL getLocalURL(URL url) {
|
||||
if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol())) {
|
||||
try {
|
||||
URLConnection conn = url.openConnection();
|
||||
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();
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
/**
|
||||
* Only useful for equinox: on felix we get the file:// url already.
|
||||
* Other OSGi implementations have not been tested
|
||||
* <p>
|
||||
* Get a URL to the content of the bundle entry that uses the file: protocol.
|
||||
* The content of the bundle entry may be downloaded or extracted to the local
|
||||
* file system in order to create a file: URL.
|
||||
* @return a URL to the content of the bundle entry that uses the file: protocol
|
||||
* </p>
|
||||
*/
|
||||
public static URL getFileURL(URL url)
|
||||
{
|
||||
if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol()))
|
||||
{
|
||||
try
|
||||
{
|
||||
URLConnection conn = url.openConnection();
|
||||
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();
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
// introspection on equinox to invoke the getLocalURL method on
|
||||
// BundleURLConnection
|
||||
// equivalent to using the FileLocator without depending on an equinox
|
||||
// class.
|
||||
private static Method BUNDLE_URL_CONNECTION_getLocalURL = null;
|
||||
|
||||
private static Method BUNDLE_URL_CONNECTION_getFileURL = null;
|
||||
|
||||
/**
|
||||
* Only useful for equinox: on felix we get the file:// or jar:// url
|
||||
* already. Other OSGi implementations have not been tested
|
||||
* <p>
|
||||
* Get a URL to the bundle entry that uses a common protocol (i.e. file:
|
||||
* jar: or http: etc.).
|
||||
* </p>
|
||||
*
|
||||
* @return a URL to the bundle entry that uses a common protocol
|
||||
*/
|
||||
public static URL getLocalURL(URL url)
|
||||
{
|
||||
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"))
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only useful for equinox: on felix we get the file:// url already. Other
|
||||
* OSGi implementations have not been tested
|
||||
* <p>
|
||||
* Get a URL to the content of the bundle entry that uses the file:
|
||||
* protocol. The content of the bundle entry may be downloaded or extracted
|
||||
* to the local file system in order to create a file: URL.
|
||||
*
|
||||
* @return a URL to the content of the bundle entry that uses the file:
|
||||
* protocol
|
||||
* </p>
|
||||
*/
|
||||
public static URL getFileURL(URL url)
|
||||
{
|
||||
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"))
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,20 +3,20 @@ Bundle-ManifestVersion: 2
|
|||
Bundle-Name: Console
|
||||
Bundle-SymbolicName: org.eclipse.jetty.osgi.equinoxtools
|
||||
Bundle-Description: Example application: equinox console accesssible on the web
|
||||
Bundle-Version: 8.1.2.qualifier
|
||||
Bundle-Version: 8.1.3.qualifier
|
||||
Bundle-Activator: org.eclipse.jetty.osgi.equinoxtools.WebEquinoxToolsActivator
|
||||
Import-Package: javax.servlet;version="2.5.0",
|
||||
javax.servlet.http;version="2.5.0",
|
||||
org.eclipse.jetty.continuation;version="8.1.2",
|
||||
org.eclipse.jetty.io;version="8.1.2",
|
||||
org.eclipse.jetty.util;version="8.1.2",
|
||||
org.eclipse.jetty.util.log;version="8.1.2",
|
||||
org.eclipse.jetty.websocket;version="8.1.2",
|
||||
org.eclipse.jetty.continuation;version="8.1.3",
|
||||
org.eclipse.jetty.io;version="8.1.3",
|
||||
org.eclipse.jetty.util;version="8.1.3",
|
||||
org.eclipse.jetty.util.log;version="8.1.3",
|
||||
org.eclipse.jetty.websocket;version="8.1.3",
|
||||
org.eclipse.osgi.framework.console;version="1.1.0",
|
||||
org.osgi.framework;version="1.3.0",
|
||||
org.osgi.service.http;version="1.2.0",
|
||||
org.osgi.util.tracker;version="1.3.0"
|
||||
Export-Package: org.eclipse.jetty.osgi.equinoxtools;x-internal:=true;version="8.1.2",
|
||||
org.eclipse.jetty.osgi.equinoxtools.console;x-internal:=true;version="8.1.2"
|
||||
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
||||
Export-Package: org.eclipse.jetty.osgi.equinoxtools;x-internal:=true;version="8.1.3",
|
||||
org.eclipse.jetty.osgi.equinoxtools.console;x-internal:=true;version="8.1.3"
|
||||
Bundle-RequiredExecutionEnvironment: J2SE-1.6
|
||||
|
||||
|
|
|
@ -2,15 +2,16 @@ Manifest-Version: 1.0
|
|||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: OSGi HttpService provided by equinox HttpServiceServlet deployed on jetty
|
||||
Bundle-SymbolicName: org.eclipse.jetty.osgi.httpservice
|
||||
Bundle-Version: 8.1.2.qualifier
|
||||
Bundle-Version: 8.1.3.qualifier
|
||||
Bundle-Vendor: Mort Bay Consulting
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Jetty-ContextFilePath: contexts/httpservice.xml
|
||||
Import-Package: javax.servlet;version="2.6.0",
|
||||
javax.servlet.http;version="2.6.0",
|
||||
org.eclipse.equinox.http.servlet,
|
||||
org.eclipse.jetty.server;version="8.1.2",
|
||||
org.eclipse.jetty.server.handler;version="8.1.2",
|
||||
org.eclipse.jetty.servlet;version="8.1.2",
|
||||
org.eclipse.jetty.util.component;version="8.1.2"
|
||||
Export-Package: org.eclipse.jetty.osgi.httpservice;version="8.1.2"
|
||||
org.eclipse.jetty.server;version="8.1.3",
|
||||
org.eclipse.jetty.server.handler;version="8.1.3",
|
||||
org.eclipse.jetty.servlet;version="8.1.3",
|
||||
org.eclipse.jetty.util.component;version="8.1.3"
|
||||
Export-Package: org.eclipse.jetty.osgi.httpservice;version="8.1.3"
|
||||
|
||||
|
|
|
@ -1,149 +0,0 @@
|
|||
package org.eclipse.jetty.rewrite.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler.Context;
|
||||
import org.eclipse.jetty.server.handler.ScopedHandler;
|
||||
import org.eclipse.jetty.util.component.AggregateLifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** A handle that uses regular expressions to select the target.
|
||||
* <p>
|
||||
* This handler applies a list of regex to target name mappings to the URIs of requests.
|
||||
* If the regex matches the URI, then the mapped target name is used in the nested
|
||||
* call to {@link #doScope(String, Request, HttpServletRequest, HttpServletResponse)}.
|
||||
* <p>
|
||||
* This handler should be installed as the first handler in a Context. It can be configured
|
||||
* either with direct calls to {@link #addPatternTarget(String, String)} or by setting
|
||||
* the context init parameters "org.eclipse.jetty.rewrite.handler.REGEX_MAPPINGS" to a comma
|
||||
* separated list of strings in the format regex==target.
|
||||
*/
|
||||
public class RegexTargetHandler extends ScopedHandler
|
||||
{
|
||||
private final static Logger LOG = Log.getLogger(RegexTargetHandler.class);
|
||||
public final static String REGEX_MAPPINGS="org.eclipse.jetty.rewrite.handler.REGEX_MAPPINGS";
|
||||
static class RegexMapping
|
||||
{
|
||||
RegexMapping(String regex,String target)
|
||||
{
|
||||
_pattern=Pattern.compile(regex);
|
||||
_target=target;
|
||||
}
|
||||
final Pattern _pattern;
|
||||
final String _target;
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return _pattern+"=="+_target;
|
||||
}
|
||||
}
|
||||
|
||||
final private List<RegexTargetHandler.RegexMapping> _patterns = new CopyOnWriteArrayList<RegexTargetHandler.RegexMapping>();
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Add a pattern to target mapping.
|
||||
* @param pattern The regular expression pattern to match.
|
||||
* @param target The target (normally servlet name) to handle the request
|
||||
*/
|
||||
public void addPatternTarget(String pattern,String target)
|
||||
{
|
||||
_patterns.add(new RegexMapping(pattern,target));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
{
|
||||
super.doStart();
|
||||
|
||||
Context context = ContextHandler.getCurrentContext();
|
||||
if (context!=null)
|
||||
{
|
||||
String config=context.getInitParameter(REGEX_MAPPINGS);
|
||||
LOG.debug("{}={}",REGEX_MAPPINGS,config);
|
||||
String[] mappings=config.split("\\s*,\\s*");
|
||||
for (String mapping : mappings)
|
||||
{
|
||||
mapping=mapping.trim();
|
||||
String[] parts=mapping.split("\\s*==\\s*");
|
||||
if (parts.length==2)
|
||||
{
|
||||
String pattern=parts[0];
|
||||
String target=parts[1];
|
||||
addPatternTarget(pattern,target);
|
||||
}
|
||||
else
|
||||
LOG.warn("Bad regex mapping: "+mapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
for (RegexTargetHandler.RegexMapping rm : _patterns)
|
||||
{
|
||||
Matcher m=rm._pattern.matcher(target);
|
||||
if (m.matches())
|
||||
{
|
||||
String new_target = rm._target;
|
||||
final String sp;
|
||||
final String pi;
|
||||
|
||||
if (m.groupCount()==1&&target.endsWith(m.group(1)))
|
||||
{
|
||||
pi=m.group(1);
|
||||
sp=target.substring(0,target.length()-pi.length());
|
||||
}
|
||||
else
|
||||
{
|
||||
sp=target;
|
||||
pi=null;
|
||||
}
|
||||
baseRequest.setServletPath(sp);
|
||||
baseRequest.setPathInfo(pi);
|
||||
baseRequest.setAttribute("org.eclipse.jetty.servlet.REGEX_PATH",target);
|
||||
super.nextScope(new_target,baseRequest,request,response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.nextScope(target,baseRequest,request,response);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
String path=(String)baseRequest.getAttribute("org.eclipse.jetty.servlet.REGEX_PATH");
|
||||
if (path==null)
|
||||
path=target;
|
||||
else
|
||||
baseRequest.setAttribute("org.eclipse.jetty.servlet.REGEX_PATH",null);
|
||||
|
||||
super.nextHandle(path,baseRequest,request,response);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void dump(Appendable out, String indent) throws IOException
|
||||
{
|
||||
AggregateLifeCycle.dumpObject(out,this);
|
||||
AggregateLifeCycle.dump(out,indent,_patterns,Collections.singletonList(getHandler()));
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -18,18 +18,22 @@ import java.util.regex.Matcher;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
|
||||
/**
|
||||
* Rewrite the URI by matching with a regular expression.
|
||||
* The replacement string may use $n" to replace the nth capture group.
|
||||
* If the replacement string contains ? character, then it is split into a path
|
||||
* and query string component. The returned target contains only the path.
|
||||
* and query string component. The replacement query string may also contain $Q, which
|
||||
* is replaced with the original query string.
|
||||
* The returned target contains only the path.
|
||||
*/
|
||||
public class RewriteRegexRule extends RegexRule implements Rule.ApplyURI
|
||||
{
|
||||
private String _replacement;
|
||||
private String _query;
|
||||
private boolean _queryGroup;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public RewriteRegexRule()
|
||||
|
@ -49,6 +53,7 @@ public class RewriteRegexRule extends RegexRule implements Rule.ApplyURI
|
|||
String[] split=replacement.split("\\?",2);
|
||||
_replacement = split[0];
|
||||
_query=split.length==2?split[1]:null;
|
||||
_queryGroup=_query!=null && _query.contains("$Q");
|
||||
}
|
||||
|
||||
|
||||
|
@ -73,21 +78,32 @@ public class RewriteRegexRule extends RegexRule implements Rule.ApplyURI
|
|||
}
|
||||
|
||||
if (query!=null)
|
||||
{
|
||||
if (_queryGroup)
|
||||
query=query.replace("$Q",request.getQueryString()==null?"":request.getQueryString());
|
||||
request.setAttribute("org.eclipse.jetty.rewrite.handler.RewriteRegexRule.Q",query);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void applyURI(Request request, String oldTarget, String newTarget) throws IOException
|
||||
{
|
||||
request.setRequestURI(newTarget);
|
||||
if (_query!=null)
|
||||
if (_query==null)
|
||||
{
|
||||
request.setRequestURI(newTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
String query=(String)request.getAttribute("org.eclipse.jetty.rewrite.handler.RewriteRegexRule.Q");
|
||||
if (request.getQueryString()==null)
|
||||
request.setQueryString(query);
|
||||
else
|
||||
request.setQueryString(request.getQueryString()+"&"+query);
|
||||
|
||||
if (!_queryGroup && request.getQueryString()!=null)
|
||||
query=request.getQueryString()+"&"+query;
|
||||
HttpURI uri=new HttpURI(newTarget+"?"+query);
|
||||
request.setUri(uri);
|
||||
request.setRequestURI(newTarget);
|
||||
request.setQueryString(query);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -197,28 +197,25 @@ public class RuleContainer extends Rule
|
|||
if (applied!=null)
|
||||
{
|
||||
LOG.debug("applied {}",rule);
|
||||
if (!target.equals(applied))
|
||||
{
|
||||
LOG.debug("rewrote {} to {}",target,applied);
|
||||
if (!original_set)
|
||||
{
|
||||
original_set=true;
|
||||
request.setAttribute(_originalPathAttribute, target);
|
||||
}
|
||||
LOG.debug("rewrote {} to {}",target,applied);
|
||||
if (!original_set)
|
||||
{
|
||||
original_set=true;
|
||||
request.setAttribute(_originalPathAttribute, target);
|
||||
}
|
||||
|
||||
if (_rewriteRequestURI)
|
||||
{
|
||||
if (rule instanceof Rule.ApplyURI && !target.equals(request.getRequestURI()))
|
||||
((Rule.ApplyURI)rule).applyURI((Request)request, target, applied);
|
||||
else
|
||||
((Request)request).setRequestURI(applied);
|
||||
}
|
||||
|
||||
if (_rewritePathInfo)
|
||||
((Request)request).setPathInfo(applied);
|
||||
|
||||
target=applied;
|
||||
if (_rewriteRequestURI)
|
||||
{
|
||||
if (rule instanceof Rule.ApplyURI)
|
||||
((Rule.ApplyURI)rule).applyURI((Request)request, target, applied);
|
||||
else
|
||||
((Request)request).setRequestURI(applied);
|
||||
}
|
||||
|
||||
if (_rewritePathInfo)
|
||||
((Request)request).setPathInfo(applied);
|
||||
|
||||
target=applied;
|
||||
|
||||
if (rule.isHandling())
|
||||
{
|
||||
|
|
|
@ -1,214 +0,0 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2009 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.rewrite.handler;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.Socket;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequestWrapper;
|
||||
import javax.servlet.ServletResponseWrapper;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.jetty.rewrite.handler.RegexTargetHandler;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class RegexTargetHandlerTest
|
||||
{
|
||||
private static Server __server = new Server(0);
|
||||
private static int __port;
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws Exception
|
||||
{
|
||||
|
||||
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
context.setContextPath("/");
|
||||
__server.setHandler(context);
|
||||
|
||||
// Serve some hello world servlets
|
||||
context.addServlet(DispatchServletServlet.class,"/dispatch/*");
|
||||
context.addServlet(new ServletHolder("HelloAll",new HelloServlet("Hello World")),"/*");
|
||||
context.addServlet(new ServletHolder("Italian",new HelloServlet("Buongiorno Mondo")),"/it/*");
|
||||
context.addServlet(new ServletHolder("French", new HelloServlet("Bonjour le Monde")),"/fr/*");
|
||||
|
||||
RegexTargetHandler regexHandler=new RegexTargetHandler();
|
||||
regexHandler.setHandler(context.getHandler());
|
||||
context.setHandler(regexHandler);
|
||||
|
||||
context.getInitParams().put(RegexTargetHandler.REGEX_MAPPINGS,
|
||||
" .*\\.fr==French, \n"+
|
||||
"/ciao(/.*)$==Italian");
|
||||
|
||||
__server.start();
|
||||
|
||||
__port=__server.getConnectors()[0].getLocalPort();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void shutdown() throws Exception
|
||||
{
|
||||
__server.stop();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNormal() throws Exception
|
||||
{
|
||||
String[] response=getResponse("/normal");
|
||||
assertEquals("HTTP/1.1 200 OK",response[0]);
|
||||
assertEquals("Hello World",response[1]);
|
||||
assertEquals("",response[2]);
|
||||
assertEquals("/normal",response[3]);
|
||||
|
||||
response=getResponse("/it/info");
|
||||
assertEquals("HTTP/1.1 200 OK",response[0]);
|
||||
assertEquals("Buongiorno Mondo",response[1]);
|
||||
assertEquals("/it",response[2]);
|
||||
assertEquals("/info",response[3]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFullMatch() throws Exception
|
||||
{
|
||||
String[] response=getResponse("/some/thing.fr");
|
||||
assertEquals("HTTP/1.1 200 OK",response[0]);
|
||||
assertEquals("Bonjour le Monde",response[1]);
|
||||
assertEquals("/some/thing.fr",response[2]);
|
||||
assertEquals("null",response[3]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCaptureMatch() throws Exception
|
||||
{
|
||||
String[] response=getResponse("/ciao/info");
|
||||
assertEquals("HTTP/1.1 200 OK",response[0]);
|
||||
assertEquals("Buongiorno Mondo",response[1]);
|
||||
assertEquals("/ciao",response[2]);
|
||||
assertEquals("/info",response[3]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDispatchFullMatch() throws Exception
|
||||
{
|
||||
String[] response=getResponse("/dispatch/xxx?forward=/some/thing.fr");
|
||||
assertEquals("HTTP/1.1 200 OK",response[0]);
|
||||
assertEquals("Bonjour le Monde",response[1]);
|
||||
assertEquals("/some/thing.fr",response[2]);
|
||||
assertEquals("null",response[3]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDispatchCaptureMatch() throws Exception
|
||||
{
|
||||
String[] response=getResponse("/dispatch/xxx?forward=/ciao/info");
|
||||
assertEquals("HTTP/1.1 200 OK",response[0]);
|
||||
assertEquals("Buongiorno Mondo",response[1]);
|
||||
assertEquals("/ciao",response[2]);
|
||||
assertEquals("/info",response[3]);
|
||||
}
|
||||
|
||||
|
||||
private String[] getResponse(String uri) throws Exception
|
||||
{
|
||||
Socket socket = new Socket("127.0.0.1",__port);
|
||||
|
||||
PrintWriter out = new PrintWriter(socket.getOutputStream());
|
||||
out.print("GET "+uri+" HTTP/1.0\r\n\r\n");
|
||||
out.flush();
|
||||
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
|
||||
String[] response=new String[4];
|
||||
response[0]=in.readLine();
|
||||
//System.err.println(response[0]);
|
||||
|
||||
String line=in.readLine();
|
||||
while(line.length()>0)
|
||||
line=in.readLine();
|
||||
|
||||
response[1]=in.readLine();
|
||||
//System.err.println(response[1]);
|
||||
response[2]=in.readLine();
|
||||
//System.err.println(response[2]);
|
||||
response[3]=in.readLine();
|
||||
//System.err.println(response[3]);
|
||||
|
||||
socket.close();
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
public static class HelloServlet extends HttpServlet implements Servlet
|
||||
{
|
||||
final String _hello;
|
||||
|
||||
public HelloServlet(String hello)
|
||||
{
|
||||
_hello=hello;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
response.setStatus(200);
|
||||
response.getWriter().println(_hello);
|
||||
response.getWriter().println(request.getServletPath());
|
||||
response.getWriter().println(request.getPathInfo());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class DispatchServletServlet extends HttpServlet implements Servlet
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
RequestDispatcher dispatcher = null;
|
||||
|
||||
if(request.getParameter("include")!=null)
|
||||
{
|
||||
dispatcher = getServletContext().getRequestDispatcher(request.getParameter("include"));
|
||||
dispatcher.include(new HttpServletRequestWrapper(request), new HttpServletResponseWrapper(response));
|
||||
}
|
||||
else if(request.getParameter("forward")!=null)
|
||||
{
|
||||
dispatcher = getServletContext().getRequestDispatcher(request.getParameter("forward"));
|
||||
dispatcher.forward(new HttpServletRequestWrapper(request), new HttpServletResponseWrapper(response));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,6 +14,10 @@ package org.eclipse.jetty.rewrite.handler;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.UrlEncoded;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -23,13 +27,21 @@ public class RewriteRegexRuleTest extends AbstractRuleTestCase
|
|||
{
|
||||
private String[][] _tests=
|
||||
{
|
||||
{"/foo/bar",".*","/replace","/replace",null},
|
||||
{"/foo/bar","/xxx.*","/replace",null,null},
|
||||
{"/foo/bar","/(.*)/(.*)","/$2/$1/xxx","/bar/foo/xxx",null},
|
||||
{"/foo/bar","/(foo)/(.*)(bar)","/$3/$1/xxx$2","/bar/foo/xxx",null},
|
||||
{"/foo/$bar",".*","/$replace","/$replace",null},
|
||||
{"/foo/$bar","/foo/(.*)","/$1/replace","/$bar/replace",null},
|
||||
{"/foo/bar/info","/foo/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2","/info/other","p1=bar"},
|
||||
{"/foo0/bar",null,".*","/replace","/replace",null},
|
||||
{"/foo1/bar","n=v",".*","/replace","/replace","n=v"},
|
||||
{"/foo2/bar",null,"/xxx.*","/replace",null,null},
|
||||
{"/foo3/bar",null,"/(.*)/(.*)","/$2/$1/xxx","/bar/foo3/xxx",null},
|
||||
{"/foo4/bar",null,"/(.*)/(.*)","/test?p2=$2&p1=$1","/test","p2=bar&p1=foo4"},
|
||||
{"/foo5/bar","n=v","/(.*)/(.*)","/test?p2=$2&p1=$1","/test","n=v&p2=bar&p1=foo5"},
|
||||
{"/foo6/bar",null,"/(.*)/(.*)","/foo6/bar?p2=$2&p1=$1","/foo6/bar","p2=bar&p1=foo6"},
|
||||
{"/foo7/bar","n=v","/(.*)/(.*)","/foo7/bar?p2=$2&p1=$1","/foo7/bar","n=v&p2=bar&p1=foo7"},
|
||||
{"/foo8/bar",null,"/(foo8)/(.*)(bar)","/$3/$1/xxx$2","/bar/foo8/xxx",null},
|
||||
{"/foo9/$bar",null,".*","/$replace","/$replace",null},
|
||||
{"/fooA/$bar",null,"/fooA/(.*)","/$1/replace","/$bar/replace",null},
|
||||
{"/fooB/bar/info",null,"/fooB/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2","/info/other","p1=bar"},
|
||||
{"/fooC/bar/info",null,"/fooC/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2&$Q","/info/other","p1=bar&"},
|
||||
{"/fooD/bar/info","n=v","/fooD/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2&$Q","/info/other","p1=bar&n=v"},
|
||||
{"/fooE/bar/info","n=v","/fooE/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2","/info/other","n=v&p1=bar"},
|
||||
};
|
||||
private RewriteRegexRule _rule;
|
||||
|
||||
|
@ -45,17 +57,59 @@ public class RewriteRegexRuleTest extends AbstractRuleTestCase
|
|||
{
|
||||
for (String[] test : _tests)
|
||||
{
|
||||
_rule.setRegex(test[1]);
|
||||
_rule.setReplacement(test[2]);
|
||||
String result = _rule.matchAndApply(test[0], _request, _response);
|
||||
assertEquals(test[1], test[3], result);
|
||||
reset();
|
||||
_request.setRequestURI(null);
|
||||
|
||||
_request.setRequestURI(test[0]);
|
||||
_request.setQueryString(null);
|
||||
String t=test[0]+"?"+test[1]+">"+test[2]+"|"+test[3];
|
||||
_rule.setRegex(test[2]);
|
||||
_rule.setReplacement(test[3]);
|
||||
|
||||
_request.setUri(new HttpURI(test[0]+(test[1]==null?"":("?"+test[1]))));
|
||||
_request.getRequestURI();
|
||||
|
||||
|
||||
String result = _rule.matchAndApply(test[0], _request, _response);
|
||||
assertEquals(t, test[4], result);
|
||||
_rule.applyURI(_request,test[0],result);
|
||||
|
||||
assertEquals(test[3], _request.getRequestURI());
|
||||
assertEquals(test[4], _request.getQueryString());
|
||||
if (result!=null)
|
||||
{
|
||||
assertEquals(t,test[4], _request.getRequestURI());
|
||||
assertEquals(t,test[5], _request.getQueryString());
|
||||
}
|
||||
|
||||
if (test[5]!=null)
|
||||
{
|
||||
MultiMap<String> params=new MultiMap<String>();
|
||||
UrlEncoded.decodeTo(test[5],params,StringUtil.__UTF8);
|
||||
|
||||
for (String n:params.keySet())
|
||||
assertEquals(params.getString(n),_request.getParameter(n));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainedRequestUriEnabled() throws IOException
|
||||
{
|
||||
RuleContainer container = new RuleContainer();
|
||||
container.setRewriteRequestURI(true);
|
||||
container.addRule(_rule);
|
||||
for (String[] test : _tests)
|
||||
{
|
||||
reset();
|
||||
String t=test[0]+"?"+test[1]+">"+test[2]+"|"+test[3];
|
||||
_rule.setRegex(test[2]);
|
||||
_rule.setReplacement(test[3]);
|
||||
|
||||
_request.setRequestURI(test[0]);
|
||||
_request.setQueryString(test[1]);
|
||||
_request.getAttributes().clearAttributes();
|
||||
|
||||
String result = container.apply(test[0],_request,_response);
|
||||
assertEquals(t,test[4]==null?test[0]:test[4], result);
|
||||
assertEquals(t,test[4]==null?test[0]:test[4], _request.getRequestURI());
|
||||
assertEquals(t,test[5], _request.getQueryString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ The easiest place to put these lines are in the start.ini file.
|
|||
For debugging the spengo authentication the following options are helpful:
|
||||
|
||||
-Dorg.eclipse.jetty.LEVEL=debug
|
||||
-Dsun.security.spnego.debug=all
|
||||
-Dsun.security.spnego.debug=true
|
||||
|
||||
|
||||
Spengo Authentication is enabled in the webapp with the following setup.
|
||||
|
@ -59,7 +59,4 @@ embedded, via the jetty.xml or in a context file for the webapp.
|
|||
</New>
|
||||
</Set>
|
||||
<Set name="checkWelcomeFiles">true</Set>
|
||||
</Get>
|
||||
|
||||
|
||||
8
|
||||
</Get>
|
|
@ -254,7 +254,7 @@ public class DigestAuthenticator extends LoginAuthenticator
|
|||
Nonce nonce=_nonceQueue.peek();
|
||||
while (nonce!=null && nonce._ts<expired)
|
||||
{
|
||||
_nonceQueue.remove();
|
||||
_nonceQueue.remove(nonce);
|
||||
_nonceCount.remove(nonce._nonce);
|
||||
nonce=_nonceQueue.peek();
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
|
|||
HttpBuffers ab = (HttpBuffers)_connector;
|
||||
_parser = newHttpParser(ab.getRequestBuffers(), endpoint, new RequestHandler());
|
||||
_requestFields = new HttpFields();
|
||||
_responseFields = new HttpFields(server.getMaxCookieVersion());
|
||||
_responseFields = new HttpFields();
|
||||
_request = new Request(this);
|
||||
_response = new Response(this);
|
||||
_generator = newHttpGenerator(ab.getResponseBuffers(), endpoint);
|
||||
|
@ -165,7 +165,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
|
|||
_connector = connector;
|
||||
_parser = parser;
|
||||
_requestFields = new HttpFields();
|
||||
_responseFields = new HttpFields(server.getMaxCookieVersion());
|
||||
_responseFields = new HttpFields();
|
||||
_request = request;
|
||||
_response = new Response(this);
|
||||
_generator = generator;
|
||||
|
|
|
@ -938,6 +938,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
|
|||
{
|
||||
synchronized (this)
|
||||
{
|
||||
_responseWrapped=!(response instanceof Response);
|
||||
doSuspend(context,request,response);
|
||||
if (request instanceof HttpServletRequest)
|
||||
{
|
||||
|
|
|
@ -193,7 +193,7 @@ public class CookieCutter
|
|||
continue;
|
||||
|
||||
case ';':
|
||||
case ',':
|
||||
// case ',':
|
||||
if (tokenstart>=0)
|
||||
value = hdr.substring(tokenstart, tokenend+1);
|
||||
else
|
||||
|
@ -239,7 +239,7 @@ public class CookieCutter
|
|||
continue;
|
||||
|
||||
case ';':
|
||||
case ',':
|
||||
// case ',':
|
||||
if (tokenstart>=0)
|
||||
{
|
||||
name = hdr.substring(tokenstart, tokenend+1);
|
||||
|
|
|
@ -65,6 +65,7 @@ import org.eclipse.jetty.http.HttpVersions;
|
|||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.io.BufferUtil;
|
||||
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.nio.DirectNIOBuffer;
|
||||
import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
|
||||
|
@ -1943,12 +1944,28 @@ public class Request implements HttpServletRequest
|
|||
{
|
||||
if (getContentType() == null || !getContentType().startsWith("multipart/form-data"))
|
||||
return null;
|
||||
|
||||
|
||||
if (_multiPartInputStream == null)
|
||||
{
|
||||
_multiPartInputStream = new MultiPartInputStream(getInputStream(),
|
||||
getContentType(),(MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT),
|
||||
(_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
|
||||
Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing
|
||||
for (Part p:parts)
|
||||
{
|
||||
MultiPartInputStream.MultiPart mp = (MultiPartInputStream.MultiPart)p;
|
||||
if (mp.getContentDispositionFilename() == null && mp.getFile() == null)
|
||||
{
|
||||
//Servlet Spec 3.0 pg 23, parts without filenames must be put into init params
|
||||
String charset = null;
|
||||
if (mp.getContentType() != null)
|
||||
charset = MimeTypes.getCharsetFromContentType(new ByteArrayBuffer(mp.getContentType()));
|
||||
|
||||
String content=new String(mp.getBytes(),charset==null?StringUtil.__UTF8:charset);
|
||||
getParameter(""); //cause params to be evaluated
|
||||
getParameters().add(mp.getName(), content);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _multiPartInputStream.getPart(name);
|
||||
}
|
||||
|
@ -1964,6 +1981,22 @@ public class Request implements HttpServletRequest
|
|||
_multiPartInputStream = new MultiPartInputStream(getInputStream(),
|
||||
getContentType(),(MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT),
|
||||
(_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
|
||||
Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing
|
||||
for (Part p:parts)
|
||||
{
|
||||
MultiPartInputStream.MultiPart mp = (MultiPartInputStream.MultiPart)p;
|
||||
if (mp.getContentDispositionFilename() == null && mp.getFile() == null)
|
||||
{
|
||||
//Servlet Spec 3.0 pg 23, parts without filenames must be put into init params
|
||||
String charset = null;
|
||||
if (mp.getContentType() != null)
|
||||
charset = MimeTypes.getCharsetFromContentType(new ByteArrayBuffer(mp.getContentType()));
|
||||
|
||||
String content=new String(mp.getBytes(),charset==null?StringUtil.__UTF8:charset);
|
||||
getParameter(""); //cause params to be evaluated
|
||||
getParameters().add(mp.getName(), content);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _multiPartInputStream.getParts();
|
||||
}
|
||||
|
|
|
@ -137,7 +137,7 @@ public class Response implements HttpServletResponse
|
|||
if (i>=0)
|
||||
{
|
||||
http_only=true;
|
||||
comment=comment.substring(i,i+HTTP_ONLY_COMMENT.length()).trim();
|
||||
comment=comment.replace(HTTP_ONLY_COMMENT,"").trim();
|
||||
if (comment.length()==0)
|
||||
comment=null;
|
||||
}
|
||||
|
|
|
@ -74,7 +74,6 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
private boolean _sendDateHeader = false; //send Date: header
|
||||
private int _graceful=0;
|
||||
private boolean _stopAtShutdown;
|
||||
private int _maxCookieVersion=1;
|
||||
private boolean _dumpAfterStart=false;
|
||||
private boolean _dumpBeforeStop=false;
|
||||
private boolean _uncheckedPrintWriter=false;
|
||||
|
@ -267,7 +266,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
mex.add(e);
|
||||
}
|
||||
|
||||
if (_connectors!=null)
|
||||
if (_connectors!=null && mex.size()==0)
|
||||
{
|
||||
for (int i=0;i<_connectors.length;i++)
|
||||
{
|
||||
|
@ -452,21 +451,20 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the maximum cookie version.
|
||||
* @return the maximum set-cookie version sent by this server
|
||||
/**
|
||||
*/
|
||||
@Deprecated
|
||||
public int getMaxCookieVersion()
|
||||
{
|
||||
return _maxCookieVersion;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the maximum cookie version.
|
||||
* @param maxCookieVersion the maximum set-cookie version sent by this server
|
||||
/**
|
||||
*/
|
||||
@Deprecated
|
||||
public void setMaxCookieVersion(int maxCookieVersion)
|
||||
{
|
||||
_maxCookieVersion = maxCookieVersion;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -21,6 +21,8 @@ import java.io.UnsupportedEncodingException;
|
|||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -30,7 +32,8 @@ import org.eclipse.jetty.continuation.Continuation;
|
|||
import org.eclipse.jetty.continuation.ContinuationListener;
|
||||
import org.eclipse.jetty.continuation.ContinuationSupport;
|
||||
import org.eclipse.jetty.http.HttpMethods;
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
|
||||
import org.eclipse.jetty.http.gzip.CompressedResponseWrapper;
|
||||
import org.eclipse.jetty.http.gzip.AbstractCompressedStream;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -222,7 +225,7 @@ public class GzipHandler extends HandlerWrapper
|
|||
}
|
||||
}
|
||||
|
||||
final GzipResponseWrapper wrappedResponse = newGzipResponseWrapper(request,response);
|
||||
final CompressedResponseWrapper wrappedResponse = newGzipResponseWrapper(request,response);
|
||||
|
||||
boolean exceptional=true;
|
||||
try
|
||||
|
@ -256,7 +259,7 @@ public class GzipHandler extends HandlerWrapper
|
|||
else if (exceptional && !response.isCommitted())
|
||||
{
|
||||
wrappedResponse.resetBuffer();
|
||||
wrappedResponse.noGzip();
|
||||
wrappedResponse.noCompression();
|
||||
}
|
||||
else
|
||||
wrappedResponse.finish();
|
||||
|
@ -276,14 +279,27 @@ public class GzipHandler extends HandlerWrapper
|
|||
* @param response the response
|
||||
* @return the gzip response wrapper
|
||||
*/
|
||||
protected GzipResponseWrapper newGzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
protected CompressedResponseWrapper newGzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
return new GzipResponseWrapper(request, response)
|
||||
return new CompressedResponseWrapper(request,response)
|
||||
{
|
||||
{
|
||||
super.setMimeTypes(GzipHandler.this._mimeTypes);
|
||||
super.setBufferSize(GzipHandler.this._bufferSize);
|
||||
super.setMinGzipSize(GzipHandler.this._minGzipSize);
|
||||
super.setMinCompressSize(GzipHandler.this._minGzipSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
|
||||
{
|
||||
return new AbstractCompressedStream("gzip",request,response,contentLength,bufferSize,minCompressSize)
|
||||
{
|
||||
@Override
|
||||
protected DeflaterOutputStream createStream() throws IOException
|
||||
{
|
||||
return new GZIPOutputStream(_response.getOutputStream(),_bufferSize);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -32,7 +32,6 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.jetty.http.HttpParser;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
|
@ -1280,4 +1279,51 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
response.setStatus(200);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSuspendedPipeline() throws Exception
|
||||
{
|
||||
SuspendHandler suspend = new SuspendHandler();
|
||||
suspend.setSuspendFor(30000);
|
||||
suspend.setResumeAfter(1000);
|
||||
configureServer(suspend);
|
||||
|
||||
long start=System.currentTimeMillis();
|
||||
Socket client=newSocket(HOST,_connector.getLocalPort());
|
||||
try
|
||||
{
|
||||
OutputStream os=client.getOutputStream();
|
||||
InputStream is=client.getInputStream();
|
||||
|
||||
// write an initial request
|
||||
os.write((
|
||||
"GET / HTTP/1.1\r\n"+
|
||||
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+
|
||||
"\r\n"
|
||||
).getBytes());
|
||||
os.flush();
|
||||
|
||||
Thread.sleep(200);
|
||||
|
||||
// write an pipelined request
|
||||
os.write((
|
||||
"GET / HTTP/1.1\r\n"+
|
||||
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+
|
||||
"connection: close\r\n"+
|
||||
"\r\n"
|
||||
).getBytes());
|
||||
os.flush();
|
||||
|
||||
String response=readResponse(client);
|
||||
assertThat(response,JUnitMatchers.containsString("RESUMEDHTTP/1.1 200 OK"));
|
||||
assertThat((System.currentTimeMillis()-start),greaterThanOrEqualTo(1999L));
|
||||
|
||||
// TODO This test should also check that that the CPU did not spin during the suspend.
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,6 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
@ -27,14 +24,15 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.continuation.Continuation;
|
||||
import org.eclipse.jetty.continuation.ContinuationListener;
|
||||
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
||||
import org.eclipse.jetty.server.session.SessionHandler;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class LocalAsyncContextTest
|
||||
{
|
||||
protected Server _server = new Server();
|
||||
|
@ -53,7 +51,7 @@ public class LocalAsyncContextTest
|
|||
_server.setHandler(session);
|
||||
_server.start();
|
||||
}
|
||||
|
||||
|
||||
protected Connector initConnector()
|
||||
{
|
||||
return new LocalConnector();
|
||||
|
@ -112,6 +110,7 @@ public class LocalAsyncContextTest
|
|||
|
||||
_handler.setResumeAfter(100);
|
||||
_handler.setCompleteAfter(-1);
|
||||
response=process("wibble");
|
||||
check(response,"DISPATCHED");
|
||||
|
||||
_handler.setResumeAfter(-1);
|
||||
|
@ -147,13 +146,14 @@ public class LocalAsyncContextTest
|
|||
check(response,"COMPLETED");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoCycles() throws Exception
|
||||
{
|
||||
String response;
|
||||
|
||||
__completed.set(0);
|
||||
__completed1.set(0);
|
||||
|
||||
|
||||
_handler.setRead(0);
|
||||
_handler.setSuspendFor(1000);
|
||||
_handler.setResumeAfter(100);
|
||||
|
@ -178,12 +178,12 @@ public class LocalAsyncContextTest
|
|||
assertTrue(i>=0);
|
||||
i+=m.length();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private synchronized String process(String content) throws Exception
|
||||
{
|
||||
String request = "GET / HTTP/1.1\r\n" +
|
||||
String request = "GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n"+
|
||||
"Connection: close\r\n";
|
||||
|
||||
|
@ -194,18 +194,294 @@ public class LocalAsyncContextTest
|
|||
|
||||
return getResponse(request);
|
||||
}
|
||||
|
||||
|
||||
protected String getResponse(String request) throws Exception
|
||||
{
|
||||
return ((LocalConnector)_connector).getResponses(request);
|
||||
}
|
||||
|
||||
private static class SuspendHandler extends HandlerWrapper
|
||||
{
|
||||
private int _read;
|
||||
private long _suspendFor=-1;
|
||||
private long _resumeAfter=-1;
|
||||
private long _completeAfter=-1;
|
||||
private long _suspendFor2=-1;
|
||||
private long _resumeAfter2=-1;
|
||||
private long _completeAfter2=-1;
|
||||
|
||||
public SuspendHandler()
|
||||
{
|
||||
}
|
||||
|
||||
public int getRead()
|
||||
{
|
||||
return _read;
|
||||
}
|
||||
|
||||
public void setRead(int read)
|
||||
{
|
||||
_read = read;
|
||||
}
|
||||
|
||||
public long getSuspendFor()
|
||||
{
|
||||
return _suspendFor;
|
||||
}
|
||||
|
||||
public void setSuspendFor(long suspendFor)
|
||||
{
|
||||
_suspendFor = suspendFor;
|
||||
}
|
||||
|
||||
public long getResumeAfter()
|
||||
{
|
||||
return _resumeAfter;
|
||||
}
|
||||
|
||||
public void setResumeAfter(long resumeAfter)
|
||||
{
|
||||
_resumeAfter = resumeAfter;
|
||||
}
|
||||
|
||||
public long getCompleteAfter()
|
||||
{
|
||||
return _completeAfter;
|
||||
}
|
||||
|
||||
public void setCompleteAfter(long completeAfter)
|
||||
{
|
||||
_completeAfter = completeAfter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the suspendFor2.
|
||||
* @return the suspendFor2
|
||||
*/
|
||||
public long getSuspendFor2()
|
||||
{
|
||||
return _suspendFor2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the suspendFor2.
|
||||
* @param suspendFor2 the suspendFor2 to set
|
||||
*/
|
||||
public void setSuspendFor2(long suspendFor2)
|
||||
{
|
||||
_suspendFor2 = suspendFor2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the resumeAfter2.
|
||||
* @return the resumeAfter2
|
||||
*/
|
||||
public long getResumeAfter2()
|
||||
{
|
||||
return _resumeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the resumeAfter2.
|
||||
* @param resumeAfter2 the resumeAfter2 to set
|
||||
*/
|
||||
public void setResumeAfter2(long resumeAfter2)
|
||||
{
|
||||
_resumeAfter2 = resumeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the completeAfter2.
|
||||
* @return the completeAfter2
|
||||
*/
|
||||
public long getCompleteAfter2()
|
||||
{
|
||||
return _completeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the completeAfter2.
|
||||
* @param completeAfter2 the completeAfter2 to set
|
||||
*/
|
||||
public void setCompleteAfter2(long completeAfter2)
|
||||
{
|
||||
_completeAfter2 = completeAfter2;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handle(String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()))
|
||||
{
|
||||
if (_read>0)
|
||||
{
|
||||
byte[] buf=new byte[_read];
|
||||
request.getInputStream().read(buf);
|
||||
}
|
||||
else if (_read<0)
|
||||
{
|
||||
InputStream in = request.getInputStream();
|
||||
int b=in.read();
|
||||
while(b!=-1)
|
||||
b=in.read();
|
||||
}
|
||||
|
||||
|
||||
final AsyncContext asyncContext = baseRequest.startAsync();
|
||||
response.getOutputStream().println("STARTASYNC");
|
||||
asyncContext.addListener(__asyncListener);
|
||||
asyncContext.addListener(__asyncListener1);
|
||||
if (_suspendFor>0)
|
||||
asyncContext.setTimeout(_suspendFor);
|
||||
|
||||
|
||||
if (_completeAfter>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_completeAfter);
|
||||
response.getOutputStream().println("COMPLETED");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_completeAfter==0)
|
||||
{
|
||||
response.getOutputStream().println("COMPLETED");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
|
||||
if (_resumeAfter>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_resumeAfter);
|
||||
if(((HttpServletRequest)asyncContext.getRequest()).getSession(true).getId()!=null)
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_resumeAfter==0)
|
||||
{
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (request.getAttribute("TIMEOUT")!=null)
|
||||
response.getOutputStream().println("TIMEOUT");
|
||||
else
|
||||
response.getOutputStream().println("DISPATCHED");
|
||||
|
||||
if (_suspendFor2>=0)
|
||||
{
|
||||
final AsyncContext asyncContext = baseRequest.startAsync();
|
||||
response.getOutputStream().println("STARTASYNC2");
|
||||
if (_suspendFor2>0)
|
||||
asyncContext.setTimeout(_suspendFor2);
|
||||
_suspendFor2=-1;
|
||||
|
||||
if (_completeAfter2>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_completeAfter2);
|
||||
response.getOutputStream().println("COMPLETED2");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_completeAfter2==0)
|
||||
{
|
||||
response.getOutputStream().println("COMPLETED2");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
|
||||
if (_resumeAfter2>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_resumeAfter2);
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_resumeAfter2==0)
|
||||
{
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static AtomicInteger __completed = new AtomicInteger();
|
||||
static AtomicInteger __completed1 = new AtomicInteger();
|
||||
|
||||
static AsyncListener __asyncListener = new AsyncListener()
|
||||
|
||||
private static AsyncListener __asyncListener = new AsyncListener()
|
||||
{
|
||||
|
||||
@Override
|
||||
|
@ -235,8 +511,8 @@ public class LocalAsyncContextTest
|
|||
}
|
||||
|
||||
};
|
||||
|
||||
static AsyncListener __asyncListener1 = new AsyncListener()
|
||||
|
||||
private static AsyncListener __asyncListener1 = new AsyncListener()
|
||||
{
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,6 +18,7 @@ import static org.junit.Assert.assertFalse;
|
|||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
|
@ -35,6 +36,7 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.Part;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
|
@ -122,6 +124,51 @@ public class RequestTest
|
|||
assertTrue(responses.startsWith("HTTP/1.1 200"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiPart() throws Exception
|
||||
{
|
||||
_handler._checker = new RequestTester()
|
||||
{
|
||||
public boolean check(HttpServletRequest request,HttpServletResponse response)
|
||||
{
|
||||
try
|
||||
{
|
||||
Part foo = request.getPart("stuff");
|
||||
assertNotNull(foo);
|
||||
String value = request.getParameter("stuff");
|
||||
byte[] expected = "000000000000000000000000000000000000000000000000000".getBytes("ISO-8859-1");
|
||||
return value.equals(new String(expected, "ISO-8859-1"));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
String multipart = "--AaB03x\r\n"+
|
||||
"content-disposition: form-data; name=\"field1\"\r\n"+
|
||||
"\r\n"+
|
||||
"Joe Blow\r\n"+
|
||||
"--AaB03x\r\n"+
|
||||
"content-disposition: form-data; name=\"stuff\"\r\n"+
|
||||
"Content-Type: text/plain;charset=ISO-8859-1\r\n"+
|
||||
"\r\n"+
|
||||
"000000000000000000000000000000000000000000000000000\r\n"+
|
||||
"--AaB03x--\r\n";
|
||||
|
||||
String request="GET / HTTP/1.1\r\n"+
|
||||
"Host: whatever\r\n"+
|
||||
"Content-Type: multipart/form-data; boundary=\"AaB03x\"\r\n"+
|
||||
"Content-Length: "+multipart.getBytes().length+"\r\n"+
|
||||
"\r\n"+
|
||||
multipart;
|
||||
|
||||
String responses=_connector.getResponses(request);
|
||||
assertTrue(responses.startsWith("HTTP/1.1 200"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadUtf8ParamExtraction() throws Exception
|
||||
|
@ -671,7 +718,7 @@ public class RequestTest
|
|||
"POST / HTTP/1.1\r\n"+
|
||||
"Host: whatever\r\n"+
|
||||
"Cookie: name0=value0; name1 = value1 ; \"name2\" = \"\\\"value2\\\"\" \n" +
|
||||
"Cookie: $Version=2; name3=value3=value3;$path=/path;$domain=acme.com;$port=8080, name4=; name5 = ; name6\n" +
|
||||
"Cookie: $Version=2; name3=value3=value3;$path=/path;$domain=acme.com;$port=8080; name4=; name5 = ; name6\n" +
|
||||
"Cookie: name7=value7;\n" +
|
||||
"Connection: close\r\n"+
|
||||
"\r\n");
|
||||
|
@ -696,6 +743,20 @@ public class RequestTest
|
|||
assertEquals("", cookies.get(6).getValue());
|
||||
assertEquals("name7", cookies.get(7).getName());
|
||||
assertEquals("value7", cookies.get(7).getValue());
|
||||
|
||||
cookies.clear();
|
||||
response=_connector.getResponses(
|
||||
"GET /other HTTP/1.1\n"+
|
||||
"Host: whatever\n"+
|
||||
"Other: header\n"+
|
||||
"Cookie: __utmz=14316.133020.1.1.utr=gna.de|ucn=(real)|utd=reral|utct=/games/hen-one,gnt-50-ba-keys:key,2072262.html\n"+
|
||||
"\n"
|
||||
);
|
||||
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
|
||||
assertEquals(1,cookies.size());
|
||||
assertEquals("__utmz", cookies.get(0).getName());
|
||||
assertEquals("14316.133020.1.1.utr=gna.de|ucn=(real)|utd=reral|utct=/games/hen-one,gnt-50-ba-keys:key,2072262.html", cookies.get(0).getValue());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -833,7 +894,9 @@ public class RequestTest
|
|||
{
|
||||
((Request)request).setHandled(true);
|
||||
|
||||
if (request.getContentLength()>0 && !MimeTypes.FORM_ENCODED.equals(request.getContentType()))
|
||||
if (request.getContentLength()>0
|
||||
&& !MimeTypes.FORM_ENCODED.equals(request.getContentType())
|
||||
&& !request.getContentType().startsWith("multipart/form-data"))
|
||||
_content=IO.toString(request.getInputStream());
|
||||
|
||||
if (_checker!=null && _checker.check(request,response))
|
||||
|
|
|
@ -385,7 +385,7 @@ public class ResponseTest
|
|||
{
|
||||
String[][] tests={
|
||||
{"/other/location?name=value","http://myhost:8888/other/location;jsessionid=12345?name=value"},
|
||||
{"/other/location","http://myhost:8888/other/location"},
|
||||
/* {"/other/location","http://myhost:8888/other/location"},
|
||||
{"/other/l%20cation","http://myhost:8888/other/l%20cation"},
|
||||
{"location","http://myhost:8888/path/location"},
|
||||
{"./location","http://myhost:8888/path/location"},
|
||||
|
@ -393,7 +393,8 @@ public class ResponseTest
|
|||
{"/other/l%20cation","http://myhost:8888/other/l%20cation"},
|
||||
{"l%20cation","http://myhost:8888/path/l%20cation"},
|
||||
{"./l%20cation","http://myhost:8888/path/l%20cation"},
|
||||
{"../l%20cation","http://myhost:8888/l%20cation"},
|
||||
{"../l%20cation","http://myhost:8888/l%20cation"},*/
|
||||
{"../locati%C3%abn","http://myhost:8888/locati%C3%ABn"},
|
||||
};
|
||||
|
||||
for (int i=1;i<tests.length;i++)
|
||||
|
@ -517,7 +518,7 @@ public class ResponseTest
|
|||
|
||||
String set = response.getHttpFields().getStringField("Set-Cookie");
|
||||
|
||||
assertEquals("name=value;Path=/path;Domain=domain;Secure;HttpOnly",set);
|
||||
assertEquals("name=value;Comment=comment;Path=/path;Domain=domain;Secure;HttpOnly",set);
|
||||
}
|
||||
|
||||
private Response newResponse()
|
||||
|
|
|
@ -31,6 +31,12 @@ public class SelectChannelServerTest extends HttpServerTestBase
|
|||
{
|
||||
super.testCommittedError();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testSuspendedPipeline() throws Exception
|
||||
{
|
||||
super.testSuspendedPipeline();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
@ -26,6 +24,8 @@ import org.eclipse.jetty.util.IO;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
|
||||
{
|
||||
|
||||
|
@ -49,7 +49,7 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
|
|||
|
||||
_handler.setSuspendFor(100);
|
||||
_handler.setResumeAfter(25);
|
||||
assertTrue(process(null).toUpperCase().contains("DISPATCHED"));
|
||||
assertTrue(process(null).toUpperCase().contains("RESUMED"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -2,8 +2,9 @@ package org.eclipse.jetty.server;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.AsyncEvent;
|
||||
import javax.servlet.AsyncListener;
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -11,15 +12,12 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
||||
|
||||
class SuspendHandler extends HandlerWrapper
|
||||
class SuspendHandler extends HandlerWrapper implements AsyncListener
|
||||
{
|
||||
private int _read;
|
||||
private long _suspendFor=-1;
|
||||
private long _resumeAfter=-1;
|
||||
private long _completeAfter=-1;
|
||||
private long _suspendFor2=-1;
|
||||
private long _resumeAfter2=-1;
|
||||
private long _completeAfter2=-1;
|
||||
|
||||
public SuspendHandler()
|
||||
{
|
||||
|
@ -64,227 +62,115 @@ class SuspendHandler extends HandlerWrapper
|
|||
{
|
||||
_completeAfter = completeAfter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the suspendFor2.
|
||||
* @return the suspendFor2
|
||||
*/
|
||||
public long getSuspendFor2()
|
||||
{
|
||||
return _suspendFor2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the suspendFor2.
|
||||
* @param suspendFor2 the suspendFor2 to set
|
||||
*/
|
||||
public void setSuspendFor2(long suspendFor2)
|
||||
{
|
||||
_suspendFor2 = suspendFor2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the resumeAfter2.
|
||||
* @return the resumeAfter2
|
||||
*/
|
||||
public long getResumeAfter2()
|
||||
{
|
||||
return _resumeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the resumeAfter2.
|
||||
* @param resumeAfter2 the resumeAfter2 to set
|
||||
*/
|
||||
public void setResumeAfter2(long resumeAfter2)
|
||||
{
|
||||
_resumeAfter2 = resumeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the completeAfter2.
|
||||
* @return the completeAfter2
|
||||
*/
|
||||
public long getCompleteAfter2()
|
||||
{
|
||||
return _completeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the completeAfter2.
|
||||
* @param completeAfter2 the completeAfter2 to set
|
||||
*/
|
||||
public void setCompleteAfter2(long completeAfter2)
|
||||
{
|
||||
_completeAfter2 = completeAfter2;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handle(String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
try
|
||||
if (DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()))
|
||||
{
|
||||
if (DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()))
|
||||
if (_read>0)
|
||||
{
|
||||
if (_read>0)
|
||||
{
|
||||
byte[] buf=new byte[_read];
|
||||
request.getInputStream().read(buf);
|
||||
}
|
||||
else if (_read<0)
|
||||
{
|
||||
InputStream in = request.getInputStream();
|
||||
int b=in.read();
|
||||
while(b!=-1)
|
||||
b=in.read();
|
||||
}
|
||||
|
||||
|
||||
final AsyncContext asyncContext = baseRequest.startAsync();
|
||||
response.getOutputStream().println("STARTASYNC");
|
||||
asyncContext.addListener(LocalAsyncContextTest.__asyncListener);
|
||||
asyncContext.addListener(LocalAsyncContextTest.__asyncListener1);
|
||||
if (_suspendFor>0)
|
||||
asyncContext.setTimeout(_suspendFor);
|
||||
|
||||
|
||||
if (_completeAfter>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_completeAfter);
|
||||
response.getOutputStream().println("COMPLETED");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_completeAfter==0)
|
||||
{
|
||||
response.getOutputStream().println("COMPLETED");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
|
||||
if (_resumeAfter>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_resumeAfter);
|
||||
if(((HttpServletRequest)asyncContext.getRequest()).getSession(true).getId()!=null)
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_resumeAfter==0)
|
||||
{
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
byte[] buf=new byte[_read];
|
||||
request.getInputStream().read(buf);
|
||||
}
|
||||
else
|
||||
else if (_read<0)
|
||||
{
|
||||
if (request.getAttribute("TIMEOUT")!=null)
|
||||
response.getOutputStream().println("TIMEOUT");
|
||||
else
|
||||
response.getOutputStream().println("DISPATCHED");
|
||||
InputStream in = request.getInputStream();
|
||||
int b=in.read();
|
||||
while(b!=-1)
|
||||
b=in.read();
|
||||
}
|
||||
|
||||
if (_suspendFor2>=0)
|
||||
{
|
||||
final AsyncContext asyncContext = baseRequest.startAsync();
|
||||
response.getOutputStream().println("STARTASYNC2");
|
||||
if (_suspendFor2>0)
|
||||
asyncContext.setTimeout(_suspendFor2);
|
||||
_suspendFor2=-1;
|
||||
final AsyncContext asyncContext = baseRequest.startAsync();
|
||||
asyncContext.addListener(this);
|
||||
if (_suspendFor>0)
|
||||
asyncContext.setTimeout(_suspendFor);
|
||||
|
||||
if (_completeAfter2>0)
|
||||
if (_completeAfter>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_completeAfter2);
|
||||
response.getOutputStream().println("COMPLETED2");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_completeAfter2==0)
|
||||
{
|
||||
response.getOutputStream().println("COMPLETED2");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
try
|
||||
{
|
||||
Thread.sleep(_completeAfter);
|
||||
response.getOutputStream().println("COMPLETED");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_completeAfter==0)
|
||||
{
|
||||
response.getOutputStream().println("COMPLETED");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
|
||||
if (_resumeAfter2>0)
|
||||
if (_resumeAfter>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_resumeAfter2);
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
try
|
||||
{
|
||||
Thread.sleep(_resumeAfter);
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
else if (_resumeAfter2==0)
|
||||
{
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_resumeAfter==0)
|
||||
{
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
}
|
||||
finally
|
||||
else if (request.getAttribute("TIMEOUT")!=null)
|
||||
{
|
||||
response.setStatus(200);
|
||||
response.getOutputStream().print("TIMEOUT");
|
||||
baseRequest.setHandled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
response.setStatus(200);
|
||||
response.getOutputStream().print("RESUMED");
|
||||
baseRequest.setHandled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete(AsyncEvent asyncEvent) throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimeout(AsyncEvent asyncEvent) throws IOException
|
||||
{
|
||||
asyncEvent.getSuppliedRequest().setAttribute("TIMEOUT",Boolean.TRUE);
|
||||
asyncEvent.getAsyncContext().dispatch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(AsyncEvent asyncEvent) throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartAsync(AsyncEvent asyncEvent) throws IOException
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,8 +99,6 @@ public class SSLEngineTest
|
|||
connector.setRequestHeaderSize(512);
|
||||
|
||||
server.setConnectors(new Connector[]{connector });
|
||||
server.setHandler(new HelloWorldHandler());
|
||||
server.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
|
@ -109,10 +107,15 @@ public class SSLEngineTest
|
|||
server.stop();
|
||||
server.join();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBigResponse() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
server.setHandler(new HelloWorldHandler());
|
||||
server.start();
|
||||
|
||||
SSLContext ctx=SSLContext.getInstance("TLS");
|
||||
ctx.init(null,SslContextFactory.TRUST_ALL_CERTS,new java.security.SecureRandom());
|
||||
|
||||
|
@ -123,7 +126,7 @@ public class SSLEngineTest
|
|||
|
||||
String request =
|
||||
"GET /?dump=102400 HTTP/1.1\r\n"+
|
||||
"Host: localhost:8080\r\n"+
|
||||
"Host: localhost:"+port+"\r\n"+
|
||||
"Connection: close\r\n"+
|
||||
"\r\n";
|
||||
|
||||
|
@ -138,6 +141,10 @@ public class SSLEngineTest
|
|||
@Test
|
||||
public void testRequestJettyHttps() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
server.setHandler(new HelloWorldHandler());
|
||||
server.start();
|
||||
|
||||
final int loops=10;
|
||||
final int numConns=10;
|
||||
|
||||
|
@ -204,8 +211,7 @@ public class SSLEngineTest
|
|||
@Test
|
||||
public void testServletPost() throws Exception
|
||||
{
|
||||
stopServer();
|
||||
|
||||
server.stop();
|
||||
StreamHandler handler = new StreamHandler();
|
||||
server.setHandler(handler);
|
||||
server.start();
|
||||
|
@ -308,6 +314,7 @@ public class SSLEngineTest
|
|||
{
|
||||
ServletOutputStream out=response.getOutputStream();
|
||||
byte[] buf = new byte[Integer.valueOf(request.getParameter("dump"))];
|
||||
// System.err.println("DUMP "+buf.length);
|
||||
for (int i=0;i<buf.length;i++)
|
||||
buf[i]=(byte)('0'+(i%10));
|
||||
out.write(buf);
|
||||
|
|
|
@ -15,20 +15,29 @@ package org.eclipse.jetty.server.ssl;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.security.KeyStore;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
|
||||
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.nio.SslConnection;
|
||||
import org.eclipse.jetty.server.HttpServerTestBase;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.hamcrest.Matchers.lessThan;
|
||||
|
||||
/**
|
||||
* HttpServer Tester.
|
||||
|
@ -46,11 +55,28 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
|
|||
return __sslContext.getSocketFactory().createSocket(host,port);
|
||||
}
|
||||
|
||||
private static final AtomicInteger _handlecount = new AtomicInteger();
|
||||
|
||||
@BeforeClass
|
||||
public static void init() throws Exception
|
||||
{
|
||||
SslSelectChannelConnector connector = new SslSelectChannelConnector();
|
||||
SslSelectChannelConnector connector = new SslSelectChannelConnector()
|
||||
{
|
||||
@Override
|
||||
protected SslConnection newSslConnection(AsyncEndPoint endPoint, SSLEngine engine)
|
||||
{
|
||||
return new SslConnection(engine, endPoint)
|
||||
{
|
||||
@Override
|
||||
public Connection handle() throws IOException
|
||||
{
|
||||
_handlecount.incrementAndGet();
|
||||
return super.handle();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
String keystorePath = System.getProperty("basedir",".") + "/src/test/resources/keystore";
|
||||
SslContextFactory cf = connector.getSslContextFactory();
|
||||
cf.setKeyStorePath(keystorePath);
|
||||
|
@ -69,7 +95,6 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
|
|||
__sslContext = SSLContext.getInstance("TLS");
|
||||
__sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(__hostnameverifier);
|
||||
|
@ -105,7 +130,6 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
|
|||
{
|
||||
OutputStream os=client.getOutputStream();
|
||||
|
||||
|
||||
int last=0;
|
||||
|
||||
// Write out the fragments
|
||||
|
@ -137,12 +161,17 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Ignore
|
||||
public void testAvailable() throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void testSuspendedPipeline() throws Exception
|
||||
{
|
||||
_handlecount.set(0);
|
||||
super.testSuspendedPipeline();
|
||||
assertThat(_handlecount.get(),lessThan(50));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -590,7 +590,8 @@ public class ServletHandler extends ScopedHandler
|
|||
}
|
||||
finally
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
if (servlet_holder!=null)
|
||||
baseRequest.setHandled(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1223,7 +1224,7 @@ public class ServletHandler extends ScopedHandler
|
|||
|
||||
try
|
||||
{
|
||||
if (isStarted())
|
||||
if (_contextHandler!=null && _contextHandler.isStarted() || _contextHandler==null && isStarted())
|
||||
initialize();
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -1239,7 +1240,7 @@ public class ServletHandler extends ScopedHandler
|
|||
{
|
||||
if(LOG.isDebugEnabled())
|
||||
LOG.debug("Not Found "+request.getRequestURI());
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
//Override to send an error back, eg with: response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -587,10 +587,14 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
|||
// Handle run as
|
||||
if (_identityService!=null)
|
||||
old_run_as=_identityService.setRunAs(baseRequest.getResolvedUserIdentity(),_runAsToken);
|
||||
|
||||
|
||||
if (!isAsyncSupported())
|
||||
baseRequest.setAsyncSupported(false);
|
||||
|
||||
|
||||
MultipartConfigElement mpce = ((Registration)getRegistration()).getMultipartConfig();
|
||||
if (mpce != null)
|
||||
request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, mpce);
|
||||
|
||||
servlet.service(request,response);
|
||||
servlet_error=false;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.eclipse.jetty.servlet;
|
|||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
|
@ -14,6 +15,7 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
|
@ -222,17 +224,20 @@ public class AsyncContextTest
|
|||
}
|
||||
else
|
||||
{
|
||||
boolean wrapped = false;
|
||||
final AsyncContext asyncContext;
|
||||
if (request.getParameter("dispatchRequestResponse") != null)
|
||||
{
|
||||
asyncContext = request.startAsync(request,response);
|
||||
wrapped = true;
|
||||
asyncContext = request.startAsync(request, new Wrapper(response));
|
||||
}
|
||||
else
|
||||
{
|
||||
asyncContext = request.startAsync();
|
||||
}
|
||||
|
||||
new Thread(new DispatchingRunnable(asyncContext)).start();
|
||||
|
||||
new Thread(new DispatchingRunnable(asyncContext, wrapped)).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -240,14 +245,18 @@ public class AsyncContextTest
|
|||
private class DispatchingRunnable implements Runnable
|
||||
{
|
||||
private AsyncContext asyncContext;
|
||||
private boolean wrapped;
|
||||
|
||||
public DispatchingRunnable(AsyncContext asyncContext)
|
||||
public DispatchingRunnable(AsyncContext asyncContext, boolean wrapped)
|
||||
{
|
||||
this.asyncContext = asyncContext;
|
||||
this.wrapped = wrapped;
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
if (wrapped)
|
||||
assertTrue(asyncContext.getResponse() instanceof Wrapper);
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
}
|
||||
|
@ -329,4 +338,13 @@ public class AsyncContextTest
|
|||
}
|
||||
}
|
||||
|
||||
private class Wrapper extends HttpServletResponseWrapper
|
||||
{
|
||||
public Wrapper (HttpServletResponse response)
|
||||
{
|
||||
super(response);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1007,7 +1007,7 @@ public class DoSFilter implements Filter
|
|||
if (_rateTrackers != null && _trackerTimeoutQ != null)
|
||||
{
|
||||
long now = _trackerTimeoutQ.getNow();
|
||||
int latestIndex = _next == 0 ? 3 : (_next - 1 ) % _timestamps.length;
|
||||
int latestIndex = _next == 0 ? (_timestamps.length-1) : (_next - 1 );
|
||||
long last=_timestamps[latestIndex];
|
||||
boolean hasRecentRequest = last != 0 && (now-last)<1000L;
|
||||
|
||||
|
|
|
@ -13,14 +13,13 @@
|
|||
package org.eclipse.jetty.servlets;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
|
@ -34,14 +33,16 @@ import org.eclipse.jetty.continuation.Continuation;
|
|||
import org.eclipse.jetty.continuation.ContinuationListener;
|
||||
import org.eclipse.jetty.continuation.ContinuationSupport;
|
||||
import org.eclipse.jetty.http.HttpMethods;
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
|
||||
import org.eclipse.jetty.http.gzip.CompressedResponseWrapper;
|
||||
import org.eclipse.jetty.http.gzip.AbstractCompressedStream;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** GZIP Filter
|
||||
* This filter will gzip the content of a response iff: <ul>
|
||||
* This filter will gzip or deflate the content of a response if: <ul>
|
||||
* <li>The filter is mapped to a matching path</li>
|
||||
* <li>accept-encoding header is set to either gzip, deflate or a combination of those</li>
|
||||
* <li>The response status code is >=200 and <300
|
||||
* <li>The content length is unknown or more than the <code>minGzipSize</code> initParameter or the minGzipSize is 0(default)</li>
|
||||
* <li>The content-type is in the comma separated list of mimeTypes set in the <code>mimeTypes</code> initParameter or
|
||||
|
@ -50,8 +51,11 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* If both gzip and deflate are specified in the accept-encoding header, then gzip will be used.
|
||||
* </p>
|
||||
* <p>
|
||||
* Compressing the content can greatly improve the network bandwidth usage, but at a cost of memory and
|
||||
* CPU cycles. If this filter is mapped for static content, then use of efficient direct NIO may be
|
||||
* CPU cycles. If this filter is mapped for static content, then use of efficient direct NIO may be
|
||||
* prevented, thus use of the gzip mechanism of the {@link org.eclipse.jetty.servlet.DefaultServlet} is
|
||||
* advised instead.
|
||||
* </p>
|
||||
|
@ -59,15 +63,49 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
* This filter extends {@link UserAgentFilter} and if the the initParameter <code>excludedAgents</code>
|
||||
* is set to a comma separated list of user agents, then these agents will be excluded from gzip content.
|
||||
* </p>
|
||||
* <p>Init Parameters:</p>
|
||||
* <PRE>
|
||||
* bufferSize The output buffer size. Defaults to 8192. Be careful as values <= 0 will lead to an
|
||||
* {@link IllegalArgumentException}.
|
||||
* @see java.util.zip.GZIPOutputStream#GZIPOutputStream(java.io.OutputStream, int)
|
||||
* @see java.util.zip.DeflaterOutputStream#DeflaterOutputStream(java.io.OutputStream, Deflater, int)
|
||||
*
|
||||
* minGzipSize Content will only be compressed if content length is either unknown or greater
|
||||
* than <code>minGzipSize</code>.
|
||||
*
|
||||
* deflateCompressionLevel The compression level used for deflate compression. (0-9).
|
||||
* @see java.util.zip.Deflater#Deflater(int, boolean)
|
||||
*
|
||||
* deflateNoWrap The noWrap setting for deflate compression. Defaults to true. (true/false)
|
||||
* @see java.util.zip.Deflater#Deflater(int, boolean)
|
||||
*
|
||||
* mimeTypes Comma separated list of mime types to compress. See description above.
|
||||
*
|
||||
* excludedAgents Comma separated list of user agents to exclude from compression. Does a
|
||||
* {@link String#contains(CharSequence)} to check if the excluded agent occurs
|
||||
* in the user-agent header. If it does -> no compression
|
||||
*
|
||||
* excludeAgentPatterns Same as excludedAgents, but accepts regex patterns for more complex matching.
|
||||
*
|
||||
* excludePaths Comma separated list of paths to exclude from compression.
|
||||
* Does a {@link String#startsWith(String)} comparison to check if the path matches.
|
||||
* If it does match -> no compression. To match subpaths use <code>excludePathPatterns</code>
|
||||
* instead.
|
||||
*
|
||||
* excludePathPatterns Same as excludePath, but accepts regex patterns for more complex matching.
|
||||
* </PRE>
|
||||
*/
|
||||
public class GzipFilter extends UserAgentFilter
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(GzipFilter.class);
|
||||
public final static String GZIP="gzip";
|
||||
public final static String DEFLATE="deflate";
|
||||
|
||||
protected Set<String> _mimeTypes;
|
||||
protected int _bufferSize=8192;
|
||||
protected int _minGzipSize=256;
|
||||
protected int _deflateCompressionLevel=Deflater.DEFAULT_COMPRESSION;
|
||||
protected boolean _deflateNoWrap = true;
|
||||
protected Set<String> _excludedAgents;
|
||||
protected Set<Pattern> _excludedAgentPatterns;
|
||||
protected Set<String> _excludedPaths;
|
||||
|
@ -91,6 +129,14 @@ public class GzipFilter extends UserAgentFilter
|
|||
if (tmp!=null)
|
||||
_minGzipSize=Integer.parseInt(tmp);
|
||||
|
||||
tmp=filterConfig.getInitParameter("deflateCompressionLevel");
|
||||
if (tmp!=null)
|
||||
_deflateCompressionLevel=Integer.parseInt(tmp);
|
||||
|
||||
tmp=filterConfig.getInitParameter("deflateNoWrap");
|
||||
if (tmp!=null)
|
||||
_deflateNoWrap=Boolean.parseBoolean(tmp);
|
||||
|
||||
tmp=filterConfig.getInitParameter("mimeTypes");
|
||||
if (tmp!=null)
|
||||
{
|
||||
|
@ -144,7 +190,7 @@ public class GzipFilter extends UserAgentFilter
|
|||
public void destroy()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlets.UserAgentFilter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
|
||||
|
@ -156,9 +202,8 @@ public class GzipFilter extends UserAgentFilter
|
|||
HttpServletRequest request=(HttpServletRequest)req;
|
||||
HttpServletResponse response=(HttpServletResponse)res;
|
||||
|
||||
String ae = request.getHeader("accept-encoding");
|
||||
if (ae != null && ae.indexOf("gzip")>=0 && !response.containsHeader("Content-Encoding")
|
||||
&& !HttpMethods.HEAD.equalsIgnoreCase(request.getMethod()))
|
||||
String compressionType = selectCompression(request.getHeader("accept-encoding"));
|
||||
if (compressionType!=null && !response.containsHeader("Content-Encoding") && !HttpMethods.HEAD.equalsIgnoreCase(request.getMethod()))
|
||||
{
|
||||
String ua = getUserAgent(request);
|
||||
if (isExcludedAgent(ua))
|
||||
|
@ -172,8 +217,8 @@ public class GzipFilter extends UserAgentFilter
|
|||
super.doFilter(request,response,chain);
|
||||
return;
|
||||
}
|
||||
|
||||
final GzipResponseWrapper wrappedResponse=newGzipResponseWrapper(request,response);
|
||||
|
||||
CompressedResponseWrapper wrappedResponse = createWrappedResponse(request,response,compressionType);
|
||||
|
||||
boolean exceptional=true;
|
||||
try
|
||||
|
@ -186,28 +231,12 @@ public class GzipFilter extends UserAgentFilter
|
|||
Continuation continuation = ContinuationSupport.getContinuation(request);
|
||||
if (continuation.isSuspended() && continuation.isResponseWrapped())
|
||||
{
|
||||
continuation.addContinuationListener(new ContinuationListener()
|
||||
{
|
||||
public void onComplete(Continuation continuation)
|
||||
{
|
||||
try
|
||||
{
|
||||
wrappedResponse.finish();
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void onTimeout(Continuation continuation)
|
||||
{}
|
||||
});
|
||||
continuation.addContinuationListener(new ContinuationListenerWaitingForWrappedResponseToFinish(wrappedResponse));
|
||||
}
|
||||
else if (exceptional && !response.isCommitted())
|
||||
{
|
||||
wrappedResponse.resetBuffer();
|
||||
wrappedResponse.noGzip();
|
||||
wrappedResponse.noCompression();
|
||||
}
|
||||
else
|
||||
wrappedResponse.finish();
|
||||
|
@ -218,9 +247,104 @@ public class GzipFilter extends UserAgentFilter
|
|||
super.doFilter(request,response,chain);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private String selectCompression(String encodingHeader)
|
||||
{
|
||||
// TODO, this could be a little more robust.
|
||||
// prefer gzip over deflate
|
||||
if (encodingHeader!=null)
|
||||
{
|
||||
if (encodingHeader.toLowerCase().contains(GZIP))
|
||||
return GZIP;
|
||||
else if (encodingHeader.toLowerCase().contains(DEFLATE))
|
||||
return DEFLATE;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected CompressedResponseWrapper createWrappedResponse(HttpServletRequest request, HttpServletResponse response, final String compressionType)
|
||||
{
|
||||
CompressedResponseWrapper wrappedResponse = null;
|
||||
if (compressionType.equals(GZIP))
|
||||
{
|
||||
wrappedResponse = new CompressedResponseWrapper(request,response)
|
||||
{
|
||||
@Override
|
||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
|
||||
{
|
||||
return new AbstractCompressedStream(compressionType,request,response,contentLength,bufferSize,minCompressSize)
|
||||
{
|
||||
@Override
|
||||
protected DeflaterOutputStream createStream() throws IOException
|
||||
{
|
||||
return new GZIPOutputStream(_response.getOutputStream(),_bufferSize);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
else if (compressionType.equals(DEFLATE))
|
||||
{
|
||||
wrappedResponse = new CompressedResponseWrapper(request,response)
|
||||
{
|
||||
@Override
|
||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
|
||||
{
|
||||
return new AbstractCompressedStream(compressionType,request,response,contentLength,bufferSize,minCompressSize)
|
||||
{
|
||||
@Override
|
||||
protected DeflaterOutputStream createStream() throws IOException
|
||||
{
|
||||
return new DeflaterOutputStream(_response.getOutputStream(),new Deflater(_deflateCompressionLevel,_deflateNoWrap));
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException(compressionType + " not supported");
|
||||
}
|
||||
configureWrappedResponse(wrappedResponse);
|
||||
return wrappedResponse;
|
||||
}
|
||||
|
||||
protected void configureWrappedResponse(CompressedResponseWrapper wrappedResponse)
|
||||
{
|
||||
wrappedResponse.setMimeTypes(_mimeTypes);
|
||||
wrappedResponse.setBufferSize(_bufferSize);
|
||||
wrappedResponse.setMinCompressSize(_minGzipSize);
|
||||
}
|
||||
|
||||
private class ContinuationListenerWaitingForWrappedResponseToFinish implements ContinuationListener{
|
||||
|
||||
private CompressedResponseWrapper wrappedResponse;
|
||||
|
||||
public ContinuationListenerWaitingForWrappedResponseToFinish(CompressedResponseWrapper wrappedResponse)
|
||||
{
|
||||
this.wrappedResponse = wrappedResponse;
|
||||
}
|
||||
|
||||
public void onComplete(Continuation continuation)
|
||||
{
|
||||
try
|
||||
{
|
||||
wrappedResponse.finish();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void onTimeout(Continuation continuation)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the UserAgent is excluded
|
||||
* Checks to see if the userAgent is excluded
|
||||
*
|
||||
* @param ua
|
||||
* the user agent
|
||||
|
@ -238,7 +362,7 @@ public class GzipFilter extends UserAgentFilter
|
|||
return true;
|
||||
}
|
||||
}
|
||||
else if (_excludedAgentPatterns != null)
|
||||
if (_excludedAgentPatterns != null)
|
||||
{
|
||||
for (Pattern pattern : _excludedAgentPatterns)
|
||||
{
|
||||
|
@ -253,9 +377,9 @@ public class GzipFilter extends UserAgentFilter
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the Path is excluded
|
||||
* Checks to see if the path is excluded
|
||||
*
|
||||
* @param ua
|
||||
* @param requestURI
|
||||
* the request uri
|
||||
* @return boolean true if excluded
|
||||
*/
|
||||
|
@ -263,6 +387,16 @@ public class GzipFilter extends UserAgentFilter
|
|||
{
|
||||
if (requestURI == null)
|
||||
return false;
|
||||
if (_excludedPaths != null)
|
||||
{
|
||||
for (String excludedPath : _excludedPaths)
|
||||
{
|
||||
if (requestURI.startsWith(excludedPath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_excludedPathPatterns != null)
|
||||
{
|
||||
for (Pattern pattern : _excludedPathPatterns)
|
||||
|
@ -275,42 +409,4 @@ public class GzipFilter extends UserAgentFilter
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows derived implementations to replace ResponseWrapper implementation.
|
||||
*
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
* @return the gzip response wrapper
|
||||
*/
|
||||
protected GzipResponseWrapper newGzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
return new GzipResponseWrapper(request, response)
|
||||
{
|
||||
{
|
||||
setMimeTypes(GzipFilter.this._mimeTypes);
|
||||
setBufferSize(GzipFilter.this._bufferSize);
|
||||
setMinGzipSize(GzipFilter.this._minGzipSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
|
||||
{
|
||||
return GzipFilter.this.newWriter(out,encoding);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows derived implementations to replace PrintWriter implementation.
|
||||
*
|
||||
* @param out the out
|
||||
* @param encoding the encoding
|
||||
* @return the prints the writer
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
|
||||
{
|
||||
return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,18 +18,19 @@ import java.io.OutputStream;
|
|||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
|
||||
import org.eclipse.jetty.http.gzip.GzipStream;
|
||||
import org.eclipse.jetty.http.gzip.CompressedResponseWrapper;
|
||||
import org.eclipse.jetty.http.gzip.AbstractCompressedStream;
|
||||
import org.eclipse.jetty.io.UncheckedPrintWriter;
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Includable GZip Filter.
|
||||
* This extension to the {@link GzipFilter} that uses Jetty features to allow
|
||||
|
@ -56,61 +57,82 @@ public class IncludableGzipFilter extends GzipFilter
|
|||
_uncheckedPrintWriter=Boolean.valueOf(tmp).booleanValue();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlets.GzipFilter#createWrappedResponse(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
protected GzipResponseWrapper newGzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
protected CompressedResponseWrapper createWrappedResponse(HttpServletRequest request, HttpServletResponse response, final String compressionType)
|
||||
{
|
||||
return new IncludableResponseWrapper(request,response);
|
||||
CompressedResponseWrapper wrappedResponse = null;
|
||||
if (compressionType.equals(GZIP))
|
||||
{
|
||||
wrappedResponse = new IncludableResponseWrapper(request,response)
|
||||
{
|
||||
@Override
|
||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
|
||||
{
|
||||
return new AbstractCompressedStream(compressionType,request,response,contentLength,bufferSize,minCompressSize)
|
||||
{
|
||||
@Override
|
||||
protected DeflaterOutputStream createStream() throws IOException
|
||||
{
|
||||
return new GZIPOutputStream(_response.getOutputStream(),_bufferSize);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
else if (compressionType.equals(DEFLATE))
|
||||
{
|
||||
wrappedResponse = new IncludableResponseWrapper(request,response)
|
||||
{
|
||||
@Override
|
||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
|
||||
{
|
||||
return new AbstractCompressedStream(compressionType,request,response,contentLength,bufferSize,minCompressSize)
|
||||
{
|
||||
@Override
|
||||
protected DeflaterOutputStream createStream() throws IOException
|
||||
{
|
||||
return new DeflaterOutputStream(_response.getOutputStream(),new Deflater(_deflateCompressionLevel, _deflateNoWrap));
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException(compressionType + " not supported");
|
||||
}
|
||||
configureWrappedResponse(wrappedResponse);
|
||||
return wrappedResponse;
|
||||
}
|
||||
|
||||
public class IncludableResponseWrapper extends GzipResponseWrapper
|
||||
|
||||
|
||||
// Extend CompressedResponseWrapper to be able to set headers during include and to create unchecked printwriters
|
||||
private abstract class IncludableResponseWrapper extends CompressedResponseWrapper
|
||||
{
|
||||
public IncludableResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
super(request,response);
|
||||
|
||||
super.setMimeTypes(IncludableGzipFilter.this._mimeTypes);
|
||||
super.setBufferSize(IncludableGzipFilter.this._bufferSize);
|
||||
super.setMinGzipSize(IncludableGzipFilter.this._minGzipSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GzipStream newGzipStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minGzipSize) throws IOException
|
||||
public void setHeader(String name,String value)
|
||||
{
|
||||
return new IncludableGzipStream(request,response,contentLength,bufferSize,minGzipSize);
|
||||
super.setHeader(name,value);
|
||||
HttpServletResponse response = (HttpServletResponse)getResponse();
|
||||
if (!response.containsHeader(name))
|
||||
response.setHeader("org.eclipse.jetty.server.include."+name,value);;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
|
||||
protected PrintWriter newWriter(OutputStream out, String encoding) throws UnsupportedEncodingException
|
||||
{
|
||||
return IncludableGzipFilter.this.newWriter(out,encoding);
|
||||
}
|
||||
}
|
||||
|
||||
public class IncludableGzipStream extends GzipStream
|
||||
{
|
||||
public IncludableGzipStream(HttpServletRequest request, HttpServletResponse response, long contentLength, int bufferSize, int minGzipSize)
|
||||
throws IOException
|
||||
{
|
||||
super(request,response,contentLength,bufferSize,minGzipSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setContentEncodingGzip()
|
||||
{
|
||||
if (_request.getAttribute("javax.servlet.include.request_uri")!=null)
|
||||
_response.setHeader("org.eclipse.jetty.server.include.Content-Encoding", "gzip");
|
||||
else
|
||||
_response.setHeader("Content-Encoding", "gzip");
|
||||
|
||||
return _response.containsHeader("Content-Encoding");
|
||||
if (_uncheckedPrintWriter)
|
||||
return encoding == null?new UncheckedPrintWriter(out):new UncheckedPrintWriter(new OutputStreamWriter(out,encoding));
|
||||
return super.newWriter(out,encoding);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
|
||||
{
|
||||
if (_uncheckedPrintWriter)
|
||||
return encoding==null?new UncheckedPrintWriter(out):new UncheckedPrintWriter(new OutputStreamWriter(out,encoding));
|
||||
return super.newWriter(out,encoding);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,7 +159,11 @@ public class MultiPartFilter implements Filter
|
|||
{
|
||||
request.setAttribute(mp.getName(),mp.getFile());
|
||||
if (mp.getContentDispositionFilename() != null)
|
||||
{
|
||||
params.add(mp.getName(), mp.getContentDispositionFilename());
|
||||
if (mp.getContentType() != null)
|
||||
params.add(mp.getName()+CONTENT_TYPE_SUFFIX, mp.getContentType());
|
||||
}
|
||||
if (_deleteFiles)
|
||||
{
|
||||
mp.getFile().deleteOnExit();
|
||||
|
@ -178,6 +182,8 @@ public class MultiPartFilter implements Filter
|
|||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
IO.copy(p.getInputStream(), bytes);
|
||||
params.add(p.getName(), bytes.toByteArray());
|
||||
if (p.getContentType() != null)
|
||||
params.add(p.getName()+CONTENT_TYPE_SUFFIX, p.getContentType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -330,7 +336,7 @@ public class MultiPartFilter implements Filter
|
|||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
else if (o instanceof String)
|
||||
|
|
|
@ -414,7 +414,7 @@ public class ProxyServlet implements Servlet
|
|||
if (request.getQueryString() != null)
|
||||
uri += "?" + request.getQueryString();
|
||||
|
||||
HttpURI url = proxyHttpURI(request.getScheme(),request.getServerName(),request.getServerPort(),uri);
|
||||
HttpURI url = proxyHttpURI(request,uri);
|
||||
|
||||
if (debug != 0)
|
||||
_log.debug(debug + " proxy " + uri + "-->" + url);
|
||||
|
@ -677,6 +677,11 @@ public class ProxyServlet implements Servlet
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected HttpURI proxyHttpURI(HttpServletRequest request, String uri) throws MalformedURLException
|
||||
{
|
||||
return proxyHttpURI(request.getScheme(), request.getServerName(), request.getServerPort(), uri);
|
||||
}
|
||||
|
||||
protected HttpURI proxyHttpURI(String scheme, String serverName, int serverPort, String uri) throws MalformedURLException
|
||||
{
|
||||
if (!validateDestination(serverName,uri))
|
||||
|
|
|
@ -6,7 +6,7 @@ import java.util.List;
|
|||
import javax.servlet.Servlet;
|
||||
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
|
||||
import org.eclipse.jetty.http.gzip.CompressedResponseWrapper;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlets.gzip.GzipTester;
|
||||
import org.eclipse.jetty.servlets.gzip.TestServletLengthStreamTypeWrite;
|
||||
|
@ -48,32 +48,42 @@ public class GzipFilterContentLengthTest
|
|||
{
|
||||
return Arrays.asList(new Object[][]
|
||||
{
|
||||
{ TestServletLengthStreamTypeWrite.class },
|
||||
{ TestServletLengthTypeStreamWrite.class },
|
||||
{ TestServletStreamLengthTypeWrite.class },
|
||||
{ TestServletStreamTypeLengthWrite.class },
|
||||
{ TestServletTypeLengthStreamWrite.class },
|
||||
{ TestServletTypeStreamLengthWrite.class } });
|
||||
{ TestServletLengthStreamTypeWrite.class, GzipFilter.GZIP },
|
||||
{ TestServletLengthTypeStreamWrite.class, GzipFilter.GZIP },
|
||||
{ TestServletStreamLengthTypeWrite.class, GzipFilter.GZIP },
|
||||
{ TestServletStreamTypeLengthWrite.class, GzipFilter.GZIP },
|
||||
{ TestServletTypeLengthStreamWrite.class, GzipFilter.GZIP },
|
||||
{ TestServletTypeStreamLengthWrite.class, GzipFilter.GZIP },
|
||||
{ TestServletLengthStreamTypeWrite.class, GzipFilter.DEFLATE },
|
||||
{ TestServletLengthTypeStreamWrite.class, GzipFilter.DEFLATE },
|
||||
{ TestServletStreamLengthTypeWrite.class, GzipFilter.DEFLATE },
|
||||
{ TestServletStreamTypeLengthWrite.class, GzipFilter.DEFLATE },
|
||||
{ TestServletTypeLengthStreamWrite.class, GzipFilter.DEFLATE },
|
||||
{ TestServletTypeStreamLengthWrite.class, GzipFilter.DEFLATE }
|
||||
});
|
||||
}
|
||||
|
||||
private static final int LARGE = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 8;
|
||||
private static final int MEDIUM = GzipResponseWrapper.DEFAULT_BUFFER_SIZE;
|
||||
private static final int SMALL = GzipResponseWrapper.DEFAULT_BUFFER_SIZE / 4;
|
||||
private static final int TINY = GzipResponseWrapper.DEFAULT_MIN_GZIP_SIZE / 2;
|
||||
private static final int LARGE = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE * 8;
|
||||
private static final int MEDIUM = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE;
|
||||
private static final int SMALL = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE / 4;
|
||||
private static final int TINY = CompressedResponseWrapper.DEFAULT_MIN_COMPRESS_SIZE/ 2;
|
||||
|
||||
private String compressionType;
|
||||
|
||||
public GzipFilterContentLengthTest(Class<? extends Servlet> testServlet, String compressionType)
|
||||
{
|
||||
this.testServlet = testServlet;
|
||||
this.compressionType = compressionType;
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestingDir testingdir = new TestingDir();
|
||||
|
||||
private Class<? extends Servlet> testServlet;
|
||||
|
||||
public GzipFilterContentLengthTest(Class<? extends Servlet> testServlet)
|
||||
{
|
||||
this.testServlet = testServlet;
|
||||
}
|
||||
|
||||
private void assertIsGzipCompressed(String filename, int filesize) throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
File testfile = tester.prepareServerFile(testServlet.getSimpleName() + "-" + filename,filesize);
|
||||
|
||||
|
@ -93,7 +103,7 @@ public class GzipFilterContentLengthTest
|
|||
|
||||
private void assertIsNotGzipCompressed(String filename, int filesize) throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
File testfile = tester.prepareServerFile(testServlet.getSimpleName() + "-" + filename,filesize);
|
||||
|
||||
|
|
|
@ -31,22 +31,41 @@ public class GzipFilterDefaultNoRecompressTest
|
|||
return Arrays.asList(new Object[][]
|
||||
{
|
||||
// Some already compressed files
|
||||
{ "test_quotes.gz", "application/gzip" },
|
||||
{ "test_quotes.bz2", "application/bzip2" },
|
||||
{ "test_quotes.zip", "application/zip" },
|
||||
{ "test_quotes.rar", "application/octet-stream" },
|
||||
{ "test_quotes.gz", "application/gzip", GzipFilter.GZIP },
|
||||
{ "test_quotes.bz2", "application/bzip2", GzipFilter.GZIP },
|
||||
{ "test_quotes.zip", "application/zip", GzipFilter.GZIP },
|
||||
{ "test_quotes.rar", "application/octet-stream", GzipFilter.GZIP },
|
||||
// Some images (common first)
|
||||
{ "jetty_logo.png", "image/png" },
|
||||
{ "jetty_logo.gif", "image/gif" },
|
||||
{ "jetty_logo.jpeg", "image/jpeg" },
|
||||
{ "jetty_logo.jpg", "image/jpeg" },
|
||||
{ "jetty_logo.png", "image/png", GzipFilter.GZIP },
|
||||
{ "jetty_logo.gif", "image/gif", GzipFilter.GZIP },
|
||||
{ "jetty_logo.jpeg", "image/jpeg", GzipFilter.GZIP },
|
||||
{ "jetty_logo.jpg", "image/jpeg", GzipFilter.GZIP },
|
||||
// Lesser encountered images (usually found being requested from non-browser clients)
|
||||
{ "jetty_logo.bmp", "image/bmp" },
|
||||
{ "jetty_logo.tga", "application/tga" },
|
||||
{ "jetty_logo.tif", "image/tiff" },
|
||||
{ "jetty_logo.tiff", "image/tiff" },
|
||||
{ "jetty_logo.xcf", "image/xcf" },
|
||||
{ "jetty_logo.jp2", "image/jpeg2000" } });
|
||||
{ "jetty_logo.bmp", "image/bmp", GzipFilter.GZIP },
|
||||
{ "jetty_logo.tga", "application/tga", GzipFilter.GZIP },
|
||||
{ "jetty_logo.tif", "image/tiff", GzipFilter.GZIP },
|
||||
{ "jetty_logo.tiff", "image/tiff", GzipFilter.GZIP },
|
||||
{ "jetty_logo.xcf", "image/xcf", GzipFilter.GZIP },
|
||||
{ "jetty_logo.jp2", "image/jpeg2000", GzipFilter.GZIP },
|
||||
|
||||
// Same tests again for deflate
|
||||
// Some already compressed files
|
||||
{ "test_quotes.gz", "application/gzip", GzipFilter.DEFLATE },
|
||||
{ "test_quotes.bz2", "application/bzip2", GzipFilter.DEFLATE },
|
||||
{ "test_quotes.zip", "application/zip", GzipFilter.DEFLATE },
|
||||
{ "test_quotes.rar", "application/octet-stream", GzipFilter.DEFLATE },
|
||||
// Some images (common first)
|
||||
{ "jetty_logo.png", "image/png", GzipFilter.DEFLATE },
|
||||
{ "jetty_logo.gif", "image/gif", GzipFilter.DEFLATE },
|
||||
{ "jetty_logo.jpeg", "image/jpeg", GzipFilter.DEFLATE },
|
||||
{ "jetty_logo.jpg", "image/jpeg", GzipFilter.DEFLATE },
|
||||
// Lesser encountered images (usually found being requested from non-browser clients)
|
||||
{ "jetty_logo.bmp", "image/bmp", GzipFilter.DEFLATE },
|
||||
{ "jetty_logo.tga", "application/tga", GzipFilter.DEFLATE },
|
||||
{ "jetty_logo.tif", "image/tiff", GzipFilter.DEFLATE },
|
||||
{ "jetty_logo.tiff", "image/tiff", GzipFilter.DEFLATE },
|
||||
{ "jetty_logo.xcf", "image/xcf", GzipFilter.DEFLATE },
|
||||
{ "jetty_logo.jp2", "image/jpeg2000", GzipFilter.DEFLATE } });
|
||||
}
|
||||
|
||||
@Rule
|
||||
|
@ -54,17 +73,19 @@ public class GzipFilterDefaultNoRecompressTest
|
|||
|
||||
private String alreadyCompressedFilename;
|
||||
private String expectedContentType;
|
||||
private String compressionType;
|
||||
|
||||
public GzipFilterDefaultNoRecompressTest(String testFilename, String expectedContentType)
|
||||
public GzipFilterDefaultNoRecompressTest(String testFilename, String expectedContentType, String compressionType)
|
||||
{
|
||||
this.alreadyCompressedFilename = testFilename;
|
||||
this.expectedContentType = expectedContentType;
|
||||
this.compressionType = compressionType;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotGzipFiltered_Default_AlreadyCompressed() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
copyTestFileToServer(alreadyCompressedFilename);
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package org.eclipse.jetty.servlets;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
|
@ -8,23 +10,46 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
|
||||
import org.eclipse.jetty.http.gzip.CompressedResponseWrapper;
|
||||
import org.eclipse.jetty.servlet.DefaultServlet;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlets.gzip.GzipTester;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
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 GzipFilter support built into the {@link DefaultServlet}
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class GzipFilterDefaultTest
|
||||
{
|
||||
@Parameters
|
||||
public static Collection<String[]> data()
|
||||
{
|
||||
String[][] data = new String[][]
|
||||
{
|
||||
{ GzipFilter.GZIP },
|
||||
{ GzipFilter.DEFLATE } };
|
||||
|
||||
return Arrays.asList(data);
|
||||
}
|
||||
|
||||
private String compressionType;
|
||||
|
||||
public GzipFilterDefaultTest(String compressionType)
|
||||
{
|
||||
this.compressionType = compressionType;
|
||||
}
|
||||
|
||||
|
||||
public static class HttpStatusServlet extends HttpServlet
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int _status = 204;
|
||||
|
||||
public HttpStatusServlet()
|
||||
|
@ -50,10 +75,10 @@ public class GzipFilterDefaultTest
|
|||
@Test
|
||||
public void testIsGzipCompressedTiny() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
// Test content that is smaller than the buffer.
|
||||
int filesize = GzipResponseWrapper.DEFAULT_BUFFER_SIZE / 4;
|
||||
int filesize = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE / 4;
|
||||
tester.prepareServerFile("file.txt",filesize);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(org.eclipse.jetty.servlet.DefaultServlet.class);
|
||||
|
@ -73,10 +98,10 @@ public class GzipFilterDefaultTest
|
|||
@Test
|
||||
public void testIsGzipCompressedLarge() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
// Test content that is smaller than the buffer.
|
||||
int filesize = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
|
||||
int filesize = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
|
||||
tester.prepareServerFile("file.txt",filesize);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(org.eclipse.jetty.servlet.DefaultServlet.class);
|
||||
|
@ -96,10 +121,10 @@ public class GzipFilterDefaultTest
|
|||
@Test
|
||||
public void testIsNotGzipCompressed() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
// Test content that is smaller than the buffer.
|
||||
int filesize = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
|
||||
int filesize = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
|
||||
tester.prepareServerFile("file.mp3",filesize);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(org.eclipse.jetty.servlet.DefaultServlet.class);
|
||||
|
@ -119,7 +144,7 @@ public class GzipFilterDefaultTest
|
|||
@Test
|
||||
public void testIsNotGzipCompressedHttpStatus() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
// Test error code 204
|
||||
FilterHolder holder = tester.setContentServlet(HttpStatusServlet.class);
|
||||
|
@ -140,20 +165,88 @@ public class GzipFilterDefaultTest
|
|||
@Test
|
||||
public void testUserAgentExclusion() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
|
||||
GzipTester tester = new GzipTester(testingdir,compressionType);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(DefaultServlet.class);
|
||||
holder.setInitParameter("excludedAgents", "foo");
|
||||
holder.setInitParameter("excludedAgents","foo");
|
||||
tester.setUserAgent("foo");
|
||||
|
||||
int filesize = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
|
||||
|
||||
int filesize = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
|
||||
tester.prepareServerFile("file.txt",filesize);
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
tester.start();
|
||||
tester.assertIsResponseNotGzipCompressed("file.txt", filesize, HttpStatus.OK_200);
|
||||
}
|
||||
tester.assertIsResponseNotGzipCompressed("file.txt",filesize,HttpStatus.OK_200);
|
||||
}
|
||||
finally
|
||||
{
|
||||
tester.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserAgentExclusionByExcludedAgentPatterns() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir,compressionType);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(DefaultServlet.class);
|
||||
holder.setInitParameter("excludedAgents","bar");
|
||||
holder.setInitParameter("excludeAgentPatterns","fo.*");
|
||||
tester.setUserAgent("foo");
|
||||
|
||||
int filesize = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
|
||||
tester.prepareServerFile("file.txt",filesize);
|
||||
|
||||
try
|
||||
{
|
||||
tester.start();
|
||||
tester.assertIsResponseNotGzipCompressed("file.txt",filesize,HttpStatus.OK_200);
|
||||
}
|
||||
finally
|
||||
{
|
||||
tester.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExcludePaths() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir,compressionType);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(DefaultServlet.class);
|
||||
holder.setInitParameter("excludePaths","/context/");
|
||||
|
||||
int filesize = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
|
||||
tester.prepareServerFile("file.txt",filesize);
|
||||
|
||||
try
|
||||
{
|
||||
tester.start();
|
||||
tester.assertIsResponseNotGzipCompressed("file.txt",filesize,HttpStatus.OK_200);
|
||||
}
|
||||
finally
|
||||
{
|
||||
tester.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExcludePathPatterns() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir,compressionType);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(DefaultServlet.class);
|
||||
holder.setInitParameter("excludePathPatterns","/cont.*");
|
||||
|
||||
int filesize = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
|
||||
tester.prepareServerFile("file.txt",filesize);
|
||||
|
||||
try
|
||||
{
|
||||
tester.start();
|
||||
tester.assertIsResponseNotGzipCompressed("file.txt",filesize,HttpStatus.OK_200);
|
||||
}
|
||||
finally
|
||||
{
|
||||
tester.stop();
|
||||
|
|
|
@ -1,18 +1,29 @@
|
|||
package org.eclipse.jetty.servlets;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
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.EnumSet;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
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;
|
||||
|
||||
|
@ -28,21 +39,46 @@ 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.Assert;
|
||||
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
|
||||
|
@ -89,7 +125,7 @@ public class GzipWithPipeliningTest
|
|||
testingdir.ensureEmpty();
|
||||
File outputDir = testingdir.getDir();
|
||||
|
||||
PipelineHelper client = new PipelineHelper(serverUri);
|
||||
PipelineHelper client = new PipelineHelper(serverUri, encodingHeader);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -98,7 +134,7 @@ public class GzipWithPipeliningTest
|
|||
|
||||
// Size of content, as it exists on disk, without gzip compression.
|
||||
long rawsize = txtFile.length() + pngFile.length();
|
||||
Assert.assertThat("Ensure that we have sufficient file size to trigger chunking",rawsize,greaterThan(300000L));
|
||||
assertThat("Ensure that we have sufficient file size to trigger chunking",rawsize,greaterThan(300000L));
|
||||
|
||||
String respHeader;
|
||||
|
||||
|
@ -109,8 +145,9 @@ public class GzipWithPipeliningTest
|
|||
|
||||
respHeader = client.readResponseHeader();
|
||||
System.out.println("Response Header #1 --\n" + respHeader);
|
||||
Assert.assertThat("Content-Encoding should be gzipped",respHeader,containsString("Content-Encoding: gzip\r\n"));
|
||||
Assert.assertThat("Transfer-Encoding should be chunked",respHeader,containsString("Transfer-Encoding: chunked\r\n"));
|
||||
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");
|
||||
|
@ -121,7 +158,7 @@ public class GzipWithPipeliningTest
|
|||
|
||||
// Read only 20% - intentionally a partial read.
|
||||
System.out.println("Attempting to read partial content ...");
|
||||
int readBytes = client.readBody(rawOutputStream,(int)((float)chunkSize * 0.20f));
|
||||
int readBytes = client.readBody(rawOutputStream,(int)(chunkSize * 0.20f));
|
||||
System.out.printf("Read %,d bytes%n",readBytes);
|
||||
|
||||
// Issue another request
|
||||
|
@ -136,14 +173,14 @@ public class GzipWithPipeliningTest
|
|||
readBytes = client.readBody(rawOutputStream,(int)chunkSize);
|
||||
System.out.printf("Read %,d bytes%n",readBytes);
|
||||
line = client.readLine();
|
||||
Assert.assertThat("Chunk delim should be an empty line with CR+LF",line,is(""));
|
||||
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();
|
||||
Assert.assertThat("Inter-pipeline delim should be an empty line with CR+LF",line,is(""));
|
||||
assertThat("Inter-pipeline delim should be an empty line with CR+LF",line,is(""));
|
||||
|
||||
// Sha1tracking for 1st Request
|
||||
MessageDigest digestTxt = MessageDigest.getInstance("SHA1");
|
||||
|
@ -152,14 +189,23 @@ public class GzipWithPipeliningTest
|
|||
// Decompress 1st request and calculate sha1sum
|
||||
IO.close(rawOutputStream);
|
||||
FileInputStream rawInputStream = new FileInputStream(rawOutputFile);
|
||||
GZIPInputStream ungzipStream = new GZIPInputStream(rawInputStream);
|
||||
IO.copy(ungzipStream, digesterTxt);
|
||||
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);
|
||||
Assert.assertThat("Content-Encoding should NOT be gzipped",respHeader,not(containsString("Content-Encoding: gzip\r\n")));
|
||||
Assert.assertThat("Transfer-Encoding should NOT be chunked",respHeader,not(containsString("Transfer-Encoding: chunked\r\n")));
|
||||
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");
|
||||
|
@ -167,7 +213,7 @@ public class GzipWithPipeliningTest
|
|||
|
||||
// Read 2nd request body
|
||||
int contentLength = client.getContentLength(respHeader);
|
||||
Assert.assertThat("Image Content Length",(long)contentLength,is(pngFile.length()));
|
||||
assertThat("Image Content Length",(long)contentLength,is(pngFile.length()));
|
||||
client.readBody(digesterImg,contentLength);
|
||||
|
||||
// Validate checksums
|
||||
|
@ -186,7 +232,7 @@ public class GzipWithPipeliningTest
|
|||
{
|
||||
String expectedSha1 = loadSha1sum(testResourceFile + ".sha1");
|
||||
String actualSha1 = Hex.asHex(digest.digest());
|
||||
Assert.assertEquals(testResourceFile + " / SHA1Sum of content",expectedSha1,actualSha1);
|
||||
assertEquals(testResourceFile + " / SHA1Sum of content",expectedSha1,actualSha1);
|
||||
}
|
||||
|
||||
private String loadSha1sum(String testResourceSha1Sum) throws IOException
|
||||
|
@ -195,7 +241,7 @@ public class GzipWithPipeliningTest
|
|||
String contents = IO.readToString(sha1File);
|
||||
Pattern pat = Pattern.compile("^[0-9A-Fa-f]*");
|
||||
Matcher mat = pat.matcher(contents);
|
||||
Assert.assertTrue("Should have found HEX code in SHA1 file: " + sha1File,mat.find());
|
||||
assertTrue("Should have found HEX code in SHA1 file: " + sha1File,mat.find());
|
||||
return mat.group();
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
|
||||
package org.eclipse.jetty.servlets;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
|
@ -21,6 +24,9 @@ import org.eclipse.jetty.servlets.gzip.TestMinGzipSizeServlet;
|
|||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
/**
|
||||
* Perform specific tests on the IncludableGzipFilter's ability to manage
|
||||
|
@ -28,17 +34,36 @@ import org.junit.Test;
|
|||
*
|
||||
* @see <a href="Eclipse Bug 366106">http://bugs.eclipse.org/366106</a>
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class IncludableGzipFilterMinSizeTest
|
||||
{
|
||||
@Parameters
|
||||
public static Collection<String[]> data()
|
||||
{
|
||||
String[][] data = new String[][]
|
||||
{
|
||||
{ GzipFilter.GZIP },
|
||||
{ GzipFilter.DEFLATE }
|
||||
};
|
||||
|
||||
return Arrays.asList(data);
|
||||
}
|
||||
|
||||
public IncludableGzipFilterMinSizeTest(String compressionType)
|
||||
{
|
||||
this.compressionType = compressionType;
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestingDir testdir = new TestingDir();
|
||||
|
||||
private String compressionType;
|
||||
private Class<? extends Servlet> testServlet = TestMinGzipSizeServlet.class;
|
||||
|
||||
@Test
|
||||
public void testUnderMinSize() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testdir);
|
||||
GzipTester tester = new GzipTester(testdir, compressionType);
|
||||
// Use IncludableGzipFilter
|
||||
tester.setGzipFilterClass(IncludableGzipFilter.class);
|
||||
|
||||
|
@ -64,7 +89,7 @@ public class IncludableGzipFilterMinSizeTest
|
|||
@Test
|
||||
public void testOverMinSize() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testdir);
|
||||
GzipTester tester = new GzipTester(testdir, compressionType);
|
||||
// Use IncludableGzipFilter
|
||||
tester.setGzipFilterClass(IncludableGzipFilter.class);
|
||||
|
||||
|
|
|
@ -22,7 +22,11 @@ import java.io.ByteArrayOutputStream;
|
|||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.Inflater;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
@ -36,9 +40,28 @@ 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;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class IncludableGzipFilterTest
|
||||
{
|
||||
@Parameters
|
||||
public static Collection<String[]> data()
|
||||
{
|
||||
String[][] data = new String[][]
|
||||
{
|
||||
{ GzipFilter.GZIP },
|
||||
{ GzipFilter.DEFLATE }
|
||||
};
|
||||
|
||||
return Arrays.asList(data);
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestingDir testdir = new TestingDir();
|
||||
|
||||
private static String __content =
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "+
|
||||
"Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "+
|
||||
|
@ -53,11 +76,14 @@ public class IncludableGzipFilterTest
|
|||
"Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "+
|
||||
"et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
|
||||
|
||||
@Rule
|
||||
public TestingDir testdir = new TestingDir();
|
||||
|
||||
private ServletTester tester;
|
||||
|
||||
private String compressionType;
|
||||
|
||||
public IncludableGzipFilterTest(String compressionType)
|
||||
{
|
||||
this.compressionType = compressionType;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
|
@ -95,7 +121,7 @@ public class IncludableGzipFilterTest
|
|||
request.setMethod("GET");
|
||||
request.setVersion("HTTP/1.0");
|
||||
request.setHeader("Host","tester");
|
||||
request.setHeader("accept-encoding","gzip");
|
||||
request.setHeader("accept-encoding", compressionType);
|
||||
request.setURI("/context/file.txt");
|
||||
|
||||
ByteArrayBuffer reqsBuff = new ByteArrayBuffer(request.generate().getBytes());
|
||||
|
@ -103,10 +129,19 @@ public class IncludableGzipFilterTest
|
|||
response.parse(respBuff.asArray());
|
||||
|
||||
assertTrue(response.getMethod()==null);
|
||||
assertTrue(response.getHeader("Content-Encoding").equalsIgnoreCase("gzip"));
|
||||
assertTrue(response.getHeader("Content-Encoding").equalsIgnoreCase(compressionType));
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
|
||||
InputStream testIn = new GZIPInputStream(new ByteArrayInputStream(response.getContentBytes()));
|
||||
InputStream testIn = null;
|
||||
ByteArrayInputStream compressedResponseStream = new ByteArrayInputStream(response.getContentBytes());
|
||||
if (compressionType.equals(GzipFilter.GZIP))
|
||||
{
|
||||
testIn = new GZIPInputStream(compressedResponseStream);
|
||||
}
|
||||
else if (compressionType.equals(GzipFilter.DEFLATE))
|
||||
{
|
||||
testIn = new InflaterInputStream(compressedResponseStream, new Inflater(true));
|
||||
}
|
||||
ByteArrayOutputStream testOut = new ByteArrayOutputStream();
|
||||
IO.copy(testIn,testOut);
|
||||
|
||||
|
|
|
@ -47,7 +47,19 @@ public class MultipartFilterTest
|
|||
private ServletTester tester;
|
||||
|
||||
|
||||
|
||||
public static class TestServlet extends DumpServlet
|
||||
{
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
|
||||
{
|
||||
assertNotNull(req.getParameter("fileup"));
|
||||
assertNotNull(req.getParameter("fileup"+MultiPartFilter.CONTENT_TYPE_SUFFIX));
|
||||
assertEquals(req.getParameter("fileup"+MultiPartFilter.CONTENT_TYPE_SUFFIX), "application/octet-stream");
|
||||
super.doPost(req, resp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -63,7 +75,7 @@ public class MultipartFilterTest
|
|||
tester=new ServletTester();
|
||||
tester.setContextPath("/context");
|
||||
tester.setResourceBase(_dir.getCanonicalPath());
|
||||
tester.addServlet(DumpServlet.class, "/");
|
||||
tester.addServlet(TestServlet.class, "/");
|
||||
tester.setAttribute("javax.servlet.context.tempdir", _dir);
|
||||
FilterHolder multipartFilter = tester.addFilter(MultiPartFilter.class,"/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
multipartFilter.setInitParameter("deleteFiles", "true");
|
||||
|
@ -253,7 +265,6 @@ public class MultipartFilterTest
|
|||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
|
||||
{
|
||||
assertEquals("How now brown cow.", req.getParameterMap().get("strupContent-Type:"));
|
||||
|
||||
super.doPost(req, resp);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,8 +25,9 @@ public class PipelineHelper
|
|||
private Socket socket;
|
||||
private OutputStream outputStream;
|
||||
private InputStream inputStream;
|
||||
private String encodingHeader;
|
||||
|
||||
public PipelineHelper(URI uri)
|
||||
public PipelineHelper(URI uri, String encodingHeader)
|
||||
{
|
||||
if (LOG instanceof StdErrLog)
|
||||
{
|
||||
|
@ -34,6 +35,7 @@ public class PipelineHelper
|
|||
}
|
||||
this.uri = uri;
|
||||
this.endpoint = new InetSocketAddress(uri.getHost(),uri.getPort());
|
||||
this.encodingHeader = encodingHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -76,7 +78,7 @@ public class PipelineHelper
|
|||
req.append("Accept-Language: en-us\r\n");
|
||||
if (acceptGzipped)
|
||||
{
|
||||
req.append("Accept-Encoding: gzip, deflate\r\n");
|
||||
req.append("Accept-Encoding: " + encodingHeader + "\r\n");
|
||||
}
|
||||
req.append("Cookie: JSESSIONID=spqx8v8szylt1336t96vc6mw0\r\n");
|
||||
if ( close )
|
||||
|
@ -134,7 +136,7 @@ public class PipelineHelper
|
|||
while (!(foundCR && foundLF))
|
||||
{
|
||||
b = inputStream.read();
|
||||
Assert.assertThat("Should not have hit EOL (yet) during chunk size read",(int)b,not(-1));
|
||||
Assert.assertThat("Should not have hit EOL (yet) during chunk size read",b,not(-1));
|
||||
if (b == 0x0D)
|
||||
{
|
||||
foundCR = true;
|
||||
|
@ -163,7 +165,7 @@ public class PipelineHelper
|
|||
while (!(foundCR && foundLF))
|
||||
{
|
||||
b = inputStream.read();
|
||||
Assert.assertThat("Should not have hit EOL (yet) during chunk size read",(int)b,not(-1));
|
||||
Assert.assertThat("Should not have hit EOL (yet) during chunk size read",b,not(-1));
|
||||
if (b == 0x0D)
|
||||
{
|
||||
foundCR = true;
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
package org.eclipse.jetty.servlets.gzip;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
|
@ -13,8 +21,10 @@ import java.util.Enumeration;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import java.util.zip.Inflater;
|
||||
import javax.servlet.DispatcherType;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
@ -29,12 +39,6 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
|||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.junit.Assert;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
public class GzipTester
|
||||
{
|
||||
private Class<? extends GzipFilter> gzipFilterClass = GzipFilter.class;
|
||||
|
@ -42,10 +46,12 @@ public class GzipTester
|
|||
private String userAgent = null;
|
||||
private ServletTester servletTester;
|
||||
private TestingDir testdir;
|
||||
private String compressionType;
|
||||
|
||||
public GzipTester(TestingDir testingdir)
|
||||
public GzipTester(TestingDir testingdir, String compressionType)
|
||||
{
|
||||
this.testdir = testingdir;
|
||||
this.compressionType = compressionType;
|
||||
// Make sure we start with a clean testing directory.
|
||||
// DOES NOT WORK IN WINDOWS - this.testdir.ensureEmpty();
|
||||
}
|
||||
|
@ -64,7 +70,7 @@ public class GzipTester
|
|||
request.setMethod("GET");
|
||||
request.setVersion("HTTP/1.0");
|
||||
request.setHeader("Host","tester");
|
||||
request.setHeader("Accept-Encoding","gzip");
|
||||
request.setHeader("Accept-Encoding",compressionType);
|
||||
if (this.userAgent != null)
|
||||
request.setHeader("User-Agent", this.userAgent);
|
||||
request.setURI("/context/" + requestedFilename);
|
||||
|
@ -79,7 +85,7 @@ public class GzipTester
|
|||
Assert.assertThat("Response.method",response.getMethod(),nullValue());
|
||||
Assert.assertThat("Response.status",response.getStatus(),is(HttpServletResponse.SC_OK));
|
||||
Assert.assertThat("Response.header[Content-Length]",response.getHeader("Content-Length"),notNullValue());
|
||||
Assert.assertThat("Response.header[Content-Encoding]",response.getHeader("Content-Encoding"),containsString("gzip"));
|
||||
Assert.assertThat("Response.header[Content-Encoding]",response.getHeader("Content-Encoding"),containsString(compressionType));
|
||||
|
||||
// Assert that the decompressed contents are what we expect.
|
||||
File serverFile = testdir.getFile(serverFilename);
|
||||
|
@ -92,12 +98,19 @@ public class GzipTester
|
|||
try
|
||||
{
|
||||
bais = new ByteArrayInputStream(response.getContentBytes());
|
||||
in = new GZIPInputStream(bais);
|
||||
if (compressionType.equals(GzipFilter.GZIP))
|
||||
{
|
||||
in = new GZIPInputStream(bais);
|
||||
}
|
||||
else if (compressionType.equals(GzipFilter.DEFLATE))
|
||||
{
|
||||
in = new InflaterInputStream(bais, new Inflater(true));
|
||||
}
|
||||
out = new ByteArrayOutputStream();
|
||||
IO.copy(in,out);
|
||||
|
||||
actual = out.toString(encoding);
|
||||
Assert.assertEquals("Uncompressed contents",expected,actual);
|
||||
assertThat("Uncompressed contents",actual,equalTo(expected));
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -131,7 +144,7 @@ public class GzipTester
|
|||
request.setMethod("GET");
|
||||
request.setVersion("HTTP/1.0");
|
||||
request.setHeader("Host","tester");
|
||||
request.setHeader("Accept-Encoding","gzip");
|
||||
request.setHeader("Accept-Encoding",compressionType);
|
||||
if (this.userAgent != null)
|
||||
request.setHeader("User-Agent", this.userAgent);
|
||||
request.setURI("/context/" + requestedFilename);
|
||||
|
@ -218,7 +231,7 @@ public class GzipTester
|
|||
request.setMethod("GET");
|
||||
request.setVersion("HTTP/1.0");
|
||||
request.setHeader("Host","tester");
|
||||
request.setHeader("Accept-Encoding","gzip");
|
||||
request.setHeader("Accept-Encoding",compressionType);
|
||||
if (this.userAgent != null)
|
||||
request.setHeader("User-Agent", this.userAgent);
|
||||
if (filename == null)
|
||||
|
@ -241,7 +254,7 @@ public class GzipTester
|
|||
int serverLength = Integer.parseInt(response.getHeader("Content-Length"));
|
||||
Assert.assertThat("Response.header[Content-Length]",serverLength,is(expectedFilesize));
|
||||
}
|
||||
Assert.assertThat("Response.header[Content-Encoding]",response.getHeader("Content-Encoding"),not(containsString("gzip")));
|
||||
Assert.assertThat("Response.header[Content-Encoding]",response.getHeader("Content-Encoding"),not(containsString(compressionType)));
|
||||
|
||||
// Assert that the contents are what we expect.
|
||||
if (filename != null)
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
<packaging>pom</packaging>
|
||||
<name>Jetty :: SPDY :: Parent</name>
|
||||
|
||||
<properties>
|
||||
<npn.version>1.0.0.v20120402</npn.version>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
<module>spdy-core</module>
|
||||
<module>spdy-jetty</module>
|
||||
|
|
|
@ -12,8 +12,9 @@
|
|||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
|
|
|
@ -35,6 +35,4 @@ public interface ISession extends Session
|
|||
public <C> void control(IStream stream, ControlFrame frame, long timeout, TimeUnit unit, Handler<C> handler, C context);
|
||||
|
||||
public <C> void data(IStream stream, DataInfo dataInfo, long timeout, TimeUnit unit, Handler<C> handler, C context);
|
||||
|
||||
public int getWindowSize();
|
||||
}
|
||||
|
|
|
@ -68,8 +68,9 @@ public interface IStream extends Stream
|
|||
* of true puts the stream into closed state.</p>
|
||||
*
|
||||
* @param close whether the close state should be updated
|
||||
* @param local whether the close is local or remote
|
||||
*/
|
||||
public void updateCloseState(boolean close);
|
||||
public void updateCloseState(boolean close, boolean local);
|
||||
|
||||
/**
|
||||
* <p>Processes the given control frame,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue