summaryrefslogtreecommitdiffstats
path: root/src/proguard/InputReader.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/proguard/InputReader.java')
-rw-r--r--src/proguard/InputReader.java233
1 files changed, 233 insertions, 0 deletions
diff --git a/src/proguard/InputReader.java b/src/proguard/InputReader.java
new file mode 100644
index 0000000..c088324
--- /dev/null
+++ b/src/proguard/InputReader.java
@@ -0,0 +1,233 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.ClassPool;
+import proguard.classfile.util.WarningPrinter;
+import proguard.classfile.visitor.*;
+import proguard.io.*;
+
+import java.io.IOException;
+
+/**
+ * This class reads the input class files.
+ *
+ * @author Eric Lafortune
+ */
+public class InputReader
+{
+ private final Configuration configuration;
+
+
+ /**
+ * Creates a new InputReader to read input class files as specified by the
+ * given configuration.
+ */
+ public InputReader(Configuration configuration)
+ {
+ this.configuration = configuration;
+ }
+
+
+ /**
+ * Fills the given program class pool and library class pool by reading
+ * class files, based on the current configuration.
+ */
+ public void execute(ClassPool programClassPool,
+ ClassPool libraryClassPool) throws IOException
+ {
+ // Check if we have at least some input classes.
+ if (configuration.programJars == null)
+ {
+ throw new IOException("The input is empty. You have to specify one or more '-injars' options");
+ }
+
+ // Perform some sanity checks on the class paths.
+ checkInputOutput(configuration.libraryJars,
+ configuration.programJars);
+ checkInputOutput(configuration.programJars,
+ configuration.programJars);
+
+ WarningPrinter warningPrinter = new WarningPrinter(System.err, configuration.warn);
+ WarningPrinter notePrinter = new WarningPrinter(System.out, configuration.note);
+
+ DuplicateClassPrinter duplicateClassPrinter = new DuplicateClassPrinter(notePrinter);
+
+ // Read the program class files.
+ // Prepare a data entry reader to filter all classes,
+ // which are then decoded to classes by a class reader,
+ // which are then put in the class pool by a class pool filler.
+ readInput("Reading program ",
+ configuration.programJars,
+ new ClassFilter(
+ new ClassReader(false,
+ configuration.skipNonPublicLibraryClasses,
+ configuration.skipNonPublicLibraryClassMembers,
+ warningPrinter,
+ new ClassPresenceFilter(programClassPool, duplicateClassPrinter,
+ new ClassPoolFiller(programClassPool)))));
+
+ // Check if we have at least some input classes.
+ if (programClassPool.size() == 0)
+ {
+ throw new IOException("The input doesn't contain any classes. Did you specify the proper '-injars' options?");
+ }
+
+ // Read the library class files, if any.
+ if (configuration.libraryJars != null)
+ {
+ // Prepare a data entry reader to filter all classes,
+ // which are then decoded to classes by a class reader,
+ // which are then put in the class pool by a class pool filler.
+ readInput("Reading library ",
+ configuration.libraryJars,
+ new ClassFilter(
+ new ClassReader(true,
+ configuration.skipNonPublicLibraryClasses,
+ configuration.skipNonPublicLibraryClassMembers,
+ warningPrinter,
+ new ClassPresenceFilter(programClassPool, duplicateClassPrinter,
+ new ClassPresenceFilter(libraryClassPool, duplicateClassPrinter,
+ new ClassPoolFiller(libraryClassPool))))));
+ }
+
+ // Print out a summary of the notes, if necessary.
+ int noteCount = notePrinter.getWarningCount();
+ if (noteCount > 0)
+ {
+ System.err.println("Note: there were " + noteCount +
+ " duplicate class definitions.");
+ }
+
+ // Print out a summary of the warnings, if necessary.
+ int warningCount = warningPrinter.getWarningCount();
+ if (warningCount > 0)
+ {
+ System.err.println("Warning: there were " + warningCount +
+ " classes in incorrectly named files.");
+ System.err.println(" You should make sure all file names correspond to their class names.");
+ System.err.println(" The directory hierarchies must correspond to the package hierarchies.");
+
+ if (!configuration.ignoreWarnings)
+ {
+ System.err.println(" If you don't mind the mentioned classes not being written out,");
+ System.err.println(" you could try your luck using the '-ignorewarnings' option.");
+ throw new IOException("Please correct the above warnings first.");
+ }
+ }
+ }
+
+
+ /**
+ * Performs some sanity checks on the class paths.
+ */
+ private void checkInputOutput(ClassPath inputClassPath,
+ ClassPath outputClassPath)
+ throws IOException
+ {
+ if (inputClassPath == null ||
+ outputClassPath == null)
+ {
+ return;
+ }
+
+ for (int index1 = 0; index1 < inputClassPath.size(); index1++)
+ {
+ ClassPathEntry entry1 = inputClassPath.get(index1);
+ if (!entry1.isOutput())
+ {
+ for (int index2 = 0; index2 < outputClassPath.size(); index2++)
+ {
+ ClassPathEntry entry2 = outputClassPath.get(index2);
+ if (entry2.isOutput() &&
+ entry2.getName().equals(entry1.getName()))
+ {
+ throw new IOException("Input jars and output jars must be different ["+entry1.getName()+"]");
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Reads all input entries from the given class path.
+ */
+ private void readInput(String messagePrefix,
+ ClassPath classPath,
+ DataEntryReader reader) throws IOException
+ {
+ readInput(messagePrefix,
+ classPath,
+ 0,
+ classPath.size(),
+ reader);
+ }
+
+
+ /**
+ * Reads all input entries from the given section of the given class path.
+ */
+ public void readInput(String messagePrefix,
+ ClassPath classPath,
+ int fromIndex,
+ int toIndex,
+ DataEntryReader reader) throws IOException
+ {
+ for (int index = fromIndex; index < toIndex; index++)
+ {
+ ClassPathEntry entry = classPath.get(index);
+ if (!entry.isOutput())
+ {
+ readInput(messagePrefix, entry, reader);
+ }
+ }
+ }
+
+
+ /**
+ * Reads the given input class path entry.
+ */
+ private void readInput(String messagePrefix,
+ ClassPathEntry classPathEntry,
+ DataEntryReader dataEntryReader) throws IOException
+ {
+ try
+ {
+ // Create a reader that can unwrap jars, wars, ears, and zips.
+ DataEntryReader reader =
+ DataEntryReaderFactory.createDataEntryReader(messagePrefix,
+ classPathEntry,
+ dataEntryReader);
+
+ // Create the data entry pump.
+ DirectoryPump directoryPump =
+ new DirectoryPump(classPathEntry.getFile());
+
+ // Pump the data entries into the reader.
+ directoryPump.pumpDataEntries(reader);
+ }
+ catch (IOException ex)
+ {
+ throw new IOException("Can't read [" + classPathEntry + "] (" + ex.getMessage() + ")");
+ }
+ }
+}