X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-binding-broker%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Fbinding%2Fcodegen%2Fimpl%2FRuntimeCodeGenerator.xtend;h=3fef544f8115879aa5dc9df4c7d4ab1306d6ca1a;hp=90fcbd99aaaad0a6f6448faf0428cbc46cc52b4d;hb=721677fcf9f9f4085422eb3523e1cf752d698b4d;hpb=b5d0a1c60d3ff26cb4d7ecf45ee5fc0f95636c19 diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend index 90fcbd99aa..3fef544f81 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend @@ -7,85 +7,78 @@ */ package org.opendaylight.controller.sal.binding.codegen.impl +import java.util.Map import javassist.ClassPool -import org.opendaylight.yangtools.yang.binding.RpcService - -import javassist.CtClass -import javassist.CtMethod import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext -import org.opendaylight.yangtools.yang.binding.BaseIdentity - -import java.util.Map -import java.util.HashMap - - -import org.opendaylight.yangtools.yang.binding.NotificationListener import org.opendaylight.yangtools.yang.binding.Notification - - -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 org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory -import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory.NotificationInvoker -import java.util.Set -import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper -import java.util.WeakHashMap -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.yang.binding.util.BindingReflections +import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils -class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator, NotificationInvokerFactory { +import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.* - val CtClass BROKER_NOTIFICATION_LISTENER; - val ClassPool classPool; - val extension JavassistUtils utils; - val Map, RuntimeGeneratedInvokerPrototype> invokerClasses; +class RuntimeCodeGenerator extends AbstractRuntimeCodeGenerator { - public new(ClassPool pool) { - classPool = pool; - utils = new JavassistUtils(pool); - invokerClasses = new WeakHashMap(); - BROKER_NOTIFICATION_LISTENER = org.opendaylight.controller.sal.binding.api.NotificationListener.asCtClass; + new(ClassPool pool) { + super(pool) } - override getDirectProxyFor(Class iface) { - val supertype = iface.asCtClass - val targetCls = createClass(iface.directProxyName, supertype) [ - field(DELEGATE_FIELD, iface); - implementMethodsFrom(supertype) [ - body = ''' - { - if(«DELEGATE_FIELD» == null) { + override directProxySupplier(Class iface) { + return [| + val proxyName = iface.directProxyName; + val potentialClass = ClassLoaderUtils.tryToLoadClassWithTCCL(proxyName) + if(potentialClass != null) { + return potentialClass.newInstance; + } + 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 ($r) «DELEGATE_FIELD».«it.name»($$); - } - ''' + ''' + ] ] + return createdCls.toClass(iface.classLoader).newInstance ] - return targetCls.toClass(iface.classLoader).newInstance as T } - override getRouterFor(Class iface) { - val instance = >withClassLoaderAndLock(iface.classLoader,lock) [ | + override routerSupplier(Class iface, RpcServiceMetadata metadata) { + return [ | val supertype = iface.asCtClass - val metadata = supertype.rpcMetadata; + val routerName = iface.routerName; + val potentialClass = ClassLoaderUtils.tryToLoadClassWithTCCL(routerName) + if(potentialClass != null) { + return potentialClass.newInstance; + } + 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) } implementMethodsFrom(supertype) [ if (parameterTypes.size === 1) { - val rpcMeta = metadata.rpcMethods.get(name); + val rpcMeta = metadata.getRpcMethod(name); val bodyTmp = ''' { final «InstanceIdentifier.name» identifier = $1.«rpcMeta.inputRouteGetter.name»()«IF rpcMeta. @@ -95,7 +88,7 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co 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»($$); }''' @@ -105,99 +98,26 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co } ] 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 ]; - return instance; - } - - 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) { - metadata.contexts.add(routingPair.context) - metadata.rpcMethods.put(method.name,routingPair) - val input = routingPair.inputType.javaClass as Class; - metadata.supportedInputs.add(input); - metadata.rpcInputs.put(input,routingPair); - } - ] - return metadata; } - private def getRpcMetadata(CtMethod method) { - val inputClass = method.parameterTypes.get(0); - return inputClass.rpcMethodMetadata(inputClass,method.name); - } - - private def RpcMetadata rpcMethodMetadata(CtClass dataClass,CtClass inputClass,String rpcMethod) { - for (method : dataClass.methods) { - if (method.name.startsWith("get") && method.parameterTypes.size === 0) { - for (annotation : method.availableAnnotations) { - if (annotation instanceof RoutingContext) { - val encapsulated = !method.returnType.equals(InstanceIdentifier.asCtClass); - return new RpcMetadata(null,rpcMethod,(annotation as RoutingContext).value, method, encapsulated,inputClass); - } - } - } - } - for (iface : dataClass.interfaces) { - val ret = rpcMethodMetadata(iface,inputClass,rpcMethod); - if(ret != null) return ret; - } - return null; - } - - private def getJavaClass(CtClass cls) { - Thread.currentThread.contextClassLoader.loadClass(cls.name) - } - - override getInvokerFactory() { - return this; - } - - override invokerFor(NotificationListener instance) { - val cls = instance.class - val prototype = resolveInvokerClass(cls); - - return new RuntimeGeneratedInvoker(instance, prototype) - } - - protected def generateListenerInvoker(Class iface) { - val callbacks = iface.methods.filter[notificationCallback] + override generateListenerInvoker(Class iface) { + val callbacks = iface.methods.filter[BindingReflections.isNotificationCallback(it)] val supportedNotification = callbacks.map[parameterTypes.get(0) as Class].toSet; - val targetCls = createClass(iface.invokerName, BROKER_NOTIFICATION_LISTENER) [ + val targetCls = createClass(iface.invokerName, brokerNotificationListener) [ field(DELEGATE_FIELD, iface) - implementMethodsFrom(BROKER_NOTIFICATION_LISTENER) [ + implementMethodsFrom(brokerNotificationListener) [ body = ''' { «FOR callback : callbacks SEPARATOR " else "» @@ -216,95 +136,4 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co return new RuntimeGeneratedInvokerPrototype(supportedNotification, finalClass as Class>); } - - - - - - protected def resolveInvokerClass(Class class1) { - return withClassLoaderAndLock(class1.classLoader,lock) [| - val invoker = invokerClasses.get(class1); - if (invoker !== null) { - return invoker; - } - val newInvoker = generateListenerInvoker(class1); - invokerClasses.put(class1, newInvoker); - return newInvoker - - ] - } -} - -@Data -package class RuntimeGeneratedInvoker implements NotificationInvoker { - - @Property - val NotificationListener delegate; - - @Property - var org.opendaylight.controller.sal.binding.api.NotificationListener invocationProxy; - - @Property - var RuntimeGeneratedInvokerPrototype prototype; - - new(NotificationListener delegate, RuntimeGeneratedInvokerPrototype prototype) { - _delegate = delegate; - _prototype = prototype; - _invocationProxy = prototype.protoClass.newInstance as org.opendaylight.controller.sal.binding.api.NotificationListener; - RuntimeCodeHelper.setDelegate(_invocationProxy, delegate); - } - - override getSupportedNotifications() { - prototype.supportedNotifications; - } - - override close() { - } -} - -@Data -package class RuntimeGeneratedInvokerPrototype { - - @Property - val Set> supportedNotifications; - - @Property - val Class> protoClass; -} - -package class RpcServiceMetadata { - - @Property - val contexts = new HashSet>(); - - @Property - val rpcMethods = new HashMap(); - - @Property - val rpcInputs = new HashMap, RpcMetadata>(); - - - @Property - val supportedInputs = new HashSet>(); -} - -@Data -package class RpcMetadata { - - @Property - val QName qname; - - @Property - val String methodName; - - @Property - val Class context; - @Property - val CtMethod inputRouteGetter; - - @Property - val boolean routeEncapsulated; - - @Property - val CtClass inputType; }