Merge branch 'master' into javawebsocket-jsr

This commit is contained in:
Joakim Erdfelt 2013-04-15 12:12:25 -07:00
commit 8088edc96c
149 changed files with 1468 additions and 1176 deletions

View File

@ -1,3 +1,83 @@
jetty-9.0.2-SNAPSHOT
jetty-9.0.1.v20130408 - 08 April 2013
+ 384552 add comment to jetty-https.xml describing keymanager password
+ 385488 non existing resources in collection are just warnings
+ 392129 fixed merged of handling of timeouts after startAsync
+ 393971 Improve setParentLoaderPriorty javadoc
+ 393972 Improve WebAppContext classloading javadoc
+ 395620 do not managed inherited life cycle listeners
+ 396562 Add an implementation of RequestLog that supports Slf4j
+ 399967 Destroyables destroyed on undeploy and shutdown hook
+ 400142 ConcurrentModificationException in JDBC SessionManger
+ 400144 When loading a session fails the JDBCSessionManger produces duplicate
session IDs
+ 400689 Add support for Proxy authentication.
+ 401150 close input stream used from cached resource
+ 401806 spdy push properly pass through request and response headers for
pushed resources
+ 402397 InputStreamResponseListener early close inputStream cause hold lock.
+ 402485 reseed secure random
+ 402626 Do not required endpoint host checking by default in server and
configure in client
+ 402666 Improve handling of TLS exceptions due to raw socket close.
+ 402694 setuid as LifeCycle listener
+ 402706 HttpSession.setMaxInactiveInterval(int) does not change JDBCSession
expiry
+ 402726 WebAppContext references old WebSocket packages in system and server
classes
+ 402735 jetty.sh to support status which is == check
+ 402757 WebSocket client module can't be used with WebSocket server module in
the same WAR.
+ 402833 Test harness for global error page and hide exception message from
reason string
+ 402844 STOP.PORT & STOP.KEY behaviour has changed
+ 402982 Premature initialization of Servlets
+ 402984 WebSocket Upgrade must honor case insensitive header fields in
upgrade request
+ 403122 Session replication fails with ClassNotFoundException when session
attribute is Java dynamic proxy
+ 403280 Update to javax.el 2.2.4
+ 403281 jetty.sh waits for started or failure before returning
+ 403360 Named connectors
+ 403370 move frameBytes.fail() call in StandardSession.flush() outside the
synchronized block to avoid deadlock
+ 403373 WebSocket change timeout log level from warn -> info
+ 403380 Introduce WebSocketTimeoutException to differentiate between EOF on
write and Timeout
+ 403451 Review synchronization in SslConnection.
+ 403510 HttpSession maxInactiveInterval is not serialized in HashSession
+ 403513 jetty:run goal cannot be executed twice during the maven build
+ 403570 Asynchronous Request Logging
+ 403591 do not use the ConcurrentArrayBlockingQueue for thread pool, selector
and async request log
+ 403817 Use of WebSocket Session.close() results in invalid status code
+ 404029 port jetty-monitor to jetty-9 and activate it
+ 404036 JDBCSessionIdManager.doStart() method should not call
cleanExpiredSessions() because Listeners can't be notified
+ 404067 If cannot connect to db fail startup of JDBCSessionIdManager
+ 404128 Add Vary headers rather than set them
+ 404176 Jetty's AnnotationConfiguration class does not scan non-jar resources
on the container classpath
+ 404204 Exception from inputstream cause hang or timeout.
+ 404283 org.eclipse.jetty.util.Scanner.scanFile() dies with an NPE if
listFiles() returns null
+ 404323 Improved parameterization of https and SPDY
+ 404325 data constraint redirection does send default port
+ 404326 set status when Request.setHandled(true) is called
+ 404511 Replaced all StringMap usage with Tries
+ 404517 Close connection if request received after half close
+ 404610 Reintroduce ability to disallow TLS renegotiation.
+ 404757 SPDY can only be built with the latest JDK version.
+ 404789 Support IPv6 addresses in DoSFilter white list.
+ 404881 Allow regexs for SslContextFactory.setIncludeCipherSuites() and
.setExcludeCipherSuites()
+ 404889 SelectorManager accepts attachments with sockets
+ 404906 servlets with load-on-startup = 0 are not fired up on jetty 9 startup
+ 404958 Fixed Resource.newSystemResource striped / handling
+ 405044 Query parameters lost for non GET or POST.
jetty-9.0.0.v20130308 - 08 March 2013
+ 399070 add updated version of npn-boot jar to start.ini
+ 399799 do not hold lock while calling invalidation listeners
@ -34,10 +114,10 @@ jetty-9.0.0.v20130308 - 08 March 2013
upstream server. Fix several other small proxy issues
+ 402316 HttpReceiver and null pointer exception.
+ 402341 Host with default port causes redirects loop.
+ 402726 WebAppContext references old WebSocket packages in system and
server classes
+ 402757 WebSocket client module can't be used with WebSocket server
module in the same WAR
+ 402726 WebAppContext references old WebSocket packages in system and server
classes
+ 402757 WebSocket client module can't be used with WebSocket server module in
the same WAR
jetty-8.1.10.v20130312 - 12 March 2013
+ 376273 Early EOF because of SSL Protocol Error on

View File

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

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>example-async-rest</artifactId>
<version>9.0.1-SNAPSHOT</version>
<version>9.0.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.example-async-rest</groupId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>example-async-rest</artifactId>
<version>9.0.1-SNAPSHOT</version>
<version>9.0.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.example-async-rest</groupId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.examples</groupId>
<artifactId>examples-parent</artifactId>
<version>9.0.1-SNAPSHOT</version>
<version>9.0.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.examples</groupId>
<artifactId>examples-parent</artifactId>
<version>9.0.1-SNAPSHOT</version>
<version>9.0.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -67,6 +67,7 @@ public class ManyConnectors
new SslConnectionFactory(sslContextFactory,"http/1.1"),
new HttpConnectionFactory(https_config));
https.setPort(8443);
https.setIdleTimeout(500000);
// Set the connectors
server.setConnectors(new Connector[] { http, https });

View File

@ -5,5 +5,6 @@ org.eclipse.jetty.SOURCE=false
#org.eclipse.jetty.STACKS=false
#org.eclipse.jetty.spdy.LEVEL=DEBUG
#org.eclipse.jetty.server.LEVEL=DEBUG
#org.eclipse.jetty.io.ssl.LEVEL=DEBUG
org.eclipse.jetty.io.LEVEL=DEBUG
org.eclipse.jetty.io.ssl.LEVEL=DEBUG
#org.eclipse.jetty.spdy.server.LEVEL=DEBUG

View File

@ -0,0 +1,50 @@
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure id="OtherServer" class="org.eclipse.jetty.server.Server">
<Set name="handler">
<New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
<Set name="handlers">
<Array type="org.eclipse.jetty.server.Handler">
<Item>
<New id="OtherContexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/>
</Item>
<Item>
<New class="org.eclipse.jetty.server.handler.DefaultHandler"/>
</Item>
</Array>
</Set>
</New>
</Set>
<Call name="addConnector">
<Arg>
<New class="org.eclipse.jetty.server.ServerConnector">
<Arg name="server"><Ref refid="OtherServer" /></Arg>
<Set name="port">8888</Set>
</New>
</Arg>
</Call>
<Call name="addBean">
<Arg>
<New id="DeploymentManager" class="org.eclipse.jetty.deploy.DeploymentManager">
<Set name="contexts">
<Ref refid="OtherContexts" />
</Set>
<Call id="webappprovider" name="addAppProvider">
<Arg>
<New class="org.eclipse.jetty.deploy.providers.WebAppProvider">
<Set name="monitoredDirName"><Property name="jetty.home" default="." />/other-webapps</Set>
<Set name="defaultsDescriptor"><Property name="jetty.home" default="." />/etc/webdefault.xml</Set>
<Set name="configurationManager">
<New class="org.eclipse.jetty.deploy.PropertiesConfigurationManager"/>
</Set>
</New>
</Arg>
</Call>
</New>
</Arg>
</Call>
</Configure>

View File

@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.0.1-SNAPSHOT</version>
<version>9.0.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>org.eclipse.jetty.examples</groupId>

View File

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

View File

@ -167,7 +167,7 @@ public class WebServletAnnotation extends DiscoveredAnnotation
//if not, add it
for (WebInitParam ip:annotation.initParams())
{
if (metaData.getOrigin(servletName+".servlet.init-param"+ip.name())==Origin.NotSet)
if (metaData.getOrigin(servletName+".servlet.init-param."+ip.name())==Origin.NotSet)
{
holder.setInitParameter(ip.name(), ip.value());
metaData.setOrigin(servletName+".servlet.init-param."+ip.name());

View File

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

View File

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

View File

@ -129,29 +129,24 @@ public class InputStreamResponseListener extends Response.Listener.Empty
}
}
@Override
public void onFailure(Response response, Throwable failure)
{
LOG.debug("Queuing failure {} {}", FAILURE, failure);
queue.offer(FAILURE);
responseLatch.countDown();
resultLatch.countDown();
this.failure = failure;
signal();
}
@Override
public void onSuccess(Response response)
{
LOG.debug("Queuing end of content {}{}", EOF, "");
queue.offer(EOF);
}
@Override
public void onComplete(Result result)
{
this.result = result;
if (result.isSucceeded())
{
LOG.debug("Queuing end of content {}{}", EOF, "");
queue.offer(EOF);
}
else
{
LOG.debug("Queuing failure {} {}", FAILURE, failure);
queue.offer(FAILURE);
this.failure = result.getFailure();
responseLatch.countDown();
}
resultLatch.countDown();
signal();
}
protected boolean await()
@ -176,7 +171,7 @@ public class InputStreamResponseListener extends Response.Listener.Empty
{
synchronized (this)
{
notify();
notifyAll();
}
}

View File

@ -445,6 +445,20 @@ public class HttpClientStreamTest extends AbstractHttpClientServerTest
Assert.assertNull(failure.get());
}
@Test
public void testInputStreamResponseListenerFailedBeforeResponse() throws Exception
{
start(new EmptyServerHandler());
InputStreamResponseListener listener = new InputStreamResponseListener();
// Connect to the wrong port
client.newRequest("localhost", 0)
.scheme(scheme)
.send(listener);
Result result = listener.await(5, TimeUnit.SECONDS);
Assert.assertNotNull(result);
}
@Test(expected = ExecutionException.class)
public void testInputStreamContentProviderThrowingWhileReading() throws Exception
{

View File

@ -356,13 +356,8 @@ public class SslBytesClientTest extends SslBytesTest
Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
proxy.flushToClient(record);
record = proxy.readFromClient();
Assert.assertEquals(TLSRecord.Type.ALERT, record.getType());
proxy.flushToServer(record);
record = proxy.readFromClient();
Assert.assertNull(record);
proxy.flushToServer(record);
server.close();
}

View File

@ -72,7 +72,6 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
public class SslBytesServerTest extends SslBytesTest
@ -87,6 +86,7 @@ public class SslBytesServerTest extends SslBytesTest
private SslContextFactory sslContextFactory;
private SSLContext sslContext;
private SimpleProxy proxy;
private Runnable idleHook;
@Before
public void init() throws Exception
@ -119,6 +119,15 @@ public class SslBytesServerTest extends SslBytesTest
}
};
}
@Override
protected boolean onReadTimeout()
{
final Runnable idleHook = SslBytesServerTest.this.idleHook;
if (idleHook != null)
idleHook.run();
return super.onReadTimeout();
}
}, connector, endPoint);
}
};
@ -165,7 +174,6 @@ public class SslBytesServerTest extends SslBytesTest
}
};
connector.setIdleTimeout(idleTimeout);
// connector.setPort(5870);
connector.setPort(0);
server.addConnector(connector);
@ -209,7 +217,7 @@ public class SslBytesServerTest extends SslBytesTest
proxy = new SimpleProxy(threadPool, "localhost", serverPort);
proxy.start();
logger.debug(":{} <==> :{}", proxy.getPort(), serverPort);
logger.info("proxy:{} <==> server:{}", proxy.getPort(), serverPort);
}
@After
@ -377,13 +385,9 @@ public class SslBytesServerTest extends SslBytesTest
Assert.assertNull(String.valueOf(record), record);
proxy.flushToServer(record);
// Close Alert
record = proxy.readFromServer();
proxy.flushToClient(record);
// Socket close
record = proxy.readFromServer();
Assert.assertNull(String.valueOf(record), record);
proxy.flushToClient(record);
}
@Test
@ -669,13 +673,9 @@ public class SslBytesServerTest extends SslBytesTest
Assert.assertNull(String.valueOf(record), record);
proxy.flushToServer(record);
// Close Alert
record = proxy.readFromServer();
proxy.flushToClient(record);
// Socket close
record = proxy.readFromServer();
Assert.assertNull(String.valueOf(record), record);
proxy.flushToClient(record);
}
@Test
@ -728,22 +728,15 @@ public class SslBytesServerTest extends SslBytesTest
Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType());
proxy.flushToClient(record);
// Close Alert
// Socket close
record = proxy.readFromServer();
Assert.assertNotNull(record);
Assert.assertEquals(TLSRecord.Type.ALERT, record.getType());
// We can't forward to the client, its socket is already closed
Assert.assertNull(record);
// Check that we did not spin
TimeUnit.MILLISECONDS.sleep(500);
Assert.assertThat(sslFills.get(), Matchers.lessThan(20));
Assert.assertThat(sslFlushes.get(), Matchers.lessThan(20));
Assert.assertThat(httpParses.get(), Matchers.lessThan(20));
// Socket close
record = proxy.readFromServer();
Assert.assertNull(String.valueOf(record), record);
proxy.flushToClient(record);
}
@Test
@ -803,11 +796,9 @@ public class SslBytesServerTest extends SslBytesTest
Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType());
proxy.flushToClient(record);
// Close Alert
// Socket close
record = proxy.readFromServer();
Assert.assertNotNull(record);
Assert.assertEquals(TLSRecord.Type.ALERT, record.getType());
// We can't forward to the client, its socket is already closed
Assert.assertNull(String.valueOf(record), record);
// Check that we did not spin
TimeUnit.MILLISECONDS.sleep(500);
@ -819,11 +810,6 @@ public class SslBytesServerTest extends SslBytesTest
record = proxy.readFromClient();
Assert.assertNull(String.valueOf(record), record);
proxy.flushToServer(record);
// Socket close
record = proxy.readFromServer();
Assert.assertNull(String.valueOf(record), record);
proxy.flushToClient(record);
}
@Test
@ -864,12 +850,9 @@ public class SslBytesServerTest extends SslBytesTest
// Close the raw socket, this generates a truncation attack
proxy.flushToServer(null);
// Expect alert + raw close from server
record = proxy.readFromServer();
Assert.assertEquals(TLSRecord.Type.ALERT, record.getType());
// Expect raw close from server
record = proxy.readFromServer();
Assert.assertNull(String.valueOf(record), record);
proxy.flushToClient(record);
// Check that we did not spin
TimeUnit.MILLISECONDS.sleep(500);
@ -917,12 +900,9 @@ public class SslBytesServerTest extends SslBytesTest
Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType());
proxy.flushToClient(record);
// Expect alert + raw close from server
record = proxy.readFromServer();
Assert.assertEquals(TLSRecord.Type.ALERT, record.getType());
// Expect raw close from server
record = proxy.readFromServer();
Assert.assertNull(String.valueOf(record), record);
proxy.flushToClient(record);
// Check that we did not spin
TimeUnit.MILLISECONDS.sleep(500);
@ -1099,6 +1079,7 @@ public class SslBytesServerTest extends SslBytesTest
System.arraycopy(closeBytes, 0, bytes, dataBytes.length, closeBytes.length / 2);
proxy.flushToServer(100, bytes);
// Send the other half of the close alert bytes
bytes = new byte[closeBytes.length - closeBytes.length / 2];
System.arraycopy(closeBytes, closeBytes.length / 2, bytes, 0, bytes.length);
proxy.flushToServer(100, bytes);
@ -1113,27 +1094,15 @@ public class SslBytesServerTest extends SslBytesTest
Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType());
proxy.flushToClient(record);
// Close Alert
// Socket close
record = proxy.readFromServer();
Assert.assertNotNull(record);
Assert.assertEquals(TLSRecord.Type.ALERT, record.getType());
// We can't forward to the client, its socket is already closed
Assert.assertNull(record);
// Check that we did not spin
TimeUnit.MILLISECONDS.sleep(500);
Assert.assertThat(sslFills.get(), Matchers.lessThan(20));
Assert.assertThat(sslFlushes.get(), Matchers.lessThan(20));
Assert.assertThat(httpParses.get(), Matchers.lessThan(20));
// Socket close
record = proxy.readFromClient();
Assert.assertNull(String.valueOf(record), record);
proxy.flushToServer(record);
// Socket close
record = proxy.readFromServer();
Assert.assertNull(String.valueOf(record), record);
proxy.flushToClient(record);
}
@Test
@ -1749,13 +1718,37 @@ public class SslBytesServerTest extends SslBytesTest
client.close();
}
@Ignore
@Test
public void testRequestConcurrentWithIdleExpiration() throws Exception
{
final SSLSocket client = newClient();
final OutputStream clientOutput = client.getOutputStream();
final CountDownLatch latch = new CountDownLatch(1);
idleHook = new Runnable()
{
public void run()
{
if (latch.getCount()==0)
return;
try
{
// Send request
clientOutput.write(("" +
"GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"\r\n").getBytes("UTF-8"));
clientOutput.flush();
latch.countDown();
}
catch (Exception x)
{
// Latch won't trigger and test will fail
x.printStackTrace();
}
}
};
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
client.startHandshake();
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
@ -1779,86 +1772,13 @@ public class SslBytesServerTest extends SslBytesTest
Assert.assertThat(sslFlushes.get(), Matchers.lessThan(20));
Assert.assertThat(httpParses.get(), Matchers.lessThan(50));
completeClose(client);
record = proxy.readFromServer();
Assert.assertNull(record);
TimeUnit.MILLISECONDS.sleep(200);
//System.err.println(((Dumpable)server.getConnectors()[0]).dump());
Assert.assertThat(((Dumpable)server.getConnectors()[0]).dump(), Matchers.not(Matchers.containsString("SCEP@")));
}
/*
@Test
public void testRequestWriteBlockedWithPipelinedRequest() throws Exception
{
final SSLSocket client = newClient();
final OutputStream clientOutput = client.getOutputStream();
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
client.startHandshake();
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
byte[] data = new byte[128 * 1024];
Arrays.fill(data, (byte)'X');
final String content = new String(data, "UTF-8");
Future<Object> request = threadPool.submit(new Callable<Object>()
{
public Object call() throws Exception
{
clientOutput.write(("" +
"POST /echo HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Content-Length: " + content.length() + "\r\n" +
"\r\n" +
content).getBytes("UTF-8"));
clientOutput.flush();
return null;
}
});
// Nine TLSRecords will be generated for the request
for (int i = 0; i < 9; ++i)
{
// Application data
TLSRecord record = proxy.readFromClient();
Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType());
proxy.flushToServer(record, 0);
}
Assert.assertNull(request.get(5, TimeUnit.SECONDS));
// We do not read the big request to cause a write blocked on the server
TimeUnit.MILLISECONDS.sleep(500);
// Now send the pipelined request
Future<Object> pipelined = threadPool.submit(new Callable<Object>()
{
public Object call() throws Exception
{
clientOutput.write(("" +
"GET /pipelined HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"\r\n").getBytes("UTF-8"));
clientOutput.flush();
return null;
}
});
TLSRecord record = proxy.readFromClient();
Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType());
proxy.flushToServer(record, 0);
Assert.assertNull(pipelined.get(5, TimeUnit.SECONDS));
// Check that we did not spin
TimeUnit.MILLISECONDS.sleep(500);
Assert.assertThat(sslFills.get(), lessThan(20));
Assert.assertThat(sslFlushes.get(), lessThan(20));
Assert.assertThat(httpParses.get(), lessThan(50));
Thread.sleep(5000);
// closeClient(client);
}
*/
private void assumeJavaVersionSupportsTLSRenegotiations()
{
// Due to a security bug, TLS renegotiations were disabled in JDK 1.6.0_19-21
@ -1893,31 +1813,8 @@ public class SslBytesServerTest extends SslBytesTest
Assert.assertNull(String.valueOf(record), record);
proxy.flushToServer(record);
// Close Alert
record = proxy.readFromServer();
proxy.flushToClient(record);
// Socket close
record = proxy.readFromServer();
Assert.assertNull(String.valueOf(record), record);
proxy.flushToClient(record);
}
private void completeClose(SSLSocket client) throws Exception
{
client.close();
// Close Alert
TLSRecord record = proxy.readFromClient();
proxy.flushToServer(record);
// Socket close
record = proxy.readFromClient();
Assert.assertNull(String.valueOf(record), record);
proxy.flushToServer(record);
// Close Alert
record = proxy.readFromServer();
proxy.flushToClient(record);
}
}

View File

@ -34,12 +34,17 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.junit.Assert;
import org.junit.Rule;
public abstract class SslBytesTest
{
@Rule
public TestTracker tracker = new TestTracker();
protected final Logger logger = Log.getLogger(getClass());
public static class TLSRecord
@ -115,8 +120,7 @@ public abstract class SslBytesTest
public void start() throws Exception
{
serverSocket = new ServerSocket(47009);
// serverSocket = new ServerSocket(0);
serverSocket = new ServerSocket(0);
Thread acceptor = new Thread(this);
acceptor.start();
server = new Socket(serverHost, serverPort);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -190,6 +190,10 @@ public class SslConnection extends AbstractConnection
if (DEBUG)
LOG.debug("onFillable enter {}", getEndPoint());
// We have received a close handshake, close the end point to send FIN.
if (_decryptedEndPoint.isInputShutdown())
getEndPoint().close();
// wake up whoever is doing the fill or the flush so they can
// do all the filling, unwrapping, wrapping and flushing
_decryptedEndPoint.getFillInterest().fillable();
@ -612,8 +616,11 @@ public class SslConnection extends AbstractConnection
// maybe we will fill some more on a retry
continue;
}
// we need to wait for more net data
return 0;
else
{
// we need to wait for more net data
return 0;
}
case FINISHED:
throw new IllegalStateException();
@ -726,6 +733,7 @@ public class SslConnection extends AbstractConnection
{
_cannotAcceptMoreAppDataToFlush = true;
getEndPoint().flush(_encryptedOutput);
getEndPoint().shutdownOutput();
// If we failed to flush the close handshake then we will just pretend that
// the write has progressed normally and let a subsequent call to flush
// (or WriteFlusher#onIncompleteFlushed) to finish writing the close handshake.
@ -733,8 +741,11 @@ public class SslConnection extends AbstractConnection
if (BufferUtil.hasContent(_encryptedOutput))
return false;
}
// otherwise we have written, and the caller will close the underlying connection
else
{
getEndPoint().shutdownOutput();
}
return allConsumed;
case BUFFER_UNDERFLOW:
@ -823,24 +834,37 @@ public class SslConnection extends AbstractConnection
{
_bufferPool.release(_encryptedOutput);
_encryptedOutput = null;
if (_sslEngine.isOutboundDone())
getEndPoint().shutdownOutput();
}
}
@Override
public void shutdownOutput()
{
_sslEngine.closeOutbound();
try
boolean ishut = isInputShutdown();
if (DEBUG)
LOG.debug("{} shutdownOutput: oshut={}, ishut={}", SslConnection.this, isOutputShutdown(), ishut);
if (ishut)
{
flush(BufferUtil.EMPTY_BUFFER);
}
catch (IOException e)
{
LOG.ignore(e);
// Aggressively close, since inbound close alert has already been processed
// and the TLS specification allows to close the connection directly, which
// is what most other implementations expect: a FIN rather than a TLS close
// reply. If a TLS close reply is sent, most implementation send a RST.
getEndPoint().close();
}
else
{
try
{
_sslEngine.closeOutbound();
flush(BufferUtil.EMPTY_BUFFER); // Send close handshake
SslConnection.this.fillInterested(); // seek reply FIN or RST or close handshake
}
catch (Exception e)
{
LOG.ignore(e);
getEndPoint().close();
}
}
}
@Override

View File

@ -202,16 +202,21 @@ public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
filled=client.read(sslIn);
if (debug) System.err.println("in="+filled);
sslIn.flip();
try
if (filled>=0)
{
// Since the client closed abruptly, the server is sending a close alert with a failure
engine.unwrap(sslIn, appIn);
Assert.fail();
}
catch (SSLException x)
{
// Expected
// this is the old behaviour.
sslIn.flip();
try
{
// Since the client closed abruptly, the server is sending a close alert with a failure
engine.unwrap(sslIn, appIn);
Assert.fail();
}
catch (SSLException x)
{
// Expected
}
}
sslIn.clear();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.0.1-SNAPSHOT</version>
<version>9.0.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jspc-maven-plugin</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.0.1-SNAPSHOT</version>
<version>9.0.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-maven-plugin</artifactId>

View File

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

View File

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

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>9.0.1-SNAPSHOT</version>
<version>9.0.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-osgi-boot-jsp</artifactId>

View File

@ -21,8 +21,6 @@ package org.eclipse.jetty.osgi.boot.jasper;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -32,67 +30,48 @@ import java.util.regex.Pattern;
import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.osgi.boot.OSGiWebInfConfiguration;
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer;
import org.eclipse.jetty.osgi.boot.utils.TldBundleDiscoverer;
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.
* ContainerTldBundleDiscoverer
*
*
* Use a System property to define bundles that contain tlds that need to
* be treated by jasper as if they were on the jetty container's classpath.
*
* The value of the property is evaluated against the DeploymentManager
* context attribute "org.eclipse.jetty.server.webapp.containerIncludeBundlePattern",
* which defines a pattern of matching bundle names.
*
* The bundle locations are converted to URLs for jasper's use.
*
* Eg:
* -Dorg.eclipse.jetty.osgi.tldbundles=org.springframework.web.servlet,com.opensymphony.module.sitemesh
*
* For example:
* -Dorg.eclipse.jetty.osgi.tldbundles=org.springframework.web.servlet
* ,com.opensymphony.module.sitemesh Otherwise use an attribute to the
* WebAppDeployer &lt;New
* class="org.eclipse.jetty.deploy.providers.WebAppProvider"&gt; .... &lt;Set
* name="tldBundles"&gt;&ltProperty name="org.eclipse.jetty.osgi.tldsbundles"
* default="" /&gt;&lt;/Set&gt; &lt;New&gt;
*/
public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistrationCustomizer
public class ContainerTldBundleDiscoverer implements TldBundleDiscoverer
{
/**
* 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
* Comma separated list of names of bundles that contain tld files that should be
* discoved by jasper as if they were on the container's classpath.
* Eg:
* -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.
* Check the System property "org.eclipse.jetty.osgi.tldbundles" for names of
* bundles that contain tlds and convert to URLs.
*
* @param provider
* @return
* @return The location of the jars that contain tld files as URLs.
*/
private static Collection<String> getTldBundles(DeploymentManager deploymentManager)
{
String sysprop = System.getProperty(SYS_PROP_TLD_BUNDLES);
String att = (String) deploymentManager.getContextAttribute(OSGiWebInfConfiguration.CONTAINER_BUNDLE_PATTERN);
if (sysprop == null && att == null) { return Collections.emptySet(); }
if (att == null)
{
att = sysprop;
}
else if (sysprop != null)
{
att = att + "," + sysprop;
}
Collection<String> tldbundles = new HashSet<String>();
StringTokenizer tokenizer = new StringTokenizer(att, ", \n\r\t", false);
while (tokenizer.hasMoreTokens())
{
tldbundles.add(tokenizer.nextToken());
}
return tldbundles;
}
/**
* @return The location of the jars that contain tld files. Jasper will
* discover them.
*/
public URL[] getJarsWithTlds(DeploymentManager deploymentManager, BundleFileLocatorHelper locatorHelper) throws Exception
public URL[] getUrlsForBundlesWithTlds(DeploymentManager deploymentManager, BundleFileLocatorHelper locatorHelper) throws Exception
{
// naive way of finding those bundles.
// lots of assumptions: for example we assume a single version of each
@ -103,7 +82,7 @@ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistra
// probably using custom properties in the ContextHandler service
// and mirroring those in the MANIFEST.MF
Bundle[] bundles = FrameworkUtil.getBundle(PluggableWebAppRegistrationCustomizerImpl.class).getBundleContext().getBundles();
Bundle[] bundles = FrameworkUtil.getBundle(ContainerTldBundleDiscoverer.class).getBundleContext().getBundles();
HashSet<URL> urls = new HashSet<URL>();
String tmp = System.getProperty(SYS_PROP_TLD_BUNDLES); //comma separated exact names
List<String> sysNames = new ArrayList<String>();
@ -118,10 +97,10 @@ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistra
for (Bundle bundle : bundles)
{
if (sysNames.contains(bundle.getSymbolicName()))
registerTldBundle(locatorHelper, bundle, urls);
convertBundleLocationToURL(locatorHelper, bundle, urls);
if (pattern != null && pattern.matcher(bundle.getSymbolicName()).matches())
registerTldBundle(locatorHelper, bundle, urls);
convertBundleLocationToURL(locatorHelper, bundle, urls);
}
return urls.toArray(new URL[urls.size()]);
@ -129,19 +108,8 @@ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistra
}
/**
* 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.
*
* 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.
* Resolves a bundle that contains tld files as a URL. The URLs are
* used by jasper to discover the tld files.
*
* 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
@ -153,7 +121,7 @@ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistra
* @param urls
* @throws Exception
*/
private void registerTldBundle(BundleFileLocatorHelper locatorHelper, Bundle bundle, Set<URL> urls) throws Exception
private void convertBundleLocationToURL(BundleFileLocatorHelper locatorHelper, Bundle bundle, Set<URL> urls) throws Exception
{
File jasperLocation = locatorHelper.getBundleInstallLocation(bundle);
if (jasperLocation.isDirectory())
@ -181,7 +149,5 @@ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistra
{
urls.add(jasperLocation.toURI().toURL());
}
}
}

View File

@ -34,7 +34,7 @@ import org.apache.jasper.xmlparser.ParserUtils;
import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator;
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer;
import org.eclipse.jetty.osgi.boot.utils.TldBundleDiscoverer;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.osgi.framework.Bundle;
@ -44,17 +44,20 @@ import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
*
* JSTLBundleDiscoverer
*
* Fix various shortcomings with the way jasper parses the tld files. Plugs the
* JSTL tlds assuming that they are packaged with the bundle that contains the
* JSTL classes.
* <p>
* Pluggable tlds at the server level are handled by
* {@link PluggableWebAppRegistrationCustomizerImpl}.
* {@link ContainerTldBundleDiscoverer}.
* </p>
*/
public class WebappRegistrationCustomizerImpl implements WebappRegistrationCustomizer
public class JSTLBundleDiscoverer implements TldBundleDiscoverer
{
private static final Logger LOG = Log.getLogger(WebappRegistrationCustomizerImpl.class);
private static final Logger LOG = Log.getLogger(JSTLBundleDiscoverer.class);
/**
@ -83,7 +86,7 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
*/
private static String DEFAULT_JSP_FACTORY_IMPL_CLASS = "org.apache.jasper.runtime.JspFactoryImpl";
public WebappRegistrationCustomizerImpl()
public JSTLBundleDiscoverer()
{
fixupDtdResolution();
@ -136,7 +139,7 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
* @return array of URLs
* @throws Exception
*/
public URL[] getJarsWithTlds(DeploymentManager deployer, BundleFileLocatorHelper locatorHelper) throws Exception
public URL[] getUrlsForBundlesWithTlds(DeploymentManager deployer, BundleFileLocatorHelper locatorHelper) throws Exception
{
ArrayList<URL> urls = new ArrayList<URL>();
@ -148,7 +151,7 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
// So we can look for this class using this bundle's classloader:
try
{
Class<?> jstlClass = WebappRegistrationCustomizerImpl.class.getClassLoader().loadClass(DEFAULT_JSTL_BUNDLE_CLASS);
Class<?> jstlClass = JSTLBundleDiscoverer.class.getClassLoader().loadClass(DEFAULT_JSTL_BUNDLE_CLASS);
classesToAddToTheTldBundles.add(jstlClass);
}

View File

@ -19,21 +19,26 @@
package org.eclipse.jetty.osgi.boot.jsp;
import org.eclipse.jetty.osgi.boot.BundleWebAppProvider;
import org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleTrackerCustomizer;
import org.eclipse.jetty.osgi.boot.jasper.PluggableWebAppRegistrationCustomizerImpl;
import org.eclipse.jetty.osgi.boot.jasper.WebappRegistrationCustomizerImpl;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
import org.eclipse.jetty.osgi.boot.jasper.ContainerTldBundleDiscoverer;
import org.eclipse.jetty.osgi.boot.jasper.JSTLBundleDiscoverer;
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.
* <p>
* It must be placed in the org.eclipse.jetty.osgi.boot.jsp package: this is
* because org.eclipse.jetty.osgi.boot.jsp is the symbolic-name of this
* fragment. From that name, the PackageadminTracker will call this class. IN a
* different package it won't be called.
* FragmentActivator
*
* Sets up support for jsp. All relevant jsp jars must also be installed
* into the osgi environment.
* <p>
* Note that as this is part of a bundle fragment, this activator is NOT
* called by the OSGi environment. Instead, the org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminTracker
* simulates fragment activation and causes this class's start() method to
* be called.
* </p>
* <p>
* The package of this class MUST match the Bundle-SymbolicName of this fragment
* in order for the PackageAdminTracker to find it.
* </p>
*/
public class FragmentActivator implements BundleActivator
@ -43,12 +48,14 @@ public class FragmentActivator implements BundleActivator
*/
public void start(BundleContext context) throws Exception
{
//jsr199 compilation does not work in osgi
System.setProperty("org.apache.jasper.compiler.disablejsr199", Boolean.TRUE.toString());
WebBundleTrackerCustomizer.JSP_REGISTRATION_HELPERS.add(new WebappRegistrationCustomizerImpl());
WebBundleTrackerCustomizer.JSP_REGISTRATION_HELPERS.add(new PluggableWebAppRegistrationCustomizerImpl());
//Put in the support for the tag libs
addTagLibSupport();
//set up some classes that will look for bundles with tlds that must be converted
//to urls and treated as if they are on the Jetty container's classpath so that
//jasper can deal with them
ServerInstanceWrapper.addContainerTldBundleDiscoverer(new JSTLBundleDiscoverer());
ServerInstanceWrapper.addContainerTldBundleDiscoverer(new ContainerTldBundleDiscoverer());
}
/**
@ -58,12 +65,4 @@ public class FragmentActivator implements BundleActivator
{
}
public void addTagLibSupport ()
{
String[] defaultConfigurations = new String[BundleWebAppProvider.getDefaultConfigurations().length+1];
System.arraycopy(BundleWebAppProvider.getDefaultConfigurations(), 0, defaultConfigurations, 0, BundleWebAppProvider.getDefaultConfigurations().length);
defaultConfigurations[defaultConfigurations.length-1] = "org.eclipse.jetty.osgi.boot.jsp.TagLibOSGiConfiguration";
BundleWebAppProvider.setDefaultConfigurations(defaultConfigurations);
}
}

View File

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

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>9.0.1-SNAPSHOT</version>
<version>9.0.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-osgi-boot</artifactId>

View File

@ -22,14 +22,12 @@ import java.io.File;
import java.net.URL;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.AppProvider;
import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
import org.eclipse.jetty.osgi.boot.utils.EventSender;
import org.eclipse.jetty.osgi.boot.utils.OSGiClassLoader;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
@ -37,11 +35,8 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.JarResource;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceRegistration;
@ -49,14 +44,15 @@ import org.osgi.framework.ServiceRegistration;
/**
* AbstractContextProvider
*
*
* Base class for DeploymentManager Providers that can deploy ContextHandlers into
* Jetty that have been discovered via OSGI either as bundles or services.
*
*/
public abstract class AbstractContextProvider extends AbstractLifeCycle implements AppProvider
{
private static final Logger LOG = Log.getLogger(AbstractContextProvider.class);
private DeploymentManager _deploymentManager;
private DeploymentManager _deploymentManager;
private ServerInstanceWrapper _serverWrapper;
@ -65,7 +61,7 @@ public abstract class AbstractContextProvider extends AbstractLifeCycle implemen
/* ------------------------------------------------------------ */
/**
* BundleApp
* OSGiApp
*
*
*/

View File

@ -32,9 +32,10 @@ import org.osgi.framework.ServiceRegistration;
/**
* AbstractBundleApp
*
* AbstractOSGiApp
*
* Base class representing info about a webapp/ContextHandler that is deployed into Jetty.
*
*/
public abstract class AbstractOSGiApp extends App
{

View File

@ -20,14 +20,9 @@ package org.eclipse.jetty.osgi.boot;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.AppProvider;
@ -35,7 +30,6 @@ import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
import org.eclipse.jetty.osgi.boot.internal.webapp.OSGiWebappClassLoader;
import org.eclipse.jetty.osgi.boot.utils.EventSender;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
@ -44,9 +38,7 @@ import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.packageadmin.PackageAdmin;
@ -55,7 +47,9 @@ import org.osgi.service.packageadmin.PackageAdmin;
/**
* AbstractWebAppProvider
*
*
* Base class for Jetty DeploymentManager Providers that are capable of deploying a webapp,
* either from a bundle or an OSGi service.
*
*/
public abstract class AbstractWebAppProvider extends AbstractLifeCycle implements AppProvider
{
@ -64,10 +58,9 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement
public static String __defaultConfigurations[] = {
"org.eclipse.jetty.osgi.boot.OSGiWebInfConfiguration",
"org.eclipse.jetty.webapp.WebXmlConfiguration",
"org.eclipse.jetty.osgi.boot.OSGiMetaInfConfiguration",
"org.eclipse.jetty.webapp.MetaInfConfiguration",
"org.eclipse.jetty.webapp.FragmentConfiguration",
"org.eclipse.jetty.webapp.JettyWebXmlConfiguration"//,
//"org.eclipse.jetty.osgi.boot.jsp.TagLibOSGiConfiguration"
"org.eclipse.jetty.webapp.JettyWebXmlConfiguration"
};
public static void setDefaultConfigurations (String[] defaultConfigs)

View File

@ -26,16 +26,11 @@ import java.util.List;
import java.util.Map;
import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
import org.eclipse.jetty.osgi.boot.utils.EventSender;
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.webapp.WebAppContext;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
@ -43,7 +38,7 @@ import org.osgi.framework.ServiceRegistration;
/**
* BundleContextProvider
*
* Handles deploying bundles that define a context xml file for configuring them.
* Handles deploying OSGi bundles that define a context xml file for configuring them.
*
*
*/
@ -136,6 +131,7 @@ public class BundleContextProvider extends AbstractContextProvider implements Bu
}
apps.add(app);
getDeploymentManager().addApp(app);
added = true;
}
return added; //true if even 1 context from this bundle was added

View File

@ -20,6 +20,11 @@ package org.eclipse.jetty.osgi.boot;
import org.osgi.framework.Bundle;
/**
* BundleProvider
*
* Jetty DeploymentManager Provider api for webapps or ContextHandlers that are discovered as osgi bundles.
*/
public interface BundleProvider
{
public boolean bundleAdded (Bundle bundle) throws Exception;

View File

@ -25,7 +25,6 @@ import java.util.Map;
import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
import org.eclipse.jetty.osgi.boot.utils.EventSender;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.osgi.framework.Bundle;

View File

@ -18,45 +18,35 @@
package org.eclipse.jetty.osgi.boot;
import java.util.Dictionary;
import java.util.Hashtable;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.DefaultJettyAtJettyHomeHelper;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.JettyServerServiceTracker;
import org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper;
import org.eclipse.jetty.osgi.boot.internal.webapp.JettyContextHandlerServiceTracker;
import org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleTrackerCustomizer;
import org.eclipse.jetty.osgi.boot.internal.webapp.BundleWatcher;
import org.eclipse.jetty.osgi.boot.internal.webapp.ServiceWatcher;
import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceRegistration;
import org.osgi.util.tracker.BundleTracker;
/**
* JettyBootstrapActivator
*
* Bootstrap jetty and publish a default Server instance as an OSGi service.
*
* Listen for other Server instances to be published as services and support them as deployment targets.
*
* Listen for Bundles to be activated, and deploy those that represent webapps to one of the known Server instances.
* Listen for Bundles to be activated, and deploy those that represent webapps/ContextHandlers to one of the known Server instances.
*
* <ol>
* <li>basic servlet [ok]</li>
* <li>basic jetty.xml [ok]</li>
* <li>basic jetty.xml and jetty-plus.xml [ok]</li>
* <li>basic jsp [ok]</li>
* <li>jsp with tag-libs [ok]</li>
* <li>test-jndi with atomikos and derby inside ${jetty.home}/lib/ext [ok]</li>
* </ul>
*/
public class JettyBootstrapActivator implements BundleActivator
{
private static final Logger LOG = Log.getLogger(JettyBootstrapActivator.class);
private static JettyBootstrapActivator INSTANCE = null;
public static JettyBootstrapActivator getInstance()
@ -66,7 +56,7 @@ public class JettyBootstrapActivator implements BundleActivator
private ServiceRegistration _registeredServer;
private JettyContextHandlerServiceTracker _jettyContextHandlerTracker;
private ServiceWatcher _jettyContextHandlerTracker;
private PackageAdminServiceTracker _packageAdminServiceTracker;
@ -75,7 +65,10 @@ public class JettyBootstrapActivator implements BundleActivator
private BundleContext _bundleContext;
private JettyServerServiceTracker _jettyServerServiceTracker;
/* ------------------------------------------------------------ */
/**
* Setup a new jetty Server, registers it as a service. Setup the Service
* tracker for the jetty ContextHandlers that are in charge of deploying the
@ -84,7 +77,7 @@ public class JettyBootstrapActivator implements BundleActivator
*
* @param context
*/
public void start(BundleContext context) throws Exception
public void start(final BundleContext context) throws Exception
{
INSTANCE = this;
_bundleContext = context;
@ -98,18 +91,23 @@ public class JettyBootstrapActivator implements BundleActivator
context.addServiceListener(_jettyServerServiceTracker, "(objectclass=" + Server.class.getName() + ")");
// track ContextHandler class instances and deploy them to one of the known Servers
_jettyContextHandlerTracker = new JettyContextHandlerServiceTracker();
_jettyContextHandlerTracker = new ServiceWatcher();
context.addServiceListener(_jettyContextHandlerTracker, "(objectclass=" + ContextHandler.class.getName() + ")");
// Create a default jetty instance right now.
DefaultJettyAtJettyHomeHelper.startJettyAtJettyHome(context);
Server defaultServer = DefaultJettyAtJettyHomeHelper.startJettyAtJettyHome(context);
// track Bundles and deploy those that represent webapps to one of the known Servers
WebBundleTrackerCustomizer customizer = new WebBundleTrackerCustomizer();
_webBundleTracker = new BundleTracker(context, Bundle.ACTIVE | Bundle.STOPPING, customizer);
customizer.setAndOpenWebBundleTracker(_webBundleTracker);
//Create a bundle tracker to help deploy webapps and ContextHandlers
BundleWatcher bundleTrackerCustomizer = new BundleWatcher();
bundleTrackerCustomizer.setWaitForDefaultServer(defaultServer != null);
_webBundleTracker = new BundleTracker(context, Bundle.ACTIVE | Bundle.STOPPING, bundleTrackerCustomizer);
bundleTrackerCustomizer.setBundleTracker(_webBundleTracker);
bundleTrackerCustomizer.open();
}
/* ------------------------------------------------------------ */
/**
* Stop the activator.
*
@ -120,7 +118,6 @@ public class JettyBootstrapActivator implements BundleActivator
{
try
{
if (_webBundleTracker != null)
{
_webBundleTracker.close();
@ -164,122 +161,4 @@ public class JettyBootstrapActivator implements BundleActivator
INSTANCE = null;
}
}
/**
* Helper method that creates a new org.jetty.webapp.WebAppContext and
* 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 "/"
* @throws Exception
*/
public static void registerWebapplication(Bundle contributor, String webappFolderPath, String contextPath) throws Exception
{
checkBundleActivated();
WebAppContext contextHandler = new WebAppContext();
Dictionary<String,String> dic = new Hashtable<String,String>();
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);
}
/**
* Helper method that creates a new org.jetty.webapp.WebAppContext and
* 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
* @throws Exception
*/
public static void registerWebapplication(Bundle contributor, String webappFolderPath, String contextPath, Dictionary<String, String> dic) throws Exception
{
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);
}
/**
* Helper method that creates a new skeleton of a ContextHandler and
* 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.
* @throws Exception
*/
public static void registerContext(Bundle contributor, String contextFilePath) throws Exception
{
registerContext(contributor, contextFilePath, new Hashtable<String, String>());
}
/**
* Helper method that creates a new skeleton of a ContextHandler and
* 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
* @throws Exception
*/
public static void registerContext(Bundle contributor, String contextFilePath, Dictionary<String, String> dic) throws Exception
{
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);
}
public static void unregister(String contextPath)
{
// todo
}
/**
* Since org.eclipse.jetty.osgi.boot does not have a lazy activation policy
* when one of the static methods to register a webapp is called we should
* make sure that the bundle is started.
*/
private static void checkBundleActivated()
{
if (INSTANCE == null)
{
Bundle thisBundle = FrameworkUtil.getBundle(JettyBootstrapActivator.class);
try
{
thisBundle.start();
}
catch (BundleException e)
{
// nevermind.
}
}
}
/**
* @return The bundle context for this bundle.
*/
public static BundleContext getBundleContext()
{
checkBundleActivated();
return INSTANCE._bundleContext;
}
}

View File

@ -27,7 +27,9 @@ import org.eclipse.jetty.osgi.boot.utils.EventSender;
/**
* OSGiDeployer
*
*
* Extension of standard Jetty deployer that emits OSGi EventAdmin
* events whenever a webapp is deployed into OSGi via Jetty.
*
*/
public class OSGiDeployer extends StandardDeployer
{

View File

@ -32,6 +32,14 @@ import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.osgi.framework.Bundle;
/**
* OSGiMetaInfConfiguration
*
* Extension of standard Jetty MetaInfConfiguration class to handle OSGi bundle
* fragments that may also need to be scanned for META-INF info.
*
* @deprecated
*/
public class OSGiMetaInfConfiguration extends MetaInfConfiguration
{
private static final Logger LOG = Log.getLogger(OSGiMetaInfConfiguration.class);

View File

@ -19,6 +19,8 @@
package org.eclipse.jetty.osgi.boot;
/**
* OSGiServerConstants
*
* Name of the properties that configure a jetty Server OSGi service.
*/
public class OSGiServerConstants

View File

@ -29,7 +29,9 @@ import org.eclipse.jetty.osgi.boot.utils.EventSender;
/**
* OSGiUndeployer
*
*
* Extension of the Jetty Undeployer which emits OSGi EventAdmin events
* whenever a webapp is undeployed from Jetty.
*
*/
public class OSGiUndeployer extends StandardUndeployer
{

View File

@ -52,7 +52,7 @@ public class OSGiWebInfConfiguration extends WebInfConfiguration
public static final String CONTAINER_BUNDLE_PATTERN = "org.eclipse.jetty.server.webapp.containerIncludeBundlePattern";
/* ------------------------------------------------------------ */
/**
* Check to see if there have been any bundle symbolic names added of bundles that should be
* regarded as being on the container classpath, and scanned for fragments, tlds etc etc.
@ -120,7 +120,7 @@ public class OSGiWebInfConfiguration extends WebInfConfiguration
}
/* ------------------------------------------------------------ */
/**
* Consider the fragment bundles associated with the bundle of the webapp being deployed.
*
@ -148,7 +148,7 @@ public class OSGiWebInfConfiguration extends WebInfConfiguration
return mergedResources;
}
/* ------------------------------------------------------------ */
/**
* Allow fragments to supply some resources that are added to the baseResource of the webapp.
*
@ -227,11 +227,10 @@ public class OSGiWebInfConfiguration extends WebInfConfiguration
resources[resources.length-1] = context.getBaseResource();
context.setBaseResource(new ResourceCollection(resources));
}
}
/* ------------------------------------------------------------ */
/**
* Resolves the bundle. Usually that would be a single URL per bundle. But we do some more work if there are jars
* embedded in the bundle.

View File

@ -19,7 +19,12 @@
package org.eclipse.jetty.osgi.boot;
/**
* Name of the service properties for a ContextHandler that configure a webapp deployed on jetty OSGi.
* OSGiWebappConstants
*
*
* Constants (MANIFEST headers, service properties etc) associated with deploying
* webapps into OSGi via Jetty.
*
*/
public class OSGiWebappConstants
{

View File

@ -38,7 +38,9 @@ import org.osgi.framework.ServiceRegistration;
/**
* ServiceContextProvider
*
*
* Jetty DeploymentManager Provider that is able to deploy ContextHandlers discovered via OSGi as services.
*
*
*/
public class ServiceContextProvider extends AbstractContextProvider implements ServiceProvider
{

View File

@ -21,6 +21,11 @@ package org.eclipse.jetty.osgi.boot;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.osgi.framework.ServiceReference;
/**
* ServiceProvider
*
* Jetty DeploymentManager Provider api for webapps or ContextHandlers that are discovered as OSGi services.
*/
public interface ServiceProvider
{
public boolean serviceAdded (ServiceReference ref, ContextHandler handler) throws Exception;

View File

@ -27,7 +27,6 @@ import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.AppProvider;
import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
import org.eclipse.jetty.osgi.boot.utils.EventSender;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

View File

@ -1,69 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.osgi.boot.internal.jsp;
import java.net.URL;
/**
* Add a classloader to the
* org.apache.jasper.compiler.TldLocatableURLClassloader. Hopefuly not
* necessary: still experimenting.
*
* @see TldLocatableURLClassloader
*/
public class TldLocatableURLClassloaderWithInsertedJettyClassloader extends TldLocatableURLClassloader
{
private ClassLoader _internalClassLoader;
/**
*
* @param osgiClassLoaderParent
* The parent classloader
* @param internalClassLoader
* The classloader that will be at the same level than the
* jarsWithTldsInside
* @param jarsWithTldsInside
* jars that are scanned for tld files.
*/
public TldLocatableURLClassloaderWithInsertedJettyClassloader(ClassLoader osgiClassLoaderParent, ClassLoader internalClassLoader, URL[] jarsWithTldsInside)
{
super(osgiClassLoaderParent,jarsWithTldsInside);
_internalClassLoader = internalClassLoader;
}
protected Class<?> findClass(String name) throws ClassNotFoundException
{
try
{
return super.findClass(name);
}
catch (ClassNotFoundException cne)
{
if (_internalClassLoader != null)
{
return _internalClassLoader.loadClass(name);
}
else
{
throw cne;
}
}
}
}

View File

@ -29,7 +29,6 @@ import java.util.StringTokenizer;
import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator;
import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -40,9 +39,12 @@ import org.osgi.framework.BundleContext;
* DefaultJettyAtJettyHomeHelper
*
*
* Creates a default instance of Jetty, based on the values of the
* System properties "jetty.home" or "jetty.home.bundle", one of which
* must be specified in order to create the default instance.
*
* Called by the {@link JettyBootstrapActivator} during the starting of the
* bundle. If the system property 'jetty.home' is defined and points to a
* folder, then setup the corresponding jetty server.
* bundle.
*/
public class DefaultJettyAtJettyHomeHelper
{
@ -64,6 +66,7 @@ public class DefaultJettyAtJettyHomeHelper
public static final String DEFAULT_JETTYHOME = "/jettyhome/";
/* ------------------------------------------------------------ */
/**
* Called by the JettyBootStrapActivator. If the system property jetty.home
@ -87,7 +90,7 @@ public class DefaultJettyAtJettyHomeHelper
* as part of their properties.
* </p>
*/
public static void startJettyAtJettyHome(BundleContext bundleContext) throws Exception
public static Server startJettyAtJettyHome(BundleContext bundleContext) throws Exception
{
String jettyHomeSysProp = System.getProperty(OSGiServerConstants.JETTY_HOME);
String jettyHomeBundleSysProp = System.getProperty(OSGiServerConstants.JETTY_HOME_BUNDLE);
@ -109,7 +112,7 @@ public class DefaultJettyAtJettyHomeHelper
if (!jettyHome.exists() || !jettyHome.isDirectory())
{
LOG.warn("Unable to locate the jetty.home folder " + jettyHomeSysProp);
return;
return null;
}
}
else if (jettyHomeBundleSysProp != null)
@ -126,14 +129,14 @@ public class DefaultJettyAtJettyHomeHelper
if (jettyHomeBundle == null)
{
LOG.warn("Unable to find the jetty.home.bundle named " + jettyHomeSysProp);
return;
return null;
}
}
if (jettyHome == null && jettyHomeBundle == null)
{
LOG.warn("No default jetty created.");
return;
return null;
}
Server server = new Server();
@ -152,8 +155,11 @@ public class DefaultJettyAtJettyHomeHelper
setProperty(properties, OSGiServerConstants.JETTY_PORT, System.getProperty(OSGiServerConstants.JETTY_PORT));
setProperty(properties, OSGiServerConstants.JETTY_PORT_SSL, System.getProperty(OSGiServerConstants.JETTY_PORT_SSL));
//register the Server instance as an OSGi service.
//Register the default Server instance as an OSGi service.
//The JettyServerServiceTracker will notice it and configure it.
bundleContext.registerService(Server.class.getName(), server, properties);
return server;
}

View File

@ -32,8 +32,11 @@ import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
/**
* Deploy the jetty server instances when they are registered as an OSGi
* service.
* JettyServerServiceTracker
*
* Tracks instances of Jetty Servers, and configures them so that they can deploy
* webapps or ContextHandlers discovered from the OSGi environment.
*
*/
public class JettyServerServiceTracker implements ServiceListener, IManagedJettyServerRegistry
{

View File

@ -19,7 +19,6 @@
package org.eclipse.jetty.osgi.boot.internal.serverfactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
@ -27,8 +26,10 @@ import java.util.Collection;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import org.eclipse.jetty.deploy.AppLifeCycle;
@ -44,11 +45,10 @@ import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
import org.eclipse.jetty.osgi.boot.OSGiUndeployer;
import org.eclipse.jetty.osgi.boot.ServiceContextProvider;
import org.eclipse.jetty.osgi.boot.ServiceWebAppProvider;
import org.eclipse.jetty.osgi.boot.internal.jsp.TldLocatableURLClassloader;
import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
import org.eclipse.jetty.osgi.boot.internal.webapp.LibExtClassLoaderHelper;
import org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleTrackerCustomizer;
import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer;
import org.eclipse.jetty.osgi.boot.utils.FakeURLClassLoader;
import org.eclipse.jetty.osgi.boot.utils.TldBundleDiscoverer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.util.IO;
@ -72,6 +72,9 @@ public class ServerInstanceWrapper
* support the case where the bundle is zipped.
*/
public static final String PROPERTY_THIS_JETTY_XML_FOLDER_URL = "this.jetty.xml.parent.folder.url";
private static Collection<TldBundleDiscoverer> __containerTldBundleDiscoverers = new ArrayList<TldBundleDiscoverer>();
private static Logger LOG = Log.getLogger(ServerInstanceWrapper.class.getName());
@ -96,6 +99,21 @@ public class ServerInstanceWrapper
private DeploymentManager _deploymentManager;
/* ------------------------------------------------------------ */
public static void addContainerTldBundleDiscoverer (TldBundleDiscoverer tldBundleDiscoverer)
{
__containerTldBundleDiscoverers.add(tldBundleDiscoverer);
}
/* ------------------------------------------------------------ */
public static Collection<TldBundleDiscoverer> getContainerTldBundleDiscoverers()
{
return __containerTldBundleDiscoverers;
}
/* ------------------------------------------------------------ */
public ServerInstanceWrapper(String managedServerName)
{
@ -173,9 +191,29 @@ public class ServerInstanceWrapper
configure(server, props);
init();
//if support for jsp is enabled, we need to convert locations of bundles that contain tlds into urls.
//these are tlds that we want jasper to treat as if they are on the container's classpath. Web bundles
//can use the Require-TldBundle MANIFEST header to name other tld-containing bundles that should be regarded
//as on the webapp classpath.
if (!__containerTldBundleDiscoverers.isEmpty())
{
Set<URL> urls = new HashSet<URL>();
//discover bundles with tlds that need to be on the container's classpath as URLs
for (TldBundleDiscoverer d:__containerTldBundleDiscoverers)
{
URL[] list = d.getUrlsForBundlesWithTlds(_deploymentManager, BundleFileLocatorHelperFactory.getFactory().getHelper());
if (list != null)
{
for (URL u:list)
urls.add(u);
}
}
_commonParentClassLoaderForWebapps = new FakeURLClassLoader(libExtClassLoader, urls.toArray(new URL[urls.size()]));
}
else
_commonParentClassLoaderForWebapps = libExtClassLoader;
URL[] jarsWithTlds = getJarsWithTlds();
_commonParentClassLoaderForWebapps = jarsWithTlds == null ? libExtClassLoader : new TldLocatableURLClassloader(libExtClassLoader, jarsWithTlds);
if (LOG.isDebugEnabled()) LOG.debug("common classloader = "+_commonParentClassLoaderForWebapps);
@ -219,54 +257,7 @@ public class ServerInstanceWrapper
}
/* ------------------------------------------------------------ */
/**
* TODO: right now only the jetty-jsp bundle is scanned for common taglibs.
* Should support a way to plug more bundles that contain taglibs.
*
* 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 implementation.
*
* 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 development situations)
* Unsupported: the bundle is a jar that embeds more jars.
*
* @return
* @throws Exception
*/
private URL[] getJarsWithTlds() throws Exception
{
//Jars that are added onto the equivalent of the container classpath are:
// jstl jars: identified by the class WhenTag (and the boot-bundle manifest imports the jstl packages
// bundles identified by System property org.eclipse.jetty.osgi.tldbundles
// bundle symbolic name patterns defined in the DeploymentManager
//
// Any bundles mentioned in the Require-TldBundle manifest header of the webapp bundle MUST ALSO HAVE Import-Bundle
// in order to get them onto the classpath of the webapp.
ArrayList<URL> res = new ArrayList<URL>();
for (WebappRegistrationCustomizer regCustomizer : WebBundleTrackerCustomizer.JSP_REGISTRATION_HELPERS)
{
URL[] urls = regCustomizer.getJarsWithTlds(_deploymentManager, BundleFileLocatorHelperFactory.getFactory().getHelper());
for (URL url : urls)
{
if (!res.contains(url)) res.add(url);
}
}
if (!res.isEmpty())
return res.toArray(new URL[res.size()]);
else
return null;
}
/* ------------------------------------------------------------ */
private void configure(Server server, Dictionary props) throws Exception
@ -340,7 +331,9 @@ public class ServerInstanceWrapper
}
}
/* ------------------------------------------------------------ */
/**
* Must be called after the server is configured.
*
@ -438,7 +431,9 @@ public class ServerInstanceWrapper
}
}
}
/* ------------------------------------------------------------ */
/**
* @return The default folder in which the context files of the osgi bundles
* are located and watched. Or null when the system property
@ -463,7 +458,7 @@ public class ServerInstanceWrapper
return new File(jettyHome, "/contexts");
}
/* ------------------------------------------------------------ */
/**
* @return the urls in this string.
*/
@ -485,7 +480,9 @@ public class ServerInstanceWrapper
}
return urls;
}
/* ------------------------------------------------------------ */
/**
* Get the folders that might contain jars for the legacy J2EE shared
* libraries

View File

@ -21,10 +21,14 @@ package org.eclipse.jetty.osgi.boot.internal.webapp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.jetty.osgi.boot.BundleProvider;
import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer;
import org.eclipse.jetty.osgi.boot.utils.TldBundleDiscoverer;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.osgi.framework.Bundle;
@ -36,52 +40,127 @@ import org.osgi.util.tracker.BundleTrackerCustomizer;
import org.osgi.util.tracker.ServiceTracker;
/**
* WebBundleTrackerCustomizer
* BundleWatcher
*
*
* Support bundles that declare a webpp or context directly through headers in their
* manifest. They will be deployed to the default jetty Server instance.
*
* If you wish to deploy a context or webapp to a different jetty Server instance,
* register your context/webapp as an osgi service, and set the property OSGiServerConstants.MANAGED_JETTY_SERVER_NAME
* with the name of the Server instance you wish to depoy to.
* Tracks the installation and removal of Bundles in the OSGi environment. Any bundles
* that are added are passed to the set of Jetty DeploymentManager providers to see if
* the bundle should be deployed as a webapp or ContextHandler into Jetty.
*
* @author hmalphettes
*/
public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
public class BundleWatcher implements BundleTrackerCustomizer
{
private static final Logger LOG = Log.getLogger(WebBundleTrackerCustomizer.class);
private static final Logger LOG = Log.getLogger(BundleWatcher.class);
public static Collection<WebappRegistrationCustomizer> JSP_REGISTRATION_HELPERS = new ArrayList<WebappRegistrationCustomizer>();
public static final String FILTER = "(&(objectclass=" + BundleProvider.class.getName() + ")"+
"("+OSGiServerConstants.MANAGED_JETTY_SERVER_NAME+"="+OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME+"))";
public static Collection<TldBundleDiscoverer> JSP_REGISTRATION_HELPERS = new ArrayList<TldBundleDiscoverer>();
public static final String FILTER = "(objectclass=" + BundleProvider.class.getName() + ")";
private ServiceTracker _serviceTracker;
private BundleTracker _bundleTracker;
private boolean _waitForDefaultServer = true;
private boolean _defaultServerReady = false;
private Bundle _bundle = null;
/* ------------------------------------------------------------ */
/**
* @throws Exception
*/
public WebBundleTrackerCustomizer ()
throws Exception
public BundleWatcher() throws Exception
{
Bundle myBundle = FrameworkUtil.getBundle(this.getClass());
//track all instances of deployers of webapps/contexts as bundles
_serviceTracker = new ServiceTracker(myBundle.getBundleContext(), FrameworkUtil.createFilter(FILTER),null) {
public Object addingService(ServiceReference reference) {
Object object = super.addingService(reference);
LOG.debug("Deployer registered {}", reference);
openBundleTracker();
return object;
}
};
_bundle = FrameworkUtil.getBundle(this.getClass());
//Track all BundleProviders (Jetty DeploymentManager Providers that can deploy bundles)
_serviceTracker = new ServiceTracker(_bundle.getBundleContext(), FrameworkUtil.createFilter(FILTER),null);
_serviceTracker.open();
}
/* ------------------------------------------------------------ */
public boolean isWaitForDefaultServer()
{
return _waitForDefaultServer;
}
/* ------------------------------------------------------------ */
public void setWaitForDefaultServer(boolean waitForDefaultServer)
{
_waitForDefaultServer = waitForDefaultServer;
}
/* ------------------------------------------------------------ */
public void setBundleTracker (BundleTracker bundleTracker)
{
_bundleTracker = bundleTracker;
}
/* ------------------------------------------------------------ */
public void open () throws Exception
{
if (_waitForDefaultServer && !_defaultServerReady)
{
String filter = "(&(objectclass=" + BundleProvider.class.getName() + ")"+
"("+OSGiServerConstants.MANAGED_JETTY_SERVER_NAME+"="+OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME+"))";
ServiceTracker defaultServerTracker = new ServiceTracker(_bundle.getBundleContext(),
FrameworkUtil.createFilter(filter),null)
{
public Object addingService(ServiceReference reference)
{
try
{
Object object = super.addingService(reference);
LOG.debug("Default Jetty Server registered {}", reference);
_defaultServerReady = true;
openBundleTracker();
return object;
}
catch (Exception e)
{
throw new IllegalStateException(e);
}
}
};
defaultServerTracker.open();
}
else
openBundleTracker();
}
/* ------------------------------------------------------------ */
/**
* @param managedServerName
* @return
*/
public Map<ServiceReference, BundleProvider> getDeployers(String managedServerName)
{
if (managedServerName == null)
managedServerName = OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME;
Map<ServiceReference, BundleProvider> candidates = new HashMap<ServiceReference, BundleProvider>();
ServiceReference[] references = _serviceTracker.getServiceReferences();
if (references != null)
{
for (ServiceReference ref:references)
{
String name = (String)ref.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
if (managedServerName.equalsIgnoreCase(name))
{
BundleProvider candidate = (BundleProvider)_serviceTracker.getService(ref);
if (candidate != null)
candidates.put(ref, candidate);
}
}
}
return candidates;
}
/* ------------------------------------------------------------ */
/**
* A bundle is being added to the <code>BundleTracker</code>.
@ -138,8 +217,6 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
*/
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);
@ -171,35 +248,40 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
}
protected void openBundleTracker()
{
_bundleTracker.open();
}
/* ------------------------------------------------------------ */
/**
* @param bundle
* @return true if this bundle in indeed a web-bundle.
* @return true if this bundle can be deployed into Jetty
*/
private boolean register(Bundle bundle)
{
if (bundle == null)
return false;
//It might be a bundle that we can deploy to our default jetty server instance
//It might be a bundle that is deployable by Jetty.
//Use any named Server instance provided, defaulting to the default Server instance if none supplied
boolean deployed = false;
Object[] deployers = _serviceTracker.getServices();
if (deployers != null)
String serverName = (String)bundle.getHeaders().get(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
Map<ServiceReference, BundleProvider> candidates = getDeployers(serverName);
if (candidates != null)
{
int i=0;
while (!deployed && i<deployers.length)
Iterator<Entry<ServiceReference, BundleProvider>> itor = candidates.entrySet().iterator();
while (!deployed && itor.hasNext())
{
BundleProvider p = (BundleProvider)deployers[i];
Entry<ServiceReference, BundleProvider> e = itor.next();
try
{
deployed = p.bundleAdded(bundle);
{
deployed = e.getValue().bundleAdded(bundle);
}
catch (Exception x)
{
LOG.warn("Error deploying bundle for jetty context", x);
}
i++;
}
}
@ -212,39 +294,24 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
*/
private void unregister(Bundle bundle)
{
Object[] deployers = _serviceTracker.getServices();
boolean undeployed = false;
if (deployers != null)
String serverName = (String)bundle.getHeaders().get(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
Map<ServiceReference, BundleProvider> candidates = getDeployers(serverName);
if (candidates != null)
{
int i=0;
while (!undeployed && i<deployers.length)
Iterator<Entry<ServiceReference, BundleProvider>> itor = candidates.entrySet().iterator();
while (!undeployed && itor.hasNext())
{
Entry<ServiceReference, BundleProvider> e = itor.next();
try
{
undeployed = ((BundleProvider)deployers[i++]).bundleRemoved(bundle);
undeployed = e.getValue().bundleRemoved(bundle);
}
catch (Exception x)
{
LOG.warn("Error undeploying bundle for jetty context", x);
LOG.warn("Error undeploying Bundle representing jetty deployable ", x);
}
}
}
}
public void setAndOpenWebBundleTracker(BundleTracker bundleTracker) {
if(_bundleTracker == null) {
_bundleTracker = bundleTracker;
LOG.debug("Bundle tracker is set");
openBundleTracker();
}
}
private void openBundleTracker() {
if(_bundleTracker != null && _serviceTracker.getServices() != null &&
_serviceTracker.getServices().length > 0) {
_bundleTracker.open();
LOG.debug("Bundle tracker has been opened");
}
}
}

View File

@ -1,88 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.osgi.boot.internal.webapp;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.webapp.WebAppContext;
import org.osgi.framework.Bundle;
/**
* Internal interface for the class that deploys a webapp on a server. Used as
* we migrate from the single instance of the jety server to multiple jetty
* servers.
*/
public interface IWebBundleDeployerHelper
{
/**
* when this property is present, the type of context handler registered is
* not known in advance.
*/
public static final String INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE = "unknownContextHandlerType";
/**
* 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 extraClasspath
* @param overrideBundleInstallLocation
* @param requireTldBundle The list of bundles's symbolic names that contain
* tld files that are required by this WAB.
* @param webXmlPath
* @param defaultWebXmlPath TODO: parameter description
* @return The contexthandler created and started
* @throws Exception
*/
public abstract WebAppContext registerWebapplication(Bundle bundle, String webappFolderPath, String contextPath, String extraClasspath,
String overrideBundleInstallLocation, String requireTldBundle, String webXmlPath,
String defaultWebXmlPath, WebAppContext webAppContext) throws Exception;
/**
* Stop a ContextHandler and remove it from the collection.
*
* @see ContextDeployer#undeploy
* @param contextHandler
* @throws Exception
*/
public abstract void unregister(ContextHandler contextHandler) throws Exception;
/**
* This type of registration relies on jetty's complete context xml file.
* Context encompasses jndi and all other things. This makes the definition
* of the webapp a lot more self-contained.
*
* @param contributor
* @param contextFileRelativePath
* @param extraClasspath
* @param overrideBundleInstallLocation
* @param requireTldBundle The list of bundles'symbolic name that contain
* tld files for this webapp.
* @param handler the context handler passed in the server reference that
* will be configured, deployed and started.
* @return The contexthandler created and started
* @throws Exception
*/
public abstract ContextHandler registerContext(Bundle contributor, String contextFileRelativePath, String extraClasspath,
String overrideBundleInstallLocation, String requireTldBundle, ContextHandler handler) throws Exception;
}

View File

@ -33,6 +33,9 @@ import java.util.Set;
import org.eclipse.jetty.server.Server;
/**
* LibExtClassLoaderHelper
*
*
* Helper to create a URL class-loader with the jars inside
* ${jetty.home}/lib/ext and ${jetty.home}/resources. In an ideal world, every
* library is an OSGi bundle that does loads nicely. To support standard jars or
@ -40,57 +43,40 @@ import org.eclipse.jetty.server.Server;
* inserting the jars in the usual jetty/lib/ext folders in the proper classpath
* for the webapps.
* <p>
* Also the folder resources typically contains central configuration files for
* things like: log config and others. We enable fragments to register classes
* that are called back and passed those resources to do what they need to do.
* The drawback is that those jars will not be available in the OSGi
* classloader.
* </p>
* <p>
* For example the test-jndi webapplication depends on derby, derbytools,
* atomikos none of them are osgi bundles. we can either re-package them or we
* can place them in the usual lib/ext. <br/>
* In fact jasper's jsp libraries should maybe place in lib/ext too.
* </p>
* <p>
* The drawback is that those libraries will not be available in the OSGi
* classloader. Note that we could have setup those jars as embedded jars of the
* current bundle. However, we would need to know in advance what are those jars
* which was not acceptable. Also having those jars in a URLClassLoader seem to
* be required for some cases. For example jaspers' TldLocationsCache (replaced
* by TldScanner for servlet-3.0). <br/>
* Also all the dependencies of those libraries must be resolvable directly from
* the JettyBootstrapActivator bundle as it is set as the parent classloader. For
* example: if atomikos is placed in lib/ext it will work if and only if
* JettyBootstrapActivator import the necessary packages from javax.naming*,
* javax.transaction*, javax.mail* etc Most of the common cases of javax are
* added as optional import packages into jetty bootstrapper plugin. When there
* are not covered: please make a request or create a fragment or register a
* bundle with a buddy-policy onto the jetty bootstrapper..
* </p>
* <p>
* Alternatives to placing jars in lib/ext
* Alternatives to placing jars in lib/ext:
* <ol>
* <li>Bundle the jars in an osgi bundle. Have the webapp(s) that context
* depends on them depend on that bundle. Things will go well for jetty.</li>
* <li>Bundle the jars in an osgi bundle. Have the webapp(s) that need these jars
* depend on that bundle.</li>
* <li>Bundle those jars in an osgi bundle-fragment that targets the
* jetty-bootstrap bundle</li>
* <li>Use equinox Buddy-Policy: register a buddy of the jetty bootstrapper
* bundle. (least favorite: it will work only on equinox)</li>
* bundle. (Note: it will work only on equinox)</li>
* </ol>
* </p>
*/
public class LibExtClassLoaderHelper
{
/* ------------------------------------------------------------ */
/**
* Class called back
* IFilesInJettyHomeResourcesProcessor
*
* Interface for callback impls
*/
public interface IFilesInJettyHomeResourcesProcessor
{
void processFilesInResourcesFolder(File jettyHome, Map<String, File> filesInResourcesFolder);
}
public static Set<IFilesInJettyHomeResourcesProcessor> registeredFilesInJettyHomeResourcesProcessors = new HashSet<IFilesInJettyHomeResourcesProcessor>();
/* ------------------------------------------------------------ */
/**
* @param server
* @return a url classloader with the jars of resources, lib/ext and the
@ -145,6 +131,8 @@ public class LibExtClassLoaderHelper
return new URLClassLoader(urls.toArray(new URL[urls.size()]), parentClassLoader);
}
/* ------------------------------------------------------------ */
/**
* @param server
* @return a url classloader with the jars of resources, lib/ext and the
@ -188,6 +176,7 @@ public class LibExtClassLoaderHelper
return new URLClassLoader(urls.toArray(new URL[urls.size()]), parentClassLoader);
}
/* ------------------------------------------------------------ */
/**
* When we find files typically used for central logging configuration we do
* what it takes in this method to do what the user expects. Without

View File

@ -33,7 +33,6 @@ import java.util.jar.JarFile;
import javax.servlet.http.HttpServlet;
import org.eclipse.jetty.osgi.boot.utils.BundleClassLoaderHelper;
import org.eclipse.jetty.osgi.boot.utils.BundleClassLoaderHelperFactory;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -44,8 +43,10 @@ import org.osgi.framework.Bundle;
import org.osgi.framework.BundleReference;
/**
* Extends the webappclassloader to insert the classloader provided by the osgi
* bundle at the same level than any other jars palced in the webappclassloader.
* OSGiWebappClassLoader
*
*
* Extends the webapp classloader to also use the classloader of the Bundle defining the webapp.
*/
public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleReference
{
@ -79,10 +80,9 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
private boolean _lookInOsgiFirst = true;
private Set<String> _libsAlreadyInManifest = new HashSet<String>();
/* ------------------------------------------------------------ */
/**
* @param parent The parent classloader. In this case
* @param parent The parent classloader.
* @param context The WebAppContext
* @param contributor The bundle that defines this web-application.
* @throws IOException
@ -94,7 +94,10 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
_contributor = contributor;
_osgiBundleClassLoader = BundleClassLoaderHelperFactory.getFactory().getHelper().getBundleClassLoader(contributor);
}
/* ------------------------------------------------------------ */
/**
* Returns the <code>Bundle</code> that defined this web-application.
*
@ -106,17 +109,7 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
return _contributor;
}
/**
* Reads the manifest. If the manifest is already configured to loads a few
* libs we should not add them to the classpath of the webapp. Not really
* important as we resolve classes through the osgi classloader first and
* then default on the libs of the webapp.
*/
private void computeLibsAlreadyInOSGiClassLoader()
{
// TODO
}
/* ------------------------------------------------------------ */
@Override
public Enumeration<URL> getResources(String name) throws IOException
{
@ -131,7 +124,10 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
return Collections.enumeration(toList(urls, osgiUrls));
}
}
/* ------------------------------------------------------------ */
@Override
public URL getResource(String name)
{
@ -146,7 +142,10 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
return url != null ? url : _osgiBundleClassLoader.getResource(name);
}
}
/* ------------------------------------------------------------ */
private List<URL> toList(Enumeration<URL> e, Enumeration<URL> e2)
{
List<URL> list = new ArrayList<URL>();
@ -157,9 +156,8 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
return list;
}
/**
*
*/
/* ------------------------------------------------------------ */
protected Class<?> findClass(String name) throws ClassNotFoundException
{
try
@ -178,7 +176,10 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
}
}
}
/* ------------------------------------------------------------ */
/**
* Parse the classpath ourselves to be able to filter things. This is a
* derivative work of the super class
@ -207,6 +208,8 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
}
/* ------------------------------------------------------------ */
/**
* @param lib
* @return true if the lib should be included in the webapp classloader.
@ -255,6 +258,8 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
private static Field _contextField;
/* ------------------------------------------------------------ */
/**
* In the case of the generation of a webapp via a jetty context file we
* need a proper classloader to setup the app before we have the

View File

@ -18,28 +18,18 @@
package org.eclipse.jetty.osgi.boot.internal.webapp;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.jetty.osgi.boot.BundleWebAppProvider;
import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator;
import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
import org.eclipse.jetty.osgi.boot.ServiceProvider;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.DefaultJettyAtJettyHomeHelper;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.IManagedJettyServerRegistry;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
import org.eclipse.jetty.server.handler.ContextHandler;
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;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
@ -49,7 +39,7 @@ import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
/**
* JettyContextHandlerServiceTracker
* ServiceWatcher
*
* When a {@link ContextHandler} is activated as an osgi service we find a jetty deployer
* for it. The ContextHandler could be either a WebAppContext or any other derivative of
@ -59,9 +49,9 @@ import org.osgi.util.tracker.ServiceTracker;
* osgi services. Instead, they can be deployed via manifest headers inside bundles. See
* {@link WebBundleTrackerCustomizer}.
*/
public class JettyContextHandlerServiceTracker implements ServiceListener
public class ServiceWatcher implements ServiceListener
{
private static Logger LOG = Log.getLogger(JettyContextHandlerServiceTracker.class);
private static Logger LOG = Log.getLogger(ServiceWatcher.class);
public static final String FILTER = "(objectclass=" + ServiceProvider.class.getName() + ")";
@ -75,7 +65,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
/**
* @param registry
*/
public JettyContextHandlerServiceTracker() throws Exception
public ServiceWatcher() throws Exception
{
//track all instances of deployers of webapps
Bundle myBundle = FrameworkUtil.getBundle(this.getClass());
@ -195,6 +185,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
try
{
added = e.getValue().serviceAdded(sr, contextHandler);
System.err.println(serverName+" deployed "+contextHandler+": "+added);
if (added && LOG.isDebugEnabled())
LOG.debug("Provider "+e.getValue()+" deployed "+contextHandler);
}

View File

@ -22,6 +22,10 @@ import org.eclipse.jetty.osgi.boot.utils.internal.DefaultBundleClassLoaderHelper
import org.osgi.framework.Bundle;
/**
*
* BundleClassLoaderHelper
*
*
* Is there a clean OSGi way to go from the Bundle object to the classloader of
* the Bundle ? You can certainly take a class inside the bundle and get the
* bundle's classloader that way. Getting the classloader directly from the

View File

@ -32,15 +32,19 @@ public class BundleClassLoaderHelperFactory
private static BundleClassLoaderHelperFactory _instance = new BundleClassLoaderHelperFactory();
/* ------------------------------------------------------------ */
public static BundleClassLoaderHelperFactory getFactory()
{
return _instance;
}
/* ------------------------------------------------------------ */
private BundleClassLoaderHelperFactory()
{
}
/* ------------------------------------------------------------ */
public BundleClassLoaderHelper getHelper()
{
//use the default

View File

@ -26,6 +26,9 @@ import org.eclipse.jetty.osgi.boot.utils.internal.DefaultFileLocatorHelper;
import org.osgi.framework.Bundle;
/**
* BundleFileLocatorHelper
*
*
* From a bundle to its location on the filesystem. Assumes the bundle is not a
* jar.
*

View File

@ -21,14 +21,18 @@ package org.eclipse.jetty.osgi.boot.utils;
import java.util.Dictionary;
import java.util.Hashtable;
import javax.security.auth.login.FailedLoginException;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
/**
* EventSender
*
* Utility class for emiting OSGi EventAdmin events
*
*/
public class EventSender
{
//OSGi Event Admin events for webapps
@ -43,6 +47,13 @@ public class EventSender
private Bundle _myBundle;
private EventAdmin _eventAdmin;
/* ------------------------------------------------------------ */
/**
*
*/
private EventSender ()
{
_myBundle = FrameworkUtil.getBundle(EventSender.class);
@ -50,13 +61,27 @@ public class EventSender
if (ref != null)
_eventAdmin = (EventAdmin)_myBundle.getBundleContext().getService(ref);
}
/* ------------------------------------------------------------ */
/**
* @return
*/
public static EventSender getInstance()
{
return __instance;
}
/* ------------------------------------------------------------ */
/**
* @param topic
* @param wab
* @param contextPath
*/
public void send (String topic, Bundle wab, String contextPath)
{
if (topic==null || wab==null || contextPath==null)
@ -66,6 +91,14 @@ public class EventSender
}
/* ------------------------------------------------------------ */
/**
* @param topic
* @param wab
* @param contextPath
* @param ex
*/
public void send (String topic, Bundle wab, String contextPath, Exception ex)
{
if (_eventAdmin == null)

View File

@ -16,29 +16,42 @@
// ========================================================================
//
package org.eclipse.jetty.osgi.boot.internal.jsp;
package org.eclipse.jetty.osgi.boot.utils;
import java.net.URL;
import java.net.URLClassLoader;
/**
* Tricky url classloader. In fact we don't want a real URLClassLoader: we want
* OSGi to provide its classloader and let it does. But to let
* {@link org.apache.jasper.compiler.TldLocationsCache} find the core tlds
* inside the jars we must be a URLClassLoader that returns an array of jars
* where tlds are stored when the method getURLs is called.
*
* FakeURLClassLoader
*
* A URLClassloader that overrides the getURLs() method to return the list
* of urls passed in to the constructor, but otherwise acts as if it has no
* urls, which would cause it to delegate to the parent classloader (in this
* case an OSGi classloader).
*
* The main use of this class is with jars containing tlds. Jasper expects a
* URL classloader to inspect for jars with tlds.
*
*/
public class TldLocatableURLClassloader extends URLClassLoader
public class FakeURLClassLoader extends URLClassLoader
{
private URL[] _jarsWithTldsInside;
public TldLocatableURLClassloader(ClassLoader osgiClassLoader, URL[] jarsWithTldsInside)
private URL[] _jars;
/* ------------------------------------------------------------ */
/**
* @param osgiClassLoader
* @param jars
*/
public FakeURLClassLoader(ClassLoader osgiClassLoader, URL[] jars)
{
super(new URL[] {},osgiClassLoader);
_jarsWithTldsInside = jarsWithTldsInside;
_jars = jars;
}
/* ------------------------------------------------------------ */
/**
* @return the jars that contains tlds so that TldLocationsCache or
* TldScanner can find them.
@ -46,16 +59,21 @@ public class TldLocatableURLClassloader extends URLClassLoader
@Override
public URL[] getURLs()
{
return _jarsWithTldsInside;
return _jars;
}
/* ------------------------------------------------------------ */
/**
* @see java.lang.Object#toString()
*/
public String toString()
{
StringBuilder builder = new StringBuilder();
if (_jarsWithTldsInside != null)
if (_jars != null)
{
for (URL u:_jarsWithTldsInside)
for (URL u:_jars)
builder.append(" "+u.toString());
return builder.toString();
}

View File

@ -78,8 +78,7 @@ public class OSGiClassLoader extends URLClassLoader
}
if (url == null)
{
{
url = _osgiBundleClassLoader.getResource(name);
if (url == null && name.startsWith("/"))

View File

@ -0,0 +1,43 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.osgi.boot.utils;
import java.net.URL;
import org.eclipse.jetty.deploy.DeploymentManager;
/**
* TldBundleDiscoverer
*
* Convert bundles that contain tlds into URL locations for consumption by jasper.
*/
public interface TldBundleDiscoverer
{
/**
* Find bundles that contain tlds and convert into URL references to their location.
*
* @param manager
* @param fileLocator
* @return array of URLs representing locations of tld containing bundles
* @throws Exception
*/
URL[] getUrlsForBundlesWithTlds(DeploymentManager manager, BundleFileLocatorHelper fileLocator) throws Exception;
}

View File

@ -1,61 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.osgi.boot.utils;
import java.net.URL;
import org.eclipse.jetty.deploy.DeploymentManager;
/**
* Fix various shortcomings with the way jasper parses the tld files.
*/
public interface WebappRegistrationCustomizer
{
/**
* we could do something a lot more pluggable with a custom header in the
* manifest or some customer declarative services let's keep it simple for
* now. hopefully the rest of the world won't need to customize this.
*/
public static final String CLASS_NAME = "org.eclipse.jetty.osgi.boot.jasper.WebappRegistrationCustomizerImpl";
/**
* TODO: right now only the jetty-jsp bundle is scanned for common taglibs.
* Should support a way to plug more bundles that contain taglibs.
*
* 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.
*
* 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
*/
URL[] getJarsWithTlds(DeploymentManager manager, BundleFileLocatorHelper fileLocator) throws Exception;
}

View File

@ -28,6 +28,9 @@ import org.eclipse.jetty.util.log.Logger;
import org.osgi.framework.Bundle;
/**
* DefaultBundleClassLoaderHelper
*
*
* Default implementation of the BundleClassLoaderHelper. Uses introspection to
* support equinox-3.5 and felix-2.0.0
*/

View File

@ -31,11 +31,14 @@ 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.eclipse.jetty.util.resource.Resource;
import org.osgi.framework.Bundle;
/**
* DefaultFileLocatorHelper
*
*
* From a bundle to its location on the filesystem. Assumes the bundle is not a
* jar.
*

View File

@ -35,8 +35,14 @@ import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.startlevel.StartLevel;
/**
* PackageAdminServiceTracker
*
*
* When the PackageAdmin service is activated we can look for the fragments
* attached to this bundle and "activate" them.
* attached to this bundle and do a fake "activate" on them.
*
* See particularly the jetty-osgi-boot-jsp fragment bundle that uses this
* facility.
*/
public class PackageAdminServiceTracker implements ServiceListener
{

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>9.0.1-SNAPSHOT</version>
<version>9.0.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-httpservice</artifactId>

View File

@ -1,9 +1,8 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>9.0.1-SNAPSHOT</version>
<version>9.0.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-osgi-npn</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.0.1-SNAPSHOT</version>
<version>9.0.2-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>9.0.1-SNAPSHOT</version>
<version>9.0.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>test-jetty-osgi-context</artifactId>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -47,11 +47,6 @@
<Arg name="minThreads" type="int">10</Arg>
<Arg name="maxThreads" type="int">200</Arg>
<Arg name="idleTimeout" type="int">60000</Arg>
<!-- Arg >
<New class="org.eclipse.jetty.util.ConcurrentArrayBlockingQueue$Unbounded">
<Arg type='int'>32</Arg>
</New>
</Arg -->
<Set name="detailedDump">false</Set>
</New>
</Arg>

View File

@ -289,8 +289,9 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
// If we have a stop timeout
long stopTimeout = getStopTimeout();
if (stopTimeout > 0 && _stopping!=null)
_stopping.await(stopTimeout,TimeUnit.MILLISECONDS);
CountDownLatch stopping=_stopping;
if (stopTimeout > 0 && stopping!=null)
stopping.await(stopTimeout,TimeUnit.MILLISECONDS);
_stopping=null;
super.doStop();
@ -475,7 +476,9 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
{
_acceptors[_acceptor] = null;
}
_stopping.countDown();
CountDownLatch stopping=_stopping;
if (stopping!=null)
stopping.countDown();
}
}
}

View File

@ -22,7 +22,7 @@ import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.util.ConcurrentArrayBlockingQueue;
import org.eclipse.jetty.util.BlockingArrayQueue;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -42,7 +42,7 @@ public class AsyncNCSARequestLog extends NCSARequestLog
{
this(null,null);
}
public AsyncNCSARequestLog(BlockingQueue<String> queue)
{
this(null,queue);
@ -52,12 +52,12 @@ public class AsyncNCSARequestLog extends NCSARequestLog
{
this(filename,null);
}
public AsyncNCSARequestLog(String filename,BlockingQueue<String> queue)
{
super(filename);
if (queue==null)
queue=new ConcurrentArrayBlockingQueue.Bounded<String>(1024);
queue=new BlockingArrayQueue<>(1024);
_queue=queue;
}
@ -67,7 +67,7 @@ public class AsyncNCSARequestLog extends NCSARequestLog
{
setName("AsyncNCSARequestLog@"+Integer.toString(AsyncNCSARequestLog.this.hashCode(),16));
}
@Override
public void run()
{
@ -78,7 +78,7 @@ public class AsyncNCSARequestLog extends NCSARequestLog
String log = _queue.poll(10,TimeUnit.SECONDS);
if (log!=null)
AsyncNCSARequestLog.super.write(log);
while(!_queue.isEmpty())
{
log=_queue.poll();

View File

@ -146,6 +146,7 @@ public class ShutdownMonitor
{
if (isAlive())
{
// TODO why are we reentrant here?
if (DEBUG)
System.err.printf("ShutdownMonitorThread already started");
return; // cannot start it again
@ -353,7 +354,9 @@ public class ShutdownMonitor
{
if (thread != null && thread.isAlive())
{
System.err.printf("ShutdownMonitorThread already started");
// TODO why are we reentrant here?
if (DEBUG)
System.err.printf("ShutdownMonitorThread already started");
return; // cannot start it again
}

View File

@ -303,7 +303,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
*
* @param virtualHosts
* Array of virtual hosts that this context responds to. A null host name or null/empty array means any hostname is acceptable. Host names may be
* String representation of IP addresses. Host names may start with '*.' to wildcard one level of names.
* String representation of IP addresses. Host names may start with '*.' to wildcard one level of names. Host names may start with '@', in which case they
* will match the {@link Connector#getName()} for the request.
*/
public void addVirtualHosts(String[] virtualHosts)
{
@ -817,8 +818,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
if (!_contextListeners.isEmpty())
{
ServletContextEvent event = new ServletContextEvent(_scontext);
for (ServletContextListener listener : _contextListeners)
callContextDestroyed(listener,event);
for (int i = _contextListeners.size(); i-->0;)
callContextDestroyed(_contextListeners.get(i),event);
}
if (_errorHandler != null)
@ -1093,20 +1094,15 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
if (!_requestListeners.isEmpty())
{
final ServletRequestEvent sre = new ServletRequestEvent(_scontext,request);
ListIterator<ServletRequestListener> iter = _requestListeners.listIterator(_requestListeners.size());
while (iter.hasNext())
iter.next();
while (iter.hasPrevious())
iter.previous().requestDestroyed(sre);
for (int i=_requestListeners.size();i-->0;)
_requestListeners.get(i).requestDestroyed(sre);
}
if (!_requestAttributeListeners.isEmpty())
{
ListIterator<ServletRequestAttributeListener> iter = _requestAttributeListeners.listIterator(_requestAttributeListeners.size());
while(iter.hasNext())
iter.next();
while(iter.hasPrevious())
baseRequest.removeEventListener(iter.previous());
for (int i=_requestAttributeListeners.size();i-->0;)
baseRequest.removeEventListener(_requestAttributeListeners.get(i));
}
}
}

View File

@ -80,13 +80,14 @@ public class LowResourcesMonitorTest
@Test
public void testLowOnThreads() throws Exception
{
Thread.sleep(1200);
_threadPool.setMaxThreads(_threadPool.getThreads()-_threadPool.getIdleThreads()+10);
Thread.sleep(1200);
Assert.assertFalse(_lowResourcesMonitor.isLowOnResources());
final CountDownLatch latch = new CountDownLatch(1);
for (int i=0;i<20;i++)
for (int i=0;i<100;i++)
{
_threadPool.dispatch(new Runnable()
{
@ -110,7 +111,6 @@ public class LowResourcesMonitorTest
latch.countDown();
Thread.sleep(1200);
System.err.println(_threadPool.dump());
Assert.assertFalse(_lowResourcesMonitor.isLowOnResources());
}

View File

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

View File

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

View File

@ -26,26 +26,22 @@ import java.util.StringTokenizer;
import java.util.regex.Pattern;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPOutputStream;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.ServletResponseWrapper;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationListener;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.servlets.gzip.AbstractCompressedStream;
import org.eclipse.jetty.servlets.gzip.CompressedResponseWrapper;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.servlets.gzip.GzipOutputStream;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -129,6 +125,9 @@ public class GzipFilter extends UserAgentFilter
protected int _minGzipSize=256;
protected int _deflateCompressionLevel=Deflater.DEFAULT_COMPRESSION;
protected boolean _deflateNoWrap = true;
// non-static, as other GzipFilter instances may have different configurations
protected final ThreadLocal<Deflater> _deflater = new ThreadLocal<Deflater>();
protected final Set<String> _methods=new HashSet<String>();
protected Set<String> _excludedAgents;
@ -296,10 +295,10 @@ public class GzipFilter extends UserAgentFilter
}
finally
{
Continuation continuation = ContinuationSupport.getContinuation(request);
if (continuation.isSuspended() && continuation.isResponseWrapped())
if (request.isAsyncStarted())
{
continuation.addContinuationListener(new ContinuationListenerWaitingForWrappedResponseToFinish(wrappedResponse));
request.getAsyncContext().addListener(new FinishOnCompleteListener(wrappedResponse));
}
else if (exceptional && !response.isCommitted())
{
@ -403,64 +402,55 @@ public class GzipFilter extends UserAgentFilter
protected CompressedResponseWrapper createWrappedResponse(HttpServletRequest request, HttpServletResponse response, final String compressionType)
{
CompressedResponseWrapper wrappedResponse = null;
if (compressionType==null)
wrappedResponse = new CompressedResponseWrapper(request,response)
{
wrappedResponse = new CompressedResponseWrapper(request,response)
@Override
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request, HttpServletResponse response) throws IOException
{
@Override
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
return new AbstractCompressedStream(compressionType,request,this,_vary)
{
return new AbstractCompressedStream(null,request,this,_vary)
private Deflater _allocatedDeflater;
@Override
protected DeflaterOutputStream createStream() throws IOException
{
@Override
protected DeflaterOutputStream createStream() throws IOException
if (compressionType == null)
{
return null;
}
};
}
};
}
else if (compressionType.equals(GZIP))
{
wrappedResponse = new CompressedResponseWrapper(request,response)
{
@Override
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
{
return new AbstractCompressedStream(compressionType,request,this,_vary)
{
@Override
protected DeflaterOutputStream createStream() throws IOException
// acquire deflater instance
_allocatedDeflater = _deflater.get();
if (_allocatedDeflater==null)
_allocatedDeflater = new Deflater(_deflateCompressionLevel,_deflateNoWrap);
else
{
return new GZIPOutputStream(_response.getOutputStream(),_bufferSize);
_deflater.remove();
_allocatedDeflater.reset();
}
};
}
};
}
else if (compressionType.equals(DEFLATE))
{
wrappedResponse = new CompressedResponseWrapper(request,response)
{
@Override
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
{
return new AbstractCompressedStream(compressionType,request,this,_vary)
{
@Override
protected DeflaterOutputStream createStream() throws IOException
switch (compressionType)
{
return new DeflaterOutputStream(_response.getOutputStream(),new Deflater(_deflateCompressionLevel,_deflateNoWrap));
case GZIP:
return new GzipOutputStream(_response.getOutputStream(),_allocatedDeflater,_bufferSize);
case DEFLATE:
return new DeflaterOutputStream(_response.getOutputStream(),_allocatedDeflater,_bufferSize);
}
};
}
};
}
else
{
throw new IllegalStateException(compressionType + " not supported");
}
throw new IllegalStateException(compressionType + " not supported");
}
@Override
public void finish() throws IOException
{
super.finish();
if (_allocatedDeflater != null && _deflater.get() == null)
{
_deflater.set(_allocatedDeflater);
}
}
};
}
};
configureWrappedResponse(wrappedResponse);
return wrappedResponse;
}
@ -472,18 +462,18 @@ public class GzipFilter extends UserAgentFilter
wrappedResponse.setMinCompressSize(_minGzipSize);
}
private class ContinuationListenerWaitingForWrappedResponseToFinish implements ContinuationListener
private class FinishOnCompleteListener implements AsyncListener
{
private CompressedResponseWrapper wrappedResponse;
public ContinuationListenerWaitingForWrappedResponseToFinish(CompressedResponseWrapper wrappedResponse)
public FinishOnCompleteListener(CompressedResponseWrapper wrappedResponse)
{
this.wrappedResponse = wrappedResponse;
}
@Override
public void onComplete(Continuation continuation)
{
public void onComplete(AsyncEvent event) throws IOException
{
try
{
wrappedResponse.finish();
@ -495,7 +485,17 @@ public class GzipFilter extends UserAgentFilter
}
@Override
public void onTimeout(Continuation continuation)
public void onTimeout(AsyncEvent event) throws IOException
{
}
@Override
public void onError(AsyncEvent event) throws IOException
{
}
@Override
public void onStartAsync(AsyncEvent event) throws IOException
{
}
}

View File

@ -29,13 +29,12 @@ import java.util.StringTokenizer;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPOutputStream;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationListener;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.HandlerWrapper;
@ -265,12 +264,28 @@ public class GzipHandler extends HandlerWrapper
}
finally
{
Continuation continuation = ContinuationSupport.getContinuation(request);
if (continuation.isSuspended() && continuation.isResponseWrapped())
if (request.isAsyncStarted())
{
continuation.addContinuationListener(new ContinuationListener()
request.getAsyncContext().addListener(new AsyncListener()
{
public void onComplete(Continuation continuation)
@Override
public void onTimeout(AsyncEvent event) throws IOException
{
}
@Override
public void onStartAsync(AsyncEvent event) throws IOException
{
}
@Override
public void onError(AsyncEvent event) throws IOException
{
}
@Override
public void onComplete(AsyncEvent event) throws IOException
{
try
{
@ -281,9 +296,6 @@ public class GzipHandler extends HandlerWrapper
LOG.warn(e);
}
}
public void onTimeout(Continuation continuation)
{}
});
}
else if (exceptional && !response.isCommitted())

View File

@ -0,0 +1,71 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.servlets.gzip;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.CRC32;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
/**
* Reimplementation of {@link java.util.zip.GZIPOutputStream} that supports reusing a {@link Deflater} instance.
*/
public class GzipOutputStream extends DeflaterOutputStream
{
private final static byte[] GZIP_HEADER = new byte[]
{ (byte)0x1f, (byte)0x8b, Deflater.DEFLATED, 0, 0, 0, 0, 0, 0, 0 };
private final CRC32 _crc = new CRC32();
public GzipOutputStream(OutputStream out, Deflater deflater, int size) throws IOException
{
super(out,deflater,size);
out.write(GZIP_HEADER);
}
public synchronized void write(byte[] buf, int off, int len) throws IOException
{
super.write(buf,off,len);
_crc.update(buf,off,len);
}
public void finish() throws IOException
{
if (!def.finished())
{
super.finish();
byte[] trailer = new byte[8];
writeInt((int)_crc.getValue(),trailer,0);
writeInt(def.getTotalIn(),trailer,4);
out.write(trailer);
}
}
private void writeInt(int i, byte[] buf, int offset)
{
int o = offset;
buf[o++] = (byte)(i & 0xFF);
buf[o++] = (byte)((i >>> 8) & 0xFF);
buf[o++] = (byte)((i >>> 16) & 0xFF);
buf[o++] = (byte)((i >>> 24) & 0xFF);
}
}

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