org.ow2.frascati.tinfi.control.intent.SCAIntentControllerTrait.scala Maven / Gradle / Ivy
The newest version!
/***
* OW2 FraSCAti Tinfi
* Copyright (C) 2011-2021 Inria, Univ. Lille
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact: [email protected]
*
* Author: Lionel Seinturier
*/
package org.ow2.frascati.tinfi.control.intent
import java.lang.annotation.Annotation
import java.lang.reflect.Method
import scala.collection.mutable.HashMap
import org.objectweb.fractal.api.Component
import org.objectweb.fractal.api.Interface
import org.objectweb.fractal.api.`type`.InterfaceType
import org.objectweb.fractal.julia.BasicControllerTrait
import org.objectweb.fractal.julia.ComponentInterface
import org.objectweb.fractal.julia.InitializationContext
import org.objectweb.fractal.julia.UseComponentTrait
import org.objectweb.fractal.juliac.runtime.ClassLoaderFcItf
import org.objectweb.fractal.juliac.runtime.ClassLoaderItf
import org.objectweb.fractal.juliac.runtime.Juliac
import org.ow2.frascati.tinfi.TinfiComponentInterceptor
import org.ow2.frascati.tinfi.TinfiRuntimeException
import org.ow2.frascati.tinfi.api.IntentHandler
import org.objectweb.fractal.juliac.commons.lang.reflect.AnnotatedElementFilter
import org.objectweb.fractal.juliac.commons.util.function.Filters
import org.objectweb.fractal.juliac.commons.lang.ClassHelper
/**
* Trait implementing the {@link SCAIntentController} interface for scaPrimitive
* components.
*
* @author Lionel Seinturier
* @since 1.4.5
*/
trait SCAIntentControllerTrait extends BasicControllerTrait
with UseComponentTrait
with org.ow2.frascati.tinfi.api.control.SCAIntentControllerTrait {
private var cl: Class[_] = null
override def initFcController( ic: InitializationContext ) = {
cl = ic.content.asInstanceOf[Class[_]]
super.initFcController(ic)
}
/**
*
* Add the specified intent handler on all service methods of the current
* component which satisfy the following conditions:
*
*
*
* - the implementation method in the component class is associated with
* an annotation of the specified class,
* - the annotation provides a
String[] value()
method,
* - one of the returned strings when calling
value()
is equal
* to the specified value.
*
*
* @param handler the intent handler to add
* @param annotcl the searched for annotation class
* @param value the searched for parameter value
*/
override def addFcIntentHandler[T <: Annotation](
handler: IntentHandler, annotcl: Class[T], value: String ) = {
val methods = getFcMatchingMethods(annotcl,value)
methods.foreach( method => {
val tci = getFcInterceptor(method)
val m = getFcItfMethod(method)
tci.addIntentHandler(handler,m)
})
}
// -------------------------------------------------------------------------
// Implementation specific
// -------------------------------------------------------------------------
/**
*
* Return the list of methods implemented by the component class which
* satisfy the following conditions:
*
*
*
* - the method is associated with an annotation of the specified class,
* - the annotation provides a
String[] value()
method,
* - one of the returned strings when calling
value()
is
* equal to the specified value.
*
*/
private def getFcMatchingMethods[T <: Annotation](
annotcl: Class[T], value: String ) : List[Method] = {
var ret = List[Method]()
// Retrieve all methods annotated with annotcl
val methods = ClassHelper.getAllMethods(cl)
val filter = new AnnotatedElementFilter(annotcl.getName)
val ms = Filters.filter(methods,filter)
ms.foreach( method => {
// Retrieve the corresponding annotation
val annot = method.getAnnotation(annotcl)
// Check whether the annotation provides a value() method
if( annot != null ) {
try {
val cl = annot.getClass
val mvalue = cl.getMethod("value")
val values = mvalue.invoke(annot).asInstanceOf[Array[String]]
values.foreach( v => {
if( v.equals(value) ) {
ret = method :: ret
}
})
}
catch {
case e: NoSuchMethodException => // No such method value()
}
}
})
return ret
}
/**
* Return the interceptor for the specified component method.
*/
private def getFcInterceptor( method: Method ) : TinfiComponentInterceptor[_] = {
if( mtcis == null ) {
initFcMaps
}
if( ! mtcis.contains(method) ) {
// Shouldn't occur
val msg = "No interceptor for component method: "+method.toString
throw new TinfiRuntimeException(msg)
}
val tci = mtcis(method)
return tci
}
/**
* Return the interface method for the specified component method.
*/
private def getFcItfMethod( method: Method ) : Method = {
if( mms == null ) {
initFcMaps
}
if( ! mms.contains(method) ) {
// Shouldn't occur
val msg =
"No interface method for component method: "+method.toString()
throw new TinfiRuntimeException(msg)
}
val m = mms(method)
return m
}
private var mtcis: HashMap[Method,TinfiComponentInterceptor[_]] = null
private var mms: HashMap[Method,Method] = null
/**
* Initialize the {@link #mtcis} and {@link #mms} maps.
*/
private def initFcMaps = {
mtcis = new HashMap[Method,TinfiComponentInterceptor[_]]
mms = new HashMap[Method,Method]
// Retrieve all public methods of the component class
val methods = cl.getMethods
// Iterate on all business interfaces of the component.
val itfs = weaveableC.getFcInterfaces
itfs.foreach( o => {
val itf = o.asInstanceOf[Interface]
val name = itf.getFcItfName
// Skip control interfaces
if( !name.endsWith("-controller") && !name.equals("component") ) {
// Retrieve the corresponding interceptor
val i = itf.asInstanceOf[ComponentInterface].getFcItfImpl
val tci = i.asInstanceOf[TinfiComponentInterceptor[_]]
// Retrieve the interface methods
val it = itf.getFcItfType().asInstanceOf[InterfaceType]
val signature = it.getFcItfSignature
val business = loadFcClass(signature)
val ms = business.getMethods
// Check if some component methods match the interface methods
methods.foreach( method => {
ms.foreach( m => {
if( areSame(m,method) ) {
mtcis += method -> tci
mms += method -> m
}
})
})
}
})
}
/**
* Load, with the Juliac classloader, the class whose name is specified.
*/
private def loadFcClass( name: String ) : Class[_] = {
val boot = new Juliac().newFcInstance
val loader = boot.getFcInterface(ClassLoaderFcItf.NAME).asInstanceOf[ClassLoaderItf]
val cl = loader.loadClass(name)
return cl
}
/**
* Return true
if the specified methods are the same: same name
* and same parameters.
*/
private def areSame( m1: Method, m2: Method ) : Boolean = {
val name1 = m1.getName
val name2 = m2.getName
if( ! name1.equals(name2) ) {
return false
}
val ptypes1 = m1.getParameterTypes
val ptypes2 = m2.getParameterTypes
if( ptypes1.length != ptypes2.length ) {
return false
}
for( i <- 0 until ptypes1.length ) {
val ptype1 = ptypes1(i)
val ptype2 = ptypes2(i)
if( ! ptype1.equals(ptype2) ) {
return false
}
}
return true
}
}