001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.satsa.jcrmic.classfile;
028:
029: import com.sun.satsa.jcrmic.utils.Notifier;
030:
031: import java.util.*;
032: import java.io.*;
033: import java.util.zip.*;
034:
035: /**
036: * This class is a class loader.
037: */
038:
039: public class Loader {
040:
041: /**
042: * Class path.
043: */
044: private Vector classPath;
045:
046: /**
047: * Loaded classes.
048: */
049: private Hashtable classes;
050:
051: /**
052: * Errors/warnings notifier.
053: */
054: private Notifier notifier;
055:
056: /**
057: * Constructor.
058: * @param notifier errors/warnings notifier
059: */
060: public Loader(Notifier notifier) {
061:
062: classPath = new Vector();
063: classes = new Hashtable();
064: this .notifier = notifier;
065: }
066:
067: /**
068: * Set path for class loading.
069: * @param path path for class loading
070: * @return true if successfull
071: */
072: public boolean setClassPath(String path) {
073:
074: classPath.clear();
075:
076: StringTokenizer parser = new StringTokenizer(path,
077: File.pathSeparator);
078:
079: while (parser.hasMoreTokens()) {
080:
081: String s = parser.nextToken();
082:
083: File f = new File(s);
084:
085: try {
086: if (f.isDirectory()) {
087: // directory - add path to the vector
088: classPath.addElement(f.getCanonicalPath());
089: } else {
090: // file - check that it exists
091: if (!f.exists()) {
092: notifier.error("rmic.file.not.found", s);
093: return false;
094: }
095:
096: ZipFile z = new ZipFile(f);
097: classPath.addElement(z);
098: }
099: } catch (IOException e) {
100: notifier.error("rmic.incorrect.classpath", s);
101: return false;
102: }
103: }
104:
105: if (classPath.size() == 0) {
106: return false;
107: }
108:
109: return true;
110: }
111:
112: /**
113: * Loads the class.
114: * @param className the class name
115: * @return true if successfull
116: */
117: public boolean loadClass(String className) {
118:
119: className = className.replace('.', '/');
120:
121: // check to avoid duplicate loading
122:
123: if (classes.containsKey(className))
124: return true;
125:
126: InputStream is = null;
127:
128: for (int i = 0; i < classPath.size(); i++) {
129:
130: if (classPath.elementAt(i) instanceof String) {
131:
132: String path = (String) classPath.elementAt(i);
133:
134: path += File.separator
135: + className.replace('/', File.separatorChar)
136: + ".class";
137:
138: File f = new File(path);
139:
140: if (!f.exists())
141: continue;
142:
143: try {
144: is = new FileInputStream(f);
145: } catch (FileNotFoundException e) {
146: continue;
147: }
148:
149: } else {
150:
151: ZipFile z = (ZipFile) classPath.elementAt(i);
152: ZipEntry ze = z.getEntry(className + ".class");
153:
154: if (ze == null)
155: continue;
156:
157: try {
158: is = z.getInputStream(ze);
159: } catch (IOException e) {
160: notifier.error("rmic.ioerror", z.getName());
161: return false;
162: }
163: }
164:
165: if (is != null)
166: break;
167: }
168:
169: if (is == null) {
170: notifier.error("rmic.class.not.found", className);
171: return false;
172: }
173:
174: // class file is found, load it
175:
176: DataInputStream dis = new DataInputStream(
177: new BufferedInputStream(is));
178:
179: JClass cl = new JClass(this );
180:
181: try {
182: cl.parse(dis);
183: } catch (Exception e) {
184: notifier.error("rmic.parsing.error", className);
185: return false;
186: }
187:
188: // class is loaded
189:
190: classes.put(className, cl);
191:
192: // update the class, load all related classes
193:
194: if (!cl.update())
195: return false;
196:
197: return true;
198: }
199:
200: /**
201: * Returns class definition loaded earlier.
202: * @param className the class name
203: * @return class definition
204: */
205: public JClass getClass(String className) {
206:
207: return (JClass) classes.get(className.replace('.', '/'));
208: }
209: }
|