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=00c9f1eb91a14f7f1df97a73bc871cac9e918058;hp=3b3f4190cfb4716a04ecfbc7808e5bbcb06acc95;hb=3e5b44dbf2576fb9b2af1a36f927555eb7ed5990;hpb=738d46bed116293e3e42171ad2035ab805b0b2be 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 3b3f4190cf..00c9f1eb91 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,180 +7,134 @@ */ 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 static com.google.common.base.Preconditions.* - -import javassist.CtField -import javassist.Modifier -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 javassist.NotFoundException -import javassist.LoaderClassPath -import org.opendaylight.controller.sal.binding.codegen.impl.JavassistUtils.MethodGenerator -import org.opendaylight.controller.sal.binding.codegen.impl.JavassistUtils.ClassGenerator -import org.opendaylight.yangtools.yang.binding.NotificationListener import org.opendaylight.yangtools.yang.binding.Notification -import java.util.Arrays +import org.opendaylight.yangtools.yang.binding.RpcImplementation +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.YangtoolsMappingHelper.* import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.* +import org.opendaylight.yangtools.yang.binding.RpcService -class RuntimeCodeGenerator { - - val ClassPool classPool; +class RuntimeCodeGenerator extends AbstractRuntimeCodeGenerator { - public new(ClassPool pool) { - classPool = pool; + new(ClassPool pool) { + super(pool) } - def Class generateDirectProxy(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»($$);''' - ] - ] - return targetCls.toClass(iface.classLoader) - } - - def Class generateRouter(Class iface) { - val supertype = iface.asCtClass - val targetCls = createClass(iface.routerName, supertype) [ - //field(ROUTING_TABLE_FIELD,Map) - field(DELEGATE_FIELD, iface) - val contexts = new HashMap>(); - // We search for routing pairs and add fields - supertype.methods.filter[declaringClass == supertype && parameterTypes.size === 1].forEach [ method | - val routingPair = method.routingContextInput; - if (routingPair !== null) - contexts.put(routingPair.context.routingTableField, routingPair.context); - ] - for (ctx : contexts.entrySet) { - field(ctx.key, Map) + override directProxySupplier(Class iface) { + return [| + val proxyName = iface.directProxyName; + val potentialClass = ClassLoaderUtils.tryToLoadClassWithTCCL(proxyName) + if(potentialClass != null) { + return potentialClass.newInstance as RpcService; } - implementMethodsFrom(supertype) [ - if (parameterTypes.size === 1) { - val routingPair = routingContextInput; - val bodyTmp = ''' + val supertype = iface.asCtClass + val createdCls = createClass(iface.directProxyName, supertype) [ + field(DELEGATE_FIELD, iface); + implementsType(RpcImplementation.asCtClass) + implementMethodsFrom(supertype) [ + body = ''' { - final «InstanceIdentifier.name» identifier = $1.«routingPair.getter.name»(); - «supertype.name» instance = («supertype.name») «routingPair.context.routingTableField».get(identifier); - if(instance == null) { - instance = «DELEGATE_FIELD»; + if(«DELEGATE_FIELD» == null) { + throw new java.lang.IllegalStateException("No default provider is available"); } - return ($r) instance.«it.name»($$); - }''' - body = bodyTmp - } else if (parameterTypes.size === 0) { - body = '''return ($r) «DELEGATE_FIELD».«it.name»($$);''' - } - ] - ] - return targetCls.toClass(iface.classLoader) - } - - def Class generateListenerInvoker(Class iface) { - val targetCls = createClass(iface.invokerName) [ - field(DELEGATE_FIELD, iface) - it.method(Void, "invoke", Notification) [ - val callbacks = iface.methods.filter[notificationCallback] - body = ''' + return ($r) «DELEGATE_FIELD».«it.name»($$); + } + ''' + ] + implementMethodsFrom(RpcImplementation.asCtClass) [ + body = ''' { - «FOR callback : callbacks SEPARATOR " else "» - if($1 instanceof «val cls = callback.parameterTypes.get(0).name») { - «DELEGATE_FIELD».«callback.name»((«cls») $1); - return; - } - «ENDFOR» + throw new java.lang.IllegalStateException("No provider is processing supplied message"); + return ($r) null; } - ''' + ''' + ] ] + return createdCls.toClass(iface.classLoader).newInstance as RpcService ] - return targetCls.toClass(iface.classLoader); - } - - def void method(CtClass it, Class returnType, String name, Class parameter, MethodGenerator function1) { - val method = new CtMethod(returnType.asCtClass, name, Arrays.asList(parameter.asCtClass), it); - function1.process(method); - it.addMethod(method); } - private def routingContextInput(CtMethod method) { - val inputClass = method.parameterTypes.get(0); - return inputClass.contextInstance; - } - - private def RoutingPair getContextInstance(CtClass dataClass) { - for (method : dataClass.methods) { - if (method.parameterTypes.size === 0 && method.name.startsWith("get")) { - for (annotation : method.availableAnnotations) { - if (annotation instanceof RoutingContext) { - return new RoutingPair((annotation as RoutingContext).value, method) - } - } + 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 RpcService; } - } - for (iface : dataClass.interfaces) { - val ret = getContextInstance(iface); - if (ret != null) return ret; - } - return null; - } - private def void implementMethodsFrom(CtClass target, CtClass source, MethodGenerator function1) { - for (method : source.methods) { - if (method.declaringClass == source) { - val redeclaredMethod = new CtMethod(method, target, null); - function1.process(redeclaredMethod); - target.addMethod(redeclaredMethod); - } - } - } + val targetCls = createClass(iface.routerName, supertype) [ - private def CtClass createClass(String fqn, ClassGenerator cls) { - val target = classPool.makeClass(fqn); - cls.process(target); - return target; - } - private def CtClass createClass(String fqn, CtClass superInterface, ClassGenerator cls) { - val target = classPool.makeClass(fqn); - target.implementsType(superInterface); - cls.process(target); - return target; - } + field(DELEGATE_FIELD, iface) + //field(REMOTE_INVOKER_FIELD,iface); + implementsType(RpcImplementation.asCtClass) - private def void implementsType(CtClass it, CtClass supertype) { - checkArgument(supertype.interface, "Supertype must be interface"); - addInterface(supertype); + for (ctx : metadata.contexts) { + field(ctx.routingTableField, Map) + } + implementMethodsFrom(supertype) [ + if (parameterTypes.size === 1) { + val rpcMeta = metadata.getRpcMethod(name); + val bodyTmp = ''' + { + final «InstanceIdentifier.name» identifier = $1.«rpcMeta.inputRouteGetter.name»()«IF rpcMeta. + routeEncapsulated».getValue()«ENDIF»; + «supertype.name» instance = («supertype.name») «rpcMeta.context.routingTableField».get(identifier); + if(instance == null) { + instance = «DELEGATE_FIELD»; + } + if(instance == null) { + throw new java.lang.IllegalStateException("No routable provider is processing routed message for " + String.valueOf(identifier)); + } + return ($r) instance.«it.name»($$); + }''' + body = bodyTmp + } else if (parameterTypes.size === 0) { + body = '''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 targetCls.toClass(iface.classLoader,iface.protectionDomain).newInstance as RpcService + ]; } - private def asCtClass(Class class1) { - classPool.get(class1); - } + override generateListenerInvoker(Class iface) { + val callbacks = iface.methods.filter[BindingReflections.isNotificationCallback(it)] - private def CtField field(CtClass it, String name, Class returnValue) { - val field = new CtField(returnValue.asCtClass, name, it); - field.modifiers = Modifier.PUBLIC - addField(field); - return field; - } + val supportedNotification = callbacks.map[parameterTypes.get(0) as Class].toSet; - def get(ClassPool pool, Class cls) { - try { - return pool.get(cls.name) - } catch (NotFoundException e) { - pool.appendClassPath(new LoaderClassPath(cls.classLoader)); - return pool.get(cls.name) - } + val targetCls = createClass(iface.invokerName, brokerNotificationListener) [ + field(DELEGATE_FIELD, iface) + implementMethodsFrom(brokerNotificationListener) [ + body = ''' + { + «FOR callback : callbacks SEPARATOR " else "» + «val cls = callback.parameterTypes.get(0).name» + if($1 instanceof «cls») { + «DELEGATE_FIELD».«callback.name»((«cls») $1); + return null; + } + «ENDFOR» + return null; + } + ''' + ] + ] + val finalClass = targetCls.toClass(iface.classLoader, iface.protectionDomain) + return new RuntimeGeneratedInvokerPrototype(supportedNotification, + finalClass as Class>); } }