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=4fb95d99b6028bbb93513388d23c6c538968bc5f;hp=93c192c0af54222533da37727f4575520dea9259;hb=37825a24cf28fc9561e6e038a78402213f4e2578;hpb=1a898f3bd37baec93cc13140a5eb24b30d4ea999 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 93c192c0af..4fb95d99b6 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,75 +7,102 @@ */ package org.opendaylight.controller.sal.binding.codegen.impl +import java.util.Map +import java.util.WeakHashMap import javassist.ClassPool -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 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.sal.binding.generator.util.ClassLoaderUtils +import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils 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.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 static org.opendaylight.yangtools.concepts.util.ClassLoaderUtils.* -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 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 ClassPool classPool; val extension JavassistUtils utils; val Map, RuntimeGeneratedInvokerPrototype> invokerClasses; - public new(ClassPool pool) { - classPool = pool; + + 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)); } override getDirectProxyFor(Class 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 getRouterFor(Class iface) { - val contexts = new HashSet> + override getRouterFor(Class iface,String routerInstanceName) { + val metadata = withClassLoader(iface.classLoader) [| + val supertype = iface.asCtClass + return supertype.rpcMetadata; + ] - val instance = >withClassLoader(iface.classLoader) [ | + val instance = 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) } @@ -91,7 +118,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»($$); }''' @@ -101,40 +128,23 @@ 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 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) { @@ -149,7 +159,7 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co } private def getRpcMetadata(CtMethod method) { - val inputClass = method.parameterTypes.get(0); + val inputClass = method.parameterTypes.get(0); return inputClass.rpcMethodMetadata(inputClass,method.name); } @@ -210,21 +220,24 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co ] val finalClass = targetCls.toClass(iface.classLoader, iface.protectionDomain) return new RuntimeGeneratedInvokerPrototype(supportedNotification, - finalClass as Class); + finalClass as Class>); } - + protected def resolveInvokerClass(Class class1) { - val invoker = invokerClasses.get(class1); - if (invoker !== null) { - return invoker; - } - val newInvoker = generateListenerInvoker(class1); - invokerClasses.put(class1, newInvoker); - return newInvoker + 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 + + ] } } @@ -235,7 +248,7 @@ package class RuntimeGeneratedInvoker implements NotificationInvoker { val NotificationListener delegate; @Property - var org.opendaylight.controller.sal.binding.api.NotificationListener invocationProxy; + var org.opendaylight.controller.sal.binding.api.NotificationListener invocationProxy; @Property var RuntimeGeneratedInvokerPrototype prototype; @@ -243,7 +256,7 @@ package class RuntimeGeneratedInvoker implements NotificationInvoker { 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; RuntimeCodeHelper.setDelegate(_invocationProxy, delegate); } @@ -255,32 +268,6 @@ package class RuntimeGeneratedInvoker implements NotificationInvoker { } } -@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 { @@ -297,7 +284,7 @@ package class RpcMetadata { @Property val boolean routeEncapsulated; - + @Property val CtClass inputType; }