Adding PojoSR tests and a lot of code cleanup

This commit is contained in:
Gert Vanthienen 2012-06-12 16:08:19 +02:00
parent 94d68e8f2d
commit cc79aae1a4
18 changed files with 517 additions and 170 deletions

View file

@ -1,4 +1,4 @@
import akka.actor.{Props, ActorSystem}
import akka.actor.{ Props, ActorSystem }
import akka.osgi.ActorSystemActivator
import org.apache.servicemix.examples.akka.Listener
import org.apache.servicemix.examples.akka.Master

View file

@ -1,25 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
-->
<!-- $Rev: 699828 $ $Date: 2008-09-28 16:35:27 +0200 (Sun, 28 Sep 2008) $ -->
<xsd:schema xmlns="http://akka.io/xmlns/blueprint/v1.0.0"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:bp="http://www.osgi.org/xmlns/blueprint/v1.0.0"
@ -44,24 +23,20 @@
</xsd:annotation>
<xsd:sequence>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="actor"/>
<xsd:element ref="config" />
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:ID"/>
<xsd:attribute name="name" type="xsd:string" use="optional"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="actor">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Defines an Akka Actor
</xsd:documentation>
</xsd:annotation>
<xsd:attribute name="id" type="xsd:ID"/>
<xsd:attribute name="name" type="xsd:string" use="optional"/>
<xsd:attribute name="class" type="xsd:string" use="optional"/>
</xsd:complexType>
<xsd:element name="config" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Defines an Akka ActorSystem configuration
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:schema>

View file

@ -40,7 +40,6 @@ abstract class ActorSystemActivator(nameFor: (BundleContext) ⇒ String) extends
*/
def stop(context: BundleContext) {
if (system != null) {
system.shutdown()
system.shutdown()
system = null
}

View file

@ -2,9 +2,9 @@ package akka.osgi
import impl.BundleDelegatingClassLoader
import org.osgi.framework.BundleContext
import java.util.Properties
import akka.actor.ActorSystem
import com.typesafe.config.{ ConfigFactory, Config }
import java.util.{ Dictionary, Properties }
/**
* Factory class to create ActorSystem implementations in an OSGi environment. This mainly involves dealing with
@ -20,16 +20,18 @@ class OsgiActorSystemFactory(val context: BundleContext) {
/**
* Creates the ActorSystem and registers it in the OSGi Service Registry
*/
def createActorSystem(name: String) = {
def createActorSystem(name: String): ActorSystem = createActorSystem(Option(name))
def createActorSystem(name: Option[String]): ActorSystem = {
val system = ActorSystem(actorSystemName(name), actorSystemConfig(context), classloader)
registerService(system)
system
}
def registerService(system: ActorSystem) {
val properties = new Properties();
val properties = new Properties()
properties.put("name", system.name)
context.registerService(classOf[ActorSystem].getName, system, properties)
context.registerService(classOf[ActorSystem].getName, system, properties.asInstanceOf[Dictionary[String, Any]])
}
/**
@ -44,8 +46,8 @@ class OsgiActorSystemFactory(val context: BundleContext) {
/**
* Determine a the ActorSystem name
*/
def actorSystemName(name: String): String =
Option(name).getOrElse("bundle-%s-ActorSystem".format(context.getBundle().getBundleId))
def actorSystemName(name: Option[String]): String =
name.getOrElse("bundle-%s-ActorSystem".format(context.getBundle().getBundleId))
}

View file

@ -4,31 +4,39 @@ import org.osgi.framework.BundleContext
import akka.osgi.OsgiActorSystemFactory
import collection.mutable.Buffer
import akka.actor.{ Actor, Props, ActorSystem }
import com.typesafe.config.ConfigFactory
/**
* A set of helper/factory classes to build a Akka system using Blueprint
*/
class BlueprintActorSystemFactory(context: BundleContext, name: String) extends OsgiActorSystemFactory(context) {
val systems: Buffer[ActorSystem] = Buffer()
var config: Option[String] = None
def this(context: BundleContext) = this(context, null)
lazy val system = super.createActorSystem(stringToOption(name))
def create: ActorSystem = create(null)
def create(name: String): ActorSystem = {
val system = super.createActorSystem(name)
systems += system
system
def setConfig(config: String) = { this.config = Some(config) }
def create = system
def destroy = system.shutdown()
def stringToOption(original: String) = if (original == null || original.isEmpty) {
None
} else {
Some(original)
}
def destroy = for (system systems) {
system.shutdown()
/**
* Strategy method to create the Config for the ActorSystem, ensuring that the default/reference configuration is
* loaded from the akka-actor bundle.
*/
override def actorSystemConfig(context: BundleContext) = {
config match {
case Some(value) ConfigFactory.parseString(value).withFallback(super.actorSystemConfig(context))
case None super.actorSystemConfig(context)
}
}
}
class BlueprintActorSystem(context: BundleContext, system: ActorSystem) {
def createActor(name: String) = system.actorOf(Props(context.getBundle.loadClass(name).asInstanceOf[Class[Actor]]))
}

View file

@ -9,92 +9,122 @@ import org.osgi.framework.BundleContext
import org.apache.aries.blueprint.reflect.{ ValueMetadataImpl, RefMetadataImpl, BeanArgumentImpl }
import org.w3c.dom.{ NodeList, Element, Node }
import org.osgi.service.blueprint.reflect.{ BeanMetadata, ComponentMetadata }
import akka.actor.{ ActorRef, ActorSystem }
import akka.osgi.blueprint.{ BlueprintActorSystem, BlueprintActorSystemFactory }
import akka.actor.{ ActorSystem }
import akka.osgi.blueprint.{ BlueprintActorSystemFactory }
import java.util.concurrent.atomic.AtomicInteger
import ParserHelper.childElements
/**
* Aries Blueprint namespace handler implementation
*/
class NamespaceHandler extends org.apache.aries.blueprint.NamespaceHandler {
val CLASS_ATTRIBUTE = "class";
val ID_ATTRIBUTE = "id";
val NAME_ATTRIBUTE = "name";
import NamespaceHandler._
var idCounter = 1
val idCounter = new AtomicInteger(0)
def getSchemaLocation(namespace: String) = getClass().getResource("akka.xsd")
def getManagedClasses = setAsJavaSet(Set(classOf[BlueprintActorSystemFactory]))
def parse(element: Element, context: ParserContext) = {
val factory = context.createMetadata(classOf[MutableBeanMetadata])
factory.setId(getId(context, element))
factory.setScope(BeanMetadata.SCOPE_SINGLETON)
factory.setProcessor(true)
factory.setClassName(classOf[BlueprintActorSystemFactory].getName)
factory.setDestroyMethod("destroy")
factory.addArgument(new BeanArgumentImpl(new RefMetadataImpl("blueprintBundleContext"), classOf[BundleContext].getName, -1))
val system = context.createMetadata(classOf[MutableBeanMetadata])
system.setId(getId(context, element))
system.setFactoryComponent(factory)
system.setFactoryMethod("create")
system.setRuntimeClass(classOf[ActorSystem])
if (element.hasAttribute(NAME_ATTRIBUTE)) {
system.addArgument(new BeanArgumentImpl(new ValueMetadataImpl(element.getAttribute(NAME_ATTRIBUTE)), classOf[String].getName, -1))
}
val actorsystem = context.createMetadata(classOf[MutableBeanMetadata])
actorsystem.setId(getId(context, element))
actorsystem.setClassName(classOf[BlueprintActorSystem].getName)
actorsystem.addArgument(new BeanArgumentImpl(new RefMetadataImpl("blueprintBundleContext"), classOf[BundleContext].getName, -1))
actorsystem.addArgument(new BeanArgumentImpl(system, classOf[ActorSystem].getName, -1))
context.getComponentDefinitionRegistry.registerComponentDefinition(actorsystem)
val nodelist = element.getChildNodes
var i = 0
while (i < nodelist.getLength) {
val node = nodelist.item(i)
node.getLocalName match {
case "actor" if node.isInstanceOf[Element] parseActor(node.asInstanceOf[Element], context, actorsystem)
case _
}
i += 1
}
factory
}
def parseActor(node: Element, context: ParserContext, actorsystem: MutableBeanMetadata) = {
val actor = context.createMetadata(classOf[MutableBeanMetadata])
actor.setFactoryComponent(actorsystem)
if (node.hasAttribute(CLASS_ATTRIBUTE)) {
actor.addArgument(new BeanArgumentImpl(new ValueMetadataImpl(node.getAttribute(CLASS_ATTRIBUTE)), classOf[String].getName, -1))
}
actor.setId(getId(context, node))
actor.setFactoryMethod("createActor")
// actor.setRuntimeClass(classOf[ActorRef])
context.getComponentDefinitionRegistry.registerComponentDefinition(actor)
def parse(element: Element, context: ParserContext) = element.getLocalName match {
case ACTORSYSTEM_ELEMENT_NAME parseActorSystem(element, context)
case _ throw new ComponentDefinitionException("Unexpected element for Akka namespace: %s".format(element))
}
def decorate(node: Node, component: ComponentMetadata, context: ParserContext) =
throw new ComponentDefinitionException("Bad xml syntax: node decoration is not supported");
/*
* Parse <akka:actor-system/>
*/
def parseActorSystem(element: Element, context: ParserContext) = {
val factory = createFactoryBean(context, element.getAttribute(NAME_ATTRIBUTE))
for (child childElements(element)) {
child.getLocalName match {
case CONFIG_ELEMENT_NAME parseConfig(child, context, factory)
case _ throw new ComponentDefinitionException("Unexpected child element %s found in %s".format(child, element))
}
}
createActorSystemBean(context, element, factory)
}
/*
* Parse <akka:config/>
*/
def parseConfig(node: Element, context: ParserContext, factory: MutableBeanMetadata) = {
factory.addProperty("config", new ValueMetadataImpl(node.getTextContent))
}
/*
* Create the bean definition for the ActorSystem
*/
def createActorSystemBean(context: ParserContext, element: Element, factory: MutableBeanMetadata): MutableBeanMetadata = {
val system = context.createMetadata(classOf[MutableBeanMetadata])
system.setId(getId(context, element))
system.setFactoryComponent(factory)
system.setFactoryMethod(FACTORY_METHOD_NAME)
system.setRuntimeClass(classOf[ActorSystem])
system
}
/*
* Create the bean definition for the BlueprintActorSystemFactory
*/
def createFactoryBean(context: ParserContext, name: String): MutableBeanMetadata = {
val factory = context.createMetadata(classOf[MutableBeanMetadata])
factory.setId(findAvailableId(context))
factory.setScope(BeanMetadata.SCOPE_SINGLETON)
factory.setProcessor(true)
factory.setClassName(classOf[BlueprintActorSystemFactory].getName)
factory.setDestroyMethod(DESTROY_METHOD_NAME)
factory.addArgument(new BeanArgumentImpl(new RefMetadataImpl(BUNDLE_CONTEXT_REFID), classOf[BundleContext].getName, -1))
factory.addArgument(new BeanArgumentImpl(new ValueMetadataImpl(name), classOf[String].getName, -1))
factory.setProcessor(true)
context.getComponentDefinitionRegistry.registerComponentDefinition(factory)
factory
}
/*
* Get the assigned id or generate a suitable id
*/
def getId(context: ParserContext, element: Element) = {
if (element.hasAttribute(ID_ATTRIBUTE)) {
element.getAttribute(ID_ATTRIBUTE);
} else {
generateId(context);
findAvailableId(context);
}
}
def generateId(context: ParserContext): String = {
var id = "";
do {
idCounter += 1
id = ".akka-" + idCounter;
} while (context.getComponentDefinitionRegistry().containsComponentDefinition(id));
id;
/*
* Find the next available component id
*/
def findAvailableId(context: ParserContext): String = {
val id = ".akka-" + idCounter.incrementAndGet()
if (context.getComponentDefinitionRegistry.containsComponentDefinition(id)) {
// id already exists, let's try the next one
findAvailableId(context)
} else id
}
}
object NamespaceHandler {
private val ID_ATTRIBUTE = "id";
private val NAME_ATTRIBUTE = "name";
private val BUNDLE_CONTEXT_REFID = "blueprintBundleContext"
private val ACTORSYSTEM_ELEMENT_NAME = "actor-system"
private val CONFIG_ELEMENT_NAME = "config"
private val DESTROY_METHOD_NAME = "destroy"
private val FACTORY_METHOD_NAME = "create"
}

View file

@ -0,0 +1,16 @@
package akka.osgi.blueprint.aries
import org.w3c.dom.{ Node, Element }
/**
* Helper class to deal with the W3C DOM types
*/
object ParserHelper {
def childElements(element: Element) = children(element).filter(_.getNodeType == Node.ELEMENT_NODE).asInstanceOf[Seq[Element]]
private[this] def children(element: Element) = {
val nodelist = element.getChildNodes
for (index 0 until nodelist.getLength) yield nodelist.item(index)
}
}

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:akka="http://akka.io/xmlns/blueprint/v1.0.0">
<akka:actor-system name="config">
<akka:config>
some.config {
key=value
}
</akka:config>
</akka:actor-system>
</blueprint>

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:akka="http://akka.io/xmlns/blueprint/v1.0.0">
<service interface="akka.osgi.test.ActorSystemAwareBean">
<bean class="akka.osgi.test.ActorSystemAwareBean">
<argument>
<akka:actor-system name="simple" />
</argument>
</bean>
</service>
</blueprint>

View file

@ -1,9 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:akka="http://akka.io/xmlns/blueprint/aries/v1.0.0">
xmlns:akka="http://akka.io/xmlns/blueprint/v1.0.0">
<akka:actor-system name="test">
<akka:actor/>
</akka:actor-system>
<akka:actor-system name="simple" />
</blueprint>

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{ISO8601} %-5level %logger %X{akkaSource} %X{sourceThread} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>target/akka-osgi.log</file>
<append>true</append>
<encoder>
<pattern>%date{ISO8601} %-5level %logger %X{akkaSource} %X{sourceThread} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>

View file

@ -1,53 +1,28 @@
package akka.osgi
import java.util.{ ServiceLoader, HashMap }
import de.kalpatec.pojosr.framework.launch.{ ClasspathScanner, PojoServiceRegistryFactory }
import org.scalatest.FlatSpec
import org.osgi.framework.BundleContext
import akka.actor.{ Actor, Props, ActorSystem }
import akka.actor.ActorSystem
import akka.pattern.ask
import akka.dispatch.Await
import akka.util.duration._
import akka.util.Timeout
import de.kalpatec.pojosr.framework.launch.BundleDescriptor
import test.TestActorSystemActivator
import test.PingPong._
import PojoSRTestSupport.bundle
/**
* Test cases for {@link ActorSystemActivator}
*/
class ActorSystemActivatorTest extends FlatSpec {
class ActorSystemActivatorTest extends FlatSpec with PojoSRTestSupport {
abstract class TestMessage
val TEST_BUNDLE_NAME = "akka.osgi.test.activator"
case object Ping extends TestMessage
case object Pong extends TestMessage
val testBundles: Seq[BundleDescriptor] = Seq(
bundle(TEST_BUNDLE_NAME).withActivator(classOf[TestActorSystemActivator]))
class PongActor extends Actor {
def receive = {
case Ping
sender ! Pong
}
}
lazy val context: BundleContext = {
val config = new HashMap[String, AnyRef]();
val loader = ServiceLoader.load(classOf[PojoServiceRegistryFactory]);
val registry = loader.iterator().next().newPojoServiceRegistry(config);
registry.getBundleContext
}
val activator = new ActorSystemActivator {
def configure(system: ActorSystem) {
system.actorOf(Props(new PongActor), name = "pong")
}
}
"ActorSystemActivator" should "start and register the ActorSystem on start" in {
activator.start(context)
val reference = context.getServiceReference(classOf[ActorSystem].getName)
assert(reference != null)
val system = context.getService(reference).asInstanceOf[ActorSystem]
"ActorSystemActivator" should "start and register the ActorSystem when bundle starts" in {
val system = serviceForType[ActorSystem]
val actor = system.actorFor("/user/pong")
implicit val timeout = Timeout(5 seconds)
@ -56,14 +31,11 @@ class ActorSystemActivatorTest extends FlatSpec {
assert(result != null)
}
it should "stop the ActorSystem on bundle stop" in {
val reference = context.getServiceReference(classOf[ActorSystem].getName)
assert(reference != null)
val system = context.getService(reference).asInstanceOf[ActorSystem]
it should "stop the ActorSystem when bundle stops" in {
val system = serviceForType[ActorSystem]
assert(!system.isTerminated)
activator.stop(context)
bundleForName(TEST_BUNDLE_NAME).stop()
system.awaitTermination()
assert(system.isTerminated)

View file

@ -0,0 +1,150 @@
package akka.osgi
import de.kalpatec.pojosr.framework.launch.{ BundleDescriptor, PojoServiceRegistryFactory, ClasspathScanner }
import scala.collection.JavaConversions.seqAsJavaList
import scala.collection.JavaConversions.collectionAsScalaIterable
import org.apache.commons.io.IOUtils.copy
import org.osgi.framework._
import java.net.URL
import java.util.jar.JarInputStream
import java.io.{ FileInputStream, FileOutputStream, File }
import java.util.{ Date, ServiceLoader, HashMap }
import org.scalatest.{ BeforeAndAfterAll, Suite }
/**
* Trait that provides support for building akka-osgi tests using PojoSR
*/
trait PojoSRTestSupport extends Suite with BeforeAndAfterAll {
val MAX_WAIT_TIME = 8000;
val START_WAIT_TIME = 100;
implicit def buildBundleDescriptor(builder: BundleDescriptorBuilder) = builder.build
/**
* All bundles being found on the test classpath are automatically installed and started in the PojoSR runtime.
* Implement this to define the extra bundles that should be available for testing.
*/
val testBundles: Seq[BundleDescriptor]
lazy val context: BundleContext = {
val config = new HashMap[String, AnyRef]();
System.setProperty("org.osgi.framework.storage", "target/akka-osgi/" + System.currentTimeMillis)
val bundles = new ClasspathScanner().scanForBundles()
bundles.addAll(testBundles)
config.put(PojoServiceRegistryFactory.BUNDLE_DESCRIPTORS, bundles);
val loader: ServiceLoader[PojoServiceRegistryFactory] = ServiceLoader.load(classOf[PojoServiceRegistryFactory])
val registry = loader.iterator.next.newPojoServiceRegistry(config)
registry.getBundleContext
}
// Ensure bundles get stopped at the end of the test to release resources and stop threads
override protected def afterAll() = context.getBundles.foreach(_.stop)
/**
* Convenience method to find a bundle by symbolic name
*/
def bundleForName(name: String) = context.getBundles.find(_.getSymbolicName == name) match {
case Some(bundle) bundle
case None fail("Unable to find bundle with symbolic name %s".format(name))
}
/**
* Convenience method to find a service by interface. If the service is not already available in the OSGi Service
* Registry, this method will wait for a few seconds for the service to appear.
*/
def serviceForType[T](implicit manifest: Manifest[T]): T = {
val reference = awaitReference(manifest.erasure)
context.getService(reference).asInstanceOf[T]
}
def awaitReference(serviceType: Class[_]): ServiceReference = awaitReference(serviceType, START_WAIT_TIME)
def awaitReference(serviceType: Class[_], wait: Long): ServiceReference = {
val option = Option(context.getServiceReference(serviceType.getName))
option match {
case Some(reference) reference;
case None if (wait > MAX_WAIT_TIME) fail("Gave up waiting for service of type %s".format(serviceType))
case None {
Thread.sleep(wait);
awaitReference(serviceType, wait * 2);
}
}
}
}
object PojoSRTestSupport {
/**
* Convenience method to define additional test bundles
*/
def bundle(name: String) = new BundleDescriptorBuilder(name)
}
/**
* Helper class to make it easier to define test bundles
*/
class BundleDescriptorBuilder(name: String) {
import org.ops4j.pax.tinybundles.core.TinyBundles
val tinybundle = TinyBundles.bundle.set(Constants.BUNDLE_SYMBOLICNAME, name)
def withBlueprintFile(name: String, contents: URL) =
returnBuilder(tinybundle.add("OSGI-INF/blueprint/%s".format(name), contents))
def withBlueprintFile(contents: URL): BundleDescriptorBuilder = withBlueprintFile(filename(contents), contents)
def withActivator(activator: Class[_ <: BundleActivator]) =
returnBuilder(tinybundle.set(Constants.BUNDLE_ACTIVATOR, activator.getName))
def returnBuilder(block: Unit) = {
block
this
}
def build = {
val file: File = tinybundleToJarFile(name)
new BundleDescriptor(
getClass().getClassLoader(),
new URL("jar:" + file.toURI().toString() + "!/"),
extractHeaders(file));
}
def extractHeaders(file: File): HashMap[String, String] = {
val headers = new HashMap[String, String]();
val jis = new JarInputStream(new FileInputStream(file));
try {
for (entry jis.getManifest().getMainAttributes().entrySet()) {
headers.put(entry.getKey().toString(), entry.getValue().toString());
}
} finally {
jis.close()
}
headers
}
def tinybundleToJarFile(name: String): File = {
val file = new File("target/%s-%tQ.jar".format(name, new Date()));
val fos = new FileOutputStream(file);
try {
copy(tinybundle.build(), fos);
} finally {
fos.close();
}
file
}
private[this] def filename(url: URL) = url.getFile.split("/").last
}

View file

@ -0,0 +1,94 @@
package akka.osgi.blueprint.aries
import org.scalatest.FlatSpec
import akka.actor.ActorSystem
import de.kalpatec.pojosr.framework.launch.BundleDescriptor
import akka.osgi.PojoSRTestSupport
import akka.osgi.PojoSRTestSupport.bundle
import akka.osgi.test.ActorSystemAwareBean
/**
* Test cases for {@link ActorSystemActivator}
*/
object NamespaceHandlerTest {
/*
* Bundle-SymbolicName to easily find our test bundle
*/
val TEST_BUNDLE_NAME = "akka.osgi.test.aries.namespace"
/*
* Bundle descriptor representing the akka-osgi bundle itself
*/
val AKKA_OSGI_BLUEPRINT =
bundle("akka-osgi").withBlueprintFile(getClass.getResource("/OSGI-INF/blueprint/akka-namespacehandler.xml"))
}
class SimpleNamespaceHandlerTest extends FlatSpec with PojoSRTestSupport {
import NamespaceHandlerTest._
val testBundles: Seq[BundleDescriptor] = Seq(
AKKA_OSGI_BLUEPRINT,
bundle(TEST_BUNDLE_NAME).withBlueprintFile(getClass.getResource("simple.xml")))
"simple.xml" should "set up ActorSystem when bundle starts" in {
val system = serviceForType[ActorSystem]
assert(system != null)
}
it should "stop the ActorSystem when bundle stops" in {
val system = serviceForType[ActorSystem]
assert(!system.isTerminated)
bundleForName(TEST_BUNDLE_NAME).stop()
system.awaitTermination()
assert(system.isTerminated)
}
}
class ConfigNamespaceHandlerTest extends FlatSpec with PojoSRTestSupport {
import NamespaceHandlerTest._
val testBundles: Seq[BundleDescriptor] = Seq(
AKKA_OSGI_BLUEPRINT,
bundle(TEST_BUNDLE_NAME).withBlueprintFile(getClass.getResource("config.xml")))
"config.xml" should "set up ActorSystem when bundle starts" in {
val system = serviceForType[ActorSystem]
assert(system != null)
assert(system.settings.config.getString("some.config.key") == "value")
}
it should "stop the ActorSystem when bundle stops" in {
val system = serviceForType[ActorSystem]
assert(!system.isTerminated)
bundleForName(TEST_BUNDLE_NAME).stop()
system.awaitTermination()
assert(system.isTerminated)
}
}
class DependencyInjectionNamespaceHandlerTest extends FlatSpec with PojoSRTestSupport {
import NamespaceHandlerTest._
val testBundles: Seq[BundleDescriptor] = Seq(
AKKA_OSGI_BLUEPRINT,
bundle(TEST_BUNDLE_NAME).withBlueprintFile(getClass.getResource("injection.xml")))
"injection.xml" should "set up bean containing ActorSystem" in {
val bean = serviceForType[ActorSystemAwareBean]
assert(bean != null)
assert(bean.system != null)
}
}

View file

@ -0,0 +1,11 @@
package akka.osgi.test
import akka.actor.ActorSystem
/**
* Just a simple POJO that can contain an actor system.
* Used for testing dependency injection with Blueprint
*/
class ActorSystemAwareBean(val system: ActorSystem) {
}

View file

@ -0,0 +1,22 @@
package akka.osgi.test
import akka.actor.Actor
/**
* Simple ping-pong actor, used for testing
*/
object PingPong {
abstract class TestMessage
case object Ping extends TestMessage
case object Pong extends TestMessage
class PongActor extends Actor {
def receive = {
case Ping
sender ! Pong
}
}
}

View file

@ -0,0 +1,16 @@
package akka.osgi.test
import akka.osgi.ActorSystemActivator
import akka.actor.{ Props, ActorSystem }
import PingPong._
/**
* Sample ActorSystemActivator implementation used for testing purposes
*/
class TestActorSystemActivator extends ActorSystemActivator {
def configure(system: ActorSystem) {
system.actorOf(Props(new PongActor), name = "pong")
}
}

View file

@ -480,7 +480,7 @@ object Dependencies {
val camel = Seq(camelCore, Test.scalatest, Test.junit, Test.mockito)
val osgi = Seq(osgiCore, ariesBlueprint, Runtime.logback, Test.pojosr, Test.tinybundles, Test.scalatest, Test.junit)
val osgi = Seq(osgiCore, ariesBlueprint, Runtime.logback, Test.ariesProxy, Test.commonsIo, Test.pojosr, Test.tinybundles, Test.scalatest, Test.junit)
val tutorials = Seq(Test.scalatest, Test.junit)
@ -505,7 +505,7 @@ object Dependency {
}
// Compile
val ariesBlueprint = "org.apache.aries.blueprint" % "org.apache.aries.blueprint" % "0.3.1" // ApacheV2
val ariesBlueprint = "org.apache.aries.blueprint" % "org.apache.aries.blueprint" % "0.3.2" // ApacheV2
val config = "com.typesafe" % "config" % "0.4.1" // ApacheV2
val camelCore = "org.apache.camel" % "camel-core" % V.Camel // ApacheV2
val netty = "io.netty" % "netty" % V.Netty // ApacheV2
@ -518,12 +518,13 @@ object Dependency {
// Test
object Test {
val ariesProxy = "org.apache.aries.proxy" % "org.apache.aries.proxy.impl" % "0.3" % "test" // ApacheV2
val commonsMath = "org.apache.commons" % "commons-math" % "2.1" % "test" // ApacheV2
val commonsIo = "commons-io" % "commons-io" % "2.0.1" % "test"// ApacheV2
val commonsIo = "commons-io" % "commons-io" % "2.0.1" % "test"// ApacheV2
val junit = "junit" % "junit" % "4.5" % "test" // Common Public License 1.0
val logback = "ch.qos.logback" % "logback-classic" % V.Logback % "test" // EPL 1.0 / LGPL 2.1
val mockito = "org.mockito" % "mockito-all" % "1.8.1" % "test" // MIT
val pojosr = "com.googlecode.pojosr" % "de.kalpatec.pojosr.framework" % "0.1.8" % "test" // ApacheV2
val pojosr = "com.googlecode.pojosr" % "de.kalpatec.pojosr.framework" % "0.1.4" % "test" // ApacheV2
val scalatest = "org.scalatest" % "scalatest_2.9.1" % V.Scalatest % "test" // ApacheV2
val scalacheck = "org.scala-tools.testing" % "scalacheck_2.9.1" % "1.9" % "test" // New BSD
val specs2 = "org.specs2" % "specs2_2.9.1" % "1.9" % "test" // Modified BSD / ApacheV2
@ -548,7 +549,10 @@ object OSGi {
val mailboxesCommon = exports(Seq("akka.actor.mailbox.*"))
val osgi = exports(Seq("akka.osgi.*"))
val osgi = exports(Seq("akka.osgi.*")) ++ Seq(
OsgiKeys.importPackage := Seq("org.apache.aries.blueprint.*;resolution:=optional",
"org.osgi.service.blueprint.*;resolution:=optional") ++ defaultImports
)
val remote = exports(Seq("akka.remote.*", "akka.routing.*", "akka.serialization.*"))
@ -559,10 +563,11 @@ object OSGi {
val zeroMQ = exports(Seq("akka.zeromq.*"))
def exports(packages: Seq[String]) = osgiSettings ++ Seq(
OsgiKeys.importPackage := Seq("!sun.misc", akkaImport(), configImport(), scalaImport(), "*"),
OsgiKeys.importPackage := defaultImports,
OsgiKeys.exportPackage := packages
)
def defaultImports = Seq("!sun.misc", akkaImport(), configImport(), scalaImport(), "*")
def akkaImport(packageName: String = "akka.*") = "%s;version=\"[2.1,2.2)\"".format(packageName)
def configImport(packageName: String = "com.typesafe.config.*") = "%s;version=\"[0.4.1,0.5)\"".format(packageName)
def scalaImport(packageName: String = "scala.*") = "%s;version=\"[2.9.2,2.10)\"".format(packageName)