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 util;
028:
029: import components.*;
030:
031: import java.io.DataInputStream;
032: import java.io.IOException;
033: import java.io.File;
034: import java.io.InputStream;
035: import java.io.FileInputStream;
036: import java.io.BufferedInputStream;
037: import java.io.ByteArrayInputStream;
038: import java.io.ByteArrayOutputStream;
039: import java.util.Enumeration;
040: import java.util.Vector;
041: import java.util.zip.ZipInputStream;
042: import java.util.zip.ZipEntry;
043: import jcc.Const;
044:
045: /*
046: * ClassReader reads classes from a variety of sources
047: * and, in all cases, creates ClassInfo structures for them.
048: * It can read single class files, mclass files, entire zip
049: * files or a member of a zip file.
050: */
051: public class ClassReader {
052:
053: int verbosity;
054: ConstantPool t;
055:
056: public ClassReader(ConstantPool cp, int verb) {
057: t = cp;
058: verbosity = verb;
059: }
060:
061: private int getMagic(InputStream file) throws IOException {
062: DataInputStream data = new DataInputStream(file);
063: int n = 0;
064: file.mark(4);
065: try {
066: n = data.readInt();
067: } finally {
068: file.reset();
069: }
070: return n;
071: }
072:
073: /*
074: * To read the contents of a single, named class or mclass file.
075: * The two cases are distinguished by magic number.
076: * The return value is the number of classes read.
077: * ClassInfo classes for the newly read classes are added
078: * to the argument Vector.
079: */
080: public int readFile(String fileName, Vector done)
081: throws IOException {
082: InputStream infile;
083: infile = new BufferedInputStream(new FileInputStream(fileName));
084: return readStream(fileName, infile, done);
085:
086: }
087:
088: /*
089: * To read the contents of an entire named zip (or Jar) file.
090: * Each element that is a class or mclass file is read.
091: * Others are silently ignored.
092: * The return value is the number of classes read.
093: * ClassInfo classes for the newly read classes are added
094: * to the argument Vector.
095: */
096: public int readZip(String fileName, Vector done) throws IOException {
097: ZipEntry ent;
098: int i = 0;
099: ZipInputStream zip = new ZipInputStream(new FileInputStream(
100: fileName));
101: while ((ent = zip.getNextEntry()) != null) {
102: String name = ent.getName();
103: if (!ent.isDirectory()
104: && (name.endsWith(".class") || name
105: .endsWith(".mclass"))) {
106: try {
107: byte buffer[] = readZipEntry(zip);
108: i += readStream(name, new ByteArrayInputStream(
109: buffer), done);
110: } catch (IOException e) {
111: System.out.println(Localizer.getString(
112: "classreader.failed_on", name));
113: }
114: }
115: }
116: return i;
117: }
118:
119: byte[] readZipEntry(ZipInputStream zip) throws IOException {
120: ByteArrayOutputStream baos = new ByteArrayOutputStream();
121: byte[] buff = new byte[1024];
122: int len;
123:
124: while (true) {
125: len = zip.read(buff, 0, buff.length);
126: if (len == -1) {
127: break;
128: }
129: baos.write(buff, 0, len);
130: }
131:
132: return baos.toByteArray();
133: }
134:
135: /*
136: * To read the contents of a class or mclass file from
137: * a given input stream.
138: * The two cases are distinguished by magic number.
139: * The return value is the number of classes read.
140: * ClassInfo classes for the newly read classes are added
141: * to the argument Vector.
142: * The inputName argument is used only for error messages.
143: * This can be used for reading a zip file element or
144: * from single opened file.
145: */
146: public int readStream(String inputName, InputStream infile,
147: Vector done) throws IOException {
148: int magicNumber = getMagic(infile);
149:
150: int ndone = 0;
151: if (magicNumber == Const.JAVA_MAGIC) {
152: /*
153: * We have a solo class.
154: */
155: ClassFile f = new ClassFile(inputName, infile,
156: verbosity >= 2);
157: if (verbosity != 0)
158: System.out.println(Localizer.getString(
159: "classreader.reading_classfile", inputName));
160: if (f.readClassFile(t)) {
161: f.clas.externalize(t);
162: done.addElement(f.clas);
163: ndone += 1;
164: } else {
165: throw new DataFormatException(Localizer.getString(
166: "classreader.read_of_class_file", inputName));
167: }
168: } else {
169: throw new DataFormatException(Localizer.getString(
170: "classreader.file_has_bad_magic_number", inputName,
171: Integer.toString(magicNumber)));
172: }
173: try {
174: infile.close();
175: } catch (Throwable x) {
176: }
177: return ndone;
178: }
179:
180: /*
181: * To read a single, named class.
182: * The return value is the number of classes read.
183: * ClassInfo classes for the newly read class is added
184: * to the argument Vector.
185: * The class to be read is found using the ClassFileFinder,
186: * which, if successful, will give us an InputStream, either
187: * of a file from its search path, or of a zip file element
188: * from its search path.
189: */
190: public int readClass(String classname, ClassFileFinder finder,
191: Vector done) {
192: InputStream f = finder.findClassFile(classname);
193: if (f == null)
194: return 0;
195: try {
196: return readStream(classname, f, done);
197: } catch (IOException e) {
198: e.printStackTrace();
199: return 0;
200: }
201: }
202:
203: }
|