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