< prev index next >

src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/SyntheticRepository.java

Print this page

        

@@ -1,8 +1,7 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.

@@ -16,45 +15,39 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package com.sun.org.apache.bcel.internal.util;
 
+import java.io.IOException;
+import java.io.InputStream;
 
-import java.io.*;
-
+import com.sun.org.apache.bcel.internal.classfile.ClassParser;
+import com.sun.org.apache.bcel.internal.classfile.JavaClass;
+import java.lang.ref.SoftReference;
 import java.util.HashMap;
-
-import com.sun.org.apache.bcel.internal.classfile.*;
+import java.util.Map;
 
 /**
- * This repository is used in situations where a Class is created
- * outside the realm of a ClassLoader. Classes are loaded from
- * the file systems using the paths specified in the given
- * class path. By default, this is the value returned by
- * ClassPath.getClassPath().
- * <br>
- * It is designed to be used as a singleton, however it
- * can also be used with custom classpaths.
- *
-/**
- * Abstract definition of a class repository. Instances may be used
- * to load classes from different sources and may be used in the
- * Repository.setRepository method.
+ * This repository is used in situations where a Class is created outside the
+ * realm of a ClassLoader. Classes are loaded from the file systems using the
+ * paths specified in the given class path. By default, this is the value
+ * returned by ClassPath.getClassPath(). <br>
+ * This repository uses a factory design, allowing it to maintain a collection
+ * of different classpaths, and as such It is designed to be used as a singleton
+ * per classpath.
  *
  * @see com.sun.org.apache.bcel.internal.Repository
  *
- * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
- * @author David Dixon-Peugh
+ * @version $Id: SyntheticRepository.java 1748124 2016-06-13 08:02:16Z ggregory
+ * $
  */
 public class SyntheticRepository implements Repository {
 
-  private static HashMap _instances = new HashMap(); // CLASSPATH X REPOSITORY
-
-  private HashMap   _loadedClasses = new HashMap(); // CLASSNAME X JAVACLASS
+    // CLASSNAME X JAVACLASS
+    private final Map<String, SoftReference<JavaClass>> loadedClasses = new HashMap<>();
 
     private SyntheticRepository() {
     }
 
   public static SyntheticRepository getInstance() {

@@ -62,92 +55,123 @@
   }
 
   /**
    * Store a new JavaClass instance into this Repository.
    */
-  public void storeClass(JavaClass clazz) {
-    _loadedClasses.put(clazz.getClassName(), clazz);
+    @Override
+    public void storeClass(final JavaClass clazz) {
+        loadedClasses.put(clazz.getClassName(), new SoftReference<>(clazz));
     clazz.setRepository(this);
  }
 
   /**
    * Remove class from repository
    */
-  public void removeClass(JavaClass clazz) {
-    _loadedClasses.remove(clazz.getClassName());
+    @Override
+    public void removeClass(final JavaClass clazz) {
+        loadedClasses.remove(clazz.getClassName());
   }
 
   /**
    * Find an already defined (cached) JavaClass object by name.
    */
-  public JavaClass findClass(String className) {
-    return (JavaClass)_loadedClasses.get(className);
+    @Override
+    public JavaClass findClass(final String className) {
+        final SoftReference<JavaClass> ref = loadedClasses.get(className);
+        if (ref == null) {
+            return null;
+        }
+        return ref.get();
   }
 
   /**
-   * Load a JavaClass object for the given class name using
-   * the CLASSPATH environment variable.
-   */
-  public JavaClass loadClass(String className)
-    throws ClassNotFoundException
-  {
-    if(className == null || className.equals("")) {
+     * Finds a JavaClass object by name. If it is already in this Repository, the
+     * Repository version is returned.
+     *
+     * @param className the name of the class
+     * @return the JavaClass object
+     * @throws ClassNotFoundException if the class is not in the Repository
+     */
+    @Override
+    public JavaClass loadClass(String className) throws ClassNotFoundException {
+        if ((className == null) || className.isEmpty()) {
       throw new IllegalArgumentException("Invalid class name " + className);
     }
-
     className = className.replace('/', '.'); // Just in case, canonical form
+        final JavaClass clazz = findClass(className);
+        if (clazz != null) {
+            return clazz;
+        }
 
     IOException e = new IOException("Couldn't find: " + className + ".class");
     throw new ClassNotFoundException("Exception while looking for class " +
-                                       className + ": " + e.toString());
+                className + ": " + e, e);
   }
 
   /**
-   * Try to find class source via getResourceAsStream().
+     * Find the JavaClass object for a runtime Class object. If a class with the
+     * same name is already in this Repository, the Repository version is
+     * returned. Otherwise, getResourceAsStream() is called on the Class object
+     * to find the class's representation. If the representation is found, it is
+     * added to the Repository.
+     *
    * @see Class
+     * @param clazz the runtime Class object
    * @return JavaClass object for given runtime class
+     * @throws ClassNotFoundException if the class is not in the Repository, and
+     * its representation could not be found
    */
-  public JavaClass loadClass(Class clazz) throws ClassNotFoundException {
-    String className = clazz.getName();
+    @Override
+    public JavaClass loadClass(final Class<?> clazz) throws ClassNotFoundException {
+        final String className = clazz.getName();
+        final JavaClass repositoryClass = findClass(className);
+        if (repositoryClass != null) {
+            return repositoryClass;
+        }
     String name      = className;
-    int    i         = name.lastIndexOf('.');
-
-    if(i > 0) {
+        final int i = name.lastIndexOf('.');
+        if (i > 0) {
       name = name.substring(i + 1);
     }
-
-    return loadClass(clazz.getResourceAsStream(name + ".class"), className);
+        JavaClass cls = null;
+        try (InputStream clsStream = clazz.getResourceAsStream(name + ".class")) {
+            return cls = loadClass(clsStream, className);
+        } catch (final IOException e) {
+            return cls;
   }
 
-  private JavaClass loadClass(InputStream is, String className)
-    throws ClassNotFoundException
-  {
-    JavaClass clazz = findClass(className);
-
-    if(clazz != null) {
-      return clazz;
     }
 
-    try {
-      if(is != null) {
-        ClassParser parser = new ClassParser(is, className);
-        clazz = parser.parse();
 
+    private JavaClass loadClass(final InputStream is, final String className)
+            throws ClassNotFoundException {
+        try {
+            if (is != null) {
+                final ClassParser parser = new ClassParser(is, className);
+                final JavaClass clazz = parser.parse();
         storeClass(clazz);
-
         return clazz;
       }
-    } catch(IOException e) {
-      throw new ClassNotFoundException("Exception while looking for class " +
-                                       className + ": " + e.toString());
+        } catch (final IOException e) {
+            throw new ClassNotFoundException("Exception while looking for class "
+                    + className + ": " + e, e);
+        } finally {
+            if (is != null) {
+                try {
+                    is.close();
+                } catch (final IOException e) {
+                    // ignored
     }
-
-    throw new ClassNotFoundException("SyntheticRepository could not load " +
-                                     className);
+            }
+        }
+        throw new ClassNotFoundException("SyntheticRepository could not load "
+                + className);
   }
 
-  /** Clear all entries from cache.
+    /**
+     * Clear all entries from cache.
    */
+    @Override
   public void clear() {
-    _loadedClasses.clear();
+        loadedClasses.clear();
   }
 }
< prev index next >