1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21package proguard; 22 23import proguard.classfile.ClassPool; 24import proguard.classfile.util.WarningPrinter; 25import proguard.classfile.visitor.*; 26import proguard.io.*; 27 28import java.io.IOException; 29 30/** 31 * This class reads the input class files. 32 * 33 * @author Eric Lafortune 34 */ 35public class InputReader 36{ 37 private final Configuration configuration; 38 39 40 /** 41 * Creates a new InputReader to read input class files as specified by the 42 * given configuration. 43 */ 44 public InputReader(Configuration configuration) 45 { 46 this.configuration = configuration; 47 } 48 49 50 /** 51 * Fills the given program class pool and library class pool by reading 52 * class files, based on the current configuration. 53 */ 54 public void execute(ClassPool programClassPool, 55 ClassPool libraryClassPool) throws IOException 56 { 57 WarningPrinter warningPrinter = new WarningPrinter(System.err, configuration.warn); 58 WarningPrinter notePrinter = new WarningPrinter(System.out, configuration.note); 59 60 DuplicateClassPrinter duplicateClassPrinter = new DuplicateClassPrinter(notePrinter); 61 62 // Read the program class files. 63 // Prepare a data entry reader to filter all classes, 64 // which are then decoded to classes by a class reader, 65 // which are then put in the class pool by a class pool filler. 66 readInput("Reading program ", 67 configuration.programJars, 68 new ClassFilter( 69 new ClassReader(false, 70 configuration.skipNonPublicLibraryClasses, 71 configuration.skipNonPublicLibraryClassMembers, 72 warningPrinter, 73 new ClassPresenceFilter(programClassPool, duplicateClassPrinter, 74 new ClassPoolFiller(programClassPool))))); 75 76 // Check if we have at least some input classes. 77 if (programClassPool.size() == 0) 78 { 79 throw new IOException("The input doesn't contain any classes. Did you specify the proper '-injars' options?"); 80 } 81 82 // Read the library class files, if any. 83 if (configuration.libraryJars != null) 84 { 85 // Prepare a data entry reader to filter all classes, 86 // which are then decoded to classes by a class reader, 87 // which are then put in the class pool by a class pool filler. 88 readInput("Reading library ", 89 configuration.libraryJars, 90 new ClassFilter( 91 new ClassReader(true, 92 configuration.skipNonPublicLibraryClasses, 93 configuration.skipNonPublicLibraryClassMembers, 94 warningPrinter, 95 new ClassPresenceFilter(programClassPool, duplicateClassPrinter, 96 new ClassPresenceFilter(libraryClassPool, duplicateClassPrinter, 97 new ClassPoolFiller(libraryClassPool)))))); 98 } 99 100 // Print out a summary of the notes, if necessary. 101 int noteCount = notePrinter.getWarningCount(); 102 if (noteCount > 0) 103 { 104 System.err.println("Note: there were " + noteCount + 105 " duplicate class definitions."); 106 System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#duplicateclass)"); 107 } 108 109 // Print out a summary of the warnings, if necessary. 110 int warningCount = warningPrinter.getWarningCount(); 111 if (warningCount > 0) 112 { 113 System.err.println("Warning: there were " + warningCount + 114 " classes in incorrectly named files."); 115 System.err.println(" You should make sure all file names correspond to their class names."); 116 System.err.println(" The directory hierarchies must correspond to the package hierarchies."); 117 System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#unexpectedclass)"); 118 119 if (!configuration.ignoreWarnings) 120 { 121 System.err.println(" If you don't mind the mentioned classes not being written out,"); 122 System.err.println(" you could try your luck using the '-ignorewarnings' option."); 123 throw new IOException("Please correct the above warnings first."); 124 } 125 } 126 } 127 128 129 /** 130 * Reads all input entries from the given class path. 131 */ 132 private void readInput(String messagePrefix, 133 ClassPath classPath, 134 DataEntryReader reader) throws IOException 135 { 136 readInput(messagePrefix, 137 classPath, 138 0, 139 classPath.size(), 140 reader); 141 } 142 143 144 /** 145 * Reads all input entries from the given section of the given class path. 146 */ 147 public void readInput(String messagePrefix, 148 ClassPath classPath, 149 int fromIndex, 150 int toIndex, 151 DataEntryReader reader) throws IOException 152 { 153 for (int index = fromIndex; index < toIndex; index++) 154 { 155 ClassPathEntry entry = classPath.get(index); 156 if (!entry.isOutput()) 157 { 158 readInput(messagePrefix, entry, reader); 159 } 160 } 161 } 162 163 164 /** 165 * Reads the given input class path entry. 166 */ 167 private void readInput(String messagePrefix, 168 ClassPathEntry classPathEntry, 169 DataEntryReader dataEntryReader) throws IOException 170 { 171 try 172 { 173 // Create a reader that can unwrap jars, wars, ears, and zips. 174 DataEntryReader reader = 175 DataEntryReaderFactory.createDataEntryReader(messagePrefix, 176 classPathEntry, 177 dataEntryReader); 178 179 // Create the data entry pump. 180 DirectoryPump directoryPump = 181 new DirectoryPump(classPathEntry.getFile()); 182 183 // Pump the data entries into the reader. 184 directoryPump.pumpDataEntries(reader); 185 } 186 catch (IOException ex) 187 { 188 throw (IOException)new IOException("Can't read [" + classPathEntry + "] (" + ex.getMessage() + ")").initCause(ex); 189 } 190 } 191} 192