diff --git a/example-jetty-embedded/pom.xml b/example-jetty-embedded/pom.xml
index e8ead3eb08e..f90da7f4eeb 100644
--- a/example-jetty-embedded/pom.xml
+++ b/example-jetty-embedded/pom.xml
@@ -38,5 +38,10 @@
jetty-jmx
${project.version}
+
+ org.eclipse.jetty
+ jetty-websocket
+ ${project.version}
+
diff --git a/jetty-distribution/pom.xml b/jetty-distribution/pom.xml
index 2eb2273acdb..57fa08fc8a3 100644
--- a/jetty-distribution/pom.xml
+++ b/jetty-distribution/pom.xml
@@ -377,6 +377,15 @@
${assembly.directory}
start.jar
+
+ org.eclipse.jetty
+ jetty-websocket
+ ${project.version}
+ jar
+ true
+ **
+ ${assembly.directory}/lib
+
@@ -500,5 +509,10 @@
jetty-policy
${project.version}
+
+ org.eclipse.jetty
+ jetty-websocket
+ ${project.version}
+
diff --git a/jetty-distribution/src/main/resources/start.ini b/jetty-distribution/src/main/resources/start.ini
index 904f8ae8404..4c9a5a5836e 100644
--- a/jetty-distribution/src/main/resources/start.ini
+++ b/jetty-distribution/src/main/resources/start.ini
@@ -14,6 +14,8 @@
#
#===========================================================
+OPTIONS=Server,jmx,resources,websocket
+
#===========================================================
# The following is an example of the ini args to run the
# server with a heap size, JMX remote enabled, JMX mbeans
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java
index 45b965f50ed..14210297c04 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java
@@ -485,6 +485,7 @@ public class HttpGenerator extends AbstractGenerator
HttpFields.Field field = fields.getField(f);
if (field==null)
continue;
+
switch (field.getNameOrdinal())
{
case HttpHeaders.CONTENT_LENGTH_ORDINAL:
@@ -506,7 +507,8 @@ public class HttpGenerator extends AbstractGenerator
break;
case HttpHeaders.TRANSFER_ENCODING_ORDINAL:
- if (_version == HttpVersions.HTTP_1_1_ORDINAL) transfer_encoding = field;
+ if (_version == HttpVersions.HTTP_1_1_ORDINAL)
+ transfer_encoding = field;
// Do NOT add yet!
break;
@@ -566,6 +568,15 @@ public class HttpGenerator extends AbstractGenerator
break;
}
+ case HttpHeaderValues.UPGRADE_ORDINAL:
+ {
+ // special case for websocket connection ordering
+ if (_method==null)
+ {
+ field.put(_header);
+ continue;
+ }
+ }
case HttpHeaderValues.CLOSE_ORDINAL:
{
close=true;
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpHeaderValues.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpHeaderValues.java
index 1c500b0b548..ba228911082 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpHeaderValues.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpHeaderValues.java
@@ -42,7 +42,8 @@ public class HttpHeaderValues extends BufferCache
PROCESSING="102-processing",
TE="TE",
BYTES="bytes",
- NO_CACHE="no-cache";
+ NO_CACHE="no-cache",
+ UPGRADE="Upgrade";
public final static int
CLOSE_ORDINAL=1,
@@ -54,7 +55,8 @@ public class HttpHeaderValues extends BufferCache
PROCESSING_ORDINAL=7,
TE_ORDINAL=8,
BYTES_ORDINAL=9,
- NO_CACHE_ORDINAL=10;
+ NO_CACHE_ORDINAL=10,
+ UPGRADE_ORDINAL=11;
public final static HttpHeaderValues CACHE= new HttpHeaderValues();
@@ -68,7 +70,8 @@ public class HttpHeaderValues extends BufferCache
PROCESSING_BUFFER=CACHE.add(PROCESSING, PROCESSING_ORDINAL),
TE_BUFFER=CACHE.add(TE,TE_ORDINAL),
BYTES_BUFFER=CACHE.add(BYTES,BYTES_ORDINAL),
- NO_CACHE_BUFFER=CACHE.add(NO_CACHE,NO_CACHE_ORDINAL);
+ NO_CACHE_BUFFER=CACHE.add(NO_CACHE,NO_CACHE_ORDINAL),
+ UPGRADE_BUFFER=CACHE.add(UPGRADE,UPGRADE_ORDINAL);
static
{
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java
index ab0a8b20ee2..fd11d780a1f 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java
@@ -32,9 +32,6 @@ import org.eclipse.jetty.util.thread.Timeout;
/* ------------------------------------------------------------ */
/**
* An Endpoint that can be scheduled by {@link SelectorManager}.
- *
- *
- *
*/
public class SelectChannelEndPoint extends ChannelEndPoint implements Runnable, AsyncEndPoint, ConnectedEndPoint
{
diff --git a/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/ObjectMBean.java b/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/ObjectMBean.java
index 59526b76791..6cba39de597 100644
--- a/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/ObjectMBean.java
+++ b/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/ObjectMBean.java
@@ -648,7 +648,7 @@ public class ObjectMBean implements DynamicMBean
}
catch (Exception e)
{
- Log.warn(Log.EXCEPTION, e);
+ Log.warn(name+": "+metaData, e);
throw new IllegalArgumentException(e.toString());
}
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java
index e62fb0baa88..14cf632ea31 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java
@@ -61,7 +61,7 @@ public class Server extends HandlerWrapper implements Attributes
if (Server.class.getPackage()!=null && Server.class.getPackage().getImplementationVersion()!=null)
_version=Server.class.getPackage().getImplementationVersion();
else
- _version=System.getProperty("jetty.version","7.0.y.z-SNAPSHOT");
+ _version=System.getProperty("jetty.version","7.0.2-SNAPSHOT");
}
private final Container _container=new Container();
private final AttributesMap _attributes = new AttributesMap();
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/nio/SelectChannelConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/nio/SelectChannelConnector.java
index 1f1e0dcd19a..69f7d555ae8 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/nio/SelectChannelConnector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/nio/SelectChannelConnector.java
@@ -63,8 +63,8 @@ import org.eclipse.jetty.util.thread.Timeout.Task;
public class SelectChannelConnector extends AbstractNIOConnector
{
protected ServerSocketChannel _acceptChannel;
- private long _lowResourcesConnections;
- private long _lowResourcesMaxIdleTime;
+ private int _lowResourcesConnections;
+ private int _lowResourcesMaxIdleTime;
private final SelectorManager _manager = new SelectorManager()
{
@@ -226,7 +226,7 @@ public class SelectChannelConnector extends AbstractNIOConnector
/**
* @return the lowResourcesConnections
*/
- public long getLowResourcesConnections()
+ public int getLowResourcesConnections()
{
return _lowResourcesConnections;
}
@@ -236,9 +236,9 @@ public class SelectChannelConnector extends AbstractNIOConnector
* Set the number of connections, which if exceeded places this manager in low resources state.
* This is not an exact measure as the connection count is averaged over the select sets.
* @param lowResourcesConnections the number of connections
- * @see {@link #setLowResourcesMaxIdleTime(long)}
+ * @see {@link #setLowResourcesMaxIdleTime(int)}
*/
- public void setLowResourcesConnections(long lowResourcesConnections)
+ public void setLowResourcesConnections(int lowResourcesConnections)
{
_lowResourcesConnections=lowResourcesConnections;
}
@@ -247,27 +247,11 @@ public class SelectChannelConnector extends AbstractNIOConnector
/**
* @return the lowResourcesMaxIdleTime
*/
- public long getLowResourcesMaxIdleTime()
+ public int getLowResourcesMaxIdleTime()
{
return _lowResourcesMaxIdleTime;
}
- /* ------------------------------------------------------------ */
- /**
- * Set the period in ms that a connection is allowed to be idle when this there are more
- * than {@link #getLowResourcesConnections()} connections. This allows the server to rapidly close idle connections
- * in order to gracefully handle high load situations.
- * @param lowResourcesMaxIdleTime the period in ms that a connection is allowed to be idle when resources are low.
- * @see {@link #setMaxIdleTime(long)}
- * @deprecated use {@link #setLowResourceMaxIdleTime(int)}
- */
- @Deprecated
- public void setLowResourcesMaxIdleTime(long lowResourcesMaxIdleTime)
- {
- _lowResourcesMaxIdleTime=lowResourcesMaxIdleTime;
- super.setLowResourceMaxIdleTime((int)lowResourcesMaxIdleTime); // TODO fix the name duplications
- }
-
/* ------------------------------------------------------------ */
/**
* Set the period in ms that a connection is allowed to be idle when this there are more
diff --git a/jetty-start/src/main/resources/org/eclipse/jetty/start/start.config b/jetty-start/src/main/resources/org/eclipse/jetty/start/start.config
index 092be487c5c..2d659f5464b 100644
--- a/jetty-start/src/main/resources/org/eclipse/jetty/start/start.config
+++ b/jetty-start/src/main/resources/org/eclipse/jetty/start/start.config
@@ -143,6 +143,9 @@ $(jetty.home)/lib/policy/jetty.policy
$(jetty.home)/lib/jetty-http-$(version).jar ! available org.eclipse.jetty.http.HttpParser
$(jetty.home)/lib/jetty-client-$(version).jar ! available org.eclipse.jetty.client.HttpClient
+[All,websocket]
+$(jetty.home)/lib/jetty-websocket-$(version).jar ! available org.eclipse.jetty.websocket.WebSocket
+
# Add ext if it exists
[All,default,=$(jetty.home)/lib/ext]
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java b/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java
index c76bfced9b2..ca923ea878c 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java
@@ -46,8 +46,8 @@ public class StringMap extends AbstractMap implements Externalizable
protected boolean _ignoreCase=false;
protected NullEntry _nullEntry=null;
protected Object _nullValue=null;
- protected HashSet _entrySet=new HashSet(3);
- protected Set _umEntrySet=Collections.unmodifiableSet(_entrySet);
+ protected HashSet _entrySet=new HashSet(3);
+ protected Set _umEntrySet=Collections.unmodifiableSet(_entrySet);
/* ------------------------------------------------------------ */
/** Constructor.
@@ -135,6 +135,9 @@ public class StringMap extends AbstractMap implements Externalizable
return oldValue;
}
+ if (_ignoreCase)
+ key=key.toUpperCase();
+
Node node = _root;
int ni=-1;
Node prev = null;
diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocket.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocket.java
index eabeb74b8f9..525dddf39b0 100644
--- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocket.java
+++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocket.java
@@ -16,7 +16,7 @@ public interface WebSocket
void sendMessage(byte frame,String data) throws IOException;
void sendMessage(byte frame,byte[] data) throws IOException;
void sendMessage(byte frame,byte[] data, int offset, int length) throws IOException;
- void disconnect() throws IOException;
+ void disconnect();
boolean isOpen();
}
}
diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketBuffers.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketBuffers.java
index 729ec83bb39..fbfc94dbdd9 100644
--- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketBuffers.java
+++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketBuffers.java
@@ -4,6 +4,7 @@ import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.ThreadLocalBuffers;
import org.eclipse.jetty.io.nio.DirectNIOBuffer;
+import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
/* ------------------------------------------------------------ */
@@ -31,7 +32,7 @@ public class WebSocketBuffers
@Override
protected Buffer newBuffer(int size)
{
- return new ByteArrayBuffer(bufferSize);
+ return new IndirectNIOBuffer(bufferSize);
}
@Override
diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketConnection.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketConnection.java
index 0696b9edce0..3b51c57f015 100644
--- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketConnection.java
+++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketConnection.java
@@ -5,10 +5,12 @@ import java.io.IOException;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.util.log.Log;
public class WebSocketConnection implements Connection, WebSocket.Outbound
{
+ final Connector _connector;
final EndPoint _endp;
final WebSocketParser _parser;
final WebSocketGenerator _generator;
@@ -16,8 +18,9 @@ public class WebSocketConnection implements Connection, WebSocket.Outbound
final WebSocket _websocket;
final int _maxIdleTimeMs=30000;
- public WebSocketConnection(WebSocketBuffers buffers, EndPoint endpoint, long timestamp, WebSocket websocket)
+ public WebSocketConnection(Connector connector, WebSocketBuffers buffers, EndPoint endpoint, long timestamp, WebSocket websocket)
{
+ _connector=connector;
_endp = endpoint;
_timestamp = timestamp;
_websocket = websocket;
@@ -72,21 +75,28 @@ public class WebSocketConnection implements Connection, WebSocket.Outbound
int filled=_parser.parseNext();
more = flushed>0 || filled>0 || !_parser.isBufferEmpty() || !_generator.isBufferEmpty();
- if (filled<0 || flushed<0)
- _endp.close();
- // System.err.println("flushed="+flushed+" filled="+filled+" more="+more+" endp="+_endp.isOpen());
+ // System.err.println("flushed="+flushed+" filled="+filled+" more="+more+" p.e="+_parser.isBufferEmpty()+" g.e="+_generator.isBufferEmpty());
+
+ if (filled<0 || flushed<0)
+ {
+ _endp.close();
+ break;
+ }
+
}
}
catch(IOException e)
{
- System.err.println(e);
+ e.printStackTrace();
throw e;
}
finally
{
- // TODO - not really the best way
- if (!_endp.isOpen())
+ if (_endp.isOpen())
+ _connector.persist(_endp);
+ else
+ // TODO - not really the best way
_websocket.onDisconnect();
}
}
@@ -115,24 +125,34 @@ public class WebSocketConnection implements Connection, WebSocket.Outbound
{
_generator.addFrame(frame,content,_maxIdleTimeMs);
_generator.flush();
+ _connector.persist(_endp);
}
public void sendMessage(byte frame, byte[] content) throws IOException
{
_generator.addFrame(frame,content,_maxIdleTimeMs);
_generator.flush();
+ _connector.persist(_endp);
}
public void sendMessage(byte frame, byte[] content, int offset, int length) throws IOException
{
_generator.addFrame(frame,content,offset,length,_maxIdleTimeMs);
_generator.flush();
+ _connector.persist(_endp);
}
- public void disconnect() throws IOException
+ public void disconnect()
{
- _generator.flush(_maxIdleTimeMs);
- _endp.close();
+ try
+ {
+ _generator.flush(_maxIdleTimeMs);
+ _endp.close();
+ }
+ catch(IOException e)
+ {
+ Log.ignore(e);
+ }
}
public void fill(Buffer buffer)
diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketHandler.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketHandler.java
index 77961b9adfe..e621d7118ff 100644
--- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketHandler.java
+++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketHandler.java
@@ -73,12 +73,17 @@ public abstract class WebSocketHandler extends HandlerWrapper
{
HttpConnection http = HttpConnection.getCurrentConnection();
ConnectedEndPoint endp = (ConnectedEndPoint)http.getEndPoint();
- WebSocketConnection connection = new WebSocketConnection(_buffers,endp,http.getTimeStamp(),websocket);
+ WebSocketConnection connection = new WebSocketConnection(http.getConnector(),_buffers,endp,http.getTimeStamp(),websocket);
+ String uri=request.getRequestURI();
+ String host=request.getHeader("Host");
+ String origin=request.getHeader("Origin");
+ origin=checkOrigin(request,host,origin);
+
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
- response.addHeader("WebSocket-Origin",request.getScheme()+"://"+request.getServerName());
- response.addHeader("WebSocket-Location","ws://"+request.getHeader("Host")+request.getRequestURI());
+ response.addHeader("WebSocket-Origin",origin);
+ response.addHeader("WebSocket-Location","ws://"+host+uri);
if (protocol!=null)
response.addHeader("WebSocket-Protocol",protocol);
response.sendError(101,"Web Socket Protocol Handshake");
@@ -101,6 +106,13 @@ public abstract class WebSocketHandler extends HandlerWrapper
}
}
+ protected String checkOrigin(HttpServletRequest request, String host, String origin)
+ {
+ if (origin==null)
+ origin=host;
+ return origin;
+ }
+
abstract protected WebSocket doWebSocketConnect(HttpServletRequest request,String protocol);
}
diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketParser.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketParser.java
index d118fcc207c..a463b507dc7 100644
--- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketParser.java
+++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketParser.java
@@ -73,6 +73,7 @@ public class WebSocketParser
int total_filled=0;
// Loop until an datagram call back or can't fill anymore
+ boolean progress=true;
while(true)
{
int length=_buffer.length();
@@ -92,7 +93,7 @@ public class WebSocketParser
{
int filled=_endp.isOpen()?_endp.fill(_buffer):-1;
if (filled<=0)
- return total_filled>0?total_filled:-1;
+ return total_filled;
total_filled+=filled;
length=_buffer.length();
}
diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketServlet.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketServlet.java
index 3d774403675..070453aa756 100644
--- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketServlet.java
+++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketServlet.java
@@ -15,19 +15,19 @@ import org.eclipse.jetty.server.HttpConnection;
/* ------------------------------------------------------------ */
/**
- * Servlet to ugrade connections to WebSocket
+ * Servlet to upgrade connections to WebSocket
*
* The request must have the correct upgrade headers, else it is
* handled as a normal servlet request.
*
* The initParameter "bufferSize" can be used to set the buffer size,
* which is also the max frame byte size (default 8192).
+ *
*/
public abstract class WebSocketServlet extends HttpServlet
{
WebSocketBuffers _buffers;
-
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.GenericServlet#init()
@@ -56,12 +56,17 @@ public abstract class WebSocketServlet extends HttpServlet
{
HttpConnection http = HttpConnection.getCurrentConnection();
ConnectedEndPoint endp = (ConnectedEndPoint)http.getEndPoint();
- WebSocketConnection connection = new WebSocketConnection(_buffers,endp,http.getTimeStamp(),websocket);
+ WebSocketConnection connection = new WebSocketConnection(http.getConnector(),_buffers,endp,http.getTimeStamp(),websocket);
+ String uri=request.getRequestURI();
+ String host=request.getHeader("Host");
+ String origin=request.getHeader("Origin");
+ origin=checkOrigin(request,host,origin);
+
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
- response.addHeader("WebSocket-Origin",request.getScheme()+"://"+request.getServerName());
- response.addHeader("WebSocket-Location","ws://"+request.getHeader("Host")+request.getRequestURI());
+ response.addHeader("WebSocket-Origin",origin);
+ response.addHeader("WebSocket-Location","ws://"+host+uri);
if (protocol!=null)
response.addHeader("WebSocket-Protocol",protocol);
response.sendError(101,"Web Socket Protocol Handshake");
@@ -81,6 +86,13 @@ public abstract class WebSocketServlet extends HttpServlet
else
super.service(request,response);
}
+
+ protected String checkOrigin(HttpServletRequest request, String host, String origin)
+ {
+ if (origin==null)
+ origin=host;
+ return origin;
+ }
abstract protected WebSocket doWebSocketConnect(HttpServletRequest request,String protocol);
diff --git a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/SimpleWebSocketServer.java b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/SimpleWebSocketServer.java
deleted file mode 100644
index 017c3c79588..00000000000
--- a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/SimpleWebSocketServer.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package org.eclipse.jetty.websocket;
-
-import java.io.IOException;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.eclipse.jetty.server.LocalConnector;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.DefaultHandler;
-import org.eclipse.jetty.server.handler.ResourceHandler;
-import org.eclipse.jetty.server.nio.SelectChannelConnector;
-import org.eclipse.jetty.util.TypeUtil;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.websocket.WebSocketTest.TestWebSocket;
-
-public class SimpleWebSocketServer extends Server
-{
- TestWebSocket _websocket;
- SelectChannelConnector _connector;
- WebSocketHandler _handler;
-
- public SimpleWebSocketServer()
- {
- _connector = new SelectChannelConnector();
- _connector.setPort(8080);
-
- addConnector(_connector);
- _handler= new WebSocketHandler()
- {
- @Override
- protected WebSocket doWebSocketConnect(HttpServletRequest request, String protocol)
- {
- _websocket = new TestWebSocket();
- return _websocket;
- }
- };
- ResourceHandler rh=new ResourceHandler();
- _handler.setHandler(rh);
- rh.setDirectoriesListed(true);
- rh.setResourceBase("./src/test/resources");
-
- setHandler(_handler);
- }
-
- /* ------------------------------------------------------------ */
- /* ------------------------------------------------------------ */
- class TestWebSocket implements WebSocket
- {
- Outbound _outbound;
-
- public void onConnect(Outbound outbound)
- {
- System.err.println("onConnect");
- _outbound=outbound;
-
- new Thread()
- {
- public void run()
- {
- for (int i=0;_outbound.isOpen()&& i<10;i++)
- {
- try
- {
- Thread.sleep(1000);
- System.err.println("send "+i);
- _outbound.sendMessage(SENTINEL_FRAME,"Roger That "+i);
- }
- catch (Exception e)
- {
- Log.warn(e);
- }
- }
- }
- }.start();
- }
-
- public void onMessage(byte frame, byte[] data,int offset, int length)
- {
- System.err.println("onMessage: "+TypeUtil.toHexString(data,offset,length));
- }
-
- public void onMessage(byte frame, String data)
- {
- System.err.println("onMessage: "+data);
- }
-
- public void onDisconnect()
- {
- System.err.println("onDisconnect");
- }
- }
-
-
- public static void main(String[] args)
- {
- try
- {
- SimpleWebSocketServer server = new SimpleWebSocketServer();
- server.start();
- server.join();
- }
- catch(Exception e)
- {
- Log.warn(e);
- }
- }
-
-
-
-}
diff --git a/jetty-websocket/src/test/resources/index.html b/jetty-websocket/src/test/resources/index.html
deleted file mode 100644
index 1a15f24e18e..00000000000
--- a/jetty-websocket/src/test/resources/index.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
WebSocket Test
-
-
\ No newline at end of file
diff --git a/test-jetty-webapp/pom.xml b/test-jetty-webapp/pom.xml
index 8c23bfc559a..b500b1c4041 100644
--- a/test-jetty-webapp/pom.xml
+++ b/test-jetty-webapp/pom.xml
@@ -117,6 +117,12 @@
servlet-api
provided
+
+ org.eclipse.jetty
+ jetty-websocket
+ ${project.version}
+ provided
+
org.eclipse.jetty
jetty-webapp
diff --git a/test-jetty-webapp/src/main/java/com/acme/ChatServlet.java b/test-jetty-webapp/src/main/java/com/acme/ChatServlet.java
index 432925162ca..f9f789ac9f8 100644
--- a/test-jetty-webapp/src/main/java/com/acme/ChatServlet.java
+++ b/test-jetty-webapp/src/main/java/com/acme/ChatServlet.java
@@ -28,7 +28,6 @@ import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationSupport;
-
// Simple asynchronous Chat room.
// This does not handle duplicate usernames or multiple frames/tabs from the same browser
// Some code is duplicated for clarity.
@@ -90,7 +89,7 @@ public class ChatServlet extends HttpServlet
return;
}
Member member = room.get(username);
- if (room==null)
+ if (member==null)
{
response.sendError(503);
return;
@@ -147,19 +146,22 @@ public class ChatServlet extends HttpServlet
throws IOException
{
Map room=_rooms.get(request.getPathInfo());
- // Post chat to all members
- for (Member m:room.values())
+ if (room!=null)
{
- synchronized (m)
+ // Post chat to all members
+ for (Member m:room.values())
{
- m._queue.add(username); // from
- m._queue.add(message); // chat
-
- // wakeup member if polling
- if (m._continuation!=null)
+ synchronized (m)
{
- m._continuation.resume();
- m._continuation=null;
+ m._queue.add(username); // from
+ m._queue.add(message); // chat
+
+ // wakeup member if polling
+ if (m._continuation!=null)
+ {
+ m._continuation.resume();
+ m._continuation=null;
+ }
}
}
}
@@ -168,111 +170,16 @@ public class ChatServlet extends HttpServlet
PrintWriter out=response.getWriter();
out.print("{action:\"chat\"}");
}
-
// Serve the HTML with embedded CSS and Javascript.
// This should be static content and should use real JS libraries.
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
- if (!request.getRequestURI().endsWith("/"))
- {
- response.sendRedirect(request.getRequestURI()+"/");
- return;
- }
if (request.getParameter("action")!=null)
- {
doPost(request,response);
- return;
- }
-
- response.setContentType("text/html");
- PrintWriter out=response.getWriter();
- out.println("");
- out.println(" async chat");
- out.println(" ");
- out.println(" ");
- out.println("");
- out.println("");
- out.println("");
- out.println("");
- out.println("");
+ else
+ getServletContext().getNamedDispatcher("default").forward(request,response);
}
}
diff --git a/test-jetty-webapp/src/main/java/com/acme/WebSocketChatServlet.java b/test-jetty-webapp/src/main/java/com/acme/WebSocketChatServlet.java
new file mode 100644
index 00000000000..4ba4b542042
--- /dev/null
+++ b/test-jetty-webapp/src/main/java/com/acme/WebSocketChatServlet.java
@@ -0,0 +1,73 @@
+package com.acme;
+
+import java.io.IOException;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.util.TypeUtil;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.websocket.WebSocket;
+import org.eclipse.jetty.websocket.WebSocketServlet;
+
+public class WebSocketChatServlet extends WebSocketServlet
+{
+ private final Set _members = new CopyOnWriteArraySet();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws javax.servlet.ServletException ,IOException
+ {
+ getServletContext().getNamedDispatcher("default").forward(request,response);
+ };
+
+ @Override
+ protected WebSocket doWebSocketConnect(HttpServletRequest request, String protocol)
+ {
+ return new ChatWebSocket();
+ }
+
+ /* ------------------------------------------------------------ */
+ /* ------------------------------------------------------------ */
+ class ChatWebSocket implements WebSocket
+ {
+ Outbound _outbound;
+
+ public void onConnect(Outbound outbound)
+ {
+ // Log.info(this+" onConnect");
+ _outbound=outbound;
+ _members.add(this);
+ }
+
+ public void onMessage(byte frame, byte[] data,int offset, int length)
+ {
+ // Log.info(this+" onMessage: "+TypeUtil.toHexString(data,offset,length));
+ }
+
+ public void onMessage(byte frame, String data)
+ {
+ // Log.info(this+" onMessage: "+data);
+ for (ChatWebSocket member : _members)
+ {
+ try
+ {
+ member._outbound.sendMessage(frame,data);
+ }
+ catch(IOException e)
+ {
+ Log.warn(e);
+ }
+ }
+ }
+
+ public void onDisconnect()
+ {
+ // Log.info(this+" onDisconnect");
+ _members.remove(this);
+ }
+ }
+}
diff --git a/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml b/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml
index d2abb3cb8e5..c962d53c99f 100644
--- a/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml
+++ b/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml
@@ -176,6 +176,17 @@
/chat/*
+
+ WSChat
+ com.acme.WebSocketChatServlet
+ 1
+
+
+
+ WSChat
+ /ws/*
+
+
Rewrite
diff --git a/test-jetty-webapp/src/main/webapp/chat/index.html b/test-jetty-webapp/src/main/webapp/chat/index.html
new file mode 100644
index 00000000000..adc33ef30d1
--- /dev/null
+++ b/test-jetty-webapp/src/main/webapp/chat/index.html
@@ -0,0 +1,85 @@
+
+ Async Chat
+
+
+
+
+
+
+
diff --git a/test-jetty-webapp/src/main/webapp/index.html b/test-jetty-webapp/src/main/webapp/index.html
index 0d6734f4520..efa81dc6be6 100644
--- a/test-jetty-webapp/src/main/webapp/index.html
+++ b/test-jetty-webapp/src/main/webapp/index.html
@@ -18,21 +18,19 @@ Commercial support for Jetty is available via w
This is a test context that serves:
diff --git a/test-jetty-webapp/src/main/webapp/ws/index.html b/test-jetty-webapp/src/main/webapp/ws/index.html
new file mode 100644
index 00000000000..bb239c2366d
--- /dev/null
+++ b/test-jetty-webapp/src/main/webapp/ws/index.html
@@ -0,0 +1,110 @@
+
+
+ WebSocket Chat
+
+
+
+
+
+
+
+
+This is a demonstration of the Jetty websocket server.
+
+
+
+
+
diff --git a/test-jetty-webapp/src/test/java/org/eclipse/jetty/DemoServer.java b/test-jetty-webapp/src/test/java/org/eclipse/jetty/DemoServer.java
deleted file mode 100644
index ef1d2452969..00000000000
--- a/test-jetty-webapp/src/test/java/org/eclipse/jetty/DemoServer.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package org.eclipse.jetty;
-
-import java.lang.management.ManagementFactory;
-
-import javax.management.MBeanServer;
-
-import org.eclipse.jetty.http.security.Password;
-import org.eclipse.jetty.jmx.MBeanContainer;
-import org.eclipse.jetty.security.HashLoginService;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.ContextHandlerCollection;
-import org.eclipse.jetty.server.nio.SelectChannelConnector;
-import org.eclipse.jetty.webapp.WebAppContext;
-
-public class DemoServer
-{
- public static void main(String[] args)
- throws Exception
- {
- if (args.length!=1)
- {
- System.err.println("Usage - java "+DemoServer.class+" webappdir|war");
- System.exit(1);
- }
-
- Server server = new Server();
-
- // setup JMX
- MBeanServer mbeanS = ManagementFactory.getPlatformMBeanServer();
- MBeanContainer mbeanC = new MBeanContainer(mbeanS);
- server.getContainer().addEventListener(mbeanC);
- server.addBean(mbeanC);
-
- // setup connector
- SelectChannelConnector connector = new SelectChannelConnector();
- connector.setPort(8080);
- server.addConnector(connector);
-
- // setup Login service
- HashLoginService login = new HashLoginService();
- login.putUser("jetty",new Password("password"),new String[]{"user"});
- login.putUser("admin",new Password("password"),new String[]{"user","admin"});
- server.addBean(login);
-
- // ContextHandlerCollection
- ContextHandlerCollection contexts = new ContextHandlerCollection();
- server.setHandler(contexts);
-
- // setup webapp
- WebAppContext context = new WebAppContext();
- context.setWar(args[0]);
- context.setDefaultsDescriptor("../jetty-webapp/src/main/config/etc/webdefault.xml");
- contexts.addHandler(context);
-
-
- // start the server
- server.start();
- System.err.println(server.dump());
- server.join();
- }
-}
diff --git a/test-jetty-webapp/src/test/java/com/acme/DispatchServletTest.java b/test-jetty-webapp/src/test/java/org/eclipse/jetty/DispatchServletTest.java
similarity index 98%
rename from test-jetty-webapp/src/test/java/com/acme/DispatchServletTest.java
rename to test-jetty-webapp/src/test/java/org/eclipse/jetty/DispatchServletTest.java
index 07e1a40e4b8..113b07e86e9 100644
--- a/test-jetty-webapp/src/test/java/com/acme/DispatchServletTest.java
+++ b/test-jetty-webapp/src/test/java/org/eclipse/jetty/DispatchServletTest.java
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================
-package com.acme;
+package org.eclipse.jetty;
import junit.framework.TestCase;
@@ -19,6 +19,8 @@ import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.testing.ServletTester;
+import com.acme.DispatchServlet;
+
/**
* Simple tests against DispatchServlet.
*/
diff --git a/test-jetty-webapp/src/test/java/org/eclipse/jetty/DumpServer.java b/test-jetty-webapp/src/test/java/org/eclipse/jetty/DumpServer.java
deleted file mode 100644
index 827792e7761..00000000000
--- a/test-jetty-webapp/src/test/java/org/eclipse/jetty/DumpServer.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.eclipse.jetty;
-
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.DebugHandler;
-import org.eclipse.jetty.servlet.FilterHolder;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.eclipse.jetty.servlets.IncludableGzipFilter;
-
-import com.acme.Dump;
-
-
-public class DumpServer
-{
- public static void main(String[] args)
- throws Exception
- {
- Server server = new Server(8080);
- DebugHandler debug = new DebugHandler();
- debug.setOutputStream(System.err);
- server.setHandler(debug);
-
- ServletContextHandler context = new ServletContextHandler(debug,"/",ServletContextHandler.SESSIONS);
- FilterHolder gzip=context.addFilter(IncludableGzipFilter.class,"/*",0);
- gzip.setInitParameter("uncheckedPrintWriter","true");
- context.addServlet(new ServletHolder(new Dump()), "/*");
-
- server.start();
- server.join();
- }
-
-}
diff --git a/test-jetty-webapp/src/test/java/org/eclipse/jetty/TestServer.java b/test-jetty-webapp/src/test/java/org/eclipse/jetty/TestServer.java
new file mode 100644
index 00000000000..c613c2ecc28
--- /dev/null
+++ b/test-jetty-webapp/src/test/java/org/eclipse/jetty/TestServer.java
@@ -0,0 +1,106 @@
+// ========================================================================
+// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty;
+
+import java.lang.management.ManagementFactory;
+
+import org.eclipse.jetty.jmx.MBeanContainer;
+import org.eclipse.jetty.security.HashLoginService;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.NCSARequestLog;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.ContextHandlerCollection;
+import org.eclipse.jetty.server.handler.DefaultHandler;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.eclipse.jetty.server.handler.RequestLogHandler;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+public class TestServer
+{
+ public static void main(String[] args) throws Exception
+ {
+ String jetty_home = System.getProperty("jetty.home","../jetty-distribution/target/distribution");
+ System.setProperty("jetty.home",jetty_home);
+
+ Server server = new Server();
+
+ // Setup JMX
+ MBeanContainer mbContainer=new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
+ server.getContainer().addEventListener(mbContainer);
+ server.addBean(mbContainer);
+ mbContainer.addBean(Log.getLog());
+
+
+ // Setup Threadpool
+ QueuedThreadPool threadPool = new QueuedThreadPool();
+ threadPool.setMaxThreads(100);
+ server.setThreadPool(threadPool);
+
+ // Setup Connectors
+ SelectChannelConnector connector = new SelectChannelConnector();
+ connector.setPort(8080);
+ connector.setMaxIdleTime(30000);
+ connector.setConfidentialPort(8443);
+ server.setConnectors(new Connector[]
+ { connector });
+
+ SslSelectChannelConnector ssl_connector = new SslSelectChannelConnector();
+ ssl_connector.setPort(8443);
+ ssl_connector.setKeystore(jetty_home + "/etc/keystore");
+ ssl_connector.setPassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
+ ssl_connector.setKeyPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");
+ ssl_connector.setTruststore(jetty_home + "/etc/keystore");
+ ssl_connector.setTrustPassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
+ server.addConnector(ssl_connector);
+
+ HandlerCollection handlers = new HandlerCollection();
+ ContextHandlerCollection contexts = new ContextHandlerCollection();
+ RequestLogHandler requestLogHandler = new RequestLogHandler();
+ handlers.setHandlers(new Handler[]
+ { contexts, new DefaultHandler(), requestLogHandler });
+ server.setHandler(handlers);
+
+
+ // Setup deployers
+
+ HashLoginService login = new HashLoginService();
+ login.setName("Test Realm");
+ login.setConfig(jetty_home + "/etc/realm.properties");
+ server.addBean(login);
+
+ NCSARequestLog requestLog = new NCSARequestLog(jetty_home + "/logs/jetty-yyyy_mm_dd.log");
+ requestLog.setExtended(false);
+ requestLogHandler.setRequestLog(requestLog);
+
+ server.setStopAtShutdown(true);
+ server.setSendServerVersion(true);
+
+
+ WebAppContext webapp = new WebAppContext();
+ webapp.setParentLoaderPriority(true);
+ webapp.setResourceBase("./src/main/webapp");
+
+ contexts.addHandler(webapp);
+
+
+ server.start();
+ server.join();
+ }
+
+}