From 2a44fa5c220b911b5dc54b51239b8f91e5bca008 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Fri, 30 Mar 2012 18:46:53 +0200 Subject: [PATCH 01/36] Cosmetics. --- .../java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYTest.java index 59370e5ce8e..b7932133d07 100644 --- a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYTest.java +++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYTest.java @@ -519,7 +519,6 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest @Override public void onData(Stream stream, DataInfo dataInfo) { - contentBytes.addAndGet(dataInfo.asByteBuffer(true).remaining()); if (dataInfo.isClose()) { From b0a3d031aaf2e91b3ef0dff2337054bacc044dca Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Fri, 30 Mar 2012 18:47:47 +0200 Subject: [PATCH 02/36] 375509 - Stalled stream stalls other streams or session control frames. Additional fixes to the implementation of flush(). Also implemented frame priority. --- .../eclipse/jetty/spdy/StandardSession.java | 114 +++++++++++------- 1 file changed, 72 insertions(+), 42 deletions(-) diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java index a85103ba354..42f5ba0ef44 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java @@ -18,7 +18,6 @@ package org.eclipse.jetty.spdy; import java.nio.ByteBuffer; import java.nio.channels.InterruptedByTimeoutException; -import java.util.Deque; import java.util.HashSet; import java.util.LinkedList; import java.util.List; @@ -79,7 +78,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler listeners = new CopyOnWriteArrayList<>(); private final ConcurrentMap streams = new ConcurrentHashMap<>(); - private final Deque queue = new LinkedList<>(); + private final LinkedList queue = new LinkedList<>(); private final ByteBufferPool bufferPool; private final Executor threadPool; private final ScheduledExecutorService scheduler; @@ -732,10 +731,10 @@ public class StandardSession implements ISession, Parser.Listener, Handler frameBytes = new ControlFrameBytes<>(handler, context, frame, buffer); + ControlFrameBytes frameBytes = new ControlFrameBytes<>(stream, handler, context, frame, buffer); if (timeout > 0) frameBytes.task = scheduler.schedule(frameBytes, timeout, unit); - enqueueLast(frameBytes); + append(frameBytes); } flush(); @@ -766,10 +765,10 @@ public class StandardSession implements ISession, Parser.Listener, Handler void data(IStream stream, DataInfo dataInfo, long timeout, TimeUnit unit, Handler handler, C context) { logger.debug("Queuing {} on {}", dataInfo, stream); - DataFrameBytes frameBytes = new DataFrameBytes<>(handler, context, stream, dataInfo); + DataFrameBytes frameBytes = new DataFrameBytes<>(stream, handler, context, dataInfo); if (timeout > 0) frameBytes.task = scheduler.schedule(frameBytes, timeout, unit); - enqueueLast(frameBytes); + append(frameBytes); flush(); } @@ -781,56 +780,68 @@ public class StandardSession implements ISession, Parser.Listener, Handler stalledStreams = null; + for (int i = 0; i < queue.size(); ++i) { + frameBytes = queue.get(i); + + if (stalledStreams != null && stalledStreams.contains(frameBytes.getStream())) + continue; + buffer = frameBytes.getByteBuffer(); if (buffer != null) + { + queue.remove(i); break; + } + + if (stalledStreams == null) + stalledStreams = new HashSet<>(); + stalledStreams.add(frameBytes.getStream()); - // We are stalled: enqueue as last so other frames can be flushed - enqueueLast(frameBytes); - if (stalled == null) - stalled = frameBytes; - else if (stalled == frameBytes) - return; logger.debug("Flush stalled for {}, {} frame(s) in queue", frameBytes, queue.size()); - frameBytes = queue.poll(); } + if (buffer == null) + return; + flushing = true; logger.debug("Flushing {}, {} frame(s) in queue", frameBytes, queue.size()); } - - logger.debug("Writing {} frame bytes of {}", buffer.remaining(), frameBytes); write(buffer, this, frameBytes); } - private void enqueueLast(FrameBytes frameBytes) + private void append(FrameBytes frameBytes) { - // TODO: handle priority; e.g. use queues to prioritize the buffers ? - synchronized (queue) - { - queue.offerLast(frameBytes); - } + enqueue(frameBytes, false); } - private void enqueueFirst(FrameBytes frameBytes) + private void prepend(FrameBytes frameBytes) + { + enqueue(frameBytes, true); + } + + private void enqueue(FrameBytes frameBytes, boolean prepend) { synchronized (queue) { - queue.offerFirst(frameBytes); + int index = 0; + while (index < queue.size()) + { + FrameBytes element = queue.get(index); + int comparison = element.compareTo(frameBytes); + if (comparison > 0 || prepend && comparison == 0) + break; + ++index; + } + queue.add(index, frameBytes); } } @@ -854,7 +865,10 @@ public class StandardSession implements ISession, Parser.Listener, Handler handler, FrameBytes frameBytes) { if (controller != null) + { + logger.debug("Writing {} frame bytes of {}", buffer.remaining(), frameBytes); controller.write(buffer, handler, frameBytes); + } } private void complete(final Handler handler, final C context) @@ -920,8 +934,10 @@ public class StandardSession implements ISession, Parser.Listener, Handler { + public IStream getStream(); + public abstract ByteBuffer getByteBuffer(); public abstract void complete(); @@ -929,16 +945,30 @@ public class StandardSession implements ISession, Parser.Listener, Handler implements FrameBytes, Runnable { + private final IStream stream; private final Handler handler; private final C context; protected volatile ScheduledFuture task; - protected AbstractFrameBytes(Handler handler, C context) + protected AbstractFrameBytes(IStream stream, Handler handler, C context) { + this.stream = stream; this.handler = handler; this.context = context; } + @Override + public IStream getStream() + { + return stream; + } + + @Override + public int compareTo(FrameBytes that) + { + return getStream().getPriority() - that.getStream().getPriority(); + } + @Override public void complete() { @@ -966,9 +996,9 @@ public class StandardSession implements ISession, Parser.Listener, Handler handler, C context, ControlFrame frame, ByteBuffer buffer) + private ControlFrameBytes(IStream stream, Handler handler, C context, ControlFrame frame, ByteBuffer buffer) { - super(handler, context); + super(stream, handler, context); this.frame = frame; this.buffer = buffer; } @@ -1003,15 +1033,13 @@ public class StandardSession implements ISession, Parser.Listener, Handler extends AbstractFrameBytes { - private final IStream stream; private final DataInfo dataInfo; private int size; private volatile ByteBuffer buffer; - private DataFrameBytes(Handler handler, C context, IStream stream, DataInfo dataInfo) + private DataFrameBytes(IStream stream, Handler handler, C context, DataInfo dataInfo) { - super(handler, context); - this.stream = stream; + super(stream, handler, context); this.dataInfo = dataInfo; } @@ -1020,6 +1048,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler 0) @@ -1049,7 +1079,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler Date: Mon, 2 Apr 2012 10:06:35 +0200 Subject: [PATCH 03/36] Fixed infinite recursive loop. --- .../src/main/java/org/eclipse/jetty/client/HttpClient.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java index 0b5581ed984..4de850fa627 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java @@ -171,7 +171,7 @@ public class HttpClient extends AggregateLifeCycle implements HttpBuffers, Attri /* ------------------------------------------------------------ */ /** Set the ThreadPool. - * The threadpool passed is added via {@link #addBean(Object)} so that + * The threadpool passed is added via {@link #addBean(Object)} so that * it's lifecycle may be managed as a {@link AggregateLifeCycle}. * @param threadPool the threadPool to set */ @@ -878,7 +878,7 @@ public class HttpClient extends AggregateLifeCycle implements HttpBuffers, Attri @Deprecated public void setProvider(String provider) { - setProvider(provider); + _sslContextFactory.setProvider(provider); } /* ------------------------------------------------------------ */ From fff059f7a99ba53c8aaa2ea9837ac47868362afc Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Mon, 2 Apr 2012 10:07:25 +0200 Subject: [PATCH 04/36] Making sure bytes are masked when doing int operations. --- .../org/eclipse/jetty/spdy/generator/SettingsGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SettingsGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SettingsGenerator.java index 7a8496eb4bd..c61846ebd84 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SettingsGenerator.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SettingsGenerator.java @@ -65,7 +65,7 @@ public class SettingsGenerator extends ControlFrameGenerator case SPDY.V2: { // In v2 the format is 24 bits of ID + 8 bits of flag - int idAndFlags = (id << 8) + flags; + int idAndFlags = (id << 8) + (flags & 0xFF); // A bug in the Chromium implementation forces v2 to have // the 3 ID bytes little endian, so we swap first and third int result = idAndFlags & 0x00_FF_00_FF; From 00b31b6577e1419fa5fe84d55c92e31297ea7627 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Mon, 2 Apr 2012 10:07:51 +0200 Subject: [PATCH 05/36] Added defaults in switches. --- .../org/eclipse/jetty/spdy/parser/GoAwayBodyParser.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/GoAwayBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/GoAwayBodyParser.java index dc948968f3d..753ad804d4d 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/GoAwayBodyParser.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/GoAwayBodyParser.java @@ -58,6 +58,10 @@ public class GoAwayBodyParser extends ControlFrameBodyParser state = State.STATUS_CODE; break; } + default: + { + throw new IllegalStateException(); + } } } else @@ -87,6 +91,10 @@ public class GoAwayBodyParser extends ControlFrameBodyParser state = State.STATUS_CODE; break; } + default: + { + throw new IllegalStateException(); + } } } break; From bb429a7f186d3812e3305e88d15a139800f210ef Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Mon, 2 Apr 2012 10:09:55 +0200 Subject: [PATCH 06/36] 375509 - Stalled stream stalls other streams or session control frames. Now using a "death pill" instead of a boolean in order to avoid race conditions where DataInfos were read from the queue (but the boolean not updated yet), and viceversa. --- .../http/ServerHTTPSPDYAsyncConnection.java | 56 ++++++++++++------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java index e263654af16..f782d656467 100644 --- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java +++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java @@ -57,6 +57,7 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem { private static final Logger logger = LoggerFactory.getLogger(ServerHTTPSPDYAsyncConnection.class); private static final ByteBuffer ZERO_BYTES = ByteBuffer.allocate(0); + private static final DataInfo END_OF_CONTENT = new ByteBufferDataInfo(ZERO_BYTES, true); private final Queue tasks = new LinkedList<>(); private final BlockingQueue dataInfos = new LinkedBlockingQueue<>(); @@ -65,7 +66,6 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem private Headers headers; // No need for volatile, guarded by state private DataInfo dataInfo; // No need for volatile, guarded by state private NIOBuffer buffer; // No need for volatile, guarded by state - private boolean complete; // No need for volatile, guarded by state private volatile State state = State.INITIAL; private boolean dispatched; // Guarded by synchronization on tasks @@ -160,7 +160,7 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem logger.debug("HTTP > {} {} {}", new Object[]{m, u, v}); startRequest(new ByteArrayBuffer(m), new ByteArrayBuffer(u), new ByteArrayBuffer(v)); - state = State.HEADERS; + updateState(State.HEADERS); handle(); break; } @@ -261,6 +261,12 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem { } + private void updateState(State newState) + { + logger.debug("State update {} -> {}", state, newState); + state = newState; + } + public void beginRequest(final Headers headers) { this.headers = headers.isEmpty() ? null : headers; @@ -270,7 +276,7 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem public void run() { if (!headers.isEmpty()) - state = State.REQUEST; + updateState(State.REQUEST); handle(); } }); @@ -284,7 +290,7 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem @Override public void run() { - state = state == State.INITIAL ? State.REQUEST : State.HEADERS; + updateState(state == State.INITIAL ? State.REQUEST : State.HEADERS); handle(); } }); @@ -292,7 +298,10 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem public void content(final DataInfo dataInfo, boolean endRequest) { - dataInfos.offer(new ByteBufferDataInfo(dataInfo.asByteBuffer(false), dataInfo.isClose(), dataInfo.isCompress()) + // We need to copy the dataInfo since we do not know when its bytes + // will be consumed. When the copy is consumed, we consume also the + // original, so the implementation can send a window update. + ByteBufferDataInfo copyDataInfo = new ByteBufferDataInfo(dataInfo.asByteBuffer(false), dataInfo.isClose(), dataInfo.isCompress()) { @Override public void consume(int delta) @@ -300,8 +309,11 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem super.consume(delta); dataInfo.consume(delta); } - }); - complete = endRequest; + }; + logger.debug("Queuing last={} content {}", endRequest, copyDataInfo); + dataInfos.offer(copyDataInfo); + if (endRequest) + dataInfos.offer(END_OF_CONTENT); post(new Runnable() { @Override @@ -310,10 +322,10 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem logger.debug("HTTP > {} bytes of content", dataInfo.length()); if (state == State.HEADERS) { - state = State.HEADERS_COMPLETE; + updateState(State.HEADERS_COMPLETE); handle(); } - state = State.CONTENT; + updateState(State.CONTENT); handle(); } }); @@ -327,10 +339,10 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem { if (state == State.HEADERS) { - state = State.HEADERS_COMPLETE; + updateState(State.HEADERS_COMPLETE); handle(); } - state = State.FINAL; + updateState(State.FINAL); handle(); } }); @@ -343,10 +355,10 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem @Override public void run() { - State currentState = state; - state = State.ASYNC; + State oldState = state; + updateState(State.ASYNC); handle(); - state = currentState; + updateState(oldState); } }); } @@ -370,12 +382,10 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem else { // The application has consumed the buffer, so consume also the DataInfo - if (dataInfo.consumed() == 0) - dataInfo.consume(dataInfo.length()); + dataInfo.consume(dataInfo.length()); + logger.debug("Consumed {} content bytes, queue size {}", dataInfo.consumed(), dataInfos.size()); dataInfo = null; buffer = null; - if (complete && dataInfos.isEmpty()) - return null; // Loop to get content bytes from DataInfos } } @@ -388,9 +398,13 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem logger.debug("Waited {} ms for content bytes", elapsed); if (dataInfo != null) { - // Only consume if it's the last DataInfo - boolean consume = complete && dataInfos.isEmpty(); - ByteBuffer byteBuffer = dataInfo.asByteBuffer(consume); + if (dataInfo == END_OF_CONTENT) + { + logger.debug("End of content bytes, queue size {}", dataInfos.size()); + return null; + } + + ByteBuffer byteBuffer = dataInfo.asByteBuffer(false); buffer = byteBuffer.isDirect() ? new DirectNIOBuffer(byteBuffer, false) : new IndirectNIOBuffer(byteBuffer, false); // Loop to return the buffer } From cc1bef6f2e43f120e417e9771976e992ba73d7f0 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 2 Apr 2012 18:18:39 +1000 Subject: [PATCH 07/36] 375594 fixed SSL tests so they are not order dependent --- .../eclipse/jetty/server/ssl/SSLEngineTest.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLEngineTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLEngineTest.java index 2fcb497d05f..df08d35508c 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLEngineTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLEngineTest.java @@ -99,8 +99,6 @@ public class SSLEngineTest connector.setRequestHeaderSize(512); server.setConnectors(new Connector[]{connector }); - server.setHandler(new HelloWorldHandler()); - server.start(); } @AfterClass @@ -109,10 +107,15 @@ public class SSLEngineTest server.stop(); server.join(); } + @Test public void testBigResponse() throws Exception { + server.stop(); + server.setHandler(new HelloWorldHandler()); + server.start(); + SSLContext ctx=SSLContext.getInstance("TLS"); ctx.init(null,SslContextFactory.TRUST_ALL_CERTS,new java.security.SecureRandom()); @@ -123,7 +126,7 @@ public class SSLEngineTest String request = "GET /?dump=102400 HTTP/1.1\r\n"+ - "Host: localhost:8080\r\n"+ + "Host: localhost:"+port+"\r\n"+ "Connection: close\r\n"+ "\r\n"; @@ -138,6 +141,10 @@ public class SSLEngineTest @Test public void testRequestJettyHttps() throws Exception { + server.stop(); + server.setHandler(new HelloWorldHandler()); + server.start(); + final int loops=10; final int numConns=10; @@ -204,8 +211,7 @@ public class SSLEngineTest @Test public void testServletPost() throws Exception { - stopServer(); - + server.stop(); StreamHandler handler = new StreamHandler(); server.setHandler(handler); server.start(); @@ -308,6 +314,7 @@ public class SSLEngineTest { ServletOutputStream out=response.getOutputStream(); byte[] buf = new byte[Integer.valueOf(request.getParameter("dump"))]; + // System.err.println("DUMP "+buf.length); for (int i=0;i Date: Mon, 2 Apr 2012 13:14:57 +0200 Subject: [PATCH 08/36] Made the test more reliable. --- .../src/test/java/org/eclipse/jetty/spdy/ResetStreamTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ResetStreamTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ResetStreamTest.java index 1a18578611c..c6c0a2b4449 100644 --- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ResetStreamTest.java +++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ResetStreamTest.java @@ -64,6 +64,8 @@ public class ResetStreamTest extends AbstractTest Assert.assertEquals(0, serverSession.getStreams().size()); Assert.assertTrue(rstLatch.await(5, TimeUnit.SECONDS)); + // Need to sleep a while to give the chance to the implementation to remove the stream + TimeUnit.SECONDS.sleep(1); Assert.assertEquals(0, clientSession.getStreams().size()); } From b44fe2094fc2bcfd3a9d83cccb5983329c69681a Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Mon, 2 Apr 2012 13:16:40 +0200 Subject: [PATCH 09/36] Fixed Maven warning. --- jetty-spdy/spdy-jetty-http/pom.xml | 6 +++--- jetty-spdy/spdy-jetty/pom.xml | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/jetty-spdy/spdy-jetty-http/pom.xml b/jetty-spdy/spdy-jetty-http/pom.xml index eb6ab126a5c..a73edfc9ed2 100644 --- a/jetty-spdy/spdy-jetty-http/pom.xml +++ b/jetty-spdy/spdy-jetty-http/pom.xml @@ -28,7 +28,7 @@ ${npn.version} jar false - ${build.directory}/npn + ${project.build.directory}/npn @@ -38,7 +38,7 @@ maven-surefire-plugin - -Xbootclasspath/p:${build.directory}/npn/npn-boot-${npn.version}.jar + -Xbootclasspath/p:${project.build.directory}/npn/npn-boot-${npn.version}.jar @@ -81,4 +81,4 @@ test - \ No newline at end of file + diff --git a/jetty-spdy/spdy-jetty/pom.xml b/jetty-spdy/spdy-jetty/pom.xml index c6f86c27769..2b4f11d2339 100644 --- a/jetty-spdy/spdy-jetty/pom.xml +++ b/jetty-spdy/spdy-jetty/pom.xml @@ -27,7 +27,7 @@ ${npn.version} jar false - ${build.directory}/npn + ${project.build.directory}/npn @@ -37,7 +37,7 @@ maven-surefire-plugin - -Xbootclasspath/p:${build.directory}/npn/npn-boot-${npn.version}.jar + -Xbootclasspath/p:${project.build.directory}/npn/npn-boot-${npn.version}.jar @@ -50,7 +50,7 @@ maven-surefire-plugin - true + true @@ -85,4 +85,4 @@ test - \ No newline at end of file + From 30adf7cd18d3611cace9a5a2da63d979847caa2d Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Mon, 2 Apr 2012 13:22:06 +0200 Subject: [PATCH 10/36] Added missing flush after writing frames. Frames may be written asynchronously but without a Handler, and therefore it was possible that frames queued up, that one flush() was writing a frame without Handler, and the flush was stopping even if the queue was non-empty. Now we call flush() after writing a frame. --- .../eclipse/jetty/spdy/StandardSession.java | 1 + .../jetty/spdy/SynDataReplyDataLoadTest.java | 54 +++++++++++-------- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java index 42f5ba0ef44..ecf5deb1fed 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java @@ -854,6 +854,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler> tasks = new ArrayList<>(); - for (int i = 0; i < count; ++i) - { - tasks.add(new Callable() - { - @Override - public Object call() throws Exception - { - synCompletedData(session, headers, iterations); - return null; - } - }); - } - ExecutorService threadPool = Executors.newFixedThreadPool(count); - List> futures = threadPool.invokeAll(tasks); - for (Future future : futures) - future.get(iterations, TimeUnit.SECONDS); - Assert.assertTrue(latch.await(count * iterations, TimeUnit.SECONDS)); + List> tasks = new ArrayList<>(); tasks.clear(); for (int i = 0; i < count; ++i) @@ -120,11 +103,38 @@ public class SynDataReplyDataLoadTest extends AbstractTest } }); } + { + long begin = System.nanoTime(); + List> futures = threadPool.invokeAll(tasks); + for (Future future : futures) + future.get(iterations, TimeUnit.SECONDS); + Assert.assertTrue(latch.await(count * iterations, TimeUnit.SECONDS)); + long end = System.nanoTime(); + System.err.printf("SYN+GET+DATA+GET completed in %d ms%n", TimeUnit.NANOSECONDS.toMillis(end - begin)); + } - futures = threadPool.invokeAll(tasks); - for (Future future : futures) - future.get(iterations, TimeUnit.SECONDS); - Assert.assertTrue(latch.await(count * iterations, TimeUnit.SECONDS)); + tasks.clear(); + for (int i = 0; i < count; ++i) + { + tasks.add(new Callable() + { + @Override + public Object call() throws Exception + { + synCompletedData(session, headers, iterations); + return null; + } + }); + } + { + long begin = System.nanoTime(); + List> futures = threadPool.invokeAll(tasks); + for (Future future : futures) + future.get(iterations, TimeUnit.SECONDS); + Assert.assertTrue(latch.await(count * iterations, TimeUnit.SECONDS)); + long end = System.nanoTime(); + System.err.printf("SYN+COMPLETED+DATA completed in %d ms%n", TimeUnit.NANOSECONDS.toMillis(end - begin)); + } threadPool.shutdown(); } From 2b83d9d9545a148eacca3fc5461eec27a502b1e2 Mon Sep 17 00:00:00 2001 From: Thomas Becker Date: Mon, 2 Apr 2012 13:41:36 +0200 Subject: [PATCH 11/36] 375692: cosmetic changes to get rid of warnings, etc. Change-Id: Id4d76a7f6e5bd989505e5233af73d5526b8e7c1f --- .../http/gzip/AbstractCompressedStream.java | 4 +-- .../eclipse/jetty/servlets/GzipFilter.java | 31 +++++++++---------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/gzip/AbstractCompressedStream.java b/jetty-http/src/main/java/org/eclipse/jetty/http/gzip/AbstractCompressedStream.java index f879610be29..77ac1fe41d0 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/gzip/AbstractCompressedStream.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/gzip/AbstractCompressedStream.java @@ -13,8 +13,6 @@ package org.eclipse.jetty.http.gzip; -import java.io.Closeable; -import java.io.Flushable; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; @@ -32,7 +30,7 @@ import org.eclipse.jetty.util.ByteArrayOutputStream2; /** * Skeletal implementation of a CompressedStream. This class adds compression features to a ServletOutputStream and takes care of setting response headers, etc. * Major work and configuration is done here. Subclasses using different kinds of compression only have to implement the abstract methods doCompress() and - * setContentEncoding() using the desired compression and setting the appropiate Content-Encoding header string. + * setContentEncoding() using the desired compression and setting the appropriate Content-Encoding header string. */ public abstract class AbstractCompressedStream extends ServletOutputStream { diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java index 40564cae0e8..2f4128da184 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java @@ -150,21 +150,6 @@ public class GzipFilter extends UserAgentFilter { } - /* ------------------------------------------------------------ */ - public String selectCompression(String encodingHeader) - { - // TODO, this could be a little more robust. - // prefer gzip over deflate - if (encodingHeader!=null) - { - if (encodingHeader.toLowerCase().contains(GZIP)) - return GZIP; - if (encodingHeader.toLowerCase().contains(DEFLATE)) - return DEFLATE; - } - return null; - } - /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.servlets.UserAgentFilter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) @@ -176,7 +161,6 @@ public class GzipFilter extends UserAgentFilter HttpServletRequest request=(HttpServletRequest)req; HttpServletResponse response=(HttpServletResponse)res; - String ae = request.getHeader("accept-encoding"); String compressionType = selectCompression(request.getHeader("accept-encoding")); if (compressionType!=null && !response.containsHeader("Content-Encoding") && !HttpMethods.HEAD.equalsIgnoreCase(request.getMethod())) { @@ -223,6 +207,21 @@ public class GzipFilter extends UserAgentFilter } } + /* ------------------------------------------------------------ */ + private String selectCompression(String encodingHeader) + { + // TODO, this could be a little more robust. + // prefer gzip over deflate + if (encodingHeader!=null) + { + if (encodingHeader.toLowerCase().contains(GZIP)) + return GZIP; + else if (encodingHeader.toLowerCase().contains(DEFLATE)) + return DEFLATE; + } + return null; + } + protected CompressedResponseWrapper createWrappedResponse(HttpServletRequest request, HttpServletResponse response, final String compressionType) { CompressedResponseWrapper wrappedResponse = null; From d231b5714494107e31018a91680f45ed459b9870 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Mon, 2 Apr 2012 15:39:01 +0200 Subject: [PATCH 12/36] Made the test more reliable. --- .../java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java index 610087acb18..85cea3452d7 100644 --- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java +++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java @@ -22,7 +22,6 @@ import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; import org.eclipse.jetty.spdy.api.Handler; import org.eclipse.jetty.spdy.api.SPDY; @@ -94,17 +93,15 @@ public class AsyncTimeoutTest Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory.StandardCompressor()); Session session = new StandardSession(SPDY.V2, bufferPool, threadPool, scheduler, new TestController(), null, 1, null, generator) { - private final AtomicInteger flushes = new AtomicInteger(); - @Override - public void flush() + protected void write(ByteBuffer buffer, Handler handler, FrameBytes frameBytes) { try { - int flushes = this.flushes.incrementAndGet(); - if (flushes == 3) + // Wait if we're writing the data frame (control frame's first byte is 0x80) + if (buffer.get(0) == 0) unit.sleep(2 * timeout); - super.flush(); + super.write(buffer, handler, frameBytes); } catch (InterruptedException x) { From 5b2d703a042c4e99dad062803340d0e909717481 Mon Sep 17 00:00:00 2001 From: Jesse McConnell Date: Mon, 2 Apr 2012 10:21:22 -0500 Subject: [PATCH 13/36] remove jetty-npn from build and release separately --- jetty-npn/pom.xml | 26 ++++++++++++++++++++++++-- pom.xml | 1 - 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/jetty-npn/pom.xml b/jetty-npn/pom.xml index b251398c1e3..d491b764486 100644 --- a/jetty-npn/pom.xml +++ b/jetty-npn/pom.xml @@ -4,13 +4,35 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> org.eclipse.jetty - jetty-project - 7.6.2-SNAPSHOT + jetty-parent + 19 4.0.0 org.eclipse.jetty.npn npn-api + 1.0.0-SNAPSHOT Jetty :: Next Protocol Negotiation :: API + + scm:git:http://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project.git + scm:git:ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project.git + http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/jetty-npn + + + + + + org.apache.maven.plugins + maven-release-plugin + 2.2.1 + + false + deploy + -Peclipse-release + clean install + + + + diff --git a/pom.xml b/pom.xml index 6e4d55f5deb..1b372a6f220 100644 --- a/pom.xml +++ b/pom.xml @@ -358,7 +358,6 @@ jetty-http jetty-websocket jetty-continuation - jetty-npn jetty-server jetty-client jetty-xml From eea06004f5a0a234b20f3ee8259f33b5b6967372 Mon Sep 17 00:00:00 2001 From: Jesse McConnell Date: Mon, 2 Apr 2012 10:23:36 -0500 Subject: [PATCH 14/36] [maven-release-plugin] prepare release npn-api-1.0.0.v20120402 --- jetty-npn/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-npn/pom.xml b/jetty-npn/pom.xml index 354b81cc2cb..dbe627a5267 100644 --- a/jetty-npn/pom.xml +++ b/jetty-npn/pom.xml @@ -9,7 +9,7 @@ 4.0.0 org.eclipse.jetty.npn npn-api - 1.0.0-SNAPSHOT + 1.0.0.v20120402 Jetty :: Next Protocol Negotiation :: API From 71091da2c4ba8a25072d3b8761a7dee8a1eef4ed Mon Sep 17 00:00:00 2001 From: Jesse McConnell Date: Mon, 2 Apr 2012 10:23:43 -0500 Subject: [PATCH 15/36] [maven-release-plugin] prepare for next development iteration --- jetty-npn/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-npn/pom.xml b/jetty-npn/pom.xml index dbe627a5267..063dffda7a0 100644 --- a/jetty-npn/pom.xml +++ b/jetty-npn/pom.xml @@ -9,7 +9,7 @@ 4.0.0 org.eclipse.jetty.npn npn-api - 1.0.0.v20120402 + 1.0.1-SNAPSHOT Jetty :: Next Protocol Negotiation :: API From b2b4b2733b6bc829c7730f8b48f57ce5b6b3ae32 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 3 Apr 2012 10:12:46 +1000 Subject: [PATCH 16/36] jetty-spdy fixed version of api --- jetty-spdy/spdy-jetty/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-spdy/spdy-jetty/pom.xml b/jetty-spdy/spdy-jetty/pom.xml index 2b4f11d2339..b2f7d3ad27e 100644 --- a/jetty-spdy/spdy-jetty/pom.xml +++ b/jetty-spdy/spdy-jetty/pom.xml @@ -71,7 +71,7 @@ org.eclipse.jetty.npn npn-api - ${project.version} + ${npn.version} provided From 83a4bb71a3551c634257ef151ace95d0e7e2ec82 Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Tue, 3 Apr 2012 17:03:26 +1000 Subject: [PATCH 17/36] 374475 Response.sendRedirect does not encode UTF-8 characters properly --- .../eclipse/jetty/server/ResponseTest.java | 5 +- .../java/org/eclipse/jetty/util/URIUtil.java | 138 +++++++++++++----- 2 files changed, 107 insertions(+), 36 deletions(-) diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java index eab27a6c9b8..b936a5f6513 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java @@ -383,7 +383,7 @@ public class ResponseTest { String[][] tests={ {"/other/location?name=value","http://myhost:8888/other/location;jsessionid=12345?name=value"}, - {"/other/location","http://myhost:8888/other/location"}, + /* {"/other/location","http://myhost:8888/other/location"}, {"/other/l%20cation","http://myhost:8888/other/l%20cation"}, {"location","http://myhost:8888/path/location"}, {"./location","http://myhost:8888/path/location"}, @@ -391,7 +391,8 @@ public class ResponseTest {"/other/l%20cation","http://myhost:8888/other/l%20cation"}, {"l%20cation","http://myhost:8888/path/l%20cation"}, {"./l%20cation","http://myhost:8888/path/l%20cation"}, - {"../l%20cation","http://myhost:8888/l%20cation"}, + {"../l%20cation","http://myhost:8888/l%20cation"},*/ + {"../locati%C3%abn","http://myhost:8888/locati%C3%ABn"}, }; for (int i=1;i': case ' ': - buf=new StringBuilder(path.length()<<1); + buf=new StringBuilder(path.length()*2); break loop; + default: + if (c>127) + { + try + { + bytes=path.getBytes(URIUtil.__CHARSET); + } + catch (UnsupportedEncodingException e) + { + throw new IllegalStateException(e); + } + buf=new StringBuilder(path.length()*2); + break loop; + } + } } if (buf==null) @@ -94,41 +114,91 @@ public class URIUtil synchronized(buf) { - for (int i=0;i': - buf.append("%3E"); - continue; - case ' ': - buf.append("%20"); - continue; - default: - buf.append(c); - continue; + byte c=bytes[i]; + switch(c) + { + case '%': + buf.append("%25"); + continue; + case '?': + buf.append("%3F"); + continue; + case ';': + buf.append("%3B"); + continue; + case '#': + buf.append("%23"); + continue; + case '"': + buf.append("%22"); + continue; + case '\'': + buf.append("%27"); + continue; + case '<': + buf.append("%3C"); + continue; + case '>': + buf.append("%3E"); + continue; + case ' ': + buf.append("%20"); + continue; + default: + if (c<0) + { + buf.append('%'); + TypeUtil.toHex(c,buf); + } + else + buf.append((char)c); + continue; + } + } + + } + else + { + for (int i=0;i': + buf.append("%3E"); + continue; + case ' ': + buf.append("%20"); + continue; + default: + buf.append(c); + continue; + } } } } From 6c464238b789c7b2f44b5472fe6a465d5067386c Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Tue, 3 Apr 2012 12:00:38 +0200 Subject: [PATCH 18/36] Updated dependency on jetty-npn, now that it moved to its own project at github and it's unlocked from jetty releases. --- jetty-spdy/pom.xml | 10 +- jetty-spdy/spdy-jetty-http-webapp/pom.xml | 123 +++++++------- .../src/main/config/etc/jetty-spdy.xml | 7 - jetty-spdy/spdy-jetty-http/pom.xml | 146 ++++++++-------- jetty-spdy/spdy-jetty/pom.xml | 157 ++++++++---------- 5 files changed, 205 insertions(+), 238 deletions(-) diff --git a/jetty-spdy/pom.xml b/jetty-spdy/pom.xml index 168a701ccf7..11853843122 100644 --- a/jetty-spdy/pom.xml +++ b/jetty-spdy/pom.xml @@ -12,13 +12,9 @@ pom Jetty :: SPDY :: Parent - - - 7.6.2.v20120308 - + + 1.0.0.v20120402 + spdy-core diff --git a/jetty-spdy/spdy-jetty-http-webapp/pom.xml b/jetty-spdy/spdy-jetty-http-webapp/pom.xml index 6c2c2c050f9..68b571f5925 100644 --- a/jetty-spdy/spdy-jetty-http-webapp/pom.xml +++ b/jetty-spdy/spdy-jetty-http-webapp/pom.xml @@ -1,63 +1,64 @@ - - - org.eclipse.jetty.spdy - spdy-parent - 7.6.3-SNAPSHOT - - 4.0.0 - spdy-jetty-http-webapp - war - Jetty :: SPDY :: Jetty HTTP Web Application - - - - org.apache.maven.plugins - maven-assembly-plugin - - - package - - single - - - - config - - - - - - - - - \ No newline at end of file + + 8888 + quit + + -Dlog4j.configuration=file://${basedir}/src/main/resources/log4j.properties + -Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${project.version}/npn-boot-${project.version}.jar + + ${basedir}/src/main/config/jetty-spdy.xml + / + + + + org.eclipse.jetty.spdy + spdy-jetty-http + ${project.version} + + + org.slf4j + slf4j-log4j12 + ${slf4j-version} + + + +--> + + + diff --git a/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy.xml b/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy.xml index 8d4c1441928..2c45ca72fdc 100644 --- a/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy.xml +++ b/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy.xml @@ -9,13 +9,6 @@ src/main/resources/truststore.jks storepwd TLSv1 - - - TLSv1 - TLSv1.1 - TLSv1.2 - - diff --git a/jetty-spdy/spdy-jetty-http/pom.xml b/jetty-spdy/spdy-jetty-http/pom.xml index a73edfc9ed2..d0dfa511a39 100644 --- a/jetty-spdy/spdy-jetty-http/pom.xml +++ b/jetty-spdy/spdy-jetty-http/pom.xml @@ -1,84 +1,72 @@ - - org.eclipse.jetty.spdy - spdy-parent - 7.6.3-SNAPSHOT - - 4.0.0 - spdy-jetty-http - Jetty :: SPDY :: Jetty HTTP Layer - - - - maven-dependency-plugin - - - copy - generate-resources - - copy - - - - - org.mortbay.jetty.npn - npn-boot - ${npn.version} - jar - false - ${project.build.directory}/npn - - - - - - - - maven-surefire-plugin - - -Xbootclasspath/p:${project.build.directory}/npn/npn-boot-${npn.version}.jar - - - - - - - eclipse-release - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + org.eclipse.jetty.spdy + spdy-parent + 7.6.3-SNAPSHOT + + 4.0.0 + spdy-jetty-http + Jetty :: SPDY :: Jetty HTTP Layer + + - - maven-surefire-plugin - - true - - + + maven-dependency-plugin + + + copy + generate-resources + + copy + + + + + org.mortbay.jetty.npn + npn-boot + ${npn.version} + jar + false + ${project.build.directory}/npn + + + + + + + + maven-surefire-plugin + + -Xbootclasspath/p:${project.build.directory}/npn/npn-boot-${npn.version}.jar + + - - - - - - org.eclipse.jetty.spdy - spdy-jetty - ${project.version} - - - junit - junit - - - org.eclipse.jetty.npn - npn-api - ${project.version} - test - - - org.slf4j - slf4j-log4j12 - ${slf4j-version} - test - - + + + + + org.eclipse.jetty.spdy + spdy-jetty + ${project.version} + + + junit + junit + + + org.eclipse.jetty.npn + npn-api + ${project.version} + test + + + org.slf4j + slf4j-log4j12 + ${slf4j-version} + test + + + diff --git a/jetty-spdy/spdy-jetty/pom.xml b/jetty-spdy/spdy-jetty/pom.xml index b2f7d3ad27e..6ed4466b993 100644 --- a/jetty-spdy/spdy-jetty/pom.xml +++ b/jetty-spdy/spdy-jetty/pom.xml @@ -1,88 +1,77 @@ - - - org.eclipse.jetty.spdy - spdy-parent - 7.6.3-SNAPSHOT - - 4.0.0 - spdy-jetty - Jetty :: SPDY :: Jetty Binding - - - - maven-dependency-plugin - - - copy - generate-resources - - copy - - - - - org.mortbay.jetty.npn - npn-boot - ${npn.version} - jar - false - ${project.build.directory}/npn - - - - - - - - maven-surefire-plugin - - -Xbootclasspath/p:${project.build.directory}/npn/npn-boot-${npn.version}.jar - - - - - - - eclipse-release - + + + org.eclipse.jetty.spdy + spdy-parent + 7.6.3-SNAPSHOT + + 4.0.0 + spdy-jetty + Jetty :: SPDY :: Jetty Binding + + - - maven-surefire-plugin - - true - - + + maven-dependency-plugin + + + copy + generate-resources + + copy + + + + + org.mortbay.jetty.npn + npn-boot + ${npn.version} + jar + false + ${project.build.directory}/npn + + + + + + + + maven-surefire-plugin + + -Xbootclasspath/p:${project.build.directory}/npn/npn-boot-${npn.version}.jar + + - - - - - - org.eclipse.jetty.spdy - spdy-core - ${project.version} - - - org.eclipse.jetty - jetty-server - ${project.version} - - - org.eclipse.jetty.npn - npn-api - ${npn.version} - provided - - - junit - junit - - - org.slf4j - slf4j-log4j12 - ${slf4j-version} - test - - + + + + + org.eclipse.jetty.spdy + spdy-core + ${project.version} + + + org.eclipse.jetty + jetty-server + ${project.version} + + + org.eclipse.jetty.npn + npn-api + ${npn.version} + provided + + + junit + junit + + + org.slf4j + slf4j-log4j12 + ${slf4j-version} + test + + + From 5b668fd6f123ffc0517c1ffe6ccd92fbafc79f14 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Tue, 3 Apr 2012 18:23:16 +0200 Subject: [PATCH 19/36] 375970 - HttpServletRequest.getRemoteAddr() returns null when HTTP is over SPDY. --- .../ServerHTTPSPDYAsyncConnectionFactory.java | 42 ++++++++++++++++++- .../jetty/spdy/http/ServerHTTPSPDYTest.java | 8 ++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java index 71bb51d5c26..30a10a61c79 100644 --- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java +++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java @@ -75,7 +75,7 @@ public class ServerHTTPSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnect logger.debug("Received {} on {}", synInfo, stream); - HTTPSPDYAsyncEndPoint asyncEndPoint = new HTTPSPDYAsyncEndPoint(stream); + HTTPSPDYAsyncEndPoint asyncEndPoint = new HTTPSPDYAsyncEndPoint(endPoint, stream); ServerHTTPSPDYAsyncConnection connection = new ServerHTTPSPDYAsyncConnection(connector, asyncEndPoint, connector.getServer(), (SPDYAsyncConnection)endPoint.getConnection(), stream); @@ -133,10 +133,12 @@ public class ServerHTTPSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnect private class HTTPSPDYAsyncEndPoint extends EmptyAsyncEndPoint { + private final AsyncEndPoint endPoint; private final Stream stream; - public HTTPSPDYAsyncEndPoint(Stream stream) + private HTTPSPDYAsyncEndPoint(AsyncEndPoint endPoint, Stream stream) { + this.endPoint = endPoint; this.stream = stream; } @@ -146,5 +148,41 @@ public class ServerHTTPSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnect ServerHTTPSPDYAsyncConnection connection = (ServerHTTPSPDYAsyncConnection)stream.getAttribute(CONNECTION_ATTRIBUTE); connection.async(); } + + @Override + public String getLocalAddr() + { + return endPoint.getLocalAddr(); + } + + @Override + public String getLocalHost() + { + return endPoint.getLocalHost(); + } + + @Override + public int getLocalPort() + { + return endPoint.getLocalPort(); + } + + @Override + public String getRemoteAddr() + { + return endPoint.getRemoteAddr(); + } + + @Override + public String getRemoteHost() + { + return endPoint.getRemoteHost(); + } + + @Override + public int getRemotePort() + { + return endPoint.getRemotePort(); + } } } diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYTest.java index b7932133d07..56d3f7d3b18 100644 --- a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYTest.java +++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYTest.java @@ -190,6 +190,14 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest Assert.assertEquals("POST", httpRequest.getMethod()); Assert.assertEquals("1", httpRequest.getParameter("a")); Assert.assertEquals("2", httpRequest.getParameter("b")); + Assert.assertNotNull(httpRequest.getRemoteHost()); + Assert.assertNotNull(httpRequest.getRemotePort()); + Assert.assertNotNull(httpRequest.getRemoteAddr()); + Assert.assertNotNull(httpRequest.getLocalPort()); + Assert.assertNotNull(httpRequest.getLocalName()); + Assert.assertNotNull(httpRequest.getLocalAddr()); + Assert.assertNotNull(httpRequest.getServerPort()); + Assert.assertNotNull(httpRequest.getServerName()); handlerLatch.countDown(); } }), null); From 792b1016398759080c6c4bb6bfb475cd05217072 Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Wed, 4 Apr 2012 15:13:02 +1000 Subject: [PATCH 20/36] Update version in MANIFESTs --- .../jetty-osgi-boot-jsp/META-INF/MANIFEST.MF | 2 +- .../META-INF/MANIFEST.MF | 2 +- .../META-INF/MANIFEST.MF | 2 +- .../jetty-osgi-boot/META-INF/MANIFEST.MF | 34 +++++++++---------- .../META-INF/MANIFEST.MF | 16 ++++----- .../META-INF/MANIFEST.MF | 12 +++---- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/jetty-osgi/jetty-osgi-boot-jsp/META-INF/MANIFEST.MF b/jetty-osgi/jetty-osgi-boot-jsp/META-INF/MANIFEST.MF index 313f9eba384..a7ddbdae081 100644 --- a/jetty-osgi/jetty-osgi-boot-jsp/META-INF/MANIFEST.MF +++ b/jetty-osgi/jetty-osgi-boot-jsp/META-INF/MANIFEST.MF @@ -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.6.2.qualifier +Bundle-Version: 7.6.3.qualifier Bundle-Vendor: Mort Bay Consulting Bundle-RequiredExecutionEnvironment: J2SE-1.5 Import-Package: com.sun.el;resolution:=optional, diff --git a/jetty-osgi/jetty-osgi-boot-logback/META-INF/MANIFEST.MF b/jetty-osgi/jetty-osgi-boot-logback/META-INF/MANIFEST.MF index 523e7195032..3d99bff6706 100644 --- a/jetty-osgi/jetty-osgi-boot-logback/META-INF/MANIFEST.MF +++ b/jetty-osgi/jetty-osgi-boot-logback/META-INF/MANIFEST.MF @@ -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.6.2.qualifier +Bundle-Version: 7.6.3.qualifier Bundle-Vendor: Mort Bay Consulting Bundle-RequiredExecutionEnvironment: J2SE-1.5 Import-Package: ch.qos.logback.classic, diff --git a/jetty-osgi/jetty-osgi-boot-warurl/META-INF/MANIFEST.MF b/jetty-osgi/jetty-osgi-boot-warurl/META-INF/MANIFEST.MF index 2a7d7cb71f9..d3b8cb1d1f8 100644 --- a/jetty-osgi/jetty-osgi-boot-warurl/META-INF/MANIFEST.MF +++ b/jetty-osgi/jetty-osgi-boot-warurl/META-INF/MANIFEST.MF @@ -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.6.2.qualifier +Bundle-Version: 7.6.3.qualifier Bundle-Activator: org.eclipse.jetty.osgi.boot.warurl.WarUrlActivator Bundle-Vendor: Mort Bay Consulting Bundle-RequiredExecutionEnvironment: J2SE-1.5 diff --git a/jetty-osgi/jetty-osgi-boot/META-INF/MANIFEST.MF b/jetty-osgi/jetty-osgi-boot/META-INF/MANIFEST.MF index cbda22dd84e..9c7522335e5 100644 --- a/jetty-osgi/jetty-osgi-boot/META-INF/MANIFEST.MF +++ b/jetty-osgi/jetty-osgi-boot/META-INF/MANIFEST.MF @@ -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.6.2.qualifier +Bundle-Version: 7.6.3.qualifier Bundle-Activator: org.eclipse.jetty.osgi.boot.JettyBootstrapActivator Import-Package: javax.mail;version="1.4.0";resolution:=optional, javax.mail.event;version="1.4.0";resolution:=optional, @@ -14,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.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.eclipse.jetty.deploy;version="7.6.3", + org.eclipse.jetty.deploy.providers;version="7.6.3", + org.eclipse.jetty.http;version="7.6.3", + org.eclipse.jetty.nested;version="7.6.3";resolution:=optional, + org.eclipse.jetty.server;version="7.6.3", + org.eclipse.jetty.server.handler;version="7.6.3", + org.eclipse.jetty.servlet;version="7.6.3", + org.eclipse.jetty.util;version="7.6.3", + org.eclipse.jetty.util.component;version="7.6.3", + org.eclipse.jetty.util.log;version="7.6.3", + org.eclipse.jetty.util.resource;version="7.6.3", + org.eclipse.jetty.webapp;version="7.6.3", + org.eclipse.jetty.xml;version="7.6.3", 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.6.2", - org.eclipse.jetty.osgi.nested;version="7.6.2", - org.eclipse.jetty.osgi.boot.utils;version="7.6.2" +Export-Package: org.eclipse.jetty.osgi.boot;version="7.6.3", + org.eclipse.jetty.osgi.nested;version="7.6.3", + org.eclipse.jetty.osgi.boot.utils;version="7.6.3" DynamicImport-Package: org.eclipse.jetty.*;version="[7.3,8)" diff --git a/jetty-osgi/jetty-osgi-equinoxtools/META-INF/MANIFEST.MF b/jetty-osgi/jetty-osgi-equinoxtools/META-INF/MANIFEST.MF index a9924522eb7..ded76f45e70 100644 --- a/jetty-osgi/jetty-osgi-equinoxtools/META-INF/MANIFEST.MF +++ b/jetty-osgi/jetty-osgi-equinoxtools/META-INF/MANIFEST.MF @@ -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.6.2.qualifier +Bundle-Version: 7.6.3.qualifier Bundle-Activator: org.eclipse.jetty.osgi.equinoxtools.WebEquinoxToolsActivator Import-Package: javax.servlet;version="2.5.0", javax.servlet.http;version="2.5.0", - org.eclipse.jetty.continuation;version="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.jetty.continuation;version="7.6.3", + org.eclipse.jetty.io;version="7.6.3", + org.eclipse.jetty.util;version="7.6.3", + org.eclipse.jetty.util.log;version="7.6.3", + org.eclipse.jetty.websocket;version="7.6.3", org.eclipse.osgi.framework.console;version="1.1.0", org.osgi.framework;version="1.3.0", org.osgi.service.http;version="1.2.0", org.osgi.util.tracker;version="1.3.0" -Export-Package: org.eclipse.jetty.osgi.equinoxtools;x-internal:=true;version="7.6.2", - org.eclipse.jetty.osgi.equinoxtools.console;x-internal:=true;version="7.6.2" +Export-Package: org.eclipse.jetty.osgi.equinoxtools;x-internal:=true;version="7.6.3", + org.eclipse.jetty.osgi.equinoxtools.console;x-internal:=true;version="7.6.3" Bundle-RequiredExecutionEnvironment: J2SE-1.5 diff --git a/jetty-osgi/jetty-osgi-httpservice/META-INF/MANIFEST.MF b/jetty-osgi/jetty-osgi-httpservice/META-INF/MANIFEST.MF index 5a4355ae120..9786928a822 100644 --- a/jetty-osgi/jetty-osgi-httpservice/META-INF/MANIFEST.MF +++ b/jetty-osgi/jetty-osgi-httpservice/META-INF/MANIFEST.MF @@ -1,16 +1,16 @@ Bundle-ManifestVersion: 2 Bundle-RequiredExecutionEnvironment: J2SE-1.5 Bundle-SymbolicName: org.eclipse.jetty.osgi.httpservice -Bundle-Version: 7.6.2.qualifier +Bundle-Version: 7.6.3.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.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" + org.eclipse.jetty.server;version="7.6.3", + org.eclipse.jetty.server.handler;version="7.6.3", + org.eclipse.jetty.servlet;version="7.6.3", + org.eclipse.jetty.util.component;version="7.6.3" +Export-Package: org.eclipse.jetty.osgi.httpservice;version="7.6.3" From 911643b783619b831cf0bbf229f41c8d62a13c46 Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Wed, 4 Apr 2012 15:13:33 +1000 Subject: [PATCH 21/36] Reformat src code; ensure url caching is controlled by jetty Resource.setDefaultUseCaches --- ...gableWebAppRegistrationCustomizerImpl.java | 170 ++--- .../WebappRegistrationCustomizerImpl.java | 242 ++++---- .../osgi/boot/jsp/FragmentActivator.java | 23 +- .../boot/jsp/TagLibOSGiConfiguration.java | 199 +++--- .../osgi/boot/warurl/WarUrlStreamHandler.java | 55 +- .../warurl/internal/WarURLConnection.java | 2 + .../osgi/boot/JettyBootstrapActivator.java | 179 +++--- .../JettyContextHandlerServiceTracker.java | 192 +++--- .../webapp/OSGiWebappClassLoader.java | 4 +- .../webapp/WebBundleDeployerHelper.java | 579 +++++++++--------- .../webapp/WebBundleTrackerCustomizer.java | 232 ++++--- .../internal/DefaultFileLocatorHelper.java | 275 +++++---- 12 files changed, 1084 insertions(+), 1068 deletions(-) diff --git a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/PluggableWebAppRegistrationCustomizerImpl.java b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/PluggableWebAppRegistrationCustomizerImpl.java index 3dc2f896c45..79854f2c99f 100644 --- a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/PluggableWebAppRegistrationCustomizerImpl.java +++ b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/PluggableWebAppRegistrationCustomizerImpl.java @@ -28,98 +28,106 @@ import org.osgi.framework.Bundle; import org.osgi.framework.FrameworkUtil; /** - * Plug bundles that contains tld files so that jasper will discover them - * and set them up in jetty. + * Plug bundles that contains tld files so that jasper will discover them and + * set them up in jetty. * - * For example: -Dorg.eclipse.jetty.osgi.tldbundles=org.springframework.web.servlet,com.opensymphony.module.sitemesh - * Otherwise use an attribute to the WebAppDeployer - * <New class="org.eclipse.jetty.deploy.providers.WebAppProvider"> - * .... - * <Set name="tldBundles"><Property name="org.eclipse.jetty.osgi.tldsbundles" default="" /></Set> - * <New> + * For example: + * -Dorg.eclipse.jetty.osgi.tldbundles=org.springframework.web.servlet + * ,com.opensymphony.module.sitemesh Otherwise use an attribute to the + * WebAppDeployer <New + * class="org.eclipse.jetty.deploy.providers.WebAppProvider"> .... <Set + * name="tldBundles"><Property name="org.eclipse.jetty.osgi.tldsbundles" + * default="" /></Set> <New> */ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistrationCustomizer { - /** - * To plug into jasper bundles that contain tld files - * please use a list of bundle's symbolic names: - * -Djetty.osgi.tldbundles=org.springframework.web.servlet,com.opensymphony.module.sitemesh - */ - public static final String SYS_PROP_TLD_BUNDLES = "org.eclipse.jetty.osgi.tldbundles"; - - /** - * Union of the tld bundles defined system wide and the one defines as an attribute of the AppProvider. - * @param provider - * @return - */ - private static Collection getTldBundles(OSGiAppProvider provider) - { - String sysprop = System.getProperty(SYS_PROP_TLD_BUNDLES); - String att = (String)provider.getTldBundles(); - if (sysprop == null && att == null) - { - return Collections.emptySet(); - } - if (att == null) - { - att = sysprop; - } - else if (sysprop != null) - { - att = att + "," + sysprop; - } - - Collection tldbundles = new HashSet(); - StringTokenizer tokenizer = new StringTokenizer(att, ", \n\r\t", false); - while (tokenizer.hasMoreTokens()) - { - tldbundles.add(tokenizer.nextToken()); - } - return tldbundles; - } - - /** - * @return The location of the jars that contain tld files. - * Jasper will discover them. - */ + /** + * To plug into jasper bundles that contain tld files please use a list of + * bundle's symbolic names: + * -Djetty.osgi.tldbundles=org.springframework.web.servlet + * ,com.opensymphony.module.sitemesh + */ + public static final String SYS_PROP_TLD_BUNDLES = "org.eclipse.jetty.osgi.tldbundles"; + + /** + * Union of the tld bundles defined system wide and the one defines as an + * attribute of the AppProvider. + * + * @param provider + * @return + */ + private static Collection getTldBundles(OSGiAppProvider provider) + { + String sysprop = System.getProperty(SYS_PROP_TLD_BUNDLES); + String att = (String) provider.getTldBundles(); + if (sysprop == null && att == null) { return Collections.emptySet(); } + if (att == null) + { + att = sysprop; + } + else if (sysprop != null) + { + att = att + "," + sysprop; + } + + Collection tldbundles = new HashSet(); + StringTokenizer tokenizer = new StringTokenizer(att, ", \n\r\t", false); + while (tokenizer.hasMoreTokens()) + { + tldbundles.add(tokenizer.nextToken()); + } + return tldbundles; + } + + /** + * @return The location of the jars that contain tld files. Jasper will + * discover them. + */ public URL[] getJarsWithTlds(OSGiAppProvider provider, BundleFileLocatorHelper locatorHelper) throws Exception { - List urls = new ArrayList(); - //naive way of finding those bundles. - //lots of assumptions: for example we assume a single version of each bundle that would contain tld files. - //this is probably good enough as those tlds are loaded system-wide on jetty. - //to do better than this we need to do it on a per webapp basis. - //probably using custom properties in the ContextHandler service - //and mirroring those in the MANIFEST.MF - - Bundle[] bundles = FrameworkUtil.getBundle(PluggableWebAppRegistrationCustomizerImpl.class).getBundleContext().getBundles(); - Collection tldbundles = getTldBundles(provider); - for (Bundle bundle : bundles) - { - if (tldbundles.contains(bundle.getSymbolicName())) - { - registerTldBundle(locatorHelper, bundle, urls); - } - } - - return urls.toArray(new URL[urls.size()]); + List urls = new ArrayList(); + // naive way of finding those bundles. + // lots of assumptions: for example we assume a single version of each + // bundle that would contain tld files. + // this is probably good enough as those tlds are loaded system-wide on + // jetty. + // to do better than this we need to do it on a per webapp basis. + // probably using custom properties in the ContextHandler service + // and mirroring those in the MANIFEST.MF + + Bundle[] bundles = FrameworkUtil.getBundle(PluggableWebAppRegistrationCustomizerImpl.class).getBundleContext().getBundles(); + Collection tldbundles = getTldBundles(provider); + for (Bundle bundle : bundles) + { + if (tldbundles.contains(bundle.getSymbolicName())) + { + registerTldBundle(locatorHelper, bundle, urls); + } + } + + return urls.toArray(new URL[urls.size()]); } - + /** * Resolves the bundle that contains tld files as a set of URLs that will be - * passed to jasper as a URLClassLoader later on. - * Usually that would be a single URL per bundle. - * But we do some more work if there are jars embedded in the bundle. + * passed to jasper as a URLClassLoader later on. Usually that would be a + * single URL per bundle. But we do some more work if there are jars + * embedded in the bundle. * - * The jasper TldScanner expects a URLClassloader to parse a jar for the /META-INF/*.tld it may contain. We place the bundles that we know contain such - * tag-libraries. Please note that it will work if and only if the bundle is a jar (!) Currently we just hardcode the bundle that contains the jstl - * implemenation. + * The jasper TldScanner expects a URLClassloader to parse a jar for the + * /META-INF/*.tld it may contain. We place the bundles that we know contain + * such tag-libraries. Please note that it will work if and only if the + * bundle is a jar (!) Currently we just hardcode the bundle that contains + * the jstl implemenation. * - * A workaround when the tld cannot be parsed with this method is to copy and paste it inside the WEB-INF of the webapplication where it is used. + * A workaround when the tld cannot be parsed with this method is to copy + * and paste it inside the WEB-INF of the webapplication where it is used. * - * Support only 2 types of packaging for the bundle: - the bundle is a jar (recommended for runtime.) - the bundle is a folder and contain jars in the root - * and/or in the lib folder (nice for PDE developement situations) Unsupported: the bundle is a jar that embeds more jars. + * Support only 2 types of packaging for the bundle: - the bundle is a jar + * (recommended for runtime.) - the bundle is a folder and contain jars in + * the root and/or in the lib folder (nice for PDE developement situations) + * Unsupported: the bundle is a jar that embeds more jars. * * @param locatorHelper * @param bundle @@ -152,9 +160,9 @@ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistra } else { - urls.add(jasperLocation.toURI().toURL()); + urls.add(jasperLocation.toURI().toURL()); } } - + } \ No newline at end of file diff --git a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/WebappRegistrationCustomizerImpl.java b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/WebappRegistrationCustomizerImpl.java index e0bd887cecd..44718bb37e3 100644 --- a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/WebappRegistrationCustomizerImpl.java +++ b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/WebappRegistrationCustomizerImpl.java @@ -36,48 +36,52 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** - * Fix various shortcomings with the way jasper parses the tld files. - * Plugs the JSTL tlds assuming that they are packaged with the bundle that contains the JSTL classes. + * Fix various shortcomings with the way jasper parses the tld files. Plugs the + * JSTL tlds assuming that they are packaged with the bundle that contains the + * JSTL classes. *

- * Pluggable tlds at the server level are handled by {@link PluggableWebAppRegistrationCustomizerImpl}. + * Pluggable tlds at the server level are handled by + * {@link PluggableWebAppRegistrationCustomizerImpl}. *

*/ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCustomizer { - - /** - * Default name of a class that belongs to the jstl bundle. - * From that class we locate the corresponding bundle and register it - * as a bundle that contains tld files. - */ - private static String DEFAULT_JSTL_BUNDLE_CLASS = "org.apache.taglibs.standard.tag.el.core.WhenTag"; - //used to be "org.apache.jasper.runtime.JspFactoryImpl" but now - //the standard tag library implementation are stored in a separate bundle. - - //DISABLED please use the tld bundle argument for the OSGiAppProvider -// /** -// * Default name of a class that belongs to the bundle where the Java server Faces tld files are defined. -// * This is the sun's reference implementation. -// */ -// private static String DEFAUT_JSF_IMPL_CLASS = "com.sun.faces.config.ConfigureListener"; - /** - * Default jsp factory implementation. - * Idally jasper is osgified and we can use services. - * In the mean time we statically set the jsp factory implementation. - * bug #299733 - */ - private static String DEFAULT_JSP_FACTORY_IMPL_CLASS = "org.apache.jasper.runtime.JspFactoryImpl"; - + /** + * Default name of a class that belongs to the jstl bundle. From that class + * we locate the corresponding bundle and register it as a bundle that + * contains tld files. + */ + private static String DEFAULT_JSTL_BUNDLE_CLASS = "org.apache.taglibs.standard.tag.el.core.WhenTag"; + + // used to be "org.apache.jasper.runtime.JspFactoryImpl" but now + // the standard tag library implementation are stored in a separate bundle. + + // DISABLED please use the tld bundle argument for the OSGiAppProvider + // /** + // * Default name of a class that belongs to the bundle where the Java + // server Faces tld files are defined. + // * This is the sun's reference implementation. + // */ + // private static String DEFAUT_JSF_IMPL_CLASS = + // "com.sun.faces.config.ConfigureListener"; + + /** + * Default jsp factory implementation. Idally jasper is osgified and we can + * use services. In the mean time we statically set the jsp factory + * implementation. bug #299733 + */ + private static String DEFAULT_JSP_FACTORY_IMPL_CLASS = "org.apache.jasper.runtime.JspFactoryImpl"; + public WebappRegistrationCustomizerImpl() { fixupDtdResolution(); - + try { - //sanity check: + // sanity check: Class cl = getClass().getClassLoader().loadClass("org.apache.jasper.servlet.JspServlet"); - //System.err.println("found the jsp servlet: " + cl.getName()); + // System.err.println("found the jsp servlet: " + cl.getName()); } catch (Exception e) { @@ -87,18 +91,18 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto } try { - //bug #299733 + // bug #299733 JspFactory fact = JspFactory.getDefaultFactory(); if (fact == null) - { //bug #299733 - //JspFactory does a simple Class.getForName("org.apache.jasper.runtime.JspFactoryImpl") - //however its bundles does not import the jasper package - //so it fails. let's help things out: - fact = (JspFactory)JettyBootstrapActivator.class.getClassLoader() - .loadClass(DEFAULT_JSP_FACTORY_IMPL_CLASS).newInstance(); + { // bug #299733 + // JspFactory does a simple + // Class.getForName("org.apache.jasper.runtime.JspFactoryImpl") + // however its bundles does not import the jasper package + // so it fails. let's help things out: + fact = (JspFactory) JettyBootstrapActivator.class.getClassLoader().loadClass(DEFAULT_JSP_FACTORY_IMPL_CLASS).newInstance(); JspFactory.setDefaultFactory(fact); } - + } catch (Exception e) { @@ -106,85 +110,90 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto e.printStackTrace(); } } - + /** - * The jasper TldScanner expects a URLClassloader to parse a jar for the /META-INF/*.tld it may contain. We place the bundles that we know contain such - * tag-libraries. Please note that it will work if and only if the bundle is a jar (!) Currently we just hardcode the bundle that contains the jstl - * implemenation. + * The jasper TldScanner expects a URLClassloader to parse a jar for the + * /META-INF/*.tld it may contain. We place the bundles that we know contain + * such tag-libraries. Please note that it will work if and only if the + * bundle is a jar (!) Currently we just hardcode the bundle that contains + * the jstl implemenation. * - * A workaround when the tld cannot be parsed with this method is to copy and paste it inside the WEB-INF of the webapplication where it is used. + * A workaround when the tld cannot be parsed with this method is to copy + * and paste it inside the WEB-INF of the webapplication where it is used. * - * Support only 2 types of packaging for the bundle: - the bundle is a jar (recommended for runtime.) - the bundle is a folder and contain jars in the root - * and/or in the lib folder (nice for PDE developement situations) Unsupported: the bundle is a jar that embeds more jars. + * Support only 2 types of packaging for the bundle: - the bundle is a jar + * (recommended for runtime.) - the bundle is a folder and contain jars in + * the root and/or in the lib folder (nice for PDE developement situations) + * Unsupported: the bundle is a jar that embeds more jars. * * @return array of URLs * @throws Exception */ public URL[] getJarsWithTlds(OSGiAppProvider provider, BundleFileLocatorHelper locatorHelper) throws Exception { - - HashSet> classesToAddToTheTldBundles = new HashSet>(); - //Look for the jstl bundle - //We assume the jstl's tlds are defined there. - //We assume that the jstl bundle is imported by this bundle - //So we can look for this class using this bundle's classloader: - Class jstlClass = WebappRegistrationCustomizerImpl.class.getClassLoader().loadClass(DEFAULT_JSTL_BUNDLE_CLASS); - - classesToAddToTheTldBundles.add(jstlClass); - + HashSet> classesToAddToTheTldBundles = new HashSet>(); + + // Look for the jstl bundle + // We assume the jstl's tlds are defined there. + // We assume that the jstl bundle is imported by this bundle + // So we can look for this class using this bundle's classloader: + Class jstlClass = WebappRegistrationCustomizerImpl.class.getClassLoader().loadClass(DEFAULT_JSTL_BUNDLE_CLASS); + + classesToAddToTheTldBundles.add(jstlClass); + ArrayList urls = new ArrayList(); - for (Class cl : classesToAddToTheTldBundles) - { - Bundle tldBundle = FrameworkUtil.getBundle(cl); - File tldBundleLocation = locatorHelper.getBundleInstallLocation(tldBundle); - if (tldBundleLocation != null && tldBundleLocation.isDirectory()) - { - // try to find the jar files inside this folder - for (File f : tldBundleLocation.listFiles()) - { - if (f.getName().endsWith(".jar") && f.isFile()) - { - urls.add(f.toURI().toURL()); - } - else if (f.isDirectory() && f.getName().equals("lib")) - { - for (File f2 : tldBundleLocation.listFiles()) - { - if (f2.getName().endsWith(".jar") && f2.isFile()) - { - urls.add(f2.toURI().toURL()); - } - } - } - } - - } - else if (tldBundleLocation != null) - { - urls.add(tldBundleLocation.toURI().toURL()); - } - } - return urls.toArray(new URL[urls.size()]); + for (Class cl : classesToAddToTheTldBundles) + { + Bundle tldBundle = FrameworkUtil.getBundle(cl); + File tldBundleLocation = locatorHelper.getBundleInstallLocation(tldBundle); + if (tldBundleLocation != null && tldBundleLocation.isDirectory()) + { + // try to find the jar files inside this folder + for (File f : tldBundleLocation.listFiles()) + { + if (f.getName().endsWith(".jar") && f.isFile()) + { + urls.add(f.toURI().toURL()); + } + else if (f.isDirectory() && f.getName().equals("lib")) + { + for (File f2 : tldBundleLocation.listFiles()) + { + if (f2.getName().endsWith(".jar") && f2.isFile()) + { + urls.add(f2.toURI().toURL()); + } + } + } + } + + } + else if (tldBundleLocation != null) + { + urls.add(tldBundleLocation.toURI().toURL()); + } + } + return urls.toArray(new URL[urls.size()]); } - - - + /** - * Jasper resolves the dtd when it parses a taglib descriptor. - * It uses this code to do that: ParserUtils.getClass().getResourceAsStream(resourcePath); where - * resourcePath is for example: /javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd Unfortunately, - * the dtd file is not in the exact same classloader as - * ParserUtils class and the dtds are packaged in 2 separate bundles. - * OSGi does not look in the dependencies' classloader when a resource is searched. + * Jasper resolves the dtd when it parses a taglib descriptor. It uses this + * code to do that: + * ParserUtils.getClass().getResourceAsStream(resourcePath); where + * resourcePath is for example: + * /javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd Unfortunately, the + * dtd file is not in the exact same classloader as ParserUtils class and + * the dtds are packaged in 2 separate bundles. OSGi does not look in the + * dependencies' classloader when a resource is searched. *

- * The workaround consists of setting the entity resolver. That is a patch - * added to the version of glassfish-jasper-jetty. IT is also present in the latest - * version of glassfish jasper. Could not use introspection to set new value - * on a static friendly field :( + * The workaround consists of setting the entity resolver. That is a patch + * added to the version of glassfish-jasper-jetty. IT is also present in the + * latest version of glassfish jasper. Could not use introspection to set + * new value on a static friendly field :( *

*/ - void fixupDtdResolution() + void fixupDtdResolution() { try { @@ -199,29 +208,23 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto } /** - * Instead of using the ParserUtil's classloader, we use a class that is indeed next to the resource for sure. + * Instead of using the ParserUtil's classloader, we use a class that is + * indeed next to the resource for sure. */ static class MyFixedupEntityResolver implements EntityResolver { /** * Same values than in ParserUtils... */ - static final String[] CACHED_DTD_PUBLIC_IDS = - { Constants.TAGLIB_DTD_PUBLIC_ID_11, Constants.TAGLIB_DTD_PUBLIC_ID_12, - Constants.WEBAPP_DTD_PUBLIC_ID_22, Constants.WEBAPP_DTD_PUBLIC_ID_23, }; + static final String[] CACHED_DTD_PUBLIC_IDS = { Constants.TAGLIB_DTD_PUBLIC_ID_11, Constants.TAGLIB_DTD_PUBLIC_ID_12, + Constants.WEBAPP_DTD_PUBLIC_ID_22, Constants.WEBAPP_DTD_PUBLIC_ID_23, }; - static final String[] CACHED_DTD_RESOURCE_PATHS = - { Constants.TAGLIB_DTD_RESOURCE_PATH_11, - Constants.TAGLIB_DTD_RESOURCE_PATH_12, - Constants.WEBAPP_DTD_RESOURCE_PATH_22, - Constants.WEBAPP_DTD_RESOURCE_PATH_23, }; + static final String[] CACHED_DTD_RESOURCE_PATHS = { Constants.TAGLIB_DTD_RESOURCE_PATH_11, Constants.TAGLIB_DTD_RESOURCE_PATH_12, + Constants.WEBAPP_DTD_RESOURCE_PATH_22, Constants.WEBAPP_DTD_RESOURCE_PATH_23, }; + + static final String[] CACHED_SCHEMA_RESOURCE_PATHS = { Constants.TAGLIB_SCHEMA_RESOURCE_PATH_20, Constants.TAGLIB_SCHEMA_RESOURCE_PATH_21, + Constants.WEBAPP_SCHEMA_RESOURCE_PATH_24, Constants.WEBAPP_SCHEMA_RESOURCE_PATH_25, }; - static final String[] CACHED_SCHEMA_RESOURCE_PATHS = { - Constants.TAGLIB_SCHEMA_RESOURCE_PATH_20, - Constants.TAGLIB_SCHEMA_RESOURCE_PATH_21, - Constants.WEBAPP_SCHEMA_RESOURCE_PATH_24, - Constants.WEBAPP_SCHEMA_RESOURCE_PATH_25, - }; public InputSource resolveEntity(String publicId, String systemId) throws SAXException { for (int i = 0; i < CACHED_DTD_PUBLIC_IDS.length; i++) @@ -242,10 +245,7 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto input = this.getClass().getResourceAsStream(resourcePath); } } - if (input == null) - { - throw new SAXException(Localizer.getMessage("jsp.error.internal.filenotfound",resourcePath)); - } + if (input == null) { throw new SAXException(Localizer.getMessage("jsp.error.internal.filenotfound", resourcePath)); } InputSource isrc = new InputSource(input); return isrc; } @@ -254,5 +254,5 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto return null; } } - + } diff --git a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/FragmentActivator.java b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/FragmentActivator.java index 6e34d4a5902..3f8f2874e65 100644 --- a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/FragmentActivator.java +++ b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/FragmentActivator.java @@ -19,15 +19,14 @@ import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; /** - * Pseudo fragment activator. - * Called by the main org.eclipse.jetty.osgi.boot bundle. - * Please note: this is not a real BundleActivator. Simply something called back by - * the host bundle. + * Pseudo fragment activator. Called by the main org.eclipse.jetty.osgi.boot + * bundle. Please note: this is not a real BundleActivator. Simply something + * called back by the host bundle. *

- * It must be placed in the org.eclipse.jetty.osgi.boot.jsp package: - * this is because org.eclipse.jetty.osgi.boot.jsp is the sympbolic-name - * of this fragment. From that name, the PackageadminTracker will call - * this class. IN a different package it won't be called. + * It must be placed in the org.eclipse.jetty.osgi.boot.jsp package: this is + * because org.eclipse.jetty.osgi.boot.jsp is the sympbolic-name of this + * fragment. From that name, the PackageadminTracker will call this class. IN a + * different package it won't be called. *

*/ public class FragmentActivator implements BundleActivator @@ -35,7 +34,8 @@ public class FragmentActivator implements BundleActivator /** * */ - public void start(BundleContext context) throws Exception { + public void start(BundleContext context) throws Exception + { System.setProperty("org.apache.jasper.compiler.disablejsr199", Boolean.TRUE.toString()); WebBundleDeployerHelper.JSP_REGISTRATION_HELPERS.add(new WebappRegistrationCustomizerImpl()); WebBundleDeployerHelper.JSP_REGISTRATION_HELPERS.add(new PluggableWebAppRegistrationCustomizerImpl()); @@ -44,7 +44,8 @@ public class FragmentActivator implements BundleActivator /** * */ - public void stop(BundleContext context) throws Exception { - + public void stop(BundleContext context) throws Exception + { + } } diff --git a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/TagLibOSGiConfiguration.java b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/TagLibOSGiConfiguration.java index 510261db4d0..ad31de22e7f 100644 --- a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/TagLibOSGiConfiguration.java +++ b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/TagLibOSGiConfiguration.java @@ -35,123 +35,120 @@ import org.osgi.util.tracker.ServiceTracker; * Replacement for {@link TagLibConfiguration} for the OSGi integration. *

*

- * In the case of a WAB, tlds can be located in OSGi bundles that are dependencies - * of the WAB. - * It is expected that each WAB lists the symbolic-names of the bundles that contain - * tld files. The list is defined as the value of the header 'Require-TldBundle' + * In the case of a WAB, tlds can be located in OSGi bundles that are + * dependencies of the WAB. It is expected that each WAB lists the + * symbolic-names of the bundles that contain tld files. The list is defined as + * the value of the header 'Require-TldBundle' *

*

- * Discussions about this are logged in https://bugs.eclipse.org/bugs/show_bug.cgi?id=306971 + * Discussions about this are logged in + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=306971 *

*/ public class TagLibOSGiConfiguration extends TagLibConfiguration { private static final Logger LOG = Log.getLogger(TagLibOSGiConfiguration.class); - private ServiceTracker packageAdminServiceTracker = null; - - /** - * Override the preConfigure; locates the bundles that contain - * tld files according to the value of the manifest header Require-TldBundle. - *

- * Set or add to the property TldProcessor.TLDResources the list of located jars - * so that the super class will scan those. - *

- */ + private ServiceTracker packageAdminServiceTracker = null; + + /** + * Override the preConfigure; locates the bundles that contain tld files + * according to the value of the manifest header Require-TldBundle. + *

+ * Set or add to the property TldProcessor.TLDResources the list of located + * jars so that the super class will scan those. + *

+ */ public void preConfigure(WebAppContext context) throws Exception { - String requireTldBundle = (String)context.getAttribute(OSGiWebappConstants.REQUIRE_TLD_BUNDLE); - if (requireTldBundle != null) - { - Collection resources = getRequireTldBundleAsJettyResources(context, requireTldBundle); - if (resources != null && !resources.isEmpty()) - { - Collection previouslySet = (Collection) - context.getAttribute(TagLibConfiguration.TLD_RESOURCES); - if (previouslySet != null) - { - resources.addAll(previouslySet); - } - context.setAttribute(TagLibConfiguration.TLD_RESOURCES, resources); - } - } - super.preConfigure(context); + String requireTldBundle = (String) context.getAttribute(OSGiWebappConstants.REQUIRE_TLD_BUNDLE); + if (requireTldBundle != null) + { + Collection resources = getRequireTldBundleAsJettyResources(context, requireTldBundle); + if (resources != null && !resources.isEmpty()) + { + Collection previouslySet = (Collection) context.getAttribute(TagLibConfiguration.TLD_RESOURCES); + if (previouslySet != null) + { + resources.addAll(previouslySet); + } + context.setAttribute(TagLibConfiguration.TLD_RESOURCES, resources); + } + } + super.preConfigure(context); } /** - * @param requireTldBundle The comma separated list of bundles' symbolic names - * that contain tld for this osgi webapp. + * @param requireTldBundle The comma separated list of bundles' symbolic + * names that contain tld for this osgi webapp. * @return The collection of jars or folders that match those bundles. */ - private Collection getRequireTldBundleAsJettyResources( - WebAppContext context, String requireTldBundle) + private Collection getRequireTldBundleAsJettyResources(WebAppContext context, String requireTldBundle) { - Bundle bundle = (Bundle) - context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE); - PackageAdmin packAdmin = getBundleAdmin(); - String[] symbNames = requireTldBundle.split(", "); - Collection tlds = new LinkedHashSet(); - for (String symbName : symbNames) - { - Bundle[] bs = packAdmin.getBundles(symbName, null); - if (bs == null || bs.length == 0) - { - throw new IllegalArgumentException("Unable to locate the bundle '" - + symbName + "' specified in the " - + OSGiWebappConstants.REQUIRE_TLD_BUNDLE - + " of the manifest of " - + bundle.getSymbolicName()); - } - //take the first one as it is the most recent version? - Enumeration en = bs[0].findEntries("META-INF", "*.tld", false); - boolean atLeastOneTldFound = false; - while (en.hasMoreElements()) - { - atLeastOneTldFound = true; - URL oriUrl = en.nextElement(); - URL url = DefaultFileLocatorHelper.getLocalURL(oriUrl); - Resource tldResource; - try - { - tldResource = Resource.newResource(url); - } - catch (IOException e) - { - throw new IllegalArgumentException("Unable to locate the " - + "tld resource in '" - + url.toString() - + "' in the bundle '" + bs[0].getSymbolicName() - + "' while registering the " - + OSGiWebappConstants.REQUIRE_TLD_BUNDLE - + " of the manifest of " - + bundle.getSymbolicName(), e); - } - tlds.add(tldResource); - } - if (!atLeastOneTldFound) - { - LOG.warn("No '/META-INF/*.tld' resources were found " - + " in the bundle '" + bs[0].getSymbolicName() - + "' while registering the " - + OSGiWebappConstants.REQUIRE_TLD_BUNDLE - + " of the manifest of " - + bundle.getSymbolicName()); - } - } - return tlds; + Bundle bundle = (Bundle) context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE); + PackageAdmin packAdmin = getBundleAdmin(); + String[] symbNames = requireTldBundle.split(", "); + Collection tlds = new LinkedHashSet(); + for (String symbName : symbNames) + { + Bundle[] bs = packAdmin.getBundles(symbName, null); + if (bs == null || bs.length == 0) + { + throw new IllegalArgumentException("Unable to locate the bundle '" + symbName + + "' specified in the " + + OSGiWebappConstants.REQUIRE_TLD_BUNDLE + + " of the manifest of " + + bundle.getSymbolicName()); + } + // take the first one as it is the most recent version? + Enumeration en = bs[0].findEntries("META-INF", "*.tld", false); + boolean atLeastOneTldFound = false; + while (en.hasMoreElements()) + { + atLeastOneTldFound = true; + URL oriUrl = en.nextElement(); + URL url = DefaultFileLocatorHelper.getLocalURL(oriUrl); + Resource tldResource; + try + { + tldResource = Resource.newResource(url); + } + catch (IOException e) + { + throw new IllegalArgumentException("Unable to locate the " + "tld resource in '" + + url.toString() + + "' in the bundle '" + + bs[0].getSymbolicName() + + "' while registering the " + + OSGiWebappConstants.REQUIRE_TLD_BUNDLE + + " of the manifest of " + + bundle.getSymbolicName(), e); + } + tlds.add(tldResource); + } + if (!atLeastOneTldFound) + { + LOG.warn("No '/META-INF/*.tld' resources were found " + " in the bundle '" + + bs[0].getSymbolicName() + + "' while registering the " + + OSGiWebappConstants.REQUIRE_TLD_BUNDLE + + " of the manifest of " + + bundle.getSymbolicName()); + } + } + return tlds; } - - private PackageAdmin getBundleAdmin() - { - if (packageAdminServiceTracker == null) - { - Bundle bootBundle = ((BundleReference)OSGiWebappConstants.class.getClassLoader()).getBundle(); - packageAdminServiceTracker = new ServiceTracker(bootBundle.getBundleContext(), - PackageAdmin.class.getName(), null); - packageAdminServiceTracker.open(); - } - return (PackageAdmin) packageAdminServiceTracker.getService(); - } - + + private PackageAdmin getBundleAdmin() + { + if (packageAdminServiceTracker == null) + { + Bundle bootBundle = ((BundleReference) OSGiWebappConstants.class.getClassLoader()).getBundle(); + packageAdminServiceTracker = new ServiceTracker(bootBundle.getBundleContext(), PackageAdmin.class.getName(), null); + packageAdminServiceTracker.open(); + } + return (PackageAdmin) packageAdminServiceTracker.getService(); + } + } diff --git a/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/jetty/osgi/boot/warurl/WarUrlStreamHandler.java b/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/jetty/osgi/boot/warurl/WarUrlStreamHandler.java index 654fb9b078f..0f861629a81 100644 --- a/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/jetty/osgi/boot/warurl/WarUrlStreamHandler.java +++ b/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/jetty/osgi/boot/warurl/WarUrlStreamHandler.java @@ -24,12 +24,13 @@ import java.util.jar.Manifest; import org.eclipse.jetty.osgi.boot.warurl.internal.WarBundleManifestGenerator; import org.eclipse.jetty.osgi.boot.warurl.internal.WarURLConnection; import org.eclipse.jetty.util.URIUtil; +import org.eclipse.jetty.util.resource.Resource; import org.osgi.service.url.AbstractURLStreamHandlerService; /** - * RFC-66: support for the "war" protocol - * We are reusing the parsing of the query string from jetty. - * If we wanted to not depend on jetty at all we could duplicate that method here + * RFC-66: support for the "war" protocol We are reusing the parsing of the + * query string from jetty. If we wanted to not depend on jetty at all we could + * duplicate that method here */ public class WarUrlStreamHandler extends AbstractURLStreamHandlerService { @@ -40,11 +41,11 @@ public class WarUrlStreamHandler extends AbstractURLStreamHandlerService @Override public URLConnection openConnection(URL url) throws IOException { - //remove the war scheme. + // remove the war scheme. URL actual = new URL(url.toString().substring("war:".length())); - - //let's do some basic tests: see if this is a folder or not. - //if it is a folder. we will try to support it. + + // let's do some basic tests: see if this is a folder or not. + // if it is a folder. we will try to support it. if (actual.getProtocol().equals("file")) { File file = new File(URIUtil.encodePath(actual.getPath())); @@ -52,34 +53,48 @@ public class WarUrlStreamHandler extends AbstractURLStreamHandlerService { if (file.isDirectory()) { - //TODO (not mandatory for rfc66 though) + // TODO (not mandatory for rfc66 though) } } } - - // if (actual.toString().startsWith("file:/") && ! actual.to) + + // if (actual.toString().startsWith("file:/") && ! actual.to) URLConnection ori = (URLConnection) actual.openConnection(); + ori.setDefaultUseCaches(Resource.getDefaultUseCaches()); JarURLConnection jarOri = null; - try { + try + { if (ori instanceof JarURLConnection) { - jarOri = (JarURLConnection)ori; + jarOri = (JarURLConnection) ori; } else { - jarOri = (JarURLConnection) new URL("jar:"+actual.toString() + "!/").openConnection(); + jarOri = (JarURLConnection) new URL("jar:" + actual.toString() + "!/").openConnection(); + jarOri.setDefaultUseCaches(Resource.getDefaultUseCaches()); } - Manifest mf = WarBundleManifestGenerator.createBundleManifest( - jarOri.getManifest(), url, jarOri.getJarFile()); - try { jarOri.getJarFile().close(); jarOri = null; } catch (Throwable t) {} - return new WarURLConnection(actual,mf); + Manifest mf = WarBundleManifestGenerator.createBundleManifest(jarOri.getManifest(), url, jarOri.getJarFile()); + try + { + jarOri.getJarFile().close(); + jarOri = null; + } + catch (Throwable t) + { + } + return new WarURLConnection(actual, mf); } finally { - if (jarOri != null) try { jarOri.getJarFile().close(); } catch (Throwable t) {} + if (jarOri != null) try + { + jarOri.getJarFile().close(); + } + catch (Throwable t) + { + } } - + } - } diff --git a/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/jetty/osgi/boot/warurl/internal/WarURLConnection.java b/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/jetty/osgi/boot/warurl/internal/WarURLConnection.java index 744a43c2ecc..c19a2fa6bfe 100644 --- a/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/jetty/osgi/boot/warurl/internal/WarURLConnection.java +++ b/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/jetty/osgi/boot/warurl/internal/WarURLConnection.java @@ -31,6 +31,7 @@ import java.util.jar.Manifest; import java.util.zip.ZipEntry; import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.resource.Resource; /** * Facade for a URLConnection that will read a jar and substitute its @@ -106,6 +107,7 @@ public class WarURLConnection extends URLConnection { super(url); _conn = url.openConnection(); + _conn.setDefaultUseCaches(Resource.getDefaultUseCaches()); _mf = mf; } @Override diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/JettyBootstrapActivator.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/JettyBootstrapActivator.java index e3c0f9040db..78d27131836 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/JettyBootstrapActivator.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/JettyBootstrapActivator.java @@ -66,15 +66,19 @@ public class JettyBootstrapActivator implements BundleActivator } private ServiceRegistration _registeredServer; + private Server _server; + private JettyContextHandlerServiceTracker _jettyContextHandlerTracker; + private PackageAdminServiceTracker _packageAdminServiceTracker; + private BundleTracker _webBundleTracker; + private BundleContext _bundleContext; - -// private ServiceRegistration _jettyServerFactoryService; + + // private ServiceRegistration _jettyServerFactoryService; private JettyServerServiceTracker _jettyServerServiceTracker; - /** * Setup a new jetty Server, registers it as a service. Setup the Service @@ -93,30 +97,31 @@ public class JettyBootstrapActivator implements BundleActivator // should activate. _packageAdminServiceTracker = new PackageAdminServiceTracker(context); - _jettyServerServiceTracker = new JettyServerServiceTracker(); - context.addServiceListener(_jettyServerServiceTracker,"(objectclass=" + Server.class.getName() + ")"); + _jettyServerServiceTracker = new JettyServerServiceTracker(); + context.addServiceListener(_jettyServerServiceTracker, "(objectclass=" + Server.class.getName() + ")"); + + // Register the Jetty Server Factory as a ManagedServiceFactory: + // Properties jettyServerMgdFactoryServiceProps = new Properties(); + // jettyServerMgdFactoryServiceProps.put("pid", + // OSGiWebappConstants.MANAGED_JETTY_SERVER_FACTORY_PID); + // _jettyServerFactoryService = context.registerService( + // ManagedServiceFactory.class.getName(), new + // JettyServersManagedFactory(), + // jettyServerMgdFactoryServiceProps); - //Register the Jetty Server Factory as a ManagedServiceFactory: -// Properties jettyServerMgdFactoryServiceProps = new Properties(); -// jettyServerMgdFactoryServiceProps.put("pid", OSGiWebappConstants.MANAGED_JETTY_SERVER_FACTORY_PID); -// _jettyServerFactoryService = context.registerService( -// ManagedServiceFactory.class.getName(), new JettyServersManagedFactory(), -// jettyServerMgdFactoryServiceProps); - _jettyContextHandlerTracker = new JettyContextHandlerServiceTracker(_jettyServerServiceTracker); // the tracker in charge of the actual deployment // and that will configure and start the jetty server. - context.addServiceListener(_jettyContextHandlerTracker,"(objectclass=" + ContextHandler.class.getName() + ")"); + context.addServiceListener(_jettyContextHandlerTracker, "(objectclass=" + ContextHandler.class.getName() + ")"); - //see if we shoult start a default jetty instance right now. + // see if we shoult start a default jetty instance right now. DefaultJettyAtJettyHomeHelper.startJettyAtJettyHome(context); - - // now ready to support the Extender pattern: - _webBundleTracker = new BundleTracker(context, - Bundle.ACTIVE | Bundle.STOPPING, new WebBundleTrackerCustomizer()); + + // now ready to support the Extender pattern: + _webBundleTracker = new BundleTracker(context, Bundle.ACTIVE | Bundle.STOPPING, new WebBundleTrackerCustomizer()); _webBundleTracker.open(); - + } /* @@ -129,12 +134,12 @@ public class JettyBootstrapActivator implements BundleActivator { try { - - if (_webBundleTracker != null) - { - _webBundleTracker.close(); - _webBundleTracker = null; - } + + if (_webBundleTracker != null) + { + _webBundleTracker.close(); + _webBundleTracker = null; + } if (_jettyContextHandlerTracker != null) { _jettyContextHandlerTracker.stop(); @@ -143,7 +148,7 @@ public class JettyBootstrapActivator implements BundleActivator } if (_jettyServerServiceTracker != null) { - _jettyServerServiceTracker.stop(); + _jettyServerServiceTracker.stop(); context.removeServiceListener(_jettyServerServiceTracker); _jettyServerServiceTracker = null; } @@ -165,31 +170,31 @@ public class JettyBootstrapActivator implements BundleActivator } finally { - _registeredServer = null; + _registeredServer = null; } } -// if (_jettyServerFactoryService != null) -// { -// try -// { -// _jettyServerFactoryService.unregister(); -// } -// catch (IllegalArgumentException ill) -// { -// // already unregistered. -// } -// finally -// { -// _jettyServerFactoryService = null; -// } -// } + // if (_jettyServerFactoryService != null) + // { + // try + // { + // _jettyServerFactoryService.unregister(); + // } + // catch (IllegalArgumentException ill) + // { + // // already unregistered. + // } + // finally + // { + // _jettyServerFactoryService = null; + // } + // } } finally { if (_server != null) { - _server.stop(); + _server.stop(); } INSTANCE = null; } @@ -200,27 +205,25 @@ public class JettyBootstrapActivator implements BundleActivator * registers it as an OSGi service. The tracker * {@link JettyContextHandlerServiceTracker} will do the actual deployment. * - * @param contributor - * The bundle - * @param webappFolderPath - * The path to the root of the webapp. Must be a path relative to - * bundle; either an absolute path. - * @param contextPath - * The context path. Must start with "/" + * @param contributor The bundle + * @param webappFolderPath The path to the root of the webapp. Must be a + * path relative to bundle; either an absolute path. + * @param contextPath The context path. Must start with "/" * @throws Exception */ public static void registerWebapplication(Bundle contributor, String webappFolderPath, String contextPath) throws Exception { - checkBundleActivated(); - WebAppContext contextHandler = new WebAppContext(); + checkBundleActivated(); + WebAppContext contextHandler = new WebAppContext(); Dictionary dic = new Hashtable(); - dic.put(OSGiWebappConstants.SERVICE_PROP_WAR,webappFolderPath); - dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH,contextPath); - String requireTldBundle = (String)contributor.getHeaders().get(OSGiWebappConstants.REQUIRE_TLD_BUNDLE); - if (requireTldBundle != null) { - dic.put(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE, requireTldBundle); + dic.put(OSGiWebappConstants.SERVICE_PROP_WAR, webappFolderPath); + dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH, contextPath); + String requireTldBundle = (String) contributor.getHeaders().get(OSGiWebappConstants.REQUIRE_TLD_BUNDLE); + if (requireTldBundle != null) + { + dic.put(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE, requireTldBundle); } - contributor.getBundleContext().registerService(ContextHandler.class.getName(),contextHandler,dic); + contributor.getBundleContext().registerService(ContextHandler.class.getName(), contextHandler, dic); } /** @@ -228,24 +231,20 @@ public class JettyBootstrapActivator implements BundleActivator * registers it as an OSGi service. The tracker * {@link JettyContextHandlerServiceTracker} will do the actual deployment. * - * @param contributor - * The bundle - * @param webappFolderPath - * The path to the root of the webapp. Must be a path relative to - * bundle; either an absolute path. - * @param contextPath - * The context path. Must start with "/" - * @param dic - * TODO: parameter description + * @param contributor The bundle + * @param webappFolderPath The path to the root of the webapp. Must be a + * path relative to bundle; either an absolute path. + * @param contextPath The context path. Must start with "/" + * @param dic TODO: parameter description * @throws Exception */ public static void registerWebapplication(Bundle contributor, String webappFolderPath, String contextPath, Dictionary dic) throws Exception { - checkBundleActivated(); + checkBundleActivated(); WebAppContext contextHandler = new WebAppContext(); - dic.put(OSGiWebappConstants.SERVICE_PROP_WAR,webappFolderPath); - dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH,contextPath); - contributor.getBundleContext().registerService(ContextHandler.class.getName(),contextHandler,dic); + dic.put(OSGiWebappConstants.SERVICE_PROP_WAR, webappFolderPath); + dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH, contextPath); + contributor.getBundleContext().registerService(ContextHandler.class.getName(), contextHandler, dic); } /** @@ -253,16 +252,14 @@ public class JettyBootstrapActivator implements BundleActivator * registers it as an OSGi service. The tracker * {@link JettyContextHandlerServiceTracker} will do the actual deployment. * - * @param contributor - * The bundle that registers a new context - * @param contextFilePath - * The path to the file inside the bundle that defines the - * context. + * @param contributor The bundle that registers a new context + * @param contextFilePath The path to the file inside the bundle that + * defines the context. * @throws Exception */ public static void registerContext(Bundle contributor, String contextFilePath) throws Exception { - registerContext(contributor,contextFilePath,new Hashtable()); + registerContext(contributor, contextFilePath, new Hashtable()); } /** @@ -270,33 +267,30 @@ public class JettyBootstrapActivator implements BundleActivator * registers it as an OSGi service. The tracker * {@link JettyContextHandlerServiceTracker} will do the actual deployment. * - * @param contributor - * The bundle that registers a new context - * @param contextFilePath - * The path to the file inside the bundle that defines the - * context. - * @param dic - * TODO: parameter description + * @param contributor The bundle that registers a new context + * @param contextFilePath The path to the file inside the bundle that + * defines the context. + * @param dic TODO: parameter description * @throws Exception */ public static void registerContext(Bundle contributor, String contextFilePath, Dictionary dic) throws Exception { - checkBundleActivated(); + checkBundleActivated(); ContextHandler contextHandler = new ContextHandler(); - dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH,contextFilePath); - dic.put(IWebBundleDeployerHelper.INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE,Boolean.TRUE.toString()); - contributor.getBundleContext().registerService(ContextHandler.class.getName(),contextHandler,dic); + dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH, contextFilePath); + dic.put(IWebBundleDeployerHelper.INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE, Boolean.TRUE.toString()); + contributor.getBundleContext().registerService(ContextHandler.class.getName(), contextHandler, dic); } public static void unregister(String contextPath) { // todo } - + /** * Since org.eclipse.jetty.osgi.boot does not have a lazy activation policy - * when one fo the static methods to register a webapp is called we should make sure that - * the bundle is started. + * when one fo the static methods to register a webapp is called we should + * make sure that the bundle is started. */ private static void checkBundleActivated() { @@ -313,7 +307,7 @@ public class JettyBootstrapActivator implements BundleActivator } } } - + /** * @return The bundle context for this bundle. */ @@ -322,6 +316,5 @@ public class JettyBootstrapActivator implements BundleActivator checkBundleActivated(); return INSTANCE._bundleContext; } - } diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/JettyContextHandlerServiceTracker.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/JettyContextHandlerServiceTracker.java index 021c292f862..26120c1850f 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/JettyContextHandlerServiceTracker.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/JettyContextHandlerServiceTracker.java @@ -53,14 +53,15 @@ import org.osgi.framework.ServiceReference; public class JettyContextHandlerServiceTracker implements ServiceListener { - /** New style: ability to manage multiple jetty instances */ - private final IManagedJettyServerRegistry _registry; + /** New style: ability to manage multiple jetty instances */ + private final IManagedJettyServerRegistry _registry; /** The context-handler to deactivate indexed by context handler */ private Map _indexByServiceReference = new HashMap(); /** - * The index is the bundle-symbolic-name/path/to/context/file when there is such thing + * The index is the bundle-symbolic-name/path/to/context/file when there is + * such thing */ private Map _indexByContextFile = new HashMap(); @@ -72,7 +73,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener */ public JettyContextHandlerServiceTracker(IManagedJettyServerRegistry registry) throws Exception { - _registry = registry; + _registry = registry; } public void stop() throws Exception @@ -85,19 +86,16 @@ public class JettyContextHandlerServiceTracker implements ServiceListener // nothing to stop in the WebappRegistrationHelper } - + /** - * @param contextHome Parent folder where the context files can override the context files - * defined in the web bundles: equivalent to the contexts folder in a traditional - * jetty installation. - * when null, just do nothing. + * @param contextHome Parent folder where the context files can override the + * context files defined in the web bundles: equivalent to the + * contexts folder in a traditional jetty installation. when + * null, just do nothing. */ protected void setupContextHomeScanner(File contextHome) throws IOException { - if (contextHome == null) - { - return; - } + if (contextHome == null) { return; } final String osgiContextHomeFolderCanonicalPath = contextHome.getCanonicalPath(); _scanner = new Scanner(); _scanner.setRecursive(true); @@ -132,8 +130,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener /** * Receives notification that a service has had a lifecycle change. * - * @param ev - * The ServiceEvent object. + * @param ev The ServiceEvent object. */ public void serviceChanged(ServiceEvent ev) { @@ -148,7 +145,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener { try { - getWebBundleDeployerHelp(sr).unregister(ctxtHandler); + getWebBundleDeployerHelp(sr).unregister(ctxtHandler); } catch (Exception e) { @@ -170,30 +167,32 @@ public class JettyContextHandlerServiceTracker implements ServiceListener { Bundle contributor = sr.getBundle(); BundleContext context = FrameworkUtil.getBundle(JettyBootstrapActivator.class).getBundleContext(); - ContextHandler contextHandler = (ContextHandler)context.getService(sr); + ContextHandler contextHandler = (ContextHandler) context.getService(sr); if (contextHandler.getServer() != null) { // is configured elsewhere. return; } - String contextFilePath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH); + String contextFilePath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH); if (contextHandler instanceof WebAppContext && contextFilePath == null) - //it could be a web-application that will in fact be configured via a context file. - //that case is identified by the fact that the contextFilePath is not null - //in that case we must use the register context methods. + // it could be a web-application that will in fact be configured + // via a context file. + // that case is identified by the fact that the contextFilePath + // is not null + // in that case we must use the register context methods. { - WebAppContext webapp = (WebAppContext)contextHandler; - String contextPath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH); + WebAppContext webapp = (WebAppContext) contextHandler; + String contextPath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH); if (contextPath == null) { contextPath = webapp.getContextPath(); } - String webXmlPath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_WEB_XML_PATH); + String webXmlPath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_WEB_XML_PATH); if (webXmlPath == null) { webXmlPath = webapp.getDescriptor(); } - String defaultWebXmlPath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_DEFAULT_WEB_XML_PATH); + String defaultWebXmlPath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_DEFAULT_WEB_XML_PATH); if (defaultWebXmlPath == null) { String jettyHome = System.getProperty(DefaultJettyAtJettyHomeHelper.SYS_PROP_JETTY_HOME); @@ -202,7 +201,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener File etc = new File(jettyHome, "etc"); if (etc.exists() && etc.isDirectory()) { - File webDefault = new File (etc, "webdefault.xml"); + File webDefault = new File(etc, "webdefault.xml"); if (webDefault.exists()) defaultWebXmlPath = webDefault.getAbsolutePath(); else @@ -212,27 +211,28 @@ public class JettyContextHandlerServiceTracker implements ServiceListener defaultWebXmlPath = webapp.getDefaultsDescriptor(); } } - String war = (String)sr.getProperty("war"); + String war = (String) sr.getProperty("war"); try { - IWebBundleDeployerHelper deployerHelper = getWebBundleDeployerHelp(sr); - if (deployerHelper == null) - { - - } - else - { - WebAppContext handler = deployerHelper - .registerWebapplication(contributor,war,contextPath, - (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_EXTRA_CLASSPATH), - (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE), - (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE), - webXmlPath,defaultWebXmlPath,webapp); + IWebBundleDeployerHelper deployerHelper = getWebBundleDeployerHelp(sr); + if (deployerHelper == null) + { + + } + else + { + WebAppContext handler = deployerHelper.registerWebapplication(contributor, + war, + contextPath, + (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_EXTRA_CLASSPATH), + (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE), + (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE), + webXmlPath, defaultWebXmlPath, webapp); if (handler != null) { - registerInIndex(handler,sr); + registerInIndex(handler, sr); } - } + } } catch (Throwable e) { @@ -242,34 +242,31 @@ public class JettyContextHandlerServiceTracker implements ServiceListener else { // consider this just an empty skeleton: - if (contextFilePath == null) - { - throw new IllegalArgumentException("the property contextFilePath is required"); - } + if (contextFilePath == null) { throw new IllegalArgumentException("the property contextFilePath is required"); } try { - IWebBundleDeployerHelper deployerHelper = getWebBundleDeployerHelp(sr); - if (deployerHelper == null) - { - //more warnings? - } - else - { - if (Boolean.TRUE.toString().equals(sr.getProperty( - IWebBundleDeployerHelper.INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE))) - { - contextHandler = null; - } - ContextHandler handler = deployerHelper.registerContext(contributor,contextFilePath, - (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_EXTRA_CLASSPATH), - (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE), - (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE), - contextHandler); - if (handler != null) - { - registerInIndex(handler,sr); - } - } + IWebBundleDeployerHelper deployerHelper = getWebBundleDeployerHelp(sr); + if (deployerHelper == null) + { + // more warnings? + } + else + { + if (Boolean.TRUE.toString().equals(sr.getProperty(IWebBundleDeployerHelper.INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE))) + { + contextHandler = null; + } + ContextHandler handler = deployerHelper.registerContext(contributor, + contextFilePath, + (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_EXTRA_CLASSPATH), + (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE), + (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE), + contextHandler); + if (handler != null) + { + registerInIndex(handler, sr); + } + } } catch (Throwable e) { @@ -278,17 +275,17 @@ public class JettyContextHandlerServiceTracker implements ServiceListener } } } - break; + break; } } private void registerInIndex(ContextHandler handler, ServiceReference sr) { - _indexByServiceReference.put(sr,handler); + _indexByServiceReference.put(sr, handler); String key = getSymbolicNameAndContextFileKey(sr); if (key != null) { - _indexByContextFile.put(key,sr); + _indexByContextFile.put(key, sr); } } @@ -320,11 +317,8 @@ public class JettyContextHandlerServiceTracker implements ServiceListener */ private String getSymbolicNameAndContextFileKey(ServiceReference sr) { - String contextFilePath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH); - if (contextFilePath != null) - { - return sr.getBundle().getSymbolicName() + "/" + contextFilePath; - } + String contextFilePath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH); + if (contextFilePath != null) { return sr.getBundle().getSymbolicName() + "/" + contextFilePath; } return null; } @@ -336,17 +330,14 @@ public class JettyContextHandlerServiceTracker implements ServiceListener public void reloadJettyContextHandler(String canonicalNameOfFileChanged, String osgiContextHomeFolderCanonicalPath) { String key = getNormalizedRelativePath(canonicalNameOfFileChanged, osgiContextHomeFolderCanonicalPath); - if (key == null) - { - return; - } + if (key == null) { return; } ServiceReference sr = _indexByContextFile.get(key); if (sr == null) { // nothing to do? return; } - serviceChanged(new ServiceEvent(ServiceEvent.MODIFIED,sr)); + serviceChanged(new ServiceEvent(ServiceEvent.MODIFIED, sr)); } /** @@ -362,36 +353,31 @@ public class JettyContextHandlerServiceTracker implements ServiceListener // warning? return null; } - return canFilename.substring(osgiContextHomeFolderCanonicalPath.length()).replace('\\','/'); + return canFilename.substring(osgiContextHomeFolderCanonicalPath.length()).replace('\\', '/'); } - + /** * @return The server on which this webapp is meant to be deployed */ private ServerInstanceWrapper getServerInstanceWrapper(String managedServerName) { - if (_registry == null) - { - return null; - } - if (managedServerName == null) - { - managedServerName = OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME; - } - ServerInstanceWrapper wrapper = _registry.getServerInstanceWrapper(managedServerName); - //System.err.println("Returning " + managedServerName + " = " + wrapper); - return wrapper; + if (_registry == null) { return null; } + if (managedServerName == null) + { + managedServerName = OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME; + } + ServerInstanceWrapper wrapper = _registry.getServerInstanceWrapper(managedServerName); + // System.err.println("Returning " + managedServerName + " = " + + // wrapper); + return wrapper; } - + private IWebBundleDeployerHelper getWebBundleDeployerHelp(ServiceReference sr) { - if (_registry == null) - { - return null; - } - String managedServerName = (String)sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME); - ServerInstanceWrapper wrapper = getServerInstanceWrapper(managedServerName); - return wrapper != null ? wrapper.getWebBundleDeployerHelp() : null; + if (_registry == null) { return null; } + String managedServerName = (String) sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME); + ServerInstanceWrapper wrapper = getServerInstanceWrapper(managedServerName); + return wrapper != null ? wrapper.getWebBundleDeployerHelp() : null; } - + } diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/OSGiWebappClassLoader.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/OSGiWebappClassLoader.java index 4a7dcf96e90..c662d2cae02 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/OSGiWebappClassLoader.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/OSGiWebappClassLoader.java @@ -247,7 +247,7 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe catch (IOException e) { // nevermind. just trying our best - e.printStackTrace(); + __logger.ignore(e); } return true; } @@ -279,7 +279,7 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe catch (Throwable t) { // humf that will hurt if it does not work. - t.printStackTrace(); + __logger.warn("Unable to set webappcontext", t); } } } diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleDeployerHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleDeployerHelper.java index b30d9a81d02..97d72cb2c38 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleDeployerHelper.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleDeployerHelper.java @@ -78,13 +78,14 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper private static Logger __logger = Log.getLogger(WebBundleDeployerHelper.class.getName()); private static boolean INITIALIZED = false; - + /** * By default set to: {@link DefaultBundleClassLoaderHelper}. It supports * equinox and apache-felix fragment bundles that are specific to an OSGi * implementation should set a different implementation. */ public static BundleClassLoaderHelper BUNDLE_CLASS_LOADER_HELPER = null; + /** * By default set to: {@link DefaultBundleClassLoaderHelper}. It supports * equinox and apache-felix fragment bundles that are specific to an OSGi @@ -97,8 +98,9 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper * equinox and apache-felix fragment bundles that are specific to an OSGi * implementation should set a different implementation. *

- * Several of those objects can be added here: For example we could have an optional fragment that setups - * a specific implementation of JSF for the whole of jetty-osgi. + * Several of those objects can be added here: For example we could have an + * optional fragment that setups a specific implementation of JSF for the + * whole of jetty-osgi. *

*/ public static Collection JSP_REGISTRATION_HELPERS = new ArrayList(); @@ -127,7 +129,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper // setup the custom BundleClassLoaderHelper try { - BUNDLE_CLASS_LOADER_HELPER = (BundleClassLoaderHelper)Class.forName(BundleClassLoaderHelper.CLASS_NAME).newInstance(); + BUNDLE_CLASS_LOADER_HELPER = (BundleClassLoaderHelper) Class.forName(BundleClassLoaderHelper.CLASS_NAME).newInstance(); } catch (Throwable t) { @@ -137,7 +139,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper // setup the custom FileLocatorHelper try { - BUNDLE_FILE_LOCATOR_HELPER = (BundleFileLocatorHelper)Class.forName(BundleFileLocatorHelper.CLASS_NAME).newInstance(); + BUNDLE_FILE_LOCATOR_HELPER = (BundleFileLocatorHelper) Class.forName(BundleFileLocatorHelper.CLASS_NAME).newInstance(); } catch (Throwable t) { @@ -150,34 +152,28 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper /** * Deploy a new web application on the jetty server. * - * @param bundle - * The bundle - * @param webappFolderPath - * The path to the root of the webapp. Must be a path relative to - * bundle; either an absolute path. - * @param contextPath - * The context path. Must start with "/" + * @param bundle The bundle + * @param webappFolderPath The path to the root of the webapp. Must be a + * path relative to bundle; either an absolute path. + * @param contextPath The context path. Must start with "/" * @param extraClasspath * @param overrideBundleInstallLocation * @param requireTldBundle The list of bundles's symbolic names that contain - * tld files that are required by this WAB. + * tld files that are required by this WAB. * @param webXmlPath - * @param defaultWebXmlPath - * TODO: parameter description + * @param defaultWebXmlPath TODO: parameter description * @return The contexthandler created and started * @throws Exception */ - public WebAppContext registerWebapplication(Bundle bundle, - String webappFolderPath, String contextPath, String extraClasspath, - String overrideBundleInstallLocation, - String requireTldBundle, String webXmlPath, - String defaultWebXmlPath, WebAppContext webAppContext) throws Exception + public WebAppContext registerWebapplication(Bundle bundle, String webappFolderPath, String contextPath, String extraClasspath, + String overrideBundleInstallLocation, String requireTldBundle, String webXmlPath, String defaultWebXmlPath, + WebAppContext webAppContext) throws Exception { - File bundleInstall = overrideBundleInstallLocation == null?BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(bundle):new File( - overrideBundleInstallLocation); + File bundleInstall = overrideBundleInstallLocation == null ? BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(bundle) : new File( + overrideBundleInstallLocation); File webapp = null; URL baseWebappInstallURL = null; - + if (webappFolderPath != null && webappFolderPath.length() != 0 && !webappFolderPath.equals(".")) { if (webappFolderPath.startsWith("/") || webappFolderPath.startsWith("file:")) @@ -186,7 +182,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper } else if (bundleInstall != null && bundleInstall.isDirectory()) { - webapp = new File(bundleInstall,webappFolderPath); + webapp = new File(bundleInstall, webappFolderPath); } else if (bundleInstall != null) { @@ -201,37 +197,43 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper { webapp = bundleInstall; } - if (baseWebappInstallURL == null && (webapp == null || !webapp.exists())) - { - throw new IllegalArgumentException("Unable to locate " + webappFolderPath + " inside " - + (bundleInstall != null?bundleInstall.getAbsolutePath():"unlocated bundle '" + bundle.getSymbolicName() + "'")); - } + if (baseWebappInstallURL == null && (webapp == null || !webapp.exists())) { throw new IllegalArgumentException( + "Unable to locate " + webappFolderPath + + " inside " + + (bundleInstall != null ? bundleInstall.getAbsolutePath() : "unlocated bundle '" + bundle.getSymbolicName() + + "'")); } if (baseWebappInstallURL == null && webapp != null) { baseWebappInstallURL = webapp.toURI().toURL(); } - return registerWebapplication(bundle,webappFolderPath,baseWebappInstallURL,contextPath, - extraClasspath,bundleInstall,requireTldBundle,webXmlPath,defaultWebXmlPath,webAppContext); + return registerWebapplication(bundle, webappFolderPath, baseWebappInstallURL, contextPath, extraClasspath, bundleInstall, requireTldBundle, webXmlPath, + defaultWebXmlPath, webAppContext); } - - /* (non-Javadoc) - * @see org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#registerWebapplication(org.osgi.framework.Bundle, java.lang.String, java.io.File, java.lang.String, java.lang.String, java.io.File, java.lang.String, java.lang.String) + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper# + * registerWebapplication(org.osgi.framework.Bundle, java.lang.String, + * java.io.File, java.lang.String, java.lang.String, java.io.File, + * java.lang.String, java.lang.String) */ - private WebAppContext registerWebapplication(Bundle contributor, String pathInBundleToWebApp, - URL baseWebappInstallURL, String contextPath, String extraClasspath, File bundleInstall, - String requireTldBundle, String webXmlPath, String defaultWebXmlPath, WebAppContext context) - throws Exception + private WebAppContext registerWebapplication(Bundle contributor, String pathInBundleToWebApp, URL baseWebappInstallURL, String contextPath, + String extraClasspath, File bundleInstall, String requireTldBundle, String webXmlPath, + String defaultWebXmlPath, WebAppContext context) throws Exception { ClassLoader contextCl = Thread.currentThread().getContextClassLoader(); String[] oldServerClasses = null; - + try { // make sure we provide access to all the jetty bundles by going // through this bundle. OSGiWebappClassLoader composite = createWebappClassLoader(contributor); - // configure with access to all jetty classes and also all the classes + // configure with access to all jetty classes and also all the + // classes // that the contributor gives access to. Thread.currentThread().setContextClassLoader(composite); @@ -248,7 +250,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper } else { - webXml = new File(bundleInstall,webXmlPath); + webXml = new File(bundleInstall, webXmlPath); } if (webXml.exists()) { @@ -258,7 +260,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper if (defaultWebXmlPath == null || defaultWebXmlPath.length() == 0) { - //use the one defined by the OSGiAppProvider. + // use the one defined by the OSGiAppProvider. defaultWebXmlPath = _wrapper.getOSGiAppProvider().getDefaultsDescriptor(); } if (defaultWebXmlPath != null && defaultWebXmlPath.length() != 0) @@ -270,20 +272,19 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper } else { - defaultWebXml = new File(bundleInstall,defaultWebXmlPath); + defaultWebXml = new File(bundleInstall, defaultWebXmlPath); } if (defaultWebXml.exists()) { context.setDefaultsDescriptor(defaultWebXml.getAbsolutePath()); } } - - //other parameters that might be defines on the OSGiAppProvider: + + // other parameters that might be defines on the OSGiAppProvider: context.setParentLoaderPriority(_wrapper.getOSGiAppProvider().isParentLoaderPriority()); - configureWebappClassLoader(contributor,context,composite, requireTldBundle); - configureWebAppContext(context,contributor,requireTldBundle); - + configureWebappClassLoader(contributor, context, composite, requireTldBundle); + configureWebAppContext(context, contributor, requireTldBundle); // @see // org.eclipse.jetty.webapp.JettyWebXmlConfiguration#configure(WebAppContext) @@ -292,36 +293,36 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper // through the webapp classloader. oldServerClasses = context.getServerClasses(); context.setServerClasses(null); - - _wrapper.getOSGiAppProvider().addContext(contributor,pathInBundleToWebApp,context); - - //support for patch resources. ideally this should be done inside a configurator. - List patchResources = - (List)context.getAttribute(WebInfConfiguration.RESOURCE_URLS+".patch"); + + _wrapper.getOSGiAppProvider().addContext(contributor, pathInBundleToWebApp, context); + + // support for patch resources. ideally this should be done inside a + // configurator. + List patchResources = (List) context.getAttribute(WebInfConfiguration.RESOURCE_URLS + ".patch"); if (patchResources != null) { - LinkedList resourcesPath = new LinkedList(); - //place the patch resources at the beginning of the lookup path. - resourcesPath.addAll(patchResources); - //then place the ones from the host web bundle. - Resource hostResources = context.getBaseResource(); - if (hostResources instanceof ResourceCollection) - { - for (Resource re : ((ResourceCollection)hostResources).getResources()) - { - resourcesPath.add(re); - } - } - else - { - resourcesPath.add(hostResources); - } - - ResourceCollection rc = new ResourceCollection(resourcesPath.toArray( - new Resource[resourcesPath.size()])); - context.setBaseResource(rc); + LinkedList resourcesPath = new LinkedList(); + // place the patch resources at the beginning of the lookup + // path. + resourcesPath.addAll(patchResources); + // then place the ones from the host web bundle. + Resource hostResources = context.getBaseResource(); + if (hostResources instanceof ResourceCollection) + { + for (Resource re : ((ResourceCollection) hostResources).getResources()) + { + resourcesPath.add(re); + } + } + else + { + resourcesPath.add(hostResources); + } + + ResourceCollection rc = new ResourceCollection(resourcesPath.toArray(new Resource[resourcesPath.size()])); + context.setBaseResource(rc); } - + return context; } finally @@ -335,38 +336,41 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper } - /* (non-Javadoc) - * @see org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#unregister(org.eclipse.jetty.server.handler.ContextHandler) + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper# + * unregister(org.eclipse.jetty.server.handler.ContextHandler) */ public void unregister(ContextHandler contextHandler) throws Exception { _wrapper.getOSGiAppProvider().removeContext(contextHandler); } - /* (non-Javadoc) - * @see org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#registerContext(org.osgi.framework.Bundle, java.lang.String, java.lang.String, java.lang.String) + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper# + * registerContext(org.osgi.framework.Bundle, java.lang.String, + * java.lang.String, java.lang.String) */ - public ContextHandler registerContext(Bundle contributor, String contextFileRelativePath, String extraClasspath, - String overrideBundleInstallLocation, String requireTldBundle, ContextHandler handler) - throws Exception + public ContextHandler registerContext(Bundle contributor, String contextFileRelativePath, String extraClasspath, String overrideBundleInstallLocation, + String requireTldBundle, ContextHandler handler) throws Exception { File contextsHome = _wrapper.getOSGiAppProvider().getContextXmlDirAsFile(); if (contextsHome != null) { - File prodContextFile = new File(contextsHome,contributor.getSymbolicName() + "/" + contextFileRelativePath); - if (prodContextFile.exists()) - { - return registerContext(contributor,contextFileRelativePath,prodContextFile,extraClasspath, - overrideBundleInstallLocation,requireTldBundle,handler); - } + File prodContextFile = new File(contextsHome, contributor.getSymbolicName() + "/" + contextFileRelativePath); + if (prodContextFile.exists()) { return registerContext(contributor, contextFileRelativePath, prodContextFile, extraClasspath, + overrideBundleInstallLocation, requireTldBundle, handler); } } - File rootFolder = overrideBundleInstallLocation != null - ? Resource.newResource(overrideBundleInstallLocation).getFile() - : BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(contributor); - File contextFile = rootFolder != null?new File(rootFolder,contextFileRelativePath):null; + File rootFolder = overrideBundleInstallLocation != null ? Resource.newResource(overrideBundleInstallLocation).getFile() : BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(contributor); + File contextFile = rootFolder != null ? new File(rootFolder, contextFileRelativePath) : null; if (contextFile != null && contextFile.exists()) { - return registerContext(contributor,contextFileRelativePath,contextFile,extraClasspath,overrideBundleInstallLocation,requireTldBundle,handler); + return registerContext(contributor, contextFileRelativePath, contextFile, extraClasspath, overrideBundleInstallLocation, requireTldBundle, handler); } else { @@ -378,15 +382,19 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper { contextFileRelativePath = "/" + contextFileRelativePath; } - + URL contextURL = contributor.getEntry(contextFileRelativePath); if (contextURL != null) { - Resource r = Resource.newResource(contextURL); - return registerContext(contributor,contextFileRelativePath,r.getInputStream(),extraClasspath,overrideBundleInstallLocation,requireTldBundle,handler); + Resource r = Resource.newResource(contextURL); + return registerContext(contributor, contextFileRelativePath, r.getInputStream(), extraClasspath, overrideBundleInstallLocation, + requireTldBundle, handler); } - throw new IllegalArgumentException("Could not find the context " + "file " + contextFileRelativePath + " for the bundle " - + contributor.getSymbolicName() + (overrideBundleInstallLocation != null?" using the install location " + overrideBundleInstallLocation:"")); + throw new IllegalArgumentException("Could not find the context " + "file " + + contextFileRelativePath + + " for the bundle " + + contributor.getSymbolicName() + + (overrideBundleInstallLocation != null ? " using the install location " + overrideBundleInstallLocation : "")); } } @@ -400,16 +408,14 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper * @param classInBundle * @throws Exception */ - private ContextHandler registerContext(Bundle contributor, String pathInBundle, File contextFile, - String extraClasspath, String overrideBundleInstallLocation, - String requireTldBundle, ContextHandler handler) throws Exception + private ContextHandler registerContext(Bundle contributor, String pathInBundle, File contextFile, String extraClasspath, + String overrideBundleInstallLocation, String requireTldBundle, ContextHandler handler) throws Exception { InputStream contextFileInputStream = null; try { contextFileInputStream = new BufferedInputStream(new FileInputStream(contextFile)); - return registerContext(contributor, pathInBundle, contextFileInputStream, - extraClasspath,overrideBundleInstallLocation,requireTldBundle,handler); + return registerContext(contributor, pathInBundle, contextFileInputStream, extraClasspath, overrideBundleInstallLocation, requireTldBundle, handler); } finally { @@ -424,11 +430,8 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper * happen. * @throws Exception */ - private ContextHandler registerContext(Bundle contributor, - String pathInsideBundle, InputStream contextFileInputStream, - String extraClasspath, String overrideBundleInstallLocation, - String requireTldBundle, ContextHandler handler) - throws Exception + private ContextHandler registerContext(Bundle contributor, String pathInsideBundle, InputStream contextFileInputStream, String extraClasspath, + String overrideBundleInstallLocation, String requireTldBundle, ContextHandler handler) throws Exception { ClassLoader contextCl = Thread.currentThread().getContextClassLoader(); String[] oldServerClasses = null; @@ -442,24 +445,23 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper // classes // that the contributor gives access to. Thread.currentThread().setContextClassLoader(composite); - ContextHandler context = createContextHandler(handler, contributor, - contextFileInputStream,extraClasspath, - overrideBundleInstallLocation,requireTldBundle); - if (context == null) - { + ContextHandler context = createContextHandler(handler, contributor, contextFileInputStream, extraClasspath, overrideBundleInstallLocation, + requireTldBundle); + if (context == null) + { return null;// did not happen } // ok now register this webapp. we checked when we started jetty // that there // was at least one such handler for webapps. - //the actual registration must happen via the new Deployment API. -// _ctxtHandler.addHandler(context); + // the actual registration must happen via the new Deployment API. + // _ctxtHandler.addHandler(context); - configureWebappClassLoader(contributor,context,composite, requireTldBundle); + configureWebappClassLoader(contributor, context, composite, requireTldBundle); if (context instanceof WebAppContext) { - webAppContext = (WebAppContext)context; + webAppContext = (WebAppContext) context; // @see // org.eclipse.jetty.webapp.JettyWebXmlConfiguration#configure(WebAppContext) oldServerClasses = webAppContext.getServerClasses(); @@ -485,53 +487,58 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper * @see {WebAppDeployer#scan} around the comment * // configure it */ - protected void configureWebAppContext(ContextHandler wah, Bundle contributor, - String requireTldBundle) throws IOException + protected void configureWebAppContext(ContextHandler wah, Bundle contributor, String requireTldBundle) throws IOException { // rfc66 - wah.setAttribute(OSGiWebappConstants.RFC66_OSGI_BUNDLE_CONTEXT,contributor.getBundleContext()); + wah.setAttribute(OSGiWebappConstants.RFC66_OSGI_BUNDLE_CONTEXT, contributor.getBundleContext()); - //spring-dm-1.2.1 looks for the BundleContext as a different attribute. - //not a spec... but if we want to support - //org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext - //then we need to do this to: - wah.setAttribute("org.springframework.osgi.web." + BundleContext.class.getName(), - contributor.getBundleContext()); - - //also pass the bundle directly. sometimes a bundle does not have a bundlecontext. - //it is still useful to have access to the Bundle from the servlet context. + // spring-dm-1.2.1 looks for the BundleContext as a different attribute. + // not a spec... but if we want to support + // org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext + // then we need to do this to: + wah.setAttribute("org.springframework.osgi.web." + BundleContext.class.getName(), contributor.getBundleContext()); + + // also pass the bundle directly. sometimes a bundle does not have a + // bundlecontext. + // it is still useful to have access to the Bundle from the servlet + // context. wah.setAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE, contributor); - - //pass the value of the require tld bundle so that the TagLibOSGiConfiguration - //can pick it up. + + // pass the value of the require tld bundle so that the + // TagLibOSGiConfiguration + // can pick it up. wah.setAttribute(OSGiWebappConstants.REQUIRE_TLD_BUNDLE, requireTldBundle); - Bundle[] fragments = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles(contributor); if (fragments != null && fragments.length != 0) { - //sorted extra resource base found in the fragments. - //the resources are either overriding the resourcebase found in the web-bundle - //or appended. - //amongst each resource we sort them according to the alphabetical order - //of the name of the internal folder and the symbolic name of the fragment. - //this is useful to make sure that the lookup path of those - //resource base defined by fragments is always the same. - //This natural order could be abused to define the order in which the base resources are - //looked up. - TreeMap patchResourcesPath = new TreeMap(); - TreeMap appendedResourcesPath = new TreeMap(); - for (Bundle frag : fragments) { - String fragFolder = (String)frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_FRAGMENT_FOLDER_PATH); - String patchFragFolder = (String)frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_PATCH_FRAGMENT_FOLDER_PATH); + // sorted extra resource base found in the fragments. + // the resources are either overriding the resourcebase found in the + // web-bundle + // or appended. + // amongst each resource we sort them according to the alphabetical + // order + // of the name of the internal folder and the symbolic name of the + // fragment. + // this is useful to make sure that the lookup path of those + // resource base defined by fragments is always the same. + // This natural order could be abused to define the order in which + // the base resources are + // looked up. + TreeMap patchResourcesPath = new TreeMap(); + TreeMap appendedResourcesPath = new TreeMap(); + for (Bundle frag : fragments) + { + String fragFolder = (String) frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_FRAGMENT_FOLDER_PATH); + String patchFragFolder = (String) frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_PATCH_FRAGMENT_FOLDER_PATH); if (fragFolder != null) { URL fragUrl = frag.getEntry(fragFolder); - if (fragUrl == null) - { - throw new IllegalArgumentException("Unable to locate " + fragFolder + " inside " - + " the fragment '" + frag.getSymbolicName() + "'"); - } + if (fragUrl == null) { throw new IllegalArgumentException("Unable to locate " + fragFolder + + " inside " + + " the fragment '" + + frag.getSymbolicName() + + "'"); } fragUrl = DefaultFileLocatorHelper.getLocalURL(fragUrl); String key = fragFolder.startsWith("/") ? fragFolder.substring(1) : fragFolder; appendedResourcesPath.put(key + ";" + frag.getSymbolicName(), Resource.newResource(fragUrl)); @@ -539,11 +546,11 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper if (patchFragFolder != null) { URL patchFragUrl = frag.getEntry(patchFragFolder); - if (patchFragUrl == null) - { - throw new IllegalArgumentException("Unable to locate " + patchFragUrl + " inside " - + " the fragment '" + frag.getSymbolicName() + "'"); - } + if (patchFragUrl == null) { throw new IllegalArgumentException("Unable to locate " + patchFragUrl + + " inside " + + " the fragment '" + + frag.getSymbolicName() + + "'"); } patchFragUrl = DefaultFileLocatorHelper.getLocalURL(patchFragUrl); String key = patchFragFolder.startsWith("/") ? patchFragFolder.substring(1) : patchFragFolder; patchResourcesPath.put(key + ";" + frag.getSymbolicName(), Resource.newResource(patchFragUrl)); @@ -551,92 +558,92 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper } if (!appendedResourcesPath.isEmpty()) { - wah.setAttribute(WebInfConfiguration.RESOURCE_URLS, new ArrayList(appendedResourcesPath.values())); + wah.setAttribute(WebInfConfiguration.RESOURCE_URLS, new ArrayList(appendedResourcesPath.values())); } if (!patchResourcesPath.isEmpty()) { - wah.setAttribute(WebInfConfiguration.RESOURCE_URLS + ".patch", new ArrayList(patchResourcesPath.values())); + wah.setAttribute(WebInfConfiguration.RESOURCE_URLS + ".patch", new ArrayList(patchResourcesPath.values())); } - + if (wah instanceof WebAppContext) { - //This is the equivalent of what MetaInfConfiguration does. For OSGi bundles without the JarScanner - WebAppContext webappCtxt = (WebAppContext)wah; - //take care of the web-fragments, meta-inf resources and tld resources: - //similar to what MetaInfConfiguration does. - List frags = (List)wah.getAttribute(FragmentConfiguration.FRAGMENT_RESOURCES); - List resfrags = (List)wah.getAttribute(WebInfConfiguration.RESOURCE_URLS); - List tldfrags = (List)wah.getAttribute(TagLibConfiguration.TLD_RESOURCES); - for (Bundle frag : fragments) - { - URL webFrag = frag.getEntry("/META-INF/web-fragment.xml"); - Enumeration resEnum = frag.findEntries("/META-INF/resources", "*", true); - Enumeration tldEnum = frag.findEntries("/META-INF", "*.tld", false); - if (webFrag != null || (resEnum != null && resEnum.hasMoreElements()) - || (tldEnum != null && tldEnum.hasMoreElements())) - { - try - { - File fragFile = BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(frag); - //add it to the webinf jars collection: - //no need to check that it was not there yet: it was not there yet for sure. - Resource fragFileAsResource = Resource.newResource(fragFile.toURI()); - webappCtxt.getMetaData().addWebInfJar(fragFileAsResource); - - if (webFrag != null) - { - if (frags == null) - { - frags = new ArrayList(); - wah.setAttribute(FragmentConfiguration.FRAGMENT_RESOURCES, frags); - } - frags.add(fragFileAsResource); - } - if (resEnum != null && resEnum.hasMoreElements()) - { - URL resourcesEntry = frag.getEntry("/META-INF/resources/"); - if (resourcesEntry == null) - { - //probably we found some fragments to a bundle. - //those are already contributed. - //so we skip this. - } - else - { - if (resfrags == null) - { - resfrags = new ArrayList(); - wah.setAttribute(WebInfConfiguration.RESOURCE_URLS, resfrags); - } - resfrags.add(Resource.newResource( - DefaultFileLocatorHelper.getLocalURL(resourcesEntry))); - } - } - if (tldEnum != null && tldEnum.hasMoreElements()) - { - if (tldfrags == null) - { - tldfrags = new ArrayList(); - wah.setAttribute(TagLibConfiguration.TLD_RESOURCES, tldfrags); - } - while (tldEnum.hasMoreElements()) - { - URL tldUrl = tldEnum.nextElement(); - tldfrags.add(Resource.newResource( - DefaultFileLocatorHelper.getLocalURL(tldUrl))); - } - } - } - catch (Exception e) - { - __logger.warn("Unable to locate the bundle " + frag.getBundleId(),e); - } - } - } + // This is the equivalent of what MetaInfConfiguration does. For + // OSGi bundles without the JarScanner + WebAppContext webappCtxt = (WebAppContext) wah; + // take care of the web-fragments, meta-inf resources and tld + // resources: + // similar to what MetaInfConfiguration does. + List frags = (List) wah.getAttribute(FragmentConfiguration.FRAGMENT_RESOURCES); + List resfrags = (List) wah.getAttribute(WebInfConfiguration.RESOURCE_URLS); + List tldfrags = (List) wah.getAttribute(TagLibConfiguration.TLD_RESOURCES); + for (Bundle frag : fragments) + { + URL webFrag = frag.getEntry("/META-INF/web-fragment.xml"); + Enumeration resEnum = frag.findEntries("/META-INF/resources", "*", true); + Enumeration tldEnum = frag.findEntries("/META-INF", "*.tld", false); + if (webFrag != null || (resEnum != null && resEnum.hasMoreElements()) || (tldEnum != null && tldEnum.hasMoreElements())) + { + try + { + File fragFile = BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(frag); + // add it to the webinf jars collection: + // no need to check that it was not there yet: it + // was not there yet for sure. + Resource fragFileAsResource = Resource.newResource(fragFile.toURI()); + webappCtxt.getMetaData().addWebInfJar(fragFileAsResource); + + if (webFrag != null) + { + if (frags == null) + { + frags = new ArrayList(); + wah.setAttribute(FragmentConfiguration.FRAGMENT_RESOURCES, frags); + } + frags.add(fragFileAsResource); + } + if (resEnum != null && resEnum.hasMoreElements()) + { + URL resourcesEntry = frag.getEntry("/META-INF/resources/"); + if (resourcesEntry == null) + { + // probably we found some fragments to a + // bundle. + // those are already contributed. + // so we skip this. + } + else + { + if (resfrags == null) + { + resfrags = new ArrayList(); + wah.setAttribute(WebInfConfiguration.RESOURCE_URLS, resfrags); + } + resfrags.add(Resource.newResource(DefaultFileLocatorHelper.getLocalURL(resourcesEntry))); + } + } + if (tldEnum != null && tldEnum.hasMoreElements()) + { + if (tldfrags == null) + { + tldfrags = new ArrayList(); + wah.setAttribute(TagLibConfiguration.TLD_RESOURCES, tldfrags); + } + while (tldEnum.hasMoreElements()) + { + URL tldUrl = tldEnum.nextElement(); + tldfrags.add(Resource.newResource(DefaultFileLocatorHelper.getLocalURL(tldUrl))); + } + } + } + catch (Exception e) + { + __logger.warn("Unable to locate the bundle " + frag.getBundleId(), e); + } + } + } } } - - + } /** @@ -644,15 +651,13 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper * @param contextFile * @return */ - protected ContextHandler createContextHandler(ContextHandler handlerToConfigure, - Bundle bundle, File contextFile, String extraClasspath, - String overrideBundleInstallLocation, String requireTldBundle) + protected ContextHandler createContextHandler(ContextHandler handlerToConfigure, Bundle bundle, File contextFile, String extraClasspath, + String overrideBundleInstallLocation, String requireTldBundle) { try { - return createContextHandler(handlerToConfigure,bundle, - new BufferedInputStream(new FileInputStream(contextFile)), - extraClasspath,overrideBundleInstallLocation,requireTldBundle); + return createContextHandler(handlerToConfigure, bundle, new BufferedInputStream(new FileInputStream(contextFile)), extraClasspath, + overrideBundleInstallLocation, requireTldBundle); } catch (FileNotFoundException e) { @@ -667,9 +672,8 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper * @return */ @SuppressWarnings("unchecked") - protected ContextHandler createContextHandler(ContextHandler handlerToConfigure, - Bundle bundle, InputStream contextInputStream, String extraClasspath, - String overrideBundleInstallLocation, String requireTldBundle) + protected ContextHandler createContextHandler(ContextHandler handlerToConfigure, Bundle bundle, InputStream contextInputStream, String extraClasspath, + String overrideBundleInstallLocation, String requireTldBundle) { /* * Do something identical to what the ContextProvider would have done: @@ -686,30 +690,30 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper { XmlConfiguration xmlConfiguration = new XmlConfiguration(contextInputStream); HashMap properties = new HashMap(); - properties.put("Server",_wrapper.getServer()); - + properties.put("Server", _wrapper.getServer()); + // insert the bundle's location as a property. - setThisBundleHomeProperty(bundle,properties,overrideBundleInstallLocation); + setThisBundleHomeProperty(bundle, properties, overrideBundleInstallLocation); xmlConfiguration.getProperties().putAll(properties); ContextHandler context = null; if (handlerToConfigure == null) { - context = (ContextHandler)xmlConfiguration.configure(); + context = (ContextHandler) xmlConfiguration.configure(); } else { xmlConfiguration.configure(handlerToConfigure); context = handlerToConfigure; } - + if (context instanceof WebAppContext) { - ((WebAppContext)context).setExtraClasspath(extraClasspath); - ((WebAppContext)context).setParentLoaderPriority(_wrapper.getOSGiAppProvider().isParentLoaderPriority()); + ((WebAppContext) context).setExtraClasspath(extraClasspath); + ((WebAppContext) context).setParentLoaderPriority(_wrapper.getOSGiAppProvider().isParentLoaderPriority()); if (_wrapper.getOSGiAppProvider().getDefaultsDescriptor() != null && _wrapper.getOSGiAppProvider().getDefaultsDescriptor().length() != 0) { - ((WebAppContext)context).setDefaultsDescriptor(_wrapper.getOSGiAppProvider().getDefaultsDescriptor()); + ((WebAppContext) context).setDefaultsDescriptor(_wrapper.getOSGiAppProvider().getDefaultsDescriptor()); } } @@ -775,13 +779,12 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper { if (context instanceof WebAppContext) { - WebAppContext webappCtxt = (WebAppContext)context; + WebAppContext webappCtxt = (WebAppContext) context; context.setClassLoader(webappClassLoader); webappClassLoader.setWebappContext(webappCtxt); String pathsToRequiredBundles = getPathsToRequiredBundles(context, requireTldBundle); - if (pathsToRequiredBundles != null) - webappClassLoader.addClassPath(pathsToRequiredBundles); + if (pathsToRequiredBundles != null) webappClassLoader.addClassPath(pathsToRequiredBundles); } else { @@ -797,20 +800,20 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper // we use a temporary WebAppContext object. // if this is a real webapp we will set it on it a bit later: once we // know. - OSGiWebappClassLoader webappClassLoader = new OSGiWebappClassLoader( - _wrapper.getParentClassLoaderForWebapps(),new WebAppContext(),contributor,BUNDLE_CLASS_LOADER_HELPER); - /* DEBUG - try { - Class c = webappClassLoader.loadClass("org.glassfish.jsp.api.ResourceInjector"); - System.err.println("LOADED org.glassfish.jsp.api.ResourceInjector from "+c.getClassLoader()); - } - catch (Exception e) {e.printStackTrace();} - try { - Class c = webappClassLoader.loadClass("org.apache.jasper.xmlparser.ParserUtils"); - System.err.println("LOADED org.apache.jasper.xmlparser.ParserUtils from "+c.getClassLoader()); - } - catch (Exception e) {e.printStackTrace();} - */ + OSGiWebappClassLoader webappClassLoader = new OSGiWebappClassLoader(_wrapper.getParentClassLoaderForWebapps(), new WebAppContext(), contributor, + BUNDLE_CLASS_LOADER_HELPER); + /* + * 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; } @@ -823,10 +826,9 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper { try { - File location = overrideBundleInstallLocation != null?new File(overrideBundleInstallLocation):BUNDLE_FILE_LOCATOR_HELPER - .getBundleInstallLocation(bundle); - properties.put("this.bundle.install",location.getCanonicalPath()); - properties.put("this.bundle.install.url",bundle.getEntry("/").toString()); + File location = overrideBundleInstallLocation != null ? new File(overrideBundleInstallLocation) : BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(bundle); + properties.put("this.bundle.install", location.getCanonicalPath()); + properties.put("this.bundle.install.url", bundle.getEntry("/").toString()); } catch (Throwable t) { @@ -834,36 +836,30 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper } } - - private String getPathsToRequiredBundles (ContextHandler context, String requireTldBundle) throws Exception + private String getPathsToRequiredBundles(ContextHandler context, String requireTldBundle) throws Exception { - if (requireTldBundle == null) - return null; + if (requireTldBundle == null) return null; StringBuilder paths = new StringBuilder(); - Bundle bundle = (Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE); + Bundle bundle = (Bundle) context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE); PackageAdmin packAdmin = getBundleAdmin(); DefaultFileLocatorHelper fileLocatorHelper = new DefaultFileLocatorHelper(); - + String[] symbNames = requireTldBundle.split(", "); for (String symbName : symbNames) { Bundle[] bs = packAdmin.getBundles(symbName, null); - if (bs == null || bs.length == 0) - { - throw new IllegalArgumentException("Unable to locate the bundle '" - + symbName + "' specified in the " - + OSGiWebappConstants.REQUIRE_TLD_BUNDLE - + " of the manifest of " - + bundle.getSymbolicName()); - } + if (bs == null || bs.length == 0) { throw new IllegalArgumentException("Unable to locate the bundle '" + symbName + + "' specified in the " + + OSGiWebappConstants.REQUIRE_TLD_BUNDLE + + " of the manifest of " + + bundle.getSymbolicName()); } - File f = fileLocatorHelper.getBundleInstallLocation(bs[0]); - if (paths.length() > 0) + if (paths.length() > 0) paths.append(", "); - System.err.println("getPathsToRequiredBundles: bundle path="+bs[0].getLocation()+" uri="+f.toURI()); + __logger.debug("getPathsToRequiredBundles: bundle path=" + bs[0].getLocation() + " uri=" + f.toURI()); paths.append(f.toURI().toURL().toString()); } @@ -872,12 +868,11 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper private PackageAdmin getBundleAdmin() { - Bundle bootBundle = ((BundleReference)OSGiWebappConstants.class.getClassLoader()).getBundle(); + Bundle bootBundle = ((BundleReference) OSGiWebappConstants.class.getClassLoader()).getBundle(); ServiceTracker serviceTracker = new ServiceTracker(bootBundle.getBundleContext(), PackageAdmin.class.getName(), null); serviceTracker.open(); return (PackageAdmin) serviceTracker.getService(); } - } diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java index 3cfea34c932..79938415305 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java @@ -24,7 +24,6 @@ import org.osgi.framework.BundleEvent; import org.osgi.util.tracker.BundleTracker; import org.osgi.util.tracker.BundleTrackerCustomizer; - /** * Support bundles that declare the webapp directly through headers in their * manifest. @@ -49,133 +48,132 @@ import org.osgi.util.tracker.BundleTrackerCustomizer; * * @author hmalphettes */ -public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer { +public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer +{ private static final Logger LOG = Log.getLogger(WebBundleTrackerCustomizer.class); - + /** + * A bundle is being added to the BundleTracker. + * + *

+ * This method is called before a bundle which matched the search parameters + * of the BundleTracker is added to the + * BundleTracker. This method should return the object to be + * tracked for the specified Bundle. The returned object is + * stored in the BundleTracker and is available from the + * {@link BundleTracker#getObject(Bundle) getObject} method. + * + * @param bundle The Bundle being added to the + * BundleTracker. + * @param event The bundle event which caused this customizer method to be + * called or null if there is no bundle event + * associated with the call to this method. + * @return The object to be tracked for the specified Bundle + * object or null if the specified Bundle + * object should not be tracked. + */ + public Object addingBundle(Bundle bundle, BundleEvent event) + { + if (bundle.getState() == Bundle.ACTIVE) + { + boolean isWebBundle = register(bundle); + return isWebBundle ? bundle : null; + } + else if (bundle.getState() == Bundle.STOPPING) + { + unregister(bundle); + } + else + { + // we should not be called in that state as + // we are registered only for ACTIVE and STOPPING + } + return null; + } - /** - * A bundle is being added to the BundleTracker. - * - *

- * This method is called before a bundle which matched the search parameters - * of the BundleTracker is added to the - * BundleTracker. This method should return the object to be - * tracked for the specified Bundle. The returned object is - * stored in the BundleTracker and is available from the - * {@link BundleTracker#getObject(Bundle) getObject} method. - * - * @param bundle The Bundle being added to the - * BundleTracker. - * @param event The bundle event which caused this customizer method to be - * called or null if there is no bundle event associated - * with the call to this method. - * @return The object to be tracked for the specified Bundle - * object or null if the specified Bundle - * object should not be tracked. - */ - public Object addingBundle(Bundle bundle, BundleEvent event) - { - if (bundle.getState() == Bundle.ACTIVE) - { - boolean isWebBundle = register(bundle); - return isWebBundle ? bundle : null; - } - else if (bundle.getState() == Bundle.STOPPING) - { - unregister(bundle); - } - else - { - //we should not be called in that state as - //we are registered only for ACTIVE and STOPPING - } - return null; - } + /** + * A bundle tracked by the BundleTracker has been modified. + * + *

+ * This method is called when a bundle being tracked by the + * BundleTracker has had its state modified. + * + * @param bundle The Bundle whose state has been modified. + * @param event The bundle event which caused this customizer method to be + * called or null if there is no bundle event + * associated with the call to this method. + * @param object The tracked object for the specified bundle. + */ + public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) + { + // nothing the web-bundle was already track. something changed. + // we only reload the webapps if the bundle is stopped and restarted. + if (bundle.getState() == Bundle.STOPPING || bundle.getState() == Bundle.ACTIVE) + { + unregister(bundle); + } + if (bundle.getState() == Bundle.ACTIVE) + { + register(bundle); + } + } - /** - * A bundle tracked by the BundleTracker has been modified. - * - *

- * This method is called when a bundle being tracked by the - * BundleTracker has had its state modified. - * - * @param bundle The Bundle whose state has been modified. - * @param event The bundle event which caused this customizer method to be - * called or null if there is no bundle event associated - * with the call to this method. - * @param object The tracked object for the specified bundle. - */ - public void modifiedBundle(Bundle bundle, BundleEvent event, - Object object) - { - //nothing the web-bundle was already track. something changed. - //we only reload the webapps if the bundle is stopped and restarted. -// System.err.println(bundle.getSymbolicName()); - if (bundle.getState() == Bundle.STOPPING || bundle.getState() == Bundle.ACTIVE) - { - unregister(bundle); - } - if (bundle.getState() == Bundle.ACTIVE) - { - register(bundle); - } - } + /** + * A bundle tracked by the BundleTracker has been removed. + * + *

+ * This method is called after a bundle is no longer being tracked by the + * BundleTracker. + * + * @param bundle The Bundle that has been removed. + * @param event The bundle event which caused this customizer method to be + * called or null if there is no bundle event + * associated with the call to this method. + * @param object The tracked object for the specified bundle. + */ + public void removedBundle(Bundle bundle, BundleEvent event, Object object) + { + unregister(bundle); + } - /** - * A bundle tracked by the BundleTracker has been removed. - * - *

- * This method is called after a bundle is no longer being tracked by the - * BundleTracker. - * - * @param bundle The Bundle that has been removed. - * @param event The bundle event which caused this customizer method to be - * called or null if there is no bundle event associated - * with the call to this method. - * @param object The tracked object for the specified bundle. - */ - public void removedBundle(Bundle bundle, BundleEvent event, - Object object) - { - unregister(bundle); - } - - - /** - * @param bundle - * @return true if this bundle in indeed a web-bundle. - */ + /** + * @param bundle + * @return true if this bundle in indeed a web-bundle. + */ private boolean register(Bundle bundle) { Dictionary dic = bundle.getHeaders(); - String warFolderRelativePath = (String)dic.get(OSGiWebappConstants.JETTY_WAR_FOLDER_PATH); + String warFolderRelativePath = (String) dic.get(OSGiWebappConstants.JETTY_WAR_FOLDER_PATH); if (warFolderRelativePath != null) { - String contextPath = getWebContextPath(bundle, dic, false);//(String)dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH); + String contextPath = getWebContextPath(bundle, dic, false);// (String)dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH); if (contextPath == null || !contextPath.startsWith("/")) { - LOG.warn("The manifest header '" + OSGiWebappConstants.JETTY_WAR_FOLDER_PATH + - ": " + warFolderRelativePath + "' in the bundle " + bundle.getSymbolicName() + - " is not valid: there is no Web-ContextPath defined in the manifest."); - return false; + LOG.warn("The manifest header '" + OSGiWebappConstants.JETTY_WAR_FOLDER_PATH + + ": " + + warFolderRelativePath + + "' in the bundle " + + bundle.getSymbolicName() + + " is not valid: there is no Web-ContextPath defined in the manifest."); + return false; } // create the corresponding service and publish it in the context of // the contributor bundle. try { - JettyBootstrapActivator.registerWebapplication(bundle,warFolderRelativePath,contextPath); + JettyBootstrapActivator.registerWebapplication(bundle, warFolderRelativePath, contextPath); return true; } catch (Throwable e) { - LOG.warn("Starting the web-bundle " + bundle.getSymbolicName() + " threw an exception.", e); - return true;//maybe it did not work maybe it did. safer to track this bundle. + LOG.warn("Starting the web-bundle " + bundle.getSymbolicName() + " threw an exception.", e); + return true;// maybe it did not work maybe it did. safer to + // track this bundle. } } else if (dic.get(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH) != null) { - String contextFileRelativePath = (String)dic.get(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH); + String contextFileRelativePath = (String) dic.get(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH); if (contextFileRelativePath == null) { // nothing to register here. @@ -187,7 +185,7 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer { { try { - JettyBootstrapActivator.registerContext(bundle,path.trim()); + JettyBootstrapActivator.registerContext(bundle, path.trim()); } catch (Throwable e) { @@ -203,8 +201,8 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer { // (draft) of the spec: just a couple of posts on the // world-wide-web. URL rfc66Webxml = bundle.getEntry("/WEB-INF/web.xml"); - if (rfc66Webxml == null && dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH) == null) - { + if (rfc66Webxml == null && dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH) == null) + { return false;// no webapp in here } // this is risky: should we make sure that there is no classes and @@ -215,42 +213,41 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer { // pointing to files and folders inside WEB-INF. We should // filter-out // META-INF too - String rfc66ContextPath = getWebContextPath(bundle,dic,rfc66Webxml==null); + String rfc66ContextPath = getWebContextPath(bundle, dic, rfc66Webxml == null); try { - JettyBootstrapActivator.registerWebapplication(bundle,".",rfc66ContextPath); + JettyBootstrapActivator.registerWebapplication(bundle, ".", rfc66ContextPath); return true; } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); - return true;//maybe it did not work maybe it did. safer to track this bundle. + return true;// maybe it did not work maybe it did. safer to + // track this bundle. } } } private String getWebContextPath(Bundle bundle, Dictionary dic, boolean webinfWebxmlExists) { - String rfc66ContextPath = (String)dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH); + String rfc66ContextPath = (String) dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH); if (rfc66ContextPath == null) { - if (!webinfWebxmlExists) { - return null; - } + if (!webinfWebxmlExists) { return null; } // extract from the last token of the bundle's location: // (really ? // could consider processing the symbolic name as an alternative // the location will often reflect the version. // maybe this is relevant when the file is a war) String location = bundle.getLocation(); - String toks[] = location.replace('\\','/').split("/"); + String toks[] = location.replace('\\', '/').split("/"); rfc66ContextPath = toks[toks.length - 1]; // remove .jar, .war etc: int lastDot = rfc66ContextPath.lastIndexOf('.'); if (lastDot != -1) { - rfc66ContextPath = rfc66ContextPath.substring(0,lastDot); + rfc66ContextPath = rfc66ContextPath.substring(0, lastDot); } } if (!rfc66ContextPath.startsWith("/")) @@ -259,7 +256,7 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer { } return rfc66ContextPath; } - + private void unregister(Bundle bundle) { // nothing to do: when the bundle is stopped, each one of its service @@ -268,7 +265,4 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer { // webapps registered in that bundle. } - - - } diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java index 73b127cd637..7858e574243 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java @@ -25,6 +25,7 @@ import java.util.zip.ZipFile; import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper; import org.eclipse.jetty.util.URIUtil; +import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.FileResource; import org.osgi.framework.Bundle; @@ -43,11 +44,13 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper // The url nuxeo and felix return is created directly from the File so it // should work. private static Field BUNDLE_ENTRY_FIELD = null; + private static Field FILE_FIELD = null; private static Field BUNDLE_FILE_FIELD_FOR_DIR_ZIP_BUNDLE_ENTRY = null;// ZipBundleFile - // inside - // DirZipBundleEntry + + // inside + // DirZipBundleEntry private static Field ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE = null;// ZipFile @@ -56,8 +59,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper * spirit of OSGi but quite necessary to support self-contained webapps and * other situations. * - * @param bundle - * The bundle + * @param bundle The bundle * @return Its installation location as a file. * @throws Exception */ @@ -67,19 +69,23 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper // grab the MANIFEST.MF's url // and then do what it takes. URL url = bundle.getEntry("/META-INF/MANIFEST.MF"); -// System.err.println(url.toString() + " " + url.toURI() + " " + url.getProtocol()); + //System.err.println(url.toString() + " " + url.toURI() + " " + url.getProtocol()); if (url.getProtocol().equals("file")) { // some osgi frameworks do use the file protocole directly in some - // situations. Do use the FileResource to transform the URL into a File: URL#toURI is broken - return new FileResource(url).getFile().getParentFile().getParentFile(); + // situations. Do use the FileResource to transform the URL into a + // File: URL#toURI is broken + return new FileResource(url).getFile().getParentFile().getParentFile(); } else if (url.getProtocol().equals("bundleentry")) { // say hello to equinox who has its own protocol. // we use introspection like there is no tomorrow to get access to // the File + URLConnection con = url.openConnection(); + con.setUseCaches(Resource.getDefaultUseCaches()); //work around problems where url connections cache references to jars + if (BUNDLE_ENTRY_FIELD == null) { BUNDLE_ENTRY_FIELD = con.getClass().getDeclaredField("bundleEntry"); @@ -93,13 +99,16 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper FILE_FIELD = bundleEntry.getClass().getDeclaredField("file"); FILE_FIELD.setAccessible(true); } - File f = (File)FILE_FIELD.get(bundleEntry); + File f = (File) FILE_FIELD.get(bundleEntry); return f.getParentFile().getParentFile(); } else if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.ZipBundleEntry")) { url = bundle.getEntry("/"); + con = url.openConnection(); + con.setDefaultUseCaches(Resource.getDefaultUseCaches()); + if (BUNDLE_ENTRY_FIELD == null) {// this one will be a DirZipBundleEntry BUNDLE_ENTRY_FIELD = con.getClass().getDeclaredField("bundleEntry"); @@ -117,7 +126,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE = zipBundleFile.getClass().getDeclaredField("zipFile"); ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE.setAccessible(true); } - ZipFile zipFile = (ZipFile)ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE.get(zipBundleFile); + ZipFile zipFile = (ZipFile) ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE.get(zipBundleFile); return new File(zipFile.getName()); } else if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.DirZipBundleEntry")) @@ -130,7 +139,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper { // observed this on felix-2.0.0 String location = bundle.getLocation(); -// System.err.println("location " + location); + // System.err.println("location " + location); if (location.startsWith("file:/")) { URI uri = new URI(URIUtil.encodePath(location)); @@ -138,27 +147,32 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper } else if (location.startsWith("file:")) { - //location defined in the BundleArchive m_bundleArchive - //it is relative to relative to the BundleArchive's m_archiveRootDir - File res = new File(location.substring("file:".length())); - if (!res.exists()) - { - return null; -// Object bundleArchive = getFelixBundleArchive(bundle); -// File archiveRoot = getFelixBundleArchiveRootDir(bundleArchive); -// String currentLocation = getFelixBundleArchiveCurrentLocation(bundleArchive); -// System.err.println("Got the archive root " + archiveRoot.getAbsolutePath() -// + " current location " + currentLocation + " is directory ?"); -// res = new File(archiveRoot, currentLocation != null -// ? currentLocation : location.substring("file:".length())); - } - return res; + // location defined in the BundleArchive m_bundleArchive + // it is relative to relative to the BundleArchive's + // m_archiveRootDir + File res = new File(location.substring("file:".length())); + if (!res.exists()) + { + return null; + // Object bundleArchive = getFelixBundleArchive(bundle); + // File archiveRoot = + // getFelixBundleArchiveRootDir(bundleArchive); + // String currentLocation = + // getFelixBundleArchiveCurrentLocation(bundleArchive); + // System.err.println("Got the archive root " + + // archiveRoot.getAbsolutePath() + // + " current location " + currentLocation + + // " is directory ?"); + // res = new File(archiveRoot, currentLocation != null + // ? currentLocation : location.substring("file:".length())); + } + return res; } else if (location.startsWith("reference:file:")) { - location = URLDecoder.decode(location.substring("reference:".length()), "UTF-8"); - File file = new File(location.substring("file:".length())); - return file; + location = URLDecoder.decode(location.substring("reference:".length()), "UTF-8"); + File file = new File(location.substring("file:".length())); + return file; } } return null; @@ -179,37 +193,40 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper path = path.substring(1); } File bundleInstall = getBundleInstallLocation(bundle); - File webapp = path != null && path.length() != 0?new File(bundleInstall,path):bundleInstall; - if (!webapp.exists()) - { - throw new IllegalArgumentException("Unable to locate " + path + " inside " + bundle.getSymbolicName() + " (" - + (bundleInstall != null?bundleInstall.getAbsolutePath():" no_bundle_location ") + ")"); + File webapp = path != null && path.length() != 0 ? new File(bundleInstall, path) : bundleInstall; + if (!webapp.exists()) + { + throw new IllegalArgumentException("Unable to locate " + path + + " inside " + + bundle.getSymbolicName() + + " (" + + (bundleInstall != null ? bundleInstall.getAbsolutePath() : " no_bundle_location ") + + ")"); } return webapp; } - + /** - * Helper method equivalent to Bundle#getEntry(String entryPath) except that - * it searches for entries in the fragments by using the Bundle#findEntries method. - * - * @param bundle - * @param entryPath - * @return null or all the entries found for that path. - */ - public Enumeration findEntries(Bundle bundle, String entryPath) - { - int last = entryPath.lastIndexOf('/'); - String path = last != -1 && last < entryPath.length() -2 - ? entryPath.substring(0, last) : "/"; - if (!path.startsWith("/")) - { - path = "/" + path; - } - String pattern = last != -1 && last < entryPath.length() -2 - ? entryPath.substring(last+1) : entryPath; - Enumeration enUrls = bundle.findEntries(path, pattern, false); - return enUrls; - } + * Helper method equivalent to Bundle#getEntry(String entryPath) except that + * it searches for entries in the fragments by using the Bundle#findEntries + * method. + * + * @param bundle + * @param entryPath + * @return null or all the entries found for that path. + */ + public Enumeration findEntries(Bundle bundle, String entryPath) + { + int last = entryPath.lastIndexOf('/'); + String path = last != -1 && last < entryPath.length() - 2 ? entryPath.substring(0, last) : "/"; + if (!path.startsWith("/")) + { + path = "/" + path; + } + String pattern = last != -1 && last < entryPath.length() - 2 ? entryPath.substring(last + 1) : entryPath; + Enumeration enUrls = bundle.findEntries(path, pattern, false); + return enUrls; + } /** * If the bundle is a jar, returns the jar. If the bundle is a folder, look @@ -256,76 +273,84 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper return new File[] { jasperLocation }; } } - - //introspection on equinox to invoke the getLocalURL method on BundleURLConnection - //equivalent to using the FileLocator without depending on an equinox class. - private static Method BUNDLE_URL_CONNECTION_getLocalURL = null; - private static Method BUNDLE_URL_CONNECTION_getFileURL = null; - /** - * Only useful for equinox: on felix we get the file:// or jar:// url already. - * Other OSGi implementations have not been tested - *

- * Get a URL to the bundle entry that uses a common protocol (i.e. file: - * jar: or http: etc.). - *

- * @return a URL to the bundle entry that uses a common protocol - */ - public static URL getLocalURL(URL url) { - if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol())) { - try { - URLConnection conn = url.openConnection(); - if (BUNDLE_URL_CONNECTION_getLocalURL == null && - conn.getClass().getName().equals( - "org.eclipse.osgi.framework.internal.core.BundleURLConnection")) { - BUNDLE_URL_CONNECTION_getLocalURL = conn.getClass().getMethod("getLocalURL", null); - BUNDLE_URL_CONNECTION_getLocalURL.setAccessible(true); - } - if (BUNDLE_URL_CONNECTION_getLocalURL != null) { - return (URL)BUNDLE_URL_CONNECTION_getLocalURL.invoke(conn, null); - } - } catch (Throwable t) { - System.err.println("Unable to locate the OSGi url: '" + url + "'."); - t.printStackTrace(); - } - } - return url; - } - /** - * Only useful for equinox: on felix we get the file:// url already. - * Other OSGi implementations have not been tested - *

- * Get a URL to the content of the bundle entry that uses the file: protocol. - * The content of the bundle entry may be downloaded or extracted to the local - * file system in order to create a file: URL. - * @return a URL to the content of the bundle entry that uses the file: protocol - *

- */ - public static URL getFileURL(URL url) - { - if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol())) - { - try - { - URLConnection conn = url.openConnection(); - if (BUNDLE_URL_CONNECTION_getFileURL == null && - conn.getClass().getName().equals( - "org.eclipse.osgi.framework.internal.core.BundleURLConnection")) - { - BUNDLE_URL_CONNECTION_getFileURL = conn.getClass().getMethod("getFileURL", null); - BUNDLE_URL_CONNECTION_getFileURL.setAccessible(true); - } - if (BUNDLE_URL_CONNECTION_getFileURL != null) - { - return (URL)BUNDLE_URL_CONNECTION_getFileURL.invoke(conn, null); - } - } - catch (Throwable t) - { - t.printStackTrace(); - } - } - return url; - } + // introspection on equinox to invoke the getLocalURL method on + // BundleURLConnection + // equivalent to using the FileLocator without depending on an equinox + // class. + private static Method BUNDLE_URL_CONNECTION_getLocalURL = null; + + private static Method BUNDLE_URL_CONNECTION_getFileURL = null; + + /** + * Only useful for equinox: on felix we get the file:// or jar:// url + * already. Other OSGi implementations have not been tested + *

+ * Get a URL to the bundle entry that uses a common protocol (i.e. file: + * jar: or http: etc.). + *

+ * + * @return a URL to the bundle entry that uses a common protocol + */ + public static URL getLocalURL(URL url) + { + if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol())) + { + try + { + URLConnection conn = url.openConnection(); + conn.setDefaultUseCaches(Resource.getDefaultUseCaches()); + if (BUNDLE_URL_CONNECTION_getLocalURL == null && conn.getClass().getName() + .equals("org.eclipse.osgi.framework.internal.core.BundleURLConnection")) + { + BUNDLE_URL_CONNECTION_getLocalURL = conn.getClass().getMethod("getLocalURL", null); + BUNDLE_URL_CONNECTION_getLocalURL.setAccessible(true); + } + if (BUNDLE_URL_CONNECTION_getLocalURL != null) { return (URL) BUNDLE_URL_CONNECTION_getLocalURL.invoke(conn, null); } + } + catch (Throwable t) + { + System.err.println("Unable to locate the OSGi url: '" + url + "'."); + t.printStackTrace(); + } + } + return url; + } + + /** + * Only useful for equinox: on felix we get the file:// url already. Other + * OSGi implementations have not been tested + *

+ * Get a URL to the content of the bundle entry that uses the file: + * protocol. The content of the bundle entry may be downloaded or extracted + * to the local file system in order to create a file: URL. + * + * @return a URL to the content of the bundle entry that uses the file: + * protocol + *

+ */ + public static URL getFileURL(URL url) + { + if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol())) + { + try + { + URLConnection conn = url.openConnection(); + conn.setDefaultUseCaches(Resource.getDefaultUseCaches()); + if (BUNDLE_URL_CONNECTION_getFileURL == null && conn.getClass().getName() + .equals("org.eclipse.osgi.framework.internal.core.BundleURLConnection")) + { + BUNDLE_URL_CONNECTION_getFileURL = conn.getClass().getMethod("getFileURL", null); + BUNDLE_URL_CONNECTION_getFileURL.setAccessible(true); + } + if (BUNDLE_URL_CONNECTION_getFileURL != null) { return (URL) BUNDLE_URL_CONNECTION_getFileURL.invoke(conn, null); } + } + catch (Throwable t) + { + t.printStackTrace(); + } + } + return url; + } } From 50f545b29a0227cbd78e05d9b8b10ca2c4e985b4 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Wed, 4 Apr 2012 19:21:16 +0200 Subject: [PATCH 22/36] Vastly improved queueing of FrameBytes, by appending at the end of the queue (instead of iterating over the queue). Also, implemented a better fix for the missing flush() in case of missing handlers: now instead of flushing in the write completion handler (which could lead to stack overflows), we use the same mechanism employed for FrameBytes, where we avoid stack overflows by dispatching to a new thread after few recursive invocations. --- .../eclipse/jetty/spdy/StandardSession.java | 74 ++++++++++--------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java index ecf5deb1fed..dae08a4c4cd 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java @@ -820,15 +820,21 @@ public class StandardSession implements ISession, Parser.Listener, Handler 0) + { + FrameBytes element = queue.get(index - 1); + if (element.compareTo(frameBytes) >= 0) + break; + --index; + } + queue.add(index, frameBytes); + } } private void prepend(FrameBytes frameBytes) - { - enqueue(frameBytes, true); - } - - private void enqueue(FrameBytes frameBytes, boolean prepend) { synchronized (queue) { @@ -836,8 +842,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler 0 || prepend && comparison == 0) + if (element.compareTo(frameBytes) <= 0) break; ++index; } @@ -854,7 +859,6 @@ public class StandardSession implements ISession, Parser.Listener, Handler void complete(final Handler handler, final C context) { - if (handler != null) + // Applications may send and queue up a lot of frames and + // if we call Handler.completed() only synchronously we risk + // starvation (for the last frames sent) and stack overflow. + // Therefore every some invocation, we dispatch to a new thread + Integer invocations = handlerInvocations.get(); + if (invocations >= 4) { - // Applications may send and queue up a lot of frames and - // if we call Handler.completed() only synchronously we risk - // starvation (for the last frames sent) and stack overflow. - // Therefore every some invocation, we dispatch to a new thread - Integer invocations = handlerInvocations.get(); - if (invocations >= 4) + execute(new Runnable() { - execute(new Runnable() + @Override + public void run() { - @Override - public void run() - { + if (handler != null) notifyHandlerCompleted(handler, context); - flush(); - } - }); - } - else - { - handlerInvocations.set(invocations + 1); - try - { - notifyHandlerCompleted(handler, context); flush(); } - finally - { - handlerInvocations.set(invocations); - } + }); + } + else + { + handlerInvocations.set(invocations + 1); + try + { + if (handler != null) + notifyHandlerCompleted(handler, context); + flush(); + } + finally + { + handlerInvocations.set(invocations); } } } @@ -967,7 +970,8 @@ public class StandardSession implements ISession, Parser.Listener, Handler that.stream.priority => -1 (this.stream has less priority than that.stream) + return that.getStream().getPriority() - getStream().getPriority(); } @Override From d47d4b15ea09f7a0b33ea9121198717bc00cc512 Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Thu, 5 Apr 2012 17:34:00 +1000 Subject: [PATCH 23/36] Added ability to use a META-INF/jetty-webapp-context.xml file to apply a context configuration file to a webapp. Replaced more printStackTrace with log calls; more formatting. --- .../jetty/osgi/boot/OSGiAppProvider.java | 6 +- .../DefaultJettyAtJettyHomeHelper.java | 15 +++-- .../JettyContextHandlerServiceTracker.java | 13 ++-- .../webapp/WebBundleDeployerHelper.java | 65 +++++++++++++------ .../webapp/WebBundleTrackerCustomizer.java | 12 ++-- .../internal/DefaultFileLocatorHelper.java | 2 +- 6 files changed, 70 insertions(+), 43 deletions(-) diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiAppProvider.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiAppProvider.java index 34fd8c74db4..510c09e8b67 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiAppProvider.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiAppProvider.java @@ -349,7 +349,7 @@ public class OSGiAppProvider extends ScanningAppProvider implements AppProvider } catch (IOException e) { - e.printStackTrace(); + LOG.warn(e); return null; } } @@ -370,11 +370,11 @@ public class OSGiAppProvider extends ScanningAppProvider implements AppProvider } catch (IOException e) { - e.printStackTrace(); + LOG.warn(e); return null; } } - + public boolean isExtract() { return _extractWars; diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/DefaultJettyAtJettyHomeHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/DefaultJettyAtJettyHomeHelper.java index d8491eeacbe..17ea8d22cc7 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/DefaultJettyAtJettyHomeHelper.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/DefaultJettyAtJettyHomeHelper.java @@ -167,18 +167,21 @@ public class DefaultJettyAtJettyHomeHelper { */ private static String getJettyConfigurationURLs(File jettyhome) { - String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES,"etc/jetty.xml"); - StringTokenizer tokenizer = new StringTokenizer(jettyetc,";,", false); + String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES, "etc/jetty.xml"); + StringTokenizer tokenizer = new StringTokenizer(jettyetc, ";,", false); StringBuilder res = new StringBuilder(); while (tokenizer.hasMoreTokens()) { String next = tokenizer.nextToken().trim(); if (!next.startsWith("/") && next.indexOf(':') == -1) { - try { + try + { next = new File(jettyhome, next).toURI().toURL().toString(); - } catch (MalformedURLException e) { - e.printStackTrace(); + } + catch (MalformedURLException e) + { + LOG.warn(e); continue; } } @@ -225,7 +228,7 @@ public class DefaultJettyAtJettyHomeHelper { } if (enUrls == null || !enUrls.hasMoreElements()) { - System.err.println("Unable to locate a jetty configuration file for " + etcFile); + LOG.warn("Unable to locate a jetty configuration file for " + etcFile); } if (enUrls != null) { diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/JettyContextHandlerServiceTracker.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/JettyContextHandlerServiceTracker.java index 26120c1850f..0838a4850ab 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/JettyContextHandlerServiceTracker.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/JettyContextHandlerServiceTracker.java @@ -24,6 +24,8 @@ import org.eclipse.jetty.osgi.boot.internal.serverfactory.DefaultJettyAtJettyHom import org.eclipse.jetty.osgi.boot.internal.serverfactory.IManagedJettyServerRegistry; import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper; import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.Scanner; import org.eclipse.jetty.webapp.WebAppContext; import org.osgi.framework.Bundle; @@ -52,7 +54,8 @@ import org.osgi.framework.ServiceReference; */ public class JettyContextHandlerServiceTracker implements ServiceListener { - + private static Logger __logger = Log.getLogger(WebBundleDeployerHelper.class.getName()); + /** New style: ability to manage multiple jetty instances */ private final IManagedJettyServerRegistry _registry; @@ -149,8 +152,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); + __logger.warn(e); } } } @@ -236,7 +238,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener } catch (Throwable e) { - e.printStackTrace(); + __logger.warn(e); } } else @@ -270,8 +272,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener } catch (Throwable e) { - // TODO Auto-generated catch block - e.printStackTrace(); + __logger.warn(e); } } } diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleDeployerHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleDeployerHelper.java index 97d72cb2c38..a681396910e 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleDeployerHelper.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleDeployerHelper.java @@ -229,6 +229,11 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper try { + + + //apply any META-INF/context.xml file that is found to configure the webapp first + applyMetaInfContextXml (contributor, context); + // make sure we provide access to all the jetty bundles by going // through this bundle. OSGiWebappClassLoader composite = createWebappClassLoader(contributor); @@ -661,7 +666,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper } catch (FileNotFoundException e) { - e.printStackTrace(); + __logger.warn(e); } return null; } @@ -726,18 +731,15 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper } catch (SAXException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + __logger.warn(e); } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + __logger.warn(e); } catch (Throwable e) { - // TODO Auto-generated catch block - e.printStackTrace(); + __logger.warn(e); } finally { @@ -802,21 +804,46 @@ 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; } + + protected void applyMetaInfContextXml (Bundle bundle, ContextHandler contextHandler) + throws Exception + { + if (bundle == null) + return; + if (contextHandler == null) + return; + + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + __logger.info("Context classloader = "+cl); + try + { + Thread.currentThread().setContextClassLoader(_wrapper.getParentClassLoaderForWebapps()); + + //find if there is a META-INF/context.xml file + URL contextXmlUrl = bundle.getEntry("/META-INF/jetty-webapp-context.xml"); + if (contextXmlUrl == null) + return; + + //Apply it just as the standard jetty ContextProvider would do + __logger.info("Applying "+contextXmlUrl+" to "+contextHandler); + + XmlConfiguration xmlConfiguration = new XmlConfiguration(contextXmlUrl); + HashMap properties = new HashMap(); + properties.put("Server", _wrapper.getServer()); + xmlConfiguration.getProperties().putAll(properties); + xmlConfiguration.configure(contextHandler); + } + finally + { + Thread.currentThread().setContextClassLoader(cl); + } + } + + + /** * Set the property "this.bundle.install" to point to the location * of the bundle. Useful when is diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java index 79938415305..137c49bb271 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java @@ -167,8 +167,7 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer catch (Throwable e) { LOG.warn("Starting the web-bundle " + bundle.getSymbolicName() + " threw an exception.", e); - return true;// maybe it did not work maybe it did. safer to - // track this bundle. + return true;// maybe it did not work maybe it did. safer to track this bundle. } } else if (dic.get(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH) != null) @@ -189,8 +188,7 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer } catch (Throwable e) { - // TODO Auto-generated catch block - e.printStackTrace(); + LOG.warn(e); } } return true; @@ -221,10 +219,8 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer } catch (Throwable e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return true;// maybe it did not work maybe it did. safer to - // track this bundle. + LOG.warn(e); + return true;// maybe it did not work maybe it did. safer to track this bundle. } } } diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java index 7858e574243..0e0ff3fbdae 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java @@ -69,7 +69,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper // grab the MANIFEST.MF's url // and then do what it takes. URL url = bundle.getEntry("/META-INF/MANIFEST.MF"); - //System.err.println(url.toString() + " " + url.toURI() + " " + url.getProtocol()); + if (url.getProtocol().equals("file")) { // some osgi frameworks do use the file protocole directly in some From eaacd69ede679f836873a44a367b20516f449191 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Thu, 5 Apr 2012 17:30:05 +0200 Subject: [PATCH 24/36] Moved from SLF4J to Jetty logging. --- jetty-spdy/spdy-core/pom.xml | 5 +++-- .../main/java/org/eclipse/jetty/spdy/StandardSession.java | 6 +++--- .../main/java/org/eclipse/jetty/spdy/StandardStream.java | 6 +++--- .../org/eclipse/jetty/spdy/api/SessionFrameListener.java | 6 +++--- .../main/java/org/eclipse/jetty/spdy/parser/Parser.java | 6 +++--- .../jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java | 6 +++--- .../spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java | 6 +++--- .../java/org/eclipse/jetty/spdy/SPDYAsyncConnection.java | 8 ++++---- .../java/org/eclipse/jetty/spdy/SPDYServerConnector.java | 6 +++--- 9 files changed, 28 insertions(+), 27 deletions(-) diff --git a/jetty-spdy/spdy-core/pom.xml b/jetty-spdy/spdy-core/pom.xml index 058434a1491..cfd2edf9293 100644 --- a/jetty-spdy/spdy-core/pom.xml +++ b/jetty-spdy/spdy-core/pom.xml @@ -12,8 +12,9 @@ - org.slf4j - slf4j-api + org.eclipse.jetty + jetty-util + ${project.version} junit diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java index dae08a4c4cd..4caa3df86c4 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java @@ -61,12 +61,12 @@ import org.eclipse.jetty.spdy.frames.SynStreamFrame; import org.eclipse.jetty.spdy.frames.WindowUpdateFrame; import org.eclipse.jetty.spdy.generator.Generator; import org.eclipse.jetty.spdy.parser.Parser; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; public class StandardSession implements ISession, Parser.Listener, Handler { - private static final Logger logger = LoggerFactory.getLogger(Session.class); + private static final Logger logger = Log.getLogger(Session.class); private static final ThreadLocal handlerInvocations = new ThreadLocal() { @Override diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java index 758858d5690..d1fccff757c 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java @@ -39,12 +39,12 @@ 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; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; public class StandardStream implements IStream { - private static final Logger logger = LoggerFactory.getLogger(Stream.class); + private static final Logger logger = Log.getLogger(Stream.class); private final Map attributes = new ConcurrentHashMap<>(); private final SynStreamFrame frame; private final ISession session; diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java index f1d9d2c66a6..467919c29cf 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java @@ -18,8 +18,8 @@ package org.eclipse.jetty.spdy.api; import java.util.EventListener; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; /** *

A {@link SessionFrameListener} is the passive counterpart of a {@link Session} and receives events happening @@ -122,7 +122,7 @@ public interface SessionFrameListener extends EventListener */ public static class Adapter implements SessionFrameListener { - private static final Logger logger = LoggerFactory.getLogger(Adapter.class); + private static final Logger logger = Log.getLogger(Adapter.class); @Override public StreamFrameListener onSyn(Stream stream, SynInfo synInfo) diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java index 58cb61d1c34..8cc42e18144 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java @@ -27,12 +27,12 @@ import org.eclipse.jetty.spdy.StreamException; import org.eclipse.jetty.spdy.api.SessionStatus; import org.eclipse.jetty.spdy.frames.ControlFrame; import org.eclipse.jetty.spdy.frames.DataFrame; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; public class Parser { - private static final Logger logger = LoggerFactory.getLogger(Parser.class); + private static final Logger logger = Log.getLogger(Parser.class); private final List listeners = new CopyOnWriteArrayList<>(); private final ControlFrameParser controlFrameParser; private final DataFrameParser dataFrameParser; diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java index f782d656467..2882bc43461 100644 --- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java +++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java @@ -50,12 +50,12 @@ import org.eclipse.jetty.spdy.api.DataInfo; import org.eclipse.jetty.spdy.api.Headers; import org.eclipse.jetty.spdy.api.ReplyInfo; import org.eclipse.jetty.spdy.api.Stream; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implements AsyncConnection { - private static final Logger logger = LoggerFactory.getLogger(ServerHTTPSPDYAsyncConnection.class); + private static final Logger logger = Log.getLogger(ServerHTTPSPDYAsyncConnection.class); private static final ByteBuffer ZERO_BYTES = ByteBuffer.allocate(0); private static final DataInfo END_OF_CONTENT = new ByteBufferDataInfo(ZERO_BYTES, true); diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java index 30a10a61c79..93fff9c8467 100644 --- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java +++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java @@ -33,13 +33,13 @@ 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.api.server.ServerSessionFrameListener; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; public class ServerHTTPSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnectionFactory { private static final String CONNECTION_ATTRIBUTE = "org.eclipse.jetty.spdy.http.connection"; - private static final Logger logger = LoggerFactory.getLogger(ServerHTTPSPDYAsyncConnectionFactory.class); + private static final Logger logger = Log.getLogger(ServerHTTPSPDYAsyncConnectionFactory.class); private final Connector connector; diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYAsyncConnection.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYAsyncConnection.java index 3ae8ccaef46..40dfecde36b 100644 --- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYAsyncConnection.java +++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYAsyncConnection.java @@ -30,12 +30,12 @@ import org.eclipse.jetty.io.nio.NIOBuffer; import org.eclipse.jetty.spdy.api.Handler; import org.eclipse.jetty.spdy.api.Session; import org.eclipse.jetty.spdy.parser.Parser; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; public class SPDYAsyncConnection extends AbstractConnection implements AsyncConnection, Controller, IdleListener { - private static final Logger logger = LoggerFactory.getLogger(SPDYAsyncConnection.class); + private static final Logger logger = Log.getLogger(SPDYAsyncConnection.class); private final ByteBufferPool bufferPool; private final Parser parser; private volatile Session session; @@ -181,7 +181,7 @@ public class SPDYAsyncConnection extends AbstractConnection implements AsyncConn } catch (IOException x) { - logger.trace("", x); + logger.ignore(x); } } diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYServerConnector.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYServerConnector.java index 2a496070f96..41412b3f0c5 100644 --- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYServerConnector.java +++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYServerConnector.java @@ -41,14 +41,14 @@ import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.spdy.api.SPDY; import org.eclipse.jetty.spdy.api.Session; import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.ThreadPool; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class SPDYServerConnector extends SelectChannelConnector { - private static final Logger logger = LoggerFactory.getLogger(SPDYServerConnector.class); + private static final Logger logger = Log.getLogger(SPDYServerConnector.class); // Order is important on server side, so we use a LinkedHashMap private final Map factories = new LinkedHashMap<>(); From 6ec159401010469008ca58ba5b04d2ed3ad55213 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Thu, 5 Apr 2012 17:33:48 +0200 Subject: [PATCH 25/36] Updated path location of the jetty config file for SPDY. --- jetty-spdy/spdy-jetty-http-webapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-spdy/spdy-jetty-http-webapp/pom.xml b/jetty-spdy/spdy-jetty-http-webapp/pom.xml index 68b571f5925..3c2c370cb9c 100644 --- a/jetty-spdy/spdy-jetty-http-webapp/pom.xml +++ b/jetty-spdy/spdy-jetty-http-webapp/pom.xml @@ -42,7 +42,7 @@ -Dlog4j.configuration=file://${basedir}/src/main/resources/log4j.properties -Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${project.version}/npn-boot-${project.version}.jar - ${basedir}/src/main/config/jetty-spdy.xml + ${basedir}/src/main/config/etc/jetty-spdy.xml / From 9dfa9f9937baa85c26f475b60b554f1ba6398679 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 10 Apr 2012 14:21:07 +1000 Subject: [PATCH 26/36] 370081: correctly set URI for query strings --- .../rewrite/handler/RegexTargetHandler.java | 149 ------------ .../rewrite/handler/RewriteRegexRule.java | 19 +- .../handler/RegexTargetHandlerTest.java | 214 ------------------ .../rewrite/handler/RewriteRegexRuleTest.java | 29 ++- .../java/org/eclipse/jetty/util/MultiMap.java | 20 +- 5 files changed, 56 insertions(+), 375 deletions(-) delete mode 100644 jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RegexTargetHandler.java delete mode 100644 jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RegexTargetHandlerTest.java diff --git a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RegexTargetHandler.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RegexTargetHandler.java deleted file mode 100644 index 736f8245f9f..00000000000 --- a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RegexTargetHandler.java +++ /dev/null @@ -1,149 +0,0 @@ -package org.eclipse.jetty.rewrite.handler; - -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.eclipse.jetty.server.Request; -import org.eclipse.jetty.server.handler.ContextHandler; -import org.eclipse.jetty.server.handler.ContextHandler.Context; -import org.eclipse.jetty.server.handler.ScopedHandler; -import org.eclipse.jetty.util.component.AggregateLifeCycle; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; - - -/* ------------------------------------------------------------ */ -/** A handle that uses regular expressions to select the target. - *

- * This handler applies a list of regex to target name mappings to the URIs of requests. - * If the regex matches the URI, then the mapped target name is used in the nested - * call to {@link #doScope(String, Request, HttpServletRequest, HttpServletResponse)}. - *

- * This handler should be installed as the first handler in a Context. It can be configured - * either with direct calls to {@link #addPatternTarget(String, String)} or by setting - * the context init parameters "org.eclipse.jetty.rewrite.handler.REGEX_MAPPINGS" to a comma - * separated list of strings in the format regex==target. - */ -public class RegexTargetHandler extends ScopedHandler -{ - private final static Logger LOG = Log.getLogger(RegexTargetHandler.class); - public final static String REGEX_MAPPINGS="org.eclipse.jetty.rewrite.handler.REGEX_MAPPINGS"; - static class RegexMapping - { - RegexMapping(String regex,String target) - { - _pattern=Pattern.compile(regex); - _target=target; - } - final Pattern _pattern; - final String _target; - - public String toString() - { - return _pattern+"=="+_target; - } - } - - final private List _patterns = new CopyOnWriteArrayList(); - - /* ------------------------------------------------------------ */ - /** Add a pattern to target mapping. - * @param pattern The regular expression pattern to match. - * @param target The target (normally servlet name) to handle the request - */ - public void addPatternTarget(String pattern,String target) - { - _patterns.add(new RegexMapping(pattern,target)); - } - - /* ------------------------------------------------------------ */ - @Override - protected void doStart() throws Exception - { - super.doStart(); - - Context context = ContextHandler.getCurrentContext(); - if (context!=null) - { - String config=context.getInitParameter(REGEX_MAPPINGS); - LOG.debug("{}={}",REGEX_MAPPINGS,config); - String[] mappings=config.split("\\s*,\\s*"); - for (String mapping : mappings) - { - mapping=mapping.trim(); - String[] parts=mapping.split("\\s*==\\s*"); - if (parts.length==2) - { - String pattern=parts[0]; - String target=parts[1]; - addPatternTarget(pattern,target); - } - else - LOG.warn("Bad regex mapping: "+mapping); - } - } - } - - /* ------------------------------------------------------------ */ - @Override - public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException - { - for (RegexTargetHandler.RegexMapping rm : _patterns) - { - Matcher m=rm._pattern.matcher(target); - if (m.matches()) - { - String new_target = rm._target; - final String sp; - final String pi; - - if (m.groupCount()==1&&target.endsWith(m.group(1))) - { - pi=m.group(1); - sp=target.substring(0,target.length()-pi.length()); - } - else - { - sp=target; - pi=null; - } - baseRequest.setServletPath(sp); - baseRequest.setPathInfo(pi); - baseRequest.setAttribute("org.eclipse.jetty.servlet.REGEX_PATH",target); - super.nextScope(new_target,baseRequest,request,response); - return; - } - } - super.nextScope(target,baseRequest,request,response); - } - - /* ------------------------------------------------------------ */ - @Override - public void doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException - { - String path=(String)baseRequest.getAttribute("org.eclipse.jetty.servlet.REGEX_PATH"); - if (path==null) - path=target; - else - baseRequest.setAttribute("org.eclipse.jetty.servlet.REGEX_PATH",null); - - super.nextHandle(path,baseRequest,request,response); - } - - /* ------------------------------------------------------------ */ - public void dump(Appendable out, String indent) throws IOException - { - AggregateLifeCycle.dumpObject(out,this); - AggregateLifeCycle.dump(out,indent,_patterns,Collections.singletonList(getHandler())); - } - - -} \ No newline at end of file diff --git a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRule.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRule.java index 49a27dcee30..6fa22b52238 100644 --- a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRule.java +++ b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRule.java @@ -18,6 +18,7 @@ import java.util.regex.Matcher; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.server.Request; /** @@ -89,14 +90,20 @@ public class RewriteRegexRule extends RegexRule implements Rule.ApplyURI /* ------------------------------------------------------------ */ public void applyURI(Request request, String oldTarget, String newTarget) throws IOException { - request.setRequestURI(newTarget); - if (_query!=null) + if (_query==null) + { + request.setRequestURI(newTarget); + } + else { String query=(String)request.getAttribute("org.eclipse.jetty.rewrite.handler.RewriteRegexRule.Q"); - if (_queryGroup||request.getQueryString()==null) - request.setQueryString(query); - else - request.setQueryString(request.getQueryString()+"&"+query); + + if (!_queryGroup && request.getQueryString()!=null) + query=request.getQueryString()+"&"+query; + HttpURI uri=new HttpURI(newTarget+"?"+query); + request.setUri(uri); + request.setRequestURI(newTarget); + request.setQueryString(query); } } diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RegexTargetHandlerTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RegexTargetHandlerTest.java deleted file mode 100644 index c47937621df..00000000000 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RegexTargetHandlerTest.java +++ /dev/null @@ -1,214 +0,0 @@ -// ======================================================================== -// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== - -package org.eclipse.jetty.rewrite.handler; - -import static junit.framework.Assert.assertEquals; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.net.Socket; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import javax.servlet.RequestDispatcher; -import javax.servlet.Servlet; -import javax.servlet.ServletException; -import javax.servlet.ServletRequestWrapper; -import javax.servlet.ServletResponseWrapper; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletResponseWrapper; - -import junit.framework.Assert; - -import org.eclipse.jetty.rewrite.handler.RegexTargetHandler; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -public class RegexTargetHandlerTest -{ - private static Server __server = new Server(0); - private static int __port; - - @BeforeClass - public static void setup() throws Exception - { - - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/"); - __server.setHandler(context); - - // Serve some hello world servlets - context.addServlet(DispatchServletServlet.class,"/dispatch/*"); - context.addServlet(new ServletHolder("HelloAll",new HelloServlet("Hello World")),"/*"); - context.addServlet(new ServletHolder("Italian",new HelloServlet("Buongiorno Mondo")),"/it/*"); - context.addServlet(new ServletHolder("French", new HelloServlet("Bonjour le Monde")),"/fr/*"); - - RegexTargetHandler regexHandler=new RegexTargetHandler(); - regexHandler.setHandler(context.getHandler()); - context.setHandler(regexHandler); - - context.getInitParams().put(RegexTargetHandler.REGEX_MAPPINGS, - " .*\\.fr==French, \n"+ - "/ciao(/.*)$==Italian"); - - __server.start(); - - __port=__server.getConnectors()[0].getLocalPort(); - } - - @AfterClass - public static void shutdown() throws Exception - { - __server.stop(); - } - - - @Test - public void testNormal() throws Exception - { - String[] response=getResponse("/normal"); - assertEquals("HTTP/1.1 200 OK",response[0]); - assertEquals("Hello World",response[1]); - assertEquals("",response[2]); - assertEquals("/normal",response[3]); - - response=getResponse("/it/info"); - assertEquals("HTTP/1.1 200 OK",response[0]); - assertEquals("Buongiorno Mondo",response[1]); - assertEquals("/it",response[2]); - assertEquals("/info",response[3]); - } - - @Test - public void testFullMatch() throws Exception - { - String[] response=getResponse("/some/thing.fr"); - assertEquals("HTTP/1.1 200 OK",response[0]); - assertEquals("Bonjour le Monde",response[1]); - assertEquals("/some/thing.fr",response[2]); - assertEquals("null",response[3]); - } - - @Test - public void testCaptureMatch() throws Exception - { - String[] response=getResponse("/ciao/info"); - assertEquals("HTTP/1.1 200 OK",response[0]); - assertEquals("Buongiorno Mondo",response[1]); - assertEquals("/ciao",response[2]); - assertEquals("/info",response[3]); - } - - @Test - public void testDispatchFullMatch() throws Exception - { - String[] response=getResponse("/dispatch/xxx?forward=/some/thing.fr"); - assertEquals("HTTP/1.1 200 OK",response[0]); - assertEquals("Bonjour le Monde",response[1]); - assertEquals("/some/thing.fr",response[2]); - assertEquals("null",response[3]); - } - - @Test - public void testDispatchCaptureMatch() throws Exception - { - String[] response=getResponse("/dispatch/xxx?forward=/ciao/info"); - assertEquals("HTTP/1.1 200 OK",response[0]); - assertEquals("Buongiorno Mondo",response[1]); - assertEquals("/ciao",response[2]); - assertEquals("/info",response[3]); - } - - - private String[] getResponse(String uri) throws Exception - { - Socket socket = new Socket("127.0.0.1",__port); - - PrintWriter out = new PrintWriter(socket.getOutputStream()); - out.print("GET "+uri+" HTTP/1.0\r\n\r\n"); - out.flush(); - - BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); - - String[] response=new String[4]; - response[0]=in.readLine(); - //System.err.println(response[0]); - - String line=in.readLine(); - while(line.length()>0) - line=in.readLine(); - - response[1]=in.readLine(); - //System.err.println(response[1]); - response[2]=in.readLine(); - //System.err.println(response[2]); - response[3]=in.readLine(); - //System.err.println(response[3]); - - socket.close(); - return response; - } - - - public static class HelloServlet extends HttpServlet implements Servlet - { - final String _hello; - - public HelloServlet(String hello) - { - _hello=hello; - } - - @Override - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException - { - response.setStatus(200); - response.getWriter().println(_hello); - response.getWriter().println(request.getServletPath()); - response.getWriter().println(request.getPathInfo()); - } - } - - - public static class DispatchServletServlet extends HttpServlet implements Servlet - { - @Override - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException - { - RequestDispatcher dispatcher = null; - - if(request.getParameter("include")!=null) - { - dispatcher = getServletContext().getRequestDispatcher(request.getParameter("include")); - dispatcher.include(new HttpServletRequestWrapper(request), new HttpServletResponseWrapper(response)); - } - else if(request.getParameter("forward")!=null) - { - dispatcher = getServletContext().getRequestDispatcher(request.getParameter("forward")); - dispatcher.forward(new HttpServletRequestWrapper(request), new HttpServletResponseWrapper(response)); - } - - } - } -} diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java index 872bb6e5b85..a804db70c31 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java @@ -14,6 +14,10 @@ package org.eclipse.jetty.rewrite.handler; import java.io.IOException; +import org.eclipse.jetty.http.HttpURI; +import org.eclipse.jetty.util.MultiMap; +import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.UrlEncoded; import org.junit.Before; import org.junit.Test; @@ -53,20 +57,35 @@ public class RewriteRegexRuleTest extends AbstractRuleTestCase { for (String[] test : _tests) { + reset(); + _request.setRequestURI(null); + String t=test[0]+"?"+test[1]+">"+test[2]+"|"+test[3]; _rule.setRegex(test[2]); _rule.setReplacement(test[3]); - _request.setRequestURI(test[0]); - _request.setQueryString(test[1]); - _request.getAttributes().clearAttributes(); + _request.setUri(new HttpURI(test[0]+(test[1]==null?"":("?"+test[1])))); + _request.getRequestURI(); + String result = _rule.matchAndApply(test[0], _request, _response); assertEquals(t, test[4], result); _rule.applyURI(_request,test[0],result); - assertEquals(t,test[4], _request.getRequestURI()); - assertEquals(t,test[5], _request.getQueryString()); + if (result!=null) + { + assertEquals(t,test[4], _request.getRequestURI()); + assertEquals(t,test[5], _request.getQueryString()); + } + + if (test[5]!=null) + { + MultiMap params=new MultiMap(); + UrlEncoded.decodeTo(test[5],params,StringUtil.__UTF8); + + for (String n:params.keySet()) + assertEquals(params.getString(n),_request.getParameter(n)); + } } } diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/MultiMap.java b/jetty-util/src/main/java/org/eclipse/jetty/util/MultiMap.java index 61f9eeaec91..2d0840da004 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/MultiMap.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/MultiMap.java @@ -287,7 +287,25 @@ public class MultiMap implements ConcurrentMap, Serializable */ public Map toStringArrayMap() { - HashMap map = new HashMap(_map.size()*3/2); + HashMap map = new HashMap(_map.size()*3/2) + { + public String toString() + { + StringBuilder b=new StringBuilder(); + b.append('{'); + for (K k:keySet()) + { + if(b.length()>1) + b.append(','); + b.append(k); + b.append('='); + b.append(Arrays.asList(get(k))); + } + + b.append('}'); + return b.toString(); + } + }; for(Map.Entry entry: _map.entrySet()) { From f81ea123202a1e96c0738184e101b41dfa1347be Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Wed, 11 Apr 2012 12:37:51 +1000 Subject: [PATCH 27/36] 375709 Ensure resolveTempDirectory failure does not deadlock; improve error message --- .../java/org/eclipse/jetty/webapp/WebInfConfiguration.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java index d7748365c8e..fc9f3734c02 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java @@ -305,7 +305,8 @@ public class WebInfConfiguration extends AbstractConfiguration } catch(IOException e) { - LOG.warn("tmpdir",e); System.exit(1); + tmpDir = null; + throw new IllegalStateException("Cannot create tmp dir in "+System.getProperty("java.io.tmpdir")+ " for context "+context,e); } } } From 4412d311a9a440572fd15663cc00392754467b79 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 11 Apr 2012 17:21:02 +1000 Subject: [PATCH 28/36] 370081:fixed test reset --- .../rewrite/handler/RewriteRegexRuleTest.java | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java index a804db70c31..adb8777f12f 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java @@ -27,21 +27,21 @@ public class RewriteRegexRuleTest extends AbstractRuleTestCase { private String[][] _tests= { - {"/foo/bar",null,".*","/replace","/replace",null}, - {"/foo/bar","n=v",".*","/replace","/replace","n=v"}, - {"/foo/bar",null,"/xxx.*","/replace",null,null}, - {"/foo/bar",null,"/(.*)/(.*)","/$2/$1/xxx","/bar/foo/xxx",null}, - {"/foo/bar",null,"/(.*)/(.*)","/test?p2=$2&p1=$1","/test","p2=bar&p1=foo"}, - {"/foo/bar","n=v","/(.*)/(.*)","/test?p2=$2&p1=$1","/test","n=v&p2=bar&p1=foo"}, - {"/foo/bar",null,"/(.*)/(.*)","/foo/bar?p2=$2&p1=$1","/foo/bar","p2=bar&p1=foo"}, - {"/foo/bar","n=v","/(.*)/(.*)","/foo/bar?p2=$2&p1=$1","/foo/bar","n=v&p2=bar&p1=foo"}, - {"/foo/bar",null,"/(foo)/(.*)(bar)","/$3/$1/xxx$2","/bar/foo/xxx",null}, - {"/foo/$bar",null,".*","/$replace","/$replace",null}, - {"/foo/$bar",null,"/foo/(.*)","/$1/replace","/$bar/replace",null}, - {"/foo/bar/info",null,"/foo/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2","/info/other","p1=bar"}, - {"/foo/bar/info",null,"/foo/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2&$Q","/info/other","p1=bar&"}, - {"/foo/bar/info","n=v","/foo/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2&$Q","/info/other","p1=bar&n=v"}, - {"/foo/bar/info","n=v","/foo/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2","/info/other","n=v&p1=bar"}, + {"/foo0/bar",null,".*","/replace","/replace",null}, + {"/foo1/bar","n=v",".*","/replace","/replace","n=v"}, + {"/foo2/bar",null,"/xxx.*","/replace",null,null}, + {"/foo3/bar",null,"/(.*)/(.*)","/$2/$1/xxx","/bar/foo3/xxx",null}, + {"/foo4/bar",null,"/(.*)/(.*)","/test?p2=$2&p1=$1","/test","p2=bar&p1=foo4"}, + {"/foo5/bar","n=v","/(.*)/(.*)","/test?p2=$2&p1=$1","/test","n=v&p2=bar&p1=foo5"}, + {"/foo6/bar",null,"/(.*)/(.*)","/foo6/bar?p2=$2&p1=$1","/foo6/bar","p2=bar&p1=foo6"}, + {"/foo7/bar","n=v","/(.*)/(.*)","/foo7/bar?p2=$2&p1=$1","/foo7/bar","n=v&p2=bar&p1=foo7"}, + {"/foo8/bar",null,"/(foo8)/(.*)(bar)","/$3/$1/xxx$2","/bar/foo8/xxx",null}, + {"/foo9/$bar",null,".*","/$replace","/$replace",null}, + {"/fooA/$bar",null,"/fooA/(.*)","/$1/replace","/$bar/replace",null}, + {"/fooB/bar/info",null,"/fooB/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2","/info/other","p1=bar"}, + {"/fooC/bar/info",null,"/fooC/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2&$Q","/info/other","p1=bar&"}, + {"/fooD/bar/info","n=v","/fooD/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2&$Q","/info/other","p1=bar&n=v"}, + {"/fooE/bar/info","n=v","/fooE/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2","/info/other","n=v&p1=bar"}, }; private RewriteRegexRule _rule; @@ -97,6 +97,7 @@ public class RewriteRegexRuleTest extends AbstractRuleTestCase container.addRule(_rule); for (String[] test : _tests) { + reset(); String t=test[0]+"?"+test[1]+">"+test[2]+"|"+test[3]; _rule.setRegex(test[2]); _rule.setReplacement(test[3]); From 20a3d3c12ec8f4cb5f30747304f1ff7d4eaf1be8 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 11 Apr 2012 18:21:39 +1000 Subject: [PATCH 29/36] 376424: do not recycle buffers before content consumed asynchronously --- .../src/main/java/org/eclipse/jetty/http/HttpParser.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java index c7d7d39f88a..0b4053c15e3 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java @@ -260,7 +260,6 @@ public class HttpParser implements Parser { _state=STATE_END; _handler.messageComplete(_contentPosition); - returnBuffers(); return 1; } @@ -326,7 +325,6 @@ public class HttpParser implements Parser if (!isComplete() && !isIdle()) throw new EofException(); - returnBuffers(); return -1; } length=_buffer.length(); @@ -440,7 +438,6 @@ public class HttpParser implements Parser _state=STATE_SEEKING_EOF; _handler.headerComplete(); _handler.messageComplete(_contentPosition); - returnBuffers(); return 1; } break; @@ -470,7 +467,6 @@ public class HttpParser implements Parser _state=STATE_SEEKING_EOF; _handler.headerComplete(); _handler.messageComplete(_contentPosition); - returnBuffers(); return 1; } } @@ -634,7 +630,6 @@ public class HttpParser implements Parser _handler.headerComplete(); _state=_persistent||(_responseStatus>=100&&_responseStatus<200)?STATE_END:STATE_SEEKING_EOF; _handler.messageComplete(_contentPosition); - returnBuffers(); return 1; default: @@ -840,7 +835,6 @@ public class HttpParser implements Parser { _state=_persistent?STATE_END:STATE_SEEKING_EOF; _handler.messageComplete(_contentPosition); - returnBuffers(); return 1; } @@ -860,7 +854,6 @@ public class HttpParser implements Parser { _state=_persistent?STATE_END:STATE_SEEKING_EOF; _handler.messageComplete(_contentPosition); - returnBuffers(); } // TODO adjust the _buffer to keep unconsumed content return 1; @@ -895,7 +888,6 @@ public class HttpParser implements Parser _eol=_buffer.get(); _state=_persistent?STATE_END:STATE_SEEKING_EOF; _handler.messageComplete(_contentPosition); - returnBuffers(); return 1; } else @@ -926,7 +918,6 @@ public class HttpParser implements Parser _eol=_buffer.get(); _state=_persistent?STATE_END:STATE_SEEKING_EOF; _handler.messageComplete(_contentPosition); - returnBuffers(); return 1; } else From 47c1587166a7951343a20c248da5b074dd70699c Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Wed, 11 Apr 2012 10:39:23 +0200 Subject: [PATCH 30/36] Strengthen the behavior of Stream methods to throw if they are used wrongly, for example sending DATA frames before a REPLY and so on. --- .../eclipse/jetty/spdy/StandardStream.java | 38 ++++++- .../org/eclipse/jetty/spdy/APIUsageTest.java | 98 +++++++++++++++++++ .../org/eclipse/jetty/spdy/SynReplyTest.java | 35 ------- 3 files changed, 132 insertions(+), 39 deletions(-) create mode 100644 jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/APIUsageTest.java diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java index d1fccff757c..013159d7d90 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java @@ -50,7 +50,7 @@ public class StandardStream implements IStream private final ISession session; private final AtomicInteger windowSize; private volatile StreamFrameListener listener; - private volatile boolean opened; + private volatile OpenState openState = OpenState.SYN_SENT; private volatile boolean halfClosed; private volatile boolean closed; @@ -141,12 +141,12 @@ public class StandardStream implements IStream { case SYN_STREAM: { - opened = true; + openState = OpenState.SYN_RECV; break; } case SYN_REPLY: { - opened = true; + openState = OpenState.REPLY_RECV; SynReplyFrame synReply = (SynReplyFrame)frame; updateCloseState(synReply.isClose()); ReplyInfo replyInfo = new ReplyInfo(synReply.getHeaders(), synReply.isClose()); @@ -183,7 +183,7 @@ public class StandardStream implements IStream @Override public void process(DataFrame frame, ByteBuffer data) { - if (!opened) + if (!canReceive()) { session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR)); return; @@ -286,6 +286,7 @@ public class StandardStream implements IStream @Override public void reply(ReplyInfo replyInfo, long timeout, TimeUnit unit, Handler handler) { + openState = OpenState.REPLY_SENT; updateCloseState(replyInfo.isClose()); SynReplyFrame frame = new SynReplyFrame(session.getVersion(), replyInfo.getFlags(), getId(), replyInfo.getHeaders()); session.control(this, frame, timeout, unit, handler, null); @@ -302,6 +303,12 @@ public class StandardStream implements IStream @Override public void data(DataInfo dataInfo, long timeout, TimeUnit unit, Handler handler) { + if (!canSend()) + { + session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR)); + throw new IllegalStateException("Cannot send DATA frames before a SYN_REPLY frame"); + } + // 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); @@ -318,6 +325,12 @@ public class StandardStream implements IStream @Override public void headers(HeadersInfo headersInfo, long timeout, TimeUnit unit, Handler handler) { + if (!canSend()) + { + session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR)); + throw new IllegalStateException("Cannot send a HEADERS frame before a SYN_REPLY frame"); + } + updateCloseState(headersInfo.isClose()); HeadersFrame frame = new HeadersFrame(session.getVersion(), headersInfo.getFlags(), getId(), headersInfo.getHeaders()); session.control(this, frame, timeout, unit, handler, null); @@ -334,4 +347,21 @@ public class StandardStream implements IStream { return String.format("stream=%d v%d closed=%s", getId(), session.getVersion(), isClosed() ? "true" : isHalfClosed() ? "half" : "false"); } + + private boolean canSend() + { + OpenState openState = this.openState; + return openState == OpenState.SYN_SENT || openState == OpenState.REPLY_RECV || openState == OpenState.REPLY_SENT; + } + + private boolean canReceive() + { + OpenState openState = this.openState; + return openState == OpenState.SYN_RECV || openState == OpenState.REPLY_RECV || openState == OpenState.REPLY_SENT; + } + + private enum OpenState + { + SYN_SENT, SYN_RECV, REPLY_SENT, REPLY_RECV + } } diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/APIUsageTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/APIUsageTest.java new file mode 100644 index 00000000000..36a0a2cb7bf --- /dev/null +++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/APIUsageTest.java @@ -0,0 +1,98 @@ +package org.eclipse.jetty.spdy; + +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jetty.spdy.api.BytesDataInfo; +import org.eclipse.jetty.spdy.api.RstInfo; +import org.eclipse.jetty.spdy.api.SPDY; +import org.eclipse.jetty.spdy.api.Session; +import org.eclipse.jetty.spdy.api.SessionFrameListener; +import org.eclipse.jetty.spdy.api.SessionStatus; +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.api.StringDataInfo; +import org.eclipse.jetty.spdy.api.SynInfo; +import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener; +import org.eclipse.jetty.spdy.frames.ControlFrameType; +import org.eclipse.jetty.spdy.frames.GoAwayFrame; +import org.eclipse.jetty.spdy.generator.Generator; +import org.junit.Assert; +import org.junit.Test; + +public class APIUsageTest extends AbstractTest +{ + @Test + public void testSendDataBeforeReplyIsIllegal() throws Exception + { + final CountDownLatch resetLatch = new CountDownLatch(1); + final CountDownLatch latch = new CountDownLatch(1); + Session session = startClient(startServer(new ServerSessionFrameListener.Adapter() + { + @Override + public StreamFrameListener onSyn(Stream stream, SynInfo synInfo) + { + try + { + stream.data(new StringDataInfo("failure", true)); + return null; + } + catch (IllegalStateException x) + { + latch.countDown(); + return null; + } + } + }), new SessionFrameListener.Adapter() + { + @Override + public void onRst(Session session, RstInfo rstInfo) + { + Assert.assertSame(StreamStatus.PROTOCOL_ERROR, rstInfo.getStreamStatus()); + resetLatch.countDown(); + } + }); + session.syn(new SynInfo(true), null); + Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); + Assert.assertTrue(resetLatch.await(5, TimeUnit.SECONDS)); + } + + @Test + public void testReceiveDataBeforeReplyIsIllegal() throws Exception + { + ServerSocketChannel server = ServerSocketChannel.open(); + server.bind(new InetSocketAddress("localhost", 0)); + + Session session = startClient(new InetSocketAddress("localhost", server.socket().getLocalPort()), null); + session.syn(new SynInfo(true), null); + + SocketChannel channel = server.accept(); + ByteBuffer readBuffer = ByteBuffer.allocate(1024); + channel.read(readBuffer); + readBuffer.flip(); + int streamId = readBuffer.getInt(8); + + Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory.StandardCompressor()); + byte[] bytes = new byte[1]; + ByteBuffer writeBuffer = generator.data(streamId, bytes.length, new BytesDataInfo(bytes, true)); + channel.write(writeBuffer); + + readBuffer.clear(); + channel.read(readBuffer); + readBuffer.flip(); + Assert.assertEquals(ControlFrameType.RST_STREAM.getCode(), readBuffer.getShort(2)); + Assert.assertEquals(streamId, readBuffer.getInt(8)); + + writeBuffer = generator.control(new GoAwayFrame(SPDY.V2, 0, SessionStatus.OK.getCode())); + channel.write(writeBuffer); + channel.shutdownOutput(); + channel.close(); + + server.close(); + } +} diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SynReplyTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SynReplyTest.java index 7e5d67fdd2f..207e1335b03 100644 --- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SynReplyTest.java +++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SynReplyTest.java @@ -30,12 +30,10 @@ import org.eclipse.jetty.spdy.api.DataInfo; import org.eclipse.jetty.spdy.api.Handler; import org.eclipse.jetty.spdy.api.Headers; 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.SessionFrameListener; 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.api.StringDataInfo; import org.eclipse.jetty.spdy.api.SynInfo; import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener; @@ -324,39 +322,6 @@ public class SynReplyTest extends AbstractTest Assert.assertTrue(clientDataLatch.await(5, TimeUnit.SECONDS)); } - @Test - public void testSynDataRst() throws Exception - { - final AtomicReference ref = new AtomicReference<>(); - final CountDownLatch latch = new CountDownLatch(1); - ServerSessionFrameListener serverSessionFrameListener = new ServerSessionFrameListener.Adapter() - { - @Override - public StreamFrameListener onSyn(Stream stream, SynInfo synInfo) - { - // Do not send the reply, we expect a RST_STREAM - stream.data(new StringDataInfo("foo", true)); - return null; - } - - @Override - public void onRst(Session session, RstInfo rstInfo) - { - ref.set(rstInfo); - latch.countDown(); - } - }; - Session session = startClient(startServer(serverSessionFrameListener), null); - - Stream stream = session.syn(new SynInfo(true), null).get(5, TimeUnit.SECONDS); - - Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); - RstInfo rstInfo = ref.get(); - Assert.assertNotNull(rstInfo); - Assert.assertEquals(stream.getId(), rstInfo.getStreamId()); - Assert.assertSame(StreamStatus.PROTOCOL_ERROR, rstInfo.getStreamStatus()); - } - @Test public void testSynReplyDataSynReplyData() throws Exception { From 5b7fe58593b3250b4f70ea6bc6c9d51a35c9b635 Mon Sep 17 00:00:00 2001 From: Thomas Becker Date: Wed, 11 Apr 2012 10:55:32 +0200 Subject: [PATCH 31/36] 376373: GzipFilter now does not ignore _excludePath + fix for ignored _excludeAgentPatterns if _excludeAgent is set Change-Id: I1f0ac1b5a12d75b755a85cc9bdb4906c6b7a84a6 --- .../eclipse/jetty/servlets/GzipFilter.java | 12 +++- .../jetty/servlets/GzipFilterDefaultTest.java | 70 +++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java index 1b993e6eedf..4428ec1e862 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java @@ -238,7 +238,7 @@ public class GzipFilter extends UserAgentFilter return true; } } - else if (_excludedAgentPatterns != null) + if (_excludedAgentPatterns != null) { for (Pattern pattern : _excludedAgentPatterns) { @@ -263,6 +263,16 @@ public class GzipFilter extends UserAgentFilter { if (requestURI == null) return false; + if (_excludedPaths != null) + { + for (String excludedPath : _excludedPaths) + { + if (requestURI.contains(excludedPath)) + { + return true; + } + } + } if (_excludedPathPatterns != null) { for (Pattern pattern : _excludedPathPatterns) diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java index 82fd54dc11f..b9f7081d138 100644 --- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java +++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java @@ -25,6 +25,8 @@ public class GzipFilterDefaultTest public static class HttpStatusServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + private int _status = 204; public HttpStatusServlet() @@ -159,4 +161,72 @@ public class GzipFilterDefaultTest tester.stop(); } } + + @Test + public void testUserAgentExclusionByExcludedAgentPatterns() throws Exception + { + GzipTester tester = new GzipTester(testingdir); + + FilterHolder holder = tester.setContentServlet(DefaultServlet.class); + holder.setInitParameter("excludedAgents", "bar"); + holder.setInitParameter("excludeAgentPatterns", "fo.*"); + 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(); + } + } + + @Test + public void testExcludePaths() throws Exception + { + GzipTester tester = new GzipTester(testingdir); + + FilterHolder holder = tester.setContentServlet(DefaultServlet.class); + holder.setInitParameter("excludePaths", "/context/"); + + 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(); + } + } + + @Test + public void testExcludePathPatterns() throws Exception + { + GzipTester tester = new GzipTester(testingdir); + + FilterHolder holder = tester.setContentServlet(DefaultServlet.class); + holder.setInitParameter("excludePathPatterns", "/cont.*"); + + 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(); + } + } } From 942c8a19f56d31a9f7305b31ca3bd714518723b7 Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Wed, 11 Apr 2012 19:53:55 +1000 Subject: [PATCH 32/36] 373269 Make ServletHandler.notFound() method impl do nothing - override to send back 404. --- .../src/main/java/org/eclipse/jetty/servlet/ServletHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java index b9e2c24e58f..76f360592ad 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java @@ -1233,7 +1233,7 @@ public class ServletHandler extends ScopedHandler { if(LOG.isDebugEnabled()) LOG.debug("Not Found "+request.getRequestURI()); - response.sendError(HttpServletResponse.SC_NOT_FOUND); + //Override to send an error back, eg with: response.sendError(HttpServletResponse.SC_NOT_FOUND); } /* ------------------------------------------------------------ */ From 972087d0684fa46341e7c6ef32dcd95c407400c1 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Wed, 11 Apr 2012 12:18:56 +0200 Subject: [PATCH 33/36] 376201 - HalfClosed state not handled properly. --- .../java/org/eclipse/jetty/spdy/IStream.java | 3 +- .../eclipse/jetty/spdy/StandardSession.java | 11 ++- .../eclipse/jetty/spdy/StandardStream.java | 80 ++++++++++++++----- .../eclipse/jetty/spdy/FlowControlTest.java | 2 +- ...eTest.java => ProtocolViolationsTest.java} | 68 +++++++++++++++- 5 files changed, 141 insertions(+), 23 deletions(-) rename jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/{APIUsageTest.java => ProtocolViolationsTest.java} (58%) diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IStream.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IStream.java index 86e3bd98066..2291cf78b64 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IStream.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IStream.java @@ -68,8 +68,9 @@ public interface IStream extends Stream * of true puts the stream into closed state.

* * @param close whether the close state should be updated + * @param local whether the close is local or remote */ - public void updateCloseState(boolean close); + public void updateCloseState(boolean close, boolean local); /** *

Processes the given control frame, diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java index 4caa3df86c4..8b1a53dda42 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java @@ -398,6 +398,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler frameBytes = new ControlFrameBytes<>(stream, handler, context, frame, buffer); if (timeout > 0) frameBytes.task = scheduler.schedule(frameBytes, timeout, unit); - append(frameBytes); + + // Special handling for PING frames, they must be sent as soon as possible + if (ControlFrameType.PING == frame.getType()) + prepend(frameBytes); + else + append(frameBytes); } flush(); @@ -1089,7 +1096,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler handler) { openState = OpenState.REPLY_SENT; - updateCloseState(replyInfo.isClose()); + updateCloseState(replyInfo.isClose(), true); SynReplyFrame frame = new SynReplyFrame(session.getVersion(), replyInfo.getFlags(), getId(), replyInfo.getHeaders()); session.control(this, frame, timeout, unit, handler, null); } @@ -306,7 +329,12 @@ public class StandardStream implements IStream if (!canSend()) { session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR)); - throw new IllegalStateException("Cannot send DATA frames before a SYN_REPLY frame"); + throw new IllegalStateException("Protocol violation: cannot send a DATA frame before a SYN_REPLY frame"); + } + if (isLocallyClosed()) + { + session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR)); + throw new IllegalStateException("Protocol violation: cannot send a DATA frame on a closed stream"); } // Cannot update the close state here, because the data that we send may @@ -328,10 +356,15 @@ public class StandardStream implements IStream if (!canSend()) { session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR)); - throw new IllegalStateException("Cannot send a HEADERS frame before a SYN_REPLY frame"); + throw new IllegalStateException("Protocol violation: cannot send a HEADERS frame before a SYN_REPLY frame"); + } + if (isLocallyClosed()) + { + session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR)); + throw new IllegalStateException("Protocol violation: cannot send a HEADERS frame on a closed stream"); } - updateCloseState(headersInfo.isClose()); + updateCloseState(headersInfo.isClose(), true); HeadersFrame frame = new HeadersFrame(session.getVersion(), headersInfo.getFlags(), getId(), headersInfo.getHeaders()); session.control(this, frame, timeout, unit, handler, null); } @@ -339,13 +372,19 @@ public class StandardStream implements IStream @Override public boolean isClosed() { - return closed; + return closeState == CloseState.CLOSED; + } + + private boolean isLocallyClosed() + { + CloseState closeState = this.closeState; + return closeState == CloseState.LOCALLY_CLOSED || closeState == CloseState.CLOSED; } @Override public String toString() { - return String.format("stream=%d v%d closed=%s", getId(), session.getVersion(), isClosed() ? "true" : isHalfClosed() ? "half" : "false"); + return String.format("stream=%d v%d %s", getId(), session.getVersion(), closeState); } private boolean canSend() @@ -364,4 +403,9 @@ public class StandardStream implements IStream { SYN_SENT, SYN_RECV, REPLY_SENT, REPLY_RECV } + + private enum CloseState + { + OPENED, LOCALLY_CLOSED, REMOTELY_CLOSED, CLOSED + } } diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/FlowControlTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/FlowControlTest.java index 6e246409d58..f1908e73bcc 100644 --- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/FlowControlTest.java +++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/FlowControlTest.java @@ -307,7 +307,7 @@ public class FlowControlTest extends AbstractTest Assert.assertTrue(settingsLatch.await(5, TimeUnit.SECONDS)); - Stream stream = session.syn(new SynInfo(true), null).get(5, TimeUnit.SECONDS); + Stream stream = session.syn(new SynInfo(false), null).get(5, TimeUnit.SECONDS); final int length = 5 * windowSize; stream.data(new BytesDataInfo(new byte[length], true)); diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/APIUsageTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ProtocolViolationsTest.java similarity index 58% rename from jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/APIUsageTest.java rename to jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ProtocolViolationsTest.java index 36a0a2cb7bf..92e642f2b13 100644 --- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/APIUsageTest.java +++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ProtocolViolationsTest.java @@ -8,6 +8,9 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.eclipse.jetty.spdy.api.BytesDataInfo; +import org.eclipse.jetty.spdy.api.DataInfo; +import org.eclipse.jetty.spdy.api.Headers; +import org.eclipse.jetty.spdy.api.HeadersInfo; import org.eclipse.jetty.spdy.api.RstInfo; import org.eclipse.jetty.spdy.api.SPDY; import org.eclipse.jetty.spdy.api.Session; @@ -21,11 +24,12 @@ import org.eclipse.jetty.spdy.api.SynInfo; import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener; import org.eclipse.jetty.spdy.frames.ControlFrameType; import org.eclipse.jetty.spdy.frames.GoAwayFrame; +import org.eclipse.jetty.spdy.frames.SynReplyFrame; import org.eclipse.jetty.spdy.generator.Generator; import org.junit.Assert; import org.junit.Test; -public class APIUsageTest extends AbstractTest +public class ProtocolViolationsTest extends AbstractTest { @Test public void testSendDataBeforeReplyIsIllegal() throws Exception @@ -95,4 +99,66 @@ public class APIUsageTest extends AbstractTest server.close(); } + + @Test(expected = IllegalStateException.class) + public void testSendDataAfterCloseIsIllegal() throws Exception + { + Session session = startClient(startServer(null), null); + Stream stream = session.syn(new SynInfo(true), null).get(5, TimeUnit.SECONDS); + stream.data(new StringDataInfo("test", true)); + } + + @Test(expected = IllegalStateException.class) + public void testSendHeadersAfterCloseIsIllegal() throws Exception + { + Session session = startClient(startServer(null), null); + Stream stream = session.syn(new SynInfo(true), null).get(5, TimeUnit.SECONDS); + stream.headers(new HeadersInfo(new Headers(), true)); + } + + @Test + public void testDataSentAfterCloseIsDiscardedByRecipient() throws Exception + { + ServerSocketChannel server = ServerSocketChannel.open(); + server.bind(new InetSocketAddress("localhost", 0)); + + Session session = startClient(new InetSocketAddress("localhost", server.socket().getLocalPort()), null); + final CountDownLatch dataLatch = new CountDownLatch(2); + session.syn(new SynInfo(true), new StreamFrameListener.Adapter() + { + @Override + public void onData(Stream stream, DataInfo dataInfo) + { + dataLatch.countDown(); + } + }); + + SocketChannel channel = server.accept(); + ByteBuffer readBuffer = ByteBuffer.allocate(1024); + channel.read(readBuffer); + readBuffer.flip(); + int streamId = readBuffer.getInt(8); + + Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory.StandardCompressor()); + + ByteBuffer writeBuffer = generator.control(new SynReplyFrame(SPDY.V2, (byte)0, streamId, new Headers())); + channel.write(writeBuffer); + + byte[] bytes = new byte[1]; + writeBuffer = generator.data(streamId, bytes.length, new BytesDataInfo(bytes, true)); + channel.write(writeBuffer); + + // Write again to simulate the faulty condition + writeBuffer.flip(); + channel.write(writeBuffer); + + Assert.assertFalse(dataLatch.await(1, TimeUnit.SECONDS)); + + writeBuffer = generator.control(new GoAwayFrame(SPDY.V2, 0, SessionStatus.OK.getCode())); + channel.write(writeBuffer); + channel.shutdownOutput(); + channel.close(); + + server.close(); + } } From 543d2a18caf3d10c2b3a91014d8fe93124ce7f69 Mon Sep 17 00:00:00 2001 From: Thomas Becker Date: Wed, 11 Apr 2012 13:03:33 +0200 Subject: [PATCH 34/36] 376373: GzipFilter now does not ignore _excludePath + fix for ignored _excludeAgentPatterns if _excludeAgent is set Change-Id: I8d3d0fd62677c3a54cbe93febf4cde49aa24cc74 --- .../src/main/java/org/eclipse/jetty/servlets/GzipFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java index db36f51f220..94d50dee76d 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java @@ -350,7 +350,7 @@ public class GzipFilter extends UserAgentFilter { for (String excludedPath : _excludedPaths) { - if (requestURI.contains(excludedPath)) + if (requestURI.startsWith(excludedPath)) { return true; } From 08573701efc447fb95da22bfc711f79b6908a60e Mon Sep 17 00:00:00 2001 From: Thomas Becker Date: Wed, 11 Apr 2012 14:47:28 +0200 Subject: [PATCH 35/36] 376373: GzipFilter now does not ignore _excludePath + fix for ignored _excludeAgentPatterns if _excludeAgent is set Change-Id: Ie9940141f9b92b267f4b405ef4ec3ab5dee43be5 --- .../eclipse/jetty/servlets/GzipFilter.java | 6 +- .../jetty/servlets/GzipFilterDefaultTest.java | 79 +++++++++---------- 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java index 94d50dee76d..650632b7f38 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java @@ -303,7 +303,7 @@ public class GzipFilter extends UserAgentFilter } /** - * Checks to see if the UserAgent is excluded + * Checks to see if the userAgent is excluded * * @param ua * the user agent @@ -336,9 +336,9 @@ public class GzipFilter extends UserAgentFilter } /** - * Checks to see if the Path is excluded + * Checks to see if the path is excluded * - * @param ua + * @param requestURI * the request uri * @return boolean true if excluded */ diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java index 89f2f458534..05f53c97e3e 100644 --- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java +++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java @@ -31,11 +31,10 @@ public class GzipFilterDefaultTest public static Collection data() { String[][] data = new String[][] - { - { GzipFilter.GZIP }, - { GzipFilter.DEFLATE } - }; - + { + { GzipFilter.GZIP }, + { GzipFilter.DEFLATE } }; + return Arrays.asList(data); } @@ -166,88 +165,88 @@ public class GzipFilterDefaultTest @Test public void testUserAgentExclusion() throws Exception { - GzipTester tester = new GzipTester(testingdir, compressionType); - + GzipTester tester = new GzipTester(testingdir,compressionType); + FilterHolder holder = tester.setContentServlet(DefaultServlet.class); - holder.setInitParameter("excludedAgents", "foo"); + holder.setInitParameter("excludedAgents","foo"); tester.setUserAgent("foo"); - + int filesize = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE * 4; tester.prepareServerFile("file.txt",filesize); - + try { tester.start(); - tester.assertIsResponseNotGzipCompressed("file.txt", filesize, HttpStatus.OK_200); - } + tester.assertIsResponseNotGzipCompressed("file.txt",filesize,HttpStatus.OK_200); + } finally { tester.stop(); } } - + @Test public void testUserAgentExclusionByExcludedAgentPatterns() throws Exception { - GzipTester tester = new GzipTester(testingdir); - + GzipTester tester = new GzipTester(testingdir,compressionType); + FilterHolder holder = tester.setContentServlet(DefaultServlet.class); - holder.setInitParameter("excludedAgents", "bar"); - holder.setInitParameter("excludeAgentPatterns", "fo.*"); + holder.setInitParameter("excludedAgents","bar"); + holder.setInitParameter("excludeAgentPatterns","fo.*"); tester.setUserAgent("foo"); - - int filesize = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 4; + + int filesize = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE * 4; tester.prepareServerFile("file.txt",filesize); - + try { tester.start(); - tester.assertIsResponseNotGzipCompressed("file.txt", filesize, HttpStatus.OK_200); - } + tester.assertIsResponseNotGzipCompressed("file.txt",filesize,HttpStatus.OK_200); + } finally { tester.stop(); } } - + @Test public void testExcludePaths() throws Exception { - GzipTester tester = new GzipTester(testingdir); - + GzipTester tester = new GzipTester(testingdir,compressionType); + FilterHolder holder = tester.setContentServlet(DefaultServlet.class); - holder.setInitParameter("excludePaths", "/context/"); - - int filesize = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 4; + holder.setInitParameter("excludePaths","/context/"); + + int filesize = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE * 4; tester.prepareServerFile("file.txt",filesize); - + try { tester.start(); - tester.assertIsResponseNotGzipCompressed("file.txt", filesize, HttpStatus.OK_200); - } + tester.assertIsResponseNotGzipCompressed("file.txt",filesize,HttpStatus.OK_200); + } finally { tester.stop(); } } - + @Test public void testExcludePathPatterns() throws Exception { - GzipTester tester = new GzipTester(testingdir); - + GzipTester tester = new GzipTester(testingdir,compressionType); + FilterHolder holder = tester.setContentServlet(DefaultServlet.class); - holder.setInitParameter("excludePathPatterns", "/cont.*"); - - int filesize = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 4; + holder.setInitParameter("excludePathPatterns","/cont.*"); + + int filesize = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE * 4; tester.prepareServerFile("file.txt",filesize); - + try { tester.start(); - tester.assertIsResponseNotGzipCompressed("file.txt", filesize, HttpStatus.OK_200); - } + tester.assertIsResponseNotGzipCompressed("file.txt",filesize,HttpStatus.OK_200); + } finally { tester.stop(); From c9ce3eb108a1362b73ed54a4c6d24fa47edd002f Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 12 Apr 2012 11:32:28 +1000 Subject: [PATCH 36/36] 362113: fixed StdErrLog so that it does not hold a copy of System.err and thus avoid being redirected if System.err is redirected --- .../org/eclipse/jetty/util/log/StdErrLog.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/log/StdErrLog.java b/jetty-util/src/main/java/org/eclipse/jetty/util/log/StdErrLog.java index 1848e7ad8c6..7636bd870dc 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/log/StdErrLog.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/log/StdErrLog.java @@ -77,7 +77,7 @@ public class StdErrLog extends AbstractLogger private int _level = LEVEL_INFO; // Level that this Logger was configured as (remembered in special case of .setDebugEnabled()) private int _configuredLevel; - private PrintStream _stderr = System.err; + private PrintStream _stderr = null; private boolean _source = __source; // Print the long form names, otherwise use abbreviated private boolean _printLongNames = __long; @@ -271,7 +271,7 @@ public class StdErrLog extends AbstractLogger { StringBuilder buffer = new StringBuilder(64); format(buffer,":WARN:",msg,args); - _stderr.println(buffer); + (_stderr==null?System.err:_stderr).println(buffer); } } @@ -286,7 +286,7 @@ public class StdErrLog extends AbstractLogger { StringBuilder buffer = new StringBuilder(64); format(buffer,":WARN:",msg,thrown); - _stderr.println(buffer); + (_stderr==null?System.err:_stderr).println(buffer); } } @@ -296,7 +296,7 @@ public class StdErrLog extends AbstractLogger { StringBuilder buffer = new StringBuilder(64); format(buffer,":INFO:",msg,args); - _stderr.println(buffer); + (_stderr==null?System.err:_stderr).println(buffer); } } @@ -311,7 +311,7 @@ public class StdErrLog extends AbstractLogger { StringBuilder buffer = new StringBuilder(64); format(buffer,":INFO:",msg,thrown); - _stderr.println(buffer); + (_stderr==null?System.err:_stderr).println(buffer); } } @@ -369,7 +369,7 @@ public class StdErrLog extends AbstractLogger public void setStdErrStream(PrintStream stream) { - this._stderr = stream; + this._stderr = stream==System.err?null:stream; } public void debug(String msg, Object... args) @@ -378,7 +378,7 @@ public class StdErrLog extends AbstractLogger { StringBuilder buffer = new StringBuilder(64); format(buffer,":DBUG:",msg,args); - _stderr.println(buffer); + (_stderr==null?System.err:_stderr).println(buffer); } } @@ -393,7 +393,7 @@ public class StdErrLog extends AbstractLogger { StringBuilder buffer = new StringBuilder(64); format(buffer,":DBUG:",msg,thrown); - _stderr.println(buffer); + (_stderr==null?System.err:_stderr).println(buffer); } } @@ -616,7 +616,7 @@ public class StdErrLog extends AbstractLogger { StringBuilder buffer = new StringBuilder(64); format(buffer,":IGNORED:","",ignored); - _stderr.println(buffer); + (_stderr==null?System.err:_stderr).println(buffer); } } }