Loading tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java +2 −0 Original line number Original line Diff line number Diff line Loading @@ -112,6 +112,8 @@ public class AsmAnalyzer { mGen.setDeps(deps); mGen.setDeps(deps); mGen.setCopyFiles(filesFound); mGen.setCopyFiles(filesFound); mGen.setRewriteMethodCallClasses(mReplaceMethodCallClasses); mGen.setRewriteMethodCallClasses(mReplaceMethodCallClasses); // hack hack hack mGen.mSimpleMonthViewReader = zipClasses.get(AsmGenerator.SIMPLE_MONTH_VIEW); } } } } Loading tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java +8 −1 Original line number Original line Diff line number Diff line Loading @@ -77,6 +77,9 @@ public class AsmGenerator { /** Methods to inject. FQCN of class in which method should be injected => runnable that does /** Methods to inject. FQCN of class in which method should be injected => runnable that does * the injection. */ * the injection. */ private final Map<String, ICreateInfo.InjectMethodRunnable> mInjectedMethodsMap; private final Map<String, ICreateInfo.InjectMethodRunnable> mInjectedMethodsMap; // A hack to do some modifications to simple month view. static final String SIMPLE_MONTH_VIEW = "android/widget/SimpleMonthView"; ClassReader mSimpleMonthViewReader; /** /** * Creates a new generator that can generate the output JAR with the stubbed classes. * Creates a new generator that can generate the output JAR with the stubbed classes. Loading Loading @@ -204,7 +207,7 @@ public class AsmGenerator { * Utility that returns the internal ASM class name from a fully qualified binary class * Utility that returns the internal ASM class name from a fully qualified binary class * name. E.g. it returns android/view/View from android.view.View. * name. E.g. it returns android/view/View from android.view.View. */ */ String binaryToInternalClassName(String className) { static String binaryToInternalClassName(String className) { if (className == null) { if (className == null) { return null; return null; } else { } else { Loading Loading @@ -380,6 +383,10 @@ public class AsmGenerator { } } } } if (SIMPLE_MONTH_VIEW.equals(className)) { cv = new SimpleMonthViewAdapter(cv); } cr.accept(cv, 0); cr.accept(cv, 0); return cw.toByteArray(); return cw.toByteArray(); } } Loading tools/layoutlib/create/src/com/android/tools/layoutlib/create/SimpleMonthViewAdapter.java 0 → 100644 +90 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2015 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.tools.layoutlib.create; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import java.text.SimpleDateFormat; import static com.android.tools.layoutlib.create.AsmGenerator.binaryToInternalClassName; /** * A very ugly hack to transform all references to {@link java.text.SimpleDateFormat} in {@code * android.widget.SimpleMonthView} to {@code com.ibm.icu.text.SimpleDateFormat}. */ public class SimpleMonthViewAdapter extends ClassVisitor { private static final String JAVA_SDF_DESC = Type.getDescriptor(SimpleDateFormat.class); private static final String JAVA_SDF_INTERNAL_NAME = binaryToInternalClassName(SimpleDateFormat.class.getName()); private static final String ICU_SDF_INTERNAL_NAME = "com/ibm/icu/text/SimpleDateFormat"; public SimpleMonthViewAdapter(ClassVisitor cv) { super(Opcodes.ASM4, cv); } @Override public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { if (JAVA_SDF_DESC.equals(desc)) { desc = "L" + ICU_SDF_INTERNAL_NAME + ";"; } return super.visitField(access, name, desc, signature, value); } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { return new MyMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions)); } private static class MyMethodVisitor extends MethodVisitor { public MyMethodVisitor(MethodVisitor mv) { super(Opcodes.ASM4, mv); } @Override public void visitTypeInsn(int opcode, String type) { if (JAVA_SDF_INTERNAL_NAME.equals(type) && opcode == Opcodes.NEW) { type = ICU_SDF_INTERNAL_NAME; } super.visitTypeInsn(opcode, type); } @Override public void visitMethodInsn(int opcode, String owner, String name, String desc) { if (JAVA_SDF_INTERNAL_NAME.equals(owner)) { owner = ICU_SDF_INTERNAL_NAME; } super.visitMethodInsn(opcode, owner, name, desc); } @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { if (JAVA_SDF_DESC.equals(desc) && (opcode == Opcodes.PUTFIELD || opcode == Opcodes.GETFIELD) && name.equals("mDayFormatter")) { desc = "L" + ICU_SDF_INTERNAL_NAME + ";"; } super.visitFieldInsn(opcode, owner, name, desc); } } } Loading
tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java +2 −0 Original line number Original line Diff line number Diff line Loading @@ -112,6 +112,8 @@ public class AsmAnalyzer { mGen.setDeps(deps); mGen.setDeps(deps); mGen.setCopyFiles(filesFound); mGen.setCopyFiles(filesFound); mGen.setRewriteMethodCallClasses(mReplaceMethodCallClasses); mGen.setRewriteMethodCallClasses(mReplaceMethodCallClasses); // hack hack hack mGen.mSimpleMonthViewReader = zipClasses.get(AsmGenerator.SIMPLE_MONTH_VIEW); } } } } Loading
tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java +8 −1 Original line number Original line Diff line number Diff line Loading @@ -77,6 +77,9 @@ public class AsmGenerator { /** Methods to inject. FQCN of class in which method should be injected => runnable that does /** Methods to inject. FQCN of class in which method should be injected => runnable that does * the injection. */ * the injection. */ private final Map<String, ICreateInfo.InjectMethodRunnable> mInjectedMethodsMap; private final Map<String, ICreateInfo.InjectMethodRunnable> mInjectedMethodsMap; // A hack to do some modifications to simple month view. static final String SIMPLE_MONTH_VIEW = "android/widget/SimpleMonthView"; ClassReader mSimpleMonthViewReader; /** /** * Creates a new generator that can generate the output JAR with the stubbed classes. * Creates a new generator that can generate the output JAR with the stubbed classes. Loading Loading @@ -204,7 +207,7 @@ public class AsmGenerator { * Utility that returns the internal ASM class name from a fully qualified binary class * Utility that returns the internal ASM class name from a fully qualified binary class * name. E.g. it returns android/view/View from android.view.View. * name. E.g. it returns android/view/View from android.view.View. */ */ String binaryToInternalClassName(String className) { static String binaryToInternalClassName(String className) { if (className == null) { if (className == null) { return null; return null; } else { } else { Loading Loading @@ -380,6 +383,10 @@ public class AsmGenerator { } } } } if (SIMPLE_MONTH_VIEW.equals(className)) { cv = new SimpleMonthViewAdapter(cv); } cr.accept(cv, 0); cr.accept(cv, 0); return cw.toByteArray(); return cw.toByteArray(); } } Loading
tools/layoutlib/create/src/com/android/tools/layoutlib/create/SimpleMonthViewAdapter.java 0 → 100644 +90 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2015 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.tools.layoutlib.create; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import java.text.SimpleDateFormat; import static com.android.tools.layoutlib.create.AsmGenerator.binaryToInternalClassName; /** * A very ugly hack to transform all references to {@link java.text.SimpleDateFormat} in {@code * android.widget.SimpleMonthView} to {@code com.ibm.icu.text.SimpleDateFormat}. */ public class SimpleMonthViewAdapter extends ClassVisitor { private static final String JAVA_SDF_DESC = Type.getDescriptor(SimpleDateFormat.class); private static final String JAVA_SDF_INTERNAL_NAME = binaryToInternalClassName(SimpleDateFormat.class.getName()); private static final String ICU_SDF_INTERNAL_NAME = "com/ibm/icu/text/SimpleDateFormat"; public SimpleMonthViewAdapter(ClassVisitor cv) { super(Opcodes.ASM4, cv); } @Override public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { if (JAVA_SDF_DESC.equals(desc)) { desc = "L" + ICU_SDF_INTERNAL_NAME + ";"; } return super.visitField(access, name, desc, signature, value); } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { return new MyMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions)); } private static class MyMethodVisitor extends MethodVisitor { public MyMethodVisitor(MethodVisitor mv) { super(Opcodes.ASM4, mv); } @Override public void visitTypeInsn(int opcode, String type) { if (JAVA_SDF_INTERNAL_NAME.equals(type) && opcode == Opcodes.NEW) { type = ICU_SDF_INTERNAL_NAME; } super.visitTypeInsn(opcode, type); } @Override public void visitMethodInsn(int opcode, String owner, String name, String desc) { if (JAVA_SDF_INTERNAL_NAME.equals(owner)) { owner = ICU_SDF_INTERNAL_NAME; } super.visitMethodInsn(opcode, owner, name, desc); } @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { if (JAVA_SDF_DESC.equals(desc) && (opcode == Opcodes.PUTFIELD || opcode == Opcodes.GETFIELD) && name.equals("mDayFormatter")) { desc = "L" + ICU_SDF_INTERNAL_NAME + ";"; } super.visitFieldInsn(opcode, owner, name, desc); } } }