merged multiverse STM rewrite with master
This commit is contained in:
commit
1968dc1f45
17 changed files with 758 additions and 130 deletions
138
README.textile
138
README.textile
|
|
@ -1,68 +1,70 @@
|
|||
h1. Akka: RESTful Distributed Persistent Transactional Actors
|
||||
|
||||
h3. "http://akkasource.org":http://akkasource.org
|
||||
|
||||
Akka implements a unique hybrid of:
|
||||
* The Actor model (Actors and Active Objects), which gives you:
|
||||
** Concurrency (high-level and simple)
|
||||
** Asynchronous, non-blocking and highly performant components.
|
||||
** Supervision with "let-it-crash" semantics. Components are loosely coupled and restarted upon failure.
|
||||
* Software Transactional Memory (STM).
|
||||
* BASE and ACID persistence - Pluggable Eventually Consistent or ACID distributed scalable persistent storage.
|
||||
* Remoting - Distributed services with supervision and error management
|
||||
* REST (JAX-RS) and Comet bindings.
|
||||
* Monitoring and Management
|
||||
|
||||
Akka can be used in two different ways:
|
||||
* As a library: used by a web app, to be put into ‘WEB-INF/lib’
|
||||
* As a kernel: stand-alone kernel, embedding the servlet container
|
||||
|
||||
See the "Use-case and Deployment Scenarios":http://wiki.github.com/jboner/akka/use-case-and-deployment-scenarios for details.
|
||||
|
||||
h1. What's Akka all about? Why should I care?
|
||||
|
||||
If you are new to Akka then I suggest you start with either the:
|
||||
|
||||
* "High Level View":http://wiki.github.com/jboner/akka/modules-the-high-level-view; which is outlining the different modules in Akka.
|
||||
* "Use-case and Deployment Scenarios":http://wiki.github.com/jboner/akka/use-case-and-deployment-scenarios; outlining how and in which use-case and deployment scenarios can I use Akka?
|
||||
* "Examples":http://wiki.github.com/jboner/akka/examples; showing how to build a RESTful, transactional, persistent Active Object and Actor.
|
||||
|
||||
After that you can dive into the "Reference Manual":http://wiki.github.com/jboner/akka/akka-reference-manual.
|
||||
|
||||
h1. Documentation
|
||||
|
||||
Akka has pretty thorough "reference documentation":https://github.com/jboner/akka/wikis. Covering examples, APIs and configuration.
|
||||
|
||||
h1. Distribution
|
||||
|
||||
The latest distribution can be found in the "downloads section":https://github.com/jboner/akka/downloads
|
||||
|
||||
h1. Mailing List
|
||||
|
||||
If you have questions and/or feedback: please sign up to the Akka User mailing list:
|
||||
"http://groups.google.com/group/akka-user":http://groups.google.com/group/akka-user
|
||||
|
||||
h1. Professional Support
|
||||
|
||||
Scalable Solutions AB is providing a variety of professional support packages for Akka, please visit their website for details:
|
||||
"http://scalablesolutions.se":http://scalablesolutions.se
|
||||
|
||||
h1. License
|
||||
|
||||
<pre>
|
||||
This software is licensed under the Apache 2 license, quoted below.
|
||||
|
||||
Copyright 2009 Scalable Solutions AB <http://scalablesolutions.se>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
use this file except in compliance with the License. You may obtain a copy of
|
||||
the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations under
|
||||
the License.
|
||||
</pre>
|
||||
h1. Akka Transactors
|
||||
|
||||
h2. RESTful Distributed Persistent Transactional Actors
|
||||
|
||||
h3. "http://akkasource.org":http://akkasource.org
|
||||
|
||||
Akka implements a unique hybrid of:
|
||||
* The Actor model (Actors and Active Objects), which gives you:
|
||||
** Concurrency (high-level and simple)
|
||||
** Asynchronous, non-blocking and highly performant components.
|
||||
** Supervision with "let-it-crash" semantics. Components are loosely coupled and restarted upon failure.
|
||||
* Software Transactional Memory (STM).
|
||||
* BASE and ACID persistence - Pluggable Eventually Consistent or ACID distributed scalable persistent storage.
|
||||
* Remoting - Distributed services with supervision and error management
|
||||
* REST (JAX-RS) and Comet bindings.
|
||||
* Monitoring and Management
|
||||
|
||||
Akka can be used in two different ways:
|
||||
* As a library: used by a web app, to be put into ‘WEB-INF/lib’
|
||||
* As a kernel: stand-alone kernel, embedding the servlet container
|
||||
|
||||
See the "Use-case and Deployment Scenarios":http://wiki.github.com/jboner/akka/use-case-and-deployment-scenarios for details.
|
||||
|
||||
h1. What's Akka all about? Why should I care?
|
||||
|
||||
If you are new to Akka then I suggest you start with either the:
|
||||
|
||||
* "High Level View":http://wiki.github.com/jboner/akka/modules-the-high-level-view; which is outlining the different modules in Akka.
|
||||
* "Use-case and Deployment Scenarios":http://wiki.github.com/jboner/akka/use-case-and-deployment-scenarios; outlining how and in which use-case and deployment scenarios can I use Akka?
|
||||
* "Examples":http://wiki.github.com/jboner/akka/examples; showing how to build a RESTful, transactional, persistent Active Object and Actor.
|
||||
|
||||
After that you can dive into the "Reference Manual":http://wiki.github.com/jboner/akka/akka-reference-manual.
|
||||
|
||||
h1. Documentation
|
||||
|
||||
Akka has pretty thorough "reference documentation":https://github.com/jboner/akka/wikis. Covering examples, APIs and configuration.
|
||||
|
||||
h1. Distribution
|
||||
|
||||
The latest distribution can be found in the "downloads section":https://github.com/jboner/akka/downloads
|
||||
|
||||
h1. Mailing List
|
||||
|
||||
If you have questions and/or feedback: please sign up to the Akka User mailing list:
|
||||
"http://groups.google.com/group/akka-user":http://groups.google.com/group/akka-user
|
||||
|
||||
h1. Professional Support
|
||||
|
||||
Scalable Solutions AB is providing a variety of professional support packages for Akka, please visit their website for details:
|
||||
"http://scalablesolutions.se":http://scalablesolutions.se
|
||||
|
||||
h1. License
|
||||
|
||||
<pre>
|
||||
This software is licensed under the Apache 2 license, quoted below.
|
||||
|
||||
Copyright 2009 Scalable Solutions AB <http://scalablesolutions.se>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
use this file except in compliance with the License. You may obtain a copy of
|
||||
the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations under
|
||||
the License.
|
||||
</pre>
|
||||
|
|
|
|||
|
|
@ -16,18 +16,20 @@ import scala.collection.jcl.HashMap
|
|||
object ActorRegistry extends Logging {
|
||||
private val actors = new HashMap[String, List[Actor]]
|
||||
|
||||
def actorsFor(clazz: Class[_]): List[Actor] = synchronized {
|
||||
actors.get(clazz.getName) match {
|
||||
def actorsFor(fqn : String): List[Actor] = synchronized {
|
||||
actors.get(fqn) match {
|
||||
case None => Nil
|
||||
case Some(instances) => instances
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def actorsFor(clazz: Class[_]) : List[Actor] = actorsFor(clazz.getName)
|
||||
|
||||
def register(actor: Actor) = synchronized {
|
||||
val name = actor.getClass.getName
|
||||
actors.get(name) match {
|
||||
case Some(instances) => actors + (name -> (actor :: instances))
|
||||
case None => actors + (name -> (actor :: Nil))
|
||||
case None => actors + (name -> (actor :: Nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,11 +11,12 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package se.scalablesolutions.akka.util
|
||||
package se.scalablesolutions.akka.actor
|
||||
|
||||
import java.util.concurrent._
|
||||
import actor.{OneForOneStrategy, Actor}
|
||||
import config.ScalaConfig._
|
||||
import _root_.se.scalablesolutions.akka.util.{Logging}
|
||||
|
||||
|
||||
import org.scala_tools.javautils.Imports._
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
package se.scalablesolutions.akka.state
|
||||
|
||||
//import org.multiverse.datastructures.refs.manual.Ref
|
||||
import stm.{TransactionManagement, Ref}
|
||||
import org.multiverse.templates.AtomicTemplate
|
||||
import org.multiverse.api.Transaction;
|
||||
|
|
@ -12,8 +11,6 @@ import akka.collection._
|
|||
|
||||
import org.codehaus.aspectwerkz.proxy.Uuid
|
||||
|
||||
import scala.collection.mutable.{ArrayBuffer, HashMap}
|
||||
|
||||
/**
|
||||
* Example Scala usage:
|
||||
* <pre>
|
||||
|
|
@ -68,7 +65,7 @@ object TransactionalRef {
|
|||
*
|
||||
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
||||
*/
|
||||
class TransactionalRef[+T] extends Transactional {
|
||||
class TransactionalRef[T] extends Transactional {
|
||||
private[this] val ref = new Ref[T]
|
||||
|
||||
def swap(elem: T) = ref.set(elem)
|
||||
|
|
@ -93,7 +90,7 @@ class TransactionalRef[+T] extends Transactional {
|
|||
|
||||
def flatMap[B](f: T => Option[B]): Option[B] = if (isEmpty) None else f(ref.get)
|
||||
|
||||
def filter(p: T => Boolean): Option[T] = if (isEmpty || p(ref.get)) this else None
|
||||
def filter(p: T => Boolean): Option[T] = if (isEmpty || p(ref.get)) Some(ref.get) else None
|
||||
|
||||
def foreach(f: T => Unit) { if (!isEmpty) f(ref.get) }
|
||||
|
||||
|
|
@ -104,8 +101,6 @@ class TransactionalRef[+T] extends Transactional {
|
|||
def toRight[X](left: => X) = if (isEmpty) Left(left) else Right(ref.get)
|
||||
|
||||
def toLeft[X](right: => X) = if (isEmpty) Right(right) else Left(ref.get)
|
||||
|
||||
def orElse[B >: T](alternative: => TransactionalRef[B]): TransactionalRef[B] = if (isEmpty) alternative else this
|
||||
}
|
||||
|
||||
object TransactionalMap {
|
||||
|
|
@ -160,7 +155,7 @@ class TransactionalMap[K, V] extends Transactional with scala.collection.mutable
|
|||
}
|
||||
|
||||
object TransactionalVector {
|
||||
def apply[T]() = new TransactionalVector
|
||||
def apply[T]() = new TransactionalVector[T]
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4,9 +4,8 @@ import junit.framework.Test
|
|||
import junit.framework.TestCase
|
||||
import junit.framework.TestSuite
|
||||
|
||||
import actor.{ActorSpec, RemoteActorSpec, InMemoryActorSpec, SupervisorSpec, RemoteSupervisorSpec}
|
||||
import actor.{ActorSpec, RemoteActorSpec, InMemoryActorSpec, SupervisorSpec, RemoteSupervisorSpec,SchedulerSpec}
|
||||
import reactor.{EventBasedSingleThreadDispatcherTest, EventBasedThreadPoolDispatcherTest}
|
||||
import util.SchedulerSpec
|
||||
|
||||
object AllTest extends TestCase {
|
||||
def suite(): Test = {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
package se.scalablesolutions.akka.util
|
||||
|
||||
import se.scalablesolutions.akka.actor.Actor
|
||||
package se.scalablesolutions.akka.actor
|
||||
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,11 @@
|
|||
<groupId>se.scalablesolutions.akka</groupId>
|
||||
<version>0.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>akka-security</artifactId>
|
||||
<groupId>se.scalablesolutions.akka</groupId>
|
||||
<version>0.6</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Core deps -->
|
||||
<dependency>
|
||||
|
|
|
|||
|
|
@ -35,10 +35,7 @@ class AkkaServlet extends ServletContainer with AtmosphereServletProcessor with
|
|||
val configurators = ConfiguratorRepository.getConfigurators
|
||||
|
||||
rc.getClasses.addAll(configurators.flatMap(_.getComponentInterfaces))
|
||||
log.info("Starting AkkaServlet with ResourceFilters: " + rc.getProperty("com.sun.jersey.spi.container.ResourceFilters"));
|
||||
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)
|
||||
rc.getProperties.put("com.sun.jersey.spi.container.ResourceFilters", akka.Config.config.getString("akka.rest.filters").getOrElse(""))
|
||||
|
||||
wa.initiate(rc, new ActorComponentProviderFactory(configurators))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,8 +108,8 @@ trait PersistentMap extends scala.collection.mutable.Map[AnyRef, AnyRef] with Tr
|
|||
override def get(key: AnyRef): Option[AnyRef] = {
|
||||
if (newAndUpdatedEntries.contains(key)) newAndUpdatedEntries.get(key)
|
||||
else try {
|
||||
storage.getMapStorageEntryFor(uuid, key)
|
||||
} catch { case e: Exception => None }
|
||||
storage.getMapStorageEntryFor(uuid, key)
|
||||
} catch { case e: Exception => None }
|
||||
}
|
||||
|
||||
override def elements: Iterator[Tuple2[AnyRef, AnyRef]] = {
|
||||
|
|
|
|||
83
akka-samples-security/pom.xml
Normal file
83
akka-samples-security/pom.xml
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
<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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>akka-samples-security</artifactId>
|
||||
<name>Akka Sample Security Module</name>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<artifactId>akka</artifactId>
|
||||
<groupId>se.scalablesolutions.akka</groupId>
|
||||
<version>0.6</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<artifactId>akka-kernel</artifactId>
|
||||
<groupId>se.scalablesolutions.akka</groupId>
|
||||
<version>0.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>akka-util-java</artifactId>
|
||||
<groupId>se.scalablesolutions.akka</groupId>
|
||||
<version>0.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>akka-util</artifactId>
|
||||
<groupId>se.scalablesolutions.akka</groupId>
|
||||
<version>0.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>akka-actors</artifactId>
|
||||
<groupId>se.scalablesolutions.akka</groupId>
|
||||
<version>0.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>akka-security</artifactId>
|
||||
<groupId>se.scalablesolutions.akka</groupId>
|
||||
<version>0.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>akka-persistence</artifactId>
|
||||
<groupId>se.scalablesolutions.akka</groupId>
|
||||
<version>0.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>jsr311-api</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>jsr250-api</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src/main/scala</sourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>install</phase>
|
||||
<configuration>
|
||||
<tasks>
|
||||
<copy file="target/akka-samples-security-${akka.version}.jar"
|
||||
tofile="../deploy/akka-samples-security-${akka.version}.jar"/>
|
||||
</tasks>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
87
akka-samples-security/src/main/scala/SimpleService.scala
Normal file
87
akka-samples-security/src/main/scala/SimpleService.scala
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* Copyright (C) 2009 Scalable Solutions.
|
||||
*/
|
||||
|
||||
package sample.secure
|
||||
|
||||
import _root_.se.scalablesolutions.akka.state.{TransactionalState,PersistentState, CassandraStorageConfig}
|
||||
import _root_.se.scalablesolutions.akka.actor.{SupervisorFactory, Actor}
|
||||
import _root_.se.scalablesolutions.akka.config.ScalaConfig._
|
||||
import _root_.se.scalablesolutions.akka.util.Logging
|
||||
import _root_.se.scalablesolutions.akka.security.{DigestAuthenticationActor, UserInfo}
|
||||
import _root_.javax.annotation.security.{DenyAll,PermitAll,RolesAllowed}
|
||||
import javax.ws.rs.{GET, POST, Path, Produces, Consumes}
|
||||
|
||||
class Boot {
|
||||
object factory extends SupervisorFactory {
|
||||
override def getSupervisorConfig: SupervisorConfig = {
|
||||
SupervisorConfig(
|
||||
RestartStrategy(OneForOne, 3, 100),
|
||||
Supervise(
|
||||
new SimpleAuthenticationService,
|
||||
LifeCycle(Permanent, 100)) ::
|
||||
Supervise(
|
||||
new SecureService,
|
||||
LifeCycle(Permanent, 100)):: Nil)
|
||||
}
|
||||
}
|
||||
|
||||
val supervisor = factory.newSupervisor
|
||||
supervisor.startSupervisor
|
||||
}
|
||||
|
||||
/*
|
||||
* In akka.conf you can set the FQN of any AuthenticationActor of your wish, under the property name: akka.rest.authenticator
|
||||
*/
|
||||
class SimpleAuthenticationService extends DigestAuthenticationActor
|
||||
{
|
||||
//If you want to have a distributed nonce-map, you can use something like below,
|
||||
//don't forget to configure your standalone Cassandra instance
|
||||
//
|
||||
//makeTransactionRequired
|
||||
//override def mkNonceMap = PersistentState.newMap(CassandraStorageConfig()).asInstanceOf[scala.collection.mutable.Map[String,Long]]
|
||||
|
||||
//Use an in-memory nonce-map as default
|
||||
override def mkNonceMap = new scala.collection.mutable.HashMap[String,Long]
|
||||
//Change this to whatever you want
|
||||
override def realm = "test"
|
||||
|
||||
//Dummy method that allows you to log on with whatever username with the password "bar"
|
||||
override def userInfo(username : String) : Option[UserInfo] = Some(UserInfo(username,"bar","ninja" :: "chef" :: Nil))
|
||||
}
|
||||
|
||||
/**
|
||||
* This is merely a secured version of the scala-sample
|
||||
*
|
||||
* The interesting part is
|
||||
* @RolesAllowed
|
||||
* @PermitAll
|
||||
* @DenyAll
|
||||
*/
|
||||
|
||||
@Path("/securecount")
|
||||
class SecureService extends Actor with Logging {
|
||||
makeTransactionRequired
|
||||
|
||||
case object Tick
|
||||
private val KEY = "COUNTER";
|
||||
private var hasStartedTicking = false;
|
||||
private val storage = PersistentState.newMap(CassandraStorageConfig())
|
||||
|
||||
@GET
|
||||
@Produces(Array("text/html"))
|
||||
@RolesAllowed(Array("chef"))
|
||||
def count = (this !! Tick).getOrElse(<error>Error in counter</error>)
|
||||
|
||||
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(<success>Tick:{counter + 1}</success>)
|
||||
} else {
|
||||
storage.put(KEY, new Integer(0))
|
||||
hasStartedTicking = true
|
||||
reply(<success>Tick: 0</success>)
|
||||
}
|
||||
}
|
||||
}
|
||||
65
akka-security/pom.xml
Normal file
65
akka-security/pom.xml
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>akka-security</artifactId>
|
||||
<name>Akka Security Module</name>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<artifactId>akka</artifactId>
|
||||
<groupId>se.scalablesolutions.akka</groupId>
|
||||
<version>0.6</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.scala-lang</groupId>
|
||||
<artifactId>scala-library</artifactId>
|
||||
<version>2.7.5</version>
|
||||
</dependency>
|
||||
<!--<dependency>
|
||||
<artifactId>akka-kernel</artifactId>
|
||||
<groupId>se.scalablesolutions.akka</groupId>
|
||||
<version>0.6</version>
|
||||
</dependency>-->
|
||||
<dependency>
|
||||
<artifactId>akka-actors</artifactId>
|
||||
<groupId>se.scalablesolutions.akka</groupId>
|
||||
<version>0.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>akka-persistence</artifactId>
|
||||
<groupId>se.scalablesolutions.akka</groupId>
|
||||
<version>0.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>akka-util</artifactId>
|
||||
<groupId>se.scalablesolutions.akka</groupId>
|
||||
<version>0.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>jsr250-api</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-server</artifactId>
|
||||
<version>1.1.1-ea</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>jsr311-api</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.liftweb</groupId>
|
||||
<artifactId>lift-util</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
334
akka-security/src/main/scala/Security.scala
Normal file
334
akka-security/src/main/scala/Security.scala
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
/*
|
||||
* Copyright 2007-2008 WorldWide Conferencing, LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* AKKA AAS (Authentication and Authorization Service)
|
||||
* Rework of lift's (www.liftweb.com) HTTP Authentication module
|
||||
* All cred to the Lift team (www.liftweb.com), especially David Pollak and Tim Perrett
|
||||
*/
|
||||
|
||||
package se.scalablesolutions.akka.security
|
||||
|
||||
import _root_.se.scalablesolutions.akka.actor.{Scheduler,Actor,ActorRegistry}
|
||||
import _root_.se.scalablesolutions.akka.state.{TransactionalState,PersistentStorageConfig}
|
||||
import _root_.se.scalablesolutions.akka.util.{Logging}
|
||||
|
||||
import _root_.com.sun.jersey.api.model.AbstractMethod
|
||||
import _root_.com.sun.jersey.spi.container.{ResourceFilterFactory,ContainerRequest,ContainerRequestFilter,ContainerResponse,ContainerResponseFilter,ResourceFilter}
|
||||
import _root_.com.sun.jersey.core.util.Base64
|
||||
import _root_.javax.ws.rs.core.{SecurityContext,Context,Response}
|
||||
import _root_.javax.ws.rs.WebApplicationException
|
||||
import _root_.javax.annotation.security.{DenyAll,PermitAll,RolesAllowed}
|
||||
import _root_.java.security.Principal
|
||||
import _root_.java.util.concurrent.TimeUnit
|
||||
|
||||
import _root_.net.liftweb.util.{SecurityHelpers, StringHelpers,IoHelpers}
|
||||
|
||||
object Enc extends SecurityHelpers with StringHelpers with IoHelpers
|
||||
|
||||
case object OK
|
||||
|
||||
/**
|
||||
* Authenticate represents a message to authenticate a request
|
||||
*/
|
||||
case class Authenticate(val req : ContainerRequest, val rolesAllowed : List[String])
|
||||
|
||||
/**
|
||||
* User info represents a sign-on with associated credentials/roles
|
||||
*/
|
||||
case class UserInfo(val username : String,val password : String,val roles : List[String])
|
||||
|
||||
|
||||
|
||||
trait Credentials
|
||||
|
||||
case class BasicCredentials(username : String, password : String) extends Credentials
|
||||
|
||||
case class DigestCredentials(method: String,
|
||||
userName: String,
|
||||
realm: String,
|
||||
nonce: String,
|
||||
uri: String,
|
||||
qop: String,
|
||||
nc: String,
|
||||
cnonce: String,
|
||||
response: String,
|
||||
opaque: String) extends Credentials
|
||||
|
||||
/**
|
||||
* Jersey Filter for invocation intercept and authorization/authentication
|
||||
*/
|
||||
class AkkaSecurityFilterFactory extends ResourceFilterFactory with Logging {
|
||||
|
||||
class Filter(actor : Actor,rolesAllowed : Option[List[String]]) extends ResourceFilter with ContainerRequestFilter with Logging {
|
||||
|
||||
override def getRequestFilter : ContainerRequestFilter = this
|
||||
override def getResponseFilter : ContainerResponseFilter = null
|
||||
|
||||
/**
|
||||
* Here's where the magic happens. The request is authenticated by
|
||||
* sending a request for authentication to the configured authenticator actor
|
||||
*/
|
||||
override def filter(request : ContainerRequest) : ContainerRequest =
|
||||
rolesAllowed match {
|
||||
case Some(roles) => {
|
||||
|
||||
val result : AnyRef = (authenticator !? Authenticate(request,roles))
|
||||
|
||||
result match {
|
||||
case OK => request
|
||||
case r if r.isInstanceOf[Response] =>
|
||||
throw new WebApplicationException(r.asInstanceOf[Response])
|
||||
case x => {
|
||||
log.error("Authenticator replied with unexpected result: ",x);
|
||||
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
}
|
||||
}
|
||||
case None => throw new WebApplicationException(Response.Status.FORBIDDEN)
|
||||
}
|
||||
}
|
||||
|
||||
lazy val authenticatorFQN = akka.Config.config.getString("akka.rest.authenticator").getOrElse(throw new IllegalStateException("akka.rest.authenticator"))
|
||||
|
||||
/**
|
||||
* Currently we always take the first, since there usually should be at most one authentication actor, but a round-robin
|
||||
* strategy could be implemented in the future
|
||||
*/
|
||||
def authenticator : Actor = ActorRegistry.actorsFor(authenticatorFQN).head
|
||||
|
||||
def mkFilter(roles : Option[List[String]]) : java.util.List[ResourceFilter] = java.util.Collections.singletonList(new Filter(authenticator,roles))
|
||||
|
||||
/**
|
||||
* The create method is invoked for each resource, and we look for javax.annotation.security annotations
|
||||
* and create the appropriate Filter configurations for each.
|
||||
*/
|
||||
override def create(am : AbstractMethod) : java.util.List[ResourceFilter] = {
|
||||
|
||||
//DenyAll takes precedence
|
||||
if (am.isAnnotationPresent(classOf[DenyAll]))
|
||||
return mkFilter(None)
|
||||
|
||||
//Method-level RolesAllowed takes precedence
|
||||
val ra = am.getAnnotation(classOf[RolesAllowed])
|
||||
|
||||
if (ra ne null)
|
||||
return mkFilter(Some(ra.value.toList))
|
||||
|
||||
//PermitAll takes precedence over resource-level RolesAllowed annotation
|
||||
if (am.isAnnotationPresent(classOf[PermitAll]))
|
||||
return null;
|
||||
|
||||
//Last but not least, the resource-level RolesAllowed
|
||||
val cra = am.getResource.getAnnotation(classOf[RolesAllowed])
|
||||
if (cra ne null)
|
||||
return mkFilter(Some(ra.value.toList))
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AuthenticationActor is the super-trait for actors doing Http authentication
|
||||
* It defines the common ground and the flow of execution
|
||||
*/
|
||||
trait AuthenticationActor[C <: Credentials] extends Actor with Logging
|
||||
{
|
||||
type Req = ContainerRequest
|
||||
|
||||
//What realm does the authentication use?
|
||||
def realm : String
|
||||
|
||||
//Creates a response to signal unauthorized
|
||||
def unauthorized : Response
|
||||
|
||||
//Used to extract information from the request, returns None if no credentials found
|
||||
def extractCredentials(r : Req) : Option[C]
|
||||
|
||||
//returns None is unverified
|
||||
def verify(c : Option[C]) : Option[UserInfo]
|
||||
|
||||
//Contruct a new SecurityContext from the supplied parameters
|
||||
def mkSecurityContext(r : Req, user : UserInfo) : SecurityContext
|
||||
|
||||
//This is the default security context factory
|
||||
def mkDefaultSecurityContext(r : Req,u : UserInfo, scheme : String) : SecurityContext = {
|
||||
val n = u.username
|
||||
val p = new Principal { def getName = n }
|
||||
|
||||
new SecurityContext {
|
||||
def getAuthenticationScheme = scheme
|
||||
def getUserPrincipal = p
|
||||
def isSecure = r.isSecure
|
||||
def isUserInRole(role : String) = u.roles.exists(_ == role)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible for the execution flow of authentication
|
||||
*
|
||||
* Credentials are extracted and verified from the request,
|
||||
* and a se3curity context is created for the ContainerRequest
|
||||
* this should ensure good integration with current Jersey security
|
||||
*/
|
||||
protected val authenticate: PartialFunction[Any,Unit] = {
|
||||
case Authenticate(req,roles) => {
|
||||
verify(extractCredentials(req)) match {
|
||||
case Some(u : UserInfo) => {
|
||||
|
||||
req.setSecurityContext(mkSecurityContext(req,u))
|
||||
|
||||
if(roles.exists(req.isUserInRole(_)))
|
||||
reply(OK)
|
||||
else
|
||||
reply(Response.status(Response.Status.FORBIDDEN).build)
|
||||
}
|
||||
case _ => reply(unauthorized)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def receive: PartialFunction[Any, Unit] = authenticate
|
||||
|
||||
//returns the string value of the "Authorization"-header of the request
|
||||
def auth(r : Req) = r.getHeaderValue("Authorization")
|
||||
|
||||
//Turns the aforementioned header value into an option
|
||||
def authOption(r : Req) : Option[String] = {
|
||||
val a = auth(r)
|
||||
if(a != null && a.length > 0) Some(a) else None
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This trait implements the logic for Http Basic authentication
|
||||
* mix this trait into a class to create an authenticator
|
||||
* Don't forget to set the authenticator FQN in the rest-part of the akka config
|
||||
*/
|
||||
trait BasicAuthenticationActor extends AuthenticationActor[BasicCredentials]
|
||||
{
|
||||
override def unauthorized =
|
||||
Response.status(401).header("WWW-Authenticate","Basic realm=\"" + realm + "\"").build
|
||||
|
||||
override def extractCredentials(r : Req) : Option[BasicCredentials] = {
|
||||
val a = r.getHeaderValue("Authorization")
|
||||
new String(Base64.decode(a.substring(6,a.length).getBytes)).split(":").toList match {
|
||||
case userName :: password :: _ => Some(BasicCredentials(userName, password))
|
||||
case userName :: Nil => Some(BasicCredentials(userName, ""))
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
|
||||
override def mkSecurityContext(r : Req,u : UserInfo) : SecurityContext =
|
||||
mkDefaultSecurityContext(r,u,SecurityContext.BASIC_AUTH)
|
||||
}
|
||||
|
||||
/**
|
||||
* This trait implements the logic for Http Digest authentication
|
||||
* mix this trait into a class to create an authenticator
|
||||
* Don't forget to set the authenticator FQN in the rest-part of the akka config
|
||||
*/
|
||||
trait DigestAuthenticationActor extends AuthenticationActor[DigestCredentials]
|
||||
{
|
||||
import Enc._
|
||||
|
||||
private object InvalidateNonces
|
||||
|
||||
//Holds the generated nonces for the specified validity period
|
||||
val nonceMap = mkNonceMap
|
||||
|
||||
//Discards old nonces
|
||||
protected val invalidateNonces: PartialFunction[Any,Unit] = {
|
||||
case InvalidateNonces =>
|
||||
{
|
||||
val ts = System.currentTimeMillis
|
||||
|
||||
nonceMap.retain((k,v) => (ts - v) < nonceValidityPeriod)
|
||||
}
|
||||
|
||||
case e => log.info("Don't know what to do with: " + e)
|
||||
}
|
||||
|
||||
//Schedule the invalidation of nonces
|
||||
Scheduler.schedule(this, InvalidateNonces, noncePurgeInterval, noncePurgeInterval, TimeUnit.MILLISECONDS )
|
||||
|
||||
//authenticate or invalidate nonces
|
||||
override def receive: PartialFunction[Any, Unit] = authenticate orElse invalidateNonces
|
||||
|
||||
override def unauthorized : Response =
|
||||
{
|
||||
val nonce = randomString(64);
|
||||
nonceMap.put(nonce,System.currentTimeMillis)
|
||||
unauthorized(nonce,"auth",randomString(64))
|
||||
}
|
||||
|
||||
def unauthorized(nonce : String, qop : String, opaque : String) : Response =
|
||||
{
|
||||
Response.status(401).header("WWW-Authenticate",
|
||||
"Digest realm=\"" + realm + "\", " +
|
||||
"qop=\"" + qop + "\", " +
|
||||
"nonce=\"" + nonce + "\", " +
|
||||
"opaque=\"" + opaque + "\"").build
|
||||
}
|
||||
|
||||
//Tests wether the specified credentials are valid
|
||||
def validate(auth: DigestCredentials,user : UserInfo) : Boolean = {
|
||||
def h(s : String) = hexEncode(md5(s.getBytes("UTF-8")))
|
||||
|
||||
val ha1 = h(auth.userName + ":" + auth.realm + ":" + user.password)
|
||||
val ha2 = h(auth.method + ":" + auth.uri)
|
||||
|
||||
val response = h(ha1 + ":" + auth.nonce + ":" +
|
||||
auth.nc + ":" + auth.cnonce + ":" +
|
||||
auth.qop + ":" + ha2)
|
||||
|
||||
(response == auth.response) && (nonceMap.getOrElse(auth.nonce, -1) != -1)
|
||||
}
|
||||
|
||||
override def verify(odc : Option[DigestCredentials]) : Option[UserInfo] = odc match {
|
||||
case Some(dc) => {
|
||||
userInfo(dc.userName) match {
|
||||
case Some(u) if validate(dc,u) =>
|
||||
nonceMap.get(dc.nonce).map( t => (System.currentTimeMillis - t) < nonceValidityPeriod ).map(_ => u)
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
case _ => None
|
||||
}
|
||||
|
||||
override def extractCredentials(r : Req) : Option[DigestCredentials] =
|
||||
{
|
||||
authOption(r).map( s => {
|
||||
val ? = splitNameValuePairs(s.substring(7,s.length ))
|
||||
|
||||
DigestCredentials(r.getMethod.toUpperCase, ?("username"), ?("realm"), ?("nonce"),
|
||||
?("uri"), ?("qop"), ?("nc"),
|
||||
?("cnonce"), ?("response"), ?("opaque"))
|
||||
})
|
||||
}
|
||||
|
||||
override def mkSecurityContext(r : Req,u : UserInfo) : SecurityContext =
|
||||
mkDefaultSecurityContext(r,u,SecurityContext.DIGEST_AUTH)
|
||||
|
||||
//Mandatory overrides
|
||||
def userInfo(username : String) : Option[UserInfo]
|
||||
|
||||
def mkNonceMap : scala.collection.mutable.Map[String,Long]
|
||||
|
||||
//Optional overrides
|
||||
def nonceValidityPeriod = 60*1000//ms
|
||||
def noncePurgeInterval = 2*60*1000 //ms
|
||||
}
|
||||
46
akka.ipr
46
akka.ipr
|
|
@ -261,6 +261,8 @@
|
|||
<module fileurl="file://$PROJECT_DIR$/akka-samples-java/akka-samples-java.iml" filepath="$PROJECT_DIR$/akka-samples-java/akka-samples-java.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/akka-samples-lift/akka-samples-lift.iml" filepath="$PROJECT_DIR$/akka-samples-lift/akka-samples-lift.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/akka-samples-scala/akka-samples-scala.iml" filepath="$PROJECT_DIR$/akka-samples-scala/akka-samples-scala.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/akka-samples-security/akka-samples-security.iml" filepath="$PROJECT_DIR$/akka-samples-security/akka-samples-security.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/akka-security/akka-security.iml" filepath="$PROJECT_DIR$/akka-security/akka-security.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/akka-util/akka-util.iml" filepath="$PROJECT_DIR$/akka-util/akka-util.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/akka-util-java/akka-util-java.iml" filepath="$PROJECT_DIR$/akka-util-java/akka-util-java.iml" />
|
||||
</modules>
|
||||
|
|
@ -1384,6 +1386,50 @@
|
|||
<root url="jar://$MAVEN_REPOSITORY$/org/scala-tools/testing/scalatest/0.9.5/scalatest-0.9.5-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: javax.annotation:jsr250-api:1.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/javax/annotation/jsr250-api/1.0/jsr250-api-1.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/javax/annotation/jsr250-api/1.0/jsr250-api-1.0-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/javax/annotation/jsr250-api/1.0/jsr250-api-1.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: org.mortbay.jetty:jetty:7.0.0.pre5">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/mortbay/jetty/jetty/7.0.0.pre5/jetty-7.0.0.pre5.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/mortbay/jetty/jetty/7.0.0.pre5/jetty-7.0.0.pre5-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/mortbay/jetty/jetty/7.0.0.pre5/jetty-7.0.0.pre5-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: org.mortbay.jetty:servlet-api:3.0.pre4">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/mortbay/jetty/servlet-api/3.0.pre4/servlet-api-3.0.pre4.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/mortbay/jetty/servlet-api/3.0.pre4/servlet-api-3.0.pre4-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/mortbay/jetty/servlet-api/3.0.pre4/servlet-api-3.0.pre4-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: org.mortbay.jetty:jetty-util:7.0.0.pre5">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/mortbay/jetty/jetty-util/7.0.0.pre5/jetty-util-7.0.0.pre5.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/mortbay/jetty/jetty-util/7.0.0.pre5/jetty-util-7.0.0.pre5-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/mortbay/jetty/jetty-util/7.0.0.pre5/jetty-util-7.0.0.pre5-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
<UsedPathMacros>
|
||||
<macro name="MAVEN_REPOSITORY" description="Maven Local Repostiry" />
|
||||
|
|
|
|||
82
akka.iws
82
akka.iws
|
|
@ -2,17 +2,9 @@
|
|||
<project relativePaths="false" version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" readonly="true" id="188c966f-a83c-4d3a-9128-54d5a2947a12" name="Default" comment="">
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka-actors/src/main/scala/actor/Actor.scala" afterPath="$PROJECT_DIR$/akka-actors/src/main/scala/actor/Actor.scala" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka-persistence/src/test/scala/MongoPersistentActorSpec.scala" afterPath="$PROJECT_DIR$/akka-persistence/src/test/scala/MongoPersistentActorSpec.scala" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka-actors/src/test/scala/InMemoryActorSpec.scala" afterPath="$PROJECT_DIR$/akka-actors/src/test/scala/InMemoryActorSpec.scala" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka-persistence/src/test/scala/AllTest.scala" afterPath="$PROJECT_DIR$/akka-persistence/src/test/scala/AllTest.scala" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka-persistence/src/main/scala/CassandraStorage.scala" afterPath="$PROJECT_DIR$/akka-persistence/src/main/scala/CassandraStorage.scala" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka-persistence/src/test/scala/CassandraPersistentActorSpec.scala" afterPath="$PROJECT_DIR$/akka-persistence/src/test/scala/CassandraPersistentActorSpec.scala" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka.ipr" afterPath="$PROJECT_DIR$/akka.ipr" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka.iws" afterPath="$PROJECT_DIR$/akka.iws" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka-actors/src/main/scala/stm/TransactionalState.scala" afterPath="$PROJECT_DIR$/akka-actors/src/main/scala/stm/TransactionalState.scala" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka-actors/src/main/scala/stm/TransactionManagement.scala" afterPath="$PROJECT_DIR$/akka-actors/src/main/scala/stm/TransactionManagement.scala" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka-persistence/src/main/scala/PersistentState.scala" afterPath="$PROJECT_DIR$/akka-persistence/src/main/scala/PersistentState.scala" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka-actors/src/main/scala/stm/Transaction.scala" afterPath="$PROJECT_DIR$/akka-actors/src/main/scala/stm/Transaction.scala" />
|
||||
</list>
|
||||
<ignored path=".idea/workspace.xml" />
|
||||
<ignored path="akka.iws" />
|
||||
|
|
@ -120,16 +112,34 @@
|
|||
<file leaf-file-name="InMemoryActorSpec.scala" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/akka-actors/src/test/scala/InMemoryActorSpec.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="38" column="0" selection-start="1046" selection-end="1433" vertical-scroll-proportion="0.0">
|
||||
<state line="30" column="59" selection-start="1165" selection-end="1165" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="MongoPersistentActorSpec.scala" pinned="false" current="true" current-in-tab="true">
|
||||
<file leaf-file-name="MongoPersistentActorSpec.scala" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/akka-persistence/src/test/scala/MongoPersistentActorSpec.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="33" column="0" selection-start="1045" selection-end="1045" vertical-scroll-proportion="0.6984127">
|
||||
<state line="33" column="0" selection-start="1045" selection-end="1045" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="TransactionalState.scala" pinned="false" current="true" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/akka-actors/src/main/scala/stm/TransactionalState.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="38" column="18" selection-start="919" selection-end="919" vertical-scroll-proportion="0.28222525">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="PersistentState.scala" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/akka-persistence/src/main/scala/PersistentState.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="263" column="5" selection-start="9023" selection-end="9023" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
|
|
@ -155,10 +165,10 @@
|
|||
<option value="$PROJECT_DIR$/akka-actors/src/main/scala/actor/Actor.scala" />
|
||||
<option value="$PROJECT_DIR$/akka-persistence/src/test/scala/AllTest.scala" />
|
||||
<option value="$PROJECT_DIR$/akka-persistence/src/main/scala/CassandraStorage.scala" />
|
||||
<option value="$PROJECT_DIR$/akka-persistence/src/main/scala/PersistentState.scala" />
|
||||
<option value="$PROJECT_DIR$/akka-actors/src/main/scala/stm/TransactionalState.scala" />
|
||||
<option value="$PROJECT_DIR$/akka-persistence/src/test/scala/CassandraPersistentActorSpec.scala" />
|
||||
<option value="$PROJECT_DIR$/akka-persistence/src/test/scala/MongoPersistentActorSpec.scala" />
|
||||
<option value="$PROJECT_DIR$/akka-persistence/src/main/scala/PersistentState.scala" />
|
||||
<option value="$PROJECT_DIR$/akka-actors/src/main/scala/stm/TransactionalState.scala" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
|
|
@ -759,27 +769,6 @@
|
|||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/akka-actors/src/main/scala/stm/TransactionalState.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="41" column="38" selection-start="1050" selection-end="1050" vertical-scroll-proportion="0.043419268">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/akka-persistence/src/main/scala/PersistentState.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="160" column="49" selection-start="6053" selection-end="6053" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/akka-actors/src/test/scala/InMemoryActorSpec.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="38" column="0" selection-start="1046" selection-end="1433" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/akka-persistence/src/test/scala/CassandraPersistentActorSpec.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="42" column="0" selection-start="969" selection-end="1352" vertical-scroll-proportion="0.0">
|
||||
|
|
@ -789,7 +778,28 @@
|
|||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/akka-persistence/src/test/scala/MongoPersistentActorSpec.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="33" column="0" selection-start="1045" selection-end="1045" vertical-scroll-proportion="0.6984127">
|
||||
<state line="33" column="0" selection-start="1045" selection-end="1045" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/akka-persistence/src/main/scala/PersistentState.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="263" column="5" selection-start="9023" selection-end="9023" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/akka-actors/src/test/scala/InMemoryActorSpec.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="30" column="59" selection-start="1165" selection-end="1165" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/akka-actors/src/main/scala/stm/TransactionalState.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="38" column="18" selection-start="919" selection-end="919" vertical-scroll-proportion="0.28222525">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<akka>
|
||||
version = "0.6"
|
||||
|
||||
boot = ["sample.java.Boot", "sample.scala.Boot"] # FQN to the class doing initial active object/actor
|
||||
boot = ["sample.java.Boot", "sample.scala.Boot", "sample.secure.Boot"] # FQN to the class doing initial active object/actor
|
||||
# supervisor bootstrap, should be defined in default constructor
|
||||
<actor>
|
||||
timeout = 5000 # default timeout for future based invocations
|
||||
|
|
@ -44,6 +44,8 @@
|
|||
service = on
|
||||
hostname = "localhost"
|
||||
port = 9998
|
||||
filters = "se.scalablesolutions.akka.security.AkkaSecurityFilterFactory;org.atmosphere.core.AtmosphereFilter"
|
||||
authenticator = "sample.secure.SimpleAuthenticationService"
|
||||
</rest>
|
||||
|
||||
<storage>
|
||||
|
|
|
|||
2
pom.xml
2
pom.xml
|
|
@ -25,11 +25,13 @@
|
|||
<module>akka-rest</module>
|
||||
<module>akka-camel</module>
|
||||
<module>akka-amqp</module>
|
||||
<module>akka-security</module>
|
||||
<module>akka-kernel</module>
|
||||
<module>akka-fun-test-java</module>
|
||||
<module>akka-samples-scala</module>
|
||||
<module>akka-samples-lift</module>
|
||||
<module>akka-samples-java</module>
|
||||
<module>akka-samples-security</module>
|
||||
</modules>
|
||||
|
||||
<organization>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue