342504 Scanner Listener
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2999 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
parent
e5bad59c14
commit
d3c5eddd79
|
@ -1,3 +1,6 @@
|
|||
jetty-7.4.0-SNAPSHOT
|
||||
+ 342504 Scanner Listener
|
||||
|
||||
jetty-7.4.0.RC0
|
||||
+ 324110 Added test harnesses for merging of QueryStrings.
|
||||
+ 337685 Update websocket API in preparation for draft -07
|
||||
|
|
|
@ -175,12 +175,6 @@ public abstract class ScanningAppProvider extends AbstractLifeCycle implements A
|
|||
return _deploymentManager;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Deprecated
|
||||
public Resource getMonitoredDir()
|
||||
{
|
||||
return _monitoredDir;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public Resource getMonitoredDirResource()
|
||||
|
@ -211,30 +205,18 @@ public abstract class ScanningAppProvider extends AbstractLifeCycle implements A
|
|||
{
|
||||
_deploymentManager = deploymentManager;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @deprecated use {@link #setMonitoredDirResource(Resource)}
|
||||
*/
|
||||
public void setMonitoredDir(Resource dir)
|
||||
{
|
||||
setMonitoredDirResource(dir);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @deprecated use {@link #setMonitoredDirName(String)}
|
||||
*/
|
||||
public void setMonitoredDir(String dir)
|
||||
{
|
||||
setMonitoredDirName(dir);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setMonitoredDirResource(Resource contextsDir)
|
||||
{
|
||||
_monitoredDir = contextsDir;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void addScannerListener(Scanner.Listener listener)
|
||||
{
|
||||
_scanner.addListener(listener);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
|
|
@ -16,9 +16,14 @@
|
|||
package org.eclipse.jetty.deploy.providers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.eclipse.jetty.deploy.AppProvider;
|
||||
import org.eclipse.jetty.deploy.DeploymentManager;
|
||||
import org.eclipse.jetty.deploy.test.XmlConfiguredJetty;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.eclipse.jetty.util.Scanner;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
|
@ -30,9 +35,11 @@ import org.junit.Test;
|
|||
*/
|
||||
public class ScanningAppProviderRuntimeUpdatesTest
|
||||
{
|
||||
@Rule
|
||||
public TestingDir testdir = new TestingDir();
|
||||
@Rule
|
||||
public TestingDir testdir = new TestingDir();
|
||||
private static XmlConfiguredJetty jetty;
|
||||
private final AtomicInteger _scans = new AtomicInteger();
|
||||
private int _providers;
|
||||
|
||||
@Before
|
||||
public void setupEnvironment() throws Exception
|
||||
|
@ -46,6 +53,24 @@ public class ScanningAppProviderRuntimeUpdatesTest
|
|||
|
||||
// Start it
|
||||
jetty.start();
|
||||
|
||||
// monitor tick
|
||||
DeploymentManager dm = jetty.getServer().getBeans(DeploymentManager.class).get(0);
|
||||
for (AppProvider provider : dm.getAppProviders())
|
||||
{
|
||||
if (provider instanceof ScanningAppProvider)
|
||||
{
|
||||
_providers++;
|
||||
((ScanningAppProvider)provider).addScannerListener(new Scanner.ScanListener()
|
||||
{
|
||||
public void scan()
|
||||
{
|
||||
_scans.incrementAndGet();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -55,6 +80,23 @@ public class ScanningAppProviderRuntimeUpdatesTest
|
|||
jetty.stop();
|
||||
}
|
||||
|
||||
public void waitForDirectoryScan()
|
||||
{
|
||||
int scan=_scans.get()+2*_providers;
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(200);
|
||||
}
|
||||
catch(InterruptedException e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
while(_scans.get()<scan);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple webapp deployment after startup of server.
|
||||
*/
|
||||
|
@ -64,7 +106,7 @@ public class ScanningAppProviderRuntimeUpdatesTest
|
|||
jetty.copyWebapp("foo-webapp-1.war","foo.war");
|
||||
jetty.copyContext("foo.xml","foo.xml");
|
||||
|
||||
jetty.waitForDirectoryScan();
|
||||
waitForDirectoryScan();
|
||||
|
||||
jetty.assertWebAppContextsExists("/foo");
|
||||
}
|
||||
|
@ -78,13 +120,13 @@ public class ScanningAppProviderRuntimeUpdatesTest
|
|||
jetty.copyWebapp("foo-webapp-1.war","foo.war");
|
||||
jetty.copyContext("foo.xml","foo.xml");
|
||||
|
||||
jetty.waitForDirectoryScan();
|
||||
waitForDirectoryScan();
|
||||
|
||||
jetty.assertWebAppContextsExists("/foo");
|
||||
|
||||
jetty.removeContext("foo.xml");
|
||||
|
||||
jetty.waitForDirectoryScan();
|
||||
waitForDirectoryScan();
|
||||
|
||||
// FIXME: hot undeploy with removal not working! - jetty.assertNoWebAppContexts();
|
||||
}
|
||||
|
@ -98,7 +140,7 @@ public class ScanningAppProviderRuntimeUpdatesTest
|
|||
jetty.copyWebapp("foo-webapp-1.war","foo.war");
|
||||
jetty.copyContext("foo.xml","foo.xml");
|
||||
|
||||
jetty.waitForDirectoryScan();
|
||||
waitForDirectoryScan();
|
||||
|
||||
jetty.assertWebAppContextsExists("/foo");
|
||||
|
||||
|
@ -111,8 +153,8 @@ public class ScanningAppProviderRuntimeUpdatesTest
|
|||
jetty.copyWebapp("foo-webapp-2.war","foo.war");
|
||||
|
||||
// This should result in the existing foo.war being replaced with the new foo.war
|
||||
jetty.waitForDirectoryScan();
|
||||
jetty.waitForDirectoryScan();
|
||||
waitForDirectoryScan();
|
||||
waitForDirectoryScan();
|
||||
jetty.assertWebAppContextsExists("/foo");
|
||||
|
||||
// Test that webapp response contains "-2"
|
||||
|
|
|
@ -431,18 +431,4 @@ public class XmlConfiguredJetty
|
|||
_server.stop();
|
||||
}
|
||||
|
||||
|
||||
public void waitForDirectoryScan()
|
||||
{
|
||||
int ms = 2000;
|
||||
System.out.printf("Waiting %d milliseconds for AppProvider to process directory scan ...%n",ms);
|
||||
try
|
||||
{
|
||||
Thread.sleep(ms);
|
||||
}
|
||||
catch (InterruptedException ignore)
|
||||
{
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<Array type="org.eclipse.jetty.deploy.AppProvider">
|
||||
<Item>
|
||||
<New class="org.eclipse.jetty.deploy.providers.ContextProvider">
|
||||
<Set name="monitoredDir"><SystemProperty name="jetty.home" />/contexts</Set>
|
||||
<Set name="monitoredDirName"><SystemProperty name="jetty.home" />/contexts</Set>
|
||||
<Set name="scanInterval">1</Set>
|
||||
<Set name="configurationManager">
|
||||
<New class="org.eclipse.jetty.deploy.FileConfigurationManager">
|
||||
|
@ -28,7 +28,7 @@
|
|||
</Item>
|
||||
<Item>
|
||||
<New class="org.eclipse.jetty.deploy.providers.WebAppProvider">
|
||||
<Set name="monitoredDir"><SystemProperty name="jetty.home" />/webapps</Set>
|
||||
<Set name="monitoredDirName"><SystemProperty name="jetty.home" />/webapps</Set>
|
||||
<Set name="scanInterval">1</Set>
|
||||
<Set name="contextXmlDir"><SystemProperty name="jetty.home" />/contexts</Set>
|
||||
</New>
|
||||
|
|
|
@ -104,6 +104,10 @@ public class Scanner extends AbstractLifeCycle
|
|||
{
|
||||
}
|
||||
|
||||
public interface ScanListener extends Listener
|
||||
{
|
||||
public void scan();
|
||||
}
|
||||
|
||||
public interface DiscreteListener extends Listener
|
||||
{
|
||||
|
@ -391,6 +395,23 @@ public class Scanner extends AbstractLifeCycle
|
|||
_prevScan.clear();
|
||||
_prevScan.putAll(_currentScan);
|
||||
reportScanEnd(_scanCount);
|
||||
|
||||
for (Listener l : _listeners)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (l instanceof ScanListener)
|
||||
((ScanListener)l).scan();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
catch (Error e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.ResourceHandler;
|
||||
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
|
@ -18,8 +19,9 @@ public class TestServer extends Server
|
|||
|
||||
WebSocket _websocket;
|
||||
SelectChannelConnector _connector;
|
||||
WebSocketHandler _handler;
|
||||
ConcurrentLinkedQueue<TestWebSocket> _webSockets = new ConcurrentLinkedQueue<TestWebSocket>();
|
||||
WebSocketHandler _wsHandler;
|
||||
ResourceHandler _rHandler;
|
||||
ConcurrentLinkedQueue<TestWebSocket> _broadcast = new ConcurrentLinkedQueue<TestWebSocket>();
|
||||
|
||||
public TestServer(int port)
|
||||
{
|
||||
|
@ -27,7 +29,7 @@ public class TestServer extends Server
|
|||
_connector.setPort(port);
|
||||
|
||||
addConnector(_connector);
|
||||
_handler = new WebSocketHandler()
|
||||
_wsHandler = new WebSocketHandler()
|
||||
{
|
||||
public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol)
|
||||
{
|
||||
|
@ -56,19 +58,38 @@ public class TestServer extends Server
|
|||
}
|
||||
};
|
||||
|
||||
setHandler(_handler);
|
||||
setHandler(_wsHandler);
|
||||
|
||||
_rHandler=new ResourceHandler();
|
||||
_rHandler.setDirectoriesListed(true);
|
||||
_rHandler.setResourceBase(".");
|
||||
_wsHandler.setHandler(_rHandler);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isVerbose()
|
||||
{
|
||||
return _verbose;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setVerbose(boolean verbose)
|
||||
{
|
||||
_verbose = verbose;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setResourceBase(String dir)
|
||||
{
|
||||
_rHandler.setResourceBase(dir);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public String getResourceBase()
|
||||
{
|
||||
return _rHandler.getResourceBase();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -84,12 +105,14 @@ public class TestServer extends Server
|
|||
public void onConnect(Connection connection)
|
||||
{
|
||||
_connection = connection;
|
||||
_webSockets.add(this);
|
||||
if (_verbose)
|
||||
System.err.printf("%s#onConnect %s\n",this.getClass().getSimpleName(),connection);
|
||||
}
|
||||
|
||||
public void onDisconnect(int code,String message)
|
||||
{
|
||||
_webSockets.remove(this);
|
||||
if (_verbose)
|
||||
System.err.printf("%s#onDisonnect %d %s\n",this.getClass().getSimpleName(),code,message);
|
||||
}
|
||||
|
||||
public boolean onFrame(byte flags, byte opcode, byte[] data, int offset, int length)
|
||||
|
@ -160,11 +183,25 @@ public class TestServer extends Server
|
|||
/* ------------------------------------------------------------ */
|
||||
class TestEchoBroadcastWebSocket extends TestWebSocket
|
||||
{
|
||||
@Override
|
||||
public void onConnect(Connection connection)
|
||||
{
|
||||
super.onConnect(connection);
|
||||
_broadcast.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnect(int code,String message)
|
||||
{
|
||||
super.onDisconnect(code,message);
|
||||
_broadcast.remove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(byte[] data, int offset, int length)
|
||||
{
|
||||
super.onMessage(data,offset,length);
|
||||
for (TestWebSocket ws : _webSockets)
|
||||
for (TestWebSocket ws : _broadcast)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -172,6 +209,7 @@ public class TestServer extends Server
|
|||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_broadcast.remove(ws);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
@ -181,7 +219,7 @@ public class TestServer extends Server
|
|||
public void onMessage(final String data)
|
||||
{
|
||||
super.onMessage(data);
|
||||
for (TestWebSocket ws : _webSockets)
|
||||
for (TestWebSocket ws : _broadcast)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -189,6 +227,7 @@ public class TestServer extends Server
|
|||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_broadcast.remove(ws);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
@ -286,17 +325,19 @@ public class TestServer extends Server
|
|||
private static void usage()
|
||||
{
|
||||
System.err.println("java -cp CLASSPATH "+TestServer.class+" [ OPTIONS ]");
|
||||
System.err.println(" -p|--port PORT ");
|
||||
System.err.println(" -p|--port PORT (default 8080)");
|
||||
System.err.println(" -v|--verbose ");
|
||||
System.err.println(" -d|--docroot file (default '.')");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
public static void main(String... args)
|
||||
{
|
||||
try
|
||||
{
|
||||
int port=8080;
|
||||
boolean verbose=false;
|
||||
String docroot=".";
|
||||
|
||||
for (int i=0;i<args.length;i++)
|
||||
{
|
||||
|
@ -305,6 +346,8 @@ public class TestServer extends Server
|
|||
port=Integer.parseInt(args[++i]);
|
||||
else if ("-v".equals(a)||"--verbose".equals(a))
|
||||
verbose=true;
|
||||
else if ("-d".equals(a)||"--docroot".equals(a))
|
||||
docroot=args[++i];
|
||||
else if (a.startsWith("-"))
|
||||
usage();
|
||||
}
|
||||
|
@ -312,6 +355,7 @@ public class TestServer extends Server
|
|||
|
||||
TestServer server = new TestServer(port);
|
||||
server.setVerbose(verbose);
|
||||
server.setResourceBase(docroot);
|
||||
server.start();
|
||||
server.join();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
|
||||
<html><head>
|
||||
<title>WebSocket Chat</title>
|
||||
<script type='text/javascript'>
|
||||
|
||||
if (!window.WebSocket)
|
||||
alert("WebSocket not supported by this browser");
|
||||
|
||||
function $() { return document.getElementById(arguments[0]); }
|
||||
function $F() { return document.getElementById(arguments[0]).value; }
|
||||
|
||||
function getKeyCode(ev) { if (window.event) return window.event.keyCode; return ev.keyCode; }
|
||||
|
||||
var room = {
|
||||
join: function(name) {
|
||||
this._username=name;
|
||||
var location = document.location.toString().replace('http://','ws://').replace('https://','wss://');
|
||||
this._ws=new WebSocket(location,"org.ietf.websocket.test-echo-broadcast");
|
||||
this._ws.onopen=this._onopen;
|
||||
this._ws.onmessage=this._onmessage;
|
||||
this._ws.onclose=this._onclose;
|
||||
},
|
||||
|
||||
_onopen: function(){
|
||||
$('join').className='hidden';
|
||||
$('joined').className='';
|
||||
$('phrase').focus();
|
||||
room._send(room._username,'has joined!');
|
||||
},
|
||||
|
||||
_send: function(user,message){
|
||||
user=user.replace(':','_');
|
||||
if (this._ws)
|
||||
this._ws.send(user+':'+message);
|
||||
},
|
||||
|
||||
chat: function(text) {
|
||||
if (text != null && text.length>0 )
|
||||
room._send(room._username,text);
|
||||
},
|
||||
|
||||
_onmessage: function(m) {
|
||||
if (m.data){
|
||||
var c=m.data.indexOf(':');
|
||||
var from=m.data.substring(0,c).replace('<','<').replace('>','>');
|
||||
var text=m.data.substring(c+1).replace('<','<').replace('>','>');
|
||||
|
||||
var chat=$('chat');
|
||||
var spanFrom = document.createElement('span');
|
||||
spanFrom.className='from';
|
||||
spanFrom.innerHTML=from+': ';
|
||||
var spanText = document.createElement('span');
|
||||
spanText.className='text';
|
||||
spanText.innerHTML=text;
|
||||
var lineBreak = document.createElement('br');
|
||||
chat.appendChild(spanFrom);
|
||||
chat.appendChild(spanText);
|
||||
chat.appendChild(lineBreak);
|
||||
chat.scrollTop = chat.scrollHeight - chat.clientHeight;
|
||||
}
|
||||
},
|
||||
|
||||
_onclose: function(m) {
|
||||
this._ws=null;
|
||||
$('join').className='';
|
||||
$('joined').className='hidden';
|
||||
$('username').focus();
|
||||
$('chat').innerHTML='';
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
</script>
|
||||
<style type='text/css'>
|
||||
div { border: 0px solid black; }
|
||||
div#chat { clear: both; width: 40em; height: 20ex; overflow: auto; background-color: #f0f0f0; padding: 4px; border: 1px solid black; }
|
||||
div#input { clear: both; width: 40em; padding: 4px; background-color: #e0e0e0; border: 1px solid black; border-top: 0px }
|
||||
input#phrase { width:30em; background-color: #e0f0f0; }
|
||||
input#username { width:14em; background-color: #e0f0f0; }
|
||||
div.hidden { display: none; }
|
||||
span.from { font-weight: bold; }
|
||||
span.alert { font-style: italic; }
|
||||
</style>
|
||||
</head><body>
|
||||
<div id='chat'></div>
|
||||
<div id='input'>
|
||||
<div id='join' >
|
||||
Username: <input id='username' type='text'/><input id='joinB' class='button' type='submit' name='join' value='Join'/>
|
||||
</div>
|
||||
<div id='joined' class='hidden'>
|
||||
Chat: <input id='phrase' type='text'/>
|
||||
<input id='sendB' class='button' type='submit' name='join' value='Send'/>
|
||||
</div>
|
||||
</div>
|
||||
<script type='text/javascript'>
|
||||
$('username').setAttribute('autocomplete','OFF');
|
||||
$('username').onkeyup = function(ev) { var keyc=getKeyCode(ev); if (keyc==13 || keyc==10) { room.join($F('username')); return false; } return true; } ;
|
||||
$('joinB').onclick = function(event) { room.join($F('username')); return false; };
|
||||
$('phrase').setAttribute('autocomplete','OFF');
|
||||
$('phrase').onkeyup = function(ev) { var keyc=getKeyCode(ev); if (keyc==13 || keyc==10) { room.chat($F('phrase')); $('phrase').value=''; return false; } return true; };
|
||||
$('sendB').onclick = function(event) { room.chat($F('phrase')); $('phrase').value=''; return false; };
|
||||
</script>
|
||||
|
||||
<p>
|
||||
This is a demonstration of the Jetty websocket server.
|
||||
</p>
|
||||
</body></html>
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue