BUG-983: prepare for proper wrapping 50/6850/1
authorRobert Varga <rovarga@cisco.com>
Sat, 10 May 2014 10:04:17 +0000 (12:04 +0200)
committerRobert Varga <rovarga@cisco.com>
Sat, 10 May 2014 10:04:17 +0000 (12:04 +0200)
This patch introduces a factory method to get instances, such that there
only ever is a single instance for a particular class pool. This fixes
the potential issue of adding a class path multiple times.

Change-Id: Ia8ff47674b768bd85ae50200734b8f14927f8a5c
Signed-off-by: Robert Varga <rovarga@cisco.com>
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/JavassistUtils.java

index 0d5175f9a3a75b88c1b5e329a57e9aa06d0e1b8f..9478dff19c74567a9c83fd9e93f7d2f8cb76c52c 100644 (file)
@@ -33,17 +33,48 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Preconditions;
 
-public class JavassistUtils {
+public final class JavassistUtils {
     private static final Logger LOG = LoggerFactory.getLogger(JavassistUtils.class);
 
+    private static final Map<ClassPool, JavassistUtils> INSTANCES = new WeakHashMap<>();
     private final Map<ClassLoader, ClassPath> loaderClassPaths = new WeakHashMap<>();
     private final Lock lock = new ReentrantLock();
     private final ClassPool classPool;
 
+    /**
+     * @deprecated Use {@link #forClassPool(ClassPool)} instead.
+     *
+     * This class provides auto-loading into the classpool. Unfortunately reusing
+     * the same class pool with multiple instances can lead the same classpath
+     * being added multiple times, which lowers performance and leaks memory.
+     */
+    @Deprecated
     public JavassistUtils(final ClassPool pool) {
+        this(pool, null);
+    }
+
+    private JavassistUtils(final ClassPool pool, final Object dummy) {
+        // FIXME: Remove 'dummy' once deprecated constructor is removed
         classPool = Preconditions.checkNotNull(pool);
     }
 
+    /**
+     * Get a utility instance for a particular class pool. A new instance is
+     * created if this is a new pool. If an instance already exists, is is
+     * returned.
+     *
+     * @param pool
+     * @return
+     */
+    public static synchronized JavassistUtils forClassPool(final ClassPool pool) {
+        JavassistUtils ret = INSTANCES.get(pool);
+        if (ret == null) {
+            ret = new JavassistUtils(pool, null);
+            INSTANCES.put(pool, ret);
+        }
+        return ret;
+    }
+
     public Lock getLock() {
         return lock;
     }
@@ -148,9 +179,6 @@ public class JavassistUtils {
     }
 
     public synchronized void appendClassLoaderIfMissing(final ClassLoader loader) {
-        // FIXME: this works as long as the ClassPool is not shared between instances of this class
-        //        How is synchronization across multiple instances done? The ClassPool itself just
-        //        keeps on adding the loaders and does not check for duplicates!
         if (!loaderClassPaths.containsKey(loader)) {
             final ClassPath ctLoader = new LoaderClassPath(loader);
             classPool.appendClassPath(ctLoader);