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=834eb4f5fb357b65ae7ed90b6e986ea7c2474a0e;hp=eea9ad6b891803dcfbff60b28c8bc32800852448;hb=23054c2ec3fa8166838f9d18af452e30acefd9d5;hpb=2e29ba0089e109c71af6fae1a6811255f9845049 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 eea9ad6b89..834eb4f5fb 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 @@ -8,49 +8,28 @@ package org.opendaylight.controller.sal.binding.codegen.impl import java.util.Map -import java.util.WeakHashMap import javassist.ClassPool -import javassist.CtClass -import javassist.CtMethod -import javassist.LoaderClassPath -import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper -import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory -import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory.NotificationInvoker -import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils -import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils -import org.opendaylight.yangtools.yang.binding.BaseIdentity -import org.opendaylight.yangtools.yang.binding.DataContainer import org.opendaylight.yangtools.yang.binding.InstanceIdentifier import org.opendaylight.yangtools.yang.binding.Notification -import org.opendaylight.yangtools.yang.binding.NotificationListener import org.opendaylight.yangtools.yang.binding.RpcImplementation -import org.opendaylight.yangtools.yang.binding.RpcService -import org.opendaylight.yangtools.yang.binding.annotations.QName -import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext +import org.opendaylight.yangtools.yang.binding.util.BindingReflections +import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.* -import static extension org.opendaylight.controller.sal.binding.codegen.YangtoolsMappingHelper.* - -class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator, NotificationInvokerFactory { - - val CtClass BROKER_NOTIFICATION_LISTENER; - val extension JavassistUtils utils; - val Map, RuntimeGeneratedInvokerPrototype> invokerClasses; +import org.opendaylight.yangtools.yang.binding.RpcService +class RuntimeCodeGenerator extends AbstractRuntimeCodeGenerator { new(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)); + super(pool) } - override getDirectProxyFor(Class iface) { - val T instance = ClassLoaderUtils.withClassLoaderAndLock(iface.classLoader,lock) [| + override directProxySupplier(Class iface) { + return [| val proxyName = iface.directProxyName; val potentialClass = ClassLoaderUtils.tryToLoadClassWithTCCL(proxyName) if(potentialClass != null) { - return potentialClass.newInstance as T; + return potentialClass.newInstance as RpcService; } val supertype = iface.asCtClass val createdCls = createClass(iface.directProxyName, supertype) [ @@ -75,23 +54,17 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co ''' ] ] - return createdCls.toClass(iface.classLoader).newInstance as T + return createdCls.toClass(iface.classLoader).newInstance as RpcService ] - return instance; } - override getRouterFor(Class iface,String routerInstanceName) { - val metadata = ClassLoaderUtils.withClassLoader(iface.classLoader) [| - val supertype = iface.asCtClass - return supertype.rpcMetadata; - ] - - val instance = ClassLoaderUtils.withClassLoaderAndLock(iface.classLoader,lock) [ | + override routerSupplier(Class iface, RpcServiceMetadata metadata) { + return [ | val supertype = iface.asCtClass val routerName = iface.routerName; val potentialClass = ClassLoaderUtils.tryToLoadClassWithTCCL(routerName) if(potentialClass != null) { - return potentialClass.newInstance as T; + return potentialClass.newInstance as RpcService; } val targetCls = createClass(iface.routerName, supertype) [ @@ -106,9 +79,15 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co } implementMethodsFrom(supertype) [ if (parameterTypes.size === 1) { - val rpcMeta = metadata.rpcMethods.get(name); + val rpcMeta = metadata.getRpcMethod(name); val bodyTmp = ''' { + if($1 == null) { + throw new IllegalArgumentException("RPC input must not be null and must contain a value for field «rpcMeta.inputRouteGetter.name»"); + } + if($1.«rpcMeta.inputRouteGetter.name»() == null) { + throw new IllegalArgumentException("Field «rpcMeta.inputRouteGetter.name» must not be null"); + } final «InstanceIdentifier.name» identifier = $1.«rpcMeta.inputRouteGetter.name»()«IF rpcMeta. routeEncapsulated».getValue()«ENDIF»; «supertype.name» instance = («supertype.name») «rpcMeta.context.routingTableField».get(identifier); @@ -134,74 +113,18 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co ''' ] ] - return targetCls.toClass(iface.classLoader,iface.protectionDomain).newInstance as T - + return targetCls.toClass(iface.classLoader,iface.protectionDomain).newInstance as RpcService ]; - 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) { - 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 "» @@ -220,69 +143,4 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co return new RuntimeGeneratedInvokerPrototype(supportedNotification, finalClass as Class>); } - - - - - - protected def resolveInvokerClass(Class class1) { - return ClassLoaderUtils.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 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; }