import org.opendaylight.yangtools.yang.binding.RpcService
import javassist.CtClass
-import static com.google.common.base.Preconditions.*
import javassist.CtMethod
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext
import static extension org.opendaylight.controller.sal.binding.codegen.YangtoolsMappingHelper.*
import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.*
import java.util.HashSet
-import static org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils.*
+import static org.opendaylight.yangtools.concepts.util.ClassLoaderUtils.*
import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory
import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory.NotificationInvoker
import java.util.Set
import org.opendaylight.yangtools.yang.binding.annotations.QName
import org.opendaylight.yangtools.yang.binding.DataContainer
import org.opendaylight.yangtools.yang.binding.RpcImplementation
-import org.opendaylight.controller.sal.binding.codegen.util.JavassistUtils
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils
+import org.opendaylight.yangtools.sal.binding.generator.util.ClassLoaderUtils
+import javassist.LoaderClassPath
class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator, NotificationInvokerFactory {
val extension JavassistUtils utils;
val Map<Class<? extends NotificationListener>, RuntimeGeneratedInvokerPrototype> invokerClasses;
- public new(ClassPool pool) {
+
+ new(ClassPool pool) {
classPool = pool;
utils = new JavassistUtils(pool);
invokerClasses = new WeakHashMap();
BROKER_NOTIFICATION_LISTENER = org.opendaylight.controller.sal.binding.api.NotificationListener.asCtClass;
+ pool.appendClassPath(new LoaderClassPath(RpcService.classLoader));
}
override <T extends RpcService> getDirectProxyFor(Class<T> iface) {
- val supertype = iface.asCtClass
- val targetCls = createClass(iface.directProxyName, supertype) [
- field(DELEGATE_FIELD, iface);
- implementMethodsFrom(supertype) [
- body = '''return ($r) «DELEGATE_FIELD».«it.name»($$);'''
+ val T instance = withClassLoaderAndLock(iface.classLoader,lock) [|
+ val proxyName = iface.directProxyName;
+ val potentialClass = ClassLoaderUtils.tryToLoadClassWithTCCL(proxyName)
+ if(potentialClass != null) {
+ return potentialClass.newInstance as T;
+ }
+ val supertype = iface.asCtClass
+ val createdCls = createClass(iface.directProxyName, supertype) [
+ field(DELEGATE_FIELD, iface);
+ implementsType(RpcImplementation.asCtClass)
+ implementMethodsFrom(supertype) [
+ body = '''
+ {
+ if(«DELEGATE_FIELD» == null) {
+ throw new java.lang.IllegalStateException("No default provider is available");
+ }
+ return ($r) «DELEGATE_FIELD».«it.name»($$);
+ }
+ '''
+ ]
+ implementMethodsFrom(RpcImplementation.asCtClass) [
+ body = '''
+ {
+ throw new java.lang.IllegalStateException("No provider is processing supplied message");
+ return ($r) null;
+ }
+ '''
+ ]
]
+ return createdCls.toClass(iface.classLoader).newInstance as T
]
- return targetCls.toClass(iface.classLoader).newInstance as T
+ return instance;
}
- override <T extends RpcService> getRouterFor(Class<T> iface) {
- val contexts = new HashSet<Class<? extends BaseIdentity>>
+ override <T extends RpcService> getRouterFor(Class<T> iface,String routerInstanceName) {
+ val metadata = withClassLoader(iface.classLoader) [|
+ val supertype = iface.asCtClass
+ return supertype.rpcMetadata;
+ ]
- val instance = <RpcRouterCodegenInstance<T>>withClassLoader(iface.classLoader) [ |
+ val instance = <T>withClassLoaderAndLock(iface.classLoader,lock) [ |
val supertype = iface.asCtClass
- val metadata = supertype.rpcMetadata;
+ val routerName = iface.routerName;
+ val potentialClass = ClassLoaderUtils.tryToLoadClassWithTCCL(routerName)
+ if(potentialClass != null) {
+ return potentialClass.newInstance as T;
+ }
+
val targetCls = createClass(iface.routerName, supertype) [
- addInterface(RpcImplementation.asCtClass)
-
+
+
field(DELEGATE_FIELD, iface)
//field(REMOTE_INVOKER_FIELD,iface);
-
+ implementsType(RpcImplementation.asCtClass)
+
for (ctx : metadata.contexts) {
field(ctx.routingTableField, Map)
}
instance = «DELEGATE_FIELD»;
}
if(instance == null) {
- throw new java.lang.IllegalStateException("No provider is processing supplied message");
+ throw new java.lang.IllegalStateException("No routable provider is processing routed message for " + String.valueOf(identifier));
}
return ($r) instance.«it.name»($$);
}'''
}
]
implementMethodsFrom(RpcImplementation.asCtClass) [
- switch (name) {
- case "getSupportedInputs":
- body = '''
- {
- throw new java.lang.UnsupportedOperationException("Not implemented yet");
- return ($r) null;
- }'''
- case "invoke": {
- val tmpBody = '''
- {
- «FOR input : metadata.supportedInputs SEPARATOR " else "»
- «val rpcMetadata = metadata.rpcInputs.get(input)»
- if(«input.name».class.equals($1)) {
- return ($r) this.«rpcMetadata.methodName»((«input.name») $2);
- }
- «ENDFOR»
- throw new java.lang.IllegalArgumentException("Not supported message type");
- return ($r) null;
- }
- '''
- body = tmpBody
- }
+ body = '''
+ {
+ throw new java.lang.IllegalStateException("No provider is processing supplied message");
+ return ($r) null;
}
+ '''
]
]
- val instance = targetCls.toClass(iface.classLoader,iface.protectionDomain).newInstance as T
- return new RpcRouterCodegenInstance(iface, instance, metadata.contexts,metadata.supportedInputs);
+ return targetCls.toClass(iface.classLoader,iface.protectionDomain).newInstance as T
+
];
- return instance;
+ return new RpcRouterCodegenInstance(routerInstanceName,iface, instance, metadata.contexts,metadata.supportedInputs);
}
private def RpcServiceMetadata getRpcMetadata(CtClass iface) {
val metadata = new RpcServiceMetadata;
-
+
iface.methods.filter[declaringClass == iface && parameterTypes.size === 1].forEach [ method |
val routingPair = method.rpcMetadata;
if (routingPair !== null) {
}
private def getRpcMetadata(CtMethod method) {
- val inputClass = method.parameterTypes.get(0);
+ val inputClass = method.parameterTypes.get(0);
return inputClass.rpcMethodMetadata(inputClass,method.name);
}
]
val finalClass = targetCls.toClass(iface.classLoader, iface.protectionDomain)
return new RuntimeGeneratedInvokerPrototype(supportedNotification,
- finalClass as Class<? extends org.opendaylight.controller.sal.binding.api.NotificationListener>);
+ finalClass as Class<? extends org.opendaylight.controller.sal.binding.api.NotificationListener<?>>);
}
-
+
protected def resolveInvokerClass(Class<? extends NotificationListener> class1) {
- val invoker = invokerClasses.get(class1);
- if (invoker !== null) {
- return invoker;
- }
- val newInvoker = generateListenerInvoker(class1);
- invokerClasses.put(class1, newInvoker);
- return newInvoker
+ return <RuntimeGeneratedInvokerPrototype>withClassLoaderAndLock(class1.classLoader,lock) [|
+ val invoker = invokerClasses.get(class1);
+ if (invoker !== null) {
+ return invoker;
+ }
+ val newInvoker = generateListenerInvoker(class1);
+ invokerClasses.put(class1, newInvoker);
+ return newInvoker
+
+ ]
}
}
val NotificationListener delegate;
@Property
- var org.opendaylight.controller.sal.binding.api.NotificationListener invocationProxy;
+ var org.opendaylight.controller.sal.binding.api.NotificationListener<Notification> invocationProxy;
@Property
var RuntimeGeneratedInvokerPrototype prototype;
new(NotificationListener delegate, RuntimeGeneratedInvokerPrototype prototype) {
_delegate = delegate;
_prototype = prototype;
- _invocationProxy = prototype.protoClass.newInstance;
+ _invocationProxy = prototype.protoClass.newInstance as org.opendaylight.controller.sal.binding.api.NotificationListener<Notification>;
RuntimeCodeHelper.setDelegate(_invocationProxy, delegate);
}
val Set<Class<? extends Notification>> supportedNotifications;
@Property
- val Class<? extends org.opendaylight.controller.sal.binding.api.NotificationListener> protoClass;
+ val Class<? extends org.opendaylight.controller.sal.binding.api.NotificationListener<?>> protoClass;
}
package class RpcServiceMetadata {
@Property
val rpcMethods = new HashMap<String, RpcMetadata>();
-
+
@Property
val rpcInputs = new HashMap<Class<? extends DataContainer>, RpcMetadata>();
-
-
+
+
@Property
val supportedInputs = new HashSet<Class<? extends DataContainer>>();
}
@Property
val boolean routeEncapsulated;
-
+
@Property
val CtClass inputType;
}