Merge branch 'master' into extra-start-dirs

This commit is contained in:
Joakim Erdfelt 2014-04-10 11:55:52 -07:00
commit 4f49bb9584
22 changed files with 543 additions and 364 deletions

View File

@ -152,7 +152,7 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
}
default:
{
throw new IllegalStateException(current.toString());
throw illegalSenderState(current);
}
}
}
@ -178,7 +178,7 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
if (expects100Continue(request))
newSenderState = content.hasContent() ? SenderState.EXPECTING_WITH_CONTENT : SenderState.EXPECTING;
if (!updateSenderState(SenderState.IDLE, newSenderState))
throw new IllegalStateException();
throw illegalSenderState(SenderState.IDLE);
// Setting the listener may trigger calls to onContent() by other
// threads so we must set it only after the sender state has been updated
@ -462,7 +462,7 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
{
// There is content to send.
if (!updateSenderState(current, SenderState.SENDING))
throw new IllegalStateException();
throw illegalSenderState(current);
LOG.debug("Proceeding while waiting");
sendContent(exchange, content, contentCallback); // TODO old style usage!
return;
@ -471,14 +471,14 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
{
// No content to send yet - it's deferred.
if (!updateSenderState(current, SenderState.IDLE))
throw new IllegalStateException();
throw illegalSenderState(current);
LOG.debug("Proceeding deferred");
return;
}
}
default:
{
throw new IllegalStateException(current.toString());
throw illegalSenderState(current);
}
}
}
@ -532,6 +532,11 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
}
}
private RuntimeException illegalSenderState(SenderState current)
{
return new IllegalStateException("Expected " + current + " found " + senderState.get() + " instead");
}
/**
* The request states {@link HttpSender} goes through when sending a request.
*/
@ -723,7 +728,7 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
}
default:
{
throw new IllegalStateException();
throw illegalSenderState(current);
}
}
}
@ -792,11 +797,11 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
return Action.SCHEDULED;
}
}
throw new IllegalStateException();
throw illegalSenderState(current);
}
default:
{
throw new IllegalStateException();
throw illegalSenderState(current);
}
}
}

View File

@ -213,7 +213,11 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
@Override
public void earlyEOF()
{
failAndClose(new EOFException());
HttpExchange exchange = getHttpExchange();
if (exchange == null)
getHttpConnection().close();
else
failAndClose(new EOFException());
}
@Override
@ -244,10 +248,8 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
private void failAndClose(Throwable failure)
{
// Close the connection anyway, even if responseFailure() returns false.
// This may happen for idle closes (there is no exchange to fail).
responseFailure(failure);
getHttpConnection().close(failure);
if (responseFailure(failure))
getHttpConnection().close(failure);
}
@Override

View File

@ -1201,7 +1201,30 @@ public class HttpClientTest extends AbstractHttpClientServerTest
}
@Test
public void testContentDelimitedByEOFWithSlowRequest() throws Exception
public void testSmallContentDelimitedByEOFWithSlowRequestHTTP10() throws Exception
{
testContentDelimitedByEOFWithSlowRequest(HttpVersion.HTTP_1_0, 1024);
}
@Test
public void testBigContentDelimitedByEOFWithSlowRequestHTTP10() throws Exception
{
testContentDelimitedByEOFWithSlowRequest(HttpVersion.HTTP_1_0, 128 * 1024);
}
@Test
public void testSmallContentDelimitedByEOFWithSlowRequestHTTP11() throws Exception
{
testContentDelimitedByEOFWithSlowRequest(HttpVersion.HTTP_1_1, 1024);
}
@Test
public void testBigContentDelimitedByEOFWithSlowRequestHTTP11() throws Exception
{
testContentDelimitedByEOFWithSlowRequest(HttpVersion.HTTP_1_1, 128 * 1024);
}
private void testContentDelimitedByEOFWithSlowRequest(final HttpVersion version, int length) throws Exception
{
// This test is crafted in a way that the response completes before the request is fully written.
// With SSL, the response coming down will close the SSLEngine so it would not be possible to
@ -1210,7 +1233,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
// This is a limit of Java's SSL implementation that does not allow half closes.
Assume.assumeTrue(sslContextFactory == null);
final byte[] data = new byte[8 * 1024];
final byte[] data = new byte[length];
new Random().nextBytes(data);
start(new AbstractHandler()
{
@ -1218,7 +1241,9 @@ public class HttpClientTest extends AbstractHttpClientServerTest
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
response.setHeader("Connection", "close");
// Send Connection: close to avoid that the server chunks the content with HTTP 1.1.
if (version.compareTo(HttpVersion.HTTP_1_0) > 0)
response.setHeader("Connection", "close");
response.getOutputStream().write(data);
}
});
@ -1226,6 +1251,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
DeferredContentProvider content = new DeferredContentProvider(ByteBuffer.wrap(new byte[]{0}));
Request request = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.version(version)
.content(content);
FutureResponseListener listener = new FutureResponseListener(request);
request.send(listener);

View File

@ -23,6 +23,7 @@ import java.io.EOFException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@ -221,8 +222,22 @@ public class HttpReceiverOverHTTPTest
"Content-Length: " + gzip.length + "\r\n" +
"Content-Encoding: gzip\r\n" +
"\r\n");
HttpExchange exchange = newExchange();
FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
HttpRequest request = (HttpRequest)client.newRequest("http://localhost");
final CountDownLatch latch = new CountDownLatch(1);
FutureResponseListener listener = new FutureResponseListener(request)
{
@Override
public void onContent(Response response, ByteBuffer content)
{
super.onContent(response, content);
latch.countDown();
}
};
HttpExchange exchange = new HttpExchange(destination, request, Collections.<Response.ResponseListener>singletonList(listener));
connection.getHttpChannel().associate(exchange);
exchange.requestComplete();
exchange.terminateRequest(null);
connection.getHttpChannel().receive();
endPoint.reset();
@ -241,6 +256,7 @@ public class HttpReceiverOverHTTPTest
ContentResponse response = listener.get(5, TimeUnit.SECONDS);
Assert.assertNotNull(response);
Assert.assertEquals(200, response.getStatus());
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
Assert.assertArrayEquals(data, response.getContent());
}
}

View File

@ -569,7 +569,7 @@
<arguments>
<argument>jetty.home=${assembly-directory}</argument>
<argument>jetty.base=${assembly-directory}/demo-base</argument>
<argument>--add-to-start=server,continuation,deploy,ext,resources,client,annotations,jndi,servlets</argument>
<argument>--add-to-start=server,continuation,deploy,websocket,ext,resources,client,annotations,jndi,servlets</argument>
<argument>--add-to-startd-ini=jsp,jstl,http,https</argument>
</arguments>
</configuration>

View File

@ -1357,24 +1357,36 @@ public class HttpParser
protected boolean parseContent(ByteBuffer buffer)
{
int remaining=buffer.remaining();
if (remaining==0 && _state==State.CONTENT)
{
long content=_contentLength - _contentPosition;
if (content == 0)
{
setState(State.END);
if (_handler.messageComplete())
return true;
}
}
// Handle _content
byte ch;
while (_state.ordinal() < State.END.ordinal() && buffer.hasRemaining())
while (_state.ordinal() < State.END.ordinal() && remaining>0)
{
switch (_state)
{
case EOF_CONTENT:
_contentChunk=buffer.asReadOnlyBuffer();
_contentPosition += _contentChunk.remaining();
buffer.position(buffer.position()+_contentChunk.remaining());
_contentPosition += remaining;
buffer.position(buffer.position()+remaining);
if (_handler.content(_contentChunk))
return true;
break;
case CONTENT:
{
long remaining=_contentLength - _contentPosition;
if (remaining == 0)
long content=_contentLength - _contentPosition;
if (content == 0)
{
setState(State.END);
if (_handler.messageComplete())
@ -1385,25 +1397,25 @@ public class HttpParser
_contentChunk=buffer.asReadOnlyBuffer();
// limit content by expected size
if (_contentChunk.remaining() > remaining)
if (remaining > content)
{
// We can cast remaining to an int as we know that it is smaller than
// or equal to length which is already an int.
_contentChunk.limit(_contentChunk.position()+(int)remaining);
_contentChunk.limit(_contentChunk.position()+(int)content);
}
_contentPosition += _contentChunk.remaining();
buffer.position(buffer.position()+_contentChunk.remaining());
boolean handle=_handler.content(_contentChunk);
if (_handler.content(_contentChunk))
return true;
if(_contentPosition == _contentLength)
{
setState(State.END);
if (_handler.messageComplete())
return true;
}
if (handle)
return true;
}
break;
}
@ -1463,8 +1475,8 @@ public class HttpParser
case CHUNK:
{
int remaining=_chunkLength - _chunkPosition;
if (remaining == 0)
int chunk=_chunkLength - _chunkPosition;
if (chunk == 0)
{
setState(State.CHUNKED_CONTENT);
}
@ -1472,13 +1484,13 @@ public class HttpParser
{
_contentChunk=buffer.asReadOnlyBuffer();
if (_contentChunk.remaining() > remaining)
_contentChunk.limit(_contentChunk.position()+remaining);
remaining=_contentChunk.remaining();
if (remaining > chunk)
_contentChunk.limit(_contentChunk.position()+chunk);
chunk=_contentChunk.remaining();
_contentPosition += remaining;
_chunkPosition += remaining;
buffer.position(buffer.position()+remaining);
_contentPosition += chunk;
_chunkPosition += chunk;
buffer.position(buffer.position()+chunk);
if (_handler.content(_contentChunk))
return true;
}
@ -1493,7 +1505,10 @@ public class HttpParser
default:
break;
}
remaining=buffer.remaining();
}
return false;
}

View File

@ -19,11 +19,13 @@
package org.eclipse.jetty.io;
import java.io.IOException;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.List;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Scheduler;
@ -57,9 +59,11 @@ public class NetworkTrafficSelectChannelEndPoint extends SelectChannelEndPoint
if (b.hasRemaining())
{
int position = b.position();
ByteBuffer view=b.slice();
flushed&=super.flush(b);
int l=b.position()-position;
notifyOutgoing(b, position, l);
view.limit(view.position()+l);
notifyOutgoing(view);
if (!flushed)
break;
}
@ -67,9 +71,12 @@ public class NetworkTrafficSelectChannelEndPoint extends SelectChannelEndPoint
return flushed;
}
public void notifyOpened()
@Override
public void onOpen()
{
super.onOpen();
if (listeners != null && !listeners.isEmpty())
{
for (NetworkTrafficListener listener : listeners)
@ -86,6 +93,27 @@ public class NetworkTrafficSelectChannelEndPoint extends SelectChannelEndPoint
}
}
@Override
public void onClose()
{
super.onClose();
if (listeners != null && !listeners.isEmpty())
{
for (NetworkTrafficListener listener : listeners)
{
try
{
listener.closed(getSocket());
}
catch (Exception x)
{
LOG.warn(x);
}
}
}
}
public void notifyIncoming(ByteBuffer buffer, int read)
{
if (listeners != null && !listeners.isEmpty() && read > 0)
@ -105,18 +133,16 @@ public class NetworkTrafficSelectChannelEndPoint extends SelectChannelEndPoint
}
}
public void notifyOutgoing(ByteBuffer buffer, int position, int written)
public void notifyOutgoing(ByteBuffer view)
{
if (listeners != null && !listeners.isEmpty() && written > 0)
if (listeners != null && !listeners.isEmpty() && view.hasRemaining())
{
Socket socket=getSocket();
for (NetworkTrafficListener listener : listeners)
{
try
{
ByteBuffer view = buffer.slice();
view.position(position);
view.limit(position + written);
listener.outgoing(getSocket(), view);
listener.outgoing(socket, view);
}
catch (Exception x)
{
@ -126,21 +152,4 @@ public class NetworkTrafficSelectChannelEndPoint extends SelectChannelEndPoint
}
}
public void notifyClosed()
{
if (listeners != null && !listeners.isEmpty())
{
for (NetworkTrafficListener listener : listeners)
{
try
{
listener.closed(getSocket());
}
catch (Exception x)
{
LOG.warn(x);
}
}
}
}
}

View File

@ -28,6 +28,7 @@
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>

View File

@ -21,10 +21,12 @@
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>

View File

@ -21,10 +21,12 @@
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>

View File

@ -14,102 +14,36 @@
<bundle-symbolic-name>${project.groupId}.boot.test.spdy</bundle-symbolic-name>
<jetty-orbit-url>http://download.eclipse.org/jetty/orbit/</jetty-orbit-url>
<assembly-directory>target/distribution</assembly-directory>
<exam.version>2.6.0</exam.version>
<url.version>1.4.0</url.version>
<paxswissbox.version>1.5.1</paxswissbox.version>
<felixversion>4.0.3</felixversion>
<exam.version>3.4.0</exam.version>
<url.version>1.5.2</url.version>
<injection.bundle.version>1.0</injection.bundle.version>
<runner.version>1.7.6</runner.version>
<runner.version>1.8.5</runner.version>
</properties>
<dependencies>
<!-- Pax Exam Dependencies -->
<!-- OPS4J Swissbox Dependencies -->
<dependency>
<groupId>org.ops4j.pax.swissbox</groupId>
<artifactId>pax-swissbox-core</artifactId>
<version>${paxswissbox.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.swissbox</groupId>
<artifactId>pax-swissbox-extender</artifactId>
<version>${paxswissbox.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.swissbox</groupId>
<artifactId>pax-swissbox-lifecycle</artifactId>
<version>${paxswissbox.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.swissbox</groupId>
<artifactId>pax-swissbox-framework</artifactId>
<version>${paxswissbox.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam</artifactId>
<version>${exam.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-atinject_1.0_spec</artifactId>
<version>${injection.bundle.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-inject</artifactId>
<version>${exam.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.aries.spifly</groupId>
<artifactId>org.apache.aries.spifly.dynamic.bundle</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
<!-- Don't use the native container for now. Observed limitations:
- single test with a single configuration
- does not read the versions of the dependencies from the pom.xml
and hence hardcode the bundles versions in the source code instead
- no support for most configuration options for the OSGi container. -->
<!--dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-container-native</artifactId>
<version>${exam.version}</version>
<scope>test</scope>
</dependency-->
<!-- container is not bad but not enough config parameters yet
can't pass the VMOption for alpn-boot
<!-- use the forked container so we can pass it system properties eg for npn/alpn -->
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-container-forked</artifactId>
<version>${exam.version}</version>
<scope>test</scope>
</dependency>
-->
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-container-paxrunner</artifactId>
<version>${exam.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.runner</groupId>
<artifactId>pax-runner-no-jcl</artifactId>
<version>${runner.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-junit4</artifactId>
@ -134,28 +68,81 @@
<version>${url.version}</version>
<scope>test</scope>
</dependency>
<!-- OSGi R4 frameworks -->
<!--
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
<version>${felixversion}</version>
<version>4.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-testforge</artifactId>
<version>${exam.version}</version>
<scope>test</scope>
</dependency>
<!-- For sane logging -->
<!--
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.1</version>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.enterprise</artifactId>
<version>5.0.0</version>
<scope>test</scope>
</dependency>
-->
<dependency>
<groupId>org.eclipse</groupId>
<artifactId>osgi</artifactId>
<version>3.9.1-v20140110-1610</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
<scope>test</scope>
</dependency>
<!-- Jetty OSGi Deps -->
<dependency>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-boot</artifactId>
<version>${project.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-boot-jsp</artifactId>
<version>${project.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-jsp-fragment</artifactId>
<version>2.3.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-httpservice</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
@ -167,47 +154,34 @@
<version>1.1.1</version>
<scope>test</scope>
</dependency>
<!-- OSGi Deps -->
<dependency>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-boot</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-boot-jsp</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-jsp-fragment</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-httpservice</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-atinject_1.0_spec</artifactId>
<version>${injection.bundle.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.aries.spifly</groupId>
<artifactId>org.apache.aries.spifly.dynamic.bundle</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>4.1</version>
</dependency>
<dependency>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-commons</artifactId>
<version>4.1</version>
</dependency>
<dependency>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-tree</artifactId>
<version>4.1</version>
</dependency>
</dependency>
<!-- Jetty Deps -->
@ -386,7 +360,9 @@
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<!-- Eclipse OSGi Deps -->
<!--
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
@ -398,7 +374,6 @@
<scope>runtime</scope>
<exclusions>
<exclusion>
<!-- we use the servlet jar from orbit -->
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
@ -409,6 +384,9 @@
<artifactId>servlet</artifactId>
<scope>runtime</scope>
</dependency>
-->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>test-jetty-webapp</artifactId>

View File

@ -37,12 +37,13 @@ import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.Configuration;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.junit.PaxExam;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
@ -55,12 +56,11 @@ import org.osgi.framework.ServiceReference;
* Tests the ServiceContextProvider.
*
*/
@RunWith(JUnit4TestRunner.class)
@RunWith(PaxExam.class)
public class TestJettyOSGiBootContextAsService
{
private static final boolean LOGGING_ENABLED = false;
private static final String LOG_LEVEL = "WARN";
private static final boolean REMOTE_DEBUGGING = false;
@Inject
BundleContext bundleContext = null;
@ -69,7 +69,6 @@ public class TestJettyOSGiBootContextAsService
public static Option[] configure()
{
ArrayList<Option> options = new ArrayList<Option>();
TestOSGiUtil.addMoreOSGiContainers(options);
options.add(CoreOptions.junitBundles());
options.addAll(configureJettyHomeAndPort("jetty-selector.xml"));
options.add(CoreOptions.bootDelegationPackages("org.xml.sax", "org.xml.*", "org.w3c.*", "javax.xml.*"));
@ -79,22 +78,10 @@ public class TestJettyOSGiBootContextAsService
// to pick up and deploy
options.add(mavenBundle().groupId("org.eclipse.jetty.osgi").artifactId("test-jetty-osgi-context").versionAsInProject().start());
String logLevel = "WARN";
// Enable Logging
if (LOGGING_ENABLED)
logLevel = "INFO";
options.addAll(Arrays.asList(options(systemProperty("pax.exam.logging").value("none"))));
options.addAll(Arrays.asList(options(systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(LOG_LEVEL))));
options.addAll(Arrays.asList(options(systemProperty("org.eclipse.jetty.LEVEL").value(LOG_LEVEL))));
options.addAll(Arrays.asList(options(
// install log service using pax runners profile abstraction (there
// are more profiles, like DS)
// logProfile(),
// this is how you set the default log level when using pax logging
// (logProfile)
systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(logLevel),
systemProperty("org.eclipse.jetty.LEVEL").value(logLevel))));
return options.toArray(new Option[options.size()]);
}
@ -117,6 +104,7 @@ public class TestJettyOSGiBootContextAsService
return options;
}
@Ignore
@Test
public void assertAllBundlesActiveOrResolved()
{
@ -148,14 +136,6 @@ public class TestJettyOSGiBootContextAsService
ServiceReference[] refs = bundleContext.getServiceReferences(ContextHandler.class.getName(), null);
assertNotNull(refs);
assertEquals(1, refs.length);
//uncomment for debugging
/*
String[] keys = refs[0].getPropertyKeys();
if (keys != null)
{
for (String k : keys)
System.err.println("service property: " + k + ", " + refs[0].getProperty(k));
}*/
ContextHandler ch = (ContextHandler) bundleContext.getService(refs[0]);
assertEquals("/acme", ch.getContextPath());

View File

@ -19,19 +19,23 @@
package org.eclipse.jetty.osgi.test;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.options;
import static org.ops4j.pax.exam.CoreOptions.systemProperty;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.inject.Inject;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.MavenUtils;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.Configuration;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.options.MavenUrlReference.VersionResolver;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@ -40,27 +44,30 @@ import org.osgi.framework.BundleContext;
/**
* Default OSGi setup integration test
*/
@RunWith( JUnit4TestRunner.class )
@RunWith( PaxExam.class )
public class TestJettyOSGiBootCore
{
private static final String LOG_LEVEL = "WARN";
public static int DEFAULT_JETTY_HTTP_PORT = 9876;
@Inject
private BundleContext bundleContext;
@Configuration
public Option[] config()
{
VersionResolver resolver = MavenUtils.asInProject();
ArrayList<Option> options = new ArrayList<Option>();
TestOSGiUtil.addMoreOSGiContainers(options);
options.addAll(provisionCoreJetty());
options.add(CoreOptions.junitBundles());
options.addAll(httpServiceJetty());
options.addAll(Arrays.asList(options(systemProperty("pax.exam.logging").value("none"))));
options.addAll(Arrays.asList(options(systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(LOG_LEVEL))));
options.addAll(Arrays.asList(options(systemProperty("org.eclipse.jetty.LEVEL").value(LOG_LEVEL))));
return options.toArray(new Option[options.size()]);
}
public static List<Option> provisionCoreJetty()
{
List<Option> res = new ArrayList<Option>();
@ -75,12 +82,21 @@ public class TestJettyOSGiBootCore
public static List<Option> coreJettyDependencies()
{
List<Option> res = new ArrayList<Option>();
res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm" ).versionAsInProject().start());
res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm-commons" ).versionAsInProject().start());
res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm-tree" ).versionAsInProject().start());
res.add(mavenBundle().groupId( "org.apache.aries" ).artifactId( "org.apache.aries.util" ).version("1.0.0").start());
res.add(mavenBundle().groupId( "org.apache.aries.spifly" ).artifactId( "org.apache.aries.spifly.dynamic.bundle" ).version("1.0.0").start());
String jdk = System.getProperty("java.version");
int firstdot = jdk.indexOf(".");
jdk = jdk.substring(0,firstdot+2);
double version = Double.parseDouble(jdk);
if (version < 1.8)
{
res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm" ).versionAsInProject().start());
res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm-commons" ).versionAsInProject().start());
res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm-tree" ).versionAsInProject().start());
res.add(mavenBundle().groupId( "org.apache.aries" ).artifactId( "org.apache.aries.util" ).version("1.0.0").start());
res.add(mavenBundle().groupId( "org.apache.aries.spifly" ).artifactId( "org.apache.aries.spifly.dynamic.bundle" ).version("1.0.0").start());
}
res.add(mavenBundle().groupId( "javax.servlet" ).artifactId( "javax.servlet-api" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "javax.annotation" ).artifactId( "javax.annotation-api" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "org.apache.geronimo.specs" ).artifactId( "geronimo-jta_1.1_spec" ).version("1.1.1").noStart());
@ -103,7 +119,10 @@ public class TestJettyOSGiBootCore
res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-client" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-jndi" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-plus" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-annotations" ).versionAsInProject().start());
if (version < 1.8)
{
res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-annotations" ).versionAsInProject().start());
}
res.add(mavenBundle().groupId( "org.eclipse.jetty.websocket" ).artifactId( "websocket-api" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "org.eclipse.jetty.websocket" ).artifactId( "websocket-common" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "org.eclipse.jetty.websocket" ).artifactId( "websocket-servlet" ).versionAsInProject().noStart());
@ -124,9 +143,12 @@ public class TestJettyOSGiBootCore
return res;
}
@Ignore
@Test
public void assertAllBundlesActiveOrResolved() throws Exception
{
TestOSGiUtil.debugBundles(bundleContext);
TestOSGiUtil.assertAllBundlesActiveOrResolved(bundleContext);
}

View File

@ -36,18 +36,18 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.Configuration;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.junit.PaxExam;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
/**
* SPDY setup.
*/
@RunWith(JUnit4TestRunner.class)
@RunWith(PaxExam.class)
public class TestJettyOSGiBootSpdy
{
private static final boolean LOGGING_ENABLED = false;
private static final String LOG_LEVEL = "WARN";
private static final String JETTY_SPDY_PORT = "jetty.spdy.port";
@ -60,31 +60,14 @@ public class TestJettyOSGiBootSpdy
public Option[] config()
{
ArrayList<Option> options = new ArrayList<Option>();
TestOSGiUtil.addMoreOSGiContainers(options);
options.addAll(TestJettyOSGiBootWithJsp.configureJettyHomeAndPort("jetty-spdy.xml"));
options.addAll(TestJettyOSGiBootCore.coreJettyDependencies());
options.addAll(spdyJettyDependencies());
options.add(CoreOptions.junitBundles());
options.addAll(TestJettyOSGiBootCore.httpServiceJetty());
String logLevel = "WARN";
// Enable Logging
if (LOGGING_ENABLED)
logLevel = "INFO";
options.addAll(Arrays.asList(options(
// install log service using pax runners profile abstraction (there
// are more profiles, like DS)
// logProfile(),
// this is how you set the default log level when using pax logging
// (logProfile)
systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(logLevel),
systemProperty("org.eclipse.jetty.LEVEL").value(logLevel))));
options.addAll(Arrays.asList(options(systemProperty("pax.exam.logging").value("none"))));
options.addAll(Arrays.asList(options(systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(LOG_LEVEL))));
options.addAll(Arrays.asList(options(systemProperty("org.eclipse.jetty.LEVEL").value(LOG_LEVEL))));
return options.toArray(new Option[options.size()]);
}
@ -101,7 +84,7 @@ public class TestJettyOSGiBootSpdy
res.add(CoreOptions.vmOptions("-Xbootclasspath/p:" + alpnBoot));
res.add(mavenBundle().groupId("org.eclipse.jetty.osgi").artifactId("jetty-osgi-alpn").versionAsInProject().start());
res.add(mavenBundle().groupId("org.eclipse.jetty.osgi").artifactId("jetty-osgi-alpn").versionAsInProject().noStart());
res.add(mavenBundle().groupId("org.eclipse.jetty").artifactId("jetty-alpn-server").versionAsInProject().start());
res.add(mavenBundle().groupId("org.eclipse.jetty.spdy").artifactId("spdy-client").versionAsInProject().noStart());
@ -112,7 +95,6 @@ public class TestJettyOSGiBootSpdy
return res;
}
@Ignore
@Test
public void checkALPNBootOnBootstrapClasspath() throws Exception
{
@ -121,13 +103,11 @@ public class TestJettyOSGiBootSpdy
Assert.assertNull(alpn.getClassLoader());
}
@Ignore
@Test
public void assertAllBundlesActiveOrResolved()
{
Bundle b = TestOSGiUtil.getBundle(bundleContext, "org.eclipse.jetty.spdy.client");
TestOSGiUtil.diagnoseNonActiveOrNonResolvedBundle(b);
b = TestOSGiUtil.getBundle(bundleContext, "org.eclipse.jetty.osgi.boot");
TestOSGiUtil.diagnoseNonActiveOrNonResolvedBundle(b);
TestOSGiUtil.debugBundles(bundleContext);
TestOSGiUtil.assertAllBundlesActiveOrResolved(bundleContext);
}

View File

@ -38,12 +38,13 @@ import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.webapp.WebAppContext;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.Configuration;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.junit.PaxExam;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
@ -58,12 +59,10 @@ import org.osgi.framework.ServiceReference;
* httpservice web-bundle. Then make sure we can deploy an OSGi service on the
* top of this.
*/
@RunWith(JUnit4TestRunner.class)
@RunWith(PaxExam.class)
public class TestJettyOSGiBootWebAppAsService
{
private static final boolean LOGGING_ENABLED = false;
private static final boolean REMOTE_DEBUGGING = false;
private static final String LOG_LEVEL = "WARN";
@Inject
BundleContext bundleContext = null;
@ -72,8 +71,6 @@ public class TestJettyOSGiBootWebAppAsService
public static Option[] configure()
{
ArrayList<Option> options = new ArrayList<Option>();
TestOSGiUtil.addMoreOSGiContainers(options);
options.add(CoreOptions.junitBundles());
options.addAll(configureJettyHomeAndPort("jetty-selector.xml"));
options.add(CoreOptions.bootDelegationPackages("org.xml.sax", "org.xml.*", "org.w3c.*", "javax.xml.*"));
@ -82,19 +79,9 @@ public class TestJettyOSGiBootWebAppAsService
"com.sun.org.apache.xpath.internal.jaxp", "com.sun.org.apache.xpath.internal.objects"));
options.addAll(TestJettyOSGiBootCore.coreJettyDependencies());
String logLevel = "WARN";
if (LOGGING_ENABLED)
logLevel = "INFO";
options.addAll(Arrays.asList(options(
// install log service using pax runners profile abstraction (there
// are more profiles, like DS)
// logProfile(),
// this is how you set the default log level when using pax logging
// (logProfile)
systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(logLevel),
systemProperty("org.eclipse.jetty.LEVEL").value(logLevel))));
options.addAll(Arrays.asList(options(systemProperty("pax.exam.logging").value("none"))));
options.addAll(Arrays.asList(options(systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(LOG_LEVEL))));
options.addAll(Arrays.asList(options(systemProperty("org.eclipse.jetty.LEVEL").value(LOG_LEVEL))));
options.addAll(jspDependencies());
return options.toArray(new Option[options.size()]);
@ -139,6 +126,7 @@ public class TestJettyOSGiBootWebAppAsService
return res;
}
@Ignore
@Test
public void assertAllBundlesActiveOrResolved()
{

View File

@ -38,25 +38,21 @@ import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.Configuration;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.osgi.framework.Bundle;
import org.ops4j.pax.exam.junit.PaxExam;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
/**
* Pax-Exam to make sure the jetty-osgi-boot can be started along with the
* httpservice web-bundle. Then make sure we can deploy an OSGi service on the
* top of this.
*/
@RunWith(JUnit4TestRunner.class)
@RunWith(PaxExam.class)
public class TestJettyOSGiBootWithJsp
{
private static final boolean LOGGING_ENABLED = false;
private static final boolean REMOTE_DEBUGGING = false;
private static final String LOG_LEVEL = "WARN";
@Inject
BundleContext bundleContext = null;
@ -66,9 +62,6 @@ public class TestJettyOSGiBootWithJsp
{
ArrayList<Option> options = new ArrayList<Option>();
TestOSGiUtil.addMoreOSGiContainers(options);
options.add(CoreOptions.junitBundles());
options.addAll(configureJettyHomeAndPort("jetty-selector.xml"));
options.add(CoreOptions.bootDelegationPackages("org.xml.sax", "org.xml.*", "org.w3c.*", "javax.xml.*", "javax.activation.*"));
@ -77,39 +70,11 @@ public class TestJettyOSGiBootWithJsp
"com.sun.org.apache.xpath.internal.jaxp", "com.sun.org.apache.xpath.internal.objects"));
options.addAll(TestJettyOSGiBootCore.coreJettyDependencies());
options.addAll(Arrays.asList(options(systemProperty("pax.exam.logging").value("none"))));
options.addAll(Arrays.asList(options(systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(LOG_LEVEL))));
options.addAll(Arrays.asList(options(systemProperty("org.eclipse.jetty.LEVEL").value(LOG_LEVEL))));
String logLevel = "WARN";
// Enable Logging
if (LOGGING_ENABLED)
logLevel = "INFO";
options.addAll(Arrays.asList(options(
// install log service using pax runners profile abstraction (there
// are more profiles, like DS)
// logProfile(),
// this is how you set the default log level when using pax logging
// (logProfile)
systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(logLevel),
systemProperty("org.eclipse.jetty.annotations.LEVEL").value(logLevel))));
options.addAll(jspDependencies());
// Remote JDWP Debugging, this won't work with the forked container.
// if(REMOTE_DEBUGGING) {
// options.addAll(Arrays.asList(options(
// // this just adds all what you write here to java vm argumenents of
// the (new) osgi process.
// PaxRunnerOptions.vmOption(
// "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5006" )
// )));
// }
// bug at the moment: this would make the httpservice catch all
// requests and prevent the webapp at the root context to catch any of
// them.
// options.addAll(TestJettyOSGiBootCore.httpServiceJetty());
return options.toArray(new Option[options.size()]);
}
@ -157,7 +122,7 @@ public class TestJettyOSGiBootWithJsp
return res;
}
@Ignore
@Test
public void assertAllBundlesActiveOrResolved()
{

View File

@ -33,7 +33,6 @@ import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@ -46,22 +45,6 @@ import org.osgi.service.http.HttpService;
public class TestOSGiUtil
{
/**
* Note: this will run many more tests. TODO: find a better way to control
* this and use non-deprecated methods.
*
* @param opti
*/
protected static void addMoreOSGiContainers(List<Option> options)
{
//Uncomment to run more containers - these have been commented out
//to improve speed of builds.
//options.add(CoreOptions.equinox().version("3.6.1"));
//options.add(CoreOptions.equinox().version("3.7.0"));
// options.add(CoreOptions.felix().version("3.2.2"));
options.add(CoreOptions.felix().version("4.0.2"));
}
protected static Bundle getBundle(BundleContext bundleContext, String symbolicName)
{
Map<String,Bundle> _bundles = new HashMap<String, Bundle>();
@ -146,7 +129,7 @@ public class TestOSGiUtil
for (Bundle b : bundleContext.getBundles())
{
bundlesIndexedBySymbolicName.put(b.getSymbolicName(), b);
System.err.println(" " + b.getSymbolicName() + " " + b.getState());
System.err.println(" " + b.getSymbolicName() + " " + b.getLocation() + " " + b.getVersion()+ " " + b.getState());
}
}

View File

@ -87,7 +87,6 @@ public class NetworkTrafficServerConnector extends ServerConnector
protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectorManager.ManagedSelector selectSet, SelectionKey key) throws IOException
{
NetworkTrafficSelectChannelEndPoint endPoint = new NetworkTrafficSelectChannelEndPoint(channel, selectSet, key, getScheduler(), getIdleTimeout(), listeners);
endPoint.notifyOpened();
return endPoint;
}
}

View File

@ -44,7 +44,6 @@ import org.junit.After;
import org.junit.Ignore;
import org.junit.Test;
@Ignore
public class NetworkTrafficListenerTest
{
private static final byte END_OF_CONTENT = '~';
@ -114,6 +113,7 @@ public class NetworkTrafficListenerTest
{
initConnector(new AbstractHandler()
{
@Override
public void handle(String uri, Request request, HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException, ServletException
{
request.setHandled(true);
@ -176,6 +176,7 @@ public class NetworkTrafficListenerTest
final String responseContent = "response_content";
initConnector(new AbstractHandler()
{
@Override
public void handle(String uri, Request request, HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException, ServletException
{
request.setHandled(true);
@ -191,12 +192,14 @@ public class NetworkTrafficListenerTest
final CountDownLatch outgoingLatch = new CountDownLatch(2);
connector.addNetworkTrafficListener(new NetworkTrafficListener.Adapter()
{
@Override
public void incoming(Socket socket, ByteBuffer bytes)
{
incomingData.set(BufferUtil.toString(bytes,StandardCharsets.UTF_8));
incomingLatch.countDown();
}
@Override
public void outgoing(Socket socket, ByteBuffer bytes)
{
outgoingData.set(outgoingData.get() + BufferUtil.toString(bytes,StandardCharsets.UTF_8));
@ -241,6 +244,7 @@ public class NetworkTrafficListenerTest
final String responseChunk2 = "response_content".substring(responseContent.length() / 2, responseContent.length());
initConnector(new AbstractHandler()
{
@Override
public void handle(String uri, Request request, HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException, ServletException
{
request.setHandled(true);
@ -255,19 +259,22 @@ public class NetworkTrafficListenerTest
final AtomicReference<String> incomingData = new AtomicReference<>();
final CountDownLatch incomingLatch = new CountDownLatch(1);
final AtomicReference<String> outgoingData = new AtomicReference<>("");
final CountDownLatch outgoingLatch = new CountDownLatch(4);
final CountDownLatch outgoingLatch = new CountDownLatch(1);
connector.addNetworkTrafficListener(new NetworkTrafficListener.Adapter()
{
@Override
public void incoming(Socket socket, ByteBuffer bytes)
{
incomingData.set(BufferUtil.toString(bytes,StandardCharsets.UTF_8));
incomingLatch.countDown();
}
@Override
public void outgoing(Socket socket, ByteBuffer bytes)
{
outgoingData.set(outgoingData.get() + BufferUtil.toString(bytes,StandardCharsets.UTF_8));
outgoingLatch.countDown();
outgoingData.set(outgoingData.get() + BufferUtil.toString(bytes,StandardCharsets.UTF_8));
if (outgoingData.get().endsWith("\r\n0\r\n\r\n"))
outgoingLatch.countDown();
}
});
int port = connector.getLocalPort();
@ -311,6 +318,7 @@ public class NetworkTrafficListenerTest
final String location = "/redirect";
initConnector(new AbstractHandler()
{
@Override
public void handle(String uri, Request request, HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException, ServletException
{
request.setHandled(true);
@ -324,12 +332,14 @@ public class NetworkTrafficListenerTest
final CountDownLatch outgoingLatch = new CountDownLatch(1);
connector.addNetworkTrafficListener(new NetworkTrafficListener.Adapter()
{
@Override
public void incoming(Socket socket, ByteBuffer bytes)
{
incomingData.set(BufferUtil.toString(bytes,StandardCharsets.UTF_8));
incomingLatch.countDown();
}
@Override
public void outgoing(Socket socket, ByteBuffer bytes)
{
outgoingData.set(outgoingData.get() + BufferUtil.toString(bytes,StandardCharsets.UTF_8));
@ -375,6 +385,7 @@ public class NetworkTrafficListenerTest
{
initConnector(new AbstractHandler()
{
@Override
public void handle(String uri, Request request, HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException, ServletException
{
// Read and discard the request body to make the test more
@ -397,11 +408,13 @@ public class NetworkTrafficListenerTest
final CountDownLatch outgoingLatch = new CountDownLatch(1);
connector.addNetworkTrafficListener(new NetworkTrafficListener.Adapter()
{
@Override
public void incoming(Socket socket, ByteBuffer bytes)
{
incomingData.set(incomingData.get() + BufferUtil.toString(bytes,StandardCharsets.UTF_8));
}
@Override
public void outgoing(Socket socket, ByteBuffer bytes)
{
outgoingData.set(outgoingData.get() + BufferUtil.toString(bytes,StandardCharsets.UTF_8));

View File

@ -294,7 +294,7 @@ public class UrlEncoded extends MultiMap<String> implements Cloneable
switch ((char)(0xff&b))
{
case '&':
value = buffer.length()==0?"":buffer.toString();
value = buffer.toReplacedString();
buffer.reset();
if (key != null)
{
@ -314,7 +314,7 @@ public class UrlEncoded extends MultiMap<String> implements Cloneable
buffer.append(b);
break;
}
key = buffer.toString();
key = buffer.toReplacedString();
buffer.reset();
break;
@ -376,7 +376,7 @@ public class UrlEncoded extends MultiMap<String> implements Cloneable
if (key != null)
{
value = buffer.length()==0?"":buffer.toReplacedString();
value = buffer.toReplacedString();
buffer.reset();
map.add(key,value);
}
@ -510,7 +510,7 @@ public class UrlEncoded extends MultiMap<String> implements Cloneable
switch ((char) b)
{
case '&':
value = buffer.length()==0?"":buffer.toString();
value = buffer.toReplacedString();
buffer.reset();
if (key != null)
{
@ -532,7 +532,7 @@ public class UrlEncoded extends MultiMap<String> implements Cloneable
buffer.append((byte)b);
break;
}
key = buffer.toString();
key = buffer.toReplacedString();
buffer.reset();
break;
@ -542,17 +542,26 @@ public class UrlEncoded extends MultiMap<String> implements Cloneable
case '%':
int code0=in.read();
boolean decoded=false;
if ('u'==code0)
{
int code1=in.read();
if (code1>=0)
code0=in.read(); // XXX: we have to read the next byte, otherwise code0 is always 'u'
if (code0>=0)
{
int code2=in.read();
if (code2>=0)
int code1=in.read();
if (code1>=0)
{
int code3=in.read();
if (code3>=0)
buffer.getStringBuilder().append(Character.toChars((convertHexDigit(code0)<<12)+(convertHexDigit(code1)<<8)+(convertHexDigit(code2)<<4)+convertHexDigit(code3)));
int code2=in.read();
if (code2>=0)
{
int code3=in.read();
if (code3>=0)
{
buffer.getStringBuilder().append(Character.toChars
((convertHexDigit(code0)<<12)+(convertHexDigit(code1)<<8)+(convertHexDigit(code2)<<4)+convertHexDigit(code3)));
decoded=true;
}
}
}
}
}
@ -560,8 +569,15 @@ public class UrlEncoded extends MultiMap<String> implements Cloneable
{
int code1=in.read();
if (code1>=0)
{
buffer.append((byte)((convertHexDigit(code0)<<4)+convertHexDigit(code1)));
decoded=true;
}
}
if (!decoded)
buffer.getStringBuilder().append(Utf8Appendable.REPLACEMENT);
break;
default:
@ -586,13 +602,13 @@ public class UrlEncoded extends MultiMap<String> implements Cloneable
if (key != null)
{
value = buffer.length()==0?"":buffer.toString();
value = buffer.toReplacedString();
buffer.reset();
map.add(key,value);
}
else if (buffer.length()>0)
{
map.add(buffer.toString(), "");
map.add(buffer.toReplacedString(), "");
}
}
}

View File

@ -0,0 +1,165 @@
//
// ========================================================================
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.util;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.junit.Assert;
import org.junit.Test;
public class UrlEncodedUtf8Test
{
static final Logger LOG=Log.getLogger(UrlEncodedUtf8Test.class);
@Test
public void testIncompleteSequestAtTheEnd() throws Exception
{
byte[] bytes= { 97, 98, 61, 99, -50 };
String test=new String(bytes,StandardCharsets.UTF_8);
String expected = "c"+Utf8Appendable.REPLACEMENT;
fromByteArray(test,bytes,"ab",expected,false);
fromInputStream(test,bytes,"ab",expected,false);
}
@Test
public void testIncompleteSequestAtTheEnd2() throws Exception
{
byte[] bytes={ 97, 98, 61, -50 };
String test=new String(bytes,StandardCharsets.UTF_8);
String expected = ""+Utf8Appendable.REPLACEMENT;
fromByteArray(test,bytes,"ab",expected,false);
fromInputStream(test,bytes,"ab",expected,false);
}
@Test
public void testIncompleteSequestInName() throws Exception
{
byte[] bytes= { 101, -50, 61, 102, 103, 38, 97, 98, 61, 99, 100 };
String test=new String(bytes,StandardCharsets.UTF_8);
String name = "e"+Utf8Appendable.REPLACEMENT;
String value = "fg";
fromByteArray(test,bytes,name,value,false);
fromInputStream(test,bytes,name,value,false);
}
@Test
public void testIncompleteSequestInValue() throws Exception
{
byte[] bytes= { 101, 102, 61, 103, -50, 38, 97, 98, 61, 99, 100 };
String test=new String(bytes,StandardCharsets.UTF_8);
String name = "ef";
String value = "g"+Utf8Appendable.REPLACEMENT;
fromByteArray(test,bytes,name,value,false);
fromInputStream(test,bytes,name,value,false);
}
@Test
public void testCorrectUnicode() throws Exception
{
String chars="a=%u0061";
byte[] bytes= chars.getBytes(StandardCharsets.UTF_8);
String test=new String(bytes,StandardCharsets.UTF_8);
String name = "a";
String value = "a";
fromByteArray(test,bytes,name,value,false);
fromInputStream(test,bytes,name,value,false);
}
@Test
public void testIncompleteUnicode() throws Exception
{
String chars="a=%u0";
byte[] bytes= chars.getBytes(StandardCharsets.UTF_8);
String test=new String(bytes,StandardCharsets.UTF_8);
String name = "a";
String value = ""+Utf8Appendable.REPLACEMENT;
fromByteArray(test,bytes,name,value,false);
fromInputStream(test,bytes,name,value,false);
}
@Test
public void testIncompletePercent() throws Exception
{
String chars="a=%A";
byte[] bytes= chars.getBytes(StandardCharsets.UTF_8);
String test=new String(bytes,StandardCharsets.UTF_8);
String name = "a";
String value = ""+Utf8Appendable.REPLACEMENT;
fromByteArray(test,bytes,name,value,false);
fromInputStream(test,bytes,name,value,false);
}
static void fromByteArray(String test,byte[] b,String field,String expected,boolean thrown) throws Exception
{
MultiMap<String> values=new MultiMap<>();
try
{
//safeDecodeUtf8To(b, 0, b.length, values);
UrlEncoded.decodeUtf8To(b, 0, b.length, values);
if (thrown)
Assert.fail();
Assert.assertEquals(test, expected, values.getString(field));
}
catch (Exception e)
{
if (!thrown)
throw e;
LOG.ignore(e);
}
}
static void fromInputStream(String test, byte[] b,String field, String expected,boolean thrown) throws Exception
{
InputStream is=new ByteArrayInputStream(b);
MultiMap<String> values=new MultiMap<>();
try
{
//safeDecodeUtf8To(is, values, 1000000, 10000000);
UrlEncoded.decodeUtf8To(is, values, 1000000, 10000000);
if (thrown)
Assert.fail();
Assert.assertEquals(test, expected, values.getString(field));
}
catch (Exception e)
{
if (!thrown)
throw e;
LOG.ignore(e);
}
}
}

View File

@ -70,9 +70,11 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
public static final String STANDARD_PROCESSOR = "org.eclipse.jetty.standardDescriptorProcessor";
final Map<String,FilterHolder> _filterHolders = new HashMap<>();
final Map<String,FilterHolder> _filterHolderMap = new HashMap<>();
final List<FilterHolder> _filterHolders = new ArrayList<>();
final List<FilterMapping> _filterMappings = new ArrayList<>();
final Map<String,ServletHolder> _servletHolders = new HashMap<>();
final Map<String,ServletHolder> _servletHolderMap = new HashMap<>();
final List<ServletHolder> _servletHolders = new ArrayList<>();
final List<ServletMapping> _servletMappings = new ArrayList<>();
public StandardDescriptorProcessor ()
@ -113,11 +115,17 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
public void start(WebAppContext context, Descriptor descriptor)
{
for (FilterHolder h : context.getServletHandler().getFilters())
_filterHolders.put(h.getName(),h);
{
_filterHolderMap.put(h.getName(),h);
_filterHolders.add(h);
}
if (context.getServletHandler().getFilterMappings()!=null)
_filterMappings.addAll(Arrays.asList(context.getServletHandler().getFilterMappings()));
for (ServletHolder h : context.getServletHandler().getServlets())
_servletHolders.put(h.getName(),h);
{
_servletHolderMap.put(h.getName(),h);
_servletHolders.add(h);
}
if (context.getServletHandler().getServletMappings()!=null)
_servletMappings.addAll(Arrays.asList(context.getServletHandler().getServletMappings()));
}
@ -128,14 +136,16 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
*/
public void end(WebAppContext context, Descriptor descriptor)
{
context.getServletHandler().setFilters(_filterHolders.values().toArray(new FilterHolder[_filterHolders.size()]));
context.getServletHandler().setServlets(_servletHolders.values().toArray(new ServletHolder[_servletHolders.size()]));
context.getServletHandler().setFilters(_filterHolders.toArray(new FilterHolder[_filterHolderMap.size()]));
context.getServletHandler().setServlets(_servletHolders.toArray(new ServletHolder[_servletHolderMap.size()]));
context.getServletHandler().setFilterMappings(_filterMappings.toArray(new FilterMapping[_filterMappings.size()]));
context.getServletHandler().setServletMappings(_servletMappings.toArray(new ServletMapping[_servletMappings.size()]));
_filterHolderMap.clear();
_filterHolders.clear();
_filterMappings.clear();
_servletHolderMap.clear();
_servletHolders.clear();
_servletMappings.clear();
}
@ -217,14 +227,15 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
// initialize holder
String name = node.getString("servlet-name", false, true);
ServletHolder holder = _servletHolders.get(name);
ServletHolder holder = _servletHolderMap.get(name);
//If servlet of that name does not already exist, create it.
if (holder == null)
{
holder = context.getServletHandler().newServletHolder(Source.DESCRIPTOR);
holder.setName(name);
_servletHolders.put(name,holder);
_servletHolderMap.put(name,holder);
_servletHolders.add(holder);
}
// init params
@ -1401,11 +1412,11 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
if (paths.size() > 0)
{
ServletHandler handler = context.getServletHandler();
ServletHolder jsp_pg_servlet = _servletHolders.get(JspPropertyGroupServlet.NAME);
ServletHolder jsp_pg_servlet = _servletHolderMap.get(JspPropertyGroupServlet.NAME);
if (jsp_pg_servlet==null)
{
jsp_pg_servlet=new ServletHolder(JspPropertyGroupServlet.NAME,new JspPropertyGroupServlet(context,handler));
_servletHolders.put(JspPropertyGroupServlet.NAME,jsp_pg_servlet);
_servletHolderMap.put(JspPropertyGroupServlet.NAME,jsp_pg_servlet);
}
ServletMapping mapping = new ServletMapping();
@ -1721,12 +1732,13 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
protected void visitFilter(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
{
String name = node.getString("filter-name", false, true);
FilterHolder holder = _filterHolders.get(name);
FilterHolder holder = _filterHolderMap.get(name);
if (holder == null)
{
holder = context.getServletHandler().newFilterHolder(Source.DESCRIPTOR);
holder.setName(name);
_filterHolders.put(name,holder);
_filterHolderMap.put(name,holder);
_filterHolders.add(holder);
}
String filter_class = node.getString("filter-class", false, true);