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
2009-05-16 10:46:24 +02:00
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-16 10:46:24 +02:00
2009-05-09 17:18:31 +02:00
import scala.collection.mutable.HashMap
2009-05-16 10:46:24 +02:00
import kernel.camel.ActiveObjectComponent
2009-05-20 16:54:42 +02:00
import kernel. { ActiveObjectFactory , Supervisor }
2009-05-16 10:46:24 +02:00
import kernel.config.ScalaConfig._
2009-05-09 17:18:31 +02:00
/* *
* @author < a href = "http://jonasboner.com" > Jonas Bon & # 233 ; r </ a >
*/
2009-05-16 10:46:24 +02:00
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 ] = _
2009-05-23 22:24:02 +02:00
private var workers : List [ Worker ] = Nil
2009-05-09 17:18:31 +02:00
private var bindings : List [ DependencyBinding ] = Nil
private var configRegistry = new HashMap [ Class [ _ ] , Component ] // TODO is configRegistry needed?
2009-05-23 22:24:02 +02:00
private var activeObjectRegistry = new HashMap [ Class [ _ ] , Tuple4 [ AnyRef , AnyRef , Component , GenericServerContainer ] ]
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 {
2009-05-23 22:24:02 +02:00
log . debug ( "Retrieving active object [%s]" , clazz . getName )
2009-05-16 10:46:24 +02:00
if ( injector == null ) throw new IllegalStateException ( "inject() and/or supervise() must be called before invoking getActiveObject(clazz)" )
2009-05-23 22:24:02 +02:00
val ( proxy , targetInstance , component , server ) =
activeObjectRegistry . getOrElse ( clazz , throw new IllegalStateException ( "Class [" + clazz . getName + "] has not been put under supervision (by passing in the config to the 'configureActiveObjects' and then invoking 'supervise') method" ) )
injector . injectMembers ( targetInstance )
proxy . asInstanceOf [ T ]
2009-05-09 17:18:31 +02:00
}
2009-05-23 22:24:02 +02:00
2009-05-20 16:54:42 +02:00
/*
2009-05-16 10:46:24 +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
2009-05-16 10:46:24 +02:00
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
}
2009-05-20 16:54:42 +02:00
*/
2009-05-16 10:46:24 +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-23 22:24:02 +02:00
override def getComponentInterfaces : List [ Class [ _ ] ] =
for ( c <- components ) yield {
if ( c . intf . isDefined ) c . intf . get
else c . target
}
2009-05-16 10:46:24 +02:00
override def getRoutingEndpoint ( uri : String ) : Endpoint = synchronized {
2009-05-11 13:48:32 +02:00
camelContext . getEndpoint ( uri )
}
2009-05-16 10:46:24 +02:00
override def getRoutingEndpoints : java.util.Collection [ Endpoint ] = synchronized {
2009-05-11 13:48:32 +02:00
camelContext . getEndpoints
}
2009-05-16 10:46:24 +02:00
override def getRoutingEndpoints ( uri : String ) : java.util.Collection [ Endpoint ] = synchronized {
2009-05-11 13:48:32 +02:00
camelContext . getEndpoints ( uri )
}
2009-05-23 22:24:02 +02:00
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 ] ]
2009-05-23 22:24:02 +02:00
bindings = for ( component <- this . components ) yield {
if ( component . intf . isDefined ) newDelegatingProxy ( component )
else newSubclassingProxy ( component )
}
//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-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
}
2009-05-23 22:24:02 +02:00
private def newSubclassingProxy ( component : Component ) : DependencyBinding = {
val targetClass = component . target
val server = new GenericServerContainer ( targetClass . getName , ( ) => new Dispatcher ( component . target . getName ) )
server . setTimeout ( component . timeout )
workers : := Worker ( server , component . lifeCycle )
val proxy = activeObjectFactory . newInstance ( targetClass , server ) . asInstanceOf [ AnyRef ]
activeObjectRegistry . put ( targetClass , ( proxy , proxy , component , server ) )
new DependencyBinding ( targetClass , proxy )
}
private def newDelegatingProxy ( component : Component ) : DependencyBinding = {
val targetClass = component . intf . get
val server = new GenericServerContainer ( targetClass . getName , ( ) => new Dispatcher ( component . target . getName ) )
server . setTimeout ( component . timeout )
workers : := Worker ( server , component . lifeCycle )
component . target . getConstructor ( Array [ Class [ _ ] ] ( ) ) . setAccessible ( true )
val targetInstance = component . target . newInstance . asInstanceOf [ AnyRef ] // TODO: perhaps need to put in registry
val proxy = activeObjectFactory . newInstance ( targetClass , targetInstance , server ) . asInstanceOf [ AnyRef ]
activeObjectRegistry . put ( targetClass , ( proxy , targetInstance , component , server ) )
new DependencyBinding ( targetClass , proxy )
}
2009-05-16 10:46:24 +02:00
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
}
2009-05-16 10:46:24 +02:00
override def supervise : ActiveObjectConfigurator = synchronized {
2009-05-09 17:18:31 +02:00
if ( injector == null ) inject
supervisor = activeObjectFactory . supervise ( restartStrategy , workers )
2009-05-20 16:54:42 +02:00
//camelContext.addComponent(AKKA_CAMEL_ROUTING_SCHEME, new ActiveObjectComponent(this))
//camelContext.start
2009-05-16 10:46:24 +02:00
ActiveObjectConfigurator . registerConfigurator ( this )
2009-05-09 17:18:31 +02:00
this
}
/* *
* Add additional services to be wired in .
* < pre >
2009-05-16 10:46:24 +02:00
* 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 >
*/
2009-05-16 10:46:24 +02:00
def addExternalGuiceModule ( module : Module ) : ActiveObjectConfigurator = synchronized {
2009-05-09 17:18:31 +02:00
modules . add ( module )
this
}
2009-05-16 10:46:24 +02:00
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
2009-05-16 10:46:24 +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 ]
2009-05-23 22:24:02 +02:00
activeObjectRegistry = new HashMap [ Class [ _ ] , Tuple4 [ AnyRef , AnyRef , Component , GenericServerContainer ] ]
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
}