Merge branch 'master' of ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project
Conflicts: jetty-server/src/main/config/etc/jetty.xml
This commit is contained in:
commit
6478306812
|
@ -25,7 +25,6 @@ import org.eclipse.jetty.deploy.PropertiesConfigurationManager;
|
|||
import org.eclipse.jetty.deploy.providers.WebAppProvider;
|
||||
import org.eclipse.jetty.jmx.MBeanContainer;
|
||||
import org.eclipse.jetty.security.HashLoginService;
|
||||
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
|
@ -42,7 +41,7 @@ import org.eclipse.jetty.server.handler.RequestLogHandler;
|
|||
import org.eclipse.jetty.server.handler.StatisticsHandler;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.eclipse.jetty.util.thread.TimerScheduler;
|
||||
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
|
||||
|
||||
public class LikeJettyXml
|
||||
{
|
||||
|
@ -51,7 +50,7 @@ public class LikeJettyXml
|
|||
String jetty_home = System.getProperty("jetty.home","../../jetty-distribution/target/distribution");
|
||||
System.setProperty("jetty.home",jetty_home);
|
||||
|
||||
|
||||
|
||||
// === jetty.xml ===
|
||||
// Setup Threadpool
|
||||
QueuedThreadPool threadPool = new QueuedThreadPool();
|
||||
|
@ -61,7 +60,7 @@ public class LikeJettyXml
|
|||
Server server = new Server(threadPool);
|
||||
|
||||
// Scheduler
|
||||
server.addBean(new TimerScheduler());
|
||||
server.addBean(new ScheduledExecutorScheduler());
|
||||
|
||||
// HTTP Configuration
|
||||
HttpConfiguration http_config = new HttpConfiguration();
|
||||
|
@ -73,7 +72,7 @@ public class LikeJettyXml
|
|||
http_config.setSendServerVersion(true);
|
||||
http_config.setSendDateHeader(false);
|
||||
// httpConfig.addCustomizer(new ForwardedRequestCustomizer());
|
||||
|
||||
|
||||
// Handler Structure
|
||||
HandlerCollection handlers = new HandlerCollection();
|
||||
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
||||
|
@ -84,21 +83,21 @@ public class LikeJettyXml
|
|||
server.setDumpAfterStart(false);
|
||||
server.setDumpBeforeStop(false);
|
||||
server.setStopAtShutdown(true);
|
||||
|
||||
|
||||
// === jetty-jmx.xml ===
|
||||
|
||||
// === jetty-jmx.xml ===
|
||||
MBeanContainer mbContainer=new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
|
||||
server.addBean(mbContainer);
|
||||
|
||||
|
||||
// === jetty-http.xml ===
|
||||
|
||||
// === jetty-http.xml ===
|
||||
ServerConnector http = new ServerConnector(server,new HttpConnectionFactory(http_config));
|
||||
http.setPort(8080);
|
||||
http.setIdleTimeout(30000);
|
||||
server.addConnector(http);
|
||||
|
||||
|
||||
// === jetty-https.xml ===
|
||||
|
||||
// === jetty-https.xml ===
|
||||
// SSL Context Factory
|
||||
SslContextFactory sslContextFactory = new SslContextFactory();
|
||||
sslContextFactory.setKeyStorePath(jetty_home + "/etc/keystore");
|
||||
|
@ -114,11 +113,11 @@ public class LikeJettyXml
|
|||
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
||||
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
||||
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
|
||||
|
||||
|
||||
// SSL HTTP Configuration
|
||||
HttpConfiguration https_config = new HttpConfiguration(http_config);
|
||||
https_config.addCustomizer(new SecureRequestCustomizer());
|
||||
|
||||
|
||||
// SSL Connector
|
||||
ServerConnector sslConnector = new ServerConnector(server,
|
||||
new SslConnectionFactory(sslContextFactory,"http/1.1"),
|
||||
|
@ -141,15 +140,15 @@ public class LikeJettyXml
|
|||
|
||||
deployer.addAppProvider(webapp_provider);
|
||||
server.addBean(deployer);
|
||||
|
||||
|
||||
// === jetty-stats.xml ===
|
||||
|
||||
// === jetty-stats.xml ===
|
||||
StatisticsHandler stats = new StatisticsHandler();
|
||||
stats.setHandler(server.getHandler());
|
||||
server.setHandler(stats);
|
||||
|
||||
|
||||
// === jetty-requestlog.xml ===
|
||||
// === jetty-requestlog.xml ===
|
||||
NCSARequestLog requestLog = new NCSARequestLog();
|
||||
requestLog.setFilename(jetty_home + "/logs/jetty-yyyy_mm_dd.log");
|
||||
requestLog.setFilenameDateFormat("yyyy_MM_dd");
|
||||
|
@ -163,7 +162,7 @@ public class LikeJettyXml
|
|||
handlers.addHandler(requestLogHandler);
|
||||
|
||||
|
||||
// === jetty-lowresources.xml ===
|
||||
// === jetty-lowresources.xml ===
|
||||
LowResourceMonitor lowResourcesMonitor=new LowResourceMonitor(server);
|
||||
lowResourcesMonitor.setPeriod(1000);
|
||||
lowResourcesMonitor.setLowResourcesIdleTimeout(200);
|
||||
|
@ -173,8 +172,8 @@ public class LikeJettyXml
|
|||
lowResourcesMonitor.setMaxLowResourcesTime(5000);
|
||||
server.addBean(lowResourcesMonitor);
|
||||
|
||||
|
||||
// === test-realm.xml ===
|
||||
|
||||
// === test-realm.xml ===
|
||||
HashLoginService login = new HashLoginService();
|
||||
login.setName("Test Realm");
|
||||
login.setConfig(jetty_home + "/etc/realm.properties");
|
||||
|
@ -182,7 +181,7 @@ public class LikeJettyXml
|
|||
server.addBean(login);
|
||||
|
||||
|
||||
// Start the server
|
||||
// Start the server
|
||||
server.start();
|
||||
server.join();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.annotations;
|
|||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EventListener;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
|
@ -29,6 +30,7 @@ import javax.servlet.annotation.HandlesTypes;
|
|||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
|
||||
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
|
||||
import org.eclipse.jetty.util.ArrayUtil;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -221,10 +223,10 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
|
||||
|
||||
|
||||
//add a listener which will call the servletcontainerinitializers when appropriate
|
||||
//add a bean which will call the servletcontainerinitializers when appropriate
|
||||
ServletContainerInitializerListener listener = new ServletContainerInitializerListener();
|
||||
listener.setWebAppContext(context);
|
||||
context.addEventListener(listener);
|
||||
context.addBean(listener, true);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -22,11 +22,10 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
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;
|
||||
|
@ -36,7 +35,7 @@ import org.eclipse.jetty.webapp.WebAppContext;
|
|||
*
|
||||
*
|
||||
*/
|
||||
public class ServletContainerInitializerListener implements ServletContextListener
|
||||
public class ServletContainerInitializerListener extends AbstractLifeCycle
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(ServletContainerInitializerListener.class);
|
||||
protected WebAppContext _context = null;
|
||||
|
@ -47,10 +46,12 @@ public class ServletContainerInitializerListener implements ServletContextListen
|
|||
_context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
|
||||
|
||||
/**
|
||||
* Call the doStart method of the ServletContainerInitializers
|
||||
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
|
||||
*/
|
||||
public void contextInitialized(ServletContextEvent sce)
|
||||
public void doStart()
|
||||
{
|
||||
List<ContainerInitializer> initializers = (List<ContainerInitializer>)_context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS);
|
||||
MultiMap classMap = (MultiMap)_context.getAttribute(AnnotationConfiguration.CLASS_INHERITANCE_MAP);
|
||||
|
@ -129,12 +130,14 @@ public class ServletContainerInitializerListener implements ServletContextListen
|
|||
addInheritedTypes (classMap, initializer, implementsOrExtends);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Nothing to do for ServletContainerInitializers on stop
|
||||
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
|
||||
*/
|
||||
public void contextDestroyed(ServletContextEvent sce)
|
||||
public void doStop()
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ abstract public class WriteFlusher
|
|||
{
|
||||
private static final Logger LOG = Log.getLogger(WriteFlusher.class);
|
||||
private static final boolean DEBUG = LOG.isDebugEnabled(); // Easy for the compiler to remove the code if DEBUG==false
|
||||
private static final ByteBuffer[] EMPTY_BUFFERS = new ByteBuffer[0];
|
||||
private static final EnumMap<StateType, Set<StateType>> __stateTransitions = new EnumMap<>(StateType.class);
|
||||
private static final State __IDLE = new IdleState();
|
||||
private static final State __WRITING = new WritingState();
|
||||
|
@ -243,7 +244,7 @@ abstract public class WriteFlusher
|
|||
private PendingState(ByteBuffer[] buffers, Callback callback)
|
||||
{
|
||||
super(StateType.PENDING);
|
||||
_buffers = buffers;
|
||||
_buffers = compact(buffers);
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
|
@ -263,6 +264,44 @@ abstract public class WriteFlusher
|
|||
if (_callback!=null)
|
||||
_callback.succeeded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compacting the buffers is needed because the semantic of WriteFlusher is
|
||||
* to write the buffers and if the caller sees that the buffer is consumed,
|
||||
* then it can recycle it.
|
||||
* If we do not compact, then it is possible that we store a consumed buffer,
|
||||
* which is then recycled and refilled; when the WriteFlusher is invoked to
|
||||
* complete the write, it will write the refilled bytes, garbling the content.
|
||||
*
|
||||
* @param buffers the buffers to compact
|
||||
* @return the compacted buffers
|
||||
*/
|
||||
private ByteBuffer[] compact(ByteBuffer[] buffers)
|
||||
{
|
||||
int length = buffers.length;
|
||||
|
||||
// Just one element, no need to compact
|
||||
if (length < 2)
|
||||
return buffers;
|
||||
|
||||
// How many still have content ?
|
||||
int consumed = 0;
|
||||
while (consumed < length && BufferUtil.isEmpty(buffers[consumed]))
|
||||
++consumed;
|
||||
|
||||
// All of them still have content, no need to compact
|
||||
if (consumed == 0)
|
||||
return buffers;
|
||||
|
||||
// None has content, return empty
|
||||
if (consumed == length)
|
||||
return EMPTY_BUFFERS;
|
||||
|
||||
int newLength = length - consumed;
|
||||
ByteBuffer[] result = new ByteBuffer[newLength];
|
||||
System.arraycopy(buffers, consumed, result, 0, newLength);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -306,7 +345,7 @@ abstract public class WriteFlusher
|
|||
if (updateState(__WRITING,pending))
|
||||
onIncompleteFlushed();
|
||||
else
|
||||
fail(new PendingState(buffers, callback));
|
||||
fail(pending);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,19 +18,11 @@
|
|||
|
||||
package org.eclipse.jetty.io;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.WritePendingException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
@ -54,16 +46,23 @@ import org.mockito.invocation.InvocationOnMock;
|
|||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class WriteFlusherTest
|
||||
{
|
||||
@Mock
|
||||
private EndPoint _endPointMock;
|
||||
|
||||
private WriteFlusher _flusher;
|
||||
|
||||
private final AtomicBoolean _flushIncomplete = new AtomicBoolean(false);
|
||||
private final ExecutorService executor = Executors.newFixedThreadPool(16);
|
||||
@Mock
|
||||
private EndPoint _endPointMock;
|
||||
private WriteFlusher _flusher;
|
||||
private ByteArrayEndPoint _endp;
|
||||
|
||||
@Before
|
||||
|
@ -400,6 +399,34 @@ public class WriteFlusherTest
|
|||
assertThat("callback completed", callback.isDone(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPendingWriteDoesNotStoreConsumedBuffers() throws Exception
|
||||
{
|
||||
int toWrite = _endp.getOutput().capacity();
|
||||
byte[] chunk1 = new byte[toWrite / 2];
|
||||
Arrays.fill(chunk1, (byte)1);
|
||||
ByteBuffer buffer1 = ByteBuffer.wrap(chunk1);
|
||||
byte[] chunk2 = new byte[toWrite];
|
||||
Arrays.fill(chunk1, (byte)2);
|
||||
ByteBuffer buffer2 = ByteBuffer.wrap(chunk2);
|
||||
|
||||
_flusher.write(new Callback.Adapter(), buffer1, buffer2);
|
||||
assertTrue(_flushIncomplete.get());
|
||||
assertFalse(buffer1.hasRemaining());
|
||||
|
||||
// Reuse buffer1
|
||||
buffer1.clear();
|
||||
Arrays.fill(chunk1, (byte)3);
|
||||
int remaining1 = buffer1.remaining();
|
||||
|
||||
// Complete the write
|
||||
_endp.takeOutput();
|
||||
_flusher.completeWrite();
|
||||
|
||||
// Make sure buffer1 is unchanged
|
||||
assertEquals(remaining1, buffer1.remaining());
|
||||
}
|
||||
|
||||
private class ExposingStateCallback extends FutureCallback
|
||||
{
|
||||
private boolean failed = false;
|
||||
|
|
|
@ -28,7 +28,6 @@ import java.util.Set;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -52,8 +51,8 @@ import org.eclipse.jetty.util.Callback;
|
|||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
import org.eclipse.jetty.util.thread.TimerScheduler;
|
||||
|
||||
/**
|
||||
* <p>Implementation of a {@link Handler} that supports HTTP CONNECT.</p>
|
||||
|
@ -163,7 +162,7 @@ public class ConnectHandler extends HandlerWrapper
|
|||
}
|
||||
if (scheduler == null)
|
||||
{
|
||||
setScheduler(new TimerScheduler());
|
||||
setScheduler(new ScheduledExecutorScheduler());
|
||||
addBean(getScheduler());
|
||||
}
|
||||
if (bufferPool == null)
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<!-- java -jar start.jar -? -->
|
||||
<!-- =============================================================== -->
|
||||
|
||||
<!-- =============================================================== -->
|
||||
<!-- =============================================================== -->
|
||||
<!-- Configure a Jetty Server instance with an ID "Server" -->
|
||||
<!-- Other configuration files may also configure the "Server" -->
|
||||
<!-- ID, in which case they are adding configuration to the same -->
|
||||
|
@ -49,13 +49,13 @@
|
|||
<Set name="detailedDump">false</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- Add shared Scheduler instance -->
|
||||
<!-- =========================================================== -->
|
||||
<Call name="addBean">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.util.thread.TimerScheduler"/>
|
||||
<New class="org.eclipse.jetty.util.thread.ScheduledExecutorScheduler"/>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
|
@ -83,14 +83,14 @@
|
|||
<Set name="sendServerVersion">true</Set>
|
||||
<Set name="sendDateHeader">false</Set>
|
||||
<Set name="headerCacheSize">512</Set>
|
||||
|
||||
<!-- Uncomment to enable handling of X-Forwarded- style headers
|
||||
|
||||
<!-- Uncomment to enable handling of X-Forwarded- style headers
|
||||
<Call name="addCustomizer">
|
||||
<Arg><New class="org.eclipse.jetty.server.ForwardedRequestCustomizer"/></Arg>
|
||||
</Call>
|
||||
-->
|
||||
</New>
|
||||
|
||||
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- Set the default handler structure for the Server -->
|
||||
|
@ -100,7 +100,7 @@
|
|||
<!-- DefaultHandler, which handles any requests not handled by -->
|
||||
<!-- the context handlers. -->
|
||||
<!-- Other handlers may be added to the "Handlers" collection, -->
|
||||
<!-- for example the jetty-requestlog.xml file adds the -->
|
||||
<!-- for example the jetty-requestlog.xml file adds the -->
|
||||
<!-- RequestLogHandler after the default handler -->
|
||||
<!-- =========================================================== -->
|
||||
<Set name="handler">
|
||||
|
|
|
@ -48,8 +48,8 @@ import org.eclipse.jetty.util.component.Dumpable;
|
|||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
import org.eclipse.jetty.util.thread.TimerScheduler;
|
||||
|
||||
/**
|
||||
* <p>An abstract implementation of {@link Connector} that provides a {@link ConnectionFactory} mechanism
|
||||
|
@ -63,7 +63,7 @@ import org.eclipse.jetty.util.thread.TimerScheduler;
|
|||
* </li>
|
||||
* <li>The {@link Scheduler} service is used to monitor the idle timeouts of all connections and is also made available
|
||||
* to the connections to time such things as asynchronous request timeouts. The default is to use a new
|
||||
* {@link TimerScheduler} instance.
|
||||
* {@link ScheduledExecutorScheduler} instance.
|
||||
* </li>
|
||||
* <li>The {@link ByteBufferPool} service is made available to all connections to be used to acquire and release
|
||||
* {@link ByteBuffer} instances from a pool. The default is to use a new {@link ArrayByteBufferPool} instance.
|
||||
|
@ -151,12 +151,12 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
|
|||
private long _idleTimeout = 30000;
|
||||
private String _defaultProtocol;
|
||||
private ConnectionFactory _defaultConnectionFactory;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param server The server this connector will be added to. Must not be null.
|
||||
* @param executor An executor for this connector or null to use the servers executor
|
||||
* @param scheduler A scheduler for this connector or null to either a {@link Scheduler} set as a server bean or if none set, then a new {@link TimerScheduler} instance.
|
||||
* @param scheduler A scheduler for this connector or null to either a {@link Scheduler} set as a server bean or if none set, then a new {@link ScheduledExecutorScheduler} instance.
|
||||
* @param pool A buffer pool for this connector or null to either a {@link ByteBufferPool} set as a server bean or none set, the new {@link ArrayByteBufferPool} instance.
|
||||
* @param acceptors the number of acceptor threads to use, or 0 for a default value.
|
||||
* @param factories The Connection Factories to use.
|
||||
|
@ -173,7 +173,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
|
|||
_executor=executor!=null?executor:_server.getThreadPool();
|
||||
if (scheduler==null)
|
||||
scheduler=_server.getBean(Scheduler.class);
|
||||
_scheduler=scheduler!=null?scheduler:new TimerScheduler();
|
||||
_scheduler=scheduler!=null?scheduler:new ScheduledExecutorScheduler();
|
||||
if (pool==null)
|
||||
pool=_server.getBean(ByteBufferPool.class);
|
||||
_byteBufferPool = pool!=null?pool:new ArrayByteBufferPool();
|
||||
|
@ -479,9 +479,9 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// protected void connectionOpened(Connection connection)
|
||||
// {
|
||||
// _stats.connectionOpened();
|
||||
|
@ -512,7 +512,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
|
|||
{
|
||||
_endpoints.add(endp);
|
||||
}
|
||||
|
||||
|
||||
protected void onEndPointClosed(EndPoint endp)
|
||||
{
|
||||
_endpoints.remove(endp);
|
||||
|
|
|
@ -32,9 +32,9 @@ import org.eclipse.jetty.util.annotation.Name;
|
|||
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.util.thread.ScheduledExecutorScheduler;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
import org.eclipse.jetty.util.thread.ThreadPool;
|
||||
import org.eclipse.jetty.util.thread.TimerScheduler;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -42,7 +42,7 @@ import org.eclipse.jetty.util.thread.TimerScheduler;
|
|||
* <p>An instance of this class will monitor all the connectors of a server (or a set of connectors
|
||||
* configured with {@link #setMonitoredConnectors(Collection)}) for a low resources state.
|
||||
* Low resources can be detected by:<ul>
|
||||
* <li>{@link ThreadPool#isLowOnThreads()} if {@link Connector#getExecutor()} is
|
||||
* <li>{@link ThreadPool#isLowOnThreads()} if {@link Connector#getExecutor()} is
|
||||
* an instance of {@link ThreadPool} and {@link #setMonitorThreads(boolean)} is true.<li>
|
||||
* <li>If {@link #setMaxMemory(long)} is non zero then low resources is detected if the JVMs
|
||||
* {@link Runtime} instance has {@link Runtime#totalMemory()} minus {@link Runtime#freeMemory()}
|
||||
|
@ -51,11 +51,11 @@ import org.eclipse.jetty.util.thread.TimerScheduler;
|
|||
* of connections exceeds {@link #getMaxConnections()}</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* <p>Once low resources state is detected, the cause is logged and all existing connections returned
|
||||
* by {@link Connector#getConnectedEndPoints()} have {@link EndPoint#setIdleTimeout(long)} set
|
||||
* to {@link #getLowResourcesIdleTimeout()}. New connections are not affected, however if the low
|
||||
* resources state persists for more than {@link #getMaxLowResourcesTime()}, then the
|
||||
* {@link #getLowResourcesIdleTimeout()} to all connections again. Once the low resources state is
|
||||
* <p>Once low resources state is detected, the cause is logged and all existing connections returned
|
||||
* by {@link Connector#getConnectedEndPoints()} have {@link EndPoint#setIdleTimeout(long)} set
|
||||
* to {@link #getLowResourcesIdleTimeout()}. New connections are not affected, however if the low
|
||||
* resources state persists for more than {@link #getMaxLowResourcesTime()}, then the
|
||||
* {@link #getLowResourcesIdleTimeout()} to all connections again. Once the low resources state is
|
||||
* cleared, the idle timeout is reset to the connector default given by {@link Connector#getIdleTimeout()}.
|
||||
* </p>
|
||||
*/
|
||||
|
@ -76,44 +76,44 @@ public class LowResourceMonitor extends AbstractLifeCycle
|
|||
private String _cause;
|
||||
private String _reasons;
|
||||
private long _lowStarted;
|
||||
|
||||
|
||||
|
||||
|
||||
private final Runnable _monitor = new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
{
|
||||
if (isRunning())
|
||||
{
|
||||
monitor();
|
||||
_scheduler.schedule(_monitor,_period,TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public LowResourceMonitor(@Name("server") Server server)
|
||||
{
|
||||
_server=server;
|
||||
}
|
||||
|
||||
|
||||
@ManagedAttribute("Are the monitored connectors low on resources?")
|
||||
public boolean isLowOnResources()
|
||||
{
|
||||
return _low.get();
|
||||
}
|
||||
|
||||
|
||||
@ManagedAttribute("The reason(s) the monitored connectors are low on resources")
|
||||
public String getLowResourcesReasons()
|
||||
{
|
||||
return _reasons;
|
||||
}
|
||||
|
||||
|
||||
@ManagedAttribute("Get the timestamp in ms since epoch that low resources state started")
|
||||
public long getLowResourcesStarted()
|
||||
{
|
||||
return _lowStarted;
|
||||
}
|
||||
|
||||
|
||||
@ManagedAttribute("The monitored connectors. If null then all server connectors are monitored")
|
||||
public Collection<Connector> getMonitoredConnectors()
|
||||
{
|
||||
|
@ -140,7 +140,7 @@ public class LowResourceMonitor extends AbstractLifeCycle
|
|||
}
|
||||
|
||||
/**
|
||||
* @param periodMS The period in ms to monitor for low resources
|
||||
* @param periodMS The period in ms to monitor for low resources
|
||||
*/
|
||||
public void setPeriod(int periodMS)
|
||||
{
|
||||
|
@ -154,8 +154,8 @@ public class LowResourceMonitor extends AbstractLifeCycle
|
|||
}
|
||||
|
||||
/**
|
||||
* @param monitorThreads If true, check connectors executors to see if they are
|
||||
* {@link ThreadPool} instances that are low on threads.
|
||||
* @param monitorThreads If true, check connectors executors to see if they are
|
||||
* {@link ThreadPool} instances that are low on threads.
|
||||
*/
|
||||
public void setMonitorThreads(boolean monitorThreads)
|
||||
{
|
||||
|
@ -222,14 +222,14 @@ public class LowResourceMonitor extends AbstractLifeCycle
|
|||
protected void doStart() throws Exception
|
||||
{
|
||||
_scheduler = _server.getBean(Scheduler.class);
|
||||
|
||||
|
||||
if (_scheduler==null)
|
||||
{
|
||||
_scheduler=new LRMScheduler();
|
||||
_scheduler.start();
|
||||
}
|
||||
super.doStart();
|
||||
|
||||
|
||||
_scheduler.schedule(_monitor,_period,TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
|
@ -240,24 +240,24 @@ public class LowResourceMonitor extends AbstractLifeCycle
|
|||
_scheduler.stop();
|
||||
super.doStop();
|
||||
}
|
||||
|
||||
|
||||
protected Connector[] getMonitoredOrServerConnectors()
|
||||
{
|
||||
if (_monitoredConnectors!=null && _monitoredConnectors.length>0)
|
||||
return _monitoredConnectors;
|
||||
return _server.getConnectors();
|
||||
}
|
||||
|
||||
|
||||
protected void monitor()
|
||||
{
|
||||
String reasons=null;
|
||||
String cause="";
|
||||
int connections=0;
|
||||
|
||||
|
||||
for(Connector connector : getMonitoredOrServerConnectors())
|
||||
{
|
||||
connections+=connector.getConnectedEndPoints().size();
|
||||
|
||||
|
||||
Executor executor = connector.getExecutor();
|
||||
if (executor instanceof ThreadPool)
|
||||
{
|
||||
|
@ -269,21 +269,21 @@ public class LowResourceMonitor extends AbstractLifeCycle
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (_maxConnections>0 && connections>_maxConnections)
|
||||
{
|
||||
reasons=low(reasons,"Max Connections exceeded: "+connections+">"+_maxConnections);
|
||||
cause+="C";
|
||||
}
|
||||
|
||||
|
||||
long memory=Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory();
|
||||
if (_maxMemory>0 && memory>_maxMemory)
|
||||
{
|
||||
reasons=low(reasons,"Max memory exceeded: "+memory+">"+_maxMemory);
|
||||
cause+="M";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (reasons!=null)
|
||||
{
|
||||
// Log the reasons if there is any change in the cause
|
||||
|
@ -292,7 +292,7 @@ public class LowResourceMonitor extends AbstractLifeCycle
|
|||
LOG.warn("Low Resources: {}",reasons);
|
||||
_cause=cause;
|
||||
}
|
||||
|
||||
|
||||
// Enter low resources state?
|
||||
if (_low.compareAndSet(false,true))
|
||||
{
|
||||
|
@ -300,12 +300,12 @@ public class LowResourceMonitor extends AbstractLifeCycle
|
|||
_lowStarted=System.currentTimeMillis();
|
||||
setLowResources();
|
||||
}
|
||||
|
||||
|
||||
// Too long in low resources state?
|
||||
if (_maxLowResourcesTime>0 && (System.currentTimeMillis()-_lowStarted)>_maxLowResourcesTime)
|
||||
setLowResources();
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
if (_low.compareAndSet(true,false))
|
||||
{
|
||||
|
@ -316,7 +316,7 @@ public class LowResourceMonitor extends AbstractLifeCycle
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void setLowResources()
|
||||
{
|
||||
for(Connector connector : getMonitoredOrServerConnectors())
|
||||
|
@ -325,7 +325,7 @@ public class LowResourceMonitor extends AbstractLifeCycle
|
|||
endPoint.setIdleTimeout(_lowResourcesIdleTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void clearLowResources()
|
||||
{
|
||||
for(Connector connector : getMonitoredOrServerConnectors())
|
||||
|
@ -334,16 +334,16 @@ public class LowResourceMonitor extends AbstractLifeCycle
|
|||
endPoint.setIdleTimeout(connector.getIdleTimeout());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String low(String reasons, String newReason)
|
||||
{
|
||||
if (reasons==null)
|
||||
return newReason;
|
||||
return reasons+", "+newReason;
|
||||
}
|
||||
|
||||
|
||||
private static class LRMScheduler extends TimerScheduler
|
||||
|
||||
|
||||
private static class LRMScheduler extends ScheduledExecutorScheduler
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2097,6 +2097,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
|||
if (!_enabled)
|
||||
throw new UnsupportedOperationException();
|
||||
ContextHandler.this.addEventListener(t);
|
||||
ContextHandler.this.addProgrammaticListener(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -995,7 +995,7 @@ public class DoSFilter implements Filter
|
|||
* @see #addWhitelistAddress(List, String)
|
||||
*/
|
||||
@ManagedOperation("removes an IP address that will not be rate limited")
|
||||
public boolean removeWhitelistAddress(String address)
|
||||
public boolean removeWhitelistAddress(@Name("address") String address)
|
||||
{
|
||||
return _whitelist.remove(address);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ import java.util.Queue;
|
|||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
|
@ -50,8 +49,8 @@ import org.eclipse.jetty.util.FuturePromise;
|
|||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
import org.eclipse.jetty.util.thread.TimerScheduler;
|
||||
|
||||
public class SPDYClient
|
||||
{
|
||||
|
@ -202,7 +201,7 @@ public class SPDYClient
|
|||
addBean(executor);
|
||||
|
||||
if (scheduler == null)
|
||||
scheduler = new TimerScheduler();
|
||||
scheduler = new ScheduledExecutorScheduler();
|
||||
this.scheduler = scheduler;
|
||||
addBean(scheduler);
|
||||
|
||||
|
|
|
@ -73,6 +73,12 @@ public interface LogicalConnection extends OutgoingFrames, SuspendToken
|
|||
*/
|
||||
InetSocketAddress getLocalAddress();
|
||||
|
||||
/**
|
||||
* Set the maximum number of milliseconds of idleness before the connection is closed/disconnected, (ie no frames are either sent or received)
|
||||
* @return the idle timeout in milliseconds
|
||||
*/
|
||||
long getMaxIdleTimeout();
|
||||
|
||||
/**
|
||||
* The policy that the connection is running under.
|
||||
* @return the policy for the connection
|
||||
|
@ -109,6 +115,14 @@ public interface LogicalConnection extends OutgoingFrames, SuspendToken
|
|||
*/
|
||||
boolean isReading();
|
||||
|
||||
/**
|
||||
* Set the maximum number of milliseconds of idleness before the connection is closed/disconnected, (ie no frames are either sent or received)
|
||||
*
|
||||
* @param ms
|
||||
* the number of milliseconds of idle timeout
|
||||
*/
|
||||
void setMaxIdleTimeout(long ms);
|
||||
|
||||
/**
|
||||
* Set where the connection should send the incoming frames to.
|
||||
* <p>
|
||||
|
|
|
@ -59,7 +59,6 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Inc
|
|||
private ExtensionFactory extensionFactory;
|
||||
private long maximumMessageSize;
|
||||
private String protocolVersion;
|
||||
private long timeout;
|
||||
private Map<String, String[]> parameterMap = new HashMap<>();
|
||||
private WebSocketRemoteEndpoint remote;
|
||||
private IncomingFrames incomingHandler;
|
||||
|
@ -165,12 +164,12 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Inc
|
|||
}
|
||||
|
||||
/**
|
||||
* The idle timeout in seconds
|
||||
* The idle timeout in milliseconds
|
||||
*/
|
||||
@Override
|
||||
public long getIdleTimeout()
|
||||
{
|
||||
return timeout;
|
||||
return connection.getMaxIdleTimeout();
|
||||
}
|
||||
|
||||
@ManagedAttribute(readonly = true)
|
||||
|
@ -320,12 +319,12 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Inc
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the timeout in seconds
|
||||
* Set the timeout in milliseconds
|
||||
*/
|
||||
@Override
|
||||
public void setIdleTimeout(long seconds)
|
||||
public void setIdleTimeout(long ms)
|
||||
{
|
||||
this.timeout = seconds;
|
||||
connection.setMaxIdleTimeout(ms);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -111,6 +111,13 @@ public class MuxChannel implements LogicalConnection, IncomingFrames, SuspendTok
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaxIdleTimeout()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebSocketPolicy getPolicy()
|
||||
{
|
||||
|
@ -205,6 +212,13 @@ public class MuxChannel implements LogicalConnection, IncomingFrames, SuspendTok
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxIdleTimeout(long ms)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNextIncomingFrames(IncomingFrames incoming)
|
||||
{
|
||||
|
|
|
@ -347,6 +347,12 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
|||
return ioState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaxIdleTimeout()
|
||||
{
|
||||
return getEndPoint().getIdleTimeout();
|
||||
}
|
||||
|
||||
public Parser getParser()
|
||||
{
|
||||
return parser;
|
||||
|
@ -568,6 +574,12 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
|||
super.setInputBufferSize(inputBufferSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxIdleTimeout(long ms)
|
||||
{
|
||||
getEndPoint().setIdleTimeout(ms);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSession(WebSocketSession session)
|
||||
{
|
||||
|
|
|
@ -91,6 +91,13 @@ public class LocalWebSocketConnection implements LogicalConnection, IncomingFram
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaxIdleTimeout()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebSocketPolicy getPolicy()
|
||||
{
|
||||
|
@ -148,6 +155,13 @@ public class LocalWebSocketConnection implements LogicalConnection, IncomingFram
|
|||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxIdleTimeout(long ms)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNextIncomingFrames(IncomingFrames incoming)
|
||||
{
|
||||
|
|
|
@ -27,7 +27,6 @@ import java.util.Map;
|
|||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
@ -39,8 +38,8 @@ import org.eclipse.jetty.server.HttpConnection;
|
|||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
import org.eclipse.jetty.util.thread.TimerScheduler;
|
||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.api.UpgradeResponse;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
|
@ -83,7 +82,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
|||
/**
|
||||
* Have the factory maintain 1 and only 1 scheduler. All connections share this scheduler.
|
||||
*/
|
||||
private final Scheduler scheduler = new TimerScheduler();
|
||||
private final Scheduler scheduler = new ScheduledExecutorScheduler();
|
||||
private final String supportedVersions;
|
||||
private final WebSocketPolicy basePolicy;
|
||||
private final EventDriverFactory eventDriverFactory;
|
||||
|
@ -308,7 +307,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
|||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see org.eclipse.jetty.websocket.server.WebSocketServletFactory#register(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
|
@ -349,7 +348,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
|||
* <p>
|
||||
* This method will not normally return, but will instead throw a UpgradeConnectionException, to exit HTTP handling and initiate WebSocket handling of the
|
||||
* connection.
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
* The request to upgrade
|
||||
* @param response
|
||||
|
|
|
@ -42,15 +42,17 @@ import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
|||
* <pre>
|
||||
* package my.example;
|
||||
*
|
||||
* import javax.servlet.http.HttpServletRequest;
|
||||
* import org.eclipse.jetty.websocket.WebSocket;
|
||||
* import org.eclipse.jetty.websocket.server.WebSocketServlet;
|
||||
* import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
|
||||
* import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
||||
*
|
||||
* public class MyEchoServlet extends WebSocketServlet
|
||||
* {
|
||||
* @Override
|
||||
* public void registerWebSockets(WebSocketServerFactory factory)
|
||||
* public void configure(WebSocketServletFactory factory)
|
||||
* {
|
||||
* // set a 10 second idle timeout
|
||||
* factory.getPolicy().setIdleTimeout(10000);
|
||||
* // register my socket
|
||||
* factory.register(MyEchoSocket.class);
|
||||
* }
|
||||
* }
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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 examples;
|
||||
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class MyExampleServlet extends WebSocketServlet
|
||||
{
|
||||
@Override
|
||||
public void configure(WebSocketServletFactory factory)
|
||||
{
|
||||
// set a 10 second timeout
|
||||
factory.getPolicy().setIdleTimeout(10000);
|
||||
// register my socket
|
||||
factory.register(MyExampleSocket.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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 examples;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
|
||||
|
||||
/**
|
||||
* Example WebSocket, simple echo
|
||||
*/
|
||||
public class MyExampleSocket extends WebSocketAdapter
|
||||
{
|
||||
@Override
|
||||
public void onWebSocketText(String message)
|
||||
{
|
||||
// Echo message back, asynchronously
|
||||
getSession().getRemote().sendStringByFuture(message);
|
||||
}
|
||||
}
|
|
@ -23,17 +23,80 @@ import java.util.Set;
|
|||
|
||||
import javax.servlet.ServletContainerInitializer;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import javax.servlet.ServletRegistration;
|
||||
import javax.servlet.annotation.HandlesTypes;
|
||||
|
||||
@HandlesTypes ({javax.servlet.Servlet.class, Foo.class})
|
||||
public class FooInitializer implements ServletContainerInitializer
|
||||
{
|
||||
public static class BarListener implements ServletContextListener
|
||||
{
|
||||
|
||||
/**
|
||||
* @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
|
||||
*/
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce)
|
||||
{
|
||||
throw new IllegalStateException("BAR LISTENER CALLED!");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
|
||||
*/
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class FooListener implements ServletContextListener
|
||||
{
|
||||
|
||||
/**
|
||||
* @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
|
||||
*/
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce)
|
||||
{
|
||||
//Can add a ServletContextListener from a ServletContainerInitializer
|
||||
sce.getServletContext().setAttribute("com.acme.AnnotationTest.listenerTest", Boolean.TRUE);
|
||||
|
||||
//Can't add a ServletContextListener from a ServletContextListener
|
||||
try
|
||||
{
|
||||
sce.getServletContext().addListener(new BarListener());
|
||||
sce.getServletContext().setAttribute("com.acme.AnnotationTest.listenerRegoTest", Boolean.FALSE);
|
||||
}
|
||||
catch (UnsupportedOperationException e)
|
||||
{
|
||||
sce.getServletContext().setAttribute("com.acme.AnnotationTest.listenerRegoTest", Boolean.TRUE);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
sce.getServletContext().setAttribute("com.acme.AnnotationTest.listenerRegoTest", Boolean.FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
|
||||
*/
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public void onStartup(Set<Class<?>> classes, ServletContext context)
|
||||
{
|
||||
context.setAttribute("com.acme.Foo", new ArrayList<Class>(classes));
|
||||
ServletRegistration.Dynamic reg = context.addServlet("AnnotationTest", "com.acme.AnnotationTest");
|
||||
context.setAttribute("com.acme.AnnotationTest.complete", (reg == null));
|
||||
context.addListener(new FooListener());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -245,6 +245,14 @@ public class AnnotationTest extends HttpServlet
|
|||
Boolean complete = (Boolean)config.getServletContext().getAttribute("com.acme.AnnotationTest.complete");
|
||||
out.println("<br/><b>Result: "+(complete.booleanValue()?"PASS":"FAIL")+"</b>");
|
||||
|
||||
out.println("<h2>ServletContextListener Programmatic Registration from ServletContainerInitializer</h2>");
|
||||
Boolean programmaticListener = (Boolean)config.getServletContext().getAttribute("com.acme.AnnotationTest.listenerTest");
|
||||
out.println("<br/><b>Result: "+(programmaticListener.booleanValue()?"PASS":"FAIL")+"</b>");
|
||||
|
||||
out.println("<h2>ServletContextListener Programmatic Registration Prevented from ServletContextListener</h2>");
|
||||
Boolean programmaticListenerPrevention = (Boolean)config.getServletContext().getAttribute("com.acme.AnnotationTest.listenerRegoTest");
|
||||
out.println("<br/><b>Result: "+(programmaticListenerPrevention.booleanValue()?"PASS":"FAIL")+"</b>");
|
||||
|
||||
out.println("<h2>@PostConstruct Callback</h2>");
|
||||
out.println("<pre>");
|
||||
out.println("@PostConstruct");
|
||||
|
|
Loading…
Reference in New Issue