diff options
| author | Raphael Moll <> | 2009-04-17 08:00:06 -0700 |
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2009-04-17 08:00:06 -0700 |
| commit | 42c230dd91c73413d4d538e7a68639816cf83f32 (patch) | |
| tree | b32017eb1be913df7f0034ab7c234ae97cea6958 /tools/mkstubs/src/com/android | |
| parent | 5ca1e5e36bee5636936bf2de42d0edb0304ac853 (diff) | |
| download | android_development-42c230dd91c73413d4d538e7a68639816cf83f32.tar.gz android_development-42c230dd91c73413d4d538e7a68639816cf83f32.tar.bz2 android_development-42c230dd91c73413d4d538e7a68639816cf83f32.zip | |
AI 146720: ADT Jar Stubber: generate stubbed jar.
This also reorganizes some source so it's 90% refactoring.
There will be more filtering to do in another CL.
BUG=1778786
Automated import of CL 146720
Diffstat (limited to 'tools/mkstubs/src/com/android')
| -rw-r--r-- | tools/mkstubs/src/com/android/mkstubs/Main.java | 19 | ||||
| -rw-r--r-- | tools/mkstubs/src/com/android/mkstubs/SourceGenerator.java (renamed from tools/mkstubs/src/com/android/mkstubs/AsmGenerator.java) | 10 | ||||
| -rw-r--r-- | tools/mkstubs/src/com/android/mkstubs/StubGenerator.java | 103 | ||||
| -rw-r--r-- | tools/mkstubs/src/com/android/mkstubs/sourcer/ClassSourcer.java (renamed from tools/mkstubs/src/com/android/mkstubs/sourcer/JavaSourcer.java) | 4 | ||||
| -rw-r--r-- | tools/mkstubs/src/com/android/mkstubs/stubber/ClassStubber.java | 86 | ||||
| -rw-r--r-- | tools/mkstubs/src/com/android/mkstubs/stubber/MethodStubber.java | 179 |
6 files changed, 382 insertions, 19 deletions
diff --git a/tools/mkstubs/src/com/android/mkstubs/Main.java b/tools/mkstubs/src/com/android/mkstubs/Main.java index 017b2f15f..5c6e209de 100644 --- a/tools/mkstubs/src/com/android/mkstubs/Main.java +++ b/tools/mkstubs/src/com/android/mkstubs/Main.java @@ -146,20 +146,15 @@ public class Main { aa.filter(classes, p.getInclusions(), p.getExclusions()); - AsmGenerator gen = new AsmGenerator(); - // dump as Java source files, mostly for debugging - File dst_src_dir = new File(p.getOutputJarPath() + File.separator + "sources"); + SourceGenerator src_gen = new SourceGenerator(); + File dst_src_dir = new File(p.getOutputJarPath() + "_sources"); dst_src_dir.mkdir(); - gen.generateSource(dst_src_dir, classes, p.getExclusions()); + src_gen.generateSource(dst_src_dir, classes, p.getExclusions()); + // dump the stubbed jar + StubGenerator stub_gen = new StubGenerator(); + File dst_jar = new File(p.getOutputJarPath()); + stub_gen.generateStubbedJar(dst_jar, classes, p.getExclusions()); } - - /** @deprecated debug only */ - private void displayClasses(Map<String, ClassReader> classes) { - for(String className : classes.keySet()) { - System.out.println("Found " + className); - } - } - } diff --git a/tools/mkstubs/src/com/android/mkstubs/AsmGenerator.java b/tools/mkstubs/src/com/android/mkstubs/SourceGenerator.java index 3446b0053..3eb19d613 100644 --- a/tools/mkstubs/src/com/android/mkstubs/AsmGenerator.java +++ b/tools/mkstubs/src/com/android/mkstubs/SourceGenerator.java @@ -16,7 +16,7 @@ package com.android.mkstubs; -import com.android.mkstubs.sourcer.JavaSourcer; +import com.android.mkstubs.sourcer.ClassSourcer; import com.android.mkstubs.sourcer.Output; import org.objectweb.asm.ClassReader; @@ -33,7 +33,7 @@ import java.util.Map.Entry; /** * */ -class AsmGenerator { +class SourceGenerator { /** * Generate source for the stubbed classes, mostly for debug purposes. @@ -51,7 +51,7 @@ class AsmGenerator { FileWriter fw = null; try { fw = createWriter(baseDir, name); - dumpClass(fw, cr, exclusions); + visitClassSource(fw, cr, exclusions); } finally { fw.close(); } @@ -79,10 +79,10 @@ class AsmGenerator { * Generate a source equivalent to the stubbed version of the class reader, * minus all exclusions */ - void dumpClass(Writer fw, ClassReader cr, List<String> exclusions) { + void visitClassSource(Writer fw, ClassReader cr, List<String> exclusions) { System.out.println("Dump " + cr.getClassName()); - ClassVisitor javaWriter = new JavaSourcer(new Output(fw)); + ClassVisitor javaWriter = new ClassSourcer(new Output(fw)); ClassVisitor filter = new FilterClassAdapter(javaWriter, exclusions); cr.accept(filter, 0 /*flags*/); } diff --git a/tools/mkstubs/src/com/android/mkstubs/StubGenerator.java b/tools/mkstubs/src/com/android/mkstubs/StubGenerator.java new file mode 100644 index 000000000..79855acb0 --- /dev/null +++ b/tools/mkstubs/src/com/android/mkstubs/StubGenerator.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.mkstubs; + +import com.android.mkstubs.stubber.ClassStubber; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.Map.Entry; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; + +/** + * + */ +class StubGenerator { + + /** + * Generate source for the stubbed classes, mostly for debug purposes. + * @throws IOException + */ + public void generateStubbedJar(File destJar, + Map<String, ClassReader> classes, + List<String> exclusions) throws IOException { + + TreeMap<String, byte[]> all = new TreeMap<String, byte[]>(); + + for (Entry<String, ClassReader> entry : classes.entrySet()) { + ClassReader cr = entry.getValue(); + + byte[] b = visitClassStubber(cr, exclusions); + String name = classNameToEntryPath(cr.getClassName()); + all.put(name, b); + } + + createJar(new FileOutputStream(destJar), all); + + System.out.println(String.format("Wrote %s", destJar.getPath())); + } + + /** + * Utility method that converts a fully qualified java name into a JAR entry path + * e.g. for the input "android.view.View" it returns "android/view/View.class" + */ + String classNameToEntryPath(String className) { + return className.replaceAll("\\.", "/").concat(".class"); + } + + /** + * Writes the JAR file. + * + * @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 + */ + void createJar(FileOutputStream outStream, Map<String,byte[]> all) throws IOException { + JarOutputStream jar = new JarOutputStream(outStream); + for (Entry<String, byte[]> entry : all.entrySet()) { + String name = entry.getKey(); + JarEntry jar_entry = new JarEntry(name); + jar.putNextEntry(jar_entry); + jar.write(entry.getValue()); + jar.closeEntry(); + } + jar.flush(); + jar.close(); + } + + byte[] visitClassStubber(ClassReader cr, List<String> exclusions) { + System.out.println("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 filter = new FilterClassAdapter(stubWriter, exclusions); + cr.accept(filter, 0 /*flags*/); + return cw.toByteArray(); + } +} diff --git a/tools/mkstubs/src/com/android/mkstubs/sourcer/JavaSourcer.java b/tools/mkstubs/src/com/android/mkstubs/sourcer/ClassSourcer.java index fb06c680d..189e1a007 100644 --- a/tools/mkstubs/src/com/android/mkstubs/sourcer/JavaSourcer.java +++ b/tools/mkstubs/src/com/android/mkstubs/sourcer/ClassSourcer.java @@ -27,13 +27,13 @@ import org.objectweb.asm.signature.SignatureReader; /** * A class visitor that rewrites a java source */ -public class JavaSourcer implements ClassVisitor { +public class ClassSourcer implements ClassVisitor { private final Output mOutput; private final AccessSourcer mAccessSourcer; private String mClassName; - public JavaSourcer(Output output) { + public ClassSourcer(Output output) { mOutput = output; mAccessSourcer = new AccessSourcer(mOutput); } diff --git a/tools/mkstubs/src/com/android/mkstubs/stubber/ClassStubber.java b/tools/mkstubs/src/com/android/mkstubs/stubber/ClassStubber.java new file mode 100644 index 000000000..dea0a5298 --- /dev/null +++ b/tools/mkstubs/src/com/android/mkstubs/stubber/ClassStubber.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.mkstubs.stubber; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.ClassAdapter; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; + +/** + * + */ +public class ClassStubber extends ClassAdapter { + + public ClassStubber(ClassVisitor cv) { + super(cv); + } + + @Override + public void visit(int version, int access, + String name, + String signature, + String superName, + String[] interfaces) { + super.visit(version, access, name, signature, superName, interfaces); + } + + @Override + public void visitEnd() { + super.visitEnd(); + } + + @Override + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + return super.visitAnnotation(desc, visible); + } + + @Override + public void visitAttribute(Attribute attr) { + super.visitAttribute(attr); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, + String[] exceptions) { + MethodVisitor mw = super.visitMethod(access, name, desc, signature, exceptions); + return new MethodStubber(mw, access, name, desc, signature, exceptions); + } + + @Override + public FieldVisitor visitField(int access, String name, String desc, String signature, + Object value) { + return super.visitField(access, name, desc, signature, value); + } + + @Override + public void visitInnerClass(String name, String outerName, String innerName, int access) { + super.visitInnerClass(name, outerName, innerName, access); + } + + @Override + public void visitOuterClass(String owner, String name, String desc) { + super.visitOuterClass(owner, name, desc); + } + + @Override + public void visitSource(String source, String debug) { + super.visitSource(source, debug); + } +} diff --git a/tools/mkstubs/src/com/android/mkstubs/stubber/MethodStubber.java b/tools/mkstubs/src/com/android/mkstubs/stubber/MethodStubber.java new file mode 100644 index 000000000..3e200cd94 --- /dev/null +++ b/tools/mkstubs/src/com/android/mkstubs/stubber/MethodStubber.java @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.mkstubs.stubber; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodAdapter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +/** + * + */ +public class MethodStubber extends MethodAdapter { + + public MethodStubber(MethodVisitor mw, + int access, String name, String desc, String signature, String[] exceptions) { + super(mw); + } + + @Override + public void visitCode() { + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitLineNumber(36, l0); + mv.visitTypeInsn(Opcodes.NEW, "java/lang/RuntimeException"); + mv.visitInsn(Opcodes.DUP); + mv.visitLdcInsn("stub"); + mv.visitMethodInsn( + Opcodes.INVOKESPECIAL, // opcode + "java/lang/RuntimeException", // owner + "<init>", // name + "(Ljava/lang/String;)V"); // desc + mv.visitInsn(Opcodes.ATHROW); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitLocalVariable( + "this", // name + "Lcom/android/mkstubs/stubber/MethodStubber;", // desc + null, // signature + l0, // label start + l1, // label end + 0); // index + mv.visitMaxs(3, 1); // maxStack, maxLocals + } + + @Override + public void visitEnd() { + super.visitEnd(); + } + + @Override + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + return super.visitAnnotation(desc, visible); + } + + @Override + public AnnotationVisitor visitAnnotationDefault() { + return super.visitAnnotationDefault(); + } + + @Override + public void visitAttribute(Attribute attr) { + super.visitAttribute(attr); + } + + @Override + public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) { + return super.visitParameterAnnotation(parameter, desc, visible); + } + + // -- stuff that gets skipped + + @Override + public void visitFieldInsn(int opcode, String owner, String name, String desc) { + // skip + } + + @Override + public void visitFrame(int type, int local, Object[] local2, int stack, Object[] stack2) { + // skip + } + + @Override + public void visitIincInsn(int var, int increment) { + // skip + } + + @Override + public void visitInsn(int opcode) { + // skip + } + + @Override + public void visitIntInsn(int opcode, int operand) { + // skip + } + + @Override + public void visitJumpInsn(int opcode, Label label) { + // skip + } + + @Override + public void visitLabel(Label label) { + // skip + } + + @Override + public void visitLdcInsn(Object cst) { + // skip + } + + @Override + public void visitLineNumber(int line, Label start) { + // skip + } + + @Override + public void visitLocalVariable(String name, String desc, String signature, + Label start, Label end, int index) { + // skip + } + + @Override + public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { + // skip + } + + @Override + public void visitMaxs(int maxStack, int maxLocals) { + // skip + } + + @Override + public void visitMethodInsn(int opcode, String owner, String name, String desc) { + // skip + } + + @Override + public void visitMultiANewArrayInsn(String desc, int dims) { + // skip + } + + @Override + public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) { + // skip + } + + @Override + public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { + // skip + } + + @Override + public void visitTypeInsn(int opcode, String type) { + // skip + } + + @Override + public void visitVarInsn(int opcode, int var) { + // skip + } +} |
