Move ClassLoaderUtils 60/7160/2
authorRobert Varga <rovarga@cisco.com>
Sun, 18 May 2014 13:07:58 +0000 (15:07 +0200)
committerRobert Varga <rovarga@cisco.com>
Sun, 18 May 2014 14:30:58 +0000 (16:30 +0200)
This patch makes an attempt at unifying and improving the two
ClassLoaderUtils versions we have available. This is a prerequisite to
being able to being able to maintain them properly.

At this point the sanest place for them is yang-binding, as it has
guava, slf4j and is at least transitively pulled from all users.

Change-Id: Iea7ae5fb7ef40f9af960ca01b000f81237c70ab0
Signed-off-by: Robert Varga <rovarga@cisco.com>
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/AbstractTransformerGenerator.java
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedClassLoadingStrategy.java
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/ModuleInfoBackedContext.java
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/ClassLoaderUtils.java
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/util/ClassLoaderUtils.java
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/BindingReflections.java
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/ClassLoaderUtils.java [new file with mode: 0644]

index fd280427d41b978c847e301da669b29e9010afc7..373ea7df71f52854129213b62b02f1f67101dbb8 100644 (file)
@@ -16,10 +16,10 @@ import javassist.ClassPool;
 
 import org.eclipse.xtext.xbase.lib.Extension;
 import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
-import org.opendaylight.yangtools.sal.binding.generator.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
 import org.opendaylight.yangtools.yang.binding.BindingCodec;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
index 362ebe6e881e9457e0b6425783a6d82c6ee6b2b9..5440e0151141d8e744abdf428b9d2ecb3ec21b1b 100644 (file)
@@ -8,25 +8,26 @@
 package org.opendaylight.yangtools.sal.binding.generator.impl;
 
 import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
-import org.opendaylight.yangtools.sal.binding.generator.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
 
 public abstract class GeneratedClassLoadingStrategy implements ClassLoadingStrategy {
 
     private static final GeneratedClassLoadingStrategy TCCL_STRATEGY = new TCCLClassLoadingStrategy();
 
     private static final GeneratedClassLoadingStrategy ALWAYS_FAIL_STRATEGY = new GeneratedClassLoadingStrategy() {
-
         @Override
-        public Class<?> loadClass(String fullyQualifiedName) throws ClassNotFoundException {
+        public Class<?> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
             throw new ClassNotFoundException(fullyQualifiedName);
         }
     };
 
-    public Class<?> loadClass(Type type) throws ClassNotFoundException {
+    @Override
+    public Class<?> loadClass(final Type type) throws ClassNotFoundException {
         return loadClass(type.getFullyQualifiedName());
     }
 
+    @Override
     public abstract Class<?> loadClass(String fullyQualifiedName) throws ClassNotFoundException;
 
     public static final GeneratedClassLoadingStrategy getTCCLClassLoadingStrategy() {
@@ -38,9 +39,8 @@ public abstract class GeneratedClassLoadingStrategy implements ClassLoadingStrat
     }
 
     private static final class TCCLClassLoadingStrategy extends GeneratedClassLoadingStrategy {
-
         @Override
-        public Class<?> loadClass(String fullyQualifiedName) throws ClassNotFoundException {
+        public Class<?> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
             return ClassLoaderUtils.loadClassWithTCCL(fullyQualifiedName);
         }
     }
index cf5c83d729070f113570fc6a44f18ef29e6b02a5..335ec5967e29536f5c8a97d3843146aa59181986 100644 (file)
@@ -7,16 +7,20 @@
  */
 package org.opendaylight.yangtools.sal.binding.generator.impl;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.ref.WeakReference;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
 import org.opendaylight.yangtools.concepts.ObjectRegistration;
 import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
 import org.opendaylight.yangtools.sal.binding.generator.api.ModuleInfoRegistry;
-import org.opendaylight.yangtools.sal.binding.generator.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
@@ -26,18 +30,15 @@ import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.ref.WeakReference;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 
 public class ModuleInfoBackedContext extends GeneratedClassLoadingStrategy //
         implements //
         AdvancedSchemaSourceProvider<InputStream>, ModuleInfoRegistry, SchemaContextProvider {
 
-    private ModuleInfoBackedContext(ClassLoadingStrategy loadingStrategy) {
+    private ModuleInfoBackedContext(final ClassLoadingStrategy loadingStrategy) {
         this.backingLoadingStrategy = loadingStrategy;
     }
 
@@ -45,7 +46,7 @@ public class ModuleInfoBackedContext extends GeneratedClassLoadingStrategy //
         return new ModuleInfoBackedContext(getTCCLClassLoadingStrategy());
     }
 
-    public static ModuleInfoBackedContext create(ClassLoadingStrategy loadingStrategy) {
+    public static ModuleInfoBackedContext create(final ClassLoadingStrategy loadingStrategy) {
         return new ModuleInfoBackedContext(loadingStrategy);
     }
 
@@ -57,7 +58,7 @@ public class ModuleInfoBackedContext extends GeneratedClassLoadingStrategy //
     private final ClassLoadingStrategy backingLoadingStrategy;
 
     @Override
-    public Class<?> loadClass(String fullyQualifiedName) throws ClassNotFoundException {
+    public Class<?> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
         String modulePackageName = BindingReflections.getModelRootPackageName(fullyQualifiedName);
 
         WeakReference<ClassLoader> classLoaderRef = packageNameToClassLoader.get(modulePackageName);
@@ -110,7 +111,7 @@ public class ModuleInfoBackedContext extends GeneratedClassLoadingStrategy //
         return sourceStreams.build();
     }
 
-    private boolean resolveModuleInfo(Class<?> cls) {
+    private boolean resolveModuleInfo(final Class<?> cls) {
         try {
             return resolveModuleInfo(BindingReflections.getModuleInfo(cls));
         } catch (Exception e) {
@@ -118,7 +119,7 @@ public class ModuleInfoBackedContext extends GeneratedClassLoadingStrategy //
         }
     }
 
-    private boolean resolveModuleInfo(YangModuleInfo moduleInfo) {
+    private boolean resolveModuleInfo(final YangModuleInfo moduleInfo) {
 
         SourceIdentifier identifier = sourceIdentifierFrom(moduleInfo);
         YangModuleInfo previous = sourceIdentifierToModuleInfo.putIfAbsent(identifier, moduleInfo);
@@ -136,18 +137,18 @@ public class ModuleInfoBackedContext extends GeneratedClassLoadingStrategy //
         return true;
     }
 
-    private SourceIdentifier sourceIdentifierFrom(YangModuleInfo moduleInfo) {
+    private SourceIdentifier sourceIdentifierFrom(final YangModuleInfo moduleInfo) {
         return SourceIdentifier.create(moduleInfo.getName(), Optional.of(moduleInfo.getRevision()));
     }
 
-    public void addModuleInfos(Iterable<? extends YangModuleInfo> moduleInfos) {
+    public void addModuleInfos(final Iterable<? extends YangModuleInfo> moduleInfos) {
         for (YangModuleInfo yangModuleInfo : moduleInfos) {
             registerModuleInfo(yangModuleInfo);
         }
     }
 
     @Override
-    public ObjectRegistration<YangModuleInfo> registerModuleInfo(YangModuleInfo yangModuleInfo) {
+    public ObjectRegistration<YangModuleInfo> registerModuleInfo(final YangModuleInfo yangModuleInfo) {
         YangModuleInfoRegistration registration = new YangModuleInfoRegistration(yangModuleInfo, this);
 
         resolveModuleInfo(yangModuleInfo);
@@ -156,7 +157,7 @@ public class ModuleInfoBackedContext extends GeneratedClassLoadingStrategy //
     }
 
     @Override
-    public Optional<InputStream> getSchemaSource(SourceIdentifier sourceIdentifier) {
+    public Optional<InputStream> getSchemaSource(final SourceIdentifier sourceIdentifier) {
         YangModuleInfo info = sourceIdentifierToModuleInfo.get(sourceIdentifier);
         if (info == null) {
             return Optional.absent();
@@ -169,7 +170,7 @@ public class ModuleInfoBackedContext extends GeneratedClassLoadingStrategy //
     }
 
     @Override
-    public Optional<InputStream> getSchemaSource(String moduleName, Optional<String> revision) {
+    public Optional<InputStream> getSchemaSource(final String moduleName, final Optional<String> revision) {
         return getSchemaSource(SourceIdentifier.create(moduleName, revision));
     }
 
@@ -177,7 +178,7 @@ public class ModuleInfoBackedContext extends GeneratedClassLoadingStrategy //
 
         private final ModuleInfoBackedContext context;
 
-        public YangModuleInfoRegistration(YangModuleInfo instance, ModuleInfoBackedContext context) {
+        public YangModuleInfoRegistration(final YangModuleInfo instance, final ModuleInfoBackedContext context) {
             super(instance);
             this.context = context;
         }
@@ -189,7 +190,7 @@ public class ModuleInfoBackedContext extends GeneratedClassLoadingStrategy //
 
     }
 
-    private void remove(YangModuleInfoRegistration registration) {
+    private void remove(final YangModuleInfoRegistration registration) {
         // FIXME implement
     }
 
index 15895528936020a89ac8010a4a3b0840b8386c4e..01ed2f0240030aeaeff055148af8038b9d1124fb 100644 (file)
@@ -19,6 +19,10 @@ import java.util.concurrent.locks.Lock;
 import com.google.common.base.Joiner;
 import com.google.common.base.Optional;
 
+/**
+ * @deprecated Use {@link org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils} instead.
+ */
+@Deprecated
 public final class ClassLoaderUtils {
 
     private ClassLoaderUtils() {
index f2402270efeaa409102c3ceffa3553f50e5d515e..e898e72479f441b6a1db405e42ac50f7ff1ec96a 100644 (file)
@@ -12,18 +12,21 @@ import java.lang.reflect.Type;
 import java.util.concurrent.Callable;
 import java.util.concurrent.locks.Lock;
 
-
+/**
+ * @deprecated Use {@link org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils} instead.
+ */
+@Deprecated
 public final class ClassLoaderUtils {
 
     private ClassLoaderUtils() {
         throw new UnsupportedOperationException("Utility class");
     }
 
-    public static <V> V withClassLoader(ClassLoader cls, Callable<V> function) throws Exception {
+    public static <V> V withClassLoader(final ClassLoader cls, final Callable<V> function) throws Exception {
         return withClassLoaderAndLock(cls, null, function);
     }
 
-    public static <V> V withClassLoaderAndLock(ClassLoader cls, Lock lock, Callable<V> function) throws Exception {
+    public static <V> V withClassLoaderAndLock(final ClassLoader cls, final Lock lock, final Callable<V> function) throws Exception {
         if (cls == null) {
             throw new IllegalArgumentException("Classloader should not be null");
         }
@@ -46,7 +49,7 @@ public final class ClassLoaderUtils {
         }
     }
 
-    public static ParameterizedType findParameterizedType(Class<?> subclass, Class<?> genericType) {
+    public static ParameterizedType findParameterizedType(final Class<?> subclass, final Class<?> genericType) {
         if(subclass == null || genericType == null) {
             throw new IllegalArgumentException("Class was not specified.");
         }
@@ -65,7 +68,7 @@ public final class ClassLoaderUtils {
             return null;
         }
     }
-    
+
     private static <S,G,P> Callable<Class<P>> findFirstGenericArgumentTask(final Class<S> scannedClass, final Class<G> genericType) {
         return new Callable<Class<P>>() {
             @Override
@@ -81,7 +84,7 @@ public final class ClassLoaderUtils {
         };
     }
 
-    public static Type getFirstGenericParameter(Type type) {
+    public static Type getFirstGenericParameter(final Type type) {
         if(type instanceof ParameterizedType) {
             return ((ParameterizedType) type).getActualTypeArguments()[0];
         }
index 5e1494c55e7d27b6a620ccba5fe9aab318560448..b0671397f3b179afcd5b14f80d60d2e766b72543 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.yangtools.yang.binding.util;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
-import static org.opendaylight.yangtools.concepts.util.ClassLoaderUtils.withClassLoader;
 
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
@@ -22,7 +21,6 @@ import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import org.opendaylight.yangtools.concepts.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.binding.Augmentable;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
@@ -35,7 +33,6 @@ import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider;
 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
 import org.opendaylight.yangtools.yang.common.QName;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -202,8 +199,7 @@ public class BindingReflections {
         checkArgument(cls != null);
         String packageName = getModelRootPackageName(cls.getPackage());
         final String potentialClassName = getModuleInfoClassName(packageName);
-        return withClassLoader(cls.getClassLoader(), new Callable<YangModuleInfo>() {
-
+        return ClassLoaderUtils.withClassLoader(cls.getClassLoader(), new Callable<YangModuleInfo>() {
             @Override
             public YangModuleInfo call() throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
                 Class<?> moduleInfoClass = Thread.currentThread().getContextClassLoader().loadClass(potentialClassName);
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/ClassLoaderUtils.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/ClassLoaderUtils.java
new file mode 100644 (file)
index 0000000..e61aa73
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * 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.yang.binding.util;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.locks.Lock;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Supplier;
+
+public final class ClassLoaderUtils {
+    private static final Logger LOG = LoggerFactory.getLogger(ClassLoaderUtils.class);
+
+    private ClassLoaderUtils() {
+        throw new UnsupportedOperationException("Utility class");
+    }
+
+    public static <V> V withClassLoader(final ClassLoader cls, final Supplier<V> function) {
+        checkNotNull(cls, "Classloader should not be null");
+        checkNotNull(function, "Function should not be null");
+
+        final ClassLoader oldCls = Thread.currentThread().getContextClassLoader();
+        try {
+            Thread.currentThread().setContextClassLoader(cls);
+            return function.get();
+        } finally {
+            Thread.currentThread().setContextClassLoader(oldCls);
+        }
+    }
+
+    public static <V> V withClassLoader(final ClassLoader cls, final Callable<V> function) throws Exception {
+        checkNotNull(cls, "Classloader should not be null");
+        checkNotNull(function, "Function should not be null");
+
+        final ClassLoader oldCls = Thread.currentThread().getContextClassLoader();
+        try {
+            Thread.currentThread().setContextClassLoader(cls);
+            return function.call();
+        } finally {
+            Thread.currentThread().setContextClassLoader(oldCls);
+        }
+    }
+
+    public static <V> V withClassLoaderAndLock(final ClassLoader cls, final Lock lock, final Supplier<V> function) {
+        checkNotNull(lock, "Lock should not be null");
+
+        lock.lock();
+        try {
+            return withClassLoader(cls, function);
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public static Object construct(final Constructor<? extends Object> constructor, final List<Object> objects)
+            throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+        final Object[] initargs = objects.toArray();
+        return constructor.newInstance(initargs);
+    }
+
+    public static Class<?> loadClass(final ClassLoader cls, final String name) throws ClassNotFoundException {
+        if ("byte[]".equals(name)) {
+            return byte[].class;
+        }
+        if ("char[]".equals(name)) {
+            return char[].class;
+        }
+
+        try {
+            return cls.loadClass(name);
+        } catch (ClassNotFoundException e) {
+            String[] components = name.split("\\.");
+            String potentialOuter;
+            int length = components.length;
+            if (length > 2 && (potentialOuter = components[length - 2]) != null && Character.isUpperCase(potentialOuter.charAt(0))) {
+                    String outerName = Joiner.on(".").join(Arrays.asList(components).subList(0, length - 1));
+                    String innerName = outerName + "$" + components[length-1];
+                    return cls.loadClass(innerName);
+            } else {
+                throw e;
+            }
+        }
+    }
+
+    public static Class<?> loadClassWithTCCL(final String name) throws ClassNotFoundException {
+        return loadClass(Thread.currentThread().getContextClassLoader(), name);
+    }
+
+    public static Class<?> tryToLoadClassWithTCCL(final String fullyQualifiedName) {
+        try {
+            return loadClassWithTCCL(fullyQualifiedName);
+        } catch (ClassNotFoundException e) {
+            LOG.debug("Failed to load class {}", fullyQualifiedName, e);
+            return null;
+        }
+    }
+
+    public static <S,G,P> Class<P> findFirstGenericArgument(final Class<S> scannedClass, final Class<G> genericType) {
+        return withClassLoader(scannedClass.getClassLoader(), ClassLoaderUtils.<S,G,P>findFirstGenericArgumentTask(scannedClass, genericType));
+    }
+
+    private static <S,G,P> Supplier<Class<P>> findFirstGenericArgumentTask(final Class<S> scannedClass, final Class<G> genericType) {
+        return new Supplier<Class<P>>() {
+            @Override
+            @SuppressWarnings("unchecked")
+            public Class<P> get() {
+                final ParameterizedType augmentationGeneric = findParameterizedType(scannedClass, genericType);
+                if (augmentationGeneric != null) {
+                    return (Class<P>) augmentationGeneric.getActualTypeArguments()[0];
+                }
+                return null;
+            }
+        };
+    }
+
+    public static ParameterizedType findParameterizedType(final Class<?> subclass, final Class<?> genericType) {
+        Preconditions.checkNotNull(subclass);
+        Preconditions.checkNotNull(genericType);
+
+        for (Type type : subclass.getGenericInterfaces()) {
+            if (type instanceof ParameterizedType && genericType.equals(((ParameterizedType) type).getRawType())) {
+                return (ParameterizedType) type;
+            }
+        }
+
+        LOG.debug("Class {} does not declare interface {}", subclass, genericType);
+        return null;
+    }
+
+    public static Type getFirstGenericParameter(final Type type) {
+        if (type instanceof ParameterizedType) {
+            return ((ParameterizedType) type).getActualTypeArguments()[0];
+        }
+        return null;
+    }
+}