OSDN Git Service

SDK: make 'mkstub' less verbose.
authorRaphael <raphael@google.com>
Fri, 4 Feb 2011 06:56:14 +0000 (22:56 -0800)
committerRaphael <raphael@google.com>
Fri, 4 Feb 2011 06:56:14 +0000 (22:56 -0800)
mkstub is the tool used to stub the google_apis maps.jar.
Since we're integrating it in the build, we want to control its verbosity.

Change-Id: Ic0cfacb79a0aa260bcafb54bdc6bdb5a98b1c87a

tools/mkstubs/src/com/android/mkstubs/AsmAnalyzer.java
tools/mkstubs/src/com/android/mkstubs/FilterClassAdapter.java
tools/mkstubs/src/com/android/mkstubs/Main.java
tools/mkstubs/src/com/android/mkstubs/SourceGenerator.java
tools/mkstubs/src/com/android/mkstubs/StubGenerator.java
tools/mkstubs/tests/com/android/mkstubs/SourceGeneratorTest.java

index 5e64ae6..0b73dc5 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.android.mkstubs;
 
+import com.android.mkstubs.Main.Logger;
+
 import org.objectweb.asm.ClassReader;
 
 import java.io.IOException;
@@ -53,7 +55,7 @@ class AsmAnalyzer {
                 classes.put(className, cr);
             }
         }
-        
+
         return classes;
     }
 
@@ -72,25 +74,26 @@ class AsmAnalyzer {
     /**
      * Filters the set of classes. Removes all classes that should not be included in the
      * filter or that should be excluded. This modifies the map in-place.
-     * 
+     *
      * @param classes The in-out map of classes to examine and filter. The map is filtered
      *                in-place.
      * @param filter  A filter describing which classes to include and which ones to exclude.
+     * @param log
      */
-    void filter(Map<String, ClassReader> classes, Filter filter) {
+    void filter(Map<String, ClassReader> classes, Filter filter, Logger log) {
 
         Set<String> keys = classes.keySet();
         for(Iterator<String> it = keys.iterator(); it.hasNext(); ) {
             String key = it.next();
 
             // TODO: We *could* filter out all private classes here: classes.get(key).getAccess().
-            
+
             // remove if we don't keep it
             if (!filter.accept(key)) {
-                System.out.println("- Remove class " + key);
+                log.debug("- Remove class " + key);
                 it.remove();
             }
         }
     }
-    
+
 }
index 3874e6b..6f570c7 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.android.mkstubs;
 
+import com.android.mkstubs.Main.Logger;
+
 import org.objectweb.asm.AnnotationVisitor;
 import org.objectweb.asm.Attribute;
 import org.objectweb.asm.ClassAdapter;
@@ -30,12 +32,14 @@ import org.objectweb.asm.Opcodes;
  */
 class FilterClassAdapter extends ClassAdapter {
 
+    private final Logger mLog;
     private final Filter mFilter;
     private String mClassName;
 
-    public FilterClassAdapter(ClassVisitor writer, Filter filter) {
+    public FilterClassAdapter(ClassVisitor writer, Filter filter, Logger log) {
         super(writer);
         mFilter = filter;
+        mLog = log;
     }
 
     @Override
@@ -73,7 +77,7 @@ class FilterClassAdapter extends ClassAdapter {
         String filterName = String.format("%s#%s", mClassName, name);
 
         if (!mFilter.accept(filterName)) {
-            System.out.println("- Remove field " + filterName);
+            mLog.debug("- Remove field " + filterName);
             return null;
         }
 
@@ -105,7 +109,7 @@ class FilterClassAdapter extends ClassAdapter {
         String filterName = String.format("%s#%s%s", mClassName, name, desc);
 
         if (!mFilter.accept(filterName)) {
-            System.out.println("- Remove method " + filterName);
+            mLog.debug("- Remove method " + filterName);
             return null;
         }
 
@@ -114,7 +118,7 @@ class FilterClassAdapter extends ClassAdapter {
             filterName = String.format("%s#%s%s", mClassName, name, signature);
 
             if (!mFilter.accept(filterName)) {
-                System.out.println("- Remove method " + filterName);
+                mLog.debug("- Remove method " + filterName);
                 return null;
             }
         }
index 55f9499..927ff9e 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.android.mkstubs;
 
+import com.android.mkstubs.Main.Params;
+
 import org.objectweb.asm.ClassReader;
 
 import java.io.BufferedReader;
@@ -31,7 +33,7 @@ import java.util.Map;
  * For workflow details, see {@link #process(Params)}.
  */
 public class Main {
-    
+
     /**
      * A struct-like class to hold the various input values (e.g. command-line args)
      */
@@ -39,11 +41,21 @@ public class Main {
         private String mInputJarPath;
         private String mOutputJarPath;
         private Filter mFilter;
-        
-        public Params(String inputJarPath, String outputJarPath) {
+        private boolean mVerbose;
+        private boolean mDumpSource;
+
+        public Params() {
+            mFilter = new Filter();
+        }
+
+        /** Sets the name of the input jar, where to read classes from. Must not be null. */
+        public void setInputJarPath(String inputJarPath) {
             mInputJarPath = inputJarPath;
+        }
+
+        /** Sets the name of the output jar, where to write classes to. Must not be null. */
+        public void setOutputJarPath(String outputJarPath) {
             mOutputJarPath = outputJarPath;
-            mFilter = new Filter();
         }
 
         /** Returns the name of the input jar, where to read classes from. */
@@ -60,13 +72,53 @@ public class Main {
         public Filter getFilter() {
             return mFilter;
         }
+
+        /** Sets verbose mode on. Default is off. */
+        public void setVerbose() {
+            mVerbose = true;
+        }
+
+        /** Returns true if verbose mode is on. */
+        public boolean isVerbose() {
+            return mVerbose;
+        }
+
+        /** Sets dump source mode on. Default is off. */
+        public void setDumpSource() {
+            mDumpSource = true;
+        }
+
+        /** Returns true if source should be dumped. */
+        public boolean isDumpSource() {
+            return mDumpSource;
+        }
+    }
+
+    /** Logger that writes on stdout depending a conditional verbose mode. */
+    static class Logger {
+        private final boolean mVerbose;
+
+        public Logger(boolean verbose) {
+            mVerbose = verbose;
+        }
+
+        /** Writes to stdout only in verbose mode. */
+        public void debug(String msg, Object...params) {
+            if (mVerbose) {
+                System.out.println(String.format(msg, params));
+            }
+        }
+
+        /** Writes to stdout all the time. */
+        public void info(String msg, Object...params) {
+            System.out.println(String.format(msg, params));
+        }
     }
-    
+
     /**
      * Main entry point. Processes arguments then performs the "real" work.
      */
     public static void main(String[] args) {
-
         Main m = new Main();
         try {
             Params p = m.processArgs(args);
@@ -88,17 +140,32 @@ public class Main {
      * @throws IOException on failure to read a pattern file.
      */
     private Params processArgs(String[] args) throws IOException {
-        
-        if (args.length < 2) {
-            usage();
+        Params p = new Params();
+
+        for (String arg : args) {
+            if (arg.startsWith("--")) {
+                if (arg.startsWith("--v")) {
+                    p.setVerbose();
+                } else if (arg.startsWith("--s")) {
+                    p.setDumpSource();
+                } else if (arg.startsWith("--h")) {
+                    usage(null);
+                } else {
+                    usage("Unknown argument: " + arg);
+                }
+            } else if (p.getInputJarPath() == null) {
+                p.setInputJarPath(arg);
+            } else if (p.getOutputJarPath() == null) {
+                p.setOutputJarPath(arg);
+            } else {
+                addString(p, arg);
+            }
         }
 
-        Params p = new Params(args[0], args[1]);
-        
-        for (int i = 2; i < args.length; i++) {
-            addString(p, args[i]);
+        if (p.getInputJarPath() == null && p.getOutputJarPath() == null) {
+            usage("Missing input or output JAR.");
         }
-        
+
         return p;
     }
 
@@ -112,7 +179,7 @@ public class Main {
      * </ul>
      * The input string is trimmed so any space around the first letter (-/+/@) or
      * at the end is removed. Empty strings are ignored.
-     * 
+     *
      * @param p The params which filters to edit.
      * @param s The string to examine.
      * @throws IOException
@@ -127,13 +194,13 @@ public class Main {
         if (s.length() < 2) {
             return;
         }
-        
+
         char mode = s.charAt(0);
         s = s.substring(1).trim();
 
         if (mode == '@') {
             addStringsFromFile(p, s);
-            
+
         } else if (mode == '-') {
             s = s.replace('.', '/');  // transform FQCN into ASM internal name
             if (s.endsWith("*")) {
@@ -154,11 +221,11 @@ public class Main {
 
     /**
      * Adds all the filter strings from the given file.
-     * 
+     *
      * @param p The params which filter to edit.
      * @param osFilePath The OS path to the file containing the patterns.
      * @throws IOException
-     * 
+     *
      * @see #addString(Params, String)
      */
     private void addStringsFromFile(Params p, String osFilePath)
@@ -179,9 +246,19 @@ public class Main {
 
     /**
      * Prints some help to stdout.
+     * @param error The error that generated the usage, if any. Can be null.
      */
-    private void usage() {
-        System.out.println("Usage: mkstub input.jar output.jar [excluded-class @excluded-classes-file ...]");
+    private void usage(String error) {
+        if (error != null) {
+            System.out.println("ERROR: " + error);
+        }
+
+        System.out.println("Usage: mkstub [--h|--s|--v] input.jar output.jar [excluded-class @excluded-classes-file ...]");
+
+        System.out.println("Options:\n" +
+                " --h | --help    : print this usage.\n" +
+                " --v | --verbose : verbose mode.\n" +
+                " --s | --source  : dump source equivalent to modified byte code.\n\n");
 
         System.out.println("Include syntax:\n" +
                 "+com.package.* : whole package, with glob\n" +
@@ -193,6 +270,7 @@ public class Main {
                        "-com.package.Class[$Inner] or ...Class*: whole classes with optional glob\n" +
                        "-com.package.Class#method: whole method or field\n" +
                 "-com.package.Class#method(IILjava/lang/String;)V: specific method with signature.\n\n");
+
         System.exit(1);
     }
 
@@ -211,20 +289,22 @@ public class Main {
         AsmAnalyzer aa = new AsmAnalyzer();
         Map<String, ClassReader> classes = aa.parseInputJar(p.getInputJarPath());
 
-        System.out.println(String.format("Classes loaded: %d", classes.size()));
-        
-        aa.filter(classes, p.getFilter());
+        Logger log = new Logger(p.isVerbose());
+        log.info("Classes loaded: %d", classes.size());
 
-        System.out.println(String.format("Classes filtered: %d", classes.size()));
+        aa.filter(classes, p.getFilter(), log);
+        log.info("Classes filtered: %d", classes.size());
 
         // dump as Java source files, mostly for debugging
-        SourceGenerator src_gen = new SourceGenerator();
-        File dst_src_dir = new File(p.getOutputJarPath() + "_sources");
-        dst_src_dir.mkdir();
-        src_gen.generateSource(dst_src_dir, classes, p.getFilter());
-        
+        if (p.isDumpSource()) {
+            SourceGenerator src_gen = new SourceGenerator(log);
+            File dst_src_dir = new File(p.getOutputJarPath() + "_sources");
+            dst_src_dir.mkdir();
+            src_gen.generateSource(dst_src_dir, classes, p.getFilter());
+        }
+
         // dump the stubbed jar
-        StubGenerator stub_gen = new StubGenerator();
+        StubGenerator stub_gen = new StubGenerator(log);
         File dst_jar = new File(p.getOutputJarPath());
         stub_gen.generateStubbedJar(dst_jar, classes, p.getFilter());
     }
index f5a339d..3f7c438 100644 (file)
@@ -16,6 +16,7 @@
 
 package com.android.mkstubs;
 
+import com.android.mkstubs.Main.Logger;
 import com.android.mkstubs.sourcer.ClassSourcer;
 import com.android.mkstubs.sourcer.Output;
 
@@ -38,17 +39,23 @@ import java.util.Map.Entry;
  */
 class SourceGenerator {
 
+    private Logger mLog;
+
+    public SourceGenerator(Logger log) {
+        mLog = log;
+    }
+
     /**
      * Generate source for the stubbed classes, mostly for debug purposes.
-     * @throws IOException 
+     * @throws IOException
      */
     public void generateSource(File baseDir,
             Map<String, ClassReader> classes,
             Filter filter) throws IOException {
-        
+
         for (Entry<String, ClassReader> entry : classes.entrySet()) {
             ClassReader cr = entry.getValue();
-            
+
             String name = classNameToJavaPath(cr.getClassName());
 
             FileWriter fw = null;
@@ -64,9 +71,9 @@ class SourceGenerator {
     FileWriter createWriter(File baseDir, String name) throws IOException {
         File f = new File(baseDir, name);
         f.getParentFile().mkdirs();
-        
-        System.out.println("Writing " + f.getPath());
-        
+
+        mLog.debug("Writing " + f.getPath());
+
         return new FileWriter(f);
     }
 
@@ -83,10 +90,10 @@ class SourceGenerator {
      * minus all exclusions
      */
     void visitClassSource(Writer fw, ClassReader cr, Filter filter) {
-        System.out.println("Dump " + cr.getClassName());
-        
+        mLog.debug("Dump " + cr.getClassName());
+
         ClassVisitor javaWriter = new ClassSourcer(new Output(fw));
-        ClassVisitor classFilter = new FilterClassAdapter(javaWriter, filter);
+        ClassVisitor classFilter = new FilterClassAdapter(javaWriter, filter, mLog);
         cr.accept(classFilter, 0 /*flags*/);
     }
 
index 6126e17..47195fa 100644 (file)
@@ -16,6 +16,7 @@
 
 package com.android.mkstubs;
 
+import com.android.mkstubs.Main.Logger;
 import com.android.mkstubs.stubber.ClassStubber;
 
 import org.objectweb.asm.ClassReader;
@@ -26,8 +27,8 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.Map;
-import java.util.TreeMap;
 import java.util.Map.Entry;
+import java.util.TreeMap;
 import java.util.jar.JarEntry;
 import java.util.jar.JarOutputStream;
 
@@ -40,9 +41,15 @@ import java.util.jar.JarOutputStream;
  */
 class StubGenerator {
 
+    private Logger mLog;
+
+    public StubGenerator(Logger log) {
+        mLog = log;
+    }
+
     /**
      * Generate source for the stubbed classes, mostly for debug purposes.
-     * @throws IOException 
+     * @throws IOException
      */
     public void generateStubbedJar(File destJar,
             Map<String, ClassReader> classes,
@@ -52,7 +59,7 @@ class StubGenerator {
 
         for (Entry<String, ClassReader> entry : classes.entrySet()) {
             ClassReader cr = entry.getValue();
-            
+
             byte[] b = visitClassStubber(cr, filter);
             String name = classNameToEntryPath(cr.getClassName());
             all.put(name, b);
@@ -60,7 +67,7 @@ class StubGenerator {
 
         createJar(new FileOutputStream(destJar), all);
 
-        System.out.println(String.format("Wrote %s", destJar.getPath()));
+        mLog.debug("Wrote %s", destJar.getPath());
     }
 
     /**
@@ -73,8 +80,8 @@ class StubGenerator {
 
     /**
      * Writes the JAR file.
-     * 
-     * @param outStream The file output stream were to write the JAR. 
+     *
+     * @param outStream The file output stream were to write the JAR.
      * @param all The map of all classes to output.
      * @throws IOException if an I/O error has occurred
      */
@@ -90,16 +97,16 @@ class StubGenerator {
         jar.flush();
         jar.close();
     }
-    
+
     byte[] visitClassStubber(ClassReader cr, Filter filter) {
-        System.out.println("Stub " + cr.getClassName());
+        mLog.debug("Stub " + cr.getClassName());
 
         // Rewrite the new class from scratch, without reusing the constant pool from the
         // original class reader.
         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
 
         ClassVisitor stubWriter = new ClassStubber(cw);
-        ClassVisitor classFilter = new FilterClassAdapter(stubWriter, filter);
+        ClassVisitor classFilter = new FilterClassAdapter(stubWriter, filter, mLog);
         cr.accept(classFilter, 0 /*flags*/);
         return cw.toByteArray();
     }
index 5b1f3a9..2a71f4f 100644 (file)
@@ -17,6 +17,8 @@
 package com.android.mkstubs;
 
 
+import com.android.mkstubs.Main.Logger;
+
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -26,7 +28,7 @@ import org.objectweb.asm.ClassReader;
 import java.io.StringWriter;
 
 /**
- * 
+ *
  */
 public class SourceGeneratorTest {
 
@@ -34,21 +36,21 @@ public class SourceGeneratorTest {
 
     @Before
     public void setUp() throws Exception {
-        mGen = new SourceGenerator();
+        mGen = new SourceGenerator(new Logger(false));
     }
 
     @After
     public void tearDown() throws Exception {
     }
 
-    
+
     @Test
     public void testDumpClass() throws Exception {
         StringWriter sw = new StringWriter();
         ClassReader cr = new ClassReader("data/TestBaseClass");
-        
+
         mGen.visitClassSource(sw, cr, new Filter());
-        
+
         String s = sw.toString();
         Assert.assertNotNull(s);
     }