Merge branch 'master' into release

This commit is contained in:
Jesse McConnell 2012-03-08 20:43:37 -06:00
commit ec7fc0313c
250 changed files with 17772 additions and 526 deletions

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>example-jetty-embedded</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-all-server</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-all</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-client</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-plus</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-server</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-servlet</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-webapp</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-websocket</artifactId>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-ajp</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-annotations</artifactId>

View File

@ -1,22 +1,19 @@
package org.eclipse.jetty.annotations.resources;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.eclipse.jetty.annotations.AnnotationIntrospector;
import org.eclipse.jetty.annotations.AnnotationParser;
import org.eclipse.jetty.annotations.ClassNameResolver;
import org.eclipse.jetty.annotations.ResourceAnnotationHandler;
import org.eclipse.jetty.annotations.ResourcesAnnotationHandler;
import org.eclipse.jetty.plus.annotation.Injection;
import org.eclipse.jetty.plus.annotation.InjectionCollection;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.MetaData;
import org.eclipse.jetty.webapp.WebAppContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
@ -24,24 +21,39 @@ import static org.junit.Assert.assertNotNull;
public class TestResourceAnnotations
{
Object objA=new Integer(1000);
Object objB=new Integer(2000);
private Server server;
private WebAppContext wac;
private InjectionCollection injections;
private Context comp;
private Context env;
private Object objA = 1000;
private Object objB = 2000;
@Before
public void init() throws Exception
{
server = new Server();
wac = new WebAppContext();
wac.setServer(server);
injections = new InjectionCollection();
wac.setAttribute(InjectionCollection.INJECTION_COLLECTION, injections);
InitialContext ic = new InitialContext();
comp = (Context)ic.lookup("java:comp");
env = comp.createSubcontext("env");
}
@After
public void destroy() throws Exception
{
comp.destroySubcontext("env");
}
@Test
public void testResourceAnnotations ()
throws Exception
{
Server server = new Server();
WebAppContext wac = new WebAppContext();
wac.setServer(server);
InjectionCollection injections = new InjectionCollection();
wac.setAttribute(InjectionCollection.INJECTION_COLLECTION, injections);
InitialContext ic = new InitialContext();
Context comp = (Context)ic.lookup("java:comp");
Context env = comp.createSubcontext("env");
org.eclipse.jetty.plus.jndi.EnvEntry resourceA = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", objA, false);
org.eclipse.jetty.plus.jndi.EnvEntry resourceB = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", objB, false);
new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", objA, false);
new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", objB, false);
AnnotationIntrospector parser = new AnnotationIntrospector();
ResourceAnnotationHandler handler = new ResourceAnnotationHandler(wac);
@ -116,32 +128,21 @@ public class TestResourceAnnotations
f = ResourceA.class.getDeclaredField("n");
f.setAccessible(true);
assertEquals(objB, f.get(binst));
comp.destroySubcontext("env");
}
@Test
public void testResourcesAnnotation ()
throws Exception
{
Server server = new Server();
WebAppContext wac = new WebAppContext();
wac.setServer(server);
InjectionCollection injections = new InjectionCollection();
wac.setAttribute(InjectionCollection.INJECTION_COLLECTION, injections);
InitialContext ic = new InitialContext();
Context comp = (Context)ic.lookup("java:comp");
Context env = comp.createSubcontext("env");
org.eclipse.jetty.plus.jndi.EnvEntry resourceA = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", objA, false);
org.eclipse.jetty.plus.jndi.EnvEntry resourceB = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", objB, false);
new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", objA, false);
new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", objB, false);
AnnotationIntrospector introspector = new AnnotationIntrospector();
ResourcesAnnotationHandler handler = new ResourcesAnnotationHandler(wac);
introspector.registerHandler(handler);
introspector.introspect(ResourceA.class);
introspector.introspect(ResourceB.class);
assertEquals(objA, env.lookup("peach"));
assertEquals(objB, env.lookup("pear"));
}

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -39,7 +39,7 @@ import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Credential;
import org.eclipse.jetty.util.ssl.SslContextFactory;
public class SslCertSecuredExchangeTest extends ContentExchangeTest
public class SslCertSecuredExchangeTest// extends ContentExchangeTest
{
// certificate is valid until Jan 1, 2050
private String _keypath = MavenTestingUtils.getTargetFile("test-policy/validation/jetty-valid.keystore").getAbsolutePath();
@ -51,7 +51,7 @@ public class SslCertSecuredExchangeTest extends ContentExchangeTest
protected void configureServer(Server server)
throws Exception
{
setProtocol("https");
//setProtocol("https");
SslSelectChannelConnector connector = new SslSelectChannelConnector();
SslContextFactory cf = connector.getSslContextFactory();
@ -139,31 +139,31 @@ public class SslCertSecuredExchangeTest extends ContentExchangeTest
ServletContextHandler root = new ServletContextHandler();
root.setContextPath("/");
root.setResourceBase(getBasePath());
// root.setResourceBase(getBasePath());
ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
servletHolder.setInitParameter( "gzip", "true" );
root.addServlet( servletHolder, "/*" );
Handler handler = new TestHandler(getBasePath());
// Handler handler = new TestHandler(getBasePath());
HandlerCollection handlers = new HandlerCollection();
handlers.setHandlers(new Handler[]{handler, root});
// handlers.setHandlers(new Handler[]{handler, root});
security.setHandler(handlers);
}
@Override
protected void configureClient(HttpClient client) throws Exception
{
SslContextFactory cf = client.getSslContextFactory();
cf.setValidateCerts(true);
cf.setCrlPath(_crlpath);
cf.setCertAlias("client");
cf.setKeyStorePath(_clientpath);
cf.setKeyStorePassword(_password);
cf.setKeyManagerPassword(_password);
cf.setTrustStore(_trustpath);
cf.setTrustStorePassword(_password);
}
// @Override
// protected void configureClient(HttpClient client) throws Exception
// {
// SslContextFactory cf = client.getSslContextFactory();
// cf.setValidateCerts(true);
// cf.setCrlPath(_crlpath);
//
// cf.setCertAlias("client");
// cf.setKeyStorePath(_clientpath);
// cf.setKeyStorePassword(_password);
// cf.setKeyManagerPassword(_password);
//
// cf.setTrustStore(_trustpath);
// cf.setTrustStorePassword(_password);
// }
}

View File

@ -17,7 +17,7 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.security.CertificateUtils;
import org.eclipse.jetty.util.ssl.SslContextFactory;
public abstract class SslValidationTestBase extends ContentExchangeTest
public abstract class SslValidationTestBase //extends ContentExchangeTest
{
protected static Class<? extends SslConnector> __klass;
protected static int __konnector;
@ -29,70 +29,70 @@ public abstract class SslValidationTestBase extends ContentExchangeTest
private String _crlpath = MavenTestingUtils.getTargetFile("test-policy/validation/crlfile.pem").getAbsolutePath();
private String _password = "OBF:1wnl1sw01ta01z0f1tae1svy1wml";
@Override
protected void configureServer(Server server)
throws Exception
{
setProtocol("https");
SslContextFactory srvFactory = new SslContextFactory() {
@Override
protected KeyStore getKeyStore(InputStream storeStream, String storePath, String storeType, String storeProvider, String storePassword) throws Exception
{
return CertificateUtils.getKeyStore(storeStream, storePath, storeType, storeProvider, storePassword);
}
@Override
protected Collection<? extends CRL> loadCRL(String crlPath) throws Exception
{
return CertificateUtils.loadCRL(crlPath);
}
};
srvFactory.setValidateCerts(true);
srvFactory.setCrlPath(_crlpath);
srvFactory.setNeedClientAuth(true);
srvFactory.setKeyStorePath(_keypath);
srvFactory.setKeyStorePassword(_password);
srvFactory.setKeyManagerPassword(_password);
srvFactory.setTrustStore(_trustpath);
srvFactory.setTrustStorePassword(_password);
Constructor<? extends SslConnector> constructor = __klass.getConstructor(SslContextFactory.class);
SslConnector connector = constructor.newInstance(srvFactory);
connector.setMaxIdleTime(5000);
server.addConnector(connector);
Handler handler = new TestHandler(getBasePath());
ServletContextHandler root = new ServletContextHandler();
root.setContextPath("/");
root.setResourceBase(getBasePath());
ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
servletHolder.setInitParameter( "gzip", "true" );
root.addServlet( servletHolder, "/*" );
HandlerCollection handlers = new HandlerCollection();
handlers.setHandlers(new Handler[]{handler, root});
server.setHandler( handlers );
}
@Override
protected void configureClient(HttpClient client)
throws Exception
{
client.setConnectorType(__konnector);
SslContextFactory cf = client.getSslContextFactory();
cf.setValidateCerts(true);
cf.setCrlPath(_crlpath);
cf.setKeyStorePath(_clientpath);
cf.setKeyStorePassword(_password);
cf.setKeyManagerPassword(_password);
cf.setTrustStore(_trustpath);
cf.setTrustStorePassword(_password);
// setProtocol("https");
//
// SslContextFactory srvFactory = new SslContextFactory() {
// @Override
// protected KeyStore getKeyStore(InputStream storeStream, String storePath, String storeType, String storeProvider, String storePassword) throws Exception
// {
// return CertificateUtils.getKeyStore(storeStream, storePath, storeType, storeProvider, storePassword);
// }
//
// @Override
// protected Collection<? extends CRL> loadCRL(String crlPath) throws Exception
// {
// return CertificateUtils.loadCRL(crlPath);
// }
// };
// srvFactory.setValidateCerts(true);
// srvFactory.setCrlPath(_crlpath);
// srvFactory.setNeedClientAuth(true);
//
// srvFactory.setKeyStorePath(_keypath);
// srvFactory.setKeyStorePassword(_password);
// srvFactory.setKeyManagerPassword(_password);
//
// srvFactory.setTrustStore(_trustpath);
// srvFactory.setTrustStorePassword(_password);
//
// Constructor<? extends SslConnector> constructor = __klass.getConstructor(SslContextFactory.class);
// SslConnector connector = constructor.newInstance(srvFactory);
// connector.setMaxIdleTime(5000);
// server.addConnector(connector);
//
// Handler handler = new TestHandler(getBasePath());
//
// ServletContextHandler root = new ServletContextHandler();
// root.setContextPath("/");
// root.setResourceBase(getBasePath());
// ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
// servletHolder.setInitParameter( "gzip", "true" );
// root.addServlet( servletHolder, "/*" );
//
// HandlerCollection handlers = new HandlerCollection();
// handlers.setHandlers(new Handler[]{handler, root});
// server.setHandler( handlers );
// }
//
// @Override
// protected void configureClient(HttpClient client)
// throws Exception
// {
// client.setConnectorType(__konnector);
//
// SslContextFactory cf = client.getSslContextFactory();
// cf.setValidateCerts(true);
// cf.setCrlPath(_crlpath);
//
// cf.setKeyStorePath(_clientpath);
// cf.setKeyStorePassword(_password);
// cf.setKeyManagerPassword(_password);
//
// cf.setTrustStore(_trustpath);
// cf.setTrustStorePassword(_password);
}
}

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-continuation</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-deploy</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<artifactId>jetty-distribution</artifactId>
<name>Jetty :: Distribution Assemblies</name>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-http-spi</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-http</artifactId>

View File

@ -106,7 +106,7 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
}
if ((_gzStream==null || _gzStream._out==null) &&
(_mimeTypes==null && "application/gzip".equalsIgnoreCase(ct) ||
(_mimeTypes==null && ct!=null && ct.contains("gzip") ||
_mimeTypes!=null && (ct==null||!_mimeTypes.contains(StringUtil.asciiToLowerCase(ct)))))
{
noGzip();

View File

@ -2,7 +2,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-io</artifactId>

View File

@ -385,7 +385,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
try
{
updateKey();
this.wait(timeoutMs>=0?(end-now):10000);
this.wait(timeoutMs>0?(end-now):10000);
}
catch (InterruptedException e)
{
@ -433,7 +433,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
try
{
updateKey();
this.wait(timeoutMs>=0?(end-now):10000);
this.wait(timeoutMs>0?(end-now):10000);
}
catch (InterruptedException e)
{
@ -455,14 +455,14 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
}
return true;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.io.AsyncEndPoint#scheduleWrite()
*/
public void scheduleWrite()
{
if (_writable==true)
if (_writable)
LOG.debug("Required scheduleWrite {}",this);
_writable=false;
@ -687,14 +687,15 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
{
try
{
if (_key!=null)
_key.cancel();
SelectionKey key = _key;
if (key!=null)
key.cancel();
}
catch (Throwable e)
{
LOG.ignore(e);
}
try
{
super.close();

View File

@ -285,7 +285,7 @@ public class IOTest
Socket client;
Socket server;
connector = new ServerSocket(9123);
connector = new ServerSocket(0);
client = new Socket("127.0.0.1",connector.getLocalPort());
server = connector.accept();
client.setTcpNoDelay(true);

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jaspi</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jmx</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jndi</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jsp</artifactId>

View File

@ -19,7 +19,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-monitor</artifactId>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<artifactId>jetty-nested</artifactId>
<name>Jetty :: Nested</name>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-nosql</artifactId>

16
jetty-npn/pom.xml Normal file
View File

@ -0,0 +1,16 @@
<?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/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.npn</groupId>
<artifactId>npn-api</artifactId>
<name>Jetty :: Next Protocol Negotiation :: API</name>
</project>

View File

@ -0,0 +1,218 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.npn;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSocket;
/**
* <p>{@link NextProtoNego} provides an API to applications that want to make use of the
* <a href="http://technotes.googlecode.com/git/nextprotoneg.html">Next Protocol Negotiation</a>.</p>
* <p>The NPN extension is only available when using the TLS protocol, therefore applications must
* ensure that the TLS protocol is used:</p>
* <pre>
* SSLContext context = SSLContext.getInstance("TLSv1");
* </pre>
* <p>Refer to the
* <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext">list
* of standard SSLContext protocol names</a> for further information on TLS protocol versions supported.</p>
* <p>Applications must register instances of either {@link SSLSocket} or {@link SSLEngine} with a
* {@link ClientProvider} or with a {@link ServerProvider}, depending whether they are on client or
* server side.</p>
* <p>The NPN implementation will invoke the provider callbacks to allow applications to interact
* with the negotiation of the next protocol.</p>
* <p>Client side typical usage:</p>
* <pre>
* SSLSocket sslSocket = ...;
* NextProtoNego.put(sslSocket, new NextProtoNego.ClientProvider()
* {
* &#64;Override
* public boolean supports()
* {
* return true;
* }
*
* &#64;Override
* public void unsupported()
* {
* }
*
* &#64;Override
* public String selectProtocol(List&lt;String&gt; protocols)
* {
* return protocols.get(0);
* }
* });
* </pre>
* <p>Server side typical usage:</p>
* <pre>
* SSLSocket sslSocket = ...;
* NextProtoNego.put(sslSocket, new NextProtoNego.ServerProvider()
* {
* &#64;Override
* public void unsupported()
* {
* }
*
* &#64;Override
* public List<String> protocols()
* {
* return Arrays.asList("http/1.1");
* }
*
* &#64;Override
* public void protocolSelected(String protocol)
* {
* System.out.println("Protocol Selected is: " + protocol);
* }
* });
* </pre>
* <p>There is no need to unregister {@link SSLSocket} or {@link SSLEngine} instances, as they
* are kept in a {@link WeakHashMap} and will be garbage collected when the application does not
* hard reference them anymore.</p>
* <p>In order to help application development, you can set the {@link NextProtoNego#debug} field
* to {@code true} to have debug code printed to {@link System#err}.</p>
*/
public class NextProtoNego
{
/**
* <p>Enables debug logging on {@link System#err}.</p>
*/
public static boolean debug = false;
private static Map<Object, Provider> objects = Collections.synchronizedMap(new WeakHashMap<Object, Provider>());
private NextProtoNego()
{
}
/**
* <p>Registers a SSLSocket with a provider.</p>
*
* @param socket the socket to register with the provider
* @param provider the provider to register with the socket
*/
public static void put(SSLSocket socket, Provider provider)
{
objects.put(socket, provider);
}
/**
* @param socket a socket registered with {@link #put(SSLSocket, Provider)}
* @return the provider registered with the given socket
*/
public static Provider get(SSLSocket socket)
{
return objects.get(socket);
}
/**
* <p>Registers a SSLEngine with a provider.</p>
*
* @param engine the engine to register with the provider
* @param provider the provider to register with the engine
*/
public static void put(SSLEngine engine, Provider provider)
{
objects.put(engine, provider);
}
/**
*
* @param engine an engine registered with {@link #put(SSLEngine, Provider)}
* @return the provider registered with the given engine
*/
public static Provider get(SSLEngine engine)
{
return objects.get(engine);
}
/**
* <p>Base, empty, interface for providers.</p>
*/
public interface Provider
{
}
/**
* <p>The client-side provider interface that applications must implement to interact
* with the negotiation of the next protocol.</p>
*/
public interface ClientProvider extends Provider
{
/**
* <p>Callback invoked to let the implementation know whether an
* empty NPN extension should be added to a ClientHello SSL message.</p>
*
* @return true to add the NPN extension, false otherwise
*/
public boolean supports();
/**
* <p>Callback invoked to let the application know that the server does
* not support NPN.</p>
*/
public void unsupported();
/**
* <p>Callback invoked to let the application select a protocol
* among the ones sent by the server.</p>
*
* @param protocols the protocols sent by the server
* @return the protocol selected by the application, or null if the
* NextProtocol SSL message should not be sent to the server
*/
public String selectProtocol(List<String> protocols);
}
/**
* <p>The server-side provider interface that applications must implement to interact
* with the negotiation of the next protocol.</p>
*/
public interface ServerProvider extends Provider
{
/**
* <p>Callback invoked to let the application know that the client does not
* support NPN.</p>
*/
public void unsupported();
/**
* <p>Callback invoked to let the implementation know the list
* of protocols that should be added to an NPN extension in a
* ServerHello SSL message.</p>
* <p>This callback is invoked only if the client sent a NPN extension.</p>
*
* @return the list of protocols, or null if no NPN extension
* should be sent to the client
*/
public List<String> protocols();
/**
* <p>Callback invoked to let the application know the protocol selected
* by the client.</p>
* <p>This callback is invoked only if the client sent a NextProtocol SSL message.</p>
*
* @param protocol the selected protocol
*/
public void protocolSelected(String protocol);
}
}

View File

@ -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: 7.4.1.qualifier
Bundle-Version: 7.6.2.qualifier
Bundle-Vendor: Mort Bay Consulting
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Import-Package: com.sun.el;resolution:=optional,
@ -22,15 +22,16 @@ Import-Package: com.sun.el;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",
org.apache.jasper;version="2.0.0";resolution:=optional,
org.apache.jasper.compiler;version="2.0.0";resolution:=optional,
org.apache.jasper.compiler.tagplugin;version="2.0.0";resolution:=optional,
org.apache.jasper.runtime;version="2.0.0";resolution:=optional,
org.apache.jasper.security;version="2.0.0";resolution:=optional,
org.apache.jasper.servlet;version="2.0.0";resolution:=optional,
org.apache.jasper.tagplugins.jstl;version="2.0.0";resolution:=optional,
org.apache.jasper.util;version="2.0.0";resolution:=optional,
org.apache.jasper.xmlparser;version="2.0.0";resolution:=optional,
org.apache.jasper;version="6.0.0";resolution:=optional,
org.apache.jasper.compiler;version="6.0.0";resolution:=optional,
org.apache.jasper.compiler.tagplugin;version="6.0.0";resolution:=optional,
org.apache.jasper.runtime;version="6.0.0";resolution:=optional,
org.apache.jasper.security;version="6.0.0";resolution:=optional,
org.apache.jasper.servlet;version="6.0.0";resolution:=optional,
org.apache.jasper.tagplugins.jstl;version="6.0.0";resolution:=optional,
org.apache.jasper.util;version="6.0.0";resolution:=optional,
org.apache.jasper.xmlparser;version="6.0.0";resolution:=optional,
org.glassfish.jasper.api;version="2.1.3";resolution:=optional,
org.apache.taglibs.standard;version="1.2.0";resolution:=optional,
org.apache.taglibs.standard.extra.spath;version="1.2.0";resolution:=optional,
org.apache.taglibs.standard.functions;version="1.2.0";resolution:=optional,

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -167,6 +167,8 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
}
return urls.toArray(new URL[urls.size()]);
}
/**
* Jasper resolves the dtd when it parses a taglib descriptor.
@ -182,7 +184,7 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
* on a static friendly field :(
* </p>
*/
void fixupDtdResolution()
void fixupDtdResolution()
{
try
{
@ -214,12 +216,12 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
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++)

View File

@ -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: 7.3.0.qualifier
Bundle-Version: 7.6.2.qualifier
Bundle-Vendor: Mort Bay Consulting
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Import-Package: ch.qos.logback.classic,

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -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: 7.3.0.qualifier
Bundle-Version: 7.6.2.qualifier
Bundle-Activator: org.eclipse.jetty.osgi.boot.warurl.WarUrlActivator
Bundle-Vendor: Mort Bay Consulting
Bundle-RequiredExecutionEnvironment: J2SE-1.5

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: Jetty OSGi bootstrap
Bundle-SymbolicName: org.eclipse.jetty.osgi.boot;singleton:=true
Bundle-Vendor: Mort Bay Consulting
Bundle-Version: 7.4.3.qualifier
Bundle-Version: 7.6.2.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,19 +14,19 @@ Import-Package: javax.mail;version="1.4.0";resolution:=optional,
javax.servlet.http;version="2.5.0",
javax.transaction;version="1.1.0";resolution:=optional,
javax.transaction.xa;version="1.1.0";resolution:=optional,
org.eclipse.jetty.deploy;version="7.4.0",
org.eclipse.jetty.deploy.providers;version="7.4.0",
org.eclipse.jetty.http;version="7.4.0",
org.eclipse.jetty.nested;version="7.4.0";resolution:=optional,
org.eclipse.jetty.server;version="7.4.0",
org.eclipse.jetty.server.handler;version="7.4.0",
org.eclipse.jetty.servlet;version="7.4.0",
org.eclipse.jetty.util;version="7.4.0",
org.eclipse.jetty.util.component;version="7.4.0",
org.eclipse.jetty.util.log;version="7.4.0",
org.eclipse.jetty.util.resource;version="7.4.0",
org.eclipse.jetty.webapp;version="7.4.1.v20110513",
org.eclipse.jetty.xml;version="7.4.0",
org.eclipse.jetty.deploy;version="7.6.2",
org.eclipse.jetty.deploy.providers;version="7.6.2",
org.eclipse.jetty.http;version="7.6.2",
org.eclipse.jetty.nested;version="7.6.2";resolution:=optional,
org.eclipse.jetty.server;version="7.6.2",
org.eclipse.jetty.server.handler;version="7.6.2",
org.eclipse.jetty.servlet;version="7.6.2",
org.eclipse.jetty.util;version="7.6.2",
org.eclipse.jetty.util.component;version="7.6.2",
org.eclipse.jetty.util.log;version="7.6.2",
org.eclipse.jetty.util.resource;version="7.6.2",
org.eclipse.jetty.webapp;version="7.6.2",
org.eclipse.jetty.xml;version="7.6.2",
org.osgi.framework,
org.osgi.service.cm;version="1.2.0",
org.osgi.service.packageadmin,
@ -40,7 +40,7 @@ Import-Package: javax.mail;version="1.4.0";resolution:=optional,
org.xml.sax.helpers
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-Classpath: .
Export-Package: org.eclipse.jetty.osgi.boot;version="7.4.0",
org.eclipse.jetty.osgi.nested;version="7.4.0",
org.eclipse.jetty.osgi.boot.utils;version="7.4.0"
Export-Package: org.eclipse.jetty.osgi.boot;version="7.6.2",
org.eclipse.jetty.osgi.nested;version="7.6.2",
org.eclipse.jetty.osgi.boot.utils;version="7.6.2"
DynamicImport-Package: org.eclipse.jetty.*;version="[7.3,8)"

View File

@ -22,14 +22,6 @@
<Set name="minThreads">10</Set>
<Set name="maxThreads">200</Set>
</New>
<!-- Optional Java 5 bounded threadpool with job queue
<New class="org.eclipse.jetty.util.thread.ExecutorThreadPool">
<Arg name="coreSize" type="int">25</Arg>
<Arg name="maxSize" type="int">50</Arg>
<Arg name="maxIdleMs" type="long">30000</Arg>
</New>
-->
</Set>
@ -118,7 +110,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>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -187,6 +187,9 @@ public class OSGiAppProvider extends ScanningAppProvider implements AppProvider
{
((WebAppContext)wah).setConfigurationClasses(_configurationClasses);
}
if (_defaultsDescriptor != null)
((WebAppContext)wah).setDefaultsDescriptor(_defaultsDescriptor);
return app.getContextHandler();
}

View File

@ -20,6 +20,7 @@ import java.util.Map;
import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator;
import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.DefaultJettyAtJettyHomeHelper;
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;
@ -195,7 +196,21 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
String defaultWebXmlPath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_DEFAULT_WEB_XML_PATH);
if (defaultWebXmlPath == null)
{
defaultWebXmlPath = webapp.getDefaultsDescriptor();
String jettyHome = System.getProperty(DefaultJettyAtJettyHomeHelper.SYS_PROP_JETTY_HOME);
if (jettyHome != null)
{
File etc = new File(jettyHome, "etc");
if (etc.exists() && etc.isDirectory())
{
File webDefault = new File (etc, "webdefault.xml");
if (webDefault.exists())
defaultWebXmlPath = webDefault.getAbsolutePath();
else
defaultWebXmlPath = webapp.getDefaultsDescriptor();
}
else
defaultWebXmlPath = webapp.getDefaultsDescriptor();
}
}
String war = (String)sr.getProperty("war");
try

View File

@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeMap;
@ -50,6 +51,9 @@ import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleReference;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.util.tracker.ServiceTracker;
import org.xml.sax.SAXException;
/**
@ -173,6 +177,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
overrideBundleInstallLocation);
File webapp = null;
URL baseWebappInstallURL = null;
if (webappFolderPath != null && webappFolderPath.length() != 0 && !webappFolderPath.equals("."))
{
if (webappFolderPath.startsWith("/") || webappFolderPath.startsWith("file:"))
@ -261,7 +266,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
File defaultWebXml = null;
if (defaultWebXmlPath.startsWith("/") || defaultWebXmlPath.startsWith("file:/"))
{
defaultWebXml = new File(webXmlPath);
defaultWebXml = new File(defaultWebXmlPath);
}
else
{
@ -276,8 +281,9 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
//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);
// @see
// org.eclipse.jetty.webapp.JettyWebXmlConfiguration#configure(WebAppContext)
@ -450,7 +456,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
//the actual registration must happen via the new Deployment API.
// _ctxtHandler.addHandler(context);
configureWebappClassLoader(contributor,context,composite);
configureWebappClassLoader(contributor,context,composite, requireTldBundle);
if (context instanceof WebAppContext)
{
webAppContext = (WebAppContext)context;
@ -615,8 +621,9 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
}
while (tldEnum.hasMoreElements())
{
URL tldUrl = tldEnum.nextElement();
tldfrags.add(Resource.newResource(
DefaultFileLocatorHelper.getLocalURL(tldEnum.nextElement())));
DefaultFileLocatorHelper.getLocalURL(tldUrl)));
}
}
}
@ -764,13 +771,17 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
* @param classInBundle
* @throws Exception
*/
protected void configureWebappClassLoader(Bundle contributor, ContextHandler context, OSGiWebappClassLoader webappClassLoader) throws Exception
protected void configureWebappClassLoader(Bundle contributor, ContextHandler context, OSGiWebappClassLoader webappClassLoader, String requireTldBundle) throws Exception
{
if (context instanceof WebAppContext)
{
WebAppContext webappCtxt = (WebAppContext)context;
context.setClassLoader(webappClassLoader);
webappClassLoader.setWebappContext(webappCtxt);
String pathsToRequiredBundles = getPathsToRequiredBundles(context, requireTldBundle);
if (pathsToRequiredBundles != null)
webappClassLoader.addClassPath(pathsToRequiredBundles);
}
else
{
@ -788,6 +799,18 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
// 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();}
*/
return webappClassLoader;
}
@ -811,5 +834,50 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
}
}
private String getPathsToRequiredBundles (ContextHandler context, String requireTldBundle) throws Exception
{
if (requireTldBundle == null)
return null;
StringBuilder paths = new StringBuilder();
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());
}
File f = fileLocatorHelper.getBundleInstallLocation(bs[0]);
if (paths.length() > 0)
paths.append(", ");
System.err.println("getPathsToRequiredBundles: bundle path="+bs[0].getLocation()+" uri="+f.toURI());
paths.append(f.toURI().toURL().toString());
}
return paths.toString();
}
private PackageAdmin getBundleAdmin()
{
Bundle bootBundle = ((BundleReference)OSGiWebappConstants.class.getClassLoader()).getBundle();
ServiceTracker serviceTracker = new ServiceTracker(bootBundle.getBundleContext(), PackageAdmin.class.getName(), null);
serviceTracker.open();
return (PackageAdmin) serviceTracker.getService();
}
}

View File

@ -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: 7.4.2.qualifier
Bundle-Version: 7.6.2.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="7.4.0",
org.eclipse.jetty.io;version="7.4.0",
org.eclipse.jetty.util;version="7.4.0",
org.eclipse.jetty.util.log;version="7.4.0",
org.eclipse.jetty.websocket;version="7.4.0",
org.eclipse.jetty.continuation;version="7.6.2",
org.eclipse.jetty.io;version="7.6.2",
org.eclipse.jetty.util;version="7.6.2",
org.eclipse.jetty.util.log;version="7.6.2",
org.eclipse.jetty.websocket;version="7.6.2",
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="7.4.2",
org.eclipse.jetty.osgi.equinoxtools.console;x-internal:=true;version="7.4.2"
Export-Package: org.eclipse.jetty.osgi.equinoxtools;x-internal:=true;version="7.6.2",
org.eclipse.jetty.osgi.equinoxtools.console;x-internal:=true;version="7.6.2"
Bundle-RequiredExecutionEnvironment: J2SE-1.5

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -1,16 +1,16 @@
Bundle-ManifestVersion: 2
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-SymbolicName: org.eclipse.jetty.osgi.httpservice
Bundle-Version: 7.4.2.qualifier
Bundle-Version: 7.6.2.qualifier
Bundle-Vendor: Mort Bay Consulting
Bundle-Name: OSGi HttpService provided by equinox HttpServiceServlet deployed on jetty
Jetty-ContextFilePath: contexts/httpservice.xml
Import-Package: javax.servlet;version="2.5.0",
javax.servlet.http;version="2.5.0",
org.eclipse.equinox.http.servlet,
org.eclipse.jetty.server;version="7.0.0",
org.eclipse.jetty.server.handler;version="7.0.0",
org.eclipse.jetty.servlet;version="7.4.0",
org.eclipse.jetty.util.component;version="7.0.0"
Export-Package: org.eclipse.jetty.osgi.httpservice;version="7.4.2"
org.eclipse.jetty.server;version="7.6.2",
org.eclipse.jetty.server.handler;version="7.6.2",
org.eclipse.jetty.servlet;version="7.6.2",
org.eclipse.jetty.util.component;version="7.6.2"
Export-Package: org.eclipse.jetty.osgi.httpservice;version="7.6.2"

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>org.eclipse.jetty.osgi</groupId>
@ -15,7 +15,6 @@
<osgi-services-version>3.2.100.v20100503</osgi-services-version>
<equinox-http-servlet-version>1.0.0-v20070606</equinox-http-servlet-version>
<!--equinox-servletbridge-version>1.0.0-v20070523</equinox-servletbridge-version-->
<jsp-2.1-glassfish-version>2.1.v20100127</jsp-2.1-glassfish-version>
<logback-version>0.9.18</logback-version>
<slf4j-version>1.5.11</slf4j-version>
</properties>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -102,6 +102,12 @@
<artifactId>jetty-websocket</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-plus</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<!-- Eclipse OSGi Deps -->
<dependency>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-overlay-deployer</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-plus</artifactId>

View File

@ -13,11 +13,15 @@
package org.eclipse.jetty.plus.jndi;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Name;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.RefAddr;
import javax.naming.Reference;
@ -25,6 +29,7 @@ import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import javax.naming.spi.ObjectFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -125,6 +130,35 @@ public class TestNamingEntries
public void init()
{
this.someObject = new SomeObject(4);
}
/**
* after each test we should scrape out any lingering bindings to prevent cross test pollution
* as observed when running java 7
*
* @throws Exception
*/
@After
public void after() throws Exception
{
InitialContext icontext = new InitialContext();
NamingEnumeration<Binding> bindings = icontext.listBindings("");
List<String> names = new ArrayList<String>();
while (bindings.hasMore())
{
Binding bd = (Binding)bindings.next();
names.add(bd.getName());
}
for (String name : names)
{
icontext.unbind(name);
}
}
@Test
@ -199,6 +233,7 @@ public class TestNamingEntries
ne = NamingEntryUtil.lookupNamingEntry(new ScopeB(), "resourceB");
assertNull(ne);
testLink();
}
@Test

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<artifactId>jetty-policy</artifactId>
<name>Jetty :: Policy Tool</name>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-rewrite</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-security</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-server</artifactId>

View File

@ -24,7 +24,6 @@ import javax.servlet.http.HttpServletRequest;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationListener;
import org.eclipse.jetty.continuation.ContinuationThrowable;
import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.handler.ContextHandler;
@ -821,8 +820,10 @@ public class AsyncContinuation implements AsyncContext, Continuation
synchronized (this)
{
doSuspend(context,request,response);
if ( request instanceof HttpServletRequest)
_event._pathInContext=URIUtil.addPaths(((HttpServletRequest)request).getServletPath(),((HttpServletRequest)request).getPathInfo());
if (request instanceof HttpServletRequest)
{
_event._pathInContext = URIUtil.addPaths(((HttpServletRequest)request).getServletPath(),((HttpServletRequest)request).getPathInfo());
}
}
}

View File

@ -783,7 +783,7 @@ public class Response implements HttpServletResponse
if (isCommitted() || _connection.isIncluding())
return;
_connection._generator.setContentLength(len);
if (len>=0)
if (len>0)
{
_connection.getResponseFields().putLongField(HttpHeaders.CONTENT_LENGTH, len);
if (_connection._generator.isAllContentWritten())

View File

@ -24,8 +24,8 @@ import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
/* ------------------------------------------------------------ */
/** A <code>HandlerContainer</code> that allows a hot swap
* of a wrapped handler.
/**
* A <code>HandlerContainer</code> that allows a hot swap of a wrapped handler.
*
*/
public class HotSwapHandler extends AbstractHandlerContainer
@ -48,113 +48,106 @@ public class HotSwapHandler extends AbstractHandlerContainer
{
return _handler;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the handlers.
*/
public Handler[] getHandlers()
{
return new Handler[] {_handler};
return new Handler[]
{ _handler };
}
/* ------------------------------------------------------------ */
/**
* @param handler Set the {@link Handler} which should be wrapped.
* @param handler
* Set the {@link Handler} which should be wrapped.
*/
public void setHandler(Handler handler)
{
if (handler == null)
throw new IllegalArgumentException("Parameter handler is null.");
try
{
Handler old_handler = _handler;
_handler = handler;
if (handler!=null)
{
handler.setServer(getServer());
if (isStarted())
handler.start();
}
Server server = getServer();
handler.setServer(server);
addBean(handler);
if (getServer()!=null)
getServer().getContainer().update(this, old_handler, handler, "handler");
if (server != null)
server.getContainer().update(this,old_handler,handler,"handler");
// if there is an old handler and it was started, stop it
if (old_handler != null && isStarted())
if (old_handler != null)
{
old_handler.stop();
removeBean(old_handler);
}
}
catch(RuntimeException e)
{
throw e;
}
catch(Exception e)
catch (Exception e)
{
throw new RuntimeException(e);
}
}
/* ------------------------------------------------------------ */
/*
/*
* @see org.eclipse.thread.AbstractLifeCycle#doStart()
*/
@Override
protected void doStart() throws Exception
{
if (_handler!=null)
_handler.start();
super.doStart();
}
/* ------------------------------------------------------------ */
/*
/*
* @see org.eclipse.thread.AbstractLifeCycle#doStop()
*/
@Override
protected void doStop() throws Exception
{
super.doStop();
if (_handler!=null)
_handler.stop();
}
/* ------------------------------------------------------------ */
/*
/*
* @see org.eclipse.jetty.server.server.EventHandler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
if (_handler!=null && isStarted())
if (_handler != null && isStarted())
{
_handler.handle(target,baseRequest, request, response);
_handler.handle(target,baseRequest,request,response);
}
}
/* ------------------------------------------------------------ */
@Override
public void setServer(Server server)
{
Server old_server=getServer();
if (server==old_server)
Server old_server = getServer();
if (server == old_server)
return;
if (isRunning())
throw new IllegalStateException(RUNNING);
super.setServer(server);
Handler h=getHandler();
if (h!=null)
Handler h = getHandler();
if (h != null)
h.setServer(server);
if (server!=null && server!=old_server)
server.getContainer().update(this, null,_handler, "handler");
if (server != null && server != old_server)
server.getContainer().update(this,null,_handler,"handler");
}
/* ------------------------------------------------------------ */
@SuppressWarnings(
{ "rawtypes", "unchecked" })
@Override
protected Object expandChildren(Object list, Class byClass)
{
@ -167,8 +160,8 @@ public class HotSwapHandler extends AbstractHandlerContainer
{
if (!isStopped())
throw new IllegalStateException("!STOPPED");
Handler child=getHandler();
if (child!=null)
Handler child = getHandler();
if (child != null)
{
setHandler(null);
child.destroy();

View File

@ -79,7 +79,16 @@ public class SelectChannelConnector extends AbstractNIOConnector
addBean(_manager,true);
setAcceptors(Math.max(1,(Runtime.getRuntime().availableProcessors()+3)/4));
}
@Override
public void setThreadPool(ThreadPool pool)
{
super.setThreadPool(pool);
// preserve start order
removeBean(_manager);
addBean(_manager,true);
}
/* ------------------------------------------------------------ */
@Override
public void accept(int acceptorID) throws IOException

View File

@ -39,7 +39,9 @@ import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.StdErrLog;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.matchers.JUnitMatchers;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.junit.Assert.assertEquals;
@ -1048,10 +1050,13 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
else
out.println(avail);
for (int i=0;i<avail;i++)
while (avail>0)
{
buf+=(char)in.read();
avail=in.available();
avail=in.available();
}
out.println(avail);
out.println(buf);
out.close();
@ -1098,9 +1103,9 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
// skip header
while(reader.readLine().length()>0);
assertEquals(10,Integer.parseInt(reader.readLine()));
assertThat(Integer.parseInt(reader.readLine()),Matchers.greaterThan(0));
assertEquals(0,Integer.parseInt(reader.readLine()));
assertEquals(20,Integer.parseInt(reader.readLine()));
assertThat(Integer.parseInt(reader.readLine()),Matchers.greaterThan(0));
assertEquals(0,Integer.parseInt(reader.readLine()));
assertEquals("1234567890abcdefghijklmnopqrst",reader.readLine());

View File

@ -439,6 +439,20 @@ public class ResponseTest
}
}
@Test
public void testZeroContent () throws Exception
{
Response response = new Response (new TestHttpConnection(connector, new ByteArrayEndPoint(), connector.getServer()));
PrintWriter writer = response.getWriter();
response.setContentLength(0);
assertTrue(!response.isCommitted());
assertTrue(!writer.checkError());
writer.print("");
assertTrue(!writer.checkError());
assertTrue(response.isCommitted());
}
@Test
public void testHead() throws Exception
{

View File

@ -1,8 +1,5 @@
package org.eclipse.jetty.server.handler;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@ -13,7 +10,6 @@ import java.net.Socket;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
@ -31,6 +27,9 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
/**
* @version $Revision$ $Date$
*/
@ -85,7 +84,7 @@ public class ConnectHandlerSSLTest extends AbstractConnectHandlerTest
output = sslSocket.getOutputStream();
input = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
request =
request =
"GET /echo HTTP/1.1\r\n" +
"Host: " + hostPort + "\r\n" +
"\r\n";
@ -188,7 +187,7 @@ public class ConnectHandlerSSLTest extends AbstractConnectHandlerTest
public X509Certificate[] getAcceptedIssuers()
{
return null;
return new X509Certificate[]{};
}
}

View File

@ -3,7 +3,7 @@
//------------------------------------------------------------------------
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//You may obtain a copy of the License at
//http://www.apache.org/licenses/LICENSE-2.0
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
@ -27,7 +27,6 @@ import java.io.OutputStream;
import java.net.Socket;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
@ -36,7 +35,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.TestCase;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
@ -53,20 +51,18 @@ public class SSLCloseTest extends TestCase
{
public X509Certificate[] getAcceptedIssuers()
{
return null;
return new X509Certificate[]{};
}
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
{
return;
}
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
{
return;
}
}
private static final TrustManager[] s_dummyTrustManagers=new TrustManager[] { new CredulousTM() };
// ~ Methods
@ -74,7 +70,7 @@ public class SSLCloseTest extends TestCase
/**
* Feed the server the entire request at once.
*
*
* @throws Exception
*/
public void testClose() throws Exception
@ -83,7 +79,7 @@ public class SSLCloseTest extends TestCase
SslSelectChannelConnector connector=new SslSelectChannelConnector();
String keystore = System.getProperty("user.dir")+File.separator+"src"+File.separator+"test"+File.separator+"resources"+File.separator+"keystore";
connector.setPort(0);
connector.getSslContextFactory().setKeyStorePath(keystore);
connector.getSslContextFactory().setKeyStorePassword("storepwd");
@ -92,7 +88,7 @@ public class SSLCloseTest extends TestCase
server.setConnectors(new Connector[]
{ connector });
server.setHandler(new WriteHandler());
server.start();
@ -107,7 +103,7 @@ public class SSLCloseTest extends TestCase
os.write("GET /test HTTP/1.1\r\nHost:test\r\nConnection:close\r\n\r\n".getBytes());
os.flush();
BufferedReader in =new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
@ -123,7 +119,7 @@ public class SSLCloseTest extends TestCase
while ((line=in.readLine())!=null)
System.err.println(line);
}
@ -137,7 +133,7 @@ public class SSLCloseTest extends TestCase
response.setStatus(200);
response.setHeader("test","value");
__endp=(AsyncEndPoint)baseRequest.getConnection().getEndPoint();
OutputStream out=response.getOutputStream();
String data = "Now is the time for all good men to come to the aid of the party.\n";

View File

@ -27,6 +27,7 @@ import javax.net.ssl.TrustManagerFactory;
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;
/**
@ -135,4 +136,13 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
client.close();
}
}
@Override
@Ignore
public void testAvailable() throws Exception
{
}
}

View File

@ -23,6 +23,7 @@ import javax.net.ssl.TrustManagerFactory;
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;
/**
@ -75,4 +76,10 @@ public class SslSocketServerTest extends HttpServerTestBase
// TODO this test uses URL, so noop for now
}
@Override
@Ignore
public void testAvailable() throws Exception
{
}
}

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-servlet</artifactId>

View File

@ -1,5 +1,9 @@
package org.eclipse.jetty.servlet;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
@ -8,8 +12,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
import junit.framework.Assert;
import org.eclipse.jetty.continuation.ContinuationSupport;
@ -42,12 +45,13 @@ public class AsyncContextTest
@Before
public void setUp() throws Exception
{
_connector.setMaxIdleTime(3000000);
_connector.setMaxIdleTime(30000);
_server.setConnectors(new Connector[]
{ _connector });
_contextHandler.setContextPath("/");
_contextHandler.addServlet(new ServletHolder(new TestServlet()),"/servletPath");
_contextHandler.addServlet(new ServletHolder(new TestServlet()),"/path with spaces/servletPath");
_contextHandler.addServlet(new ServletHolder(new TestServlet2()),"/servletPath2");
_contextHandler.addServlet(new ServletHolder(new ForwardingServlet()),"/forward");
_contextHandler.addServlet(new ServletHolder(new AsyncDispatchingServlet()),"/dispatchingServlet");
@ -62,111 +66,102 @@ public class AsyncContextTest
@Test
public void testSimpleAsyncContext() throws Exception
{
{
String request = "GET /servletPath HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n"
+ "Connection: close\r\n" + "\r\n";
String responseString = _connector.getResponses(request);
BufferedReader br = new BufferedReader(new StringReader(responseString));
Assert.assertEquals("HTTP/1.1 200 OK",br.readLine());
br.readLine();// connection close
br.readLine();// server
br.readLine();// empty
Assert.assertEquals("servlet gets right path","doGet:getServletPath:/servletPath", br.readLine());
Assert.assertEquals("async context gets right path in get","doGet:async:getServletPath:/servletPath", br.readLine());
Assert.assertEquals("async context gets right path in async","async:run:attr:servletPath:/servletPath", br.readLine());
BufferedReader br = parseHeader(responseString);
Assert.assertEquals("servlet gets right path","doGet:getServletPath:/servletPath",br.readLine());
Assert.assertEquals("async context gets right path in get","doGet:async:getServletPath:/servletPath",br.readLine());
Assert.assertEquals("async context gets right path in async","async:run:attr:servletPath:/servletPath",br.readLine());
}
@Test
public void testDispatchAsyncContext() throws Exception
{
{
String request = "GET /servletPath?dispatch=true HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n"
+ "Connection: close\r\n" + "\r\n";
String responseString = _connector.getResponses(request);
BufferedReader br = new BufferedReader(new StringReader(responseString));
Assert.assertEquals("HTTP/1.1 200 OK",br.readLine());
br.readLine();// connection close
br.readLine();// server
br.readLine();// empty
Assert.assertEquals("servlet gets right path","doGet:getServletPath:/servletPath2", br.readLine());
Assert.assertEquals("async context gets right path in get","doGet:async:getServletPath:/servletPath2", br.readLine());
Assert.assertEquals("servlet path attr is original","async:run:attr:servletPath:/servletPath", br.readLine());
Assert.assertEquals("path info attr is correct","async:run:attr:pathInfo:null", br.readLine());
Assert.assertEquals("query string attr is correct","async:run:attr:queryString:dispatch=true", br.readLine());
Assert.assertEquals("context path attr is correct","async:run:attr:contextPath:", br.readLine());
Assert.assertEquals("request uri attr is correct","async:run:attr:requestURI:/servletPath", br.readLine());
}
@Test
public void testSimpleWithContextAsyncContext() throws Exception
{
_contextHandler.setContextPath("/foo");
String request = "GET /foo/servletPath HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n"
+ "Connection: close\r\n" + "\r\n";
String responseString = _connector.getResponses(request);
BufferedReader br = new BufferedReader(new StringReader(responseString));
Assert.assertEquals("HTTP/1.1 200 OK",br.readLine());
br.readLine();// connection close
br.readLine();// server
br.readLine();// empty
Assert.assertEquals("servlet gets right path","doGet:getServletPath:/servletPath", br.readLine());
Assert.assertEquals("async context gets right path in get","doGet:async:getServletPath:/servletPath", br.readLine());
Assert.assertEquals("async context gets right path in async","async:run:attr:servletPath:/servletPath", br.readLine());
BufferedReader br = parseHeader(responseString);
Assert.assertEquals("servlet gets right path","doGet:getServletPath:/servletPath2",br.readLine());
Assert.assertEquals("async context gets right path in get","doGet:async:getServletPath:/servletPath2",br.readLine());
Assert.assertEquals("servlet path attr is original","async:run:attr:servletPath:/servletPath",br.readLine());
Assert.assertEquals("path info attr is correct","async:run:attr:pathInfo:null",br.readLine());
Assert.assertEquals("query string attr is correct","async:run:attr:queryString:dispatch=true",br.readLine());
Assert.assertEquals("context path attr is correct","async:run:attr:contextPath:",br.readLine());
Assert.assertEquals("request uri attr is correct","async:run:attr:requestURI:/servletPath",br.readLine());
}
@Test
public void testDispatchWithContextAsyncContext() throws Exception
{
_contextHandler.setContextPath("/foo");
String request = "GET /foo/servletPath?dispatch=true HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n"
public void testDispatchAsyncContextEncodedPathAndQueryString() throws Exception
{
String request = "GET /path%20with%20spaces/servletPath?dispatch=true&queryStringWithEncoding=space%20space HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n"
+ "Connection: close\r\n" + "\r\n";
String responseString = _connector.getResponses(request);
System.out.println(responseString);
BufferedReader br = parseHeader(responseString);
BufferedReader br = new BufferedReader(new StringReader(responseString));
Assert.assertEquals("HTTP/1.1 200 OK",br.readLine());
br.readLine();// connection close
br.readLine();// server
br.readLine();// empty
Assert.assertEquals("servlet gets right path","doGet:getServletPath:/servletPath2", br.readLine());
Assert.assertEquals("async context gets right path in get","doGet:async:getServletPath:/servletPath2", br.readLine());
Assert.assertEquals("servlet path attr is original","async:run:attr:servletPath:/servletPath", br.readLine());
Assert.assertEquals("path info attr is correct","async:run:attr:pathInfo:null", br.readLine());
Assert.assertEquals("query string attr is correct","async:run:attr:queryString:dispatch=true", br.readLine());
Assert.assertEquals("context path attr is correct","async:run:attr:contextPath:/foo", br.readLine());
Assert.assertEquals("request uri attr is correct","async:run:attr:requestURI:/foo/servletPath", br.readLine());
}
assertThat("servlet gets right path",br.readLine(),equalTo("doGet:getServletPath:/servletPath2"));
assertThat("async context gets right path in get",br.readLine(), equalTo("doGet:async:getServletPath:/servletPath2"));
assertThat("servlet path attr is original",br.readLine(),equalTo("async:run:attr:servletPath:/path with spaces/servletPath"));
assertThat("path info attr is correct",br.readLine(),equalTo("async:run:attr:pathInfo:null"));
assertThat("query string attr is correct",br.readLine(),equalTo("async:run:attr:queryString:dispatch=true&queryStringWithEncoding=space%20space"));
assertThat("context path attr is correct",br.readLine(),equalTo("async:run:attr:contextPath:"));
assertThat("request uri attr is correct",br.readLine(),equalTo("async:run:attr:requestURI:/path%20with%20spaces/servletPath"));
}
@Test
public void testSimpleWithContextAsyncContext() throws Exception
{
_contextHandler.setContextPath("/foo");
String request = "GET /foo/servletPath HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n"
+ "Connection: close\r\n" + "\r\n";
String responseString = _connector.getResponses(request);
BufferedReader br = parseHeader(responseString);
Assert.assertEquals("servlet gets right path","doGet:getServletPath:/servletPath",br.readLine());
Assert.assertEquals("async context gets right path in get","doGet:async:getServletPath:/servletPath",br.readLine());
Assert.assertEquals("async context gets right path in async","async:run:attr:servletPath:/servletPath",br.readLine());
}
@Test
public void testDispatchWithContextAsyncContext() throws Exception
{
_contextHandler.setContextPath("/foo");
String request = "GET /foo/servletPath?dispatch=true HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n"
+ "Connection: close\r\n" + "\r\n";
String responseString = _connector.getResponses(request);
BufferedReader br = parseHeader(responseString);
Assert.assertEquals("servlet gets right path","doGet:getServletPath:/servletPath2",br.readLine());
Assert.assertEquals("async context gets right path in get","doGet:async:getServletPath:/servletPath2",br.readLine());
Assert.assertEquals("servlet path attr is original","async:run:attr:servletPath:/servletPath",br.readLine());
Assert.assertEquals("path info attr is correct","async:run:attr:pathInfo:null",br.readLine());
Assert.assertEquals("query string attr is correct","async:run:attr:queryString:dispatch=true",br.readLine());
Assert.assertEquals("context path attr is correct","async:run:attr:contextPath:/foo",br.readLine());
Assert.assertEquals("request uri attr is correct","async:run:attr:requestURI:/foo/servletPath",br.readLine());
}
@Test
public void testDispatch() throws Exception
{
String request = "GET /forward HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "Connection: close\r\n"
+ "\r\n";
String responseString = _connector.getResponses(request);
BufferedReader br = new BufferedReader(new StringReader(responseString));
assertEquals("HTTP/1.1 200 OK",br.readLine());
br.readLine();// connection close
br.readLine();// server
br.readLine();// empty
BufferedReader br = parseHeader(responseString);
assertThat("!ForwardingServlet",br.readLine(),equalTo("Dispatched back to ForwardingServlet"));
}
@ -176,16 +171,24 @@ public class AsyncContextTest
{
String request = "GET /forward?dispatchRequestResponse=true HTTP/1.1\r\n" + "Host: localhost\r\n"
+ "Content-Type: application/x-www-form-urlencoded\r\n" + "Connection: close\r\n" + "\r\n";
String responseString = _connector.getResponses(request);
BufferedReader br = parseHeader(responseString);
assertThat("!AsyncDispatchingServlet",br.readLine(),equalTo("Dispatched back to AsyncDispatchingServlet"));
}
private BufferedReader parseHeader(String responseString) throws IOException
{
BufferedReader br = new BufferedReader(new StringReader(responseString));
assertEquals("HTTP/1.1 200 OK",br.readLine());
br.readLine();// connection close
br.readLine();// server
br.readLine();// empty
assertThat("!AsyncDispatchingServlet",br.readLine(),equalTo("Dispatched back to AsyncDispatchingServlet"));
return br;
}
private class ForwardingServlet extends HttpServlet
@ -206,28 +209,32 @@ public class AsyncContextTest
}
}
private class AsyncDispatchingServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
private class AsyncDispatchingServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, final HttpServletResponse response) throws ServletException, IOException
{
Request request = (Request)req;
if (request.getDispatcherType() == DispatcherType.ASYNC)
{
response.getOutputStream().print("Dispatched back to AsyncDispatchingServlet");
}
else
{
final AsyncContext asyncContext;
if (request.getParameter("dispatchRequestResponse") != null)
asyncContext = request.startAsync(request,response);
else
asyncContext = request.startAsync();
@Override
protected void doGet(HttpServletRequest req, final HttpServletResponse response) throws ServletException, IOException
{
Request request = (Request)req;
if (request.getDispatcherType() == DispatcherType.ASYNC)
{
response.getOutputStream().print("Dispatched back to AsyncDispatchingServlet");
}
else
{
final AsyncContext asyncContext;
if (request.getParameter("dispatchRequestResponse") != null)
{
asyncContext = request.startAsync(request,response);
}
else
{
asyncContext = request.startAsync();
}
new Thread(new DispatchingRunnable(asyncContext)).start();
}
new Thread(new DispatchingRunnable(asyncContext)).start();
}
}
}

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>7.6.3-SNAPSHOT</version>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-servlets</artifactId>

View File

@ -20,6 +20,7 @@ import java.io.UnsupportedEncodingException;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
@ -67,12 +68,17 @@ public class GzipFilter extends UserAgentFilter
protected Set<String> _mimeTypes;
protected int _bufferSize=8192;
protected int _minGzipSize=256;
protected Set<String> _excluded;
protected Set<String> _excludedAgents;
protected Set<Pattern> _excludedAgentPatterns;
protected Set<String> _excludedPaths;
protected Set<Pattern> _excludedPathPatterns;
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.servlets.UserAgentFilter#init(javax.servlet.FilterConfig)
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
super.init(filterConfig);
@ -93,21 +99,48 @@ public class GzipFilter extends UserAgentFilter
while (tok.hasMoreTokens())
_mimeTypes.add(tok.nextToken());
}
tmp=filterConfig.getInitParameter("excludedAgents");
if (tmp!=null)
{
_excluded=new HashSet<String>();
_excludedAgents=new HashSet<String>();
StringTokenizer tok = new StringTokenizer(tmp,",",false);
while (tok.hasMoreTokens())
_excluded.add(tok.nextToken());
_excludedAgents.add(tok.nextToken());
}
tmp=filterConfig.getInitParameter("excludeAgentPatterns");
if (tmp!=null)
{
_excludedAgentPatterns=new HashSet<Pattern>();
StringTokenizer tok = new StringTokenizer(tmp,",",false);
while (tok.hasMoreTokens())
_excludedAgentPatterns.add(Pattern.compile(tok.nextToken()));
}
tmp=filterConfig.getInitParameter("excludePaths");
if (tmp!=null)
{
_excludedPaths=new HashSet<String>();
StringTokenizer tok = new StringTokenizer(tmp,",",false);
while (tok.hasMoreTokens())
_excludedPaths.add(tok.nextToken());
}
tmp=filterConfig.getInitParameter("excludePathPatterns");
if (tmp!=null)
{
_excludedPathPatterns=new HashSet<Pattern>();
StringTokenizer tok = new StringTokenizer(tmp,",",false);
while (tok.hasMoreTokens())
_excludedPathPatterns.add(Pattern.compile(tok.nextToken()));
}
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.servlets.UserAgentFilter#destroy()
*/
@Override
public void destroy()
{
}
@ -116,6 +149,7 @@ public class GzipFilter extends UserAgentFilter
/**
* @see org.eclipse.jetty.servlets.UserAgentFilter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException
{
@ -126,14 +160,17 @@ public class GzipFilter extends UserAgentFilter
if (ae != null && ae.indexOf("gzip")>=0 && !response.containsHeader("Content-Encoding")
&& !HttpMethods.HEAD.equalsIgnoreCase(request.getMethod()))
{
if (_excluded!=null)
String ua = getUserAgent(request);
if (isExcludedAgent(ua))
{
String ua=getUserAgent(request);
if (_excluded.contains(ua))
{
super.doFilter(request,response,chain);
return;
}
super.doFilter(request,response,chain);
return;
}
String requestURI = request.getRequestURI();
if (isExcludedPath(requestURI))
{
super.doFilter(request,response,chain);
return;
}
final GzipResponseWrapper wrappedResponse=newGzipResponseWrapper(request,response);
@ -181,7 +218,64 @@ public class GzipFilter extends UserAgentFilter
super.doFilter(request,response,chain);
}
}
/**
* Checks to see if the UserAgent is excluded
*
* @param ua
* the user agent
* @return boolean true if excluded
*/
private boolean isExcludedAgent(String ua)
{
if (ua == null)
return false;
if (_excludedAgents != null)
{
if (_excludedAgents.contains(ua))
{
return true;
}
}
else if (_excludedAgentPatterns != null)
{
for (Pattern pattern : _excludedAgentPatterns)
{
if (pattern.matcher(ua).matches())
{
return true;
}
}
}
return false;
}
/**
* Checks to see if the Path is excluded
*
* @param ua
* the request uri
* @return boolean true if excluded
*/
private boolean isExcludedPath(String requestURI)
{
if (requestURI == null)
return false;
if (_excludedPathPatterns != null)
{
for (Pattern pattern : _excludedPathPatterns)
{
if (pattern.matcher(requestURI).matches())
{
return true;
}
}
}
return false;
}
/**
* Allows derived implementations to replace ResponseWrapper implementation.
*

View File

@ -27,6 +27,7 @@ import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -460,7 +461,14 @@ public class MultiPartFilter implements Filter
@Override
public Map getParameterMap()
{
return Collections.unmodifiableMap(_params.toStringArrayMap());
Map<String, String> cmap = new HashMap<String,String>();
for ( Object key : _params.keySet() )
{
cmap.put((String)key,getParameter((String)key));
}
return Collections.unmodifiableMap(cmap);
}
/* ------------------------------------------------------------------------------- */

View File

@ -597,12 +597,14 @@ public class ProxyServlet implements Servlet
{
exchange.addRequestHeader("X-Forwarded-For",request.getRemoteAddr());
exchange.addRequestHeader("X-Forwarded-Proto",request.getScheme());
exchange.addRequestHeader("X-Forwarded-Host",request.getServerName());
exchange.addRequestHeader("X-Forwarded-Host",request.getHeader("Host"));
exchange.addRequestHeader("X-Forwarded-Server",request.getLocalName());
}
if (hasContent)
{
exchange.setRequestContentSource(in);
}
customizeExchange(exchange, request);

View File

@ -4,11 +4,11 @@
// 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
// 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.
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.servlets;
@ -18,7 +18,6 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
@ -39,19 +38,20 @@ import javax.servlet.http.HttpServletRequest;
* <dt>attribute</dt><dd>If set, then the request attribute of this name is set with the matched user agent string</dd>
* <dt>cacheSize</dt><dd>The size of the user-agent cache, used to avoid reparsing of user agent strings. The entire cache is flushed
* when this size is reached</dd>
* <dt>userAgent</dt><dd>A regex {@link Pattern} to extract the essential elements of the user agent.
* <dt>userAgent</dt><dd>A regex {@link Pattern} to extract the essential elements of the user agent.
* The concatenation of matched pattern groups is used as the user agent name</dd>
* <dl>
* <dl>
* An example value for pattern is <code>(?:Mozilla[^\(]*\(compatible;\s*+([^;]*);.*)|(?:.*?([^\s]+/[^\s]+).*)</code>. These two
* pattern match the common compatibility user-agent strings and extract the real user agent, failing that, the first
* element of the agent string is returned.
*
* element of the agent string is returned.
*
*
*/
public class UserAgentFilter implements Filter
{
private Pattern _pattern;
private Map _agentCache = new ConcurrentHashMap();
private static final String __defaultPattern = "(?:Mozilla[^\\(]*\\(compatible;\\s*+([^;]*);.*)|(?:.*?([^\\s]+/[^\\s]+).*)";
private Pattern _pattern = Pattern.compile(__defaultPattern);
private Map<String, String> _agentCache = new ConcurrentHashMap<String, String>();
private int _agentCacheSize=1024;
private String _attribute;
@ -70,7 +70,7 @@ public class UserAgentFilter implements Filter
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
if (_attribute!=null && _pattern!=null)
{
{
String ua=getUserAgent(request);
request.setAttribute(_attribute,ua);
}
@ -84,11 +84,11 @@ public class UserAgentFilter implements Filter
public void init(FilterConfig filterConfig) throws ServletException
{
_attribute=filterConfig.getInitParameter("attribute");
String p=filterConfig.getInitParameter("userAgent");
if (p!=null)
_pattern=Pattern.compile(p);
String size=filterConfig.getInitParameter("cacheSize");
if (size!=null)
_agentCacheSize=Integer.parseInt(size);
@ -100,7 +100,7 @@ public class UserAgentFilter implements Filter
String ua=((HttpServletRequest)request).getHeader("User-Agent");
return getUserAgent(ua);
}
/* ------------------------------------------------------------ */
/** Get UserAgent.
* The configured agent patterns are used to match against the passed user agent string.
@ -111,37 +111,42 @@ public class UserAgentFilter implements Filter
*/
public String getUserAgent(String ua)
{
if (ua==null)
if (ua == null)
return null;
String tag = (String)_agentCache.get(ua);
if (tag==null)
String tag = _agentCache.get(ua);
if (tag == null)
{
Matcher matcher=_pattern.matcher(ua);
if (matcher.matches())
if (_pattern != null)
{
if(matcher.groupCount()>0)
Matcher matcher = _pattern.matcher(ua);
if (matcher.matches())
{
for (int g=1;g<=matcher.groupCount();g++)
if (matcher.groupCount() > 0)
{
String group=matcher.group(g);
if (group!=null)
tag=tag==null?group:(tag+group);
for (int g = 1; g <= matcher.groupCount(); g++)
{
String group = matcher.group(g);
if (group != null)
tag = tag == null ? group : tag + group;
}
}
else
{
tag = matcher.group();
}
}
else
tag=matcher.group();
}
else
tag=ua;
if (_agentCache.size()>=_agentCacheSize)
_agentCache.clear();
_agentCache.put(ua,tag);
if (tag == null)
tag = ua;
if (_agentCache.size() >= _agentCacheSize)
_agentCache.clear();
_agentCache.put(ua, tag);
}
return tag;
}
}

View File

@ -137,4 +137,26 @@ public class GzipFilterDefaultTest
}
@Test
public void testUserAgentExclusion() throws Exception
{
GzipTester tester = new GzipTester(testingdir);
FilterHolder holder = tester.setContentServlet(DefaultServlet.class);
holder.setInitParameter("excludedAgents", "foo");
tester.setUserAgent("foo");
int filesize = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
tester.prepareServerFile("file.txt",filesize);
try
{
tester.start();
tester.assertIsResponseNotGzipCompressed("file.txt", filesize, HttpStatus.OK_200);
}
finally
{
tester.stop();
}
}
}

View File

@ -50,11 +50,14 @@ public class MultipartFilterTest
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);
}
}
@Before
public void setUp() throws Exception
{
@ -245,6 +248,65 @@ public class MultipartFilterTest
assertTrue(response.getContent().indexOf("brown cow")>=0);
}
/*
* see the testParameterMap test
*
*/
public static class TestServletParameterMap extends DumpServlet
{
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
assertEquals("How now brown cow.", req.getParameterMap().get("strupContent-Type: application/octet-stream"));
super.doPost(req, resp);
}
}
/**
* Validate that the getParameterMap() call is correctly unencoding the parameters in the
* map that it returns.
* @throws Exception
*/
@Test
public void testParameterMap() throws Exception
{
// generated and parsed test
HttpTester request = new HttpTester();
HttpTester response = new HttpTester();
tester.addServlet(TestServletParameterMap.class,"/test2");
// test GET
request.setMethod("POST");
request.setVersion("HTTP/1.0");
request.setHeader("Host","tester");
request.setURI("/context/test2");
String boundary="XyXyXy";
request.setHeader("Content-Type","multipart/form-data; boundary="+boundary);
String content = "--" + boundary + "\r\n"+
"Content-Disposition: form-data; name=\"fileup\"; filename=\"Diplomsko Delo Lektorirano KON&#268;NA.doc\"\r\n"+
"Content-Type: application/octet-stream\r\n\r\n"+
"How now brown cow."+
"\r\n--" + boundary + "\r\n"+
"Content-Disposition: form-data; name=\"strup\""+
"Content-Type: application/octet-stream\r\n\r\n"+
"How now brown cow."+
"\r\n--" + boundary + "--\r\n\r\n";
request.setContent(content);
response.parse(tester.getResponses(request.generate()));
assertTrue(response.getMethod()==null);
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
assertTrue(response.getContent().indexOf("brown cow")>=0);
}
public static class DumpServlet extends HttpServlet
{
private static final long serialVersionUID = 201012011130L;

View File

@ -4,6 +4,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
@ -12,7 +13,6 @@ import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.Assert;
import org.eclipse.jetty.client.ContentExchange;
import org.eclipse.jetty.client.HttpClient;
@ -30,21 +30,24 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.junit.After;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
public class ProxyServletTest
{
private Server server;
private Connector connector;
private HttpClient client;
private Server _server;
private Connector _connector;
private HttpClient _client;
public void init(HttpServlet servlet) throws Exception
{
server = new Server();
_server = new Server();
connector = new SelectChannelConnector();
server.addConnector(connector);
_connector = new SelectChannelConnector();
_server.addConnector(_connector);
HandlerCollection handlers = new HandlerCollection();
server.setHandler(handlers);
_server.setHandler(handlers);
ServletContextHandler proxyCtx = new ServletContextHandler(handlers, "/proxy", ServletContextHandler.NO_SESSIONS);
ServletHolder proxyServletHolder = new ServletHolder(new ProxyServlet()
@ -66,25 +69,49 @@ public class ProxyServletTest
handlers.addHandler(proxyCtx);
handlers.addHandler(appCtx);
server.start();
_server.start();
client = new HttpClient();
client.start();
_client = new HttpClient();
_client.start();
}
@After
public void destroy() throws Exception
{
if (client != null)
client.stop();
if (_client != null)
_client.stop();
if (server != null)
if (_server != null)
{
server.stop();
server.join();
_server.stop();
_server.join();
}
}
@Test
public void testXForwardedHostHeader() throws Exception
{
init(new HttpServlet()
{
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
PrintWriter writer = resp.getWriter();
writer.write(req.getHeader("X-Forwarded-Host"));
writer.flush();
}
});
String url = "http://localhost:" + _connector.getLocalPort() + "/proxy/test";
ContentExchange exchange = new ContentExchange();
exchange.setURL(url);
_client.send(exchange);
exchange.waitForDone();
assertThat("Response expected to contain content of X-Forwarded-Host Header from the request",exchange.getResponseContent(),equalTo("localhost:"
+ _connector.getLocalPort()));
}
@Test
public void testBigDownloadWithSlowReader() throws Exception
@ -101,6 +128,8 @@ public class ProxyServletTest
init(new HttpServlet()
{
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
@ -114,7 +143,7 @@ public class ProxyServletTest
}
});
String url = "http://localhost:" + connector.getLocalPort() + "/proxy" + "/test";
String url = "http://localhost:" + _connector.getLocalPort() + "/proxy/test";
ContentExchange exchange = new ContentExchange(true)
{
@Override
@ -134,7 +163,7 @@ public class ProxyServletTest
};
exchange.setURL(url);
long start = System.nanoTime();
client.send(exchange);
_client.send(exchange);
Assert.assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
long elapsed = System.nanoTime() - start;
Assert.assertEquals(HttpStatus.OK_200, exchange.getResponseStatus());

View File

@ -36,6 +36,7 @@ public class GzipTester
{
private Class<? extends GzipFilter> gzipFilterClass = GzipFilter.class;
private String encoding = "ISO8859_1";
private String userAgent = null;
private ServletTester servletTester;
private TestingDir testdir;
@ -61,6 +62,8 @@ public class GzipTester
request.setVersion("HTTP/1.0");
request.setHeader("Host","tester");
request.setHeader("Accept-Encoding","gzip");
if (this.userAgent != null)
request.setHeader("User-Agent", this.userAgent);
request.setURI("/context/" + requestedFilename);
// Issue the request
@ -126,6 +129,8 @@ public class GzipTester
request.setVersion("HTTP/1.0");
request.setHeader("Host","tester");
request.setHeader("Accept-Encoding","gzip");
if (this.userAgent != null)
request.setHeader("User-Agent", this.userAgent);
request.setURI("/context/" + requestedFilename);
// Issue the request
@ -211,6 +216,8 @@ public class GzipTester
request.setVersion("HTTP/1.0");
request.setHeader("Host","tester");
request.setHeader("Accept-Encoding","gzip");
if (this.userAgent != null)
request.setHeader("User-Agent", this.userAgent);
if (filename == null)
request.setURI("/context/");
else
@ -384,6 +391,11 @@ public class GzipTester
{
this.encoding = encoding;
}
public void setUserAgent(String ua)
{
this.userAgent = ua;
}
public void start() throws Exception
{

60
jetty-spdy/pom.xml Normal file
View File

@ -0,0 +1,60 @@
<?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/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-parent</artifactId>
<packaging>pom</packaging>
<name>Jetty :: SPDY :: Parent</name>
<modules>
<module>spdy-core</module>
<module>spdy-jetty</module>
<module>spdy-jetty-http</module>
<module>spdy-jetty-http-webapp</module>
</modules>
<build>
<plugins>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>require-jdk7</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireJavaVersion>
<version>[1.7,)</version>
</requireJavaVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-pmd-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,32 @@
<?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/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-parent</artifactId>
<version>7.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spdy-core</artifactId>
<name>Jetty :: SPDY :: Core</name>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j-version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.spdy;
import java.nio.ByteBuffer;
/**
* <p>A {@link ByteBuffer} pool.</p>
* <p>Acquired buffers may be {@link #release(ByteBuffer) released} but they do not need to;
* if they are released, they may be recycled and reused, otherwise they will be garbage
* collected as usual.</p>
*/
public interface ByteBufferPool
{
/**
* <p>Requests a {@link ByteBuffer} of the given size.</p>
* <p>The returned buffer may have a bigger capacity than the size being
* requested but it will have the limit set to the given size.</p>
*
* @param size the size of the buffer
* @param direct whether the buffer must be direct or not
* @return the requested buffer
* @see #release(ByteBuffer)
*/
public ByteBuffer acquire(int size, boolean direct);
/**
* <p>Returns a {@link ByteBuffer}, usually obtained with {@link #acquire(int, boolean)}
* (but not necessarily), making it available for recycling and reuse.</p>
*
* @param buffer the buffer to return
* @see #acquire(int, boolean)
*/
public void release(ByteBuffer buffer);
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.spdy;
import org.eclipse.jetty.spdy.api.SPDY;
public class CompressionDictionary
{
private static final byte[] DICTIONARY_V2 = ("" +
"optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-" +
"languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi" +
"f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser" +
"-agent10010120020120220320420520630030130230330430530630740040140240340440" +
"5406407408409410411412413414415416417500501502503504505accept-rangesageeta" +
"glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic" +
"ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran" +
"sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati" +
"oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo" +
"ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe" +
"pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic" +
"ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1" +
".1statusversionurl" +
// Must be NUL terminated
"\u0000").getBytes();
private static final byte[] DICTIONARY_V3 = ("" +
"\u0000\u0000\u0000\u0007options\u0000\u0000\u0000\u0004head\u0000\u0000\u0000\u0004post" +
"\u0000\u0000\u0000\u0003put\u0000\u0000\u0000\u0006delete\u0000\u0000\u0000\u0005trace" +
"\u0000\u0000\u0000\u0006accept\u0000\u0000\u0000\u000Eaccept-charset" +
"\u0000\u0000\u0000\u000Faccept-encoding\u0000\u0000\u0000\u000Faccept-language" +
"\u0000\u0000\u0000\raccept-ranges\u0000\u0000\u0000\u0003age\u0000\u0000\u0000\u0005allow" +
"\u0000\u0000\u0000\rauthorization\u0000\u0000\u0000\rcache-control" +
"\u0000\u0000\u0000\nconnection\u0000\u0000\u0000\fcontent-base\u0000\u0000\u0000\u0010content-encoding" +
"\u0000\u0000\u0000\u0010content-language\u0000\u0000\u0000\u000Econtent-length" +
"\u0000\u0000\u0000\u0010content-location\u0000\u0000\u0000\u000Bcontent-md5" +
"\u0000\u0000\u0000\rcontent-range\u0000\u0000\u0000\fcontent-type\u0000\u0000\u0000\u0004date" +
"\u0000\u0000\u0000\u0004etag\u0000\u0000\u0000\u0006expect\u0000\u0000\u0000\u0007expires" +
"\u0000\u0000\u0000\u0004from\u0000\u0000\u0000\u0004host\u0000\u0000\u0000\bif-match" +
"\u0000\u0000\u0000\u0011if-modified-since\u0000\u0000\u0000\rif-none-match\u0000\u0000\u0000\bif-range" +
"\u0000\u0000\u0000\u0013if-unmodified-since\u0000\u0000\u0000\rlast-modified" +
"\u0000\u0000\u0000\blocation\u0000\u0000\u0000\fmax-forwards\u0000\u0000\u0000\u0006pragma" +
"\u0000\u0000\u0000\u0012proxy-authenticate\u0000\u0000\u0000\u0013proxy-authorization" +
"\u0000\u0000\u0000\u0005range\u0000\u0000\u0000\u0007referer\u0000\u0000\u0000\u000Bretry-after" +
"\u0000\u0000\u0000\u0006server\u0000\u0000\u0000\u0002te\u0000\u0000\u0000\u0007trailer" +
"\u0000\u0000\u0000\u0011transfer-encoding\u0000\u0000\u0000\u0007upgrade\u0000\u0000\u0000\nuser-agent" +
"\u0000\u0000\u0000\u0004vary\u0000\u0000\u0000\u0003via\u0000\u0000\u0000\u0007warning" +
"\u0000\u0000\u0000\u0010www-authenticate\u0000\u0000\u0000\u0006method\u0000\u0000\u0000\u0003get" +
"\u0000\u0000\u0000\u0006status\u0000\u0000\u0000\u0006200 OK\u0000\u0000\u0000\u0007version" +
"\u0000\u0000\u0000\bHTTP/1.1\u0000\u0000\u0000\u0003url\u0000\u0000\u0000\u0006public" +
"\u0000\u0000\u0000\nset-cookie\u0000\u0000\u0000\nkeep-alive\u0000\u0000\u0000\u0006origin" +
"100101201202205206300302303304305306307402405406407408409410411412413414415416417502504505" +
"203 Non-Authoritative Information204 No Content301 Moved Permanently400 Bad Request401 Unauthorized" +
"403 Forbidden404 Not Found500 Internal Server Error501 Not Implemented503 Service Unavailable" +
"Jan Feb Mar Apr May Jun Jul Aug Sept Oct Nov Dec 00:00:00 Mon, Tue, Wed, Thu, Fri, Sat, Sun, GMT" +
"chunked,text/html,image/png,image/jpg,image/gif,application/xml,application/xhtml+xml,text/plain," +
"text/javascript,publicprivatemax-age=gzip,deflate,sdchcharset=utf-8charset=iso-8859-1,utf-,*,enq=0.")
.getBytes();
public static byte[] get(short version)
{
switch (version)
{
case SPDY.V2:
return DICTIONARY_V2;
case SPDY.V3:
return DICTIONARY_V3;
default:
throw new IllegalStateException();
}
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.spdy;
import java.util.zip.ZipException;
public interface CompressionFactory
{
public Compressor newCompressor();
public Decompressor newDecompressor();
public interface Compressor
{
public void setInput(byte[] input);
public void setDictionary(byte[] dictionary);
public int compress(byte[] output);
}
public interface Decompressor
{
public void setDictionary(byte[] dictionary);
public void setInput(byte[] input);
public int decompress(byte[] output) throws ZipException;
}
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.spdy;
import java.nio.ByteBuffer;
import org.eclipse.jetty.spdy.api.Handler;
public interface Controller<T>
{
public int write(ByteBuffer buffer, Handler<T> handler, T context);
public void close(boolean onlyOutput);
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.spdy;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.Handler;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.frames.ControlFrame;
public interface ISession extends Session
{
/**
* <p>Initiates the flush of data to the other peer.</p>
* <p>Note that the flush may do nothing if, for example, there is nothing to flush, or
* if the data to be flushed belong to streams that have their flow-control stalled.</p>
*/
public void flush();
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();
}

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.spdy;
import java.nio.ByteBuffer;
import org.eclipse.jetty.spdy.api.SessionFrameListener;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.frames.ControlFrame;
import org.eclipse.jetty.spdy.frames.DataFrame;
/**
* <p>The internal interface that represents a stream.</p>
* <p>{@link IStream} contains additional methods used by a SPDY
* implementation (and not by an application).</p>
*/
public interface IStream extends Stream
{
/**
* <p>Senders of data frames need to know the current window size
* to determine whether they can send more data.</p>
*
* @return the current window size for this stream.
* @see #updateWindowSize(int)
*/
public int getWindowSize();
/**
* <p>Updates the window size for this stream by the given amount,
* that can be positive or negative.</p>
* <p>Senders and recipients of data frames update the window size,
* respectively, with negative values and positive values.</p>
*
* @param delta the signed amount the window size needs to be updated
* @see #getWindowSize()
*/
public void updateWindowSize(int delta);
/**
* @param listener the stream frame listener associated to this stream
* as returned by {@link SessionFrameListener#onSyn(Stream, SynInfo)}
*/
public void setStreamFrameListener(StreamFrameListener listener);
/**
* <p>A stream can be open, {@link #isHalfClosed() half closed} or
* {@link #isClosed() closed} and this method updates the close state
* of this stream.</p>
* <p>If the stream is open, calling this method with a value of true
* puts the stream into half closed state.</p>
* <p>If the stream is half closed, calling this method with a value
* of true puts the stream into closed state.</p>
*
* @param close whether the close state should be updated
*/
public void updateCloseState(boolean close);
/**
* <p>Processes the given control frame,
* for example by updating the stream's state or by calling listeners.</p>
*
* @param frame the control frame to process
* @see #process(DataFrame, ByteBuffer)
*/
public void process(ControlFrame frame);
/**
* <p>Processes the give data frame along with the given byte buffer,
* for example by updating the stream's state or by calling listeners.</p>
*
* @param frame the data frame to process
* @param data the byte buffer to process
* @see #process(ControlFrame)
*/
public void process(DataFrame frame, ByteBuffer data);
}

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.spdy;
public interface IdleListener
{
public void onIdle(boolean idle);
}

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.spdy;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.eclipse.jetty.spdy.api.Handler;
/**
* <p>A {@link Promise} is a {@link Future} that allows a result or a failure to be set,
* so that the {@link Future} will be {@link #isDone() done}.</p>
*
* @param <T> the type of the result object
*/
public class Promise<T> implements Handler<T>, Future<T>
{
private final CountDownLatch latch = new CountDownLatch(1);
private boolean cancelled;
private Throwable failure;
private T promise;
@Override
public void completed(T result)
{
this.promise = result;
latch.countDown();
}
public void failed(Throwable x)
{
this.failure = x;
latch.countDown();
}
@Override
public boolean cancel(boolean mayInterruptIfRunning)
{
cancelled = true;
latch.countDown();
return true;
}
@Override
public boolean isCancelled()
{
return cancelled;
}
@Override
public boolean isDone()
{
return cancelled || latch.getCount() == 0;
}
@Override
public T get() throws InterruptedException, ExecutionException
{
latch.await();
return result();
}
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
{
latch.await(timeout, unit);
return result();
}
private T result() throws ExecutionException
{
Throwable failure = this.failure;
if (failure != null)
throw new ExecutionException(failure);
return promise;
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.spdy;
import org.eclipse.jetty.spdy.api.SessionStatus;
public class SessionException extends RuntimeException
{
private final SessionStatus sessionStatus;
public SessionException(SessionStatus sessionStatus)
{
this.sessionStatus = sessionStatus;
}
public SessionException(SessionStatus sessionStatus, String message)
{
super(message);
this.sessionStatus = sessionStatus;
}
public SessionException(SessionStatus sessionStatus, Throwable cause)
{
super(cause);
this.sessionStatus = sessionStatus;
}
public SessionStatus getSessionStatus()
{
return sessionStatus;
}
}

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.spdy;
import java.nio.ByteBuffer;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
public class StandardByteBufferPool implements ByteBufferPool
{
private final ConcurrentMap<Integer, Queue<ByteBuffer>> directBuffers = new ConcurrentHashMap<>();
private final ConcurrentMap<Integer, Queue<ByteBuffer>> heapBuffers = new ConcurrentHashMap<>();
private final int factor;
public StandardByteBufferPool()
{
this(1024);
}
public StandardByteBufferPool(int factor)
{
this.factor = factor;
}
public ByteBuffer acquire(int size, boolean direct)
{
int bucket = bucketFor(size);
ConcurrentMap<Integer, Queue<ByteBuffer>> buffers = buffersFor(direct);
ByteBuffer result = null;
Queue<ByteBuffer> byteBuffers = buffers.get(bucket);
if (byteBuffers != null)
result = byteBuffers.poll();
if (result == null)
{
int capacity = bucket * factor;
result = direct ? ByteBuffer.allocateDirect(capacity) : ByteBuffer.allocate(capacity);
}
result.clear();
result.limit(size);
return result;
}
public void release(ByteBuffer buffer)
{
int bucket = bucketFor(buffer.capacity());
ConcurrentMap<Integer, Queue<ByteBuffer>> buffers = buffersFor(buffer.isDirect());
// Avoid to create a new queue every time, just to be discarded immediately
Queue<ByteBuffer> byteBuffers = buffers.get(bucket);
if (byteBuffers == null)
{
byteBuffers = new ConcurrentLinkedQueue<>();
Queue<ByteBuffer> existing = buffers.putIfAbsent(bucket, byteBuffers);
if (existing != null)
byteBuffers = existing;
}
buffer.clear();
byteBuffers.offer(buffer);
}
public void clear()
{
directBuffers.clear();
heapBuffers.clear();
}
private int bucketFor(int size)
{
int bucket = size / factor;
if (size % factor > 0)
++bucket;
return bucket;
}
private ConcurrentMap<Integer, Queue<ByteBuffer>> buffersFor(boolean direct)
{
return direct ? directBuffers : heapBuffers;
}
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.spdy;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
import java.util.zip.ZipException;
public class StandardCompressionFactory implements CompressionFactory
{
@Override
public Compressor newCompressor()
{
return new StandardCompressor();
}
@Override
public Decompressor newDecompressor()
{
return new StandardDecompressor();
}
public static class StandardCompressor implements Compressor
{
private final Deflater deflater = new Deflater();
@Override
public void setInput(byte[] input)
{
deflater.setInput(input);
}
@Override
public void setDictionary(byte[] dictionary)
{
deflater.setDictionary(dictionary);
}
@Override
public int compress(byte[] output)
{
return deflater.deflate(output, 0, output.length, Deflater.SYNC_FLUSH);
}
}
public static class StandardDecompressor implements CompressionFactory.Decompressor
{
private final Inflater inflater = new Inflater();
@Override
public void setDictionary(byte[] dictionary)
{
inflater.setDictionary(dictionary);
}
@Override
public void setInput(byte[] input)
{
inflater.setInput(input);
}
@Override
public int decompress(byte[] output) throws ZipException
{
try
{
return inflater.inflate(output);
}
catch (DataFormatException x)
{
throw (ZipException)new ZipException().initCause(x);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,337 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.spdy;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.Handler;
import org.eclipse.jetty.spdy.api.HeadersInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.RstInfo;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.StreamStatus;
import org.eclipse.jetty.spdy.frames.ControlFrame;
import org.eclipse.jetty.spdy.frames.DataFrame;
import org.eclipse.jetty.spdy.frames.HeadersFrame;
import org.eclipse.jetty.spdy.frames.SynReplyFrame;
import org.eclipse.jetty.spdy.frames.SynStreamFrame;
import org.eclipse.jetty.spdy.frames.WindowUpdateFrame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class StandardStream implements IStream
{
private static final Logger logger = LoggerFactory.getLogger(Stream.class);
private final Map<String, Object> attributes = new ConcurrentHashMap<>();
private final SynStreamFrame frame;
private final ISession session;
private final AtomicInteger windowSize;
private volatile StreamFrameListener listener;
private volatile boolean opened;
private volatile boolean halfClosed;
private volatile boolean closed;
public StandardStream(SynStreamFrame frame, ISession session, int windowSize)
{
this.frame = frame;
this.session = session;
this.windowSize = new AtomicInteger(windowSize);
this.halfClosed = frame.isClose();
}
@Override
public int getId()
{
return frame.getStreamId();
}
@Override
public byte getPriority()
{
return frame.getPriority();
}
@Override
public int getWindowSize()
{
return windowSize.get();
}
@Override
public void updateWindowSize(int delta)
{
int size = windowSize.addAndGet(delta);
logger.debug("Updated window size by {}, new window size {}", delta, size);
}
@Override
public Session getSession()
{
return session;
}
public boolean isHalfClosed()
{
return halfClosed;
}
@Override
public Object getAttribute(String key)
{
return attributes.get(key);
}
@Override
public void setAttribute(String key, Object value)
{
attributes.put(key, value);
}
@Override
public Object removeAttribute(String key)
{
return attributes.remove(key);
}
@Override
public void setStreamFrameListener(StreamFrameListener listener)
{
this.listener = listener;
}
@Override
public void updateCloseState(boolean close)
{
if (close)
{
if (isHalfClosed())
closed = true;
else
halfClosed = true;
}
}
@Override
public void process(ControlFrame frame)
{
switch (frame.getType())
{
case SYN_STREAM:
{
opened = true;
break;
}
case SYN_REPLY:
{
opened = true;
SynReplyFrame synReply = (SynReplyFrame)frame;
updateCloseState(synReply.isClose());
ReplyInfo replyInfo = new ReplyInfo(synReply.getHeaders(), synReply.isClose());
notifyOnReply(replyInfo);
break;
}
case HEADERS:
{
HeadersFrame headers = (HeadersFrame)frame;
updateCloseState(headers.isClose());
HeadersInfo headersInfo = new HeadersInfo(headers.getHeaders(), headers.isClose(), headers.isResetCompression());
notifyOnHeaders(headersInfo);
break;
}
case WINDOW_UPDATE:
{
WindowUpdateFrame windowUpdate = (WindowUpdateFrame)frame;
updateWindowSize(windowUpdate.getWindowDelta());
break;
}
case RST_STREAM:
{
// TODO:
break;
}
default:
{
throw new IllegalStateException();
}
}
session.flush();
}
@Override
public void process(DataFrame frame, ByteBuffer data)
{
if (!opened)
{
session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR));
return;
}
updateCloseState(frame.isClose());
ByteBufferDataInfo dataInfo = new ByteBufferDataInfo(data, frame.isClose(), frame.isCompress())
{
@Override
public void consume(int delta)
{
super.consume(delta);
// This is the algorithm for flow control.
// This method may be called multiple times with delta=1, but we only send a window
// update when the whole dataInfo has been consumed.
// Other policies may be to send window updates when consumed() is greater than
// a certain threshold, etc. but for now the policy is not pluggable for simplicity.
// Note that the frequency of window updates depends on the read buffer, that
// should not be too smaller than the window size to avoid frequent window updates.
// Therefore, a pluggable policy should be able to modify the read buffer capacity.
if (consumed() == length() && !isClosed())
windowUpdate(length());
}
};
notifyOnData(dataInfo);
session.flush();
}
private void windowUpdate(int delta)
{
if (delta > 0)
{
WindowUpdateFrame windowUpdateFrame = new WindowUpdateFrame(session.getVersion(), getId(), delta);
session.control(this, windowUpdateFrame, 0, TimeUnit.MILLISECONDS, null, null);
}
}
private void notifyOnReply(ReplyInfo replyInfo)
{
final StreamFrameListener listener = this.listener;
try
{
if (listener != null)
{
logger.debug("Invoking reply callback with {} on listener {}", replyInfo, listener);
listener.onReply(this, replyInfo);
}
}
catch (Exception x)
{
logger.info("Exception while notifying listener " + listener, x);
}
}
private void notifyOnHeaders(HeadersInfo headersInfo)
{
final StreamFrameListener listener = this.listener;
try
{
if (listener != null)
{
logger.debug("Invoking headers callback with {} on listener {}", frame, listener);
listener.onHeaders(this, headersInfo);
}
}
catch (Exception x)
{
logger.info("Exception while notifying listener " + listener, x);
}
}
private void notifyOnData(DataInfo dataInfo)
{
final StreamFrameListener listener = this.listener;
try
{
if (listener != null)
{
logger.debug("Invoking data callback with {} on listener {}", dataInfo, listener);
listener.onData(this, dataInfo);
logger.debug("Invoked data callback with {} on listener {}", dataInfo, listener);
}
}
catch (Exception x)
{
logger.info("Exception while notifying listener " + listener, x);
}
}
@Override
public Future<Void> reply(ReplyInfo replyInfo)
{
Promise<Void> result = new Promise<>();
reply(replyInfo, 0, TimeUnit.MILLISECONDS, result);
return result;
}
@Override
public void reply(ReplyInfo replyInfo, long timeout, TimeUnit unit, Handler<Void> handler)
{
updateCloseState(replyInfo.isClose());
SynReplyFrame frame = new SynReplyFrame(session.getVersion(), replyInfo.getFlags(), getId(), replyInfo.getHeaders());
session.control(this, frame, timeout, unit, handler, null);
}
@Override
public Future<Void> data(DataInfo dataInfo)
{
Promise<Void> result = new Promise<>();
data(dataInfo, 0, TimeUnit.MILLISECONDS, result);
return result;
}
@Override
public void data(DataInfo dataInfo, long timeout, TimeUnit unit, Handler<Void> handler)
{
// Cannot update the close state here, because the data that we send may
// be flow controlled, so we need the stream to update the window size.
session.data(this, dataInfo, timeout, unit, handler, null);
}
@Override
public Future<Void> headers(HeadersInfo headersInfo)
{
Promise<Void> result = new Promise<>();
headers(headersInfo, 0, TimeUnit.MILLISECONDS, result);
return result;
}
@Override
public void headers(HeadersInfo headersInfo, long timeout, TimeUnit unit, Handler<Void> handler)
{
updateCloseState(headersInfo.isClose());
HeadersFrame frame = new HeadersFrame(session.getVersion(), headersInfo.getFlags(), getId(), headersInfo.getHeaders());
session.control(this, frame, timeout, unit, handler, null);
}
@Override
public boolean isClosed()
{
return closed;
}
@Override
public String toString()
{
return String.format("stream=%d v%d closed=%s", getId(), session.getVersion(), isClosed() ? "true" : isHalfClosed() ? "half" : "false");
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.spdy;
import org.eclipse.jetty.spdy.api.StreamStatus;
public class StreamException extends RuntimeException
{
private final int streamId;
private final StreamStatus streamStatus;
public StreamException(int streamId, StreamStatus streamStatus)
{
this.streamId = streamId;
this.streamStatus = streamStatus;
}
public StreamException(int streamId, StreamStatus streamStatus, String message)
{
super(message);
this.streamId = streamId;
this.streamStatus = streamStatus;
}
public int getStreamId()
{
return streamId;
}
public StreamStatus getStreamStatus()
{
return streamStatus;
}
}

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.spdy.api;
import java.nio.ByteBuffer;
/**
* <p>Specialized {@link DataInfo} for {@link ByteBuffer} content.</p>
*/
public class ByteBufferDataInfo extends DataInfo
{
private final ByteBuffer buffer;
private final int length;
public ByteBufferDataInfo(ByteBuffer buffer, boolean close)
{
this(buffer, close, false);
}
public ByteBufferDataInfo(ByteBuffer buffer, boolean close, boolean compress)
{
super(close, compress);
this.buffer = buffer;
this.length = buffer.remaining();
}
@Override
public int length()
{
return length;
}
@Override
public int available()
{
return buffer.remaining();
}
@Override
public int readInto(ByteBuffer output)
{
int space = output.remaining();
if (available() > space)
{
int limit = buffer.limit();
buffer.limit(buffer.position() + space);
output.put(buffer);
buffer.limit(limit);
}
else
{
space = buffer.remaining();
output.put(buffer);
}
return space;
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.spdy.api;
import java.nio.ByteBuffer;
/**
* <p>Specialized {@link DataInfo} for byte array content.</p>
*/
public class BytesDataInfo extends DataInfo
{
private byte[] bytes;
private int offset;
public BytesDataInfo(byte[] bytes, boolean close)
{
this(bytes, close, false);
}
public BytesDataInfo(byte[] bytes, boolean close, boolean compress)
{
super(close, compress);
this.bytes = bytes;
}
@Override
public int length()
{
return bytes.length;
}
@Override
public int available()
{
return length() - offset;
}
@Override
public int readInto(ByteBuffer output)
{
int space = output.remaining();
int length = Math.min(available(), space);
output.put(bytes, offset, length);
offset += length;
return length;
}
}

View File

@ -0,0 +1,249 @@
/*
* Copyright (c) 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.jetty.spdy.api;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.concurrent.atomic.AtomicInteger;
/**
* <p>A container for DATA frames metadata and content bytes.</p>
* <p>Specialized subclasses (like {@link StringDataInfo}) may be used by applications
* to send specific types of content.</p>
* <p>Applications may send multiple instances of {@link DataInfo}, usually of the same
* type, via {@link Stream#data(DataInfo)}. The last instance must have the
* {@link #isClose() close flag} set, so that the client knows that no more content is
* expected.</p>
* <p>Receivers of {@link DataInfo} via {@link StreamFrameListener#onData(Stream, DataInfo)}
* have two different APIs to read the data content bytes: a {@link #readInto(ByteBuffer) read}
* API that does not interact with flow control, and a {@link #consumeInto(ByteBuffer) drain}
* API that interacts with flow control.</p>
* <p>Flow control is defined so that when the sender wants to sends a number of bytes larger
* than the {@link Settings.ID#INITIAL_WINDOW_SIZE} value, it will stop sending as soon as it
* has sent a number of bytes equal to the window size. The receiver has to <em>consume</em>
* the data bytes that it received in order to tell the sender to send more bytes.</p>
* <p>Consuming the data bytes can be done only via {@link #consumeInto(ByteBuffer)} or by a combination
* of {@link #readInto(ByteBuffer)} and {@link #consume(int)} (possibly at different times).</p>
*/
public abstract class DataInfo
{
/**
* <p>Flag that indicates that this {@link DataInfo} is the last frame in the stream.</p>
*
* @see #isClose()
* @see #getFlags()
*/
public final static byte FLAG_CLOSE = 1;
/**
* <p>Flag that indicates that this {@link DataInfo}'s data is compressed.</p>
*
* @see #isCompress()
* @see #getFlags()
*/
public final static byte FLAG_COMPRESS = 2;
private final AtomicInteger consumed = new AtomicInteger();
private boolean close;
private boolean compress;
/**
* <p>Creates a new {@link DataInfo} with the given close flag and no compression flag.</p>
*
* @param close the value of the close flag
*/
public DataInfo(boolean close)
{
setClose(close);
}
/**
* <p>Creates a new {@link DataInfo} with the given close flag and given compression flag.</p>
*
* @param close the close flag
* @param compress the compress flag
*/
public DataInfo(boolean close, boolean compress)
{
setClose(close);
setCompress(compress);
}
/**
* @return the value of the compress flag
* @see #setCompress(boolean)
*/
public boolean isCompress()
{
return compress;
}
/**
* @param compress the value of the compress flag
* @see #isCompress()
*/
public void setCompress(boolean compress)
{
this.compress = compress;
}
/**
* @return the value of the close flag
* @see #setClose(boolean)
*/
public boolean isClose()
{
return close;
}
/**
* @param close the value of the close flag
* @see #isClose()
*/
public void setClose(boolean close)
{
this.close = close;
}
/**
* @return the close and compress flags as integer
* @see #FLAG_CLOSE
* @see #FLAG_COMPRESS
*/
public byte getFlags()
{
byte flags = isClose() ? FLAG_CLOSE : 0;
flags |= isCompress() ? FLAG_COMPRESS : 0;
return flags;
}
/**
* @return the total number of content bytes
* @see #available()
*/
public abstract int length();
/**
* <p>Returns the available content bytes that can be read via {@link #readInto(ByteBuffer)}.</p>
* <p>Each invocation to {@link #readInto(ByteBuffer)} modifies the value returned by this method,
* until no more content bytes are available.</p>
*
* @return the available content bytes
* @see #readInto(ByteBuffer)
*/
public abstract int available();
/**
* <p>Copies the content bytes of this {@link DataInfo} into the given {@link ByteBuffer}.</p>
* <p>If the given {@link ByteBuffer} cannot contain the whole content of this {@link DataInfo}
* then after the read {@link #available()} will return a positive value, and further content
* may be retrieved by invoking again this method with a new output buffer.</p>
*
* @param output the {@link ByteBuffer} to copy to bytes into
* @return the number of bytes copied
* @see #available()
* @see #consumeInto(ByteBuffer)
*/
public abstract int readInto(ByteBuffer output);
/**
* <p>Reads and consumes the content bytes of this {@link DataInfo} into the given {@link ByteBuffer}.</p>
*
* @param output the {@link ByteBuffer} to copy to bytes into
* @return the number of bytes copied
* @see #consume(int)
*/
public int consumeInto(ByteBuffer output)
{
int read = readInto(output);
consume(read);
return read;
}
/**
* <p>Consumes the given number of bytes from this {@link DataInfo}.</p>
*
* @param delta the number of bytes consumed
*/
public void consume(int delta)
{
if (delta < 0)
throw new IllegalArgumentException();
int read = length() - available();
int newConsumed = consumed() + delta;
// if (newConsumed > read)
// throw new IllegalStateException("Consuming without reading: consumed " + newConsumed + " but only read " + read);
consumed.addAndGet(delta);
}
/**
* @return the number of bytes consumed
*/
public int consumed()
{
return consumed.get();
}
/**
*
* @param charset the charset used to convert the bytes
* @param consume whether to consume the content
* @return a String with the content of this {@link DataInfo}
*/
public String asString(String charset, boolean consume)
{
ByteBuffer buffer = asByteBuffer(consume);
return Charset.forName(charset).decode(buffer).toString();
}
/**
* @return a byte array with the content of this {@link DataInfo}
* @param consume whether to consume the content
*/
public byte[] asBytes(boolean consume)
{
ByteBuffer buffer = asByteBuffer(consume);
byte[] result = new byte[buffer.remaining()];
buffer.get(result);
return result;
}
/**
* @return a {@link ByteBuffer} with the content of this {@link DataInfo}
* @param consume whether to consume the content
*/
public ByteBuffer asByteBuffer(boolean consume)
{
ByteBuffer buffer = allocate(available());
if (consume)
consumeInto(buffer);
else
readInto(buffer);
buffer.flip();
return buffer;
}
protected ByteBuffer allocate(int size)
{
return ByteBuffer.allocate(size);
}
@Override
public String toString()
{
return String.format("DATA @%x available=%d consumed=%d close=%b compress=%b", hashCode(), available(), consumed(), isClose(), isCompress());
}
}

Some files were not shown because too many files have changed in this diff Show More