Added getServiceType and support for classloading strategies. 62/5062/4
authorTony Tkacik <ttkacik@cisco.com>
Fri, 31 Jan 2014 13:09:51 +0000 (14:09 +0100)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 4 Feb 2014 21:17:34 +0000 (21:17 +0000)
Change-Id: I8e43f66fd7d22f34aa0dbc4f89df07c3c0962cd2
Signed-off-by: Tony Tkacik <ttkacik@cisco.com>
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedClassLoadingStrategy.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/LazyGeneratedCodecRegistry.java
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/RuntimeGeneratedMappingServiceImpl.xtend
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/TransformerGenerator.xtend
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/ClassLoaderUtils.java
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingMapping.java
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/BindingReflections.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/BindingIndependentMappingService.java

diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedClassLoadingStrategy.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedClassLoadingStrategy.java
new file mode 100644 (file)
index 0000000..89c9fa2
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.sal.binding.generator.impl;
+
+import org.opendaylight.yangtools.sal.binding.generator.util.ClassLoaderUtils;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+public abstract class GeneratedClassLoadingStrategy {
+
+    private static final GeneratedClassLoadingStrategy TCCL_STRATEGY = new TCCLClassLoadingStrategy();
+
+    public Class<?> loadClass(Type type) throws ClassNotFoundException {
+        return loadClass(type.getFullyQualifiedName());
+    }
+
+    public abstract Class<?> loadClass(String fullyQualifiedName) throws ClassNotFoundException;
+
+    public static final GeneratedClassLoadingStrategy getTCCLClassLoadingStrategy() {
+        return TCCL_STRATEGY;
+    }
+
+    private static final class TCCLClassLoadingStrategy extends GeneratedClassLoadingStrategy {
+
+        @Override
+        public Class<?> loadClass(String fullyQualifiedName) throws ClassNotFoundException {
+            return ClassLoaderUtils.loadClassWithTCCL(fullyQualifiedName);
+        }
+    }
+}
index 9f151ded7783917406873dbe0c245d53189704c0..d06a8f9e7c240a58b300f3b9011fbe9148317744 100644 (file)
@@ -53,13 +53,20 @@ public class LazyGeneratedCodecRegistry implements //
     private TransformerGenerator generator;
 
     // Concrete class to codecs
-    private static final Map<Class<?>, DataContainerCodec<?>> containerCodecs = Collections.synchronizedMap(new WeakHashMap<Class<?>, DataContainerCodec<?>>());
-    private static final Map<Class<?>, IdentifierCodec<?>> identifierCodecs = Collections.synchronizedMap(new WeakHashMap<Class<?>, IdentifierCodec<?>>());
-    private static final Map<Class<?>, ChoiceCodecImpl<?>> choiceCodecs = Collections.synchronizedMap(new WeakHashMap<Class<?>, ChoiceCodecImpl<?>>());
-    private static final Map<Class<?>, ChoiceCaseCodecImpl<?>> caseCodecs = Collections.synchronizedMap(new WeakHashMap<Class<?>, ChoiceCaseCodecImpl<?>>());
-    private static final Map<Class<?>, AugmentableCompositeCodec> augmentableCodecs = Collections.synchronizedMap(new WeakHashMap<Class<?>, AugmentableCompositeCodec>());
-    private static final Map<Class<?>, AugmentationCodec<?>> augmentationCodecs = Collections.synchronizedMap(new WeakHashMap<Class<?>, AugmentationCodec<?>>());
-    private static final Map<Class<?>, QName> identityQNames = Collections.synchronizedMap(new WeakHashMap<Class<?>, QName>());
+    private static final Map<Class<?>, DataContainerCodec<?>> containerCodecs = Collections
+            .synchronizedMap(new WeakHashMap<Class<?>, DataContainerCodec<?>>());
+    private static final Map<Class<?>, IdentifierCodec<?>> identifierCodecs = Collections
+            .synchronizedMap(new WeakHashMap<Class<?>, IdentifierCodec<?>>());
+    private static final Map<Class<?>, ChoiceCodecImpl<?>> choiceCodecs = Collections
+            .synchronizedMap(new WeakHashMap<Class<?>, ChoiceCodecImpl<?>>());
+    private static final Map<Class<?>, ChoiceCaseCodecImpl<?>> caseCodecs = Collections
+            .synchronizedMap(new WeakHashMap<Class<?>, ChoiceCaseCodecImpl<?>>());
+    private static final Map<Class<?>, AugmentableCompositeCodec> augmentableCodecs = Collections
+            .synchronizedMap(new WeakHashMap<Class<?>, AugmentableCompositeCodec>());
+    private static final Map<Class<?>, AugmentationCodec<?>> augmentationCodecs = Collections
+            .synchronizedMap(new WeakHashMap<Class<?>, AugmentationCodec<?>>());
+    private static final Map<Class<?>, QName> identityQNames = Collections
+            .synchronizedMap(new WeakHashMap<Class<?>, QName>());
     private static final Map<QName, Type> qnamesToIdentityMap = new ConcurrentHashMap<>();
     /** Binding type to encountered classes mapping **/
     @SuppressWarnings("rawtypes")
@@ -78,6 +85,8 @@ public class LazyGeneratedCodecRegistry implements //
 
     private SchemaContext currentSchema;
 
+    private GeneratedClassLoadingStrategy classLoadingStrategy;
+
     LazyGeneratedCodecRegistry(SchemaLock lock) {
         this.lock = Preconditions.checkNotNull(lock);
     }
@@ -117,7 +126,9 @@ public class LazyGeneratedCodecRegistry implements //
             } catch (InstantiationException e) {
                 LOG.error("Can not instantiate raw augmentation codec {}", object.getSimpleName(), e);
             } catch (IllegalAccessException e) {
-                LOG.debug("Run-time consistency issue: constructor {} is not available. This indicates either a code generation bug or a misconfiguration of JVM.", object.getSimpleName(), e);
+                LOG.debug(
+                        "Run-time consistency issue: constructor {} is not available. This indicates either a code generation bug or a misconfiguration of JVM.",
+                        object.getSimpleName(), e);
             }
         Class<? extends Augmentable<?>> objectSupertype = getAugmentableArgumentFrom(object);
         if (objectSupertype != null) {
@@ -131,7 +142,7 @@ public class LazyGeneratedCodecRegistry implements //
     @Override
     public QName getQNameForAugmentation(Class<?> cls) {
         Preconditions.checkArgument(Augmentation.class.isAssignableFrom(cls));
-        return getCodecForAugmentation((Class<? extends Augmentation>)cls).getAugmentationQName();
+        return getCodecForAugmentation((Class<? extends Augmentation>) cls).getAugmentationQName();
     }
 
     private static Class<? extends Augmentable<?>> getAugmentableArgumentFrom(
@@ -350,8 +361,10 @@ public class LazyGeneratedCodecRegistry implements //
         ConcreteType typeref = Types.typeForClass(caseClass);
         ChoiceCaseCodecImpl caseCodec = typeToCaseCodecs.get(typeref);
 
-        Preconditions.checkState(caseCodec != null, "Case Codec was not created proactivelly for %s", caseClass.getName());
-        Preconditions.checkState(caseCodec.getSchema() != null, "Case schema is not available for %s", caseClass.getName());
+        Preconditions.checkState(caseCodec != null, "Case Codec was not created proactivelly for %s",
+                caseClass.getName());
+        Preconditions.checkState(caseCodec.getSchema() != null, "Case schema is not available for %s",
+                caseClass.getName());
         @SuppressWarnings("unchecked")
         Class<? extends BindingCodec> newCodec = generator.caseCodecFor(caseClass, caseCodec.getSchema());
         BindingCodec newInstance = newInstanceOf(newCodec);
@@ -431,10 +444,11 @@ public class LazyGeneratedCodecRegistry implements //
                 if (partialCodec.getSchema() == null) {
                     partialCodec.setSchema(caseNode);
                 }
-
-                Class<?> caseClass = ClassLoaderUtils.tryToLoadClassWithTCCL(type.getFullyQualifiedName());
-                if (caseClass != null) {
+                try {
+                    Class<?> caseClass = classLoadingStrategy.loadClass(type.getFullyQualifiedName());
                     getCaseCodecFor(caseClass);
+                } catch (ClassNotFoundException e) {
+                    LOG.trace("Could not proactivelly create case codec for {}", type, e);
                 }
             }
         }
@@ -633,7 +647,8 @@ public class LazyGeneratedCodecRegistry implements //
         private final BindingCodec<Map<QName, Object>, Object> delegate;
 
         @SuppressWarnings("rawtypes")
-        private final Map<Class, ChoiceCaseCodecImpl<?>> cases = Collections.synchronizedMap(new WeakHashMap<Class, ChoiceCaseCodecImpl<?>>());
+        private final Map<Class, ChoiceCaseCodecImpl<?>> cases = Collections
+                .synchronizedMap(new WeakHashMap<Class, ChoiceCaseCodecImpl<?>>());
 
         private final CaseCompositeNodeMapFacade CompositeToCase;
 
@@ -712,9 +727,10 @@ public class LazyGeneratedCodecRegistry implements //
     }
 
     /**
-     * This map is used as only facade for {@link org.opendaylight.yangtools.yang.binding.BindingCodec} in different
+     * This map is used as only facade for
+     * {@link org.opendaylight.yangtools.yang.binding.BindingCodec} in different
      * classloaders to retrieve codec dynamicly based on provided key.
-     *
+     * 
      * @param <T>
      *            Key type
      */
@@ -796,7 +812,8 @@ public class LazyGeneratedCodecRegistry implements //
 
         private final Class augmentableType;
 
-        Map<Class, AugmentationCodec<?>> localAugmentationCodecs = Collections.synchronizedMap(new WeakHashMap<Class, AugmentationCodec<?>>());
+        Map<Class, AugmentationCodec<?>> localAugmentationCodecs = Collections
+                .synchronizedMap(new WeakHashMap<Class, AugmentationCodec<?>>());
 
         public AugmentableCompositeCodec(Class type) {
             Preconditions.checkArgument(Augmentable.class.isAssignableFrom(type));
@@ -942,6 +959,17 @@ public class LazyGeneratedCodecRegistry implements //
             ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName());
             WeakReference<Class> softref = typeToClass.get(typeref);
             if (softref == null) {
+
+                try {
+                    Class<?> cls = classLoadingStrategy.loadClass(typeref.getFullyQualifiedName());
+                    if (cls != null) {
+                        serialize(cls);
+                        return cls;
+                    }
+                } catch (Exception e) {
+                    LOG.warn("Identity {} was not deserialized, because of missing class {}", input,
+                            typeref.getFullyQualifiedName());
+                }
                 return null;
             }
             return softref.get();
index 04d66dcb89acf9f2283a8e43907a16951b529ad8..edd487705f05ea029d5ab5e79d9535a0759fdd2d 100644 (file)
@@ -36,8 +36,10 @@ import org.slf4j.LoggerFactory
 import org.opendaylight.yangtools.yang.data.impl.codec.ValueWithQName
 import org.opendaylight.yangtools.yang.data.impl.codec.DataContainerCodec
 import org.opendaylight.yangtools.binding.generator.util.Types
+
 //import org.osgi.framework.BundleContext
 import java.util.Hashtable
+
 //import org.osgi.framework.ServiceRegistration
 import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException
 import java.util.concurrent.Callable
@@ -55,6 +57,10 @@ import org.opendaylight.yangtools.yang.common.QName
 import com.google.common.collect.FluentIterable
 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
 import java.util.HashMap
+import java.net.URI
+import org.opendaylight.yangtools.yang.model.api.Module
+import com.google.common.base.Optional
+import org.opendaylight.yangtools.yang.binding.BindingMapping
 
 class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingService, SchemaServiceListener, SchemaLock, AutoCloseable {
 
@@ -79,15 +85,17 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
     val ConcurrentMap<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
 
     @Property
-    val ConcurrentMap<Type,Set<QName>> serviceTypeToRpc = new ConcurrentHashMap();
+    val ConcurrentMap<Type, Set<QName>> serviceTypeToRpc = new ConcurrentHashMap();
 
     val promisedTypeDefinitions = HashMultimap.<Type, SettableFuture<GeneratedTypeBuilder>>create;
 
     val promisedTypes = HashMultimap.<Type, SettableFuture<Type>>create;
 
-    //ServiceRegistration<SchemaServiceListener> listenerRegistration
+    var SchemaContext schemaContext;
 
+    //ServiceRegistration<SchemaServiceListener> listenerRegistration
     override onGlobalContextUpdated(SchemaContext arg0) {
+        schemaContext = arg0
         recreateBindingContext(arg0);
         registry.onGlobalContextUpdated(arg0);
     }
@@ -106,22 +114,23 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
             updateBindingFor(context.cases, schemaContext);
             val namespace = BindingGeneratorUtil.moduleNamespaceToPackageName(module);
 
-            if(!module.rpcs.empty) {
+            if (!module.rpcs.empty) {
                 val rpcs = FluentIterable.from(module.rpcs).transform[QName].toSet
-                val serviceClass = new ReferencedTypeImpl(namespace,BindingGeneratorUtil.parseToClassName(module.name)+"Service");
-                serviceTypeToRpc.put(serviceClass,rpcs);
+                val serviceClass = new ReferencedTypeImpl(namespace,
+                    BindingGeneratorUtil.parseToClassName(module.name) + "Service");
+                serviceTypeToRpc.put(serviceClass, rpcs);
             }
 
             val typedefs = context.typedefs;
             for (typedef : typedefs.entrySet) {
-                val typeRef = new ReferencedTypeImpl(typedef.value.packageName,typedef.value.name)
+                val typeRef = new ReferencedTypeImpl(typedef.value.packageName, typedef.value.name)
                 binding.typeDefinitions.put(typeRef, typedef.value as GeneratedType);
-                val schemaNode = YangSchemaUtils.findTypeDefinition(schemaContext,typedef.key);
-                if(schemaNode != null) {
+                val schemaNode = YangSchemaUtils.findTypeDefinition(schemaContext, typedef.key);
+                if (schemaNode != null) {
 
-                    binding.typeToSchemaNode.put(typeRef,schemaNode);
+                    binding.typeToSchemaNode.put(typeRef, schemaNode);
                 } else {
-                    LOG.error("Type definition for {} is not available",typedef.value);
+                    LOG.error("Type definition for {} is not available", typedef.value);
                 }
 
             }
@@ -130,7 +139,7 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
                 binding.typeToDefinition.put(augmentation, augmentation);
             }
             binding.typeToAugmentation.putAll(context.typeToAugmentation);
-            for(augmentation : augmentations) {
+            for (augmentation : augmentations) {
                 updatePromisedSchemas(augmentation);
             }
         }
@@ -144,17 +153,17 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
         Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry) {
 
         try {
-        val key = toDataDom(entry.key)
-        var CompositeNode data;
-        if(Augmentation.isAssignableFrom(entry.key.targetType)) {
-            data = toCompositeNodeImplAugument(key,entry.value);
-        } else {
-          data = toCompositeNodeImpl(key,entry.value);
-        }
-        return new SimpleEntry(key, data);
+            val key = toDataDom(entry.key)
+            var CompositeNode data;
+            if (Augmentation.isAssignableFrom(entry.key.targetType)) {
+                data = toCompositeNodeImplAugument(key, entry.value);
+            } else {
+                data = toCompositeNodeImpl(key, entry.value);
+            }
+            return new SimpleEntry(key, data);
 
         } catch (Exception e) {
-            LOG.error("Error during serialization for {}.", entry.key,e);
+            LOG.error("Error during serialization for {}.", entry.key, e);
             throw e;
         }
     }
@@ -166,8 +175,9 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
         val ret = codec.serialize(new ValueWithQName(null, object));
         return ret as CompositeNode;
     }
-    
-    private def CompositeNode toCompositeNodeImpl(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier identifier,DataObject object) {
+
+    private def CompositeNode toCompositeNodeImpl(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier identifier,
+        DataObject object) {
         val last = identifier.path.last;
         val cls = object.implementedInterface;
         waitForSchema(cls);
@@ -176,29 +186,29 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
         return ret as CompositeNode;
     }
 
-
-    private def CompositeNode toCompositeNodeImplAugument(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier identifier,DataObject object) {
+    private def CompositeNode toCompositeNodeImplAugument(
+        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier identifier, DataObject object) {
 
         //val cls = object.implementedInterface;
         //waitForSchema(cls);
         val last = identifier.path.last;
         val codec = registry.getCodecForAugmentation(object.implementedInterface as Class) as AugmentationCodec;
         val ret = codec.serialize(new ValueWithQName(last.nodeType, object));
-        if(last instanceof NodeIdentifierWithPredicates) {
+        if (last instanceof NodeIdentifierWithPredicates) {
             val predicates = last as NodeIdentifierWithPredicates;
             val newNodes = new ArrayList<Node<?>>(predicates.keyValues.size);
-            for(predicate : predicates.keyValues.entrySet) {
-                newNodes.add(new SimpleNodeTOImpl(predicate.key,null,predicate.value));
+            for (predicate : predicates.keyValues.entrySet) {
+                newNodes.add(new SimpleNodeTOImpl(predicate.key, null, predicate.value));
             }
             newNodes.addAll(ret.children);
-            return new CompositeNodeTOImpl(last.nodeType,null,newNodes);
+            return new CompositeNodeTOImpl(last.nodeType, null, newNodes);
         }
         return ret as CompositeNode;
     }
 
     override waitForSchema(Class class1) {
 
-        if(registry.isCodecAvailable(class1)) {
+        if (registry.isCodecAvailable(class1)) {
             return;
         }
         val ref = Types.typeForClass(class1);
@@ -214,7 +224,7 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
     }
 
     override dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode node) {
-         dataObjectFromDataDom(path.targetType,node) as DataObject;
+        dataObjectFromDataDom(path.targetType, node) as DataObject;
     }
 
     override fromDataDom(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry) {
@@ -243,7 +253,7 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
             val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key);
 
             //LOG.info("{} : {}",entry.key,entry.value.fullyQualifiedName)
-            val typeRef = new ReferencedTypeImpl(entry.value.packageName,entry.value.name)
+            val typeRef = new ReferencedTypeImpl(entry.value.packageName, entry.value.name)
             typeToDefinition.put(typeRef, entry.value);
             if (schemaNode != null) {
                 typeToSchemaNode.put(typeRef, schemaNode);
@@ -263,9 +273,10 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
         binding.typeToDefinition = typeToDefinition
         binding.typeToSchemaNode = typeToSchemaNode
         binding.typeDefinitions = typeDefinitions
-//        if (ctx !== null) {
-//            listenerRegistration = ctx.registerService(SchemaServiceListener, this, new Hashtable<String, String>());
-//        }
+
+    //        if (ctx !== null) {
+    //            listenerRegistration = ctx.registerService(SchemaServiceListener, this, new Hashtable<String, String>());
+    //        }
     }
 
     override getRpcQNamesFor(Class<? extends RpcService> service) {
@@ -280,9 +291,9 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
         if (typeToDefinition.containsKey(type)) {
             return;
         }
-        LOG.info("Thread blocked waiting for schema for: {}",type.fullyQualifiedName)
+        LOG.info("Thread blocked waiting for schema for: {}", type.fullyQualifiedName)
         type.waitForTypeDefinition.get();
-        LOG.info("Schema for {} became available, thread unblocked",type.fullyQualifiedName)
+        LOG.info("Schema for {} became available, thread unblocked", type.fullyQualifiedName)
     }
 
     private def Future<Type> waitForTypeDefinition(Type type) {
@@ -318,4 +329,30 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
         ]
     }
 
+    override getRpcServiceClassFor(String namespace, String revision) {
+        val module = schemaContext?.findModuleByName(namespace.toString, QName.parseRevision(revision));
+        if (module == null) {
+            return Optional.absent();
+        }
+        try {
+            val rpcTypeName = module.rpcServiceType;
+            if (rpcTypeName.present) {
+                val rpcClass = classLoadingStrategy.loadClass(rpcTypeName.get.fullyQualifiedName);
+                return Optional.of(rpcClass as Class<? extends RpcService>);
+            }
+        } catch (Exception e) {
+            LOG.debug("RPC class not present for {},{}", namespace, revision, e);
+        }
+        return Optional.absent()
+    }
+
+    def Optional<Type> getRpcServiceType(Module module) {
+        val namespace = BindingGeneratorUtil.moduleNamespaceToPackageName(module);
+        if (module.rpcs.empty) {
+            return Optional.<Type>absent();
+        }
+        return Optional.<Type>of(
+            new ReferencedTypeImpl(namespace,
+                BindingMapping.getClassName(module.name) + BindingMapping.RPC_SERVICE_SUFFIX));
+    }
 }
index 0103e69add6ca88482b4d978c7b02e74f664bb5d..35c8c16d819c703be741f43f72fb270ba8234e49 100644 (file)
@@ -113,6 +113,9 @@ class TransformerGenerator {
     @Property
     var GeneratorListener listener;
 
+    @Property
+    var extension GeneratedClassLoadingStrategy classLoadingStrategy
+
     public static val CLASS_TYPE = Types.typeForClass(Class);
 
     public new(ClassPool pool) {
@@ -121,6 +124,8 @@ class TransformerGenerator {
 
         BINDING_CODEC = BindingCodec.asCtClass;
         ctQName = QName.asCtClass
+
+        classLoadingStrategy = GeneratedClassLoadingStrategy.TCCLClassLoadingStrategy;
     }
 
     def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType) {
@@ -154,7 +159,7 @@ class TransformerGenerator {
                 typeSpecBuilder = pathToType.get(node.path);
             }
             var schemaNode = typeToSchemaNode.get(ref);
-            if(schemaNode === null) {
+            if (schemaNode === null) {
                 schemaNode = node;
             }
             checkState(typeSpecBuilder !== null, "Could not find TypeDefinition for %s, $s", inputType.name, node);
@@ -198,7 +203,7 @@ class TransformerGenerator {
     def Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifiable(Class<?> parentType) {
         return withClassLoaderAndLock(parentType.classLoader, lock) [ |
             val inputName = parentType.name + "Key";
-            val inputType = loadClassWithTCCL(inputName);
+            val inputType = loadClass(inputName);
             val ret = getGeneratedClass(inputType)
             if (ret !== null) {
                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
@@ -247,24 +252,24 @@ class TransformerGenerator {
     private def Class<?> getGeneratedClass(Class<? extends Object> cls) {
 
         try {
-            return loadClassWithTCCL(cls.codecClassName)
+            return loadClass(cls.codecClassName)
         } catch (ClassNotFoundException e) {
             return null;
         }
     }
 
     private def Class<?> keyTransformer(GeneratedType type, ListSchemaNode node) {
-        val cls = loadClassWithTCCL(type.resolvedName + "Key");
+        val cls = loadClass(type.resolvedName + "Key");
         keyTransformerFor(cls, type, node);
     }
 
     private def serializer(Type type, DataSchemaNode node) {
-        val cls = loadClassWithTCCL(type.resolvedName);
+        val cls = loadClass(type.resolvedName);
         transformerFor(cls, node);
     }
 
     private def Class<?> valueSerializer(GeneratedTransferObject type, TypeDefinition<?> typeDefinition) {
-        val cls = loadClassWithTCCL(type.resolvedName);
+        val cls = loadClass(type.resolvedName);
         val transformer = cls.generatedClass;
         if (transformer !== null) {
             return transformer;
@@ -281,7 +286,7 @@ class TransformerGenerator {
     }
 
     private def Class<?> valueSerializer(Enumeration type, TypeDefinition<?> typeDefinition) {
-        val cls = loadClassWithTCCL(type.resolvedName);
+        val cls = loadClass(type.resolvedName);
         val transformer = cls.generatedClass;
         if (transformer !== null) {
             return transformer;
@@ -543,7 +548,7 @@ class TransformerGenerator {
                     bodyChecked = '''
                         {
                             «QName.name» _localQName = QNAME;
-
+                        
                             if($2 == null) {
                             return null;
                             }
@@ -552,12 +557,12 @@ class TransformerGenerator {
                             «type.builderName» _builder = new «type.builderName»();
                             boolean _is_empty = true;
                             «FOR child : node.childNodes»
-                                «val signature = properties.getFor(child)»
-                                «deserializeProperty(child, signature.value, signature.key)»
-                                _builder.«signature.key.toSetter»(«signature.key»);
+                            «val signature = properties.getFor(child)»
+                            «deserializeProperty(child, signature.value, signature.key)»
+                            _builder.«signature.key.toSetter»(«signature.key»);
                             «ENDFOR»
                             if(_is_empty) {
-                                return null;
+                            return null;
                             }
                             return _builder.build();
                         }
@@ -675,7 +680,7 @@ class TransformerGenerator {
             ''';
         }
     }
-    
+
     private def String deserializeBodyWithAugmentations(GeneratedType type, DataNodeContainer node) '''
         {
             «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
@@ -694,9 +699,9 @@ class TransformerGenerator {
     private def dispatch String deserializeBodyImpl(GeneratedType type, SchemaNode node) '''
         {
             «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
-
+        
             if($2 == null) {
-                return null;
+            return null;
             }
             java.util.Map _compositeNode = (java.util.Map) $2;
             «type.builderName» _builder = new «type.builderName»();
@@ -721,15 +726,15 @@ class TransformerGenerator {
     '''
 
     private def dispatch String deserializeBodyImpl(GeneratedType type, ContainerSchemaNode node) {
-        return deserializeBodyWithAugmentations(type,node);
+        return deserializeBodyWithAugmentations(type, node);
     }
-    
+
     private def dispatch String deserializeBodyImpl(GeneratedType type, NotificationDefinition node) {
-        return deserializeBodyWithAugmentations(type,node);
+        return deserializeBodyWithAugmentations(type, node);
     }
 
-    private def dispatch String deserializeBodyImpl(GeneratedType type, ChoiceCaseNode node)  {
-        return deserializeBodyWithAugmentations(type,node);
+    private def dispatch String deserializeBodyImpl(GeneratedType type, ChoiceCaseNode node) {
+        return deserializeBodyWithAugmentations(type, node);
     }
 
     private def deserializeDataNodeContainerBody(GeneratedType type, DataNodeContainer node) {
@@ -787,7 +792,7 @@ class TransformerGenerator {
                 _hasNext = _iterator.hasNext();
             }
         }
-
+        
         ////System.out.println(" list" + «propertyName»);
     '''
 
@@ -878,9 +883,9 @@ class TransformerGenerator {
                     bodyChecked = '''
                         {
                             ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
-
+                        
                             if($1 == null) {
-                                return null;
+                            return null;
                             }
                             «typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
                             ////System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
@@ -903,9 +908,9 @@ class TransformerGenerator {
                     bodyChecked = '''
                         {
                             ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
-
+                        
                             if($1 == null) {
-                                return null;
+                            return null;
                             }
                             «returnType.resolvedName» _simpleValue = «deserializeValue(returnType, "$1", null)»;
                             «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(_simpleValue);
@@ -937,7 +942,7 @@ class TransformerGenerator {
         try {
             val ctCls = createClass(typeSpec.codecClassName) [
                 val properties = typeSpec.allProperties;
-                val getterToTypeDefinition = XtendHelper.getTypes(typeDef).toMap[type | type.QName.getterName];
+                val getterToTypeDefinition = XtendHelper.getTypes(typeDef).toMap[type|type.QName.getterName];
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
                 if (inputType.isYangBindingAvailable) {
                     implementsType(BINDING_CODEC)
@@ -948,25 +953,25 @@ class TransformerGenerator {
                 method(Object, "toDomValue", Object) [
                     modifiers = PUBLIC + FINAL + STATIC
                     val ctSpec = inputType.asCtClass;
-
                     bodyChecked = '''
                         {
                             ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
-
+                        
                             if($1 == null) {
-                                return null;
+                            return null;
                             }
                             «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
                             «FOR property : properties.entrySet»
-                                «IF property.key != "getValue"»
-                                    «property.value.resolvedName» «property.key» = («property.value.resolvedName») _value.«property.
+                            «IF property.key != "getValue"»
+                                «property.value.resolvedName» «property.key» = («property.value.resolvedName») _value.«property.
                             key»();
-                                    if(«property.key» != null) {
-                                        return «serializeValue(property.value, property.key, getterToTypeDefinition.get(property.key))»;
-                                    }
-                                «ENDIF»
+                                if(«property.key» != null) {
+                                    return «serializeValue(property.value, property.key,
+                            getterToTypeDefinition.get(property.key))»;
+                                }
+                            «ENDIF»
                             «ENDFOR»
-
+                        
                             return null;
                         }
                     '''
@@ -983,13 +988,13 @@ class TransformerGenerator {
                     bodyChecked = '''
                         {
                             ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
-
+                        
                             if($1 == null) {
-                                return null;
+                            return null;
                             }
                             if($1 instanceof String) {
-                                String _simpleValue = (String) $1;
-                                return new «typeSpec.resolvedName»(_simpleValue.toCharArray());
+                            String _simpleValue = (String) $1;
+                            return new «typeSpec.resolvedName»(_simpleValue.toCharArray());
                             }
                             return null;
                         }
@@ -1014,7 +1019,6 @@ class TransformerGenerator {
         }
     }
 
-
     private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
         Class<?> inputType, GeneratedTransferObject typeSpec, BitsTypeDefinition typeDef) {
         try {
@@ -1032,23 +1036,23 @@ class TransformerGenerator {
                     bodyChecked = '''
                         {
                             ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
-
+                        
                             if($1 == null) {
-                                return null;
+                            return null;
                             }
                             «typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
                             «HashSet.resolvedName» _value = new «HashSet.resolvedName»();
                             //System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
-
+                        
                             «FOR bit : typeDef.bits»
-                                «val getter = bit.getterName()»
-                                if(Boolean.TRUE.equals(_encapsulatedValue.«getter»())) {
-                                    _value.add("«bit.name»");
-                                }
+                            «val getter = bit.getterName()»
+                            if(Boolean.TRUE.equals(_encapsulatedValue.«getter»())) {
+                                _value.add("«bit.name»");
+                            }
                             «ENDFOR»
                             «Set.resolvedName» _domValue =  «Collections.resolvedName».unmodifiableSet(_value);
                             //System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_domValue);
-
+                        
                             return _domValue;
                         }
                     '''
@@ -1066,15 +1070,15 @@ class TransformerGenerator {
                     bodyChecked = '''
                         {
                             //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
-
+                        
                             if($1 == null) {
-                                return null;
+                            return null;
                             }
                             «Set.resolvedName» _domValue = («Set.resolvedName») $1;
                             «FOR bit : sortedBits»
-                                Boolean «bit.propertyName» = Boolean.valueOf(_domValue.contains("«bit.name»"));
+                            Boolean «bit.propertyName» = Boolean.valueOf(_domValue.contains("«bit.name»"));
                             «ENDFOR»
-
+                        
                             return new «inputType.resolvedName»(«FOR bit : sortedBits SEPARATOR ","»«bit.propertyName»«ENDFOR»);
                         }
                     '''
@@ -1318,19 +1322,19 @@ class TransformerGenerator {
     '''
 
     private def dispatch String serializeBody(GeneratedType type, ListSchemaNode node) {
-        return serializeBodyImpl(type,node);
+        return serializeBodyImpl(type, node);
     }
 
     private def dispatch String serializeBody(GeneratedType type, NotificationDefinition node) {
-        return serializeBodyImpl(type,node);
+        return serializeBodyImpl(type, node);
     }
 
     private def dispatch String serializeBody(GeneratedType type, ContainerSchemaNode node) {
-        return serializeBodyImpl(type,node);
+        return serializeBodyImpl(type, node);
     }
 
-    private def dispatch String serializeBody(GeneratedType type, ChoiceCaseNode node){
-        return serializeBodyImpl(type,node);
+    private def dispatch String serializeBody(GeneratedType type, ChoiceCaseNode node) {
+        return serializeBodyImpl(type, node);
     }
 
     private def dispatch String serializeBody(GeneratedType type, SchemaNode node) '''
@@ -1404,7 +1408,7 @@ class TransformerGenerator {
 
     private def dispatch CharSequence serializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
         «type.resolvedName» «propertyName» = value.«propertyName»();
-
+        
         if(«propertyName» != null) {
             «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
             Object _propValue = «serializeValue(type, propertyName, schema.type)»;
@@ -1530,7 +1534,7 @@ class TransformerGenerator {
     }
 
     def CtClass asCtClass(Type type) {
-        val cls = loadClassWithTCCL(type.fullyQualifiedName)
+        val cls = loadClass(type.fullyQualifiedName)
         return cls.asCtClass;
     }
 
index be74c9caaad5e4e604ccb2aa833324ac6c1a8e05..b5421a3f28cd12f4c052caca5de97c905c495c9c 100644 (file)
@@ -59,14 +59,15 @@ public final class ClassLoaderUtils {
         return constructor.newInstance(initargs);
     }
 
-    public static Class<?> loadClassWithTCCL(String name) throws ClassNotFoundException {
+    
+    public static Class<?> loadClass(ClassLoader cls, String name) throws ClassNotFoundException {
         if ("byte[]".equals(name)) {
             return byte[].class;
         } else if("char[]".equals(name)) {
             return char[].class;
         }
         try {
-            return Thread.currentThread().getContextClassLoader().loadClass(name);
+            return cls.loadClass(name);
         } catch (ClassNotFoundException e) {
             String[] components = name.split("\\.");
             String potentialOuter;
@@ -75,12 +76,16 @@ public final class ClassLoaderUtils {
 
                     String outerName = Joiner.on(".").join(Arrays.asList(components).subList(0, length - 1));
                     String innerName = outerName + "$" + components[length-1];
-                    return Thread.currentThread().getContextClassLoader().loadClass(innerName);
+                    return cls.loadClass(innerName);
             } else {
                 throw e;
             }
         }
     }
+    
+    public static Class<?> loadClassWithTCCL(String name) throws ClassNotFoundException {
+        return loadClass(Thread.currentThread().getContextClassLoader(), name);
+    }
 
     public static Class<?> tryToLoadClassWithTCCL(String fullyQualifiedName) {
         try {
index f5db26dedaf01b401247799e607cdd4c674d2b9d..5b1d45a679f762e2f0eaad464da2f15c7feac838 100644 (file)
@@ -35,6 +35,8 @@ public final class BindingMapping {
 
     private static final Splitter SPACE_SPLITTER = Splitter.on(" ").omitEmptyStrings().trimResults();
 
+    public static final String MODULE_INFO_CLASS_NAME = "$ModuleInfoImpl";
+
     public static final String getMethodName(QName name) {
         checkArgument(name != null, "Name should not be null.");
         return getMethodName(name.getLocalName());
index 137640203378d67a2a0ce78837ed01fb173c880c..8967270870b052ab4db91221f8e3b74e42b6f832 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.yangtools.yang.binding.util;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
+import java.util.concurrent.Callable;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.MatchResult;
@@ -25,11 +26,15 @@ import org.opendaylight.yangtools.yang.binding.ChildOf;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.annotations.ModuleQName;
 import org.opendaylight.yangtools.yang.common.QName;
 
 import static com.google.common.base.Preconditions.*;
+import static org.opendaylight.yangtools.concepts.util.ClassLoaderUtils.*;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
@@ -167,4 +172,29 @@ public class BindingReflections {
         return rootPackage;
     }
 
+    public static YangModuleInfo getModuleInfo(final Class<?> cls) throws Exception {
+        checkArgument(cls != null);
+        String packageName = getModelRootPackageName(cls.getPackage());
+        final String potentialClassName = getModuleInfoClassName(packageName);
+        return withClassLoader(cls.getClassLoader(), new Callable<YangModuleInfo>() {
+        
+            @Override
+            public YangModuleInfo call() throws Exception {
+                Class<?> moduleInfoClass = Thread.currentThread().getContextClassLoader().loadClass(potentialClassName);
+                return (YangModuleInfo) moduleInfoClass.getMethod("getInstance").invoke(null);
+            }
+        });
+    }
+
+    public static String getModuleInfoClassName(String packageName) {
+        return packageName + "." + BindingMapping.MODULE_INFO_CLASS_NAME;
+    }
+
+    public static boolean isBindingClass(Class<?> cls) {
+       if(DataContainer.class.isAssignableFrom(cls) || Augmentation.class.isAssignableFrom(cls)) {
+           return true;
+       }
+       return (cls.getName().startsWith(BindingMapping.PACKAGE_PREFIX));
+    }
+
 }
index 4e49bfd2d49faccfedce95add4145abd73d21582..b4de8b5c5110be094475955900c29483543fb55a 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.codec;
 
+import java.net.URI;
 import java.util.Map.Entry;
 import java.util.Set;
 
@@ -17,6 +18,8 @@ import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
+import com.google.common.base.Optional;
+
 public interface BindingIndependentMappingService {
 
     CodecRegistry getCodecRegistry();
@@ -39,6 +42,8 @@ public interface BindingIndependentMappingService {
      * @return List of QNames. The user may not modify this list.
      */
     Set<QName> getRpcQNamesFor(Class<? extends RpcService> service);
+    
+    Optional<Class<? extends RpcService>> getRpcServiceClassFor(String namespace, String revision);
 
     DataContainer dataObjectFromDataDom(Class<? extends DataContainer> inputClass, CompositeNode domInput);