upload android base code part4
This commit is contained in:
parent
b9e30e05b1
commit
78ea2404cd
23455 changed files with 5250148 additions and 0 deletions
|
@ -0,0 +1,382 @@
|
|||
/*
|
||||
* 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 dex.reader;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import dex.reader.util.JavaSource;
|
||||
import dex.structure.DexAnnotation;
|
||||
import dex.structure.DexAnnotationAttribute;
|
||||
import dex.structure.DexClass;
|
||||
import dex.structure.DexEncodedValue;
|
||||
import dex.structure.DexField;
|
||||
import dex.structure.DexFile;
|
||||
import dex.structure.DexMethod;
|
||||
import dex.structure.DexParameter;
|
||||
|
||||
|
||||
public class DexFileReaderTests extends DexTestsCommon {
|
||||
|
||||
private static final String LDALVIK_ANNOTATION_SIGNATURE = "Ldalvik/annotation/Signature;";
|
||||
|
||||
|
||||
JavaSource A = new JavaSource("a.b.c.A",
|
||||
"package a.b.c; public class A{ public void get() {}}"
|
||||
);
|
||||
|
||||
@Test
|
||||
public void testA() throws IOException {
|
||||
DexFile dexFile = javaToDexUtil.getFrom(A);
|
||||
assertEquals(1, dexFile.getDefinedClasses().size());
|
||||
@SuppressWarnings("unused")
|
||||
DexClass class1 = getClass(dexFile, "La/b/c/A;");
|
||||
System.out.println(dexFile);
|
||||
}
|
||||
|
||||
|
||||
JavaSource T0 = new JavaSource("T0",
|
||||
"public class T0 {" +
|
||||
" public int publicIntField;" +
|
||||
" protected long protectedLongField;" +
|
||||
" short defaultShortField;" +
|
||||
" private double privateDoubleField;" +
|
||||
" " +
|
||||
" public String publicStringMethodInt(int a){ return \"bla\"; }" +
|
||||
" protected String protectedStringMethodInt(int a){ return \"bla\"; }" +
|
||||
" String defaultStringMethodInt(int a){ return \"bla\"; }" +
|
||||
" private String privateStringMethodInt(int a){ return \"bla\"; }" +
|
||||
"}"
|
||||
);
|
||||
|
||||
/**
|
||||
* Tests parsing a simple class.
|
||||
*/
|
||||
@Test
|
||||
public void testT0() throws IOException {
|
||||
|
||||
DexFile dexFile = javaToDexUtil.getFrom(T0);
|
||||
assertEquals(1, dexFile.getDefinedClasses().size());
|
||||
DexClass clazz = dexFile.getDefinedClasses().get(0);
|
||||
assertEquals("LT0;", clazz.getName());
|
||||
assertPublic(clazz);
|
||||
//fields
|
||||
assertEquals(4, clazz.getFields().size());
|
||||
DexField field = getField(clazz, "publicIntField");
|
||||
assertPublic(field);
|
||||
field = getField(clazz, "protectedLongField");
|
||||
assertProtected(field);
|
||||
field = getField(clazz, "defaultShortField");
|
||||
assertDefault(field);
|
||||
field = getField(clazz, "privateDoubleField");
|
||||
assertPrivate(field);
|
||||
//methods
|
||||
DexMethod method = getMethod(clazz, "publicStringMethodInt", "I");
|
||||
assertPublic(method);
|
||||
method = getMethod(clazz, "protectedStringMethodInt", "I");/** a.b.C */
|
||||
assertProtected(method);
|
||||
method = getMethod(clazz, "defaultStringMethodInt", "I");
|
||||
assertDefault(method);
|
||||
method = getMethod(clazz, "privateStringMethodInt", "I");
|
||||
assertPrivate(method);
|
||||
}
|
||||
|
||||
JavaSource T1 = new JavaSource( "T1","public class T1 extends T0 {}" );
|
||||
|
||||
|
||||
private static Set<JavaSource> toSet(JavaSource...javaSources){
|
||||
return new HashSet<JavaSource>(Arrays.asList(javaSources));
|
||||
}
|
||||
|
||||
private static Set<String> toStringSet(JavaSource... javaSources) {
|
||||
Set<String> names = new HashSet<String>();
|
||||
for (JavaSource javaSource : javaSources) {
|
||||
names.add(javaSource.getName());
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
private static Set<String> toStringSet(String... javaSourceName) {
|
||||
return new HashSet<String>(Arrays.asList(javaSourceName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests parsing a simple sub class.
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testT1() throws IOException {
|
||||
DexFile dexFile = javaToDexUtil.getFrom(toSet(T1, T0), toStringSet(T1));
|
||||
assertEquals(1, dexFile.getDefinedClasses().size());
|
||||
DexClass clazz = dexFile.getDefinedClasses().get(0);
|
||||
assertEquals("LT1;", clazz.getName());
|
||||
assertPublic(clazz);
|
||||
assertEquals("LT0;", clazz.getSuperClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests parsing T0 and T1 from same dex file.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testT0_T1() throws IOException {
|
||||
DexFile dexFile = javaToDexUtil.getFrom(T1, T0);
|
||||
assertEquals(2, dexFile.getDefinedClasses().size());
|
||||
|
||||
DexClass T0 = getClass(dexFile, "LT0;");
|
||||
assertPublic(T0);
|
||||
|
||||
DexClass T1 = getClass(dexFile, "LT1;");
|
||||
assertPublic(T1);
|
||||
|
||||
assertEquals(T1.getSuperClass(), T0.getName());
|
||||
}
|
||||
|
||||
static final JavaSource A0 = new JavaSource("A0",
|
||||
"import java.lang.annotation.*;" +
|
||||
"@Retention(RetentionPolicy.RUNTIME)" +
|
||||
"@Target(ElementType.TYPE)" +
|
||||
"public @interface A0 {}"
|
||||
);
|
||||
|
||||
/**
|
||||
* Tests parsing Annotation Declaration.
|
||||
*/
|
||||
@Test
|
||||
public void testA0() throws IOException {
|
||||
DexFile dexFile = javaToDexUtil.getFrom(A0);
|
||||
assertEquals(1, dexFile.getDefinedClasses().size());
|
||||
|
||||
DexClass A0 = getClass(dexFile, "LA0;");
|
||||
assertPublic(A0);
|
||||
assertEquals(2, A0.getAnnotations().size());
|
||||
}
|
||||
|
||||
|
||||
static final JavaSource T3 = new JavaSource("T3",
|
||||
"import java.io.*;" +
|
||||
"@A0 " +
|
||||
"public final class T3 {}"
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Tests parsing Annotated Class.
|
||||
*/
|
||||
@Test
|
||||
public void testA0_T3() throws IOException {
|
||||
DexFile dexFile = javaToDexUtil.getFrom(T3, A0);
|
||||
assertEquals(2, dexFile.getDefinedClasses().size());
|
||||
|
||||
DexClass T3 = getClass(dexFile, "LT3;");
|
||||
assertPublic(T3);
|
||||
assertEquals(1, T3.getAnnotations().size());
|
||||
|
||||
DexAnnotation annotation = getAnnotation(T3, "LA0;");
|
||||
|
||||
DexClass A0 = getClass(dexFile, "LA0;");
|
||||
|
||||
assertEquals(A0.getName(), annotation.getTypeName());
|
||||
}
|
||||
|
||||
|
||||
static final JavaSource G0 = new JavaSource("G0","public class G0<T>{}");
|
||||
|
||||
/**
|
||||
* Tests parsing Generic Type.
|
||||
*/
|
||||
@Test
|
||||
public void testG0() throws IOException {
|
||||
DexFile dexFile = javaToDexUtil.getFrom(G0);
|
||||
assertEquals(1, dexFile.getDefinedClasses().size());
|
||||
DexClass G0 = getClass(dexFile, "LG0;");
|
||||
assertPublic(G0);
|
||||
DexAnnotation sig = getAnnotation(G0, LDALVIK_ANNOTATION_SIGNATURE);
|
||||
assertEquals(1, sig.getAttributes().size());
|
||||
DexAnnotationAttribute dexAnnotationValue = sig.getAttributes().get(0);
|
||||
assertNotNull(dexAnnotationValue.getEncodedValue());
|
||||
Object value = dexAnnotationValue.getEncodedValue().getValue();
|
||||
assertTrue(value instanceof List);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (Object o : (List<?>)value) {
|
||||
builder.append(((DexEncodedValue)o).getValue());
|
||||
}
|
||||
//FIXME verify
|
||||
assertEquals("<T:Ljava/lang/Object;>Ljava/lang/Object;", builder.toString());
|
||||
}
|
||||
|
||||
static final JavaSource G1 = new JavaSource("G1","public class G1<T extends G1>{}");
|
||||
|
||||
/**
|
||||
* Tests parsing Generic Type.
|
||||
*/
|
||||
@Test
|
||||
public void testG1() throws IOException {
|
||||
DexFile dexFile = javaToDexUtil.getFrom(G1);
|
||||
assertEquals(1, dexFile.getDefinedClasses().size());
|
||||
DexClass G1 = getClass(dexFile, "LG1;");
|
||||
assertPublic(G1);
|
||||
DexAnnotation sig = getAnnotation(G1, LDALVIK_ANNOTATION_SIGNATURE);
|
||||
assertEquals(1, sig.getAttributes().size());
|
||||
DexAnnotationAttribute dexAnnotationValue = sig.getAttributes().get(0);
|
||||
assertNotNull(dexAnnotationValue.getEncodedValue());
|
||||
Object value = dexAnnotationValue.getEncodedValue().getValue();
|
||||
assertTrue(value instanceof List);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (Object o : (List<?>)value) {
|
||||
builder.append(((DexEncodedValue)o).getValue());
|
||||
}
|
||||
//FIXME verify
|
||||
assertEquals("<T:LG1;>Ljava/lang/Object;", builder.toString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
static final JavaSource I0 = new JavaSource("I0",
|
||||
"import java.io.Serializable;" +
|
||||
"public interface I0 extends Serializable {}"
|
||||
);
|
||||
|
||||
/**
|
||||
* Tests parsing Interface Type.
|
||||
*/
|
||||
@Test
|
||||
public void testI0() throws IOException {
|
||||
DexFile dexFile = javaToDexUtil.getFrom(I0);
|
||||
assertEquals(1, dexFile.getDefinedClasses().size());
|
||||
DexClass I0 = getClass(dexFile, "LI0;");
|
||||
assertPublic(I0);
|
||||
assertTrue(Modifier.isInterface(I0.getModifiers()));
|
||||
assertEquals(1, I0.getInterfaces().size());
|
||||
assertEquals("Ljava/io/Serializable;", I0.getInterfaces().get(0));
|
||||
}
|
||||
|
||||
|
||||
static final JavaSource Outer0 = new JavaSource("Outer0",
|
||||
"public class Outer0 {" +
|
||||
" static class StaticInner {}" +
|
||||
" class Inner{}" +
|
||||
"}"
|
||||
);
|
||||
|
||||
/**
|
||||
* Tests parsing Interface Type.
|
||||
* @throws IOException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testOuter0() throws IOException {
|
||||
DexFile dexFile = javaToDexUtil.getFrom(toSet(Outer0), toStringSet("Outer0", "Outer0$Inner", "Outer0$StaticInner"));
|
||||
assertEquals(3, dexFile.getDefinedClasses().size());
|
||||
DexClass Outer0 = getClass(dexFile, "LOuter0;");
|
||||
DexAnnotation sig = getAnnotation(Outer0, "Ldalvik/annotation/MemberClasses;");
|
||||
assertEquals(1, sig.getAttributes().size());
|
||||
DexAnnotationAttribute dexAnnotationValue = sig.getAttributes().get(0);
|
||||
assertNotNull(dexAnnotationValue.getEncodedValue());
|
||||
List<DexEncodedValue> values = (List<DexEncodedValue>) dexAnnotationValue.getEncodedValue().getValue();
|
||||
Set<String> innerTypeNames = new HashSet<String>();
|
||||
for (DexEncodedValue value : values) {
|
||||
innerTypeNames.add((String) value.getValue());
|
||||
}
|
||||
DexClass inner = getClass(dexFile, "LOuter0$Inner;");
|
||||
DexClass staticInner = getClass(dexFile, "LOuter0$StaticInner;");
|
||||
assertTrue(innerTypeNames.contains(inner.getName()));
|
||||
assertTrue(innerTypeNames.contains(staticInner.getName()));
|
||||
}
|
||||
|
||||
static final JavaSource parameterAnnotation = new JavaSource("A",
|
||||
"public class A {" +
|
||||
" void m(@Deprecated int a) {}" +
|
||||
"}");
|
||||
|
||||
/**
|
||||
* Tests parameter annotation.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testParameterAnnotation() throws IOException {
|
||||
DexFile dexFile = javaToDexUtil.getFrom(parameterAnnotation);
|
||||
assertEquals(1, dexFile.getDefinedClasses().size());
|
||||
DexClass A = getClass(dexFile, "LA;");
|
||||
|
||||
DexMethod method = getMethod(A, "m", "I");
|
||||
assertEquals(1, method.getParameters().size());
|
||||
DexParameter dexParameter = method.getParameters().get(0);
|
||||
assertEquals("I", dexParameter.getTypeName());
|
||||
|
||||
assertEquals(1, dexParameter.getAnnotations().size());
|
||||
DexAnnotation annotation = dexParameter.getAnnotations().iterator().next();
|
||||
assertEquals("Ljava/lang/Deprecated;", annotation.getTypeName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnum() throws IOException {
|
||||
JavaSource source = new JavaSource("E", "public enum E { A,B; public static final E C = null; }");
|
||||
DexFile dexFile = javaToDexUtil.getFrom(source);
|
||||
assertEquals(1, dexFile.getDefinedClasses().size());
|
||||
DexClass E = getClass(dexFile, "LE;");
|
||||
System.out.println(E);
|
||||
System.out.println(E.getFields());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests parsing of huge dex file.
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testAllReader() throws IOException {
|
||||
FileWriter w = new FileWriter("dex/classes.out.dex");
|
||||
DexFileReader dexReader = new DexFileReader();
|
||||
DexFile dexFile = dexReader.read(new DexBuffer("dex/classes.dex"));
|
||||
TypeFormatter formatter = new TypeFormatter();
|
||||
w.append(formatter.formatDexFile(dexFile));
|
||||
w.flush();
|
||||
w.close();
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests parsing of huge dex file.
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testAllReader0() throws IOException {
|
||||
FileWriter w = new FileWriter("dex/classes0.out.dex");
|
||||
DexFileReader dexReader = new DexFileReader();
|
||||
DexFile dexFile = dexReader.read(new DexBuffer("dex/classes0.dex"));
|
||||
TypeFormatter formatter = new TypeFormatter();
|
||||
w.append(formatter.formatDexFile(dexFile));
|
||||
w.flush();
|
||||
w.close();
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
}
|
151
android/cts/tools/dex-tools/test/dex/reader/DexTestsCommon.java
Normal file
151
android/cts/tools/dex-tools/test/dex/reader/DexTestsCommon.java
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* 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 dex.reader;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import dex.reader.util.JavaSourceToDexUtil;
|
||||
import dex.structure.DexAnnotatedElement;
|
||||
import dex.structure.DexAnnotation;
|
||||
import dex.structure.DexClass;
|
||||
import dex.structure.DexField;
|
||||
import dex.structure.DexFile;
|
||||
import dex.structure.DexMethod;
|
||||
import dex.structure.DexParameter;
|
||||
import dex.structure.WithModifiers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class DexTestsCommon {
|
||||
|
||||
protected JavaSourceToDexUtil javaToDexUtil;
|
||||
|
||||
@Before
|
||||
public void initializeJavaToDexUtil() {
|
||||
javaToDexUtil = new JavaSourceToDexUtil();
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdownJavaToDexUtil() {
|
||||
javaToDexUtil = null;
|
||||
}
|
||||
|
||||
public static void assertPublic(WithModifiers withMod) {
|
||||
assertTrue(Modifier.isPublic(withMod.getModifiers()));
|
||||
assertFalse(Modifier.isPrivate(withMod.getModifiers())
|
||||
|| Modifier.isProtected(withMod.getModifiers()));
|
||||
}
|
||||
|
||||
public static void assertProtected(WithModifiers withMod) {
|
||||
assertTrue(Modifier.isProtected(withMod.getModifiers()));
|
||||
assertFalse(Modifier.isPrivate(withMod.getModifiers())
|
||||
|| Modifier.isPublic(withMod.getModifiers()));
|
||||
}
|
||||
|
||||
public static void assertPrivate(WithModifiers withMod) {
|
||||
assertTrue(Modifier.isPrivate(withMod.getModifiers()));
|
||||
assertFalse(Modifier.isProtected(withMod.getModifiers())
|
||||
|| Modifier.isPublic(withMod.getModifiers()));
|
||||
}
|
||||
|
||||
public static void assertDefault(WithModifiers withMod) {
|
||||
assertFalse(Modifier.isPrivate(withMod.getModifiers())
|
||||
|| Modifier.isProtected(withMod.getModifiers())
|
||||
|| Modifier.isPublic(withMod.getModifiers()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a dex file from the specified file.
|
||||
*
|
||||
* @param fileName the name of the file to read
|
||||
* @return the dex file
|
||||
* @throws IOException if the file is not accessible
|
||||
*/
|
||||
protected DexFile prepareDexFile(String fileName) throws IOException{
|
||||
DexFileReader dexReader = new DexFileReader();
|
||||
return dexReader.read(new DexBuffer(fileName));
|
||||
}
|
||||
|
||||
protected DexClass getClass(DexFile file, String className) {
|
||||
assertNotNull(file);
|
||||
assertNotNull(className);
|
||||
for (DexClass clazz : file.getDefinedClasses()) {
|
||||
if(className.equals(clazz.getName())){
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
fail("Class: " + className +" not present in file: " + file.getName());
|
||||
throw new IllegalArgumentException("Class: " + className +" not present in file: " + file.getName());
|
||||
}
|
||||
|
||||
protected DexField getField(DexClass clazz, String fieldName) {
|
||||
assertNotNull(clazz);
|
||||
assertNotNull(fieldName);
|
||||
for (DexField field : clazz.getFields()) {
|
||||
if(fieldName.equals(field.getName())){
|
||||
return field;
|
||||
}
|
||||
}
|
||||
fail("Field: " + fieldName +" not present in class: " + clazz.getName());
|
||||
throw new IllegalArgumentException("Field: " + fieldName +" not present in class: " + clazz.getName());
|
||||
}
|
||||
|
||||
protected DexAnnotation getAnnotation(DexAnnotatedElement element, String annotationType) {
|
||||
assertNotNull(element);
|
||||
assertNotNull(annotationType);
|
||||
for (DexAnnotation anno : element.getAnnotations()) {
|
||||
if(annotationType.equals(anno.getTypeName())){
|
||||
return anno;
|
||||
}
|
||||
}
|
||||
fail("Annotation: " + annotationType +" not present in Element.");
|
||||
throw new IllegalArgumentException("Annotation: " + annotationType +" not present in Element.");
|
||||
}
|
||||
|
||||
protected DexMethod getMethod(DexClass clazz, String methodName, String... typeNames) {
|
||||
assertNotNull(clazz);
|
||||
assertNotNull(methodName);
|
||||
List<String> paramTypeNames = Arrays.asList(typeNames);
|
||||
for (DexMethod method : clazz.getMethods()) {
|
||||
List<String> methodsParamTypeNames = getParamTypeNames(method.getParameters());
|
||||
if(methodName.equals(method.getName()) && paramTypeNames.equals(methodsParamTypeNames)){
|
||||
return method;
|
||||
}
|
||||
}
|
||||
fail("Method: " + methodName +" not present in class: " + clazz.getName());
|
||||
throw new IllegalArgumentException("Method: " + methodName +" not present in class: " + clazz.getName());
|
||||
}
|
||||
|
||||
private List<String> getParamTypeNames(List<DexParameter> parameters) {
|
||||
List<String> paramTypeNames = new LinkedList<String>();
|
||||
for (DexParameter parameter : parameters) {
|
||||
paramTypeNames.add(parameter.getTypeName());
|
||||
}
|
||||
return paramTypeNames;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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 dex.reader;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import dex.reader.util.JavaSource;
|
||||
import dex.structure.DexClass;
|
||||
import dex.structure.DexFile;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class LargeDexTests extends DexTestsCommon{
|
||||
|
||||
/**
|
||||
* Tests parsing a class with 10000 Fields.
|
||||
*/
|
||||
@Test
|
||||
public void testManyFields() throws IOException{
|
||||
String CLASS_NAME = "L0";
|
||||
int NR_OF_FIELDS = 10000;
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append("public class ").append(CLASS_NAME).append("{\n");
|
||||
for (int i = 0; i < NR_OF_FIELDS; i++) {
|
||||
b.append("\tpublic int f").append(i).append(";\n");
|
||||
}
|
||||
b.append("}\n");
|
||||
|
||||
JavaSource source = new JavaSource(CLASS_NAME, b.toString());
|
||||
DexFile dexFile = javaToDexUtil.getFrom(source);
|
||||
assertEquals(1, dexFile.getDefinedClasses().size());
|
||||
DexClass clazz = dexFile.getDefinedClasses().get(0);
|
||||
assertEquals("LL0;", clazz.getName());
|
||||
assertPublic(clazz);
|
||||
assertEquals(NR_OF_FIELDS, clazz.getFields().size());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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 dex.reader.util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
|
||||
/**
|
||||
* {@code JavaSource} represents an in-memory java source.
|
||||
*/
|
||||
public class JavaSource extends SimpleJavaFileObject {
|
||||
private String src;
|
||||
private final String sourceName;
|
||||
|
||||
public JavaSource(String sourceName, String sourceCode) {
|
||||
super(URI.create("string:///" + sourceName.replace(".", "/") + ".java"),
|
||||
Kind.SOURCE);
|
||||
this.sourceName = sourceName;
|
||||
this.src = sourceCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return sourceName;
|
||||
}
|
||||
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
||||
return src;
|
||||
}
|
||||
|
||||
public OutputStream openOutputStream() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
public InputStream openInputStream() {
|
||||
return new ByteArrayInputStream(src.getBytes());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* 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 dex.reader.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.DiagnosticCollector;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
import javax.tools.ToolProvider;
|
||||
import javax.tools.JavaCompiler.CompilationTask;
|
||||
|
||||
import com.android.dx.dex.cf.CfOptions;
|
||||
import com.android.dx.dex.cf.CfTranslator;
|
||||
import com.android.dx.dex.file.ClassDefItem;
|
||||
import com.android.dx.dex.file.DexFile;
|
||||
|
||||
import dex.reader.DexBuffer;
|
||||
import dex.reader.DexFileReader;
|
||||
|
||||
public class JavaSourceToDexUtil {
|
||||
|
||||
public dex.structure.DexFile getFrom(JavaSource source) throws IOException{
|
||||
return getAllFrom(Collections.singleton(source));
|
||||
}
|
||||
|
||||
public dex.structure.DexFile getFrom(JavaSource... source) throws IOException{
|
||||
return getAllFrom(new HashSet<JavaSource>(Arrays.asList(source)));
|
||||
}
|
||||
|
||||
public dex.structure.DexFile getAllFrom(Set<JavaSource> sources) throws IOException{
|
||||
return getFrom(sources, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts java source code to a {@link dex.structure.DexFile} loaded by
|
||||
* {@link DexFileReader}. Converts only classes with the specified name in
|
||||
* classesToDex or all classes if classesToDex is null.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public dex.structure.DexFile getFrom(Set<JavaSource> sources,
|
||||
Set<String> classesToDex) throws IOException {
|
||||
Set<MemoryByteCode> byteCodeInMemory = compileToByteCode(sources);
|
||||
|
||||
byte[] dexCode = convertToDexCode(byteCodeInMemory, classesToDex);
|
||||
DexBuffer dexBuffer = new DexBuffer(dexCode);
|
||||
DexFileReader reader = new DexFileReader();
|
||||
return reader.read(dexBuffer);
|
||||
}
|
||||
|
||||
|
||||
private byte[] convertToDexCode(Set<MemoryByteCode> byteCodeInMemory, Set<String> classNamesToDex) throws IOException {
|
||||
CfOptions cfOptions = new CfOptions();
|
||||
DexFile dexFile = new DexFile();
|
||||
for (MemoryByteCode memoryByteCode : byteCodeInMemory) {
|
||||
if(classNamesToDex == null || classNamesToDex.contains(memoryByteCode.getName())) {
|
||||
ClassDefItem classDefItem = CfTranslator.translate(memoryByteCode.getName().replace('.', '/') +".class", memoryByteCode.getBytes(), cfOptions);
|
||||
dexFile.add(classDefItem);
|
||||
}
|
||||
}
|
||||
return dexFile.toDex(null, false);
|
||||
}
|
||||
|
||||
|
||||
public Set<MemoryByteCode> compileToByteCode(Set<JavaSource> source) {
|
||||
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
|
||||
DiagnosticCollector<JavaFileObject> diacol = new DiagnosticCollector<JavaFileObject>();
|
||||
StandardJavaFileManager sjfm = javac.getStandardFileManager(diacol,
|
||||
null, null);
|
||||
SpecialJavaFileManager xfm = new SpecialJavaFileManager(sjfm);
|
||||
|
||||
CompilationTask compile = javac.getTask(null, xfm, diacol, Arrays
|
||||
.asList(new String[] {"-classpath", "."}), null, source);
|
||||
boolean success = compile.call();
|
||||
if(!success) {
|
||||
StringBuilder errorMessage = new StringBuilder();
|
||||
for (Diagnostic<? extends JavaFileObject> dia : diacol.getDiagnostics()) {
|
||||
errorMessage.append(dia);
|
||||
}
|
||||
throw new IllegalStateException(errorMessage.toString());
|
||||
}
|
||||
return xfm.getAllMemoryByteCodes();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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 dex.reader.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
|
||||
/**
|
||||
* {@code MemoryByteCode} represents an in-memory java byte code.
|
||||
*/
|
||||
/* package */ class MemoryByteCode extends SimpleJavaFileObject {
|
||||
private ByteArrayOutputStream baos;
|
||||
private final String name;
|
||||
|
||||
public MemoryByteCode(String name) {
|
||||
super(URI.create("byte:///" + name.replace(".", "/") + ".class"),
|
||||
Kind.CLASS);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
public OutputStream openOutputStream() {
|
||||
baos = new ByteArrayOutputStream();
|
||||
return baos;
|
||||
}
|
||||
|
||||
public InputStream openInputStream() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return baos.toByteArray();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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 dex.reader.util;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.ForwardingJavaFileManager;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
|
||||
/**
|
||||
* {@code SpecialJavaFileManager} is a file manager which returns
|
||||
* {@link MemoryByteCode} objects for its output and keeps track of them.
|
||||
*/
|
||||
/* package */ class SpecialJavaFileManager extends
|
||||
ForwardingJavaFileManager<StandardJavaFileManager> {
|
||||
|
||||
private Map<String, MemoryByteCode> store;
|
||||
|
||||
public SpecialJavaFileManager(StandardJavaFileManager sjfm) {
|
||||
super(sjfm);
|
||||
store = new HashMap<String, MemoryByteCode>();
|
||||
}
|
||||
|
||||
public JavaFileObject getJavaFileForOutput(Location location, String name,
|
||||
JavaFileObject.Kind kind, FileObject sibling) {
|
||||
MemoryByteCode mbc = new MemoryByteCode(name);
|
||||
store.put(name, mbc);
|
||||
return mbc;
|
||||
}
|
||||
|
||||
public Set<MemoryByteCode> getAllMemoryByteCodes() {
|
||||
return new HashSet<MemoryByteCode>(store.values());
|
||||
}
|
||||
|
||||
public MemoryByteCode getMemoryByteCode(String className) {
|
||||
return store.get(className);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue