AI 147194: am: CL 147193 am: CL 147190 Javadoc for MkStubs.
  Original author: raphael
  Merged from: //branches/cupcake/...
  Original author: android-build

Automated import of CL 147194
diff --git a/tools/mkstubs/src/com/android/mkstubs/AsmAnalyzer.java b/tools/mkstubs/src/com/android/mkstubs/AsmAnalyzer.java
index 0a37f29..5e64ae6 100644
--- a/tools/mkstubs/src/com/android/mkstubs/AsmAnalyzer.java
+++ b/tools/mkstubs/src/com/android/mkstubs/AsmAnalyzer.java
@@ -28,7 +28,10 @@
 import java.util.zip.ZipFile;
 
 /**
- * 
+ * Analyzes an input Jar to get all the relevant classes according to the given filter.
+ * <p/>
+ * This is mostly a helper extracted for convenience. Callers will want to use
+ * {@link #parseInputJar(String)} followed by {@link #filter(Map, Filter)}.
  */
 class AsmAnalyzer {
 
@@ -66,12 +69,22 @@
         }
     }
 
-    public void filter(Map<String, ClassReader> classes, Filter filter) {
+    /**
+     * 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.
+     */
+    void filter(Map<String, ClassReader> classes, Filter filter) {
 
         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);
diff --git a/tools/mkstubs/src/com/android/mkstubs/Filter.java b/tools/mkstubs/src/com/android/mkstubs/Filter.java
index c566c6b..0dcd8da 100644
--- a/tools/mkstubs/src/com/android/mkstubs/Filter.java
+++ b/tools/mkstubs/src/com/android/mkstubs/Filter.java
@@ -19,7 +19,15 @@
 import java.util.TreeSet;
 
 /**
- * 
+ * A "filter" holds the various patterns that MkStubs should accept (include)
+ * or reject (exclude). Patterns can be of two kind:
+ * <ul>
+ * <li>Full patterns are simple string matches, similar to a "^pattern$" regex.
+ * <li>Prefix patterns are partial string matches, similar to a "^pattern.*" regex.
+ * </ul>
+ * <p/>
+ * The {@link #accept(String)} method examines a given string against the known
+ * pattern to decide if it should be included.
  */
 class Filter {
     private TreeSet<String> mIncludePrefix = new TreeSet<String>();
@@ -27,22 +35,44 @@
     private TreeSet<String> mExcludePrefix = new TreeSet<String>();
     private TreeSet<String> mExcludeFull   = new TreeSet<String>();
 
+    /**
+     * Returns the set of all full patterns to be included.
+     */
     public TreeSet<String> getIncludeFull() {
         return mIncludeFull;
     }
-    
+
+    /**
+     * Returns the set of all prefix patterns to be included.
+     */
     public TreeSet<String> getIncludePrefix() {
         return mIncludePrefix;
     }
     
+    /**
+     * Returns the set of all full patterns to be excluded.
+     */
     public TreeSet<String> getExcludeFull() {
         return mExcludeFull;
     }
     
+    /**
+     * Returns the set of all prefix patterns to be excluded.
+     */
     public TreeSet<String> getExcludePrefix() {
         return mExcludePrefix;
     }
-    
+
+    /**
+     * Checks if the given string passes the various include/exclude rules.
+     * The matching is done as follows:
+     * <ul>
+     * <li> The string must match either a full include or a prefix include.
+     * <li> The string must not match any full exclude nor any prefix exclude.
+     * </ul>
+     * @param s The string to accept or reject.
+     * @return True if the string can be accepted, false if it must be rejected.
+     */
     public boolean accept(String s) {
         
         // Check if it can be included.
diff --git a/tools/mkstubs/src/com/android/mkstubs/FilterClassAdapter.java b/tools/mkstubs/src/com/android/mkstubs/FilterClassAdapter.java
index c3585a8..d3b06f7 100644
--- a/tools/mkstubs/src/com/android/mkstubs/FilterClassAdapter.java
+++ b/tools/mkstubs/src/com/android/mkstubs/FilterClassAdapter.java
@@ -25,7 +25,8 @@
 import org.objectweb.asm.Opcodes;
 
 /**
- * A class visitor that filters out all the referenced exclusions
+ * A class visitor that filters out all members (fields, methods and inner classes) that are
+ * either private or rejected by the {@link Filter}.
  */
 class FilterClassAdapter extends ClassAdapter {
 
diff --git a/tools/mkstubs/src/com/android/mkstubs/Main.java b/tools/mkstubs/src/com/android/mkstubs/Main.java
index fd8fa4d..01cda71 100644
--- a/tools/mkstubs/src/com/android/mkstubs/Main.java
+++ b/tools/mkstubs/src/com/android/mkstubs/Main.java
@@ -26,10 +26,15 @@
 
 
 /**
- * 
+ * Main entry point of the MkStubs app.
+ * <p/>
+ * 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)
+     */
     static class Params {
         private String mInputJarPath;
         private String mOutputJarPath;
@@ -40,22 +45,25 @@
             mOutputJarPath = outputJarPath;
             mFilter = new Filter();
         }
-        
+
+        /** Returns the name of the input jar, where to read classes from. */
         public String getInputJarPath() {
             return mInputJarPath;
         }
 
+        /** Returns the name of the output jar, where to write classes to. */
         public String getOutputJarPath() {
             return mOutputJarPath;
         }
-        
+
+        /** Returns the current instance of the filter, the include/exclude patterns. */
         public Filter getFilter() {
             return mFilter;
         }
     }
     
     /**
-     * @param args
+     * Main entry point. Processes arguments then performs the "real" work.
      */
     public static void main(String[] args) {
 
@@ -68,6 +76,17 @@
         }
     }
 
+    /**
+     * Grabs command-line arguments.
+     * The expected arguments are:
+     * <ul>
+     * <li> The filename of the input Jar.
+     * <li> The filename of the output Jar.
+     * <li> One or more include/exclude patterns or files containing these patterns.
+     *      See {@link #addString(Params, String)} for syntax.
+     * </ul>
+     * @throws IOException on failure to read a pattern file.
+     */
     private Params processArgs(String[] args) throws IOException {
         
         if (args.length < 2) {
@@ -83,7 +102,26 @@
         return p;
     }
 
+    /**
+     * Adds one pattern string to the current filter.
+     * The syntax must be:
+     * <ul>
+     * <li> +full_include or +prefix_include*
+     * <li> -full_exclude or -prefix_exclude*
+     * <li> @filename
+     * </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
+     */
     private void addString(Params p, String s) throws IOException {
+        if (s == null) {
+            return;
+        }
+
         s = s.trim();
 
         if (s.length() < 2) {
@@ -114,11 +152,20 @@
         }
     }
 
-    private void addStringsFromFile(Params p, String inputFile)
+    /**
+     * 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)
             throws IOException {
         BufferedReader br = null;
         try {
-            br = new BufferedReader(new FileReader(inputFile));
+            br = new BufferedReader(new FileReader(osFilePath));
             String line;
             while ((line = br.readLine()) != null) {
                 addString(p, line);
@@ -128,6 +175,9 @@
         }
     }
 
+    /**
+     * Prints some help to stdout.
+     */
     private void usage() {
         System.out.println("Usage: mkstub input.jar output.jar [excluded-class @excluded-classes-file ...]");
 
@@ -144,6 +194,17 @@
         System.exit(1);
     }
 
+    /**
+     * Performs the main workflow of this app:
+     * <ul>
+     * <li> Read the input Jar to get all its classes.
+     * <li> Filter out all classes that should not be included or that should be excluded.
+     * <li> Goes thru the classes, filters methods/fields and generate their source
+     *      in a directory called "&lt;outpath_jar_path&gt;_sources"
+     * <li> Does the same filtering on the classes but this time generates the real stubbed
+     *      output jar.
+     * </ul>
+     */
     private void process(Params p) throws IOException {
         AsmAnalyzer aa = new AsmAnalyzer();
         Map<String, ClassReader> classes = aa.parseInputJar(p.getInputJarPath());
diff --git a/tools/mkstubs/src/com/android/mkstubs/SourceGenerator.java b/tools/mkstubs/src/com/android/mkstubs/SourceGenerator.java
index 461a25f..f5a339d 100644
--- a/tools/mkstubs/src/com/android/mkstubs/SourceGenerator.java
+++ b/tools/mkstubs/src/com/android/mkstubs/SourceGenerator.java
@@ -30,7 +30,11 @@
 import java.util.Map.Entry;
 
 /**
- * 
+ * Given a set of already filtered classes, this filters out all private members and then
+ * generates the Java source for the remaining classes.
+ * <p/>
+ * This is an helper extracted for convenience. Callers just need to use
+ * {@link #generateSource(File, Map, Filter)}.
  */
 class SourceGenerator {
 
diff --git a/tools/mkstubs/src/com/android/mkstubs/StubGenerator.java b/tools/mkstubs/src/com/android/mkstubs/StubGenerator.java
index 0321dc3..6126e17 100644
--- a/tools/mkstubs/src/com/android/mkstubs/StubGenerator.java
+++ b/tools/mkstubs/src/com/android/mkstubs/StubGenerator.java
@@ -32,7 +32,11 @@
 import java.util.jar.JarOutputStream;
 
 /**
- * 
+ * Given a set of already filtered classes, this filters out all private members,
+ * stubs the remaining classes and then generates a Jar out of them.
+ * <p/>
+ * This is an helper extracted for convenience. Callers just need to use
+ * {@link #generateStubbedJar(File, Map, Filter)}.
  */
 class StubGenerator {
 
diff --git a/tools/mkstubs/src/com/android/mkstubs/sourcer/AccessSourcer.java b/tools/mkstubs/src/com/android/mkstubs/sourcer/AccessSourcer.java
index 757dcea..3b14ea7 100644
--- a/tools/mkstubs/src/com/android/mkstubs/sourcer/AccessSourcer.java
+++ b/tools/mkstubs/src/com/android/mkstubs/sourcer/AccessSourcer.java
@@ -19,7 +19,11 @@
 import org.objectweb.asm.Opcodes;
 
 /**
- * 
+ * Source generator for the access fields of methods, fields and classes.
+ * <p/>
+ * Given an integer access field and a type ({@link #IS_CLASS}, {@link #IS_FIELD} or
+ * {@link #IS_METHOD}), the {@link #write(int, int)} method can generate a string
+ * desribing the access modifiers for a Java source. 
  */
 class AccessSourcer {
 
@@ -81,6 +85,9 @@
 
     /**
      * Generates a list of access keywords, e.g. "public final".
+     * <p/>
+     * It is up to the caller to filter extra keywords that should not be generated,
+     * e.g. {@link Flag#ACC_SYNTHETIC}.
      *  
      * @param access The access mode, e.g. 33 or 18
      * @param filter One of {@link #IS_CLASS}, {@link #IS_FIELD} or {@link #IS_METHOD}, which
diff --git a/tools/mkstubs/src/com/android/mkstubs/sourcer/AnnotationSourcer.java b/tools/mkstubs/src/com/android/mkstubs/sourcer/AnnotationSourcer.java
index bbf1cb2..d2843a8 100644
--- a/tools/mkstubs/src/com/android/mkstubs/sourcer/AnnotationSourcer.java
+++ b/tools/mkstubs/src/com/android/mkstubs/sourcer/AnnotationSourcer.java
@@ -19,7 +19,7 @@
 import org.objectweb.asm.AnnotationVisitor;
 
 /**
- * 
+ * An annotation visitor that generates Java source for an annotation.
  */
 class AnnotationSourcer implements AnnotationVisitor {
 
diff --git a/tools/mkstubs/src/com/android/mkstubs/sourcer/ClassSourcer.java b/tools/mkstubs/src/com/android/mkstubs/sourcer/ClassSourcer.java
index 189e1a0..3d95039 100644
--- a/tools/mkstubs/src/com/android/mkstubs/sourcer/ClassSourcer.java
+++ b/tools/mkstubs/src/com/android/mkstubs/sourcer/ClassSourcer.java
@@ -25,7 +25,7 @@
 import org.objectweb.asm.signature.SignatureReader;
 
 /**
- * A class visitor that rewrites a java source
+ * A class visitor that writes a java source.
  */
 public class ClassSourcer implements ClassVisitor {
 
diff --git a/tools/mkstubs/src/com/android/mkstubs/sourcer/FieldSourcer.java b/tools/mkstubs/src/com/android/mkstubs/sourcer/FieldSourcer.java
index 4f9c229..7f30a24 100644
--- a/tools/mkstubs/src/com/android/mkstubs/sourcer/FieldSourcer.java
+++ b/tools/mkstubs/src/com/android/mkstubs/sourcer/FieldSourcer.java
@@ -19,10 +19,11 @@
 import org.objectweb.asm.AnnotationVisitor;
 import org.objectweb.asm.Attribute;
 import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Type;
 import org.objectweb.asm.signature.SignatureReader;
 
 /**
- * 
+ * A field visitor that generates Java source defining a field. 
  */
 class FieldSourcer implements FieldVisitor {
 
@@ -56,7 +57,7 @@
         as.write(mAccess, AccessSourcer.IS_FIELD);
         
         if (mSignature == null) {
-            mOutput.write(" %s", mOutput.decodeDesc(mDesc));
+            mOutput.write(" %s", Type.getType(mDesc).getClassName());
         } else {
             mOutput.write(" ");
             SignatureReader sigReader = new SignatureReader(mSignature);
diff --git a/tools/mkstubs/src/com/android/mkstubs/sourcer/MethodSourcer.java b/tools/mkstubs/src/com/android/mkstubs/sourcer/MethodSourcer.java
index d474e4b..f58de32 100644
--- a/tools/mkstubs/src/com/android/mkstubs/sourcer/MethodSourcer.java
+++ b/tools/mkstubs/src/com/android/mkstubs/sourcer/MethodSourcer.java
@@ -26,7 +26,7 @@
 import java.util.ArrayList;
 
 /**
- * 
+ * A method visitor that generates the Java source for a whole method. 
  */
 class MethodSourcer implements MethodVisitor {
 
diff --git a/tools/mkstubs/src/com/android/mkstubs/sourcer/Output.java b/tools/mkstubs/src/com/android/mkstubs/sourcer/Output.java
index 837cf95..bc2218f 100644
--- a/tools/mkstubs/src/com/android/mkstubs/sourcer/Output.java
+++ b/tools/mkstubs/src/com/android/mkstubs/sourcer/Output.java
@@ -16,22 +16,38 @@
 
 package com.android.mkstubs.sourcer;
 
-import org.objectweb.asm.Type;
-
 import java.io.IOException;
 import java.io.Writer;
 
 /**
- * 
+ * An {@link Output} objects is an helper to write to a character stream {@link Writer}.
+ * <p/>
+ * It provide some helper methods to the various "sourcer" classes from this package
+ * to help them write to the underlying stream.
  */
 public class Output {
     
     private final Writer mWriter;
 
+    /**
+     * Creates a new {@link Output} object that wraps the given {@link Writer}.
+     * <p/>
+     * The caller is responsible of opening and closing the {@link Writer}.
+     * 
+     * @param writer The writer to write to. Could be a file, a string, etc.
+     */
     public Output(Writer writer) {
         mWriter = writer;
     }
 
+    /**
+     * Writes a formatted string to the writer.
+     * 
+     * @param format The format string.
+     * @param args The arguments for the format string.
+     * 
+     * @see String#format(String, Object...)
+     */
     public void write(String format, Object... args) {
         try {
             mWriter.write(String.format(format, args));
@@ -40,18 +56,21 @@
         }
     }
     
+    /**
+     * Writes a single character to the writer.
+     * 
+     * @param c The character to write.
+     */
     public void write(char c) {
         write(Character.toString(c));
     }
     
+    /**
+     * Writes a {@link StringBuilder} to the writer.
+     * 
+     * @param sb The {@link StringBuilder#toString()} method is used to ge the string to write.
+     */
     public void write(StringBuilder sb) {
         write(sb.toString());
     }
-
-    
-    public String decodeDesc(String desc) {
-        return Type.getType(desc).getClassName();
-    }
-
-
 }
diff --git a/tools/mkstubs/src/com/android/mkstubs/sourcer/SignatureSourcer.java b/tools/mkstubs/src/com/android/mkstubs/sourcer/SignatureSourcer.java
index 6202528..7805d7d 100644
--- a/tools/mkstubs/src/com/android/mkstubs/sourcer/SignatureSourcer.java
+++ b/tools/mkstubs/src/com/android/mkstubs/sourcer/SignatureSourcer.java
@@ -24,14 +24,22 @@
 import java.util.ArrayList;
 
 /**
- * Note: most of the implementation is a duplicate of
- * ASM's SignatureWriter with some slight variations.
+ * A signature visitor that can be used to generate Java source corresponding to
+ * various types of signatures.
  * <p/>
- * Note: When processing a method's signature, the signature order is the
- * reverse of the source order, e.g. it is (parameters)return-type where
- * we want to generate "return-type method-name (parameters)".
- * So in this case the return-type and parameters are not output directly
- * but are instead accumulated in internal variables.
+ * Terminology: a "signature" is a type descriptor for generics. There are different types
+ * of signatures depending on the context where they are used, e.g. method declarations,
+ * method parameters, class declarations, etc..
+ * <p/>
+ * Note: most of the implementation is a duplicate of ASM's SignatureWriter with some
+ * slight variations.
+ * <p/>
+ * Note: When processing a method's signature, the signature order is the reverse of the source
+ * order, e.g. the signature is written as "(parameters)return-type" where we want to generate
+ * "return-type method-name (parameters)". To hanlde this case, the return-type and parameters
+ * are <em>not</em> output directly but are instead accumulated in internal variables that you can
+ * get later using {@link #getReturnType()}, {@link #getParameters()}, {@link #getSuperClass()}
+ * and {@link #formalsToString()}.
  */
 class SignatureSourcer implements SignatureVisitor {
 
@@ -58,10 +66,22 @@
      */
     private int mArgumentStack;
 
+    /**
+     * {@link SignatureSourcer} generated when parsing the return type of <em>this</em>
+     * signature. Initially null.
+     */
     private SignatureSourcer mReturnType;
 
+    /**
+     * {@link SignatureSourcer} generated when parsing the super class of <em>this</em>
+     * signature. Initially null.
+     */
     private SignatureSourcer mSuperClass;
 
+    /**
+     * {@link SignatureSourcer}s for each parameters generated when parsing the method parameters
+     * of <em>this</em> signature. Initially empty but not null.
+     */
     private ArrayList<SignatureSourcer> mParameters = new ArrayList<SignatureSourcer>();
 
 
diff --git a/tools/mkstubs/src/com/android/mkstubs/stubber/ClassStubber.java b/tools/mkstubs/src/com/android/mkstubs/stubber/ClassStubber.java
index dea0a52..8f9ae11 100644
--- a/tools/mkstubs/src/com/android/mkstubs/stubber/ClassStubber.java
+++ b/tools/mkstubs/src/com/android/mkstubs/stubber/ClassStubber.java
@@ -24,7 +24,8 @@
 import org.objectweb.asm.MethodVisitor;
 
 /**
- * 
+ * A class visitor that generates stubs for all methods of the visited class.
+ * Everything else is passed as-is.
  */
 public class ClassStubber extends ClassAdapter {
 
diff --git a/tools/mkstubs/src/com/android/mkstubs/stubber/MethodStubber.java b/tools/mkstubs/src/com/android/mkstubs/stubber/MethodStubber.java
index 3e200cd..1617809 100644
--- a/tools/mkstubs/src/com/android/mkstubs/stubber/MethodStubber.java
+++ b/tools/mkstubs/src/com/android/mkstubs/stubber/MethodStubber.java
@@ -24,7 +24,13 @@
 import org.objectweb.asm.Opcodes;
 
 /**
- * 
+ * A method visitor that generates a code stub for the visited method.
+ * <p/>
+ * Annotations and parameters are passed as-is.
+ * All other code is replaced by the following:
+ * <pre>throw new RuntimeException("stub");</pre>
+ * Note that constructors rewritten this way will probably fail with the runtime bytecode
+ * verifier since no call to <code>super</code> is generated.
  */
 public class MethodStubber extends MethodAdapter {