1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.bcel.internal.util;
  23 
  24 
  25 import java.io.*;
  26 
  27 import java.util.Map;
  28 import java.util.HashMap;
  29 
  30 import com.sun.org.apache.bcel.internal.classfile.*;
  31 
  32 /**
  33  * This repository is used in situations where a Class is created
  34  * outside the realm of a ClassLoader. Classes are loaded from
  35  * the file systems using the paths specified in the given
  36  * class path. By default, this is the value returned by
  37  * ClassPath.getClassPath().
  38  * <br>
  39  * It is designed to be used as a singleton, however it
  40  * can also be used with custom classpaths.
  41  *
  42 /**
  43  * Abstract definition of a class repository. Instances may be used
  44  * to load classes from different sources and may be used in the
  45  * Repository.setRepository method.
  46  *
  47  * @see com.sun.org.apache.bcel.internal.Repository
  48  *
  49  * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  50  * @author David Dixon-Peugh
  51  */
  52 public class SyntheticRepository implements Repository {
  53   private static final String DEFAULT_PATH = ClassPath.getClassPath();
  54 
  55   private static HashMap _instances = new HashMap(); // CLASSPATH X REPOSITORY
  56 
  57   private ClassPath _path = null;
  58   private HashMap   _loadedClasses = new HashMap(); // CLASSNAME X JAVACLASS
  59 
  60   private SyntheticRepository(ClassPath path) {
  61     _path = path;
  62   }
  63 
  64   public static SyntheticRepository getInstance() {
  65     return getInstance(ClassPath.SYSTEM_CLASS_PATH);
  66   }
  67 
  68   public static SyntheticRepository getInstance(ClassPath classPath) {
  69     SyntheticRepository rep = (SyntheticRepository)_instances.get(classPath);
  70 
  71     if(rep == null) {
  72       rep = new SyntheticRepository(classPath);
  73       _instances.put(classPath, rep);
  74     }
  75 
  76     return rep;
  77   }
  78 
  79   /**
  80    * Store a new JavaClass instance into this Repository.
  81    */
  82   public void storeClass(JavaClass clazz) {
  83     _loadedClasses.put(clazz.getClassName(), clazz);
  84     clazz.setRepository(this);
  85  }
  86 
  87   /**
  88    * Remove class from repository
  89    */
  90   public void removeClass(JavaClass clazz) {
  91     _loadedClasses.remove(clazz.getClassName());
  92   }
  93 
  94   /**
  95    * Find an already defined (cached) JavaClass object by name.
  96    */
  97   public JavaClass findClass(String className) {
  98     return (JavaClass)_loadedClasses.get(className);
  99   }
 100 
 101   /**
 102    * Load a JavaClass object for the given class name using
 103    * the CLASSPATH environment variable.
 104    */
 105   public JavaClass loadClass(String className)
 106     throws ClassNotFoundException
 107   {
 108     if(className == null || className.equals("")) {
 109       throw new IllegalArgumentException("Invalid class name " + className);
 110     }
 111 
 112     className = className.replace('/', '.'); // Just in case, canonical form
 113 
 114     try {
 115       return loadClass(_path.getInputStream(className), className);
 116     } catch(IOException e) {
 117       throw new ClassNotFoundException("Exception while looking for class " +
 118                                        className + ": " + e.toString());
 119     }
 120   }
 121 
 122   /**
 123    * Try to find class source via getResourceAsStream().
 124    * @see Class
 125    * @return JavaClass object for given runtime class
 126    */
 127   public JavaClass loadClass(Class clazz) throws ClassNotFoundException {
 128     String className = clazz.getName();
 129     String name      = className;
 130     int    i         = name.lastIndexOf('.');
 131 
 132     if(i > 0) {
 133       name = name.substring(i + 1);
 134     }
 135 
 136     return loadClass(clazz.getResourceAsStream(name + ".class"), className);
 137   }
 138 
 139   private JavaClass loadClass(InputStream is, String className)
 140     throws ClassNotFoundException
 141   {
 142     JavaClass clazz = findClass(className);
 143 
 144     if(clazz != null) {
 145       return clazz;
 146     }
 147 
 148     try {
 149       if(is != null) {
 150         ClassParser parser = new ClassParser(is, className);
 151         clazz = parser.parse();
 152 
 153         storeClass(clazz);
 154 
 155         return clazz;
 156       }
 157     } catch(IOException e) {
 158       throw new ClassNotFoundException("Exception while looking for class " +
 159                                        className + ": " + e.toString());
 160     }
 161 
 162     throw new ClassNotFoundException("SyntheticRepository could not load " +
 163                                      className);
 164   }
 165 
 166   /** Clear all entries from cache.
 167    */
 168   public void clear() {
 169     _loadedClasses.clear();
 170   }
 171 }