diff --git a/bin/start-akka-server.sh b/bin/start-akka-server.sh
index 82f2290155..3f9cee68e7 100755
--- a/bin/start-akka-server.sh
+++ b/bin/start-akka-server.sh
@@ -15,55 +15,68 @@ mkdir $BASE_DIR/storage/commitlog
mkdir $BASE_DIR/storage/data
mkdir $BASE_DIR/storage/system
-CLASSPATH=$CLASSPATH:$BASE_DIR/config
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/akka-kernel-0.5.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/akka-util-java-0.5.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/akka-util-java.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/antlr-3.1.3.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/aopalliance-1.0.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/asm-3.1.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/aspectwerkz-nodeps-jdk5-2.1.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/camel-core-2.0-SNAPSHOT.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/cassandra-0.4.0-dev.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/cglib-2.2.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/commons-cli-1.1.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/commons-collections-3.2.1.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/commons-io-1.3.2.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/commons-javaflow-1.0-SNAPSHOT.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/commons-lang-2.4.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/commons-logging-1.0.4.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/commons-math-1.1.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/configgy-1.3.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/google-collect-snapshot-20090211.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/grizzly-framework-1.8.6.3.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/grizzly-http-1.8.6.3.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/grizzly-http-servlet-1.8.6.3.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/grizzly-http-utils-1.8.6.3.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/grizzly-servlet-webserver-1.8.6.3.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/guice-core-2.0-SNAPSHOT.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/guice-jsr250-2.0-SNAPSHOT.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/high-scale-lib.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/jackson-core-asl-1.1.0.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/jackson-mapper-asl-1.1.0.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/jersey-client-1.1.0-ea.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/jersey-core-1.0.3.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/jersey-json-1.0.3.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/jersey-server-1.0.3.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/JSAP-2.1.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/jsr250-api-1.0.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/jsr311-api-1.0.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/libfb303.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/libthrift.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/log4j-1.2.15.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/lucene-core-2.2.0.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/netty-3.1.0.CR1.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/protobuf-java-2.1.0.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/scala-library-2.7.5.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/servlet-api-2.5.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/slf4j-api-1.4.3.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/slf4j-log4j12-1.4.3.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/stringtemplate-3.0.jar
-CLASSPATH=$CLASSPATH:$BASE_DIR/lib/zookeeper-3.1.0.jar
+LIB_DIR=$BASE_DIR/lib
+
+CLASSPATH=$BASE_DIR/config
+CLASSPATH=$CLASSPATH:$LIB_DIR/fscontext.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/providerutil.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/akka-kernel-0.5.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/akka-util-java-0.5.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/akka-util-java.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/antlr-3.1.3.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/aopalliance-1.0.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/asm-3.1.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/aspectwerkz-nodeps-jdk5-2.1.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/camel-core-2.0-SNAPSHOT.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/cassandra-0.4.0-dev.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/cglib-2.2.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/commons-cli-1.1.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/commons-collections-3.2.1.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/commons-io-1.3.2.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/commons-javaflow-1.0-SNAPSHOT.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/commons-lang-2.4.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/commons-logging-1.0.4.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/commons-math-1.1.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/configgy-1.3.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/google-collect-snapshot-20090211.jar
+#CLASSPATH=$CLASSPATH:$LIB_DIR/grizzly-framework-1.8.6.3.jar
+#CLASSPATH=$CLASSPATH:$LIB_DIR/grizzly-http-1.8.6.3.jar
+#CLASSPATH=$CLASSPATH:$LIB_DIR/grizzly-http-servlet-1.8.6.3.jar
+#CLASSPATH=$CLASSPATH:$LIB_DIR/grizzly-http-utils-1.9.1.jar
+#CLASSPATH=$CLASSPATH:$LIB_DIR/grizzly-servlet-webserver-1.8.6.3.jar
+#CLASSPATH=$CLASSPATH:$LIB_DIR/grizzly-comet-1.8.6.3.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/grizzly-comet-webserver-1.8.6.3.jar
+#CLASSPATH=$CLASSPATH:$LIB_DIR/grizzly-comet-webserver-1.9.17-RC2.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/guice-core-2.0-SNAPSHOT.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/guice-jsr250-2.0-SNAPSHOT.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/high-scale-lib.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/jackson-core-asl-1.1.0.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/jackson-mapper-asl-1.1.0.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/jersey-client-1.1.0-ea.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/jersey-core-1.0.3.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/jersey-json-1.0.3.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/jersey-server-1.0.3.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/jersey-scala-1.1.2-ea-SNAPSHOT.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/atmosphere-core-0.3-SNAPSHOT.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/atmosphere-portable-runtime-0.3-SNAPSHOT.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/atmosphere-compat-0.3-SNAPSHOT.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/JSAP-2.1.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/jsr250-api-1.0.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/jsr311-api-1.0.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/libfb303.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/libthrift.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/lift-webkit-1.1-M3.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/lift-util-1.1-M3.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/log4j-1.2.15.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/lucene-core-2.2.0.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/netty-3.1.0.CR1.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/protobuf-java-2.0.3.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/scala-library-2.7.5.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/servlet-api-2.5.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/slf4j-api-1.4.3.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/slf4j-log4j12-1.4.3.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/stringtemplate-3.0.jar
+CLASSPATH=$CLASSPATH:$LIB_DIR/zookeeper-3.1.0.jar
# Add for debugging: -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005 \
# To have Akka dump the generated classes, add the '-Daspectwerkz.transform.dump=*' option and it will dump classes to $BASE_DIR/_dump
@@ -81,7 +94,10 @@ JVM_OPTS=" \
-XX:+HeapDumpOnOutOfMemoryError \
-Dcom.sun.management.jmxremote.port=8080 \
-Dcom.sun.management.jmxremote.ssl=false \
+ -Djava.naming.factory.initial=com.sun.jndi.fscontext.RefFSContextFactory \
+ -Dcom.sun.grizzly.cometSupport=true \
-Dcom.sun.management.jmxremote.authenticate=false"
+
#$JAVA_HOME/bin/java $JVM_OPTS -cp $CLASSPATH se.scalablesolutions.akka.Boot se.scalablesolutions.akka.kernel.Kernel ${1}
$JAVA_HOME/bin/java $JVM_OPTS -cp $CLASSPATH se.scalablesolutions.akka.kernel.Kernel ${1}
diff --git a/config/log4j.properties b/config/log4j.properties
index 0e58e64e80..7e38b9c134 100755
--- a/config/log4j.properties
+++ b/config/log4j.properties
@@ -17,3 +17,4 @@ log4j.appender.R.layout.ConversionPattern=%5p [%t] %d{ISO8601} %F (line %L) %m%n
# Edit the next line to point to your logs directory
log4j.appender.R.File=./logs/cassandra.log
+log4j.logger.org.atmosphere=DEBUG
diff --git a/config/web.xml b/config/web.xml
deleted file mode 100644
index f49e728729..0000000000
--- a/config/web.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
- Akka Servlet
- se.scalablesolutions.akka.kernel.jersey.AkkaServlet
-
-
- Akka Servlet
- /*
-
-
diff --git a/deploy/akka-samples-java-0.5.jar b/deploy/akka-samples-java-0.5.jar
new file mode 100644
index 0000000000..62656411d1
Binary files /dev/null and b/deploy/akka-samples-java-0.5.jar differ
diff --git a/deploy/akka-samples-scala-0.5.jar b/deploy/akka-samples-scala-0.5.jar
new file mode 100644
index 0000000000..ade3b767ee
Binary files /dev/null and b/deploy/akka-samples-scala-0.5.jar differ
diff --git a/deploy/root/page.html b/deploy/root/page.html
new file mode 100644
index 0000000000..ea13c3f710
--- /dev/null
+++ b/deploy/root/page.html
@@ -0,0 +1,10 @@
+
+
blah
+
+
+
\ No newline at end of file
diff --git a/kernel/pom.xml b/kernel/pom.xml
index 3c4295eaaa..e1ec0f1850 100644
--- a/kernel/pom.xml
+++ b/kernel/pom.xml
@@ -89,59 +89,65 @@
1.0
-
-
- org.apache.cassandra
- cassandra
- 0.4.0-dev
-
-
- com.facebook
- thrift
- 1.0
-
-
- com.facebook
- fb303
- 1.0
-
-
- commons-collections
- commons-collections
- 3.2.1
-
-
- high-scale-lib
- high-scale-lib
- 1.0
-
-
- commons-lang
- commons-lang
- 2.4
-
-
-
- com.sun.grizzly
- grizzly-servlet-webserver
- 1.9.9
-
-
- com.sun.jersey
- jersey-server
- 1.0.3
-
-
- com.sun.jersey
- jersey-json
- 1.0.3
-
-
- javax.ws.rs
- jsr311-api
- 1.0
-
+
+
+
+ com.sun.grizzly
+ grizzly-comet-webserver
+
+ 1.8.6.3
+
+
+ com.sun.jersey
+ jersey-server
+ 1.0.3
+
+
+ com.sun.jersey
+ jersey-json
+ 1.0.3
+
+
+ javax.ws.rs
+ jsr311-api
+ 1.0
+
+
+ com.sun.jersey.contribs
+ jersey-scala
+ 1.1.2-ea-SNAPSHOT
+
+
+
+
+ org.atmosphere
+ atmosphere-core
+ 0.3-SNAPSHOT
+
+
+ org.atmosphere
+ atmosphere-portable-runtime
+ 0.3-SNAPSHOT
+
+
+ org.atmosphere
+ atmosphere-compat
+ 0.3-SNAPSHOT
+
+
@@ -191,100 +197,100 @@
-
- src/main/scala
- src/test/scala
-
-
- org.scala-tools
- maven-scala-plugin
-
-
-
- compile
- testCompile
-
-
-
-
-
- -target:jvm-1.5
-
-
- ${scala.version}
- 1.1
-
-
-
- org.apache.maven.plugins
- maven-eclipse-plugin
-
- true
-
-
- ch.epfl.lamp.sdt.core.scalabuilder
-
-
-
-
- ch.epfl.lamp.sdt.core.scalanature
-
-
-
-
- org.eclipse.jdt.launching.JRE_CONTAINER
-
-
- ch.epfl.lamp.sdt.launching.SCALA_CONTAINER
-
-
-
-
-
- maven-antrun-plugin
-
-
- install
-
-
-
-
-
-
- run
-
-
-
-
-
-
-
- false
- src/main/resources
-
-
- false
- src/main/scala
-
- **
-
-
- **/*.scala
-
-
-
-
-
-
-
- org.scala-tools
- maven-scala-plugin
-
- 1.1
- ${scala.version}
-
-
-
-
+
+ src/main/scala
+ src/test/scala
+
+
+ org.scala-tools
+ maven-scala-plugin
+
+
+
+ compile
+ testCompile
+
+
+
+
+
+ -target:jvm-1.5
+
+
+ ${scala.version}
+ 1.1
+
+
+
+ org.apache.maven.plugins
+ maven-eclipse-plugin
+
+ true
+
+
+ ch.epfl.lamp.sdt.core.scalabuilder
+
+
+
+
+ ch.epfl.lamp.sdt.core.scalanature
+
+
+
+
+ org.eclipse.jdt.launching.JRE_CONTAINER
+
+
+ ch.epfl.lamp.sdt.launching.SCALA_CONTAINER
+
+
+
+
+
+ maven-antrun-plugin
+
+
+ install
+
+
+
+
+
+
+ run
+
+
+
+
+
+
+
+ false
+ src/main/resources
+
+
+ false
+ src/main/scala
+
+ **
+
+
+ **/*.scala
+
+
+
+
+
+
+
+ org.scala-tools
+ maven-scala-plugin
+
+ 1.1
+ ${scala.version}
+
+
+
+
diff --git a/kernel/src/main/scala/Kernel.scala b/kernel/src/main/scala/Kernel.scala
index 80b268198f..2bfb0df29f 100644
--- a/kernel/src/main/scala/Kernel.scala
+++ b/kernel/src/main/scala/Kernel.scala
@@ -14,7 +14,7 @@ import java.net.URLClassLoader
import net.lag.configgy.{Config, Configgy, RuntimeEnvironment}
-import kernel.jersey.AkkaServlet
+import kernel.jersey.{AkkaServlet,AkkaCometServlet}
import kernel.nio.RemoteServer
import kernel.state.CassandraStorage
import kernel.util.Logging
@@ -37,7 +37,6 @@ object Kernel extends Logging {
val REST_URL = "http://" + REST_HOSTNAME
val REST_PORT = kernel.Kernel.config.getInt("akka.rest.port", 9998)
-
// FIXME add API to shut server down gracefully
private var remoteServer: RemoteServer = _
private var jerseySelectorThread: SelectorThread = _
@@ -90,8 +89,8 @@ object Kernel extends Logging {
private[akka] def runApplicationBootClasses = {
val HOME = try { System.getenv("AKKA_HOME") } catch { case e: NullPointerException => throw new IllegalStateException("AKKA_HOME system variable needs to be set. Should point to the root of the Akka distribution.") }
- val CLASSES = HOME + "/kernel/target/classes" // FIXME remove for dist
- val LIB = HOME + "/lib"
+ //val CLASSES = HOME + "/kernel/target/classes" // FIXME remove for dist
+ //val LIB = HOME + "/lib"
val CONFIG = HOME + "/config"
val DEPLOY = HOME + "/deploy"
val DEPLOY_DIR = new File(DEPLOY)
@@ -123,19 +122,29 @@ object Kernel extends Logging {
private[akka] def startJersey = {
val uri = UriBuilder.fromUri(REST_URL).port(REST_PORT).build()
- val adapter = new ServletAdapter
- val servlet = new AkkaServlet
- adapter.setServletInstance(servlet)
- adapter.setContextPath(uri.getPath)
val scheme = uri.getScheme
if (!scheme.equalsIgnoreCase("http")) throw new IllegalArgumentException("The URI scheme, of the URI " + REST_URL + ", must be equal (ignoring case) to 'http'")
+
+ val adapter = new ServletAdapter()
+
+ adapter.setHandleStaticResources(true)
+ adapter.setServletInstance(new AkkaCometServlet)
+ adapter.setContextPath(uri.getPath)
+ adapter.setRootFolder(System.getenv("AKKA_HOME") + "/deploy/root")
+ log.info("REST service root path: [" + adapter.getRootFolder + "] and context path [" + adapter.getContextPath + "] ")
+
+ val ah = new com.sun.grizzly.arp.DefaultAsyncHandler
+ ah.addAsyncFilter(new com.sun.grizzly.comet.CometAsyncFilter)
jerseySelectorThread = new SelectorThread
jerseySelectorThread.setAlgorithmClassName(classOf[StaticStreamAlgorithm].getName)
jerseySelectorThread.setPort(REST_PORT)
jerseySelectorThread.setAdapter(adapter)
+ jerseySelectorThread.setEnableAsyncExecution(true)
+ jerseySelectorThread.setAsyncHandler(ah)
jerseySelectorThread.listen
+
log.info("REST service started successfully. Listening to port [" + REST_PORT + "]")
}
diff --git a/kernel/src/main/scala/jersey/ActorComponentProviderFactory.scala b/kernel/src/main/scala/jersey/ActorComponentProviderFactory.scala
index d2935f1a16..82d0f1e76b 100644
--- a/kernel/src/main/scala/jersey/ActorComponentProviderFactory.scala
+++ b/kernel/src/main/scala/jersey/ActorComponentProviderFactory.scala
@@ -4,17 +4,22 @@
package se.scalablesolutions.akka.kernel.jersey
-import com.sun.jersey.core.spi.component.ioc.IoCComponentProviderFactory
-import com.sun.jersey.core.spi.component.ComponentContext
+import kernel.Kernel
+import util.Logging
+import javax.ws.rs.core.Context
+
+import com.sun.jersey.core.spi.component.ioc.{IoCComponentProvider,IoCComponentProviderFactory}
+import com.sun.jersey.core.spi.component.{ComponentContext}
import config.Configurator
+
class ActorComponentProviderFactory(val configurators: List[Configurator])
- extends IoCComponentProviderFactory {
+extends IoCComponentProviderFactory with Logging {
+ override def getComponentProvider(clazz: Class[_]): IoCComponentProvider = getComponentProvider(null, clazz)
- override def getComponentProvider(clazz: Class[_]): ActorComponentProvider = getComponentProvider(null, clazz)
-
- override def getComponentProvider(context: ComponentContext, clazz: Class[_]): ActorComponentProvider = {
- new ActorComponentProvider(clazz, configurators)
+ override def getComponentProvider(context: ComponentContext, clazz: Class[_]): IoCComponentProvider = {
+ //log.info("ProviderFactory: resolve => " + clazz.getName)
+ configurators.find(_.isDefined(clazz)).map(_ => new ActorComponentProvider(clazz, configurators)).getOrElse(null)
}
}
\ No newline at end of file
diff --git a/kernel/src/main/scala/jersey/AkkaServlet.scala b/kernel/src/main/scala/jersey/AkkaServlet.scala
index efb9e0a960..9d67def133 100644
--- a/kernel/src/main/scala/jersey/AkkaServlet.scala
+++ b/kernel/src/main/scala/jersey/AkkaServlet.scala
@@ -6,26 +6,101 @@ package se.scalablesolutions.akka.kernel.jersey
import kernel.Kernel
import config.ConfiguratorRepository
+import util.Logging
-import com.sun.jersey.api.core.{DefaultResourceConfig, ResourceConfig}
+import com.sun.jersey.api.core.{DefaultResourceConfig, ResourceConfig,ClasspathResourceConfig}
import com.sun.jersey.spi.container.servlet.ServletContainer
import com.sun.jersey.spi.container.WebApplication
-import java.util.HashSet
+import com.sun.jersey.server.impl.component.{IoCResourceFactory}
-class AkkaServlet extends ServletContainer {
+import javax.servlet.{ServletConfig}
+import javax.servlet.http.{HttpServletRequest,HttpServletResponse}
+
+import org.atmosphere.cpr.{AtmosphereServlet,AtmosphereServletProcessor,AtmosphereEvent,DefaultBroadcaster}
+import org.atmosphere.cpr.AtmosphereServlet.{AtmosphereHandlerWrapper}
+import org.atmosphere.container.GrizzlyCometSupport
+import org.atmosphere.handler.ReflectorServletProcessor
+import org.atmosphere.core.{JerseyBroadcaster}
+
+import java.util.{HashSet, HashMap}
+import java.net.{URL,URLClassLoader}
+import java.io.{InputStream}
+
+import scala.collection.jcl.Conversions._
+
+
+class AkkaServlet extends ServletContainer with AtmosphereServletProcessor with Logging {
override def initiate(rc: ResourceConfig, wa: WebApplication) = {
- Kernel.boot // will boot if not already booted by 'main'
- val configurators = ConfiguratorRepository.getConfiguratorsFor(getServletContext);
- val set = new HashSet[Class[_]]
- for {
- conf <- configurators
- clazz <- conf.getComponentInterfaces
- } set.add(clazz)
- wa.initiate(
- new DefaultResourceConfig(set),
- new ActorComponentProviderFactory(configurators));
+ Kernel.boot // will boot if not already booted by 'main'
+ val configurators = ConfiguratorRepository.getConfiguratorsFor(getServletContext)
+
+ rc.getClasses.addAll(configurators.flatMap(_.getComponentInterfaces))
+ rc.getProperties.put("com.sun.jersey.spi.container.ResourceFilters","org.atmosphere.core.AtmosphereFilter")
+ //rc.getFeatures.put("com.sun.jersey.config.feature.Redirect", true)
+ //rc.getFeatures.put("com.sun.jersey.config.feature.ImplicitViewables",true)
+
+ wa.initiate(rc,new ActorComponentProviderFactory(configurators))
}
-}
\ No newline at end of file
+
+ //Borrowed from AbstractReflectorAtmosphereHandler
+ override def onMessage(event : AtmosphereEvent[HttpServletRequest,HttpServletResponse]) : AtmosphereEvent[_,_] =
+ {
+ //log.info("onMessage: " + event.getMessage.toString)
+
+ if(event.getMessage ne null)
+ {
+ var isUsingStream = false
+ try {
+ event.getResponse.getWriter
+ } catch {
+ case e: IllegalStateException => isUsingStream = true
+ }
+
+ val data = event.getMessage.toString
+
+ if (isUsingStream){
+ if(data != null)
+ event.getResponse.getOutputStream.write(data.getBytes)
+ event.getResponse.getOutputStream.flush
+ } else {
+ event.getResponse.getWriter.write(data)
+ event.getResponse.getWriter.flush
+ }
+ }
+ else
+ log.info("Null event message :/ req[ " + event.getRequest + "] res[" +event.getResponse + "]")
+
+ event
+ }
+
+ override def onEvent(event : AtmosphereEvent[HttpServletRequest,HttpServletResponse]) : AtmosphereEvent[_,_] =
+ {
+ //log.info("onEvent: " + event.getMessage)
+ event.getRequest.setAttribute(ReflectorServletProcessor.ATMOSPHERE_EVENT, event)
+ event.getRequest.setAttribute(ReflectorServletProcessor.ATMOSPHERE_HANDLER, this)
+
+ service(event.getRequest, event.getResponse)
+
+ event
+ }
+}
+
+class AkkaCometServlet extends org.atmosphere.cpr.AtmosphereServlet
+{
+ override def init(sconf : ServletConfig) = {
+ val servlet = new AkkaServlet
+ this.config = new AtmosphereConfig { ah = servlet }
+
+ atmosphereHandlers.put("", new AtmosphereHandlerWrapper(servlet,new JerseyBroadcaster))
+
+ setCometSupport(new GrizzlyCometSupport(config))
+ getCometSupport.init(sconf)
+
+ servlet.init(sconf)
+ }
+
+ override def loadAtmosphereDotXml(is : InputStream, urlc :URLClassLoader) = () //Hide it
+}
diff --git a/lib/akka-kernel-0.5.jar b/lib/akka-kernel-0.5.jar
new file mode 100644
index 0000000000..4fb6825ced
Binary files /dev/null and b/lib/akka-kernel-0.5.jar differ
diff --git a/lib/akka-util-java-0.5.jar b/lib/akka-util-java-0.5.jar
new file mode 100644
index 0000000000..e47dc22cd7
Binary files /dev/null and b/lib/akka-util-java-0.5.jar differ
diff --git a/lib/atmosphere-compat-0.3-SNAPSHOT.jar b/lib/atmosphere-compat-0.3-SNAPSHOT.jar
new file mode 100644
index 0000000000..7125488274
Binary files /dev/null and b/lib/atmosphere-compat-0.3-SNAPSHOT.jar differ
diff --git a/lib/atmosphere-core-0.3-SNAPSHOT.jar b/lib/atmosphere-core-0.3-SNAPSHOT.jar
new file mode 100644
index 0000000000..6876b9e845
Binary files /dev/null and b/lib/atmosphere-core-0.3-SNAPSHOT.jar differ
diff --git a/lib/atmosphere-portable-runtime-0.3-SNAPSHOT.jar b/lib/atmosphere-portable-runtime-0.3-SNAPSHOT.jar
new file mode 100644
index 0000000000..c12212705a
Binary files /dev/null and b/lib/atmosphere-portable-runtime-0.3-SNAPSHOT.jar differ
diff --git a/lib/fscontext.jar b/lib/fscontext.jar
new file mode 100644
index 0000000000..0efc25071a
Binary files /dev/null and b/lib/fscontext.jar differ
diff --git a/lib/grizzly-servlet-webserver-1.8.6.3.jar b/lib/grizzly-comet-webserver-1.8.6.3.jar
similarity index 91%
rename from lib/grizzly-servlet-webserver-1.8.6.3.jar
rename to lib/grizzly-comet-webserver-1.8.6.3.jar
index be0a596ef1..965c623bac 100644
Binary files a/lib/grizzly-servlet-webserver-1.8.6.3.jar and b/lib/grizzly-comet-webserver-1.8.6.3.jar differ
diff --git a/lib/grizzly-framework-1.8.6.3.jar b/lib/grizzly-framework-1.8.6.3.jar
deleted file mode 100644
index ded488b1b2..0000000000
Binary files a/lib/grizzly-framework-1.8.6.3.jar and /dev/null differ
diff --git a/lib/grizzly-http-1.8.6.3.jar b/lib/grizzly-http-1.8.6.3.jar
deleted file mode 100644
index 7e6fe75107..0000000000
Binary files a/lib/grizzly-http-1.8.6.3.jar and /dev/null differ
diff --git a/lib/grizzly-http-servlet-1.8.6.3.jar b/lib/grizzly-http-servlet-1.8.6.3.jar
deleted file mode 100644
index 9011703cc9..0000000000
Binary files a/lib/grizzly-http-servlet-1.8.6.3.jar and /dev/null differ
diff --git a/lib/grizzly-http-utils-1.8.6.3.jar b/lib/grizzly-http-utils-1.8.6.3.jar
deleted file mode 100644
index 00780f5d40..0000000000
Binary files a/lib/grizzly-http-utils-1.8.6.3.jar and /dev/null differ
diff --git a/lib/jersey-scala-1.1.2-ea-SNAPSHOT.jar b/lib/jersey-scala-1.1.2-ea-SNAPSHOT.jar
new file mode 100644
index 0000000000..a24bb19a7d
Binary files /dev/null and b/lib/jersey-scala-1.1.2-ea-SNAPSHOT.jar differ
diff --git a/lib/providerutil.jar b/lib/providerutil.jar
new file mode 100644
index 0000000000..0d6e48f388
Binary files /dev/null and b/lib/providerutil.jar differ
diff --git a/samples-scala/src/main/scala/SimpleService.scala b/samples-scala/src/main/scala/SimpleService.scala
index b29dbef6ec..a766bccb0f 100644
--- a/samples-scala/src/main/scala/SimpleService.scala
+++ b/samples-scala/src/main/scala/SimpleService.scala
@@ -1,23 +1,33 @@
package sample.scala
-import javax.ws.rs.{Path, GET, Produces}
+import javax.ws.rs.{GET, POST, Path, Produces, WebApplicationException, Consumes}
import se.scalablesolutions.akka.kernel.state.{TransactionalState, TransactionalMap, CassandraStorageConfig}
import se.scalablesolutions.akka.kernel.actor.{Supervisor, SupervisorFactory, Actor, StartSupervisor}
import se.scalablesolutions.akka.kernel.config.ScalaConfig._
+import javax.ws.rs.core.MultivaluedMap
+
+
+import _root_.scala.xml.{NodeSeq}
+import se.scalablesolutions.akka.kernel.util.{Logging}
+import org.atmosphere.core.annotation.{Broadcast, BroadcastFilter => FilterBroadcast, Suspend}
+import org.atmosphere.util.{XSSHtmlFilter}
+import org.atmosphere.cpr.{BroadcastFilter}
+
+
class Boot {
- object factory extends SupervisorFactory {
- override def getSupervisorConfig: SupervisorConfig = {
- SupervisorConfig(
- RestartStrategy(OneForOne, 3, 100),
- Supervise(
- new SimpleService,
- LifeCycle(Permanent, 100))
- :: Nil)
+ object factory extends SupervisorFactory {
+ override def getSupervisorConfig: SupervisorConfig = {
+ SupervisorConfig(
+ RestartStrategy(OneForOne, 3, 100),
+ Supervise(
+ new Chat,
+ LifeCycle(Permanent, 100))
+ :: Nil)
+ }
}
- }
- val supervisor = factory.newSupervisor
- supervisor.startSupervisor
+ val supervisor = factory.newSupervisor
+ supervisor.startSupervisor
}
/**
@@ -26,36 +36,99 @@ class Boot {
* curl http://localhost:9998/scalacount
*
* Or browse to the URL from a web browser.
- */
+ */
@Path("/scalacount")
class SimpleService extends Actor {
- uuid = "SimpleService"
- makeTransactionRequired
+ uuid = "SimpleService"
+ makeTransactionRequired
- case object Tick
- private val KEY = "COUNTER";
- private var hasStartedTicking = false;
- private val storage = TransactionalState.newPersistentMap(CassandraStorageConfig())
+ case object Tick
+ private val KEY = "COUNTER";
+ private var hasStartedTicking = false;
+ private val storage = TransactionalState.newPersistentMap(CassandraStorageConfig())
- @GET
- @Produces(Array("application/json"))
- def count = (this !! Tick).getOrElse("Error in counter")
-
- override def receive: PartialFunction[Any, Unit] = {
- case Tick => if (hasStartedTicking) {
- val counter = storage.get(KEY).get.asInstanceOf[Integer].intValue
- storage.put(KEY, new Integer(counter + 1))
- //reply(Tick: { counter + 1 }
)
- reply("Tick: " + (counter + 1) + "\n")
- } else {
- storage.put(KEY, new Integer(0))
- hasStartedTicking = true
- //reply(Tick: 0
)
- reply("Tick: 0\n")
+ @GET
+ @Produces(Array("text/html"))
+ def count() = {
+ (this !! Tick).getOrElse(Error in counter)
}
- }
-
- override protected def postRestart(reason: AnyRef, config: Option[AnyRef]) = {
- println("Restarting due to: " + reason.asInstanceOf[Exception].getMessage)
- }
-}
\ No newline at end of file
+
+ override def receive: PartialFunction[Any, Unit] = {
+ case Tick => if (hasStartedTicking) {
+ val counter = storage.get(KEY).get.asInstanceOf[Integer].intValue
+ storage.put(KEY, new Integer(counter + 1))
+ reply(Tick: {counter + 1})
+ } else {
+ storage.put(KEY, new Integer(0))
+ hasStartedTicking = true
+ reply(Tick: 0)
+ }
+ }
+
+ override protected def postRestart(reason: AnyRef, config: Option[AnyRef]) = {
+ println("Restarting due to: " + reason.asInstanceOf[Exception].getMessage)
+ }
+}
+
+@Path("/chat")
+class Chat extends Actor with Logging{
+ uuid = "Chat"
+ makeTransactionRequired
+
+ case class Chat(val who : String, val what : String,val msg : String)
+
+ override protected def postRestart(reason: AnyRef, config: Option[AnyRef]) = {
+ println("Restarting due to: " + reason.asInstanceOf[Exception].getMessage)
+ }
+
+ @Suspend
+ @GET
+ @Produces(Array("text/html"))
+ def suspend() = "\n"
+
+ override def receive: PartialFunction[Any, Unit] = {
+ case Chat(who,what,msg) => {
+
+ //log.info("Chat(" + who + ", " + what + ", " + msg + ")")
+
+ what match {
+ case "login" => reply("System Message__"+who+" has joined.")
+ case "post" => reply("" + who + "__" + msg)
+ case _ => throw new WebApplicationException(422)
+ }
+ }
+ case x => log.info("recieve unknown: " + x)
+ }
+
+ @Broadcast
+ @Consumes(Array("application/x-www-form-urlencoded"))
+ @POST
+ @Produces(Array("text/html"))
+ @FilterBroadcast(Array(classOf[XSSHtmlFilter],classOf[JsonpFilter]))
+ def publishMessage(form: MultivaluedMap[String, String]) = (this !! Chat(form.getFirst("name"),form.getFirst("action"),form.getFirst("message"))).getOrElse("System__error")
+ }
+
+
+ class JsonpFilter extends BroadcastFilter[String] with Logging
+ {
+
+ val BEGIN_SCRIPT_TAG = "\n"
+
+ def filter(m : String) = {
+ var name = m
+ var message = ""
+
+ if (m.indexOf("__") > 0) {
+ name = m.substring(0, m.indexOf("__"))
+ message = m.substring(m.indexOf("__") + 2)
+ }
+
+ (BEGIN_SCRIPT_TAG + "window.parent.app.update({ name: \""
+ + name + "\", message: \""
+ + message + "\" });\n"
+ + END_SCRIPT_TAG)
+ }
+ }
\ No newline at end of file