diff options
20 files changed, 1391 insertions, 25 deletions
diff --git a/jetty-osgi/jetty-osgi-boot-jsp/pom.xml b/jetty-osgi/jetty-osgi-boot-jsp/pom.xml index 7d5bde4857..4497ca556b 100644 --- a/jetty-osgi/jetty-osgi-boot-jsp/pom.xml +++ b/jetty-osgi/jetty-osgi-boot-jsp/pom.xml @@ -25,12 +25,12 @@ <scope>provided</scope> </dependency> <dependency> - <groupId>org.eclipse</groupId> - <artifactId>osgi</artifactId> + <groupId>org.eclipse.osgi</groupId> + <artifactId>org.eclipse.osgi</artifactId> </dependency> <dependency> <groupId>org.eclipse.osgi</groupId> - <artifactId>services</artifactId> + <artifactId>org.eclipse.osgi.services</artifactId> </dependency> <dependency> <groupId>org.mortbay.jetty</groupId> diff --git a/jetty-osgi/jetty-osgi-boot-logback/pom.xml b/jetty-osgi/jetty-osgi-boot-logback/pom.xml index bc8ec5d678..b1aa85fdad 100644 --- a/jetty-osgi/jetty-osgi-boot-logback/pom.xml +++ b/jetty-osgi/jetty-osgi-boot-logback/pom.xml @@ -21,8 +21,8 @@ <scope>provided</scope> </dependency> <dependency> - <groupId>org.eclipse</groupId> - <artifactId>osgi</artifactId> + <groupId>org.eclipse.osgi</groupId> + <artifactId>org.eclipse.osgi</artifactId> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> @@ -30,7 +30,7 @@ </dependency> <dependency> <groupId>org.eclipse.osgi</groupId> - <artifactId>services</artifactId> + <artifactId>org.eclipse.osgi.services</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> diff --git a/jetty-osgi/jetty-osgi-boot-warurl/pom.xml b/jetty-osgi/jetty-osgi-boot-warurl/pom.xml index a46267a58f..b496d8896e 100644 --- a/jetty-osgi/jetty-osgi-boot-warurl/pom.xml +++ b/jetty-osgi/jetty-osgi-boot-warurl/pom.xml @@ -19,8 +19,8 @@ <artifactId>jetty-util</artifactId> </dependency> <dependency> - <groupId>org.eclipse</groupId> - <artifactId>osgi</artifactId> + <groupId>org.eclipse.osgi</groupId> + <artifactId>org.eclipse.osgi</artifactId> </dependency> </dependencies> diff --git a/jetty-osgi/jetty-osgi-boot/pom.xml b/jetty-osgi/jetty-osgi-boot/pom.xml index a9802b5df2..fa01b221eb 100644 --- a/jetty-osgi/jetty-osgi-boot/pom.xml +++ b/jetty-osgi/jetty-osgi-boot/pom.xml @@ -31,12 +31,12 @@ <artifactId>jetty-nested</artifactId> </dependency> <dependency> - <groupId>org.eclipse</groupId> - <artifactId>osgi</artifactId> + <groupId>org.eclipse.osgi</groupId> + <artifactId>org.eclipse.osgi</artifactId> </dependency> <dependency> <groupId>org.eclipse.osgi</groupId> - <artifactId>services</artifactId> + <artifactId>org.eclipse.osgi.services</artifactId> </dependency> </dependencies> diff --git a/jetty-osgi/jetty-osgi-equinoxtools/META-INF/MANIFEST.MF b/jetty-osgi/jetty-osgi-equinoxtools/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..6a67257a6a --- /dev/null +++ b/jetty-osgi/jetty-osgi-equinoxtools/META-INF/MANIFEST.MF @@ -0,0 +1,20 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Console +Bundle-SymbolicName: org.eclipse.jetty.osgi.equinoxtools +Bundle-Description: Example application: equinox console accesssible on the web +Bundle-Version: 7.4.2.qualifier +Bundle-Activator: org.eclipse.jetty.osgi.equinoxtools.WebEquinoxToolsActivator +Import-Package: javax.servlet;version="2.5.0", + javax.servlet.http;version="2.5.0", + org.eclipse.jetty.continuation;version="7.4.0", + org.eclipse.jetty.io;version="7.4.0", + org.eclipse.jetty.util;version="7.4.0", + org.eclipse.jetty.util.log;version="7.4.0", + org.eclipse.jetty.websocket;version="7.4.0", + org.eclipse.osgi.framework.console;version="1.1.0", + org.osgi.framework;version="1.3.0", + org.osgi.service.http;version="1.2.0", + org.osgi.util.tracker;version="1.3.0" +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 + diff --git a/jetty-osgi/jetty-osgi-equinoxtools/build.properties b/jetty-osgi/jetty-osgi-equinoxtools/build.properties new file mode 100644 index 0000000000..34d2e4d2da --- /dev/null +++ b/jetty-osgi/jetty-osgi-equinoxtools/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/jetty-osgi/jetty-osgi-equinoxtools/equinoxconsole/index.html b/jetty-osgi/jetty-osgi-equinoxtools/equinoxconsole/index.html new file mode 100644 index 0000000000..4deba32c28 --- /dev/null +++ b/jetty-osgi/jetty-osgi-equinoxtools/equinoxconsole/index.html @@ -0,0 +1,85 @@ +<html><head> + <title>Async Equinox Console</title> + <script type='text/javascript'> + 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; } + function xhr(method,uri,body,handler) { + var req=(window.XMLHttpRequest)?new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP'); + req.onreadystatechange=function() { if (req.readyState==4 && handler) { eval('var o='+req.responseText);handler(o);} } + req.open(method,uri,true); + req.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); + req.send(body); + }; + function send(action,user,message,handler){ + if (message) message=message.replace('%','%25').replace('&','%26').replace('=','%3D'); + if (user) user=user.replace('%','%25').replace('&','%26').replace('=','%3D'); + xhr('POST','chat','action='+action+'&user='+user+'&message='+message,handler); + }; + + var room = { + join: function(name) { + this._username=name; + $('join').className='hidden'; + $('joined').className=''; + $('phrase').focus(); + send('join', room._username,null); + send('chat', room._username,'has joined!'); + send('poll', room._username,null, room._poll); + }, + chat: function(text) { + if (text != null && text.length>0 ) + send('chat',room._username,text); + }, + _poll: function(m) { + //console.debug(m); + if (m.chat){ + var chat=document.getElementById('chat'); + var spanFrom = document.createElement('span'); + spanFrom.className='from'; + spanFrom.innerHTML=m.from+' '; + var spanText = document.createElement('span'); + spanText.className='text'; + spanText.innerHTML=m.chat; + var lineBreak = document.createElement('br'); + chat.appendChild(spanFrom); + chat.appendChild(spanText); + chat.appendChild(lineBreak); + chat.scrollTop = chat.scrollHeight - chat.clientHeight; + } + if (m.action=='poll') + send('poll', room._username,null, room._poll); + }, + _end:'' + }; + </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'> + OSGi: <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> +</body></html> diff --git a/jetty-osgi/jetty-osgi-equinoxtools/equinoxconsole/ws/index.html b/jetty-osgi/jetty-osgi-equinoxtools/equinoxconsole/ws/index.html new file mode 100644 index 0000000000..4d5acc96d7 --- /dev/null +++ b/jetty-osgi/jetty-osgi-equinoxtools/equinoxconsole/ws/index.html @@ -0,0 +1,109 @@ +<html><head> + <title>Equinox Console (WebSocket)</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://').replace('/index.html',''); + this._ws=new WebSocket(location); + 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> + + + diff --git a/jetty-osgi/jetty-osgi-equinoxtools/pom.xml b/jetty-osgi/jetty-osgi-equinoxtools/pom.xml new file mode 100644 index 0000000000..9db6231e71 --- /dev/null +++ b/jetty-osgi/jetty-osgi-equinoxtools/pom.xml @@ -0,0 +1,96 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <parent> + <groupId>org.eclipse.jetty.osgi</groupId> + <artifactId>jetty-osgi-project</artifactId> + <version>7.4.2-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <modelVersion>4.0.0</modelVersion> + <artifactId>jetty-osgi-equinoxtools</artifactId> + <name>Jetty :: OSGi :: Example Equinox Tools</name> + <description>Jetty OSGi Example Equinox Tools</description> + <properties> + <bundle-symbolic-name>${project.groupId}.equinoxtools</bundle-symbolic-name> + </properties> + <dependencies> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-webapp</artifactId> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-continuation</artifactId> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-websocket</artifactId> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-servlet</artifactId> + </dependency> + <dependency> + <groupId>org.eclipse.osgi</groupId> + <artifactId>org.eclipse.osgi</artifactId> + </dependency> + <dependency> + <groupId>org.eclipse.osgi</groupId> + <artifactId>org.eclipse.osgi.services</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-antrun-plugin</artifactId> + <executions> + <execution> + <phase>process-resources</phase> + <configuration> + <tasks> + <replace file="target/classes/META-INF/MANIFEST.MF" token="Bundle-Version: 7.4.2.qualifier" value="Bundle-Version: ${parsedVersion.osgiVersion}" /> + <copy todir="target/classes/equinoxconsole"> + <fileset dir="equinoxconsole" /> + </copy> + </tasks> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <executions> + <execution> + <id>artifact-jar</id> + <goals> + <goal>jar</goal> + </goals> + </execution> + <execution> + <id>test-jar</id> + <goals> + <goal>test-jar</goal> + </goals> + </execution> + </executions> + <configuration> + <archive> + <manifestFile>target/classes/META-INF/MANIFEST.MF</manifestFile> + </archive> + </configuration> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>findbugs-maven-plugin</artifactId> + <configuration> + <onlyAnalyze>org.eclipse.jetty.osgi.equinoxtools.*</onlyAnalyze> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/WebEquinoxToolsActivator.java b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/WebEquinoxToolsActivator.java new file mode 100644 index 0000000000..23de6fd8a5 --- /dev/null +++ b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/WebEquinoxToolsActivator.java @@ -0,0 +1,127 @@ +// ======================================================================== +// Copyright (c) 2006-2011 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.osgi.equinoxtools; + +import javax.servlet.ServletException; + +import org.eclipse.jetty.osgi.equinoxtools.console.EquinoxChattingSupport; +import org.eclipse.jetty.osgi.equinoxtools.console.EquinoxConsoleContinuationServlet; +import org.eclipse.jetty.osgi.equinoxtools.console.EquinoxConsoleSyncServlet; +import org.eclipse.jetty.osgi.equinoxtools.console.EquinoxConsoleWebSocketServlet; +import org.eclipse.jetty.osgi.equinoxtools.console.WebConsoleSession; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.osgi.framework.console.ConsoleSession; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.service.http.HttpService; +import org.osgi.service.http.NamespaceException; +import org.osgi.util.tracker.ServiceTracker; +import org.osgi.util.tracker.ServiceTrackerCustomizer; + +/** + * When started will register on the HttpService 3 servlets for 3 different styles of equinox consoles. + */ +public class WebEquinoxToolsActivator implements BundleActivator +{ + + private static BundleContext context; + public static BundleContext getContext() + { + return context; + } + + private HttpService _httpService; + private ServiceTracker _tracker; + private EquinoxChattingSupport _equinoxChattingSupport; + + + /* + * (non-Javadoc) + * + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext bundleContext) throws Exception + { + WebEquinoxToolsActivator.context = bundleContext; + + ServiceTrackerCustomizer httpServiceTrackerCustomizer = new ServiceTrackerCustomizer() + { + @Override + public void removedService(ServiceReference reference, Object service) + { + _httpService = null; + } + + @Override + public void modifiedService(ServiceReference reference, Object service) + { + _httpService = (HttpService)context.getService(reference); + } + + @Override + public Object addingService(ServiceReference reference) + { + _httpService = (HttpService)context.getService(reference); + try + { + //TODO; some effort to use the same console session on the 2 async console servlets? + + //websocket: +// WebConsoleSession wsSession = new WebConsoleSession(); +// WebEquinoxConsoleActivator.context.registerService(ConsoleSession.class.getName(), wsSession, null); +// EquinoxChattingSupport wsEquinoxChattingSupport = new EquinoxChattingSupport(wsSession); + _httpService.registerResources("/equinoxconsole/ws/index.html","/equinoxconsole/ws/index.html",null); + _httpService.registerServlet("/equinoxconsole/ws",new EquinoxConsoleWebSocketServlet(/*wsSession, wsEquinoxChattingSupport*/),null,null); + + //continuations: +// WebConsoleSession contSession = new WebConsoleSession(); +// WebEquinoxConsoleActivator.context.registerService(ConsoleSession.class.getName(), contSession, null); +// EquinoxChattingSupport contEquinoxChattingSupport = new EquinoxChattingSupport(contSession); + _httpService.registerResources("/equinoxconsole/index.html","/equinoxconsole/index.html",null); + _httpService.registerServlet("/equinoxconsole",new EquinoxConsoleContinuationServlet(/*contSession, contEquinoxChattingSupport*/),null,null); + + //legacy synchroneous; keep it in a separate console session. + WebConsoleSession syncSession = new WebConsoleSession(); + WebEquinoxToolsActivator.context.registerService(ConsoleSession.class.getName(), syncSession, null); + _httpService.registerServlet("/equinoxconsole/sync",new EquinoxConsoleSyncServlet(syncSession),null,null); + } + catch (ServletException e) + { + Log.warn(e); + } + catch (NamespaceException e) + { + Log.warn(e); + } + return _httpService; + } + }; + + _tracker = new ServiceTracker(context,HttpService.class.getName(),httpServiceTrackerCustomizer); + _tracker.open(); + } + + /* + * (non-Javadoc) + * + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext bundleContext) throws Exception + { + _tracker.close(); + WebEquinoxToolsActivator.context = null; + } + + +} diff --git a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxChattingSupport.java b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxChattingSupport.java new file mode 100644 index 0000000000..fbb9cfaa1a --- /dev/null +++ b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxChattingSupport.java @@ -0,0 +1,150 @@ +// ======================================================================== +// Copyright (c) 2006-2011 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.osgi.equinoxtools.console; + +import java.util.LinkedList; +import java.util.Queue; + +import org.eclipse.jetty.osgi.equinoxtools.console.WebConsoleWriterOutputStream.OnFlushListener; + +/** + * Processing of the messages to be received and sent to the chat servlets. + * Made to be extended for filtering of the messages and commands. + */ +public class EquinoxChattingSupport +{ + + private WebConsoleSession _consoleSession; + + public EquinoxChattingSupport(WebConsoleSession consoleSession) + { + _consoleSession = consoleSession; + } + + /** + * Split the output into multiple lines. + * Format them for the json messages sent to the chat. + * Empties the console output from what is already displayed in the chat. + * @return The lines to add to the message queue of each client. + */ + protected Queue<String> processConsoleOutput(boolean escape, OnFlushListener onflush) + { + Queue<String> result = new LinkedList<String>(); + String toDisplay = _consoleSession.getOutputAsWriter().getBuffer().toString(); + //the last listener to be called is in charge of clearing the console. + boolean clearConsole = _consoleSession.getOnFlushListeners().indexOf(onflush) == _consoleSession.getOnFlushListeners().size(); + if (clearConsole) + { + _consoleSession.clearOutput(); + } + boolean lastLineIsComplete = toDisplay.endsWith("\n") || toDisplay.endsWith("\r"); + String[] lines = toDisplay.split("\n"); + String lastLine = lastLineIsComplete ? null : lines[lines.length-1]; + if (clearConsole) + { + _consoleSession.getOutputAsWriter().append(lastLine); + } + for (int lnNb = 0; lnNb < (lastLineIsComplete ? lines.length : lines.length-1); lnNb++) + { + String line = lines[lnNb]; + while (line.trim().startsWith("null")) + {//hum.. + line = line.trim().substring("null".length()).trim(); + } + if (line.startsWith("osgi>")) + { + result.add("osgi>"); + result.add(escape ? jsonEscapeString(line.substring("osgi>".length())) : line.substring("osgi>".length())); + } + else + { + result.add(" "); + result.add(escape ? jsonEscapeString(line) : line); + } + } + return result; + } + + /** + * http://www.ietf.org/rfc/rfc4627.txt + * @param str + * @return The same string escaped according to the JSON RFC. + */ + public static String jsonEscapeString(String str) + { + StringBuilder sb = new StringBuilder(); + char[] asChars = str.toCharArray(); + for (char ch : asChars) + { + switch (ch) + { + //the reserved characters + case '"': + sb.append("\\\""); + break; + case '\\': + sb.append("\\\\"); + break; + case '\b': + sb.append("\\b"); + break; + case '\f': + sb.append("\\f"); + break; + case '\n': + sb.append("\\n"); + break; + case '\r': + sb.append("\\r"); + break; + case '\t': + sb.append("\\t"); + break; + case '/': + sb.append("\\/"); + break; + default: + //The non reserved characters + if (ch >= '\u0000' && ch <= '\u001F') + { + //escape as a unicode number when out of range. + String ss = Integer.toHexString(ch); + sb.append("\\u"); + for (int i = 0; i < 4 - ss.length(); i++) + { + //padding + sb.append('0'); + } + sb.append(ss.toUpperCase()); + } + else + { + sb.append(ch); + } + } + } + return sb.toString(); + } + + public void broadcast(OnFlushListener source) + { + for (OnFlushListener onflush : _consoleSession.getOnFlushListeners()) + { + if (onflush != source) + { + onflush.onFlush(); + } + } + } + +} diff --git a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleContinuationServlet.java b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleContinuationServlet.java new file mode 100644 index 0000000000..41a4e933c5 --- /dev/null +++ b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleContinuationServlet.java @@ -0,0 +1,248 @@ +// ======================================================================== +// Copyright (c) 2006-2011 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.osgi.equinoxtools.console; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Queue; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.continuation.Continuation; +import org.eclipse.jetty.continuation.ContinuationSupport; +import org.eclipse.jetty.osgi.equinoxtools.WebEquinoxToolsActivator; +import org.eclipse.jetty.osgi.equinoxtools.console.WebConsoleWriterOutputStream.OnFlushListener; +import org.eclipse.osgi.framework.console.ConsoleSession; +import org.osgi.framework.Bundle; +import org.osgi.framework.FrameworkUtil; + +/** + * Async servlet with jetty continuations to interact with the equinox console. + * Ported from jetty's example 'ChatServlet' + */ +public class EquinoxConsoleContinuationServlet extends HttpServlet implements OnFlushListener +{ + + private static final long serialVersionUID = 1L; + private Map<String,ConsoleUser> _consoleUsers = new HashMap<String, ConsoleUser>(); + private WebConsoleSession _consoleSession; + private EquinoxChattingSupport _support; + + /** + * @param consoleSession + */ + public EquinoxConsoleContinuationServlet() + { + + } + /** + * @param consoleSession + */ + public EquinoxConsoleContinuationServlet(WebConsoleSession consoleSession, EquinoxChattingSupport support) + { + _consoleSession = consoleSession; + _support = support; + } + @Override + public void init() throws ServletException + { + if (_consoleSession == null) + { + _consoleSession = new WebConsoleSession(); + WebEquinoxToolsActivator.getContext().registerService(ConsoleSession.class.getName(), _consoleSession, null); + } + if (_support == null) + { + _support = new EquinoxChattingSupport(_consoleSession); + } + _consoleSession.addOnFlushListener(this); + } + @Override + public void destroy() + { + _consoleSession.removeOnFlushListener(this); + } + + // 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.getParameter("action")!=null) + doPost(request,response); + else + response.sendRedirect("index.html"); + } + + // Handle Ajax calls from browser + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + // Ajax calls are form encoded + String action = request.getParameter("action"); + String message = request.getParameter("message"); + String username = request.getParameter("user"); + + if (action.equals("join")) + join(request,response,username); + else if (action.equals("poll")) + poll(request,response,username); + else if (action.equals("chat")) + chat(request,response,username,message); + } + + private synchronized void join(HttpServletRequest request,HttpServletResponse response,String username) + throws IOException + { + ConsoleUser member = new ConsoleUser(username); + _consoleUsers.put(username,member); + response.setContentType("text/json;charset=utf-8"); + PrintWriter out=response.getWriter(); + out.print("{action:\"join\"}"); + } + + private synchronized void poll(HttpServletRequest request,HttpServletResponse response,String username) + throws IOException + { + ConsoleUser member = _consoleUsers.get(username); + if (member==null) + { + response.sendError(503); + return; + } + + synchronized(member) + { + if (member.getMessageQueue().size()>0) + { + // Send one chat message + response.setContentType("text/json;charset=utf-8"); + StringBuilder buf=new StringBuilder(); + + buf.append("{\"action\":\"poll\","); + buf.append("\"from\":\""); + buf.append(member.getMessageQueue().poll()); + buf.append("\","); + + String message = member.getMessageQueue().poll(); + int quote=message.indexOf('"'); + while (quote>=0) + { + message=message.substring(0,quote)+'\\'+message.substring(quote); + quote=message.indexOf('"',quote+2); + } + buf.append("\"chat\":\""); + buf.append(message); + buf.append("\"}"); + byte[] bytes = buf.toString().getBytes("utf-8"); + response.setContentLength(bytes.length); + response.getOutputStream().write(bytes); + } + else + { + Continuation continuation = ContinuationSupport.getContinuation(request); + if (continuation.isInitial()) + { + // No chat in queue, so suspend and wait for timeout or chat + continuation.setTimeout(20000); + continuation.suspend(); + member.setContinuation(continuation); + } + else + { + // Timeout so send empty response + response.setContentType("text/json;charset=utf-8"); + PrintWriter out=response.getWriter(); + out.print("{action:\"poll\"}"); + } + } + } + } + + private synchronized void chat(HttpServletRequest request,HttpServletResponse response,String username,String message) + throws IOException + { + if (!message.endsWith("has joined!")) + { + _consoleSession.processCommand(message, false); + } + // Post chat to all members + onFlush(); + + response.setContentType("text/json;charset=utf-8"); + PrintWriter out=response.getWriter(); + out.print("{action:\"chat\"}"); + } + + /** + * Called right after the flush method on the output stream has been executed. + */ + public void onFlush() + { + Queue<String> pendingConsoleOutputMessages = _support.processConsoleOutput(true, this); + for (ConsoleUser m:_consoleUsers.values()) + { + synchronized (m) + { +// m.getMessageQueue().add("osgi>"); // from +// m.getMessageQueue().add("something was printed"); // chat + m.getMessageQueue().addAll(pendingConsoleOutputMessages); + + // wakeup member if polling + if (m.getContinuation()!=null) + { + m.getContinuation().resume(); + m.setContinuation(null); + } + } + } + } + + class ConsoleUser + { + private String _name; + private Continuation _continuation; + private Queue<String> _queue = new LinkedList<String>(); + + public ConsoleUser(String name) + { + _name = name; + } + + public String getName() + { + return _name; + } + + public void setContinuation(Continuation continuation) + { + _continuation = continuation; + } + + public Continuation getContinuation() + { + return _continuation; + } + public Queue<String> getMessageQueue() + { + return _queue; + } + + } +} diff --git a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleSyncServlet.java b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleSyncServlet.java new file mode 100644 index 0000000000..5ada26187e --- /dev/null +++ b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleSyncServlet.java @@ -0,0 +1,76 @@ +// ======================================================================== +// Copyright (c) 2006-2011 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.osgi.equinoxtools.console; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + + +/** + * Take the example ChatServlet and use it to make an Equinox Console on the web. + */ +public class EquinoxConsoleSyncServlet extends HttpServlet +{ + + private static final long serialVersionUID = 1L; + + private WebConsoleSession _consoleSession; + + public EquinoxConsoleSyncServlet(WebConsoleSession consoleSession) + { + _consoleSession = consoleSession; + } + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + String cmd = request.getParameter("cmd"); + String Action = request.getParameter("Action"); + if (Action != null && Action.toLowerCase().indexOf("clear") != -1) + { + _consoleSession.clearOutput(); + } + if (cmd != null) + { + _consoleSession.processCommand(cmd, true); + } + + response.setContentType("text/html;charset=utf-8"); + PrintWriter p = response.getWriter(); + p.println("<html><head><title>Equinox Console (Synchroneous)</title></head><body>"); + p.println("<textarea rows=\"30\" cols=\"110\">"); + p.println(_consoleSession.getOutputAsWriter().toString()); + p.println("</textarea>"); + p.println("<form method=\"GET\" action=\""+response.encodeURL(getURI(request))+"\">"); + p.println("osgi> <input type=\"text\" name=\"cmd\" value=\"\"/><br/>\n"); + p.println("<input type=\"submit\" name=\"Action\" value=\"Submit or Refresh\"><br/>"); + p.println("<input type=\"submit\" name=\"Action\" value=\"Clear and Submit\"><br/>"); + p.println("</form>"); + p.println("<br/>"); + } + + + private String getURI(HttpServletRequest request) + { + String uri= (String)request.getAttribute("javax.servlet.forward.request_uri"); + if (uri == null) + uri= request.getRequestURI(); + return uri; + } + +} diff --git a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleWebSocketServlet.java b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleWebSocketServlet.java new file mode 100644 index 0000000000..c66d1b53d3 --- /dev/null +++ b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleWebSocketServlet.java @@ -0,0 +1,170 @@ +// ======================================================================== +// Copyright (c) 2006-2011 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.osgi.equinoxtools.console; + +import java.io.IOException; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.osgi.equinoxtools.WebEquinoxToolsActivator; +import org.eclipse.jetty.osgi.equinoxtools.console.WebConsoleWriterOutputStream.OnFlushListener; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.websocket.WebSocket; +import org.eclipse.jetty.websocket.WebSocketServlet; +import org.eclipse.osgi.framework.console.ConsoleSession; +import org.osgi.framework.Bundle; +import org.osgi.framework.FrameworkUtil; + +/** + * Websocket version of the Chat with equinox. + * Ported from jetty's example 'WebSocketChatServlet' + */ +public class EquinoxConsoleWebSocketServlet extends WebSocketServlet implements OnFlushListener +{ + private final Set<ChatWebSocket> _members = new CopyOnWriteArraySet<ChatWebSocket>(); + private static final long serialVersionUID = 1L; + private WebConsoleSession _consoleSession; + private EquinoxChattingSupport _support; + + public EquinoxConsoleWebSocketServlet() + { + + } + public EquinoxConsoleWebSocketServlet(WebConsoleSession consoleSession, EquinoxChattingSupport support) + { + _consoleSession = consoleSession; + _support = support; + } + @Override + public void init() throws ServletException + { + if (_consoleSession == null) + { + _consoleSession = new WebConsoleSession(); + WebEquinoxToolsActivator.getContext().registerService(ConsoleSession.class.getName(), _consoleSession, null); + } + if (_support == null) + { + _support = new EquinoxChattingSupport(_consoleSession); + } + super.init(); + _consoleSession.addOnFlushListener(this); + } + + @Override + public void destroy() + { + _consoleSession.removeOnFlushListener(this); + } + + + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws javax.servlet.ServletException ,IOException + { + //getServletContext().getNamedDispatcher("default").forward(request,response); + response.sendRedirect(request.getContextPath() + request.getServletPath() + + (request.getPathInfo() != null ? request.getPathInfo() : "") + "/index.html"); + }; + + public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) + { + return new ChatWebSocket(); + } + + /* ------------------------------------------------------------ */ + /* ------------------------------------------------------------ */ + class ChatWebSocket implements WebSocket.OnTextMessage + { + Connection _connection; + String _username; + + public void onOpen(Connection connection) + { + // Log.info(this+" onConnect"); + _connection=connection; + _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(String data) + { + Log.info("onMessage: {}",data); + if (data.indexOf("disconnect")>=0) + _connection.disconnect(); + else + { + if (!data.endsWith(":has joined!")) + { + if (_username != null) + { + if (data.startsWith(_username + ":")) + { + data = data.substring(_username.length()+1); + } + else + { + //we should not be here? + } + } + _consoleSession.processCommand(data, false); + } + else + { + _username = data.substring(0, data.length()-":has joined!".length()); + } + // Log.info(this+" onMessage: "+data); + onFlush(); + } + } + + public void onClose(int code, String message) + { + // Log.info(this+" onDisconnect"); + _members.remove(this); + } + + } + + + /** + * Called right after the flush method on the output stream has been executed. + */ + public void onFlush() + { + Queue<String> pendingConsoleOutputMessages = _support.processConsoleOutput(false, this); + for (ChatWebSocket member : _members) + { + try + { + for (String line : pendingConsoleOutputMessages) + { + member._connection.sendMessage(line); + } + } + catch(IOException e) + { + Log.warn(e); + } + } + } + +} diff --git a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/WebConsoleSession.java b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/WebConsoleSession.java new file mode 100644 index 0000000000..614c0fc6c2 --- /dev/null +++ b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/WebConsoleSession.java @@ -0,0 +1,183 @@ +// ======================================================================== +// Copyright (c) 2006-2011 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.osgi.equinoxtools.console; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.io.PrintStream; +import java.io.StringWriter; +import java.util.List; + +import org.eclipse.jetty.osgi.equinoxtools.console.WebConsoleWriterOutputStream.OnFlushListener; +import org.eclipse.osgi.framework.console.ConsoleSession; + +/** + * A simple console session for equinox. + * + * @author hmalphettes + */ +public class WebConsoleSession extends ConsoleSession +{ + + private OutputStream _out; + private StringWriter _outWriter; + private PrintStream _source; + private InputStream _in; + + public WebConsoleSession() + { + _outWriter = new StringWriter(); + _out = new WebConsoleWriterOutputStream(_outWriter,"UTF-8"); + try + { + PipedOutputStream source = new PipedOutputStream(); + PipedInputStream sink = new PipedInputStream(source); + _in = sink; + _source = new PrintStream(source); + } + catch (IOException e) + { + //this never happens? + e.printStackTrace(); + } + } + + @Override + protected void doClose() + { + if (_out != null) try { _out.close(); } catch (IOException e) {} + if (_in != null) try { _in.close(); } catch (IOException ioe) {} + } + + @Override + public InputStream getInput() + { + return _in; + } + + @Override + public OutputStream getOutput() + { + return _out; + } + + /** + * For the output we are using a string writer in fact. + * @return + */ + public StringWriter getOutputAsWriter() + { + return _outWriter; + } + + /** + * @return The print stream where commands can be written. + */ + public PrintStream getSource() + { + return _source; + } + + /** + * Issue a command on the console. + * @param cmd + */ + public void issueCommand(String cmd) + { + if (cmd != null) + { + getSource().println(cmd); + } + } + + /** + * @param flushListener Object that is called back when the outputstream is flushed. + */ + public void addOnFlushListener(OnFlushListener flushListener) + { + ((WebConsoleWriterOutputStream)_out).addOnFlushListener(flushListener); + } + /** + * @param flushListener Object that is called back when the outputstream is flushed. + */ + public boolean removeOnFlushListener(OnFlushListener flushListener) + { + return ((WebConsoleWriterOutputStream)_out).removeOnFlushListener(flushListener); + } + + /** + * Process command comming from a web UI + * @param cmd + */ + public void processCommand(String cmd, boolean wait) + { + cmd = cmd.trim(); + while (cmd.startsWith("osgi>")) + { + cmd = cmd.substring("osgi>".length()).trim(); + } + if (cmd.equals("clear")) + { + clearOutput(); + } + else + { + getOutputAsWriter().append(cmd + "\n"); + int originalOutputLength = getOutputAsWriter().getBuffer().length(); + issueCommand(cmd); + + if (wait) + { + //it does not get uglier than this: + //give a little time to equinox to interpret the command so we see the response + //we could do a lot better, but we might as well use the async servlets anyways. + int waitLoopNumber = 0; + int lastWaitOutputLength = -1; + while (waitLoopNumber < 10) + { + waitLoopNumber++; + try + { + Thread.sleep(100); + } + catch (InterruptedException e) + { + break; + } + int newOutputLength = getOutputAsWriter().getBuffer().length(); + if (newOutputLength > originalOutputLength && newOutputLength == lastWaitOutputLength) + { + break; + } + lastWaitOutputLength = newOutputLength; + } + } + } + + } + + public void clearOutput() + { + StringBuffer buf = getOutputAsWriter().getBuffer(); + if (buf.length() > 0) buf.delete(0,buf.length()-1); + } + + public List<OnFlushListener> getOnFlushListeners() + { + return ((WebConsoleWriterOutputStream)_out).getOnFlushListeners(); + } + +} diff --git a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/WebConsoleWriterOutputStream.java b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/WebConsoleWriterOutputStream.java new file mode 100644 index 0000000000..d9d26ea58a --- /dev/null +++ b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/WebConsoleWriterOutputStream.java @@ -0,0 +1,87 @@ +// ======================================================================== +// Copyright (c) 2006-2011 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.osgi.equinoxtools.console; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; + +/** + * Can be set with a listener that is called back right after the flush method is called. + */ +public class WebConsoleWriterOutputStream extends org.eclipse.jetty.io.WriterOutputStream +{ + + /** + * Interface called back after the outputstream is flushed. + */ + public interface OnFlushListener + { + /** + * Called right after the flush method on the output stream has been executed. + */ + public void onFlush(); + + } + + public interface MessageBroadcaster + { + public void broadcast(); + } + + private List<OnFlushListener> _callBacks; + + public WebConsoleWriterOutputStream(Writer writer, String encoding) + { + super(writer, encoding); + } + + @Override + public synchronized void flush() throws IOException + { + super.flush(); + if (_callBacks != null) + { + for (OnFlushListener listener : _callBacks) + { + listener.onFlush(); + } + } + } + + public synchronized void addOnFlushListener(OnFlushListener callback) + { + if (_callBacks == null) + { + _callBacks = new ArrayList<WebConsoleWriterOutputStream.OnFlushListener>(); + } + if (!_callBacks.contains(callback)) + { + _callBacks.add(callback); + } + } + public synchronized boolean removeOnFlushListener(OnFlushListener callback) + { + if (_callBacks != null) + { + return _callBacks.remove(callback); + } + return false; + } + public synchronized List<OnFlushListener> getOnFlushListeners() + { + return _callBacks; + } + +} diff --git a/jetty-osgi/jetty-osgi-httpservice/pom.xml b/jetty-osgi/jetty-osgi-httpservice/pom.xml index b30a3af910..f39e1ee6d4 100644 --- a/jetty-osgi/jetty-osgi-httpservice/pom.xml +++ b/jetty-osgi/jetty-osgi-httpservice/pom.xml @@ -27,8 +27,8 @@ <artifactId>servlet</artifactId> </dependency> <dependency> - <groupId>org.eclipse</groupId> - <artifactId>osgi</artifactId> + <groupId>org.eclipse.osgi</groupId> + <artifactId>org.eclipse.osgi</artifactId> </dependency> <dependency> <groupId>javax.servlet</groupId> diff --git a/jetty-osgi/pom.xml b/jetty-osgi/pom.xml index dfab66bc9a..526872b107 100644 --- a/jetty-osgi/pom.xml +++ b/jetty-osgi/pom.xml @@ -11,8 +11,8 @@ <name>Jetty :: OSGi</name> <packaging>pom</packaging> <properties> - <osgi-version>3.5.0.v20090520</osgi-version> - <osgi-services-version>3.1.200-v20070605</osgi-services-version> + <osgi-version>3.6.0.v20100517</osgi-version> + <osgi-services-version>3.2.100.v20100503</osgi-services-version> <equinox-http-servlet-version>1.0.0-v20070606</equinox-http-servlet-version> <!--equinox-servletbridge-version>1.0.0-v20070523</equinox-servletbridge-version--> <jsp-2.1-glassfish-version>2.1.v20100127</jsp-2.1-glassfish-version> @@ -25,6 +25,7 @@ <module>jetty-osgi-boot-logback</module> <module>jetty-osgi-boot-warurl</module> <module>jetty-osgi-httpservice</module> + <module>jetty-osgi-equinoxtools</module> <module>test-jetty-osgi</module> </modules> <build> @@ -74,6 +75,16 @@ <dependencies> <dependency> <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-continuation</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-websocket</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-util</artifactId> <version>${project.version}</version> </dependency> @@ -108,14 +119,14 @@ <version>${project.version}</version> </dependency> <dependency> - <groupId>org.eclipse</groupId> - <artifactId>osgi</artifactId> - <version>${osgi-version}</version> + <groupId>org.eclipse.osgi</groupId> + <artifactId>org.eclipse.osgi.services</artifactId> + <version>${osgi-services-version}</version> </dependency> <dependency> <groupId>org.eclipse.osgi</groupId> - <artifactId>services</artifactId> - <version>${osgi-services-version}</version> + <artifactId>org.eclipse.osgi</artifactId> + <version>${osgi-version}</version> </dependency> <dependency> <groupId>org.eclipse.equinox.http</groupId> diff --git a/jetty-osgi/test-jetty-osgi/pom.xml b/jetty-osgi/test-jetty-osgi/pom.xml index 2622f28328..56b8252f5a 100644 --- a/jetty-osgi/test-jetty-osgi/pom.xml +++ b/jetty-osgi/test-jetty-osgi/pom.xml @@ -110,14 +110,14 @@ </dependency> <dependency> - <groupId>org.eclipse</groupId> - <artifactId>osgi</artifactId> + <groupId>org.eclipse.osgi</groupId> + <artifactId>org.eclipse.osgi</artifactId> <version>${osgi-version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.eclipse.osgi</groupId> - <artifactId>services</artifactId> + <artifactId>org.eclipse.osgi.services</artifactId> <version>${osgi-services-version}</version> <scope>runtime</scope> </dependency> diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootCore.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootCore.java index 077d3d75fb..5f49c5307b 100644 --- a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootCore.java +++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootCore.java @@ -72,8 +72,8 @@ public class TestJettyOSGiBootCore // CoreOptions.equinox(), mavenBundle().groupId( "org.mortbay.jetty" ).artifactId( "servlet-api" ).versionAsInProject().noStart(), - mavenBundle().groupId( "org.eclipse" ).artifactId( "osgi" ).versionAsInProject().noStart(), - mavenBundle().groupId( "org.eclipse.osgi" ).artifactId( "services" ).versionAsInProject().noStart(), + mavenBundle().groupId( "org.eclipse.osgi" ).artifactId( "org.eclipse.osgi" ).versionAsInProject().noStart(), + mavenBundle().groupId( "org.eclipse.osgi" ).artifactId( "org.eclipse.osgi.services" ).versionAsInProject().noStart(), mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-deploy" ).versionAsInProject().noStart(), mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-server" ).versionAsInProject().noStart(), |