1010import java .io .InputStreamReader ;
1111import java .io .InvalidClassException ;
1212import java .io .OutputStreamWriter ;
13+ import java .util .ArrayList ;
1314import java .util .HashMap ;
1415import java .util .HashSet ;
16+ import java .util .List ;
1517import java .util .zip .ZipEntry ;
1618import java .util .zip .ZipOutputStream ;
1719
2426import dalvik .system .DexFile ;
2527
2628public class DexFactory {
27- private static final char CLASS_NAME_LOCATION_SEPARATOR = '_' ;
29+ private static final String COM_TNS_GEN_PREFIX = "com.tns.gen." ;
2830
2931 private final Logger logger ;
3032 private final File dexDir ;
@@ -61,8 +63,9 @@ public DexFactory(Logger logger, ClassLoader classLoader, File dexBaseDir, Strin
6163 static long totalMultiDexTime = 0 ;
6264 static long totalLoadDexTime = 0 ;
6365
64- public Class <?> resolveClass (String name , String className , String [] methodOverrides , String [] implementedInterfaces , boolean isInterface ) throws ClassNotFoundException , IOException {
66+ public Class <?> resolveClass (String baseClassName , String name , String className , String [] methodOverrides , String [] implementedInterfaces , boolean isInterface ) throws ClassNotFoundException , IOException {
6567 String fullClassName = className .replace ("$" , "_" );
68+ String originalFullClassName = fullClassName ;
6669
6770 // try to get pre-generated binding classes
6871 try {
@@ -84,19 +87,31 @@ public Class<?> resolveClass(String name, String className, String[] methodOverr
8487 }
8588 //
8689
90+ // new: com.tns.gen.android.widget.DatePicker_MyActivity_59_56_
91+ // old: com.tns.tests.Button1_fMyActivity_l56_c44__MyButton
92+ // ne1: com.tns.tests.Button1_MyActivity_58_44_MyButton_0
8793 Class <?> existingClass = this .injectedDexClasses .get (fullClassName );
8894 if (existingClass != null ) {
8995 return existingClass ;
9096 }
9197
92- String classToProxy = this .getClassToProxyName (className );
93- String dexFilePath = classToProxy ;
98+ String classToProxy ;
99+ if (!baseClassName .isEmpty ()) {
100+ classToProxy = this .getClassToProxyName (baseClassName );
101+ } else {
102+ classToProxy = this .getClassToProxyName (className );
103+ }
94104
95- if (!isInterface ) {
96- dexFilePath += CLASS_NAME_LOCATION_SEPARATOR + name ;
105+ // strip the `com.tns.gen` off the base extended class name
106+ String desiredDexClassName = this .getClassToProxyName (fullClassName );
107+
108+ // when interfaces are extended as classes, we still want to preserve
109+ // just the interface name without the extra file, line, column information
110+ if (!baseClassName .isEmpty () && isInterface ) {
111+ fullClassName = COM_TNS_GEN_PREFIX + classToProxy ;
97112 }
98113
99- File dexFile = this .getDexFile (dexFilePath );
114+ File dexFile = this .getDexFile (desiredDexClassName );
100115
101116 // generate dex file
102117 if (dexFile == null ) {
@@ -105,7 +120,12 @@ public Class<?> resolveClass(String name, String className, String[] methodOverr
105120 logger .write ("generating proxy in place" );
106121 }
107122
108- dexFilePath = this .generateDex (name , classToProxy , methodOverrides , implementedInterfaces , isInterface );
123+ String dexFilePath ;
124+ if (isInterface ) {
125+ dexFilePath = this .generateDex (name , classToProxy , methodOverrides , implementedInterfaces , isInterface );
126+ } else {
127+ dexFilePath = this .generateDex (desiredDexClassName , classToProxy , methodOverrides , implementedInterfaces , isInterface );
128+ }
109129 dexFile = new File (dexFilePath );
110130 long stopGenTime = System .nanoTime ();
111131 totalGenTime += stopGenTime - startGenTime ;
@@ -145,16 +165,21 @@ public Class<?> resolveClass(String name, String className, String[] methodOverr
145165 // However, this is the only viable way to get our dynamic classes
146166 // loaded within the system class loader
147167
148- df = DexFile .loadDex (jarFilePath , new File (this .odexDir , fullClassName ).getAbsolutePath (), 0 );
149- result = df .loadClass (fullClassName , classLoader );
168+ if (isInterface ) {
169+ df = DexFile .loadDex (jarFilePath , new File (this .odexDir , fullClassName ).getAbsolutePath (), 0 );
170+ result = df .loadClass (fullClassName , classLoader );
171+ } else {
172+ df = DexFile .loadDex (jarFilePath , new File (this .odexDir , desiredDexClassName ).getAbsolutePath (), 0 );
173+ result = df .loadClass (desiredDexClassName , classLoader );
174+ }
150175 } catch (IOException e ) {
151176 e .printStackTrace ();
152177 // fall back to DexClassLoader
153178 DexClassLoader dexClassLoader = new DexClassLoader (jarFilePath , this .odexDir .getAbsolutePath (), null , classLoader );
154179 result = dexClassLoader .loadClass (fullClassName );
155180 }
156181
157- this .injectedDexClasses .put (fullClassName , result );
182+ this .injectedDexClasses .put (originalFullClassName , result );
158183
159184 return result ;
160185 }
@@ -191,11 +216,11 @@ public static String strJoin(String[] array, String separator) {
191216 private String getClassToProxyName (String className ) throws InvalidClassException {
192217 String classToProxy = className ;
193218
194- if (className .startsWith ("com.tns.gen." )) {
219+ if (className .startsWith (COM_TNS_GEN_PREFIX )) {
195220 classToProxy = className .substring (12 );
196221 }
197222
198- if (classToProxy .startsWith ("com.tns.gen." )) {
223+ if (classToProxy .startsWith (COM_TNS_GEN_PREFIX )) {
199224 throw new InvalidClassException ("Can't generate proxy of proxy" );
200225 }
201226
0 commit comments