Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugues Malphettes2011-05-20 04:33:57 -0400
committerHugues Malphettes2011-05-20 04:33:57 -0400
commit850170ba5fc9f567c57868f288fac585584c5462 (patch)
treede73268fe3e2b0e13f3c6f47d7abec4fc17ebfa3
parent538038a7f2434a673b35add13dd9408e0703dad0 (diff)
downloadorg.eclipse.jetty.project-850170ba5fc9f567c57868f288fac585584c5462.tar.gz
org.eclipse.jetty.project-850170ba5fc9f567c57868f288fac585584c5462.tar.xz
org.eclipse.jetty.project-850170ba5fc9f567c57868f288fac585584c5462.zip
bug 346605 commit the demo of jetty's continuation and webscoket to 'chat with the equinox console
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@3221 7e9141cc-0065-0410-87d8-b60c137991c4
-rw-r--r--jetty-osgi/jetty-osgi-boot-jsp/pom.xml6
-rw-r--r--jetty-osgi/jetty-osgi-boot-logback/pom.xml6
-rw-r--r--jetty-osgi/jetty-osgi-boot-warurl/pom.xml4
-rw-r--r--jetty-osgi/jetty-osgi-boot/pom.xml6
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/META-INF/MANIFEST.MF20
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/build.properties4
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/equinoxconsole/index.html85
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/equinoxconsole/ws/index.html109
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/pom.xml96
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/WebEquinoxToolsActivator.java127
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxChattingSupport.java150
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleContinuationServlet.java248
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleSyncServlet.java76
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleWebSocketServlet.java170
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/WebConsoleSession.java183
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/WebConsoleWriterOutputStream.java87
-rw-r--r--jetty-osgi/jetty-osgi-httpservice/pom.xml4
-rw-r--r--jetty-osgi/pom.xml25
-rw-r--r--jetty-osgi/test-jetty-osgi/pom.xml6
-rw-r--r--jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootCore.java4
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+'&nbsp;';
+ 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:&nbsp;<input id='username' type='text'/><input id='joinB' class='button' type='submit' name='join' value='Join'/>
+ </div>
+ <div id='joined' class='hidden'>
+ OSGi:&nbsp;<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('<','&lt;').replace('>','&gt;');
+ var text=m.data.substring(c+1).replace('<','&lt;').replace('>','&gt;');
+
+ var chat=$('chat');
+ var spanFrom = document.createElement('span');
+ spanFrom.className='from';
+ spanFrom.innerHTML=from+':&nbsp;';
+ 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:&nbsp;<input id='username' type='text'/><input id='joinB' class='button' type='submit' name='join' value='Join'/>
+ </div>
+ <div id='joined' class='hidden'>
+ Chat:&nbsp;<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("&#10;");
+ 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>&nbsp;<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(),

Back to the top