Merge branch 'jetty-9.1' into release-9.1

This commit is contained in:
Jesse McConnell 2013-09-30 18:19:56 -05:00
commit 727c64a5e9
114 changed files with 2584 additions and 2453 deletions

View File

@ -51,7 +51,7 @@ public class FileServer
handlers.setHandlers(new Handler[] { resource_handler, new DefaultHandler() });
server.setHandler(handlers);
//Start things up! By using the server.join() the server thread will join with the current thread.
// Start things up! By using the server.join() the server thread will join with the current thread.
// See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details.
server.start();
server.join();

View File

@ -48,7 +48,9 @@ public class LikeJettyXml
public static void main(String[] args) throws Exception
{
String jetty_home = System.getProperty("jetty.home","../../jetty-distribution/target/distribution");
String jetty_base = System.getProperty("jetty.home","../../jetty-distribution/target/distribution/demo-base");
System.setProperty("jetty.home",jetty_home);
System.setProperty("jetty.base",jetty_base);
// === jetty.xml ===
@ -132,7 +134,7 @@ public class LikeJettyXml
deployer.setContextAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",".*/servlet-api-[^/]*\\.jar$");
WebAppProvider webapp_provider = new WebAppProvider();
webapp_provider.setMonitoredDirName(jetty_home + "/webapps");
webapp_provider.setMonitoredDirName(jetty_base + "/webapps");
webapp_provider.setDefaultsDescriptor(jetty_home + "/etc/webdefault.xml");
webapp_provider.setScanInterval(1);
webapp_provider.setExtractWars(true);
@ -176,7 +178,7 @@ public class LikeJettyXml
// === test-realm.xml ===
HashLoginService login = new HashLoginService();
login.setName("Test Realm");
login.setConfig(jetty_home + "/etc/realm.properties");
login.setConfig(jetty_base + "/etc/realm.properties");
login.setRefreshInterval(0);
server.addBean(login);

View File

@ -46,12 +46,14 @@ public class MinimalServlets
// on a given context path.
// !! This is a raw Servlet, not a servlet that has been configured through a web.xml or anything like that !!
handler.addServletWithMapping(HelloServlet.class,"/*");
handler.addServletWithMapping(HelloServlet.class, "/*");
// Start things up! By using the server.join() the server thread will join with the current thread.
// See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details.
server.start();
server.join();
}
@SuppressWarnings("serial")
public static class HelloServlet extends HttpServlet
{

View File

@ -18,6 +18,9 @@
package org.eclipse.jetty.embedded;
import java.lang.management.ManagementFactory;
import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
@ -26,19 +29,40 @@ public class OneWebApp
{
public static void main(String[] args) throws Exception
{
// Create a basic jetty server object that will listen on port 8080. Note that if you set this to port 0 then
// a randomly available port will be assigned that you can either look in the logs for the port,
// or programmatically obtain it for use in test cases.
Server server = new Server(8080);
// Setup JMX
MBeanContainer mbContainer=new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
server.addBean(mbContainer);
// The WebAppContext is the entity that controls the environment in which a web application lives and
// breathes. In this example the context path is being set to "/" so it is suitable for serving root context
// requests and then we see it setting the location of the war. A whole host of other configurations are
// available, ranging from configuring to support annotation scanning in the webapp (through
// PlusConfiguration) to choosing where the webapp will unpack itself.
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/");
webapp.setWar("../../tests/test-webapps/test-jetty-webapp/target/test-jetty-webapp-9.0.0-SNAPSHOT.war");
webapp.setWar("../../jetty-distribution/target/distribution/demo-base/webapps/test.war");
// A WebAppContext is a ContextHandler as well so it needs to be set to the server so it is aware of where to
// send the appropriate requests.
server.setHandler(webapp);
// Configure a LoginService
// Since this example is for our test webapp, we need to setup a LoginService so this shows how to create a
// very simple hashmap based one. The name of the LoginService needs to correspond to what is configured in
// the webapp's web.xml and since it has a lifecycle of its own we register it as a bean with the Jetty
// server object so it can be started and stopped according to the lifecycle of the server itself.
HashLoginService loginService = new HashLoginService();
loginService.setName("Test Realm");
loginService.setConfig("src/test/resources/realm.properties");
server.addBean(loginService);
// Start things up! By using the server.join() the server thread will join with the current thread.
// See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details.
server.start();
server.join();
}

View File

@ -32,31 +32,56 @@ public class SecuredHelloHandler
{
public static void main(String[] args) throws Exception
{
// Create a basic jetty server object that will listen on port 8080. Note that if you set this to port 0
// then a randomly available port will be assigned that you can either look in the logs for the port,
// or programmatically obtain it for use in test cases.
Server server = new Server(8080);
// Since this example is for our test webapp, we need to setup a LoginService so this shows how to create a
// very simple hashmap based one. The name of the LoginService needs to correspond to what is configured a
// webapp's web.xml and since it has a lifecycle of its own we register it as a bean with the Jetty server
// object so it can be started and stopped according to the lifecycle of the server itself. In this example
// the name can be whatever you like since we are not dealing with webapp realms.
LoginService loginService = new HashLoginService("MyRealm","src/test/resources/realm.properties");
server.addBean(loginService);
// A security handler is a jetty handler that secures content behind a particular portion of a url space. The
// ConstraintSecurityHandler is a more specialized handler that allows matching of urls to different
// constraints. The server sets this as the first handler in the chain,
// effectively applying these constraints to all subsequent handlers in the chain.
ConstraintSecurityHandler security = new ConstraintSecurityHandler();
server.setHandler(security);
// This constraint requires authentication and in addition that an authenticated user be a member of a given
// set of roles for authorization purposes.
Constraint constraint = new Constraint();
constraint.setName("auth");
constraint.setAuthenticate( true );
constraint.setRoles(new String[]{"user", "admin"});
// Binds a url pattern with the previously created constraint. The roles for this constraing mapping are
// mined from the Constraint itself although methods exist to declare and bind roles separately as well.
ConstraintMapping mapping = new ConstraintMapping();
mapping.setPathSpec( "/*" );
mapping.setConstraint( constraint );
// First you see the constraint mapping being applied to the handler as a singleton list,
// however you can passing in as many security constraint mappings as you like so long as they follow the
// mapping requirements of the servlet api. Next we set a BasicAuthenticator instance which is the object
// that actually checks the credentials followed by the LoginService which is the store of known users, etc.
security.setConstraintMappings(Collections.singletonList(mapping));
security.setAuthenticator(new BasicAuthenticator());
security.setLoginService(loginService);
// The Hello Handler is the handler we are securing so we create one, and then set it as the handler on the
// security handler to complain the simple handler chain.
HelloHandler hh = new HelloHandler();
// chain the hello handler into the security handler
security.setHandler(hh);
// Start things up! By using the server.join() the server thread will join with the current thread.
// See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details.
server.start();
server.join();
}

View File

@ -43,7 +43,8 @@ public class ServerWithAnnotations
//Create a WebApp
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/");
webapp.setWar("../../tests/test-webapps/test-servlet-spec/test-spec-webapp/target/test-spec-webapp-9.0.4-SNAPSHOT.war");
webapp.setWar("../../tests/test-webapps/test-servlet-spec/test-spec-webapp/target/test-spec-webapp-9.1.0-SNAPSHOT.war");
webapp.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",".*/javax.servlet-[^/]*\\.jar$|.*/servlet-api-[^/]*\\.jar$");
server.setHandler(webapp);
//Register new transaction manager in JNDI

View File

@ -40,30 +40,42 @@ public class SplitFileServer
public static void main(String[] args) throws Exception
{
// Create the Server object and a corresponding ServerConnector and then set the port for the connector. In
// this example the server will listen on port 8090. If you set this to port 0 then when the server has been
// started you can called connector.getLocalPort() to programmatically get the port the server started on.
Server server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(8090);
server.setConnectors(new Connector[]
{ connector });
// Create a Context Handler and ResourceHandler. The ContextHandler is getting set to "/" path but this could
// be anything you like for builing out your url. Note how we are setting the ResourceBase using our jetty
// maven testing utilities to get the proper resource directory, you needn't use these,
// you simply need to supply the paths you are looking to serve content from.
ContextHandler context0 = new ContextHandler();
context0.setContextPath("/");
ResourceHandler rh0 = new ResourceHandler();
rh0.setBaseResource( Resource.newResource(MavenTestingUtils.getTestResourceDir("dir0")));
context0.setHandler(rh0);
// Rinse and repeat the previous item, only specifying a different resource base.
ContextHandler context1 = new ContextHandler();
context1.setContextPath("/");
ResourceHandler rh1 = new ResourceHandler();
rh1.setBaseResource( Resource.newResource(MavenTestingUtils.getTestResourceDir("dir1")));
context1.setHandler(rh1);
// Create a ContextHandlerCollection and set the context handlers to it. This will let jetty process urls
// against the declared contexts in order to match up content.
ContextHandlerCollection contexts = new ContextHandlerCollection();
contexts.setHandlers(new Handler[]
{ context0, context1 });
server.setHandler(contexts);
// Start things up! By using the server.join() the server thread will join with the current thread.
// See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details.
server.start();
System.err.println(server.dump());
server.join();

View File

@ -25,7 +25,7 @@ import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
import org.eclipse.jetty.websocket.jsr356.server.WebSocketConfiguration;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
/**
* Example of setting up a javax.websocket server with Jetty embedded
@ -54,7 +54,7 @@ public class WebSocketJsrServer
server.setHandler(context);
// Enable javax.websocket configuration for the context
ServerContainer wsContainer = WebSocketConfiguration.configureContext(context);
ServerContainer wsContainer = WebSocketServerContainerInitializer.configureContext(context);
// Add your websockets to the container
wsContainer.addEndpoint(EchoJsrSocket.class);

View File

@ -102,8 +102,12 @@
<artifactId>javax.annotation-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>org.objectweb.asm</artifactId>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-commons</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -18,62 +18,30 @@
package org.eclipse.jetty.annotations;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.annotations.AnnotationParser.AbstractHandler;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.WebAppContext;
/**
* DiscoverableAnnotationHandler
*
*
* Base class for handling the discovery of an annotation.
*
*/
public abstract class AbstractDiscoverableAnnotationHandler implements DiscoverableAnnotationHandler
public abstract class AbstractDiscoverableAnnotationHandler extends AbstractHandler
{
protected WebAppContext _context;
protected List<DiscoveredAnnotation> _annotations;
protected Resource _resource;
public AbstractDiscoverableAnnotationHandler(WebAppContext context)
{
this(context, null);
}
public AbstractDiscoverableAnnotationHandler(WebAppContext context, List<DiscoveredAnnotation> list)
{
_context = context;
if (list == null)
_annotations = new ArrayList<DiscoveredAnnotation>();
else
_annotations = list;
}
public Resource getResource()
{
return _resource;
}
public void setResource(Resource resource)
{
_resource = resource;
}
public List<DiscoveredAnnotation> getAnnotationList ()
{
return _annotations;
}
public void resetList()
{
_annotations.clear();
}
public void addAnnotation (DiscoveredAnnotation a)
{
_annotations.add(a);
_context.getMetaData().addDiscoveredAnnotation(a);
}
}

View File

@ -20,22 +20,28 @@ package org.eclipse.jetty.annotations;
import java.net.URI;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceLoader;
import java.util.StringTokenizer;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.annotation.HandlesTypes;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationParser.Handler;
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.util.ArrayUtil;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.ConcurrentHashSet;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.webapp.AbstractConfiguration;
import org.eclipse.jetty.webapp.FragmentDescriptor;
import org.eclipse.jetty.webapp.MetaDataComplete;
@ -50,16 +56,51 @@ import org.eclipse.jetty.webapp.WebDescriptor;
public class AnnotationConfiguration extends AbstractConfiguration
{
private static final Logger LOG = Log.getLogger(AnnotationConfiguration.class);
public static final String CLASS_INHERITANCE_MAP = "org.eclipse.jetty.classInheritanceMap";
public static final String CONTAINER_INITIALIZERS = "org.eclipse.jetty.containerInitializers";
public static final String CONTAINER_INITIALIZER_LISTENER = "org.eclipse.jetty.containerInitializerListener";
public static final String CONTAINER_INITIALIZER_STARTER = "org.eclipse.jetty.containerInitializerStarter";
public static final String MULTI_THREADED = "org.eclipse.jetty.annotations.multiThreaded";
public static final String MAX_SCAN_WAIT = "org.eclipse.jetty.annotations.maxWait";
protected List<DiscoverableAnnotationHandler> _discoverableAnnotationHandlers = new ArrayList<DiscoverableAnnotationHandler>();
public static final int DEFAULT_MAX_SCAN_WAIT = 60; /* time in sec */
public static final boolean DEFAULT_MULTI_THREADED = true;
protected List<AbstractDiscoverableAnnotationHandler> _discoverableAnnotationHandlers = new ArrayList<AbstractDiscoverableAnnotationHandler>();
protected ClassInheritanceHandler _classInheritanceHandler;
protected List<ContainerInitializerAnnotationHandler> _containerInitializerAnnotationHandlers = new ArrayList<ContainerInitializerAnnotationHandler>();
protected List<ParserTask> _parserTasks;
protected WebAppClassNameResolver _webAppClassNameResolver;
protected ContainerClassNameResolver _containerClassNameResolver;
public class ParserTask implements Callable<Void>
{
protected Exception _exception;
protected final AnnotationParser _parser;
protected final Set<? extends Handler> _handlers;
protected final ClassNameResolver _resolver;
protected final Resource _resource;
public ParserTask (AnnotationParser parser, Set<? extends Handler>handlers, Resource resource, ClassNameResolver resolver)
{
_parser = parser;
_handlers = handlers;
_resolver = resolver;
_resource = resource;
}
public Void call() throws Exception
{
if (_parser != null)
_parser.parse(_handlers, _resource, _resolver);
return null;
}
}
/**
* WebAppClassNameResolver
*
@ -138,10 +179,12 @@ public class AnnotationConfiguration extends AbstractConfiguration
@Override
public void preConfigure(final WebAppContext context) throws Exception
{
_webAppClassNameResolver = new WebAppClassNameResolver(context);
_containerClassNameResolver = new ContainerClassNameResolver(context);
}
public void addDiscoverableAnnotationHandler(DiscoverableAnnotationHandler handler)
public void addDiscoverableAnnotationHandler(AbstractDiscoverableAnnotationHandler handler)
{
_discoverableAnnotationHandlers.add(handler);
}
@ -151,11 +194,11 @@ public class AnnotationConfiguration extends AbstractConfiguration
{
context.removeAttribute(CLASS_INHERITANCE_MAP);
context.removeAttribute(CONTAINER_INITIALIZERS);
ServletContainerInitializerListener listener = (ServletContainerInitializerListener)context.getAttribute(CONTAINER_INITIALIZER_LISTENER);
if (listener != null)
ServletContainerInitializersStarter starter = (ServletContainerInitializersStarter)context.getAttribute(CONTAINER_INITIALIZER_STARTER);
if (starter != null)
{
context.removeBean(listener);
context.removeAttribute(CONTAINER_INITIALIZER_LISTENER);
context.removeBean(starter);
context.removeAttribute(CONTAINER_INITIALIZER_STARTER);
}
}
@ -165,13 +208,11 @@ public class AnnotationConfiguration extends AbstractConfiguration
@Override
public void configure(WebAppContext context) throws Exception
{
boolean metadataComplete = context.getMetaData().isMetaDataComplete();
context.addDecorator(new AnnotationDecorator(context));
//Even if metadata is complete, we still need to scan for ServletContainerInitializers - if there are any
AnnotationParser parser = null;
if (!metadataComplete)
if (!context.getMetaData().isMetaDataComplete())
{
//If metadata isn't complete, if this is a servlet 3 webapp or isConfigDiscovered is true, we need to search for annotations
if (context.getServletContext().getEffectiveMajorVersion() >= 3 || context.isConfigurationDiscovered())
@ -181,31 +222,13 @@ public class AnnotationConfiguration extends AbstractConfiguration
_discoverableAnnotationHandlers.add(new WebListenerAnnotationHandler(context));
}
}
else
if (LOG.isDebugEnabled()) LOG.debug("Metadata-complete==true, not processing discoverable servlet annotations for context "+context);
//Regardless of metadata, if there are any ServletContainerInitializers with @HandlesTypes, then we need to scan all the
//classes so we can call their onStartup() methods correctly
createServletContainerInitializerAnnotationHandlers(context, getNonExcludedInitializers(context));
if (!_discoverableAnnotationHandlers.isEmpty() || _classInheritanceHandler != null || !_containerInitializerAnnotationHandlers.isEmpty())
{
parser = createAnnotationParser();
if (LOG.isDebugEnabled()) LOG.debug("Scanning all classses for annotations: webxmlVersion="+context.getServletContext().getEffectiveMajorVersion()+" configurationDiscovered="+context.isConfigurationDiscovered());
parseContainerPath(context, parser);
//email from Rajiv Mordani jsrs 315 7 April 2010
// If there is a <others/> then the ordering should be
// WEB-INF/classes the order of the declared elements + others.
// In case there is no others then it is
// WEB-INF/classes + order of the elements.
parseWebInfClasses(context, parser);
parseWebInfLib (context, parser);
for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
context.getMetaData().addDiscoveredAnnotations(((AbstractDiscoverableAnnotationHandler)h).getAnnotationList());
}
scanForAnnotations(context);
}
@ -216,34 +239,191 @@ public class AnnotationConfiguration extends AbstractConfiguration
@Override
public void postConfigure(WebAppContext context) throws Exception
{
MultiMap<String> map = (MultiMap<String>)context.getAttribute(CLASS_INHERITANCE_MAP);
if (map != null)
map.clear();
ConcurrentHashMap<String, ConcurrentHashSet<String>> classMap = (ConcurrentHashMap<String, ConcurrentHashSet<String>>)context.getAttribute(CLASS_INHERITANCE_MAP);
List<ContainerInitializer> initializers = (List<ContainerInitializer>)context.getAttribute(CONTAINER_INITIALIZERS);
context.removeAttribute(CLASS_INHERITANCE_MAP);
if (classMap != null)
classMap.clear();
List<ContainerInitializer> initializers = (List<ContainerInitializer>)context.getAttribute(CONTAINER_INITIALIZERS);
context.removeAttribute(CONTAINER_INITIALIZERS);
if (initializers != null)
initializers.clear();
if (_discoverableAnnotationHandlers != null)
_discoverableAnnotationHandlers.clear();
_classInheritanceHandler = null;
if (_containerInitializerAnnotationHandlers != null)
_containerInitializerAnnotationHandlers.clear();
if (_parserTasks != null)
{
_parserTasks.clear();
_parserTasks = null;
}
super.postConfigure(context);
}
/**
* @return a new AnnotationParser. This method can be overridden to use a different impleemntation of
* Perform scanning of classes for annotations
*
* @param context
* @throws Exception
*/
protected void scanForAnnotations (WebAppContext context)
throws Exception
{
AnnotationParser parser = createAnnotationParser();
boolean multiThreadedScan = isUseMultiThreading(context);
int maxScanWait = 0;
if (multiThreadedScan)
{
_parserTasks = new ArrayList<ParserTask>();
maxScanWait = getMaxScanWait(context);
}
long start = 0;
if (LOG.isDebugEnabled())
{
start = System.nanoTime();
LOG.debug("Scanning for annotations: webxml={}, metadatacomplete={}, configurationDiscovered={}, multiThreaded={}",
context.getServletContext().getEffectiveMajorVersion(),
context.getMetaData().isMetaDataComplete(),
context.isConfigurationDiscovered(),
multiThreadedScan);
}
parseContainerPath(context, parser);
//email from Rajiv Mordani jsrs 315 7 April 2010
// If there is a <others/> then the ordering should be
// WEB-INF/classes the order of the declared elements + others.
// In case there is no others then it is
// WEB-INF/classes + order of the elements.
parseWebInfClasses(context, parser);
parseWebInfLib (context, parser);
if (!multiThreadedScan)
{
if (LOG.isDebugEnabled())
{
long end = System.nanoTime();
LOG.debug("Annotation parsing millisec={}",(TimeUnit.MILLISECONDS.convert(end-start, TimeUnit.NANOSECONDS)));
}
return;
}
if (LOG.isDebugEnabled())
start = System.nanoTime();
//execute scan asynchronously using jetty's thread pool
final CountDownLatch latch = new CountDownLatch(_parserTasks.size());
final MultiException me = new MultiException();
final Semaphore task_limit=new Semaphore(Runtime.getRuntime().availableProcessors());
for (final ParserTask p:_parserTasks)
{
task_limit.acquire();
context.getServer().getThreadPool().execute(new Runnable()
{
@Override
public void run()
{
try
{
p.call();
}
catch (Exception e)
{
me.add(e);
}
finally
{
task_limit.release();
latch.countDown();
}
}
});
}
boolean timeout = !latch.await(maxScanWait, TimeUnit.SECONDS);
if (LOG.isDebugEnabled())
{
long end = System.nanoTime();
LOG.debug("Annotation parsing millisec={}",(TimeUnit.MILLISECONDS.convert(end-start, TimeUnit.NANOSECONDS)));
}
if (timeout)
me.add(new Exception("Timeout scanning annotations"));
me.ifExceptionThrow();
}
/**
* @return a new AnnotationParser. This method can be overridden to use a different implementation of
* the AnnotationParser. Note that this is considered internal API.
*/
protected AnnotationParser createAnnotationParser()
{
return new AnnotationParser();
}
/**
* Check if we should use multiple threads to scan for annotations or not
* @param context
* @return
*/
protected boolean isUseMultiThreading(WebAppContext context)
{
//try context attribute to see if we should use multithreading
Object o = context.getAttribute(MULTI_THREADED);
if (o instanceof Boolean)
{
return ((Boolean)o).booleanValue();
}
//try server attribute to see if we should use multithreading
o = context.getServer().getAttribute(MULTI_THREADED);
if (o instanceof Boolean)
{
return ((Boolean)o).booleanValue();
}
//try system property to see if we should use multithreading
return Boolean.valueOf(System.getProperty(MULTI_THREADED, Boolean.toString(DEFAULT_MULTI_THREADED)));
}
/**
* Work out how long we should wait for the async scanning to occur.
*
* @param context
* @return
*/
protected int getMaxScanWait (WebAppContext context)
{
//try context attribute to get max time in sec to wait for scan completion
Object o = context.getAttribute(MAX_SCAN_WAIT);
if (o != null && o instanceof Number)
{
return ((Number)o).intValue();
}
//try server attribute to get max time in sec to wait for scan completion
o = context.getServer().getAttribute(MAX_SCAN_WAIT);
if (o != null && o instanceof Number)
{
return ((Number)o).intValue();
}
//try system property to get max time in sec to wait for scan completion
return Integer.getInteger(MAX_SCAN_WAIT, DEFAULT_MAX_SCAN_WAIT).intValue();
}
/**
* @see org.eclipse.jetty.webapp.AbstractConfiguration#cloneConfigure(org.eclipse.jetty.webapp.WebAppContext, org.eclipse.jetty.webapp.WebAppContext)
*/
@ -263,12 +443,8 @@ public class AnnotationConfiguration extends AbstractConfiguration
public void createServletContainerInitializerAnnotationHandlers (WebAppContext context, List<ServletContainerInitializer> scis)
throws Exception
{
if (scis == null || scis.isEmpty())
return; // nothing to do
List<ContainerInitializer> initializers = new ArrayList<ContainerInitializer>();
context.setAttribute(CONTAINER_INITIALIZERS, initializers);
@ -276,23 +452,21 @@ public class AnnotationConfiguration extends AbstractConfiguration
for (ServletContainerInitializer service : scis)
{
HandlesTypes annotation = service.getClass().getAnnotation(HandlesTypes.class);
ContainerInitializer initializer = new ContainerInitializer();
initializer.setTarget(service);
initializers.add(initializer);
ContainerInitializer initializer = null;
if (annotation != null)
{
{
//There is a HandlesTypes annotation on the on the ServletContainerInitializer
Class[] classes = annotation.value();
if (classes != null)
{
initializer.setInterestedTypes(classes);
initializer = new ContainerInitializer(service, classes);
//If we haven't already done so, we need to register a handler that will
//process the whole class hierarchy to satisfy the ServletContainerInitializer
if (context.getAttribute(CLASS_INHERITANCE_MAP) == null)
{
MultiMap<String> map = new MultiMap<>();
//MultiMap<String> map = new MultiMap<>();
ConcurrentHashMap<String, ConcurrentHashSet<String>> map = new ConcurrentHashMap<String, ConcurrentHashSet<String>>();
context.setAttribute(CLASS_INHERITANCE_MAP, map);
_classInheritanceHandler = new ClassInheritanceHandler(map);
}
@ -304,28 +478,33 @@ public class AnnotationConfiguration extends AbstractConfiguration
if (c.isAnnotation())
{
if (LOG.isDebugEnabled()) LOG.debug("Registering annotation handler for "+c.getName());
_containerInitializerAnnotationHandlers.add(new ContainerInitializerAnnotationHandler(initializer, c));
}
}
}
else
{
initializer = new ContainerInitializer(service, null);
if (LOG.isDebugEnabled()) LOG.debug("No classes in HandlesTypes on initializer "+service.getClass());
}
}
else
{
initializer = new ContainerInitializer(service, null);
if (LOG.isDebugEnabled()) LOG.debug("No annotation on initializer "+service.getClass());
}
initializers.add(initializer);
}
//add a bean which will call the servletcontainerinitializers when appropriate
ServletContainerInitializerListener listener = (ServletContainerInitializerListener)context.getAttribute(CONTAINER_INITIALIZER_LISTENER);
if (listener != null)
throw new IllegalStateException("ServletContainerInitializerListener already exists");
listener = new ServletContainerInitializerListener();
listener.setWebAppContext(context);
context.setAttribute(CONTAINER_INITIALIZER_LISTENER, listener);
context.addBean(listener, true);
//add a bean to the context which will call the servletcontainerinitializers when appropriate
ServletContainerInitializersStarter starter = (ServletContainerInitializersStarter)context.getAttribute(CONTAINER_INITIALIZER_STARTER);
if (starter != null)
throw new IllegalStateException("ServletContainerInitializersStarter already exists");
starter = new ServletContainerInitializersStarter(context);
context.setAttribute(CONTAINER_INITIALIZER_STARTER, starter);
context.addBean(starter, true);
}
@ -383,8 +562,13 @@ public class AnnotationConfiguration extends AbstractConfiguration
List<ServletContainerInitializer> nonExcludedInitializers = new ArrayList<ServletContainerInitializer>();
//We use the ServiceLoader mechanism to find the ServletContainerInitializer classes to inspect
long start = 0;
if (LOG.isDebugEnabled())
start = System.nanoTime();
ServiceLoader<ServletContainerInitializer> loadedInitializers = ServiceLoader.load(ServletContainerInitializer.class, context.getClassLoader());
if (LOG.isDebugEnabled())
LOG.debug("Service loaders found in {}ms", (TimeUnit.MILLISECONDS.convert((System.nanoTime()-start), TimeUnit.NANOSECONDS)));
if (loadedInitializers != null)
{
for (ServletContainerInitializer service : loadedInitializers)
@ -406,33 +590,27 @@ public class AnnotationConfiguration extends AbstractConfiguration
* @param parser
* @throws Exception
*/
public void parseContainerPath (final WebAppContext context, final AnnotationParser parser)
throws Exception
public void parseContainerPath (final WebAppContext context, final AnnotationParser parser) throws Exception
{
//if no pattern for the container path is defined, then by default scan NOTHING
LOG.debug("Scanning container jars");
LOG.debug("Scanning container jars");
//always parse for discoverable annotations as well as class hierarchy and servletcontainerinitializer related annotations
parser.clearHandlers();
for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
{
if (h instanceof AbstractDiscoverableAnnotationHandler)
((AbstractDiscoverableAnnotationHandler)h).setResource(null); //
}
parser.registerHandlers(_discoverableAnnotationHandlers);
parser.registerHandler(_classInheritanceHandler);
parser.registerHandlers(_containerInitializerAnnotationHandlers);
final Set<Handler> handlers = new HashSet<Handler>();
handlers.addAll(_discoverableAnnotationHandlers);
handlers.addAll(_containerInitializerAnnotationHandlers);
if (_classInheritanceHandler != null)
handlers.add(_classInheritanceHandler);
//Convert from Resource to URI
ArrayList<URI> containerUris = new ArrayList<URI>();
for (Resource r : context.getMetaData().getContainerResources())
{
URI uri = r.getURI();
containerUris.add(uri);
}
parser.parse (containerUris.toArray(new URI[containerUris.size()]),
new ContainerClassNameResolver (context));
//queue it up for scanning if using multithreaded mode
if (_parserTasks != null)
_parserTasks.add(new ParserTask(parser, handlers, r, _containerClassNameResolver));
else
//just scan it now
parser.parse(handlers, r, _containerClassNameResolver);
}
}
@ -443,9 +621,10 @@ public class AnnotationConfiguration extends AbstractConfiguration
* @param parser
* @throws Exception
*/
public void parseWebInfLib (final WebAppContext context, final AnnotationParser parser)
throws Exception
{
public void parseWebInfLib (final WebAppContext context, final AnnotationParser parser) throws Exception
{
LOG.debug("Scanning WEB-INF/lib jars");
List<FragmentDescriptor> frags = context.getMetaData().getFragments();
//email from Rajiv Mordani jsrs 315 7 April 2010
@ -462,9 +641,8 @@ public class AnnotationConfiguration extends AbstractConfiguration
for (Resource r : jars)
{
//for each jar, we decide which set of annotations we need to parse for
parser.clearHandlers();
final Set<Handler> handlers = new HashSet<Handler>();
URI uri = r.getURI();
FragmentDescriptor f = getFragmentFromJar(r, frags);
//if its from a fragment jar that is metadata complete, we should skip scanning for @webservlet etc
@ -474,27 +652,26 @@ public class AnnotationConfiguration extends AbstractConfiguration
if (f == null || !isMetaDataComplete(f) || _classInheritanceHandler != null || !_containerInitializerAnnotationHandlers.isEmpty())
{
//register the classinheritance handler if there is one
parser.registerHandler(_classInheritanceHandler);
if (_classInheritanceHandler != null)
handlers.add(_classInheritanceHandler);
//register the handlers for the @HandlesTypes values that are themselves annotations if there are any
parser.registerHandlers(_containerInitializerAnnotationHandlers);
handlers.addAll(_containerInitializerAnnotationHandlers);
//only register the discoverable annotation handlers if this fragment is not metadata complete, or has no fragment descriptor
if (f == null || !isMetaDataComplete(f))
{
for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
{
if (h instanceof AbstractDiscoverableAnnotationHandler)
((AbstractDiscoverableAnnotationHandler)h).setResource(r);
}
parser.registerHandlers(_discoverableAnnotationHandlers);
}
handlers.addAll(_discoverableAnnotationHandlers);
parser.parse(uri, new WebAppClassNameResolver(context));
if (_parserTasks != null)
_parserTasks.add (new ParserTask(parser, handlers,r, _webAppClassNameResolver));
else
parser.parse(handlers, r, _webAppClassNameResolver);
}
}
}
/**
* Scan classes in WEB-INF/classes
*
@ -505,27 +682,26 @@ public class AnnotationConfiguration extends AbstractConfiguration
public void parseWebInfClasses (final WebAppContext context, final AnnotationParser parser)
throws Exception
{
LOG.debug("Scanning classes in WEB-INF/classes");
parser.clearHandlers();
for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
{
if (h instanceof AbstractDiscoverableAnnotationHandler)
((AbstractDiscoverableAnnotationHandler)h).setResource(null); //
}
parser.registerHandlers(_discoverableAnnotationHandlers);
parser.registerHandler(_classInheritanceHandler);
parser.registerHandlers(_containerInitializerAnnotationHandlers);
LOG.debug("Scanning WEB-INF/classes");
Set<Handler> handlers = new HashSet<Handler>();
handlers.addAll(_discoverableAnnotationHandlers);
if (_classInheritanceHandler != null)
handlers.add(_classInheritanceHandler);
handlers.addAll(_containerInitializerAnnotationHandlers);
for (Resource dir : context.getMetaData().getWebInfClassesDirs())
{
parser.parseDir(dir, new WebAppClassNameResolver(context));
if (_parserTasks != null)
_parserTasks.add(new ParserTask(parser, handlers, dir, _webAppClassNameResolver));
else
parser.parse(handlers, dir, _webAppClassNameResolver);
}
}
/**
/**
* Get the web-fragment.xml from a jar
*
* @param jar
@ -554,6 +730,4 @@ public class AnnotationConfiguration extends AbstractConfiguration
{
return (d!=null && d.getMetaDataComplete() == MetaDataComplete.True);
}
}

View File

@ -19,8 +19,13 @@
package org.eclipse.jetty.annotations;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.jetty.annotations.AnnotationParser.ClassHandler;
import org.eclipse.jetty.annotations.AnnotationParser.AbstractHandler;
import org.eclipse.jetty.annotations.AnnotationParser.ClassInfo;
import org.eclipse.jetty.util.ConcurrentHashSet;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -30,33 +35,33 @@ import org.eclipse.jetty.util.log.Logger;
*
* As asm scans for classes, remember the type hierarchy.
*/
public class ClassInheritanceHandler implements ClassHandler
public class ClassInheritanceHandler extends AbstractHandler
{
private static final Logger LOG = Log.getLogger(ClassInheritanceHandler.class);
MultiMap<String> _inheritanceMap;
ConcurrentHashMap<String, ConcurrentHashSet<String>> _inheritanceMap;
public ClassInheritanceHandler()
{
_inheritanceMap = new MultiMap<>();
}
public ClassInheritanceHandler(MultiMap<String> map)
public ClassInheritanceHandler(ConcurrentHashMap<String, ConcurrentHashSet<String>> map)
{
_inheritanceMap = map;
}
public void handle(String className, int version, int access, String signature, String superName, String[] interfaces)
public void handle(ClassInfo classInfo)
{
try
{
for (int i=0; interfaces != null && i<interfaces.length;i++)
for (int i=0; classInfo.getInterfaces() != null && i < classInfo.getInterfaces().length;i++)
{
_inheritanceMap.add (interfaces[i], className);
addToInheritanceMap(classInfo.getInterfaces()[i], classInfo.getClassName());
//_inheritanceMap.add (classInfo.getInterfaces()[i], classInfo.getClassName());
}
//To save memory, we don't record classes that only extend Object, as that can be assumed
if (!"java.lang.Object".equals(superName))
_inheritanceMap.add(superName, className);
if (!"java.lang.Object".equals(classInfo.getSuperName()))
{
addToInheritanceMap(classInfo.getSuperName(), classInfo.getClassName());
//_inheritanceMap.add(classInfo.getSuperName(), classInfo.getClassName());
}
}
catch (Exception e)
{
@ -64,13 +69,21 @@ public class ClassInheritanceHandler implements ClassHandler
}
}
public List<String> getClassNamesExtendingOrImplementing (String className)
private void addToInheritanceMap (String interfaceOrSuperClassName, String implementingOrExtendingClassName)
{
return _inheritanceMap.getValues(className);
}
public MultiMap<String> getMap ()
{
return _inheritanceMap;
//As it is likely that the interfaceOrSuperClassName is already in the map, try getting it first
ConcurrentHashSet<String> implementingClasses = _inheritanceMap.get(interfaceOrSuperClassName);
//If it isn't in the map, then add it in, but test to make sure that someone else didn't get in
//first and add it
if (implementingClasses == null)
{
implementingClasses = new ConcurrentHashSet<String>();
ConcurrentHashSet<String> tmp = _inheritanceMap.putIfAbsent(interfaceOrSuperClassName, implementingClasses);
if (tmp != null)
implementingClasses = tmp;
}
implementingClasses.add(implementingOrExtendingClassName);
}
}

View File

@ -19,10 +19,11 @@
package org.eclipse.jetty.annotations;
import java.util.List;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationParser.Value;
import org.eclipse.jetty.annotations.AnnotationParser.AbstractHandler;
import org.eclipse.jetty.annotations.AnnotationParser.ClassInfo;
import org.eclipse.jetty.annotations.AnnotationParser.FieldInfo;
import org.eclipse.jetty.annotations.AnnotationParser.MethodInfo;
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
/**
@ -32,10 +33,14 @@ import org.eclipse.jetty.plus.annotation.ContainerInitializer;
* method level. The specified annotation is derived from an @HandlesTypes on
* a ServletContainerInitializer class.
*/
public class ContainerInitializerAnnotationHandler implements DiscoverableAnnotationHandler
/**
* @author janb
*
*/
public class ContainerInitializerAnnotationHandler extends AbstractHandler
{
ContainerInitializer _initializer;
Class _annotation;
final ContainerInitializer _initializer;
final Class _annotation;
public ContainerInitializerAnnotationHandler (ContainerInitializer initializer, Class annotation)
{
@ -45,35 +50,43 @@ public class ContainerInitializerAnnotationHandler implements DiscoverableAnnota
/**
* Handle finding a class that is annotated with the annotation we were constructed with.
* @see org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler#handleClass(java.lang.String, int, int, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, java.util.List)
* @see org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler#handle(ClassInfo)
* */
public void handle(ClassInfo info, String annotationName)
{
if (annotationName == null || !_annotation.getName().equals(annotationName))
return;
_initializer.addAnnotatedTypeName(info.getClassName());
}
/**
* Handle finding a field that is annotated with the annotation we were constructed with.
*
* @see org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler#handle(org.eclipse.jetty.annotations.AnnotationParser.FieldAnnotationInfo)
*/
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotationName,
List<Value> values)
{
_initializer.addAnnotatedTypeName(className);
public void handle(FieldInfo info, String annotationName)
{
if (annotationName == null || !_annotation.getName().equals(annotationName))
return;
_initializer.addAnnotatedTypeName(info.getClassInfo().getClassName());
}
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
List<Value> values)
/**
* Handle finding a method that is annotated with the annotation we were constructed with.
*
* @see org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler#handle(org.eclipse.jetty.annotations.AnnotationParser.MethodAnnotationInfo)
*/
public void handle(MethodInfo info, String annotationName)
{
_initializer.addAnnotatedTypeName(className);
if (annotationName == null || !_annotation.getName().equals(annotationName))
return;
_initializer.addAnnotatedTypeName(info.getClassInfo().getClassName());
}
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
List<Value> values)
{
_initializer.addAnnotatedTypeName(className);
}
@Override
public String getAnnotationName()
{
return _annotation.getName();
}
public ContainerInitializer getContainerInitializer()
{
return _initializer;
}
}

View File

@ -23,7 +23,6 @@ import java.util.List;
import javax.servlet.Servlet;
import org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationParser.Value;
import org.eclipse.jetty.plus.annotation.RunAsCollection;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.log.Log;
@ -87,14 +86,12 @@ public class RunAsAnnotationHandler extends AbstractIntrospectableAnnotationHand
}
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
List<Value> values)
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation)
{
LOG.warn ("@RunAs annotation not applicable for fields: "+className+"."+fieldName);
}
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
List<Value> values)
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation)
{
LOG.warn("@RunAs annotation ignored on method: "+className+"."+methodName+" "+signature);
}

View File

@ -1,145 +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.annotations;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.WebAppContext;
/**
* ServletContainerInitializerListener
*
*
*/
public class ServletContainerInitializerListener extends AbstractLifeCycle
{
private static final Logger LOG = Log.getLogger(ServletContainerInitializerListener.class);
protected WebAppContext _context = null;
public void setWebAppContext (WebAppContext context)
{
_context = context;
}
/**
* Call the doStart method of the ServletContainerInitializers
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
*/
public void doStart()
{
List<ContainerInitializer> initializers = (List<ContainerInitializer>)_context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS);
MultiMap classMap = (MultiMap)_context.getAttribute(AnnotationConfiguration.CLASS_INHERITANCE_MAP);
if (initializers != null)
{
for (ContainerInitializer i : initializers)
{
//We have already found the classes that directly have an annotation that was in the HandlesTypes
//annotation of the ServletContainerInitializer. For each of those classes, walk the inheritance
//hierarchy to find classes that extend or implement them.
if (i.getAnnotatedTypeNames() != null)
{
Set<String> annotatedClassNames = new HashSet<String>(i.getAnnotatedTypeNames());
for (String name : annotatedClassNames)
{
//add the class with the annotation
i.addApplicableTypeName(name);
//add the classes that inherit the annotation
if (classMap != null)
{
List<String> implementsOrExtends = (List<String>)classMap.getValues(name);
if (implementsOrExtends != null && !implementsOrExtends.isEmpty())
addInheritedTypes(classMap, i, implementsOrExtends);
}
}
}
//Now we need to look at the HandlesTypes classes that were not annotations. We need to
//find all classes that extend or implement them.
if (i.getInterestedTypes() != null)
{
for (Class c : i.getInterestedTypes())
{
if (!c.isAnnotation())
{
//add the classes that implement or extend the class.
//TODO but not including the class itself?
if (classMap != null)
{
List<String> implementsOrExtends = (List<String>)classMap.getValues(c.getName());
if (implementsOrExtends != null && !implementsOrExtends.isEmpty())
addInheritedTypes(classMap, i, implementsOrExtends);
}
}
}
}
//instantiate ServletContainerInitializers, call doStart
try
{
i.callStartup(_context);
}
catch (Exception e)
{
LOG.warn(e);
throw new RuntimeException(e);
}
}
}
}
void addInheritedTypes (MultiMap classMap, ContainerInitializer initializer, List<String> applicableTypes)
{
for (String s : applicableTypes)
{
//add the name of the class that extends or implements
initializer.addApplicableTypeName(s);
//walk the hierarchy and find all types that extend or implement it
List<String> implementsOrExtends = (List<String>)classMap.getValues(s);
if (implementsOrExtends != null && !implementsOrExtends.isEmpty())
addInheritedTypes (classMap, initializer, implementsOrExtends);
}
}
/**
* Nothing to do for ServletContainerInitializers on stop
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
*/
public void doStop()
{
}
}

View File

@ -0,0 +1,161 @@
//
// ========================================================================
// 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.annotations;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.util.ConcurrentHashSet;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.WebAppContext;
/**
* ServletContainerInitializersStarter
*
* Call the onStartup() method on all ServletContainerInitializers, after having
* found all applicable classes (if any) to pass in as args.
*/
public class ServletContainerInitializersStarter extends AbstractLifeCycle
{
private static final Logger LOG = Log.getLogger(ServletContainerInitializersStarter.class);
WebAppContext _context;
/**
* @param context
*/
public ServletContainerInitializersStarter(WebAppContext context)
{
_context = context;
}
/**
* Call the doStart method of the ServletContainerInitializers
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
*/
public void doStart()
{
List<ContainerInitializer> initializers = (List<ContainerInitializer>)_context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS);
if (initializers == null)
return;
ConcurrentHashMap<String, ConcurrentHashSet<String>> map = ( ConcurrentHashMap<String, ConcurrentHashSet<String>>)_context.getAttribute(AnnotationConfiguration.CLASS_INHERITANCE_MAP);
for (ContainerInitializer i : initializers)
{
configureHandlesTypes(_context, i, map);
//instantiate ServletContainerInitializers, call doStart
try
{
i.callStartup(_context);
}
catch (Exception e)
{
LOG.warn(e);
throw new RuntimeException(e);
}
}
}
private void configureHandlesTypes (WebAppContext context, ContainerInitializer initializer, ConcurrentHashMap<String, ConcurrentHashSet<String>> classMap)
{
doHandlesTypesAnnotations(context, initializer, classMap);
doHandlesTypesClasses(context, initializer, classMap);
}
private void doHandlesTypesAnnotations(WebAppContext context, ContainerInitializer initializer, ConcurrentHashMap<String, ConcurrentHashSet<String>> classMap)
{
if (initializer == null)
return;
if (context == null)
throw new IllegalArgumentException("WebAppContext null");
//We have already found the classes that directly have an annotation that was in the HandlesTypes
//annotation of the ServletContainerInitializer. For each of those classes, walk the inheritance
//hierarchy to find classes that extend or implement them.
Set<String> annotatedClassNames = initializer.getAnnotatedTypeNames();
if (annotatedClassNames != null && !annotatedClassNames.isEmpty())
{
if (classMap == null)
throw new IllegalStateException ("No class hierarchy");
for (String name : annotatedClassNames)
{
//add the class that has the annotation
initializer.addApplicableTypeName(name);
//find and add the classes that inherit the annotation
addInheritedTypes(classMap, initializer, (ConcurrentHashSet<String>)classMap.get(name));
}
}
}
private void doHandlesTypesClasses (WebAppContext context, ContainerInitializer initializer, ConcurrentHashMap<String, ConcurrentHashSet<String>> classMap)
{
if (initializer == null)
return;
if (context == null)
throw new IllegalArgumentException("WebAppContext null");
//Now we need to look at the HandlesTypes classes that were not annotations. We need to
//find all classes that extend or implement them.
if (initializer.getInterestedTypes() != null)
{
if (classMap == null)
throw new IllegalStateException ("No class hierarchy");
for (Class c : initializer.getInterestedTypes())
{
if (!c.isAnnotation())
{
//find and add the classes that implement or extend the class.
//but not including the class itself
addInheritedTypes(classMap, initializer, (ConcurrentHashSet<String>)classMap.get(c.getName()));
}
}
}
}
private void addInheritedTypes (ConcurrentHashMap<String, ConcurrentHashSet<String>> classMap, ContainerInitializer initializer, ConcurrentHashSet<String> names)
{
if (names == null || names.isEmpty())
return;
for (String s : names)
{
//add the name of the class
initializer.addApplicableTypeName(s);
//walk the hierarchy and find all types that extend or implement the class
addInheritedTypes(classMap, initializer, (ConcurrentHashSet<String>)classMap.get(s));
}
}
}

View File

@ -18,12 +18,11 @@
package org.eclipse.jetty.annotations;
import java.util.List;
import org.eclipse.jetty.annotations.AnnotationParser.Value;
import org.eclipse.jetty.annotations.AnnotationParser.ClassInfo;
import org.eclipse.jetty.annotations.AnnotationParser.FieldInfo;
import org.eclipse.jetty.annotations.AnnotationParser.MethodInfo;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.WebAppContext;
/**
@ -39,38 +38,31 @@ public class WebFilterAnnotationHandler extends AbstractDiscoverableAnnotationHa
{
super(context);
}
public WebFilterAnnotationHandler (WebAppContext context, List<DiscoveredAnnotation> list)
{
super(context, list);
}
@Override
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
List<Value> values)
public void handle(ClassInfo info, String annotationName)
{
WebFilterAnnotation wfAnnotation = new WebFilterAnnotation(_context, className, _resource);
if (annotationName == null || !"javax.servlet.annotation.WebFilter".equals(annotationName))
return;
WebFilterAnnotation wfAnnotation = new WebFilterAnnotation(_context, info.getClassName(), info.getContainingResource());
addAnnotation(wfAnnotation);
}
@Override
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
List<Value> values)
{
LOG.warn ("@WebFilter not applicable for fields: "+className+"."+fieldName);
public void handle(FieldInfo info, String annotationName)
{
if (annotationName == null || !"javax.servlet.annotation.WebFilter".equals(annotationName))
return;
LOG.warn ("@WebFilter not applicable for fields: "+info.getClassInfo().getClassName()+"."+info.getFieldName());
}
@Override
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
List<Value> values)
{
LOG.warn ("@WebFilter not applicable for methods: "+className+"."+methodName+" "+signature);
public void handle(MethodInfo info, String annotationName)
{
if (annotationName == null || !"javax.servlet.annotation.WebFilter".equals(annotationName))
return;
LOG.warn ("@WebFilter not applicable for methods: "+info.getClassInfo().getClassName()+"."+info.getMethodName()+" "+info.getSignature());
}
@Override
public String getAnnotationName()
{
return "javax.servlet.annotation.WebFilter";
}
}

View File

@ -18,12 +18,11 @@
package org.eclipse.jetty.annotations;
import java.util.List;
import org.eclipse.jetty.annotations.AnnotationParser.Value;
import org.eclipse.jetty.annotations.AnnotationParser.ClassInfo;
import org.eclipse.jetty.annotations.AnnotationParser.FieldInfo;
import org.eclipse.jetty.annotations.AnnotationParser.MethodInfo;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.WebAppContext;
public class WebListenerAnnotationHandler extends AbstractDiscoverableAnnotationHandler
@ -35,37 +34,30 @@ public class WebListenerAnnotationHandler extends AbstractDiscoverableAnnotation
super(context);
}
public WebListenerAnnotationHandler (WebAppContext context, List<DiscoveredAnnotation> list)
{
super(context, list);
}
/**
* @see org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler#handleClass(java.lang.String, int, int, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, java.util.List)
* @see org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler#handle(ClassAnnotationInfo)
*/
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
List<Value> values)
public void handle(ClassInfo info, String annotationName)
{
WebListenerAnnotation wlAnnotation = new WebListenerAnnotation(_context, className, _resource);
if (annotationName == null || !"javax.servlet.annotation.WebListener".equals(annotationName))
return;
WebListenerAnnotation wlAnnotation = new WebListenerAnnotation(_context, info.getClassName(), info.getContainingResource());
addAnnotation(wlAnnotation);
}
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
List<Value> values)
public void handle(FieldInfo info, String annotationName)
{
LOG.warn ("@WebListener is not applicable to fields: "+className+"."+fieldName);
if (annotationName == null || !"javax.servlet.annotation.WebListener".equals(annotationName))
return;
LOG.warn ("@WebListener is not applicable to fields: "+info.getClassInfo().getClassName()+"."+info.getFieldName());
}
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
List<Value> values)
public void handle(MethodInfo info, String annotationName)
{
LOG.warn ("@WebListener is not applicable to methods: "+className+"."+methodName+" "+signature);
if (annotationName == null || !"javax.servlet.annotation.WebListener".equals(annotationName))
return;
LOG.warn ("@WebListener is not applicable to methods: "+info.getClassInfo().getClassName()+"."+info.getMethodName()+" "+info.getSignature());
}
@Override
public String getAnnotationName()
{
return "javax.servlet.annotation.WebListener";
}
}

View File

@ -20,7 +20,9 @@ package org.eclipse.jetty.annotations;
import java.util.List;
import org.eclipse.jetty.annotations.AnnotationParser.Value;
import org.eclipse.jetty.annotations.AnnotationParser.ClassInfo;
import org.eclipse.jetty.annotations.AnnotationParser.FieldInfo;
import org.eclipse.jetty.annotations.AnnotationParser.MethodInfo;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
@ -41,11 +43,6 @@ public class WebServletAnnotationHandler extends AbstractDiscoverableAnnotationH
super(context);
}
public WebServletAnnotationHandler (WebAppContext context, List<DiscoveredAnnotation> list)
{
super(context, list);
}
/**
* Handle discovering a WebServlet annotation.
@ -54,34 +51,30 @@ public class WebServletAnnotationHandler extends AbstractDiscoverableAnnotationH
* @see org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler#handleClass(java.lang.String, int, int, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, java.util.List)
*/
@Override
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotationName,
List<Value> values)
public void handle(ClassInfo info, String annotationName)
{
if (!"javax.servlet.annotation.WebServlet".equals(annotationName))
if (annotationName == null || !"javax.servlet.annotation.WebServlet".equals(annotationName))
return;
WebServletAnnotation annotation = new WebServletAnnotation (_context, className, _resource);
WebServletAnnotation annotation = new WebServletAnnotation (_context, info.getClassName(), info.getContainingResource());
addAnnotation(annotation);
}
@Override
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
List<Value> values)
public void handle(FieldInfo info, String annotationName)
{
if (annotationName == null || !"javax.servlet.annotation.WebServlet".equals(annotationName))
return;
LOG.warn ("@WebServlet annotation not supported for fields");
}
@Override
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
List<Value> values)
public void handle(MethodInfo info, String annotationName)
{
if (annotationName == null || !"javax.servlet.annotation.WebServlet".equals(annotationName))
return;
LOG.warn ("@WebServlet annotation not supported for methods");
}
@Override
public String getAnnotationName()
{
return "javax.servlet.annotation.WebServlet";
}
}

View File

@ -24,14 +24,19 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationParser.Value;
import org.eclipse.jetty.annotations.AnnotationParser.AbstractHandler;
import org.eclipse.jetty.annotations.AnnotationParser.ClassInfo;
import org.eclipse.jetty.annotations.AnnotationParser.FieldInfo;
import org.eclipse.jetty.annotations.AnnotationParser.MethodInfo;
import org.eclipse.jetty.util.ConcurrentHashSet;
import org.eclipse.jetty.util.MultiMap;
import org.junit.After;
import org.junit.Test;
@ -44,34 +49,32 @@ public class TestAnnotationInheritance
List<String> classNames = new ArrayList<String>();
class SampleHandler implements DiscoverableAnnotationHandler
class SampleHandler extends AbstractHandler
{
public final List<String> annotatedClassNames = new ArrayList<String>();
public final List<String> annotatedMethods = new ArrayList<String>();
public final List<String> annotatedFields = new ArrayList<String>();
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
List<Value> values)
public void handle(ClassInfo info, String annotation)
{
annotatedClassNames.add(className);
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))
return;
annotatedClassNames.add(info.getClassName());
}
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
List<Value> values)
{
annotatedFields.add(className+"."+fieldName);
public void handle(FieldInfo info, String annotation)
{
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))
return;
annotatedFields.add(info.getClassInfo().getClassName()+"."+info.getFieldName());
}
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
List<Value> values)
public void handle(MethodInfo info, String annotation)
{
annotatedMethods.add(className+"."+methodName);
}
@Override
public String getAnnotationName()
{
return "org.eclipse.jetty.annotations.Sample";
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))
return;
annotatedMethods.add(info.getClassInfo().getClassName()+"."+info.getMethodName());
}
}
@ -92,8 +95,7 @@ public class TestAnnotationInheritance
SampleHandler handler = new SampleHandler();
AnnotationParser parser = new AnnotationParser();
parser.registerHandler(handler);
parser.parse(classNames, new ClassNameResolver ()
parser.parse(Collections.singleton(handler), classNames, new ClassNameResolver ()
{
public boolean isExcluded(String name)
{
@ -129,8 +131,7 @@ public class TestAnnotationInheritance
{
SampleHandler handler = new SampleHandler();
AnnotationParser parser = new AnnotationParser();
parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Sample", handler);
parser.parse(ClassB.class, new ClassNameResolver ()
parser.parse(Collections.singleton(handler), ClassB.class, new ClassNameResolver ()
{
public boolean isExcluded(String name)
{
@ -166,8 +167,7 @@ public class TestAnnotationInheritance
{
AnnotationParser parser = new AnnotationParser();
SampleHandler handler = new SampleHandler();
parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Sample", handler);
parser.parse(ClassA.class.getName(), new ClassNameResolver()
parser.parse(Collections.singleton(handler), ClassA.class.getName(), new ClassNameResolver()
{
public boolean isExcluded(String name)
{
@ -187,7 +187,7 @@ public class TestAnnotationInheritance
handler.annotatedFields.clear();
handler.annotatedMethods.clear();
parser.parse (ClassA.class.getName(), new ClassNameResolver()
parser.parse (Collections.singleton(handler), ClassA.class.getName(), new ClassNameResolver()
{
public boolean isExcluded(String name)
{
@ -205,9 +205,10 @@ public class TestAnnotationInheritance
@Test
public void testTypeInheritanceHandling() throws Exception
{
ConcurrentHashMap<String, ConcurrentHashSet<String>> map = new ConcurrentHashMap<String, ConcurrentHashSet<String>>();
AnnotationParser parser = new AnnotationParser();
ClassInheritanceHandler handler = new ClassInheritanceHandler();
parser.registerClassHandler(handler);
ClassInheritanceHandler handler = new ClassInheritanceHandler(map);
class Foo implements InterfaceD
{
@ -219,22 +220,22 @@ public class TestAnnotationInheritance
classNames.add(InterfaceD.class.getName());
classNames.add(Foo.class.getName());
parser.parse(classNames, null);
parser.parse(Collections.singleton(handler), classNames, null);
MultiMap map = handler.getMap();
assertNotNull(map);
assertFalse(map.isEmpty());
assertEquals(2, map.size());
Map stringArrayMap = map.toStringArrayMap();
assertTrue (stringArrayMap.keySet().contains("org.eclipse.jetty.annotations.ClassA"));
assertTrue (stringArrayMap.keySet().contains("org.eclipse.jetty.annotations.InterfaceD"));
String[] classes = (String[])stringArrayMap.get("org.eclipse.jetty.annotations.ClassA");
assertEquals(1, classes.length);
assertEquals ("org.eclipse.jetty.annotations.ClassB", classes[0]);
assertTrue (map.keySet().contains("org.eclipse.jetty.annotations.ClassA"));
assertTrue (map.keySet().contains("org.eclipse.jetty.annotations.InterfaceD"));
ConcurrentHashSet<String> classes = map.get("org.eclipse.jetty.annotations.ClassA");
assertEquals(1, classes.size());
assertEquals ("org.eclipse.jetty.annotations.ClassB", classes.iterator().next());
classes = (String[])stringArrayMap.get("org.eclipse.jetty.annotations.InterfaceD");
assertEquals(2, classes.length);
assertEquals ("org.eclipse.jetty.annotations.ClassB", classes[0]);
assertEquals(Foo.class.getName(), classes[1]);
classes = map.get("org.eclipse.jetty.annotations.InterfaceD");
assertEquals(2, classes.size());
assertTrue(classes.contains("org.eclipse.jetty.annotations.ClassB"));
assertTrue(classes.contains(Foo.class.getName()));
}
}

View File

@ -18,8 +18,11 @@
package org.eclipse.jetty.annotations;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileOutputStream;
@ -28,24 +31,26 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationParser.Value;
import org.eclipse.jetty.annotations.AnnotationParser.ClassInfo;
import org.eclipse.jetty.annotations.AnnotationParser.FieldInfo;
import org.eclipse.jetty.annotations.AnnotationParser.Handler;
import org.eclipse.jetty.annotations.AnnotationParser.MethodInfo;
import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.IO;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.TestingDir;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Rule;
import org.junit.Test;
public class TestAnnotationParser
{
public static class TrackingAnnotationHandler implements DiscoverableAnnotationHandler
public static class TrackingAnnotationHandler extends AnnotationParser.AbstractHandler
{
private final String annotationName;
public final Set<String> foundClasses;
@ -57,30 +62,11 @@ public class TestAnnotationParser
}
@Override
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
List<Value> values)
public void handle(ClassInfo info, String annotation)
{
foundClasses.add(className);
}
@Override
public void handleMethod(String className, String methodName, int access, String desc, String signature, String[] exceptions, String annotation,
List<Value> values)
{
/* ignore */
}
@Override
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
List<Value> values)
{
/* ignore */
}
@Override
public String getAnnotationName()
{
return this.annotationName;
if (annotation == null || !annotationName.equals(annotation))
return;
foundClasses.add(info.getClassName());
}
}
@ -94,47 +80,38 @@ public class TestAnnotationParser
{ "org.eclipse.jetty.annotations.ClassA" };
AnnotationParser parser = new AnnotationParser();
class SampleAnnotationHandler implements DiscoverableAnnotationHandler
class SampleAnnotationHandler extends AnnotationParser.AbstractHandler
{
private List<String> methods = Arrays.asList("a","b","c","d","l");
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
List<Value> values)
public void handle(ClassInfo info, String annotation)
{
assertEquals("org.eclipse.jetty.annotations.ClassA",className);
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))
return;
assertEquals("org.eclipse.jetty.annotations.ClassA",info.getClassName());
}
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
List<Value> values)
{
assertEquals("m",fieldName);
assertEquals(org.objectweb.asm.Type.OBJECT,org.objectweb.asm.Type.getType(fieldType).getSort());
assertEquals(1,values.size());
Value anv1 = values.get(0);
assertEquals("value",anv1.getName());
assertEquals(7,anv1.getValue());
public void handle(FieldInfo info, String annotation)
{
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))
return;
assertEquals("m",info.getFieldName());
assertEquals(org.objectweb.asm.Type.OBJECT,org.objectweb.asm.Type.getType(info.getFieldType()).getSort());
}
public void handleMethod(String className, String methodName, int access, String desc, String signature, String[] exceptions, String annotation,
List<Value> values)
{
assertEquals("org.eclipse.jetty.annotations.ClassA",className);
assertTrue(methods.contains(methodName));
public void handle(MethodInfo info, String annotation)
{
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))
return;
assertEquals("org.eclipse.jetty.annotations.ClassA",info.getClassInfo().getClassName());
assertTrue(methods.contains(info.getMethodName()));
assertEquals("org.eclipse.jetty.annotations.Sample",annotation);
}
@Override
public String getAnnotationName()
{
return "org.eclipse.jetty.annotations.Sample";
}
}
parser.registerHandler(new SampleAnnotationHandler());
//long start = System.currentTimeMillis();
parser.parse(classNames,new ClassNameResolver()
parser.parse(Collections.singleton(new SampleAnnotationHandler()), classNames,new ClassNameResolver()
{
public boolean isExcluded(String name)
{
@ -159,38 +136,33 @@ public class TestAnnotationParser
{ "org.eclipse.jetty.annotations.ClassB" };
AnnotationParser parser = new AnnotationParser();
class MultiAnnotationHandler implements DiscoverableAnnotationHandler
class MultiAnnotationHandler extends AnnotationParser.AbstractHandler
{
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
List<Value> values)
public void handle(ClassInfo info, String annotation)
{
assertTrue("org.eclipse.jetty.annotations.ClassB".equals(className));
if (annotation == null || ! "org.eclipse.jetty.annotations.Multi".equals(annotation))
return;
assertTrue("org.eclipse.jetty.annotations.ClassB".equals(info.getClassName()));
}
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
List<Value> values)
{
public void handle(FieldInfo info, String annotation)
{
if (annotation == null || ! "org.eclipse.jetty.annotations.Multi".equals(annotation))
return;
// there should not be any
fail();
}
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
List<Value> values)
{
assertTrue("org.eclipse.jetty.annotations.ClassB".equals(className));
assertTrue("a".equals(methodName));
public void handle(MethodInfo info, String annotation)
{
if (annotation == null || ! "org.eclipse.jetty.annotations.Multi".equals(annotation))
return;
assertTrue("org.eclipse.jetty.annotations.ClassB".equals(info.getClassInfo().getClassName()));
assertTrue("a".equals(info.getMethodName()));
}
@Override
public String getAnnotationName()
{
return "org.eclipse.jetty.annotations.Multi";
}
}
parser.registerHandler(new MultiAnnotationHandler());
parser.parse(classNames,null);
parser.parse(Collections.singleton(new MultiAnnotationHandler()), classNames,null);
}
@Test
@ -198,7 +170,8 @@ public class TestAnnotationParser
{
File badClassesJar = MavenTestingUtils.getTestResourceFile("bad-classes.jar");
AnnotationParser parser = new AnnotationParser();
parser.parse(badClassesJar.toURI(),null);
Set<Handler> emptySet = Collections.emptySet();
parser.parse(emptySet, badClassesJar.toURI(),null);
// only the valid classes inside bad-classes.jar should be parsed. If any invalid classes are parsed and exception would be thrown here
}
@ -221,10 +194,9 @@ public class TestAnnotationParser
// Setup annotation scanning
AnnotationParser parser = new AnnotationParser();
parser.registerHandler(tracker);
// Parse
parser.parse(basedir.toURI(),null);
parser.parse(Collections.singleton(tracker), basedir.toURI(),null);
// Validate
Assert.assertThat("Found Class", tracker.foundClasses, contains(ClassA.class.getName()));

View File

@ -25,12 +25,14 @@ import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.WebAppContext;
import org.junit.Test;
@ -41,6 +43,27 @@ import org.junit.Test;
*/
public class TestServletAnnotations
{
public class TestWebServletAnnotationHandler extends WebServletAnnotationHandler
{
List<DiscoveredAnnotation> _list = null;
public TestWebServletAnnotationHandler(WebAppContext context, List<DiscoveredAnnotation> list)
{
super(context);
_list = list;
}
@Override
public void addAnnotation(DiscoveredAnnotation a)
{
super.addAnnotation(a);
_list.add(a);
}
}
@Test
public void testServletAnnotation() throws Exception
{
@ -49,10 +72,11 @@ public class TestServletAnnotations
AnnotationParser parser = new AnnotationParser();
WebAppContext wac = new WebAppContext();
WebServletAnnotationHandler handler = new WebServletAnnotationHandler(wac);
parser.registerAnnotationHandler("javax.servlet.annotation.WebServlet", handler);
parser.parse(classes, new ClassNameResolver ()
List<DiscoveredAnnotation> results = new ArrayList<DiscoveredAnnotation>();
TestWebServletAnnotationHandler handler = new TestWebServletAnnotationHandler(wac, results);
parser.parse(Collections.singleton(handler), classes, new ClassNameResolver ()
{
public boolean isExcluded(String name)
{
@ -65,10 +89,11 @@ public class TestServletAnnotations
}
});
assertEquals(1, handler.getAnnotationList().size());
assertTrue(handler.getAnnotationList().get(0) instanceof WebServletAnnotation);
assertEquals(1, results.size());
assertTrue(results.get(0) instanceof WebServletAnnotation);
handler.getAnnotationList().get(0).apply();
results.get(0).apply();
ServletHolder[] holders = wac.getServletHandler().getServlets();
assertNotNull(holders);

View File

@ -27,7 +27,7 @@ public class HttpClientTransportOverHTTP extends AbstractHttpClientTransport
{
public HttpClientTransportOverHTTP()
{
this(1);
this(Runtime.getRuntime().availableProcessors());
}
public HttpClientTransportOverHTTP(int selectors)

View File

@ -69,7 +69,7 @@ public class SslBytesClientTest extends SslBytesTest
client.start();
SSLContext sslContext = sslContextFactory.getSslContext();
acceptor = (SSLServerSocket)sslContext.getServerSocketFactory().createServerSocket(43191);
acceptor = (SSLServerSocket)sslContext.getServerSocketFactory().createServerSocket(0);
int serverPort = acceptor.getLocalPort();

View File

@ -399,8 +399,8 @@
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>javax.annotation,org.eclipse.jetty.orbit</includeGroupIds>
<includeArtifactIds>javax.annotation-api,org.objectweb.asm</includeArtifactIds>
<includeGroupIds>javax.annotation,org.eclipse.jetty.orbit,org.ow2.asm</includeGroupIds>
<includeArtifactIds>javax.annotation-api,asm,asm-commons</includeArtifactIds>
<includeTypes>jar</includeTypes>
<outputDirectory>${assembly-directory}/lib/annotations</outputDirectory>
</configuration>
@ -439,12 +439,25 @@
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>org.eclipse.jetty.orbit,org.glassfish.web, org.glassfish, javax.el, javax.servlet.jsp</includeGroupIds>
<includeArtifactIds>javax.servlet.jsp.jstl,org.apache.taglibs.standard.glassfish,org.eclipse.jdt.core, javax.servlet.jsp-api, javax.servlet.jsp, javax.el-api, javax.el</includeArtifactIds>
<includeGroupIds>org.eclipse.jetty.orbit,org.glassfish.web, org.glassfish, javax.el, javax.servlet.jsp, org.eclipse.jetty.toolchain</includeGroupIds>
<includeArtifactIds>javax.servlet.jsp.jstl,org.apache.taglibs.standard.glassfish,org.eclipse.jdt.core, javax.servlet.jsp-api, javax.servlet.jsp, jetty-jsp-jdt, javax.el-api, javax.el</includeArtifactIds>
<includeTypes>jar</includeTypes>
<outputDirectory>${assembly-directory}/lib/jsp</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-jaspi-deps</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>org.eclipse.jetty.orbit</includeGroupIds>
<includeArtifactIds>javax.security.auth.message</includeArtifactIds>
<includeTypes>jar</includeTypes>
<outputDirectory>${assembly-directory}/lib/jaspi</outputDirectory>
</configuration>
</execution>
<execution>
<id>unpack-config-deps</id>
<phase>generate-resources</phase>
@ -489,6 +502,7 @@
<arguments>
<argument>jetty.home=${assembly-directory}</argument>
<argument>jetty.base=${assembly-directory}/demo-base</argument>
<argument>--add-to-start=server,deploy,jsp,ext,resources,client,annotations,jndi</argument>
<argument>--add-to-startd-ini=http,https</argument>
</arguments>
</configuration>
@ -541,10 +555,6 @@
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>org.objectweb.asm</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>javax.activation</artifactId>
@ -570,6 +580,10 @@
<groupId>org.glassfish.web</groupId>
<artifactId>javax.servlet.jsp</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-jsp-jdt</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
@ -579,6 +593,15 @@
<artifactId>javax.el</artifactId>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-commons</artifactId>
</dependency>
<!-- jetty deps -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
@ -704,5 +727,10 @@
<version>${project.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jaspi</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -1,9 +0,0 @@
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
org.eclipse.jetty.LEVEL=INFO
org.eclipse.jetty.STACKS=true
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.spdy.server.LEVEL=DEBUG

View File

@ -57,7 +57,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.spi.JettyExchange#getRequestHeaders()
* @see JettyHttpExchangeDelegate#getRequestHeaders()
*/
@Override
public Headers getRequestHeaders()
@ -67,7 +67,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.spi.JettyExchange#getResponseHeaders()
* @see JettyHttpExchangeDelegate#getResponseHeaders()
*/
@Override
public Headers getResponseHeaders()
@ -77,7 +77,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.spi.JettyExchange#getRequestURI()
* @see JettyHttpExchangeDelegate#getRequestURI()
*/
@Override
public URI getRequestURI()
@ -87,7 +87,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.spi.JettyExchange#getRequestMethod()
* @see JettyHttpExchangeDelegate#getRequestMethod()
*/
@Override
public String getRequestMethod()
@ -97,7 +97,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.spi.JettyExchange#getHttpContext()
* @see JettyHttpExchangeDelegate#getHttpContext()
*/
@Override
public HttpContext getHttpContext()
@ -107,7 +107,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.spi.JettyExchange#close()
* @see JettyHttpExchangeDelegate#close()
*/
@Override
public void close()
@ -127,7 +127,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.spi.JettyExchange#getRequestBody()
* @see JettyHttpExchangeDelegate#getRequestBody()
*/
@Override
public InputStream getRequestBody()
@ -137,7 +137,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.spi.JettyExchange#getResponseBody()
* @see JettyHttpExchangeDelegate#getResponseBody()
*/
@Override
public OutputStream getResponseBody()
@ -147,7 +147,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.spi.JettyExchange#sendResponseHeaders(int, long)
* @see JettyHttpExchangeDelegate#sendResponseHeaders(int, long)
*/
@Override
public void sendResponseHeaders(int rCode, long responseLength) throws IOException
@ -157,7 +157,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.spi.JettyExchange#getRemoteAddress()
* @see JettyHttpExchangeDelegate#getRemoteAddress()
*/
@Override
public InetSocketAddress getRemoteAddress()
@ -167,7 +167,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.spi.JettyExchange#getResponseCode()
* @see JettyHttpExchangeDelegate#getResponseCode()
*/
@Override
public int getResponseCode()
@ -177,7 +177,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.spi.JettyExchange#getLocalAddress()
* @see JettyHttpExchangeDelegate#getLocalAddress()
*/
@Override
public InetSocketAddress getLocalAddress()
@ -187,7 +187,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.spi.JettyExchange#getProtocol()
* @see JettyHttpExchangeDelegate#getProtocol()
*/
@Override
public String getProtocol()
@ -197,7 +197,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.spi.JettyExchange#getAttribute(java.lang.String)
* @see JettyHttpExchangeDelegate#getAttribute(java.lang.String)
*/
@Override
public Object getAttribute(String name)
@ -207,7 +207,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.spi.JettyExchange#setAttribute(java.lang.String, java.lang.Object)
* @see JettyHttpExchangeDelegate#setAttribute(java.lang.String, java.lang.Object)
*/
@Override
public void setAttribute(String name, Object value)
@ -217,7 +217,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.spi.JettyExchange#setStreams(java.io.InputStream, java.io.OutputStream)
* @see JettyHttpExchangeDelegate#setStreams(java.io.InputStream, java.io.OutputStream)
*/
@Override
public void setStreams(InputStream i, OutputStream o)

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.http;
import java.nio.ByteBuffer;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import org.eclipse.jetty.util.ArrayTrie;
import org.eclipse.jetty.util.BufferUtil;
@ -100,7 +101,8 @@ public class HttpField
CACHE.put(new HttpField(HttpHeader.AUTHORIZATION,(String)null));
CACHE.put(new HttpField(HttpHeader.COOKIE,(String)null));
}
private final static Pattern __splitter = Pattern.compile("\\s*,\\s*");
private final static byte[] __colon_space = new byte[] {':',' '};
private final HttpHeader _header;
@ -153,10 +155,10 @@ public class HttpField
if (value.equalsIgnoreCase(_value))
return true;
String[] split = _value.split("\\s*,\\s*");
for (String s : split)
String[] split = __splitter.split(_value);
for (int i = 0; split!=null && i < split.length; i++)
{
if (value.equalsIgnoreCase(s))
if (value.equalsIgnoreCase(split[i]))
return true;
}

View File

@ -272,6 +272,12 @@ public class HttpFieldsTest
public void testSetCookie() throws Exception
{
HttpFields fields = new HttpFields();
fields.addSetCookie("null",null,null,null,-1,null,false,false,-1);
assertEquals("null=",fields.getStringField("Set-Cookie"));
fields.clear();
fields.addSetCookie("minimal","value",null,null,-1,null,false,false,-1);
assertEquals("minimal=value",fields.getStringField("Set-Cookie"));

View File

@ -26,11 +26,9 @@ import java.nio.channels.ReadPendingException;
import java.nio.channels.WritePendingException;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.ExecutorCallback;
import org.eclipse.jetty.util.FutureCallback;
/**
*
* A transport EndPoint

View File

@ -232,7 +232,10 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
}
catch (Exception x)
{
LOG.info("Exception while notifying connection " + connection, x);
if (isRunning())
LOG.warn("Exception while notifying connection " + connection, x);
else
LOG.debug("Exception while notifying connection {}",connection, x);
}
}
@ -421,7 +424,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
String name = _thread.getName();
try
{
_thread.setName(name + "-selector-" + _id);
_thread.setName(name + "-selector-" + SelectorManager.this.getClass().getSimpleName()+"@"+Integer.toHexString(SelectorManager.this.hashCode())+"/"+_id);
LOG.debug("Starting {} on {}", _thread, this);
while (isRunning())
select();

View File

@ -14,6 +14,23 @@
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>config</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>

View File

@ -0,0 +1,9 @@
#
# Jetty JASPI Module
#
[depend]
security
[lib]
lib/jetty-jaspi-${jetty.version}.jar
lib/jaspi/*.jar

View File

@ -45,7 +45,10 @@ import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.eclipse.jetty.jndi.NamingContext;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.junit.Ignore;
@ -78,17 +81,24 @@ public class TestJNDI
public void testThreadContextClassloaderAndCurrentContext()
throws Exception
{
//create a jetty context, and start it so that its classloader it created
//and it is the current context
ClassLoader currentLoader = Thread.currentThread().getContextClassLoader();
ContextHandler ch = new ContextHandler();
URLClassLoader chLoader = new URLClassLoader(new URL[0], currentLoader);
ch.setClassLoader(chLoader);
Server server = new Server();
HandlerList hl = new HandlerList();
server.setHandler(hl);
hl.addHandler(ch);
//Create another one
ContextHandler ch2 = new ContextHandler();
URLClassLoader ch2Loader = new URLClassLoader(new URL[0], currentLoader);
ch2.setClassLoader(ch2Loader);
hl.addHandler(ch2);
try
{

View File

@ -1,5 +1,5 @@
#
# Jetty Servlet Module
# Jetty JSP Module
#
[depend]
@ -8,3 +8,6 @@ servlet
[lib]
lib/jsp/*.jar
[ini-template]
# To use an non-jdk compiler for JSP compilation uncomment next line
#-Dorg.apache.jasper.compiler.disablejsr199=true

View File

@ -709,19 +709,20 @@ public class JettyRunForkedMojo extends AbstractMojo
if (PluginLog.getLog().isDebugEnabled())
PluginLog.getLog().debug(Arrays.toString(cmd.toArray()));
forkedProcess = builder.start();
PluginLog.getLog().info("Forked process starting");
if (waitForChild)
{
forkedProcess = builder.start();
startPump("STDOUT",forkedProcess.getInputStream());
startPump("STDERR",forkedProcess.getErrorStream());
int exitcode = forkedProcess.waitFor();
PluginLog.getLog().info("Forked execution exit: "+exitcode);
}
else
{ //we're not going to be reading the stderr as we're not waiting for the child to finish
forkedProcess.getErrorStream().close();
{ //merge stderr and stdout from child
builder.redirectErrorStream(true);
forkedProcess = builder.start();
//wait for the child to be ready before terminating.
//child indicates it has finished starting by printing on stdout the token passed to it
@ -754,6 +755,7 @@ public class JettyRunForkedMojo extends AbstractMojo
{
throw new MojoExecutionException ("Problem determining if forked process is ready: "+e.getMessage());
}
}
}
catch (InterruptedException ex)

View File

@ -174,7 +174,7 @@ public class JettyRunMojo extends AbstractJettyMojo
/**
* Verify the configuration given in the pom.
*
* @see org.mortbay.jetty.plugin.AbstractJettyMojo#checkPomConfiguration()
* @see AbstractJettyMojo#checkPomConfiguration()
*/
public void checkPomConfiguration () throws MojoExecutionException
{

View File

@ -78,7 +78,7 @@ public class JettyRunWarExplodedMojo extends AbstractJettyMojo
/**
*
* @see org.mortbay.jetty.plugin.AbstractJettyMojo#checkPomConfiguration()
* @see AbstractJettyMojo#checkPomConfiguration()
*/
public void checkPomConfiguration() throws MojoExecutionException
{
@ -89,7 +89,7 @@ public class JettyRunWarExplodedMojo extends AbstractJettyMojo
/**
* @see org.mortbay.jetty.plugin.AbstractJettyMojo#configureScanner()
* @see AbstractJettyMojo#configureScanner()
*/
public void configureScanner() throws MojoExecutionException
{

View File

@ -83,7 +83,7 @@ public class JettyRunWarMojo extends AbstractJettyMojo
/**
* @see org.mortbay.jetty.plugin.AbstractJettyMojo#checkPomConfiguration()
* @see AbstractJettyMojo#checkPomConfiguration()
*/
public void checkPomConfiguration() throws MojoExecutionException
{
@ -94,7 +94,7 @@ public class JettyRunWarMojo extends AbstractJettyMojo
/**
* @see org.eclipse.jetty.server.plugin.AbstractJettyMojo#configureScanner()
* @see AbstractJettyMojo#configureScanner()
*/
public void configureScanner() throws MojoExecutionException
{

View File

@ -47,7 +47,6 @@ import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration;
import org.eclipse.jetty.websocket.jsr356.server.WebSocketConfiguration;
/**
* JettyWebAppContext
@ -112,7 +111,6 @@ public class JettyWebAppContext extends WebAppContext
new FragmentConfiguration(),
_envConfig = new EnvConfiguration(),
new PlusConfiguration(),
new WebSocketConfiguration(),
new MavenAnnotationConfiguration(),
new JettyWebXmlConfiguration()
});

View File

@ -19,11 +19,12 @@
package org.eclipse.jetty.maven.plugin;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jetty.annotations.AbstractDiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.annotations.AnnotationParser;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationParser.Handler;
import org.eclipse.jetty.annotations.ClassNameResolver;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -51,15 +52,11 @@ public class MavenAnnotationConfiguration extends AnnotationConfiguration
if (metaData == null)
throw new IllegalStateException ("No metadata");
parser.clearHandlers();
for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
{
if (h instanceof AbstractDiscoverableAnnotationHandler)
((AbstractDiscoverableAnnotationHandler)h).setResource(null); //
}
parser.registerHandlers(_discoverableAnnotationHandlers);
parser.registerHandler(_classInheritanceHandler);
parser.registerHandlers(_containerInitializerAnnotationHandlers);
Set<Handler> handlers = new HashSet<Handler>();
handlers.addAll(_discoverableAnnotationHandlers);
if (_classInheritanceHandler != null)
handlers.add(_classInheritanceHandler);
handlers.addAll(_containerInitializerAnnotationHandlers);
for (File f:jwac.getClassPathFiles())
@ -67,7 +64,7 @@ public class MavenAnnotationConfiguration extends AnnotationConfiguration
//scan the equivalent of the WEB-INF/classes directory that has been synthesised by the plugin
if (f.isDirectory() && f.exists())
{
doParse(context, parser, Resource.newResource(f.toURI()));
doParse(handlers, context, parser, Resource.newResource(f.toURI()));
}
}
@ -78,32 +75,19 @@ public class MavenAnnotationConfiguration extends AnnotationConfiguration
Resource classesDir = context.getWebInf().addPath("classes/");
if (classesDir.exists())
{
doParse(context, parser, classesDir);
doParse(handlers, context, parser, classesDir);
}
}
}
}
public void doParse (final WebAppContext context, final AnnotationParser parser, Resource resource)
public void doParse (final Set<? extends Handler> handlers, final WebAppContext context, final AnnotationParser parser, Resource resource)
throws Exception
{
parser.parseDir(resource, new ClassNameResolver()
{
public boolean isExcluded (String name)
{
if (context.isSystemClass(name)) return true;
if (context.isServerClass(name)) return false;
return false;
}
public boolean shouldOverride (String name)
{
//looking at webapp classpath, found already-parsed class of same name - did it come from system or duplicate in webapp?
if (context.isParentLoaderPriority())
return false;
return true;
}
});
if (_parserTasks != null)
_parserTasks.add(new ParserTask(parser, handlers, resource, _webAppClassNameResolver));
else
parser.parse(handlers, resource, _webAppClassNameResolver);
}
}

View File

@ -18,16 +18,14 @@
package org.eclipse.jetty.osgi.annotations;
import java.util.ArrayList;
import java.util.List;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jetty.annotations.AbstractDiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationParser.Handler;
import org.eclipse.jetty.annotations.ClassNameResolver;
import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.WebAppContext;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
@ -39,7 +37,27 @@ import org.osgi.framework.Constants;
*/
public class AnnotationConfiguration extends org.eclipse.jetty.annotations.AnnotationConfiguration
{
public class BundleParserTask extends ParserTask
{
public BundleParserTask (AnnotationParser parser, Set<? extends Handler>handlers, Resource resource, ClassNameResolver resolver)
{
super(parser, handlers, resource, resolver);
}
public Void call() throws Exception
{
if (_parser != null)
{
org.eclipse.jetty.osgi.annotations.AnnotationParser osgiAnnotationParser = (org.eclipse.jetty.osgi.annotations.AnnotationParser)_parser;
Bundle bundle = osgiAnnotationParser.getBundle(_resource);
osgiAnnotationParser.parse(_handlers, bundle, _resolver);
}
return null;
}
}
/**
* This parser scans the bundles using the OSGi APIs instead of assuming a jar.
*/
@ -69,7 +87,7 @@ public class AnnotationConfiguration extends org.eclipse.jetty.annotations.Annot
Bundle[] fragAndRequiredBundles = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles(webbundle);
if (fragAndRequiredBundles != null)
{
//index:
//index and scan fragments
for (Bundle bundle : fragAndRequiredBundles)
{
Resource bundleRes = oparser.indexBundle(bundle);
@ -77,19 +95,16 @@ public class AnnotationConfiguration extends org.eclipse.jetty.annotations.Annot
{
context.getMetaData().addWebInfJar(bundleRes);
}
}
//scan the fragments
for (Bundle fragmentBundle : fragAndRequiredBundles)
{
if (fragmentBundle.getHeaders().get(Constants.FRAGMENT_HOST) != null)
if (bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null)
{
//a fragment indeed:
parseFragmentBundle(context,oparser,webbundle,fragmentBundle);
parseFragmentBundle(context,oparser,webbundle,bundle);
}
}
}
//scan ourselves
oparser.indexBundle(webbundle);
parseWebBundle(context,oparser,webbundle);
//scan the WEB-INF/lib
@ -151,27 +166,21 @@ public class AnnotationConfiguration extends org.eclipse.jetty.annotations.Annot
}
protected void parseBundle(WebAppContext context, AnnotationParser parser,
Bundle webbundle, Bundle bundle) throws Exception
{
Resource bundleRes = parser.getResource(bundle);
parser.clearHandlers();
for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
{
if (h instanceof AbstractDiscoverableAnnotationHandler)
{
if (webbundle == bundle)
((AbstractDiscoverableAnnotationHandler)h).setResource(null);
else
((AbstractDiscoverableAnnotationHandler)h).setResource(bundleRes);
}
}
parser.registerHandlers(_discoverableAnnotationHandlers);
parser.registerHandler(_classInheritanceHandler);
parser.registerHandlers(_containerInitializerAnnotationHandlers);
parser.parse(bundle,createClassNameResolver(context));
Bundle webbundle, Bundle bundle) throws Exception
{
Resource bundleRes = parser.getResource(bundle);
Set<Handler> handlers = new HashSet<Handler>();
handlers.addAll(_discoverableAnnotationHandlers);
if (_classInheritanceHandler != null)
handlers.add(_classInheritanceHandler);
handlers.addAll(_containerInitializerAnnotationHandlers);
ClassNameResolver classNameResolver = createClassNameResolver(context);
if (_parserTasks != null)
_parserTasks.add(new BundleParserTask(parser, handlers, bundleRes, classNameResolver));
else
parser.parse(handlers, bundle, classNameResolver);
}
/**

View File

@ -29,9 +29,11 @@ import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.jetty.annotations.ClassNameResolver;
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
import org.eclipse.jetty.util.ConcurrentHashSet;
import org.eclipse.jetty.util.resource.Resource;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
@ -41,11 +43,12 @@ import org.osgi.framework.Constants;
*/
public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationParser
{
private Set<URI> _alreadyParsed = new HashSet<URI>();
private Set<URI> _alreadyParsed = new ConcurrentHashSet<URI>();
private Map<URI,Bundle> _uriToBundle = new HashMap<URI, Bundle>();
private Map<Bundle,Resource> _resourceToBundle = new HashMap<Bundle,Resource>();
private Map<Bundle,URI> _bundleToUri = new HashMap<Bundle, URI>();
private ConcurrentHashMap<URI,Bundle> _uriToBundle = new ConcurrentHashMap<URI, Bundle>();
private ConcurrentHashMap<Bundle,Resource> _bundleToResource = new ConcurrentHashMap<Bundle,Resource>();
private ConcurrentHashMap<Resource, Bundle> _resourceToBundle = new ConcurrentHashMap<Resource, Bundle>();
private ConcurrentHashMap<Bundle,URI> _bundleToUri = new ConcurrentHashMap<Bundle, URI>();
/**
* Keep track of a jetty URI Resource and its associated OSGi bundle.
@ -58,9 +61,10 @@ public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationPa
File bundleFile = BundleFileLocatorHelper.DEFAULT.getBundleInstallLocation(bundle);
Resource resource = Resource.newResource(bundleFile.toURI());
URI uri = resource.getURI();
_uriToBundle.put(uri,bundle);
_bundleToUri.put(bundle,uri);
_resourceToBundle.put(bundle,resource);
_uriToBundle.putIfAbsent(uri,bundle);
_bundleToUri.putIfAbsent(bundle,uri);
_bundleToResource.putIfAbsent(bundle,resource);
_resourceToBundle.putIfAbsent(resource,bundle);
return resource;
}
protected URI getURI(Bundle bundle)
@ -69,13 +73,19 @@ public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationPa
}
protected Resource getResource(Bundle bundle)
{
return _resourceToBundle.get(bundle);
return _bundleToResource.get(bundle);
}
protected Bundle getBundle (Resource resource)
{
return _resourceToBundle.get(resource);
}
/**
*
*/
@Override
public void parse (URI[] uris, ClassNameResolver resolver)
public void parse (Set<? extends Handler> handlers, URI[] uris, ClassNameResolver resolver)
throws Exception
{
for (URI uri : uris)
@ -89,16 +99,16 @@ public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationPa
}
//a jar in WEB-INF/lib or the WEB-INF/classes
//use the behavior of the super class for a standard jar.
super.parse(new URI[] {uri},resolver);
super.parse(handlers, new URI[] {uri},resolver);
}
else
{
parse(associatedBundle,resolver);
parse(handlers, associatedBundle,resolver);
}
}
}
protected void parse(Bundle bundle, ClassNameResolver resolver)
protected void parse(Set<? extends Handler> handlers, Bundle bundle, ClassNameResolver resolver)
throws Exception
{
URI uri = _bundleToUri.get(bundle);
@ -190,7 +200,7 @@ public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationPa
//transform into a classname to pass to the resolver
String shortName = name.replace('/', '.').substring(0,name.length()-6);
if ((resolver == null)|| (!resolver.isExcluded(shortName) && (!isParsed(shortName) || resolver.shouldOverride(shortName))))
scanClass(classUrl.openStream());
scanClass(handlers, getResource(bundle), classUrl.openStream());
}
}

View File

@ -21,7 +21,11 @@ package org.eclipse.jetty.osgi.boot;
import java.net.URL;
import java.util.ArrayList;
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 org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelperFactory;
import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
@ -53,8 +57,8 @@ public class OSGiMetaInfConfiguration extends MetaInfConfiguration
@Override
public void preConfigure(final WebAppContext context) throws Exception
{
List<Resource> frags = (List<Resource>) context.getAttribute(METAINF_FRAGMENTS);
List<Resource> resfrags = (List<Resource>) context.getAttribute(METAINF_RESOURCES);
Map<Resource, Resource> frags = (Map<Resource, Resource>) context.getAttribute(METAINF_FRAGMENTS);
Set<Resource> resfrags = (Set<Resource>) context.getAttribute(METAINF_RESOURCES);
List<Resource> tldfrags = (List<Resource>) context.getAttribute(METAINF_TLDS);
Bundle[] fragments = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles((Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE));
@ -73,10 +77,11 @@ public class OSGiMetaInfConfiguration extends MetaInfConfiguration
{
if (frags == null)
{
frags = new ArrayList<Resource>();
frags = new HashMap<Resource,Resource>();
context.setAttribute(METAINF_FRAGMENTS, frags);
}
frags.add(Resource.newResource(BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(frag).toURI()));
frags.put(Resource.newResource(BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(frag).toURI()),
Resource.newResource(webFrag));
}
if (resEnum != null && resEnum.hasMoreElements())
{
@ -92,7 +97,7 @@ public class OSGiMetaInfConfiguration extends MetaInfConfiguration
{
if (resfrags == null)
{
resfrags = new ArrayList<Resource>();
resfrags = new HashSet<Resource>();
context.setAttribute(METAINF_RESOURCES, resfrags);
}
resfrags.add(Resource.newResource(BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(resourcesEntry)));

View File

@ -212,7 +212,7 @@ public class OSGiWebInfConfiguration extends WebInfConfiguration
}
}
if (!appendedResourcesPath.isEmpty())
context.setAttribute(WebInfConfiguration.RESOURCE_URLS, new ArrayList<Resource>(appendedResourcesPath.values()));
context.setAttribute(WebInfConfiguration.RESOURCE_DIRS, new HashSet<Resource>(appendedResourcesPath.values()));
}
}

View File

@ -172,7 +172,7 @@
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-jsp-fragment</artifactId>
<version>2.3.2</version>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
<dependency>

View File

@ -18,26 +18,33 @@
package org.eclipse.jetty.plus.annotation;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContextListener;
import org.eclipse.jetty.util.ConcurrentHashSet;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.WebAppContext;
public class ContainerInitializer
{
protected ServletContainerInitializer _target;
protected Class[] _interestedTypes;
protected Set<String> _applicableTypeNames;
protected Set<String> _annotatedTypeNames;
private static final Logger LOG = Log.getLogger(ContainerInitializer.class);
final protected ServletContainerInitializer _target;
final protected Class[] _interestedTypes;
protected Set<String> _applicableTypeNames = new ConcurrentHashSet<String>();
protected Set<String> _annotatedTypeNames = new ConcurrentHashSet<String>();
public void setTarget (ServletContainerInitializer target)
public ContainerInitializer (ServletContainerInitializer target, Class[] classes)
{
_target = target;
_interestedTypes = classes;
}
public ServletContainerInitializer getTarget ()
@ -50,10 +57,6 @@ public class ContainerInitializer
return _interestedTypes;
}
public void setInterestedTypes (Class[] interestedTypes)
{
_interestedTypes = interestedTypes;
}
/**
* A class has been found that has an annotation of interest
@ -62,26 +65,22 @@ public class ContainerInitializer
*/
public void addAnnotatedTypeName (String className)
{
if (_annotatedTypeNames == null)
_annotatedTypeNames = new HashSet<String>();
_annotatedTypeNames.add(className);
}
public Set<String> getAnnotatedTypeNames ()
{
return _annotatedTypeNames;
return Collections.unmodifiableSet(_annotatedTypeNames);
}
public void addApplicableTypeName (String className)
{
if (_applicableTypeNames == null)
_applicableTypeNames = new HashSet<String>();
_applicableTypeNames.add(className);
}
public Set<String> getApplicableTypeNames ()
{
return _applicableTypeNames;
return Collections.unmodifiableSet(_applicableTypeNames);
}
@ -97,13 +96,18 @@ public class ContainerInitializer
try
{
if (_applicableTypeNames != null)
{
for (String s : _applicableTypeNames)
classes.add(Loader.loadClass(context.getClass(), s));
}
for (String s : _applicableTypeNames)
classes.add(Loader.loadClass(context.getClass(), s));
context.getServletContext().setExtendedListenerTypes(true);
_target.onStartup(classes, context.getServletContext());
if (LOG.isDebugEnabled())
{
long start = System.nanoTime();
_target.onStartup(classes, context.getServletContext());
LOG.debug("ContainerInitializer {} called in {}ms", _target.getClass().getName(), TimeUnit.MILLISECONDS.convert(System.nanoTime()-start, TimeUnit.NANOSECONDS));
}
else
_target.onStartup(classes, context.getServletContext());
}
finally
{

View File

@ -177,7 +177,7 @@ public class ConnectHandler extends HandlerWrapper
protected SelectorManager newSelectorManager()
{
return new Manager(getExecutor(), getScheduler(), 1);
return new ConnectManager(getExecutor(), getScheduler(), 1);
}
@Override
@ -429,10 +429,10 @@ public class ConnectHandler extends HandlerWrapper
dump(out, indent, getBeans(), TypeUtil.asList(getHandlers()));
}
protected class Manager extends SelectorManager
protected class ConnectManager extends SelectorManager
{
private Manager(Executor executor, Scheduler scheduler, int selectors)
private ConnectManager(Executor executor, Scheduler scheduler, int selectors)
{
super(executor, scheduler, selectors);
}

View File

@ -28,8 +28,10 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.servlet.AsyncContext;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
@ -47,7 +49,6 @@ import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.HttpCookieStore;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -206,7 +207,8 @@ public class ProxyServlet extends HttpServlet
* <tr>
* <td>maxThreads</td>
* <td>256</td>
* <td>The max number of threads of HttpClient's Executor</td>
* <td>The max number of threads of HttpClient's Executor. If not set, or set to the value of "-", then the
* Jetty server thread pool will be used.</td>
* </tr>
* <tr>
* <td>maxConnections</td>
@ -244,21 +246,30 @@ public class ProxyServlet extends HttpServlet
ServletConfig config = getServletConfig();
HttpClient client = newHttpClient();
// Redirects must be proxied as is, not followed
client.setFollowRedirects(false);
// Must not store cookies, otherwise cookies of different clients will mix
client.setCookieStore(new HttpCookieStore.Empty());
Executor executor;
String value = config.getInitParameter("maxThreads");
if (value == null)
value = "256";
QueuedThreadPool executor = new QueuedThreadPool(Integer.parseInt(value));
String servletName = config.getServletName();
int dot = servletName.lastIndexOf('.');
if (dot >= 0)
servletName = servletName.substring(dot + 1);
executor.setName(servletName);
if (value == null || "-".equals(value))
{
executor = (Executor)getServletContext().getAttribute("org.eclipse.jetty.server.Executor");
}
else
{
QueuedThreadPool qtp= new QueuedThreadPool(Integer.parseInt(value));
String servletName = config.getServletName();
int dot = servletName.lastIndexOf('.');
if (dot >= 0)
servletName = servletName.substring(dot + 1);
qtp.setName(servletName);
executor=qtp;
}
client.setExecutor(executor);
value = config.getInitParameter("maxConnections");

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@ -361,13 +362,13 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
// Complete generating the response
_response.closeOutput();
}
catch(EofException e)
catch(EofException|ClosedChannelException e)
{
LOG.debug(e);
}
catch(Exception e)
{
LOG.warn("handle complete",e);
LOG.warn("complete failed",e);
}
finally
{
@ -762,7 +763,7 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
@Override
public void failed(final Throwable x)
{
if (x instanceof EofException)
if (x instanceof EofException || x instanceof ClosedChannelException)
{
LOG.debug(x);
_callback.failed(x);

View File

@ -51,6 +51,7 @@ public abstract class HttpInput<T> extends ServletInputStream implements Runnabl
{
private final static Logger LOG = Log.getLogger(HttpInput.class);
private final byte[] _oneByteBuffer = new byte[1];
private HttpChannelState _channelState;
private Throwable _onError;
private ReadListener _listener;
@ -59,6 +60,7 @@ public abstract class HttpInput<T> extends ServletInputStream implements Runnabl
protected State _state = BLOCKING;
private State _eof=null;
private final Object _lock;
private long _contentRead;
protected HttpInput()
{
@ -82,6 +84,7 @@ public abstract class HttpInput<T> extends ServletInputStream implements Runnabl
_state = BLOCKING;
_eof=null;
_onError=null;
_contentRead=0;
}
}
@ -118,9 +121,8 @@ public abstract class HttpInput<T> extends ServletInputStream implements Runnabl
@Override
public int read() throws IOException
{
byte[] bytes = new byte[1];
int read = read(bytes, 0, 1);
return read < 0 ? -1 : 0xff & bytes[0];
int read = read(_oneByteBuffer, 0, 1);
return read < 0 ? -1 : 0xff & _oneByteBuffer[0];
}
@Override
@ -144,6 +146,7 @@ public abstract class HttpInput<T> extends ServletInputStream implements Runnabl
public int read(byte[] b, int off, int len) throws IOException
{
T item = null;
int l;
synchronized (lock())
{
// System.err.printf("read s=%s q=%d e=%s%n",_state,_inputQ.size(),_eof);
@ -159,10 +162,14 @@ public abstract class HttpInput<T> extends ServletInputStream implements Runnabl
if (item==null)
return _state.noContent();
}
l=get(item, b, off, len);
_contentRead+=l;
}
return get(item, b, off, len);
return l;
}
protected abstract int remaining(T item);
protected abstract int get(T item, byte[] buffer, int offset, int length);
@ -179,14 +186,20 @@ public abstract class HttpInput<T> extends ServletInputStream implements Runnabl
return true;
}
/* ------------------------------------------------------------ */
public long getContentRead()
{
synchronized (lock())
{
return _contentRead;
}
}
/** Add some content to the input stream
* @param item
*/
public abstract void content(T item);
/* ------------------------------------------------------------ */
/** This method should be called to signal to the HttpInput
* that an EOF has arrived before all the expected content.
* Typically this will result in an EOFException being thrown
@ -206,7 +219,6 @@ public abstract class HttpInput<T> extends ServletInputStream implements Runnabl
}
}
/* ------------------------------------------------------------ */
public void messageComplete()
{
synchronized (lock())
@ -221,7 +233,6 @@ public abstract class HttpInput<T> extends ServletInputStream implements Runnabl
}
}
/* ------------------------------------------------------------ */
public void consumeAll()
{
synchronized (lock())
@ -355,7 +366,6 @@ public abstract class HttpInput<T> extends ServletInputStream implements Runnabl
}
}
protected static class State
{
public void waitForContent(HttpInput<?> in) throws IOException
@ -432,7 +442,6 @@ public abstract class HttpInput<T> extends ServletInputStream implements Runnabl
}
};
public void init(HttpChannelState state)
{
synchronized (lock())

View File

@ -312,6 +312,7 @@ public class LowResourceMonitor extends AbstractLifeCycle
LOG.info("Low Resources cleared");
_reasons=null;
_lowStarted=0;
_cause=null;
clearLowResources();
}
}

View File

@ -515,7 +515,7 @@ public class Request implements HttpServletRequest
{
return (int)_fields.getLongField(HttpHeader.CONTENT_LENGTH.toString());
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest.getContentLengthLong()
@ -526,6 +526,12 @@ public class Request implements HttpServletRequest
return _fields.getLongField(HttpHeader.CONTENT_LENGTH.toString());
}
/* ------------------------------------------------------------ */
public long getContentRead()
{
return _input.getContentRead();
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getContentType()

View File

@ -54,7 +54,7 @@ public class AllowSymLinkAliasChecker implements AliasCheck
{
// we can use the real path method to check the symlinks resolve to the alias
URI real = file.toPath().toRealPath().toUri();
if (real.equals(resource.getAlias().toURI()))
if (real.equals(resource.getAlias()))
{
LOG.debug("Allow symlink {} --> {}",resource,real);
return true;
@ -77,7 +77,7 @@ public class AllowSymLinkAliasChecker implements AliasCheck
d=link.toFile().getAbsoluteFile().getCanonicalFile();
}
}
if (resource.getAlias().toURI().equals(d.toURI()))
if (resource.getAlias().equals(d.toURI()))
{
LOG.debug("Allow symlink {} --> {}",resource,d);
return true;

View File

@ -22,6 +22,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
@ -96,6 +97,8 @@ import org.eclipse.jetty.util.resource.Resource;
* <p>
* The maximum size of a form that can be processed by this context is controlled by the system properties org.eclipse.jetty.server.Request.maxFormKeys
* and org.eclipse.jetty.server.Request.maxFormContentSize. These can also be configured with {@link #setMaxFormContentSize(int)} and {@link #setMaxFormKeys(int)}
* <p>
* This servers executore is made available via a context attributed "org.eclipse.jetty.server.Executor".
*
* @org.apache.xbean.XBean description="Creates a basic HTTP context"
*/
@ -718,6 +721,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
Thread current_thread = null;
Context old_context = null;
_attributes.setAttribute("org.eclipse.jetty.server.Executor",getServer().getThreadPool());
try
{
// Set the classloader
@ -1652,6 +1657,15 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
{
return Resource.newResource(url);
}
/* ------------------------------------------------------------ */
/**
* Convert URL to Resource wrapper for {@link Resource#newResource(URL)} enables extensions to provide alternate resource implementations.
*/
public Resource newResource(URI uri) throws IOException
{
return Resource.newResource(uri);
}
/* ------------------------------------------------------------ */
/**

View File

@ -316,7 +316,7 @@ public class ContextHandlerGetResourceTest
Resource resource=context.getResource(path);
assertNotNull(resource);
assertEquals(context.getResource("/subdir/TextFile.Long.txt").getURL(),resource.getAlias());
assertEquals(context.getResource("/subdir/TextFile.Long.txt").getURI(),resource.getAlias());
URL url=context.getServletContext().getResource(path);
assertNotNull(url);

View File

@ -399,6 +399,7 @@ public class ContextHandlerTest
public void testAttributes() throws Exception
{
ContextHandler handler = new ContextHandler();
handler.setServer(new Server());
handler.setAttribute("aaa","111");
assertEquals("111",handler.getServletContext().getAttribute("aaa"));
assertEquals(null,handler.getAttribute("bbb"));

View File

@ -80,7 +80,7 @@ public class SPDYConnection extends AbstractConnection implements Controller, Id
@Override
public void onFillable()
{
ByteBuffer buffer = bufferPool.acquire(bufferSize, true);
ByteBuffer buffer = bufferPool.acquire(bufferSize, false);
boolean readMore = read(buffer) == 0;
bufferPool.release(buffer);
if (readMore)

View File

@ -533,7 +533,6 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
streamListener = notifyOnSyn(listener, stream, synInfo);
}
stream.setStreamFrameListener(streamListener);
flush();
// The onSyn() listener may have sent a frame that closed the stream
if (stream.isClosed())
removeStream(stream);
@ -698,7 +697,6 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
RstInfo rstInfo = new RstInfo(frame.getStreamId(), StreamStatus.from(frame.getVersion(), frame.getStatusCode()));
notifyOnRst(listener, rstInfo);
flush();
if (stream != null)
removeStream(stream);
@ -722,7 +720,6 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
}
SettingsInfo settingsInfo = new SettingsInfo(frame.getSettings(), frame.isClearPersisted());
notifyOnSettings(listener, settingsInfo);
flush();
}
private void onPing(PingFrame frame)
@ -732,7 +729,6 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
{
PingResultInfo pingResultInfo = new PingResultInfo(frame.getPingId());
notifyOnPing(listener, pingResultInfo);
flush();
}
else
{
@ -747,7 +743,6 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
//TODO: Find a better name for GoAwayResultInfo
GoAwayResultInfo goAwayResultInfo = new GoAwayResultInfo(frame.getLastStreamId(), SessionStatus.from(frame.getStatusCode()));
notifyOnGoAway(listener, goAwayResultInfo);
flush();
// SPDY does not require to send back a response to a GO_AWAY.
// We notified the application of the last good stream id and
// tried our best to flush remaining data.
@ -788,7 +783,6 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
private void onCredential(CredentialFrame frame)
{
LOG.warn("{} frame not yet supported", frame.getType());
flush();
}
protected void close()

View File

@ -246,7 +246,6 @@ public class StandardStream extends IdleTimeout implements IStream
throw new IllegalStateException();
}
}
session.flush();
}
@Override
@ -270,7 +269,6 @@ public class StandardStream extends IdleTimeout implements IStream
updateCloseState(dataInfo.isClose(), false);
notifyOnData(dataInfo);
session.flush();
}
@Override

View File

@ -53,7 +53,7 @@ public class CredentialGenerator extends ControlFrameGenerator
int frameBodyLength = 2 + 4 + proof.length + certificates.size() * 4 + certificatesLength;
int totalLength = ControlFrame.HEADER_LENGTH + frameBodyLength;
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, true);
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, Generator.useDirectBuffers);
BufferUtil.clearToFill(buffer);
generateControlFrameHeader(credential, frameBodyLength, buffer);

View File

@ -36,7 +36,7 @@ public class DataFrameGenerator
public ByteBuffer generate(int streamId, int length, DataInfo dataInfo)
{
ByteBuffer buffer = bufferPool.acquire(DataFrame.HEADER_LENGTH + length, true);
ByteBuffer buffer = bufferPool.acquire(DataFrame.HEADER_LENGTH + length, Generator.useDirectBuffers);
BufferUtil.clearToFill(buffer);
buffer.limit(length + DataFrame.HEADER_LENGTH);
buffer.position(DataFrame.HEADER_LENGTH);

View File

@ -29,6 +29,7 @@ import org.eclipse.jetty.spdy.frames.ControlFrameType;
public class Generator
{
final static boolean useDirectBuffers=false;
private final EnumMap<ControlFrameType, ControlFrameGenerator> generators = new EnumMap<>(ControlFrameType.class);
private final DataFrameGenerator dataFrameGenerator;

View File

@ -40,7 +40,7 @@ public class GoAwayGenerator extends ControlFrameGenerator
int frameBodyLength = 8;
int totalLength = ControlFrame.HEADER_LENGTH + frameBodyLength;
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, true);
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, Generator.useDirectBuffers);
BufferUtil.clearToFill(buffer);
generateControlFrameHeader(goAway, frameBodyLength, buffer);

View File

@ -60,7 +60,7 @@ public class HeadersGenerator extends ControlFrameGenerator
int totalLength = ControlFrame.HEADER_LENGTH + frameLength;
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, true);
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, Generator.useDirectBuffers);
BufferUtil.clearToFill(buffer);
generateControlFrameHeader(headers, frameLength, buffer);

View File

@ -39,7 +39,7 @@ public class NoOpGenerator extends ControlFrameGenerator
int frameBodyLength = 0;
int totalLength = ControlFrame.HEADER_LENGTH + frameBodyLength;
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, true);
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, Generator.useDirectBuffers);
BufferUtil.clearToFill(buffer);
generateControlFrameHeader(noOp, frameBodyLength, buffer);

View File

@ -39,7 +39,7 @@ public class PingGenerator extends ControlFrameGenerator
int frameBodyLength = 4;
int totalLength = ControlFrame.HEADER_LENGTH + frameBodyLength;
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, true);
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, Generator.useDirectBuffers);
BufferUtil.clearToFill(buffer);
generateControlFrameHeader(ping, frameBodyLength, buffer);

View File

@ -39,7 +39,7 @@ public class RstStreamGenerator extends ControlFrameGenerator
int frameBodyLength = 8;
int totalLength = ControlFrame.HEADER_LENGTH + frameBodyLength;
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, true);
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, Generator.useDirectBuffers);
BufferUtil.clearToFill(buffer);
generateControlFrameHeader(rstStream, frameBodyLength, buffer);

View File

@ -43,7 +43,7 @@ public class SettingsGenerator extends ControlFrameGenerator
int size = settings.size();
int frameBodyLength = 4 + 8 * size;
int totalLength = ControlFrame.HEADER_LENGTH + frameBodyLength;
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, true);
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, Generator.useDirectBuffers);
BufferUtil.clearToFill(buffer);
generateControlFrameHeader(settingsFrame, frameBodyLength, buffer);

View File

@ -58,7 +58,7 @@ public class SynReplyGenerator extends ControlFrameGenerator
int totalLength = ControlFrame.HEADER_LENGTH + frameLength;
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, true);
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, Generator.useDirectBuffers);
BufferUtil.clearToFill(buffer);
generateControlFrameHeader(synReply, frameLength, buffer);

View File

@ -60,7 +60,7 @@ public class SynStreamGenerator extends ControlFrameGenerator
int totalLength = ControlFrame.HEADER_LENGTH + frameLength;
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, true);
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, Generator.useDirectBuffers);
BufferUtil.clearToFill(buffer);
generateControlFrameHeader(synStream, frameLength, buffer);

View File

@ -39,7 +39,7 @@ public class WindowUpdateGenerator extends ControlFrameGenerator
int frameBodyLength = 8;
int totalLength = ControlFrame.HEADER_LENGTH + frameBodyLength;
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, true);
ByteBuffer buffer = getByteBufferPool().acquire(totalLength, Generator.useDirectBuffers);
BufferUtil.clearToFill(buffer);
generateControlFrameHeader(windowUpdate, frameBodyLength, buffer);

View File

@ -57,7 +57,7 @@ public class SSLExternalServerTest extends AbstractHTTPSPDYTest
return new SPDYClient.Factory(threadPool, null, sslContextFactory, 30000);
}
@Test
@Test(timeout=5000)
public void testExternalServer() throws Exception
{
String host = "encrypted.google.com";

View File

@ -0,0 +1,159 @@
//
// ========================================================================
// 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.spdy.server.http;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.http.HTTPSPDYHeader;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.hamcrest.CoreMatchers;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@Ignore("So far only used for testing performance tweaks. So no need to run it in a build")
public class SimpleHTTPBenchmarkTest extends AbstractHTTPSPDYTest
{
private static final Logger LOG = Log.getLogger(SimpleHTTPBenchmarkTest.class);
private final int dataSize = 4096 * 100;
private Session session;
private int requestCount = 100;
public SimpleHTTPBenchmarkTest(short version)
{
super(version);
}
@Before
public void setUp() throws Exception
{
final byte[] data = new byte[dataSize];
new Random().nextBytes(data);
session = startClient(version, startHTTPServer(version, new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
throws IOException, ServletException
{
request.setHandled(true);
assertEquals("GET", httpRequest.getMethod());
assertThat("accept-encoding is set to gzip, even if client didn't set it",
httpRequest.getHeader("accept-encoding"), containsString("gzip"));
assertThat(httpRequest.getHeader("host"), is("localhost:" + connector.getLocalPort()));
httpResponse.getOutputStream().write(data);
}
}, 0), null);
}
@Test
public void testRunBenchmark() throws Exception
{
long overallStart = System.nanoTime();
int iterations = 20;
for (int j = 0; j < iterations; j++)
{
long start = System.nanoTime();
for (int i = 0; i < requestCount; i++)
sendGetRequestWithData();
long timeElapsed = System.nanoTime() - start;
LOG.info("Requests with {}b response took: {}ms", dataSize, timeElapsed / 1000 / 1000);
}
long timeElapsedOverall = (System.nanoTime() - overallStart) / 1000 / 1000;
LOG.info("Time elapsed overall: {}ms avg: {}ms", timeElapsedOverall, timeElapsedOverall / iterations);
}
private void sendGetRequest() throws Exception
{
final CountDownLatch replyLatch = new CountDownLatch(1);
final String path = "/foo";
Fields headers = SPDYTestUtils.createHeaders("localhost", connector.getLocalPort(), version, "GET", path);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
{
assertTrue(replyInfo.isClose());
Fields replyHeaders = replyInfo.getHeaders();
assertThat(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version)).value().contains("200"), CoreMatchers.is(true));
assertThat(replyHeaders.get(HttpHeader.SERVER.asString()), CoreMatchers.is(notNullValue()));
assertThat(replyHeaders.get(HttpHeader.X_POWERED_BY.asString()), CoreMatchers.is(notNullValue()));
replyLatch.countDown();
}
});
assertThat("reply has been received", replyLatch.await(5, TimeUnit.SECONDS), is(true));
}
private void sendGetRequestWithData() throws Exception
{
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
final String path = "/foo";
Fields headers = SPDYTestUtils.createHeaders("localhost", connector.getLocalPort(), version, "GET", path);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
{
Fields replyHeaders = replyInfo.getHeaders();
assertThat(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version)).value().contains("200"), CoreMatchers.is(true));
assertThat(replyHeaders.get(HttpHeader.SERVER.asString()), CoreMatchers.is(notNullValue()));
assertThat(replyHeaders.get(HttpHeader.X_POWERED_BY.asString()), CoreMatchers.is(notNullValue()));
replyLatch.countDown();
}
@Override
public void onData(Stream stream, DataInfo dataInfo)
{
dataInfo.consume(dataInfo.available());
if (dataInfo.isClose())
dataLatch.countDown();
}
});
assertThat("reply has been received", replyLatch.await(5, TimeUnit.SECONDS), is(true));
assertThat("data has been received", dataLatch.await(5, TimeUnit.SECONDS), is(true));
}
}

View File

@ -67,18 +67,8 @@ import java.util.regex.Pattern;
* </li>
* <li>Module Resolution</li>
* <li>Properties Resolution</li>
* <li>Execution
* <ul>
* <li>--list-modules</li>
* <li>--list-classpath</li>
* <li>--list-config</li>
* <li>--version</li>
* <li>--help</li>
* <li>--dry-run</li>
* <li>--exec</li>
* <li>--stop</li>
* <li>(or normal startup)</li>
* </ul>
* <li>Present Optional Informational Options</li>
* <li>Normal Startup</li>
* </li>
* </ol>
*/

View File

@ -26,6 +26,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
@ -206,14 +207,21 @@ public class StartArgs
System.out.println(" (no properties specified)");
return;
}
List<String> sortedKeys = new ArrayList<>();
@SuppressWarnings("unchecked")
Enumeration<String> keyEnum = (Enumeration<String>)properties.propertyNames();
while (keyEnum.hasMoreElements())
{
String name = keyEnum.nextElement();
String value = properties.getProperty(name);
System.out.printf(" %s = %s%n",name,value);
sortedKeys.add(keyEnum.nextElement());
}
Collections.sort(sortedKeys);
for(String key: sortedKeys)
{
String value = properties.getProperty(key);
System.out.printf(" %s = %s%n",key,value);
}
}
@ -228,8 +236,12 @@ public class StartArgs
System.out.println(" (no system properties specified)");
return;
}
List<String> sortedKeys = new ArrayList<>();
sortedKeys.addAll(systemPropertyKeys);
Collections.sort(sortedKeys);
for (String key : systemPropertyKeys)
for (String key : sortedKeys)
{
String value = System.getProperty(key);
System.out.printf(" %s = %s%n",key,value);

View File

@ -2,20 +2,20 @@ Usage: java -jar start.jar [options...] [properties...] [configs...]
The start.jar builds a classpath and executes a main java class with
a classloader built from that classpath. By default the start.jar
mechanism is configured to start the jetty server, but it can be
mechanism is configured to start the jetty server, but it can be
configured to start any java main class.
Command Line Options:
---------------------
--help This help / usage information.
--version Print the version information for Jetty and
dependent jars, then exit.
--list-classpath Print the classpath information that will be used to start
Jetty
--list-config List the resolved configuration that will be used to
start Jetty.
Output includes:
@ -25,25 +25,25 @@ Command Line Options:
o Properties
o Server Classpath
o Server XML Configuration
--dry-run Print the command line that the start.jar generates,
then exit. This may be used to generate command lines
when the start.ini includes -X or -D arguments.
--exec Run the generated command line (see --dry-run) in
--exec Run the generated command line (see --dry-run) in
a sub process. This can be used when start.ini
contains -X or -D arguments, but creates an extra
JVM instance.
Debug and Start Logging:
------------------------
--debug Enable debug output of the startup procedure.
Note: this does not setup debug for Jetty itself.
If you want debug for Jetty, configure your logging
(See bellow)
If you want debug for Jetty, configure your logging.
http://www.eclipse.org/jetty/documentation/
--start-log-file=<filename>
A filename, relative to ${jetty.base}, where all startup
output will be sent. This is useful for capturing startup
@ -56,29 +56,29 @@ Module Management:
--list-modules List all modules defined by the system.
Looking for module files in ${jetty.base}/modules/*.mod and
then ${jetty.home}/modules/*.mod
then ${jetty.home}/modules/*.mod
Will also list enabled state based on information
present on ..
o The command line
o The ${jetty.base}/start.ini
o The ${jetty.base}/start.d/*.ini files
--module=<modulename>(,<modulename>)*
Temporarily enable a module from the command line.
Note: this can also be used in the ${jetty.base}/start.ini
or ${jetty.base}/start.d/*.ini files.
--add-to-start=<modulename>(,<modulename>)*
Enable a module by appending lines to the
${jetty.base}/start.ini file.
Enable a module by appending lines to the
${jetty.base}/start.ini file.
Lines that are added come from the ini template that
the module itself maintains.
Transitive module dependencies are followed and all
modules that the specified module depends on are also
enabled in the ${jetty.base}/start.ini using the same
techniques.
Note: not all modules have ini templates.
Note: not all modules have ini templates.
--add-to-startd=<modulename>(,<modulename>)*
Enable a module via creation of an ini file in the
${jetty.base}/start.d/ directory.
@ -86,7 +86,7 @@ Module Management:
Transitive module dependencies are followed and all
modules that the specified module depends on are also
enabled via their own ini files in the same directory.
Note: not all modules have ini templates.
Note: not all modules have ini templates.
--write-module-graph=<filename>
Create a graphviz *.dot file of the module graph as it
@ -97,7 +97,7 @@ Module Management:
Startup / Shutdown Command Line:
--------------------------------
--stop Send a stop signal to the running Jetty instance.
The server must have been started with a STOP.PORT=<port>
property set and the stop command must have the same property.
@ -107,23 +107,23 @@ Properties:
STOP.PORT=[number]
The port to use to stop the running Jetty server.
Required along with STOP.KEY if you want to use the --stop option above.
STOP.KEY=[alphanumeric]
The passphrase defined to stop the server.
Requried along with STOP.PORT if you want to use the --stop option above.
STOP.WAIT=[number]
The time (in seconds) to wait for confirmation that the running
Jetty server has stopped. If not specified, the stopper will wait
The time (in seconds) to wait for confirmation that the running
Jetty server has stopped. If not specified, the stopper will wait
indefinitely. Use in conjunction with the --stop option.
Advanced Commands:
------------------
--download=<http-uri>:<location>
Advanced usage, If the file does not exist at the given
location, download it from the given http URI.
Note: location is always relative to ${jetty.base}
Note: location is always relative to ${jetty.base}
--lib=<classpath>
Add arbitrary classpath entries to the the server classpath.
@ -134,17 +134,17 @@ System Properties:
These are set with a command line like "java -Dname=value ..." and are
accessible via the java.lang.System#getProperty(String) API.
Some key system properties are:
org.eclipse.jetty.util.log.class=[class]
org.eclipse.jetty.util.log.class=[class]
A Low Level Jetty Logger Implementation to use
(default: org.eclipse.jetty.util.log.Slf4jLog)
[name|hierarchy].LEVEL=[loglevel]
Change loglevel for the stderr and javautil Loggers. Slf4j
and other loggers must be separately configured for debug.
For example: Dorg.eclipse.jetty.LEVEL=DEBUG
(default: INFO)
org.eclipse.jetty.util.log.IGNORED=[boolean]
Ignored exceptions are logged, independent of DEBUG settings
(default: false)
@ -152,7 +152,7 @@ System Properties:
org.eclipse.jetty.util.log.SOURCE=[boolean]
The source location of logs is logged in the stderr Logger.
(default: false)
com.sun.management.jmxremote
Enable remote JMX management in Sun JVMS.
@ -161,22 +161,22 @@ Properties:
-----------
These are set with a command line like "java -jar start.jar name=value"
and only affect the start mechanism. Some of these are defined in the
and only affect the start mechanism. Some of these are defined in the
default start.config and will not be available if another configuration
file is used. NOTE: Not all properties are listed here:
jetty.home=[directory]
Set the home directory of the jetty distribution.
jetty.base=[directory]
Set the jetty configuration directory. This is where the etc, webapps and start
files will be looked for. If not found in jetty.base, they are looked for in
files will be looked for. If not found in jetty.base, they are looked for in
jetty.home.
Defaults:
---------
A ${jetty.base}/start.ini file and/or ${jetty.base|/start.d/*.ini files may be
used to specify default arguments to start.jar. In case of a conflict between
A ${jetty.base}/start.ini file and/or ${jetty.base|/start.d/*.ini files may be
used to specify default arguments to start.jar. In case of a conflict between
the command line, and ini files, the command line will win.

View File

@ -1,134 +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.util;
import java.util.concurrent.Executor;
public abstract class ExecutorCallback implements Callback
{
private final ForkInvoker<Void> _invoker;
private final Executor _executor;
private final Runnable _onComplete=new Runnable()
{
@Override
public void run()
{
onCompleted();
}
};
public ExecutorCallback(Executor executor)
{
this(executor, 4);
}
public ExecutorCallback(Executor executor, int maxRecursion)
{
_executor = executor;
_invoker = maxRecursion>0?new ExecutorCallbackInvoker(maxRecursion):null;
if (_executor==null)
throw new IllegalArgumentException();
}
@Override
public void succeeded()
{
// Should we execute?
if (_invoker==null)
{
_executor.execute(_onComplete);
}
else if (alwaysDispatchCompletion())
{
_invoker.fork(null);
}
else
{
_invoker.invoke(null);
}
}
protected abstract void onCompleted();
@Override
public void failed(final Throwable x)
{
// Always execute failure
Runnable runnable = new Runnable()
{
@Override
public void run()
{
onFailed(x);
}
@Override
public String toString()
{
return String.format("ExecutorCallback@%x{%s}", hashCode(), x);
}
};
if (_executor == null)
new Thread(runnable).start();
else
_executor.execute(runnable);
}
protected void onFailed(Throwable x)
{
}
protected boolean alwaysDispatchCompletion()
{
return _executor != null;
}
@Override
public String toString()
{
return String.format("%s@%x", getClass(), hashCode());
}
private class ExecutorCallbackInvoker extends ForkInvoker<Void> implements Runnable
{
private ExecutorCallbackInvoker(int maxInvocations)
{
super(maxInvocations);
}
@Override
public void fork(Void arg)
{
_executor.execute(this);
}
@Override
public void call(Void arg)
{
onCompleted();
}
@Override
public void run()
{
onCompleted();
}
}
}

View File

@ -0,0 +1,130 @@
//
// ========================================================================
// 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.util.resource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.channels.ReadableByteChannel;
/**
* EmptyResource
*
* Represents a resource that does does not refer to any file, url, jar etc.
*/
public class EmptyResource extends Resource
{
public static final Resource INSTANCE = new EmptyResource();
private EmptyResource()
{
}
@Override
public boolean isContainedIn(Resource r) throws MalformedURLException
{
return false;
}
@Override
public void close()
{
}
@Override
public boolean exists()
{
return false;
}
@Override
public boolean isDirectory()
{
return false;
}
@Override
public long lastModified()
{
return 0;
}
@Override
public long length()
{
return 0;
}
@Override
public URL getURL()
{
return null;
}
@Override
public File getFile() throws IOException
{
return null;
}
@Override
public String getName()
{
return null;
}
@Override
public InputStream getInputStream() throws IOException
{
return null;
}
@Override
public ReadableByteChannel getReadableByteChannel() throws IOException
{
return null;
}
@Override
public boolean delete() throws SecurityException
{
return false;
}
@Override
public boolean renameTo(Resource dest) throws SecurityException
{
return false;
}
@Override
public String[] list()
{
return null;
}
@Override
public Resource addPath(String path) throws IOException, MalformedURLException
{
return null;
}
}

View File

@ -32,6 +32,8 @@ import java.nio.channels.ReadableByteChannel;
import java.nio.file.StandardOpenOption;
import java.security.Permission;
import javax.management.RuntimeErrorException;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
@ -54,7 +56,7 @@ public class FileResource extends Resource
/* ------------------------------------------------------------ */
private final File _file;
private final String _uri;
private final URL _alias;
private final URI _alias;
/* -------------------------------------------------------- */
public FileResource(URL url)
@ -133,7 +135,7 @@ public class FileResource extends Resource
}
/* -------------------------------------------------------- */
private static URL checkAlias(File file)
private static URI checkAlias(File file)
{
try
{
@ -143,14 +145,24 @@ public class FileResource extends Resource
if (!abs.equals(can))
{
LOG.debug("ALIAS abs={} can={}",abs,can);
return new File(can).toURI().toURL();
return new File(can).toURI();
}
}
catch(IOException e)
{
LOG.warn(e);
LOG.warn("bad alias for {}: {}",file,e.toString());
LOG.debug(e);
try
{
return new URI("http://eclipse.org/bad/canonical/alias");
}
catch(Exception e2)
{
LOG.ignore(e2);
throw new RuntimeException(e);
}
}
return null;
}
@ -193,7 +205,7 @@ public class FileResource extends Resource
/* ------------------------------------------------------------ */
@Override
public URL getAlias()
public URI getAlias()
{
return _alias;
}
@ -389,6 +401,12 @@ public class FileResource extends Resource
throw new IllegalStateException(e);
}
}
@Override
public URI getURI()
{
return _file.toURI();
}
@Override
public String toString()

View File

@ -29,7 +29,9 @@ import java.net.URI;
import java.net.URL;
import java.nio.channels.ReadableByteChannel;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import org.eclipse.jetty.util.B64Code;
@ -471,7 +473,7 @@ public abstract class Resource implements ResourceFactory, Closeable
/**
* @return The canonical Alias of this resource or null if none.
*/
public URL getAlias()
public URI getAlias()
{
return null;
}
@ -662,6 +664,34 @@ public abstract class Resource implements ResourceFactory, Closeable
}
}
/* ------------------------------------------------------------ */
public Collection<Resource> getAllResources()
{
try
{
ArrayList<Resource> deep=new ArrayList<>();
{
String[] list=list();
if (list!=null)
{
for (String i:list)
{
Resource r=addPath(i);
if (r.isDirectory())
deep.addAll(r.getAllResources());
else
deep.add(r);
}
}
}
return deep;
}
catch(Exception e)
{
throw new IllegalStateException(e);
}
}
/* ------------------------------------------------------------ */
/** Generate a properly encoded URL from a {@link File} instance.
* @param file Target file.

View File

@ -30,9 +30,9 @@ import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipFile;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
@ -297,10 +297,20 @@ public class ResourceTest
assertTrue(entries.contains("numbers"));
IO.delete(extract);
}
/* ------------------------------------------------------------ */
@Test
public void testJarFileGetAllResoures()
throws Exception
{
String s = "jar:"+__userURL+"TestData/test.zip!/subdir/";
Resource r = Resource.newResource(s);
Collection<Resource> deep=r.getAllResources();
assertEquals(4, deep.size());
}
@Test
public void testJarFileIsContainedIn ()
throws Exception

View File

@ -168,11 +168,11 @@
</init-param>
<init-param>
<param-name>gzip</param-name>
<param-value>true</param-value>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>etags</param-name>
<param-value>true</param-value>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>useFileMappedBuffer</param-name>

View File

@ -19,7 +19,7 @@
package org.eclipse.jetty.webapp;
import java.util.List;
import java.util.Map;
import org.eclipse.jetty.util.resource.Resource;
@ -70,18 +70,18 @@ public class FragmentConfiguration extends AbstractConfiguration
public void findWebFragments (final WebAppContext context, final MetaData metaData) throws Exception
{
@SuppressWarnings("unchecked")
List<Resource> frags = (List<Resource>)context.getAttribute(FRAGMENT_RESOURCES);
Map<Resource, Resource> frags = (Map<Resource,Resource>)context.getAttribute(FRAGMENT_RESOURCES);
if (frags!=null)
{
for (Resource frag : frags)
for (Resource key : frags.keySet())
{
if (frag.isDirectory()) //tolerate the case where the library is a directory, not a jar. useful for OSGi for example
if (key.isDirectory()) //tolerate the case where the library is a directory, not a jar. useful for OSGi for example
{
metaData.addFragment(frag, Resource.newResource(frag.getURL()+"/META-INF/web-fragment.xml"));
metaData.addFragment(key, frags.get(key));
}
else //the standard case: a jar most likely inside WEB-INF/lib
{
metaData.addFragment(frag, Resource.newResource("jar:"+frag.getURL()+"!/META-INF/web-fragment.xml"));
metaData.addFragment(key, frags.get(key));
}
}
}

View File

@ -18,6 +18,12 @@
package org.eclipse.jetty.webapp;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.channels.ReadableByteChannel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -28,6 +34,8 @@ import javax.servlet.ServletContext;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.EmptyResource;
import org.eclipse.jetty.util.resource.JarResource;
import org.eclipse.jetty.util.resource.Resource;
@ -43,18 +51,18 @@ public class MetaData
private static final Logger LOG = Log.getLogger(MetaData.class);
public static final String ORDERED_LIBS = "javax.servlet.context.orderedLibs";
public static final Resource NON_FRAG_RESOURCE = EmptyResource.INSTANCE;
protected Map<String, OriginInfo> _origins =new HashMap<String,OriginInfo>();
protected WebDescriptor _webDefaultsRoot;
protected WebDescriptor _webXmlRoot;
protected final List<WebDescriptor> _webOverrideRoots=new ArrayList<WebDescriptor>();
protected boolean _metaDataComplete;
protected final List<DiscoveredAnnotation> _annotations = new ArrayList<DiscoveredAnnotation>();
protected boolean _metaDataComplete;
protected final List<DescriptorProcessor> _descriptorProcessors = new ArrayList<DescriptorProcessor>();
protected final List<FragmentDescriptor> _webFragmentRoots = new ArrayList<FragmentDescriptor>();
protected final Map<String,FragmentDescriptor> _webFragmentNameMap = new HashMap<String,FragmentDescriptor>();
protected final Map<Resource, FragmentDescriptor> _webFragmentResourceMap = new HashMap<Resource, FragmentDescriptor>();
protected final Map<Resource, List<DiscoveredAnnotation>> _webFragmentAnnotations = new HashMap<Resource, List<DiscoveredAnnotation>>();
protected final Map<Resource, List<DiscoveredAnnotation>> _annotations = new HashMap<Resource, List<DiscoveredAnnotation>>();
protected final List<Resource> _webInfClasses = new ArrayList<Resource>();
protected final List<Resource> _webInfJars = new ArrayList<Resource>();
protected final List<Resource> _orderedWebInfJars = new ArrayList<Resource>();
@ -135,7 +143,7 @@ public class MetaData
_webFragmentRoots.clear();
_webFragmentNameMap.clear();
_webFragmentResourceMap.clear();
_webFragmentAnnotations.clear();
_annotations.clear();
_webInfJars.clear();
_orderedWebInfJars.clear();
_orderedContainerResources.clear();
@ -276,45 +284,47 @@ public class MetaData
return;
for (DiscoveredAnnotation a:annotations)
{
Resource r = a.getResource();
if (r == null || !_webInfJars.contains(r))
_annotations.add(a);
else
addDiscoveredAnnotation(a.getResource(), a);
addDiscoveredAnnotation(a);
}
}
public void addDiscoveredAnnotation(Resource resource, DiscoveredAnnotation annotation)
{
List<DiscoveredAnnotation> list = _webFragmentAnnotations.get(resource);
if (list == null)
{
list = new ArrayList<DiscoveredAnnotation>();
_webFragmentAnnotations.put(resource, list);
}
list.add(annotation);
}
public void addDiscoveredAnnotations(Resource resource, List<DiscoveredAnnotation> annotations)
/**
* Add an annotation that has been discovered on a class, method or field within a resource
* eg a jar or dir.
*
* This method is synchronized as it is anticipated that it may be called by many threads
* during the annotation scanning phase.
*
* @param annotation
*/
public synchronized void addDiscoveredAnnotation (DiscoveredAnnotation annotation)
{
List<DiscoveredAnnotation> list = _webFragmentAnnotations.get(resource);
if (annotation == null)
return;
//if no resource associated with an annotation or the resource is not one of the WEB-INF/lib jars,
//map it to empty resource
Resource resource = annotation.getResource();
if (resource == null || !_webInfJars.contains(resource))
resource = EmptyResource.INSTANCE;
List<DiscoveredAnnotation> list = _annotations.get(resource);
if (list == null)
{
list = new ArrayList<DiscoveredAnnotation>();
_webFragmentAnnotations.put(resource, list);
_annotations.put(resource, list);
}
list.addAll(annotations);
list.add(annotation);
}
public void addDescriptorProcessor(DescriptorProcessor p)
{
_descriptorProcessors.add(p);
}
public void orderFragments ()
{
//if we have already ordered them don't do it again
@ -373,13 +383,20 @@ public class MetaData
}
}
for (DiscoveredAnnotation a:_annotations)
//get an apply the annotations that are not associated with a fragment (and hence for
//which no ordering applies
List<DiscoveredAnnotation> nonFragAnnotations = _annotations.get(NON_FRAG_RESOURCE);
if (nonFragAnnotations != null)
{
LOG.debug("apply {}",a);
a.apply();
for (DiscoveredAnnotation a:nonFragAnnotations)
{
LOG.debug("apply {}",a);
a.apply();
}
}
//apply the annotations that are associated with a fragment, according to the
//established ordering
List<Resource> resources = getOrderedWebInfJars();
for (Resource r:resources)
{
@ -393,7 +410,7 @@ public class MetaData
}
}
List<DiscoveredAnnotation> fragAnnotations = _webFragmentAnnotations.get(r);
List<DiscoveredAnnotation> fragAnnotations = _annotations.get(r);
if (fragAnnotations != null)
{
for (DiscoveredAnnotation a:fragAnnotations)

View File

@ -21,8 +21,13 @@ package org.eclipse.jetty.webapp;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.jar.JarEntry;
import org.eclipse.jetty.util.log.Log;
@ -45,57 +50,51 @@ public class MetaInfConfiguration extends AbstractConfiguration
public static final String METAINF_TLDS = TagLibConfiguration.TLD_RESOURCES;
public static final String METAINF_FRAGMENTS = FragmentConfiguration.FRAGMENT_RESOURCES;
public static final String METAINF_RESOURCES = WebInfConfiguration.RESOURCE_URLS;
public static final String METAINF_RESOURCES = WebInfConfiguration.RESOURCE_DIRS;
@Override
public void preConfigure(final WebAppContext context) throws Exception
{
//Merge all container and webinf lib jars to look for META-INF resources
//Merge all container and webinf lib jars to look for META-INF resources
ArrayList<Resource> jars = new ArrayList<Resource>();
jars.addAll(context.getMetaData().getContainerResources());
jars.addAll(context.getMetaData().getWebInfJars());
JarScanner scanner = new JarScanner()
{
public void processEntry(URI jarUri, JarEntry entry)
{
try
{
MetaInfConfiguration.this.processEntry(context,jarUri,entry);
}
catch (Exception e)
{
LOG.warn("Problem processing jar entry " + entry, e);
}
}
};
//Scan jars for META-INF information
if (jars != null)
{
URI[] uris = new URI[jars.size()];
int i=0;
for (Resource r : jars)
{
uris[i++] = r.getURI();
URI uri = r.getURI();
Resource fragXml = Resource.newResource("jar:"+uri+"!/META-INF/web-fragment.xml");
if (fragXml.exists())
{
//add mapping for resource->fragment
Map<Resource, Resource> fragments = (Map<Resource,Resource>)context.getAttribute(METAINF_FRAGMENTS);
if (fragments == null)
{
fragments = new HashMap<Resource, Resource>();
context.setAttribute(METAINF_FRAGMENTS, fragments);
}
fragments.put(r, fragXml);
}
Resource resourcesDir = Resource.newResource("jar:"+uri+"!/META-INF/resources");
if (resourcesDir.exists())
{
//add resources dir
Set<Resource> dirs = (Set<Resource>)context.getAttribute(METAINF_RESOURCES);
if (dirs == null)
{
dirs = new HashSet<Resource>();
context.setAttribute(METAINF_RESOURCES, dirs);
}
dirs.add(resourcesDir);
}
}
scanner.scan(null, uris, true);
}
}
@Override
public void configure(WebAppContext context) throws Exception
{
}
@Override
public void deconfigure(WebAppContext context) throws Exception
{
}
@Override
public void postConfigure(WebAppContext context) throws Exception
{
@ -103,50 +102,4 @@ public class MetaInfConfiguration extends AbstractConfiguration
context.setAttribute(METAINF_RESOURCES, null);
context.setAttribute(METAINF_TLDS, null);
}
public void addResource (WebAppContext context, String attribute, Resource jar)
{
@SuppressWarnings("unchecked")
List<Resource> list = (List<Resource>)context.getAttribute(attribute);
if (list==null)
{
list=new ArrayList<Resource>();
context.setAttribute(attribute,list);
}
if (!list.contains(jar))
list.add(jar);
}
protected void processEntry(WebAppContext context, URI jarUri, JarEntry entry)
{
String name = entry.getName();
if (!name.startsWith("META-INF/"))
return;
try
{
if (name.equals("META-INF/web-fragment.xml") && context.isConfigurationDiscovered())
{
addResource(context,METAINF_FRAGMENTS,Resource.newResource(jarUri));
}
else if (name.equals("META-INF/resources/") && context.isConfigurationDiscovered())
{
addResource(context,METAINF_RESOURCES,Resource.newResource("jar:"+jarUri+"!/META-INF/resources"));
}
else
{
String lcname = name.toLowerCase(Locale.ENGLISH);
if (lcname.endsWith(".tld"))
{
addResource(context,METAINF_TLDS,Resource.newResource("jar:"+jarUri+"!/"+name));
}
}
}
catch(Exception e)
{
context.getServletContext().log(jarUri+"!/"+name,e);
}
}
}

View File

@ -27,7 +27,9 @@ import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import org.eclipse.jetty.server.Connector;
@ -54,7 +56,7 @@ public class WebInfConfiguration extends AbstractConfiguration
* If set, to a list of URLs, these resources are added to the context
* resource base as a resource collection.
*/
public static final String RESOURCE_URLS = "org.eclipse.jetty.resources";
public static final String RESOURCE_DIRS = "org.eclipse.jetty.resources";
protected Resource _preUnpackBaseResource;
@ -140,7 +142,7 @@ public class WebInfConfiguration extends AbstractConfiguration
}
}
webInfJarNameMatcher.match(webInfPattern, uris, true); //null is inclusive, no pattern == all jars match
//No pattern to appy to classes, just add to metadata
context.getMetaData().setWebInfClassesDirs(findClassDirs(context));
}
@ -175,7 +177,7 @@ public class WebInfConfiguration extends AbstractConfiguration
// Look for extra resource
@SuppressWarnings("unchecked")
List<Resource> resources = (List<Resource>)context.getAttribute(RESOURCE_URLS);
Set<Resource> resources = (Set<Resource>)context.getAttribute(RESOURCE_DIRS);
if (resources!=null)
{
Resource[] collection=new Resource[resources.size()+1];

View File

@ -26,6 +26,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import javax.websocket.ClientEndpoint;
@ -71,6 +72,11 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
private WebSocketClient client;
public ClientContainer()
{
this(null);
}
public ClientContainer(Executor executor)
{
endpointClientMetadataCache = new ConcurrentHashMap<>();
decoderFactory = new DecoderFactory(PrimitiveDecoderMetadataSet.INSTANCE);
@ -80,7 +86,7 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
decoderFactory.init(empty);
encoderFactory.init(empty);
client = new WebSocketClient();
client = new WebSocketClient(executor);
client.setEventDriverFactory(new JsrEventDriverFactory(client.getPolicy()));
client.setSessionFactory(new JsrSessionFactory(this));
addBean(client);

View File

@ -1,27 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- =========================================================== -->
<!-- Add javax.websocket Configuring classes to all webapps for this Server -->
<!-- =========================================================== -->
<Call class="org.eclipse.jetty.webapp.Configuration$ClassList" name="setServerDefault">
<Arg><Ref refid="Server" /></Arg>
<Call name="addBefore">
<Arg name="beforeClass">org.eclipse.jetty.annotations.AnnotationConfiguration</Arg>
<Arg>
<Array type="String">
<Item>org.eclipse.jetty.websocket.jsr356.server.WebSocketConfiguration</Item>
</Array>
</Arg>
</Call>
</Call>
<!-- Should a Websocket container be initialized for each context? -->
<!-- Can be overridden by context attribute -->
<Call name="setAttribute">
<Arg>org.eclipse.jetty.websocket.jsr356</Arg>
<Arg type="Boolean"><Property name="org.eclipse.jetty.websocket.jsr356" default="true"/></Arg>
</Call>
</Configure>

View File

@ -4,17 +4,10 @@
[depend]
# WebSocket needs Annotations feature
server
annotations
[lib]
# WebSocket needs websocket jars (as defined in start.config)
lib/websocket/*.jar
[xml]
# WebSocket needs websocket configuration
etc/jetty-websockets.xml
[ini-template]
# Start Websocket containter for all contexts
org.eclipse.jetty.websocket.jsr356=true

View File

@ -18,6 +18,8 @@
package org.eclipse.jetty.websocket.jsr356.server;
import java.util.concurrent.Executor;
import javax.websocket.DeploymentException;
import javax.websocket.Endpoint;
import javax.websocket.server.ServerEndpoint;
@ -42,9 +44,9 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
private final MappedWebSocketCreator mappedCreator;
private final WebSocketServerFactory webSocketServerFactory;
public ServerContainer(MappedWebSocketCreator creator, WebSocketServerFactory factory)
public ServerContainer(MappedWebSocketCreator creator, WebSocketServerFactory factory, Executor executor)
{
super();
super(executor);
this.mappedCreator = creator;
this.webSocketServerFactory = factory;
EventDriverFactory eventDriverFactory = this.webSocketServerFactory.getEventDriverFactory();

View File

@ -1,122 +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.websocket.jsr356.server;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.AbstractConfiguration;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.websocket.jsr356.server.deploy.DiscoveredEndpoints;
import org.eclipse.jetty.websocket.jsr356.server.deploy.ServerEndpointAnnotationHandler;
import org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter;
/**
* WebSocket Server Configuration component.
* <p>
* This configuration will configure a context for JSR356 Websockets.
* <p>
* It is possible to disable specific contexts with an attribute <code>"org.eclipse.jetty.websocket.jsr356"</code> (set to <code>"false"</code>)
* <p>
* This attribute may be set on an individual context, or on the server to affect all deployed contexts.
*/
public class WebSocketConfiguration extends AbstractConfiguration
{
public static final String ENABLE = "org.eclipse.jetty.websocket.jsr356";
private static final Logger LOG = Log.getLogger(WebSocketConfiguration.class);
/**
* Create a ServerContainer properly, useful for embedded application use.
* <p>
* Notably, the cometd3 project uses this.
*
* @param context
* the context to enable javax.websocket support filters on
* @return the ServerContainer that was created
*/
public static ServerContainer configureContext(ServletContextHandler context)
{
LOG.debug("Configure javax.websocket for WebApp {}",context);
WebSocketUpgradeFilter filter = WebSocketUpgradeFilter.configureContext(context);
// Create the Jetty ServerContainer implementation
ServerContainer jettyContainer = new ServerContainer(filter,filter.getFactory());
context.addBean(jettyContainer);
// Store a reference to the ServerContainer per javax.websocket spec 1.0 final section 6.4 Programmatic Server Deployment
context.setAttribute(javax.websocket.server.ServerContainer.class.getName(),jettyContainer);
// Store reference to DiscoveredEndpoints
context.setAttribute(DiscoveredEndpoints.class.getName(),new DiscoveredEndpoints());
return jettyContainer;
}
public static boolean isJSR356Context(WebAppContext context)
{
Object enable = context.getAttribute(ENABLE);
if (enable instanceof Boolean)
{
return ((Boolean)enable).booleanValue();
}
enable = context.getServer().getAttribute(ENABLE);
if (enable instanceof Boolean)
{
return ((Boolean)enable).booleanValue();
}
return true;
}
@Override
public void configure(WebAppContext context) throws Exception
{
if (isJSR356Context(context))
{
WebSocketConfiguration.configureContext(context);
}
else
{
LOG.debug("JSR-356 support disabled for WebApp {}",context);
}
}
@Override
public void preConfigure(WebAppContext context) throws Exception
{
if (isJSR356Context(context))
{
boolean scanningAdded = false;
// Add the annotation scanning handlers (if annotation scanning enabled)
for (Configuration config : context.getConfigurations())
{
if (config instanceof AnnotationConfiguration)
{
AnnotationConfiguration annocfg = (AnnotationConfiguration)config;
annocfg.addDiscoverableAnnotationHandler(new ServerEndpointAnnotationHandler(context));
scanningAdded = true;
}
}
LOG.debug("@ServerEndpoint scanning added: {}",scanningAdded);
}
}
}

View File

@ -1,158 +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.websocket.jsr356.server.deploy;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
import javax.websocket.Endpoint;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* Tracking for Discovered Endpoints.
* <p>
* This is a collection of endpoints, grouped by type (by Annotation or by extending Endpoint). Along with some better error messages for conflicting endpoints.
*/
public class DiscoveredEndpoints
{
private static class LocatedClass
{
private Class<?> clazz;
private URI location;
public LocatedClass(Class<?> clazz)
{
this.clazz = clazz;
this.location = getArchiveURI(clazz);
}
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("LocatedClass[");
builder.append(clazz.getName());
builder.append("]");
return builder.toString();
}
}
private static final Logger LOG = Log.getLogger(DiscoveredEndpoints.class);
public static URI getArchiveURI(Class<?> clazz)
{
String resourceName = clazz.getName().replace('.','/') + ".class";
URL classUrl = clazz.getClassLoader().getResource(resourceName);
if (classUrl == null)
{
// is this even possible at this point?
return null;
}
try
{
URI uri = classUrl.toURI();
String scheme = uri.getScheme();
if (scheme.equalsIgnoreCase("jar"))
{
String ssp = uri.getSchemeSpecificPart();
int idx = ssp.indexOf("!/");
if (idx >= 0)
{
ssp = ssp.substring(0,idx);
}
return URI.create(ssp);
}
}
catch (URISyntaxException e)
{
LOG.warn("Class reference not a valid URI? " + classUrl,e);
}
return null;
}
private Set<LocatedClass> extendedEndpoints;
private Set<LocatedClass> annotatedEndpoints;
public DiscoveredEndpoints()
{
extendedEndpoints = new HashSet<>();
annotatedEndpoints = new HashSet<>();
}
public void addAnnotatedEndpoint(Class<?> endpoint)
{
this.annotatedEndpoints.add(new LocatedClass(endpoint));
}
public void addExtendedEndpoint(Class<? extends Endpoint> endpoint)
{
this.extendedEndpoints.add(new LocatedClass(endpoint));
}
public Set<Class<?>> getAnnotatedEndpoints()
{
Set<Class<?>> endpoints = new HashSet<>();
for (LocatedClass lc : annotatedEndpoints)
{
endpoints.add(lc.clazz);
}
return endpoints;
}
public void getArchiveSpecificAnnnotatedEndpoints(URI archiveURI, Set<Class<?>> archiveSpecificEndpoints)
{
for (LocatedClass lc : annotatedEndpoints)
{
if ((archiveURI == null) || lc.location.getPath().equals(archiveURI.getPath()))
{
archiveSpecificEndpoints.add(lc.clazz);
}
}
}
@SuppressWarnings("unchecked")
public void getArchiveSpecificExtendedEndpoints(URI archiveURI, Set<Class<? extends Endpoint>> archiveSpecificEndpoints)
{
for (LocatedClass lc : extendedEndpoints)
{
if ((archiveURI == null) || (lc.location.getPath().equals(archiveURI.getPath()) && Endpoint.class.isAssignableFrom(lc.clazz)))
{
archiveSpecificEndpoints.add((Class<? extends Endpoint>)lc.clazz);
}
}
}
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("DiscoveredEndpoints [extendedEndpoints=");
builder.append(extendedEndpoints);
builder.append(", annotatedEndpoints=");
builder.append(annotatedEndpoints);
builder.append("]");
return builder.toString();
}
}

View File

@ -1,162 +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.websocket.jsr356.server.deploy;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.HandlesTypes;
import javax.websocket.DeploymentException;
import javax.websocket.Endpoint;
import javax.websocket.server.ServerApplicationConfig;
import javax.websocket.server.ServerEndpointConfig;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
import org.eclipse.jetty.websocket.jsr356.server.WebSocketConfiguration;
import org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter;
@HandlesTypes(
{ ServerApplicationConfig.class, Endpoint.class })
public class ServerApplicationConfigListener implements ServletContainerInitializer
{
private static final Logger LOG = Log.getLogger(ServerApplicationConfigListener.class);
@Override
public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException
{
if (!WebSocketConfiguration.isJSR356Context(WebAppContext.getCurrentWebAppContext()))
return;
WebSocketUpgradeFilter filter = (WebSocketUpgradeFilter)ctx.getAttribute(WebSocketUpgradeFilter.class.getName());
if (filter == null)
{
LOG.warn("Required attribute not available: " + WebSocketUpgradeFilter.class.getName());
return;
}
DiscoveredEndpoints discovered = (DiscoveredEndpoints)ctx.getAttribute(DiscoveredEndpoints.class.getName());
if (discovered == null)
{
LOG.warn("Required attribute not available: " + DiscoveredEndpoints.class.getName());
return;
}
LOG.debug("Found {} classes",c.size());
LOG.debug("Discovered: {}",discovered);
// First add all of the Endpoints
addEndpoints(c,discovered);
// Now process the ServerApplicationConfig entries
ServerContainer container = (ServerContainer)ctx.getAttribute(javax.websocket.server.ServerContainer.class.getName());
Set<Class<? extends Endpoint>> archiveSpecificExtendEndpoints = new HashSet<>();
Set<Class<?>> archiveSpecificAnnotatedEndpoints = new HashSet<>();
List<Class<? extends ServerApplicationConfig>> serverAppConfigs = filterServerApplicationConfigs(c);
if(serverAppConfigs.size() >= 1) {
for (Class<? extends ServerApplicationConfig> clazz : filterServerApplicationConfigs(c))
{
LOG.debug("Found ServerApplicationConfig: {}",clazz);
try
{
ServerApplicationConfig config = (ServerApplicationConfig)clazz.newInstance();
URI archiveURI = DiscoveredEndpoints.getArchiveURI(clazz);
archiveSpecificExtendEndpoints.clear();
archiveSpecificAnnotatedEndpoints.clear();
discovered.getArchiveSpecificExtendedEndpoints(archiveURI,archiveSpecificExtendEndpoints);
discovered.getArchiveSpecificAnnnotatedEndpoints(archiveURI,archiveSpecificAnnotatedEndpoints);
Set<ServerEndpointConfig> seconfigs = config.getEndpointConfigs(archiveSpecificExtendEndpoints);
if (seconfigs != null)
{
for (ServerEndpointConfig sec : seconfigs)
{
container.addEndpoint(sec);
}
}
Set<Class<?>> annotatedClasses = config.getAnnotatedEndpointClasses(archiveSpecificAnnotatedEndpoints);
if (annotatedClasses != null)
{
for (Class<?> annotatedClass : annotatedClasses)
{
container.addEndpoint(annotatedClass);
}
}
}
catch (InstantiationException | IllegalAccessException e)
{
throw new ServletException("Unable to instantiate: " + clazz.getName(),e);
}
catch (DeploymentException e)
{
throw new ServletException(e);
}
}
} else {
// Default behavior (no ServerApplicationConfigs found)
// Note: it is impossible to determine path of "extends Endpoint" discovered classes
for(Class<?> annotatedClass: discovered.getAnnotatedEndpoints())
{
try
{
container.addEndpoint(annotatedClass);
}
catch (DeploymentException e)
{
throw new ServletException(e);
}
}
}
}
@SuppressWarnings("unchecked")
private List<Class<? extends ServerApplicationConfig>> filterServerApplicationConfigs(Set<Class<?>> c)
{
List<Class<? extends ServerApplicationConfig>> configs = new ArrayList<>();
for (Class<?> clazz : c)
{
if (ServerApplicationConfig.class.isAssignableFrom(clazz))
{
configs.add((Class<? extends ServerApplicationConfig>)clazz);
}
}
return configs;
}
@SuppressWarnings("unchecked")
private void addEndpoints(Set<Class<?>> c, DiscoveredEndpoints discovered)
{
for (Class<?> clazz : c)
{
if (Endpoint.class.isAssignableFrom(clazz))
{
discovered.addExtendedEndpoint((Class<? extends Endpoint>)clazz);
}
}
}
}

View File

@ -1,64 +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.websocket.jsr356.server.deploy;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.WebAppContext;
/**
* Once an Annotated Server Endpoint is discovered, add it to the list of
* discovered Annotated Endpoints.
*/
public class ServerEndpointAnnotation extends DiscoveredAnnotation
{
private static final Logger LOG = Log.getLogger(ServerEndpointAnnotation.class);
public ServerEndpointAnnotation(WebAppContext context, String className)
{
super(context,className);
}
public ServerEndpointAnnotation(WebAppContext context, String className, Resource resource)
{
super(context,className,resource);
}
@Override
public void apply()
{
Class<?> clazz = getTargetClass();
if (clazz == null)
{
LOG.warn(_className + " cannot be loaded");
return;
}
DiscoveredEndpoints discovered = (DiscoveredEndpoints)_context.getAttribute(DiscoveredEndpoints.class.getName());
if(discovered == null) {
LOG.warn("Context attribute not found: " + DiscoveredEndpoints.class.getName());
return;
}
discovered.addAnnotatedEndpoint(clazz);
}
}

View File

@ -1,88 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.jsr356.server.deploy;
import java.util.List;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.annotations.AbstractDiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationParser.Value;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.WebAppContext;
/**
* Processing for &#64;{@link ServerEndpoint} annotations during Web App Annotation Scanning
*/
public class ServerEndpointAnnotationHandler extends AbstractDiscoverableAnnotationHandler
{
private static final String ANNOTATION_NAME = "javax.websocket.server.ServerEndpoint";
private static final Logger LOG = Log.getLogger(ServerEndpointAnnotationHandler.class);
public ServerEndpointAnnotationHandler(WebAppContext context)
{
super(context);
}
public ServerEndpointAnnotationHandler(WebAppContext context, List<DiscoveredAnnotation> list)
{
super(context,list);
}
@Override
public String getAnnotationName()
{
return ANNOTATION_NAME;
}
@Override
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotationName,
List<Value> values)
{
if (LOG.isDebugEnabled())
{
LOG.debug("handleClass: {}, {}, {}",className,annotationName,values);
}
if (!ANNOTATION_NAME.equals(annotationName))
{
// Not the one we are interested in
return;
}
ServerEndpointAnnotation annotation = new ServerEndpointAnnotation(_context,className,_resource);
addAnnotation(annotation);
}
@Override
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
List<Value> values)
{
/* @ServerEndpoint annotation not supported for fields */
}
@Override
public void handleMethod(String className, String methodName, int access, String desc, String signature, String[] exceptions, String annotation,
List<Value> values)
{
/* @ServerEndpoint annotation not supported for methods */
}
}

View File

@ -0,0 +1,211 @@
//
// ========================================================================
// 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.websocket.jsr356.server.deploy;
import java.util.HashSet;
import java.util.Set;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.HandlesTypes;
import javax.websocket.DeploymentException;
import javax.websocket.Endpoint;
import javax.websocket.server.ServerApplicationConfig;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.ServerEndpointConfig;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
import org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter;
@HandlesTypes(
{ ServerApplicationConfig.class, ServerEndpoint.class, Endpoint.class })
public class WebSocketServerContainerInitializer implements ServletContainerInitializer
{
public static final String ENABLE_KEY = "org.eclipse.jetty.websocket.jsr356";
private static final Logger LOG = Log.getLogger(WebSocketServerContainerInitializer.class);
public static boolean isJSR356EnabledOnContext(ServletContext context)
{
Object enable = context.getAttribute(ENABLE_KEY);
if (enable instanceof Boolean)
{
return ((Boolean)enable).booleanValue();
}
return true;
}
public static ServerContainer configureContext(ServletContextHandler context)
{
// Create Filter
WebSocketUpgradeFilter filter = WebSocketUpgradeFilter.configureContext(context);
// Store reference to the WebSocketUpgradeFilter
context.setAttribute(WebSocketUpgradeFilter.class.getName(),filter);
// Create the Jetty ServerContainer implementation
ServerContainer jettyContainer = new ServerContainer(filter,filter.getFactory(),context.getServer().getThreadPool());
context.addBean(jettyContainer);
// Store a reference to the ServerContainer per javax.websocket spec 1.0 final section 6.4 Programmatic Server Deployment
context.setAttribute(javax.websocket.server.ServerContainer.class.getName(),jettyContainer);
return jettyContainer;
}
@Override
public void onStartup(Set<Class<?>> c, ServletContext context) throws ServletException
{
if (!isJSR356EnabledOnContext(context))
{
LOG.info("JSR-356 support disabled via attribute on context {} - {}",context.getContextPath(),context);
return;
}
ContextHandler handler = ContextHandler.getContextHandler(context);
if (handler == null)
{
throw new ServletException("Not running on Jetty, JSR support disabled");
}
if (!(handler instanceof ServletContextHandler))
{
throw new ServletException("Not running in Jetty ServletContextHandler, JSR support disabled");
}
ServletContextHandler jettyContext = (ServletContextHandler)handler;
// Create the Jetty ServerContainer implementation
ServerContainer jettyContainer = configureContext(jettyContext);
// Store a reference to the ServerContainer per javax.websocket spec 1.0 final section 6.4 Programmatic Server Deployment
context.setAttribute(javax.websocket.server.ServerContainer.class.getName(),jettyContainer);
LOG.debug("Found {} classes",c.size());
// Now process the incoming classes
Set<Class<? extends Endpoint>> discoveredExtendedEndpoints = new HashSet<>();
Set<Class<?>> discoveredAnnotatedEndpoints = new HashSet<>();
Set<Class<? extends ServerApplicationConfig>> serverAppConfigs = new HashSet<>();
filterClasses(c,discoveredExtendedEndpoints,discoveredAnnotatedEndpoints,serverAppConfigs);
LOG.debug("Discovered {} extends Endpoint classes",discoveredExtendedEndpoints.size());
LOG.debug("Discovered {} @ServerEndpoint classes",discoveredAnnotatedEndpoints.size());
LOG.debug("Discovered {} ServerApplicationConfig classes",serverAppConfigs.size());
// Process the server app configs to determine endpoint filtering
boolean wasFiltered = false;
Set<ServerEndpointConfig> deployableExtendedEndpointConfigs = new HashSet<>();
Set<Class<?>> deployableAnnotatedEndpoints = new HashSet<>();
for (Class<? extends ServerApplicationConfig> clazz : serverAppConfigs)
{
LOG.debug("Found ServerApplicationConfig: {}",clazz);
try
{
ServerApplicationConfig config = (ServerApplicationConfig)clazz.newInstance();
Set<ServerEndpointConfig> seconfigs = config.getEndpointConfigs(discoveredExtendedEndpoints);
if (seconfigs != null)
{
wasFiltered = true;
deployableExtendedEndpointConfigs.addAll(seconfigs);
}
Set<Class<?>> annotatedClasses = config.getAnnotatedEndpointClasses(discoveredAnnotatedEndpoints);
if (annotatedClasses != null)
{
wasFiltered = true;
deployableAnnotatedEndpoints.addAll(annotatedClasses);
}
}
catch (InstantiationException | IllegalAccessException e)
{
throw new ServletException("Unable to instantiate: " + clazz.getName(),e);
}
}
// Default behavior if nothing filtered
if (!wasFiltered)
{
deployableAnnotatedEndpoints.addAll(discoveredAnnotatedEndpoints);
// Note: it is impossible to determine path of "extends Endpoint" discovered classes
deployableExtendedEndpointConfigs = new HashSet<>();
}
// Deploy what should be deployed.
LOG.debug("Deploying {} ServerEndpointConfig(s)",deployableExtendedEndpointConfigs.size());
for (ServerEndpointConfig config : deployableExtendedEndpointConfigs)
{
try
{
jettyContainer.addEndpoint(config);
}
catch (DeploymentException e)
{
throw new ServletException(e);
}
}
LOG.debug("Deploying {} @ServerEndpoint(s)",deployableAnnotatedEndpoints.size());
for (Class<?> annotatedClass : deployableAnnotatedEndpoints)
{
try
{
jettyContainer.addEndpoint(annotatedClass);
}
catch (DeploymentException e)
{
throw new ServletException(e);
}
}
}
@SuppressWarnings("unchecked")
private void filterClasses(Set<Class<?>> c, Set<Class<? extends Endpoint>> discoveredExtendedEndpoints, Set<Class<?>> discoveredAnnotatedEndpoints,
Set<Class<? extends ServerApplicationConfig>> serverAppConfigs)
{
for (Class<?> clazz : c)
{
if (ServerApplicationConfig.class.isAssignableFrom(clazz))
{
serverAppConfigs.add((Class<? extends ServerApplicationConfig>)clazz);
}
if (Endpoint.class.isAssignableFrom(clazz))
{
discoveredExtendedEndpoints.add((Class<? extends Endpoint>)clazz);
}
ServerEndpoint endpoint = clazz.getAnnotation(ServerEndpoint.class);
if (endpoint != null)
{
discoveredAnnotatedEndpoints.add(clazz);
}
}
}
}

View File

@ -1 +1 @@
org.eclipse.jetty.websocket.jsr356.server.deploy.ServerApplicationConfigListener
org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer

View File

@ -45,6 +45,7 @@ import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.jsr356.server.blockhead.BlockheadClient;
import org.eclipse.jetty.websocket.jsr356.server.blockhead.HttpResponse;
import org.eclipse.jetty.websocket.jsr356.server.blockhead.IncomingFramesCapture;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
@ -144,7 +145,7 @@ public class ConfiguratorTest
context.setContextPath("/");
server.setHandler(context);
ServerContainer container = WebSocketConfiguration.configureContext(context);
ServerContainer container = WebSocketServerContainerInitializer.configureContext(context);
container.addEndpoint(CaptureHeadersSocket.class);
container.addEndpoint(EmptySocket.class);
container.addEndpoint(NoExtensionsSocket.class);

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