implementation.
b- A brand new implementation of SomeClass.MethodName() which calls to a non-existing static method
named SomeClass_Delegate.MethodName(). The implementation of this 'delegate' method is done in
-layoutlib_brigde.
+layoutlib_bridge.
The delegate method is a static method. If the original method is non-static, the delegate method
receives the original 'this' as its first argument. If the original method is an inner non-static
String name = classToEntryPath(clazz);
InputStream is = ClassLoader.getSystemResourceAsStream(name);
ClassReader cr = new ClassReader(is);
- byte[] b = transform(cr, true /* stubNativesOnly */);
+ byte[] b = transform(cr, true);
name = classNameToEntryPath(transformName(cr.getClassName()));
all.put(name, b);
}
for (Entry<String, ClassReader> entry : mDeps.entrySet()) {
ClassReader cr = entry.getValue();
- byte[] b = transform(cr, true /* stubNativesOnly */);
+ byte[] b = transform(cr, true);
String name = classNameToEntryPath(transformName(cr.getClassName()));
all.put(name, b);
}
for (Entry<String, ClassReader> entry : mKeep.entrySet()) {
ClassReader cr = entry.getValue();
- byte[] b = transform(cr, true /* stubNativesOnly */);
+ byte[] b = transform(cr, true);
String name = classNameToEntryPath(transformName(cr.getClassName()));
all.put(name, b);
}
/**
* Utility method to get the JAR entry path from a Class name.
- * e.g. it returns someting like "com/foo/OuterClass$InnerClass1$InnerClass2.class"
+ * e.g. it returns something like "com/foo/OuterClass$InnerClass1$InnerClass2.class"
*/
private String classToEntryPath(Class<?> clazz) {
String name = "";
cv = new RenameClassAdapter(cv, className, newName);
}
- cv = new TransformClassAdapter(mLog, mStubMethods,
- mDeleteReturns.get(className),
- newName, cv,
- stubNativesOnly, stubNativesOnly || hasNativeMethods);
+ cv = new TransformClassAdapter(mLog, mStubMethods, mDeleteReturns.get(className),
+ newName, cv, stubNativesOnly);
Set<String> delegateMethods = mDelegateMethods.get(className);
if (delegateMethods != null && !delegateMethods.isEmpty()) {
}
}
- cr.accept(cv, 0 /* flags */);
+ cr.accept(cv, 0);
return cw.toByteArray();
}
*/
boolean hasNativeMethods(ClassReader cr) {
ClassHasNativeVisitor cv = new ClassHasNativeVisitor();
- cr.accept(cv, 0 /* flags */);
+ cr.accept(cv, 0);
return cv.hasNativeMethods();
}
/** Suffix added to original methods. */
private static final String ORIGINAL_SUFFIX = "_Original";
- private static String CONSTRUCTOR = "<init>";
- private static String CLASS_INIT = "<clinit>";
+ private static final String CONSTRUCTOR = "<init>";
+ private static final String CLASS_INIT = "<clinit>";
- public final static String ALL_NATIVES = "<<all_natives>>";
+ public static final String ALL_NATIVES = "<<all_natives>>";
private final String mClassName;
private final Set<String> mDelegateMethods;
mDelegateMethods.contains(name);
if (!useDelegate) {
- // Not creating a delegate for this method, pass it as-is from the reader
- // to the writer.
+ // Not creating a delegate for this method, pass it as-is from the reader to the writer.
return super.visitMethod(access, name, desc, signature, exceptions);
}
- if (useDelegate) {
- if (CONSTRUCTOR.equals(name) || CLASS_INIT.equals(name)) {
- // We don't currently support generating delegates for constructors.
- throw new UnsupportedOperationException(
- String.format(
- "Delegate doesn't support overriding constructor %1$s:%2$s(%3$s)", //$NON-NLS-1$
- mClassName, name, desc));
- }
+ if (CONSTRUCTOR.equals(name) || CLASS_INIT.equals(name)) {
+ // We don't currently support generating delegates for constructors.
+ throw new UnsupportedOperationException(
+ String.format(
+ "Delegate doesn't support overriding constructor %1$s:%2$s(%3$s)", //$NON-NLS-1$
+ mClassName, name, desc));
}
if (isNative) {
access = access & ~Opcodes.ACC_NATIVE;
MethodVisitor mwDelegate = super.visitMethod(access, name, desc, signature, exceptions);
- DelegateMethodAdapter2 a = new DelegateMethodAdapter2(
- mLog, null /*mwOriginal*/, mwDelegate, mClassName, name, desc, isStatic);
+ DelegateMethodAdapter a = new DelegateMethodAdapter(
+ mLog, null, mwDelegate, mClassName, name, desc, isStatic);
// A native has no code to visit, so we need to generate it directly.
a.generateDelegateCode();
// The content is the original method as-is from the reader.
// - A brand new implementation of SomeClass.MethodName() which calls to a
// non-existing method named SomeClass_Delegate.MethodName().
- // The implementation of this 'delegate' method is done in layoutlib_brigde.
+ // The implementation of this 'delegate' method is done in layoutlib_bridge.
int accessDelegate = access;
- // change access to public for the original one
- if (Main.sOptions.generatePublicAccess) {
- access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
- access |= Opcodes.ACC_PUBLIC;
- }
MethodVisitor mwOriginal = super.visitMethod(access, name + ORIGINAL_SUFFIX,
desc, signature, exceptions);
MethodVisitor mwDelegate = super.visitMethod(accessDelegate, name,
desc, signature, exceptions);
- DelegateMethodAdapter2 a = new DelegateMethodAdapter2(
+ return new DelegateMethodAdapter(
mLog, mwOriginal, mwDelegate, mClassName, name, desc, isStatic);
- return a;
}
}
* Instances of this class are not re-usable.
* The class adapter creates a new instance for each method.
*/
-class DelegateMethodAdapter2 extends MethodVisitor {
+class DelegateMethodAdapter extends MethodVisitor {
/** Suffix added to delegate classes. */
public static final String DELEGATE_SUFFIX = "_Delegate";
private Object[] mDelegateLineNumber;
/**
- * Creates a new {@link DelegateMethodAdapter2} that will transform this method
+ * Creates a new {@link DelegateMethodAdapter} that will transform this method
* into a delegate call.
* <p/>
- * See {@link DelegateMethodAdapter2} for more details.
+ * See {@link DelegateMethodAdapter} for more details.
*
* @param log The logger object. Must not be null.
* @param mvOriginal The parent method writer to copy of the original method.
* {@link Type#getArgumentTypes(String)})
* @param isStatic True if the method is declared static.
*/
- public DelegateMethodAdapter2(Log log,
+ public DelegateMethodAdapter(Log log,
MethodVisitor mvOriginal,
MethodVisitor mvDelegate,
String className,
* (since they have no code to visit).
* <p/>
* Otherwise for non-native methods the {@link DelegateClassAdapter} simply needs to
- * return this instance of {@link DelegateMethodAdapter2} and let the normal visitor pattern
+ * return this instance of {@link DelegateMethodAdapter} and let the normal visitor pattern
* invoke it as part of the {@link ClassReader#accept(ClassVisitor, int)} workflow and then
* this method will be invoked from {@link MethodVisitor#visitEnd()}.
*/
public class Main {
public static class Options {
- public boolean generatePublicAccess = true;
public boolean listAllDeps = false;
public boolean listOnlyMissingDeps = false;
}
for (String s : args) {
if (s.equals("-v")) {
log.setVerbose(true);
- } else if (s.equals("-p")) {
- sOptions.generatePublicAccess = false;
} else if (s.equals("--list-deps")) {
sOptions.listAllDeps = true;
needs_dest = false;
return false;
}
- sOptions.generatePublicAccess = false;
-
return true;
}
}
/**
* Creates a new class adapter that will stub some or all methods.
- * @param logger
* @param stubMethods list of method signatures to always stub out
* @param deleteReturns list of types that trigger the deletion of methods returning them.
* @param className The name of the class being modified
* @param cv The parent class writer visitor
* @param stubNativesOnly True if only native methods should be stubbed. False if all
* methods should be stubbed.
- * @param hasNative True if the method has natives, in which case its access should be
- * changed.
*/
public TransformClassAdapter(Log logger, Set<String> stubMethods,
Set<String> deleteReturns, String className, ClassVisitor cv,
- boolean stubNativesOnly, boolean hasNative) {
+ boolean stubNativesOnly) {
super(Opcodes.ASM4, cv);
mLog = logger;
mStubMethods = stubMethods;
// This class might be being renamed.
name = mClassName;
- // remove protected or private and set as public
- if (Main.sOptions.generatePublicAccess) {
- access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
- access |= Opcodes.ACC_PUBLIC;
- }
// remove final
access = access & ~Opcodes.ACC_FINAL;
// note: leave abstract classes as such
/* Visits the header of an inner class. */
@Override
public void visitInnerClass(String name, String outerName, String innerName, int access) {
- // remove protected or private and set as public
- if (Main.sOptions.generatePublicAccess) {
- access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
- access |= Opcodes.ACC_PUBLIC;
- }
// remove final
access = access & ~Opcodes.ACC_FINAL;
// note: leave abstract classes as such
String methodSignature = mClassName.replace('/', '.') + "#" + name;
- // change access to public
- if (Main.sOptions.generatePublicAccess) {
- access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
- access |= Opcodes.ACC_PUBLIC;
- }
-
// remove final
access = access & ~Opcodes.ACC_FINAL;
@Override
public FieldVisitor visitField(int access, String name, String desc, String signature,
Object value) {
- // change access to public
- if (Main.sOptions.generatePublicAccess) {
- access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
- access |= Opcodes.ACC_PUBLIC;
- }
return super.visitField(access, name, desc, signature, value);
}
}
/**
- * {@link DelegateMethodAdapter2} does not support overriding constructors yet,
+ * {@link DelegateMethodAdapter} does not support overriding constructors yet,
* so this should fail with an {@link UnsupportedOperationException}.
*
* Although not tested here, the message of the exception should contain the
// Check the inner class. Since it's not a static inner class, we need
// to use the hidden constructor that takes the outer class as first parameter.
Class<?> innerClazz2 = loadClass(INNER_CLASS_NAME);
- Constructor<?> innerCons = innerClazz2.getConstructor(
- new Class<?>[] { outerClazz2 });
- Object i2 = innerCons.newInstance(new Object[] { o2 });
+ Constructor<?> innerCons = innerClazz2.getConstructor(outerClazz2);
+ Object i2 = innerCons.newInstance(o2);
assertNotNull(i2);
// The original Inner.get returns 3+10+20,
*/
public int callGet(Object instance, int a, long b) throws Exception {
Method m = instance.getClass().getMethod("get",
- new Class<?>[] { int.class, long.class } );
+ int.class, long.class);
- Object result = m.invoke(instance, new Object[] { a, b });
- return ((Integer) result).intValue();
+ Object result = m.invoke(instance, a, b);
+ return (Integer) result;
}
/**
*/
public int callGet_Original(Object instance, int a, long b) throws Exception {
Method m = instance.getClass().getMethod("get_Original",
- new Class<?>[] { int.class, long.class } );
+ int.class, long.class);
- Object result = m.invoke(instance, new Object[] { a, b });
- return ((Integer) result).intValue();
+ Object result = m.invoke(instance, a, b);
+ return (Integer) result;
}
/**
*/
public int callAdd(Object instance, int a, int b) throws Exception {
Method m = instance.getClass().getMethod("add",
- new Class<?>[] { int.class, int.class });
+ int.class, int.class);
- Object result = m.invoke(instance, new Object[] { a, b });
- return ((Integer) result).intValue();
+ Object result = m.invoke(instance, a, b);
+ return (Integer) result;
}
/**
public int callCallNativeInstance(Object instance, int a, double d, Object[] o)
throws Exception {
Method m = instance.getClass().getMethod("callNativeInstance",
- new Class<?>[] { int.class, double.class, Object[].class });
+ int.class, double.class, Object[].class);
- Object result = m.invoke(instance, new Object[] { a, d, o });
- return ((Integer) result).intValue();
+ Object result = m.invoke(instance, a, d, o);
+ return (Integer) result;
}
public abstract void testModifiedInstance() throws Exception;
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
// next 2 lines do: TraceClassVisitor tcv = new TraceClassVisitor(pw);
- Constructor<?> cons = tcvClass.getConstructor(new Class<?>[] { pw.getClass() });
- Object tcv = cons.newInstance(new Object[] { pw });
+ Constructor<?> cons = tcvClass.getConstructor(pw.getClass());
+ Object tcv = cons.newInstance(pw);
ClassReader cr2 = new ClassReader(bytes);
cr2.accept((ClassVisitor) tcv, 0 /* flags */);
}
// Re-throw exception with new message
- RuntimeException ex = new RuntimeException(sb.toString(), t);
- return ex;
+ return new RuntimeException(sb.toString(), t);
} catch (Throwable ignore) {
// In case of problem, just throw the original exception as-is.
return t;