pekko/kernel/src/main/scala/config/ActiveObjectGuiceConfigurator.scala

178 lines
7.3 KiB
Scala
Raw Normal View History

2009-05-09 17:18:31 +02:00
/**
* Copyright (C) 2009 Scalable Solutions.
*/
package se.scalablesolutions.akka.kernel.config
import com.google.inject._
import com.google.inject.jsr250.ResourceProviderFactory
import java.lang.reflect.Method
import javax.servlet.ServletContext
2009-05-09 17:18:31 +02:00
import org.apache.camel.impl.{JndiRegistry, DefaultCamelContext}
2009-05-11 13:48:32 +02:00
import org.apache.camel.{CamelContext, Endpoint, Routes}
2009-05-09 17:18:31 +02:00
import scala.collection.mutable.HashMap
import kernel.camel.ActiveObjectComponent
import kernel.ActiveObjectFactory
import kernel.ActiveObjectProxy
import kernel.Supervisor
import kernel.config.ScalaConfig._
2009-05-09 17:18:31 +02:00
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurator with CamelConfigurator with Logging {
2009-05-09 17:18:31 +02:00
val AKKA_CAMEL_ROUTING_SCHEME = "akka"
private var injector: Injector = _
private var supervisor: Supervisor = _
private var restartStrategy: RestartStrategy = _
private var components: List[Component] = _
private var bindings: List[DependencyBinding] = Nil
private var configRegistry = new HashMap[Class[_], Component] // TODO is configRegistry needed?
private var activeObjectRegistry = new HashMap[Class[_], Tuple3[Class[_], Class[_], ActiveObjectProxy]]
2009-05-09 17:18:31 +02:00
private var activeObjectFactory = new ActiveObjectFactory
2009-05-11 13:48:32 +02:00
private var camelContext = new DefaultCamelContext
2009-05-09 17:18:31 +02:00
private var modules = new java.util.ArrayList[Module]
private var methodToUriRegistry = new HashMap[Method, String]
/**
* Returns the active abject that has been put under supervision for the class specified.
*
* @param clazz the class for the active object
* @return the active object for the class
*/
2009-05-18 08:19:30 +02:00
override def getActiveObject[T](clazz: Class[T]): T = synchronized {
log.debug("Creating new active object [%s]", clazz.getName)
if (injector == null) throw new IllegalStateException("inject() and/or supervise() must be called before invoking getActiveObject(clazz)")
val activeObjectOption: Option[Tuple3[Class[_], Class[_], ActiveObjectProxy]] = activeObjectRegistry.get(clazz)
2009-05-09 17:18:31 +02:00
if (activeObjectOption.isDefined) {
val classInfo = activeObjectOption.get
val intfClass = classInfo._1
val implClass = classInfo._2
2009-05-09 17:18:31 +02:00
val activeObjectProxy = classInfo._3
val target = implClass.newInstance
injector.injectMembers(target)
activeObjectProxy.setTargetInstance(target.asInstanceOf[AnyRef])
2009-05-18 08:19:30 +02:00
activeObjectFactory.newInstance(intfClass, activeObjectProxy).asInstanceOf[T]
} else throw new IllegalStateException("Class [" + clazz.getName + "] has not been put under supervision (by passing in the config to the 'supervise') method")
2009-05-09 17:18:31 +02:00
}
override def getActiveObjectProxy(clazz: Class[_]): ActiveObjectProxy = synchronized {
log.debug("Looking up active object proxy [%s]", clazz.getName)
if (injector == null) throw new IllegalStateException("inject() and/or supervise() must be called before invoking getActiveObjectProxy(clazz)")
val activeObjectOption: Option[Tuple3[Class[_], Class[_], ActiveObjectProxy]] = activeObjectRegistry.get(clazz)
2009-05-09 17:18:31 +02:00
if (activeObjectOption.isDefined) activeObjectOption.get._3
else throw new IllegalStateException("Class [" + clazz.getName + "] has not been put under supervision (by passing in the config to the 'supervise') method")
2009-05-09 17:18:31 +02:00
}
override def getExternalDependency[T](clazz: Class[T]): T = synchronized {
2009-05-11 13:48:32 +02:00
injector.getInstance(clazz).asInstanceOf[T]
}
2009-05-18 08:19:30 +02:00
override def getComponentInterfaces: List[Class[_]] = components.map(_.intf)
override def getRoutingEndpoint(uri: String): Endpoint = synchronized {
2009-05-11 13:48:32 +02:00
camelContext.getEndpoint(uri)
}
override def getRoutingEndpoints: java.util.Collection[Endpoint] = synchronized {
2009-05-11 13:48:32 +02:00
camelContext.getEndpoints
}
override def getRoutingEndpoints(uri: String): java.util.Collection[Endpoint] = synchronized {
2009-05-11 13:48:32 +02:00
camelContext.getEndpoints(uri)
}
override def configureActiveObjects(restartStrategy: RestartStrategy, components: List[Component]): ActiveObjectConfigurator = synchronized {
2009-05-09 17:18:31 +02:00
this.restartStrategy = restartStrategy
this.components = components.toArray.toList.asInstanceOf[List[Component]]
bindings = for (c <- this.components)
yield new DependencyBinding(c.intf, c.target) // build up the Guice interface class -> impl class bindings
2009-05-18 08:19:30 +02:00
val deps = new java.util.ArrayList[DependencyBinding](bindings.size)
for (b <- bindings) deps.add(b)
modules.add(new ActiveObjectGuiceModule(deps))
2009-05-09 17:18:31 +02:00
this
}
override def inject: ActiveObjectConfigurator = synchronized {
2009-05-09 17:18:31 +02:00
if (injector != null) throw new IllegalStateException("inject() has already been called on this configurator")
injector = Guice.createInjector(modules)
this
}
override def supervise: ActiveObjectConfigurator = synchronized {
2009-05-09 17:18:31 +02:00
if (injector == null) inject
var workers = new java.util.ArrayList[Worker]
for (component <- components) {
2009-05-09 20:40:36 +02:00
val activeObjectProxy = new ActiveObjectProxy(component.intf, component.target, component.timeout)
2009-05-09 17:18:31 +02:00
workers.add(Worker(activeObjectProxy.server, component.lifeCycle))
activeObjectRegistry.put(component.intf, (component.intf, component.target, activeObjectProxy))
2009-05-11 13:48:32 +02:00
camelContext.getRegistry.asInstanceOf[JndiRegistry].bind(component.name, activeObjectProxy)
for (method <- component.intf.getDeclaredMethods.toList) {
registerMethodForUri(method, component.name)
}
log.debug("Registering active object in Camel context under the name [%s]", component.target.getName)
2009-05-09 17:18:31 +02:00
}
supervisor = activeObjectFactory.supervise(restartStrategy, workers)
2009-05-11 13:48:32 +02:00
camelContext.addComponent(AKKA_CAMEL_ROUTING_SCHEME, new ActiveObjectComponent(this))
camelContext.start
ActiveObjectConfigurator.registerConfigurator(this)
2009-05-09 17:18:31 +02:00
this
}
/**
* Add additional services to be wired in.
* <pre>
* activeObjectConfigurator.addExternalGuiceModule(new AbstractModule {
2009-05-09 17:18:31 +02:00
* protected void configure() {
* bind(Foo.class).to(FooImpl.class).in(Scopes.SINGLETON);
* bind(BarImpl.class);
* link(Bar.class).to(BarImpl.class);
* bindConstant(named("port")).to(8080);
* }})
* </pre>
*/
def addExternalGuiceModule(module: Module): ActiveObjectConfigurator = synchronized {
2009-05-09 17:18:31 +02:00
modules.add(module)
this
}
override def addRoutes(routes: Routes): ActiveObjectConfigurator = synchronized {
2009-05-09 17:18:31 +02:00
camelContext.addRoutes(routes)
this
}
2009-05-11 13:48:32 +02:00
override def getCamelContext: CamelContext = camelContext
2009-05-11 13:48:32 +02:00
def getGuiceModules: java.util.List[Module] = modules
2009-05-09 17:18:31 +02:00
def reset = synchronized {
modules = new java.util.ArrayList[Module]
configRegistry = new HashMap[Class[_], Component]
activeObjectRegistry = new HashMap[Class[_], Tuple3[Class[_], Class[_], ActiveObjectProxy]]
2009-05-09 17:18:31 +02:00
methodToUriRegistry = new HashMap[Method, String]
injector = null
restartStrategy = null
2009-05-11 13:48:32 +02:00
camelContext = new DefaultCamelContext
2009-05-09 17:18:31 +02:00
}
def stop = synchronized {
2009-05-11 13:48:32 +02:00
camelContext.stop
2009-05-09 17:18:31 +02:00
supervisor.stop
}
def registerMethodForUri(method: Method, componentName: String) =
methodToUriRegistry += method -> buildUri(method, componentName)
def lookupUriFor(method: Method): String =
methodToUriRegistry.getOrElse(method, throw new IllegalStateException("Could not find URI for method [" + method.getName + "]"))
def buildUri(method: Method, componentName: String): String =
AKKA_CAMEL_ROUTING_SCHEME + ":" + componentName + "." + method.getName
}