Merge branch 'master' into javawebsocket-jsr
This commit is contained in:
commit
8088edc96c
88
VERSION.txt
88
VERSION.txt
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 });
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 <New
|
||||
* class="org.eclipse.jetty.deploy.providers.WebAppProvider"> .... <Set
|
||||
* name="tldBundles"><Property name="org.eclipse.jetty.osgi.tldsbundles"
|
||||
* default="" /></Set> <New>
|
||||
*/
|
||||
public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistrationCustomizer
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -78,8 +78,7 @@ public class OSGiClassLoader extends URLClassLoader
|
|||
}
|
||||
|
||||
if (url == null)
|
||||
{
|
||||
|
||||
{
|
||||
url = _osgiBundleClassLoader.getResource(name);
|
||||
|
||||
if (url == null && name.startsWith("/"))
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue