001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.tools;
019:
020: import java.io.File;
021: import java.io.FileInputStream;
022: import java.io.InputStream;
023: import java.util.Enumeration;
024: import java.util.HashMap;
025: import java.util.Map;
026:
027: import org.apache.bcel.classfile.ClassParser;
028: import org.apache.bcel.classfile.JavaClass;
029: import org.apache.bcel.util.ClassPath;
030:
031: /**
032: * This class locates a class in the given class path with the given name. You
033: * can use this class to get a JavaClass object which represents the found
034: * class.
035: *
036: * This class depends on Apache Byte Code Engineering Library (BCEL) 5.0 or
037: * later. Please see http://jakarta.apache.org/bcel for more information
038: * about this library.
039: */
040: public class ClassProvider {
041:
042: /**
043: * Loading class files from a class path.
044: */
045: private ClassPath classpath;
046:
047: /**
048: * Verbose output or not.
049: */
050: private boolean verbose;
051:
052: /**
053: * Keeps loaded and parsed class files.
054: */
055: private Map cache;
056:
057: /**
058: * Constructs a <code>ClassProvider</code> object.
059: *
060: * @param bootClasspath - a path that will be prepended to the default
061: * class path.
062: * @param classpath - a path that will be apppended to the default class
063: * path.
064: * @param verbose - a verbose output.
065: */
066: public ClassProvider(String bootClasspath, String classpath,
067: boolean verbose) {
068: StringBuffer pathString = new StringBuffer();
069:
070: // Append the given boot class path, if any.
071: if (bootClasspath != null) {
072: pathString.append(bootClasspath).append(
073: File.pathSeparatorChar);
074: }
075:
076: // Append the default class path.
077: pathString.append(getSystemClassPath()).append(
078: File.pathSeparatorChar);
079:
080: // Append the given class path, if any.
081: if (classpath != null) {
082: pathString.append(classpath).append(File.pathSeparatorChar);
083: }
084:
085: if (verbose) {
086: System.out.println("class.path: " + pathString.toString());
087: }
088:
089: this .classpath = new ClassPath(pathString.toString());
090: this .verbose = verbose;
091: this .cache = new HashMap();
092: }
093:
094: /**
095: * Returns the system class path.
096: *
097: * @return the system class path.
098: */
099: private String getSystemClassPath() {
100: String sep = System.getProperty("path.separator");
101: StringBuffer cp = new StringBuffer();
102: for (Enumeration e = System.getProperties().propertyNames(); e
103: .hasMoreElements();) {
104: // Enumerate all the system properties.
105: String prop = (String) e.nextElement();
106: if (prop.endsWith("class.path")) {
107: // Add the value of a property to the class path, if its
108: // name ends with "class.path".
109: cp.append(System.getProperty(prop)).append(sep);
110: }
111: }
112: return cp.toString();
113: }
114:
115: /**
116: * Returns a JavaClass object which represents a class file with the given
117: * name.
118: *
119: * @param name - a fully qualified name of a class.
120: * @return a JavaClass object which represents a class file with the given
121: * name.
122: * @throws ClassNotFoundException if a class file with the given name is
123: * not found.
124: */
125: public synchronized JavaClass getJavaClass(String name)
126: throws ClassNotFoundException {
127: try {
128: // Try to get the class from the cache.
129: JavaClass result = (JavaClass) cache.get(name);
130: // If cache doesn't contain such a class load it from a class path.
131: if (result == null) {
132: // Get a file and parse its contents.
133: ClassPath.ClassFile cf = classpath.getClassFile(name);
134: InputStream is = cf.getInputStream();
135: ClassParser parser = new ClassParser(is, cf.getPath());
136: result = parser.parse();
137: // Put the parsed class file into the cache.
138: cache.put(name, result);
139:
140: if (verbose) {
141: StringBuffer s = new StringBuffer();
142: // If we use BCEL 5.1 or later one day we definitely
143: // should remove the following if and replace
144: // cf.getPath() with cf.getBase()!
145: if (!(is instanceof FileInputStream)) {
146: s.append("class.path:");
147: }
148: s.append(cf.getPath());
149: System.out.println(name + " loaded from " + s);
150: }
151: } else {
152: if (verbose) {
153: System.out
154: .println(name + " retrieved from a cache");
155: }
156: }
157: return result;
158: } catch (Exception e) {
159: throw new ClassNotFoundException(name, e);
160: }
161: }
162: }
|