001: /*
002: * ProGuard -- shrinking, optimization, obfuscation, and preverification
003: * of Java bytecode.
004: *
005: * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu)
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the Free
009: * Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful, but WITHOUT
013: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
015: * more details.
016: *
017: * You should have received a copy of the GNU General Public License along
018: * with this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: */
021: package proguard.io;
022:
023: import proguard.classfile.*;
024: import proguard.classfile.io.*;
025: import proguard.classfile.util.*;
026: import proguard.classfile.visitor.ClassVisitor;
027:
028: import java.io.*;
029:
030: /**
031: * This DataEntryReader applies a given ClassVisitor to the class
032: * definitions that it reads.
033: * <p>
034: * Class files are read as ProgramClass objects or LibraryClass objects,
035: * depending on the <code>isLibrary</code> flag.
036: * <p>
037: * In case of libraries, only public classes are considered, if the
038: * <code>skipNonPublicLibraryClasses</code> flag is set.
039: *
040: * @author Eric Lafortune
041: */
042: public class ClassReader implements DataEntryReader {
043: private final boolean isLibrary;
044: private final boolean skipNonPublicLibraryClasses;
045: private final boolean skipNonPublicLibraryClassMembers;
046: private final WarningPrinter warningPrinter;
047: private final ClassVisitor classVisitor;
048:
049: /**
050: * Creates a new DataEntryClassFilter for reading the specified
051: * Clazz objects.
052: */
053: public ClassReader(boolean isLibrary,
054: boolean skipNonPublicLibraryClasses,
055: boolean skipNonPublicLibraryClassMembers,
056: WarningPrinter warningPrinter, ClassVisitor classVisitor) {
057: this .isLibrary = isLibrary;
058: this .skipNonPublicLibraryClasses = skipNonPublicLibraryClasses;
059: this .skipNonPublicLibraryClassMembers = skipNonPublicLibraryClassMembers;
060: this .warningPrinter = warningPrinter;
061: this .classVisitor = classVisitor;
062: }
063:
064: // Implementations for DataEntryReader.
065:
066: public void read(DataEntry dataEntry) throws IOException {
067: try {
068: // Get the input stream.
069: InputStream inputStream = dataEntry.getInputStream();
070:
071: // Wrap it into a data input stream.
072: DataInputStream dataInputStream = new DataInputStream(
073: inputStream);
074:
075: // Create a Clazz representation.
076: Clazz clazz;
077: if (isLibrary) {
078: clazz = new LibraryClass();
079: clazz.accept(new LibraryClassReader(dataInputStream,
080: skipNonPublicLibraryClasses,
081: skipNonPublicLibraryClassMembers));
082: } else {
083: clazz = new ProgramClass();
084: clazz.accept(new ProgramClassReader(dataInputStream));
085: }
086:
087: // Apply the visitor, if we have a real class.
088: String className = clazz.getName();
089: if (className != null) {
090: if (!dataEntry
091: .getName()
092: .replace(
093: File.pathSeparatorChar,
094: ClassConstants.INTERNAL_PACKAGE_SEPARATOR)
095: .equals(
096: className
097: + ClassConstants.CLASS_FILE_EXTENSION)
098: && warningPrinter != null) {
099: warningPrinter.print("Warning: class ["
100: + dataEntry.getName()
101: + "] unexpectedly contains class ["
102: + ClassUtil.externalClassName(className)
103: + "]");
104: }
105:
106: clazz.accept(classVisitor);
107: }
108:
109: dataEntry.closeInputStream();
110: } catch (Exception ex) {
111: throw new IOException("Can't process class ["
112: + dataEntry.getName() + "] (" + ex.getMessage()
113: + ")");
114: }
115: }
116: }
|