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
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 >
*/
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 ] = _
private var bindings : List [ DependencyBinding ] = Nil
private var configRegistry = new HashMap [ Class [ _ ] , Component ] // TODO is configRegistry needed?
2009-05-16 10:46:24 +02:00
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-16 10:46:24 +02:00
override def getActiveObject ( clazz : Class [ _ ] ) : AnyRef = synchronized {
2009-05-09 17:18:31 +02:00
//def getActiveObject[T](name: String): T = synchronized {
2009-05-16 10:46:24 +02:00
log . debug ( "Looking up 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
2009-05-16 10:46:24 +02:00
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 ] )
activeObjectFactory . newInstance ( intfClass , activeObjectProxy ) . asInstanceOf [ AnyRef ]
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-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-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-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-16 10:46:24 +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 ] ]
bindings = for ( c <- this . components )
yield new DependencyBinding ( c . intf , c . target ) // build up the Guice interface class -> impl class bindings
val arrayList = new java . util . ArrayList [ DependencyBinding ] ( )
for ( b <- bindings ) arrayList . add ( b )
modules . add ( new ActiveObjectGuiceModule ( arrayList ) )
this
}
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
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 ) )
2009-05-16 10:46:24 +02:00
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
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-16 10:46:24 +02:00
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
}