summaryrefslogtreecommitdiffstats
path: root/dx/src/com/android/dx/gen/DexGenerator.java
diff options
context:
space:
mode:
Diffstat (limited to 'dx/src/com/android/dx/gen/DexGenerator.java')
-rw-r--r--dx/src/com/android/dx/gen/DexGenerator.java281
1 files changed, 0 insertions, 281 deletions
diff --git a/dx/src/com/android/dx/gen/DexGenerator.java b/dx/src/com/android/dx/gen/DexGenerator.java
deleted file mode 100644
index 56c516b0c..000000000
--- a/dx/src/com/android/dx/gen/DexGenerator.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (C) 2011 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.dx.gen;
-
-import static com.android.dx.rop.code.AccessFlags.ACC_CONSTRUCTOR;
-import static com.android.dx.rop.code.AccessFlags.ACC_PRIVATE;
-import static com.android.dx.rop.code.AccessFlags.ACC_STATIC;
-
-import com.android.dx.dex.DexFormat;
-import com.android.dx.dex.DexOptions;
-import com.android.dx.dex.code.DalvCode;
-import com.android.dx.dex.code.PositionList;
-import com.android.dx.dex.code.RopTranslator;
-import com.android.dx.dex.file.ClassDefItem;
-import com.android.dx.dex.file.DexFile;
-import com.android.dx.dex.file.EncodedField;
-import com.android.dx.dex.file.EncodedMethod;
-import com.android.dx.rop.code.AccessFlags;
-import com.android.dx.rop.code.LocalVariableInfo;
-import com.android.dx.rop.code.RopMethod;
-import com.android.dx.rop.cst.CstString;
-import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.type.StdTypeList;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.jar.JarEntry;
-import java.util.jar.JarOutputStream;
-
-/**
- * Define types, fields and methods.
- */
-public final class DexGenerator {
- private final Map<Type<?>, TypeDeclaration> types
- = new LinkedHashMap<Type<?>, TypeDeclaration>();
-
- private TypeDeclaration getTypeDeclaration(Type<?> type) {
- TypeDeclaration result = types.get(type);
- if (result == null) {
- result = new TypeDeclaration(type);
- types.put(type, result);
- }
- return result;
- }
-
- /**
- * @param flags any flags masked by {@link com.android.dx.rop.code.AccessFlags#CLASS_FLAGS}.
- */
- public void declare(Type<?> type, String sourceFile, int flags,
- Type<?> supertype, Type<?>... interfaces) {
- TypeDeclaration declaration = getTypeDeclaration(type);
- if (declaration.declared) {
- throw new IllegalStateException("already declared: " + type);
- }
- declaration.declared = true;
- declaration.flags = flags;
- declaration.supertype = supertype;
- declaration.sourceFile = sourceFile;
- declaration.interfaces = new TypeList(interfaces);
- }
-
- /**
- * @param flags any flags masked by {@link com.android.dx.rop.code.AccessFlags#METHOD_FLAGS}.
- */
- public Code declare(MethodId<?, ?> method, int flags) {
- TypeDeclaration typeDeclaration = getTypeDeclaration(method.declaringType);
- if (typeDeclaration.methods.containsKey(method)) {
- throw new IllegalStateException("already declared: " + method);
- }
- MethodDeclaration methodDeclaration = new MethodDeclaration(method, flags);
- typeDeclaration.methods.put(method, methodDeclaration);
- return methodDeclaration.code;
- }
-
- /**
- * @param flags any flags masked by {@link AccessFlags#FIELD_FLAGS}.
- */
- public void declare(FieldId<?, ?> fieldId, int flags, Object staticValue) {
- TypeDeclaration typeDeclaration = getTypeDeclaration(fieldId.declaringType);
- if (typeDeclaration.fields.containsKey(fieldId)) {
- throw new IllegalStateException("already declared: " + fieldId);
- }
- FieldDeclaration fieldDeclaration = new FieldDeclaration(fieldId, flags, staticValue);
- typeDeclaration.fields.put(fieldId, fieldDeclaration);
- }
-
- /**
- * Returns a .dex formatted file.
- */
- public byte[] generate() {
- DexOptions options = new DexOptions();
- options.targetApiLevel = DexFormat.API_NO_EXTENDED_OPCODES;
- DexFile outputDex = new DexFile(options);
-
- for (TypeDeclaration typeDeclaration : types.values()) {
- outputDex.add(typeDeclaration.toClassDefItem());
- }
-
- try {
- return outputDex.toDex(null, false);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Loads the generated types into the current process.
- *
- * <p>All parameters are optional, you may pass {@code null} and suitable
- * defaults will be used.
- *
- * <p>If you opt to provide your own output directories, take care to
- * ensure that they are not world-readable, otherwise a malicious app will
- * be able to inject code to run. A suitable parameter for these output
- * directories would be something like this:
- * {@code getApplicationContext().getDir("dx", Context.MODE_PRIVATE); }
- *
- * @param parent the parent ClassLoader to be used when loading
- * our generated types
- * @param dexOutputDir the destination directory wherein we will write
- * emitted .dex files before they end up in the cache directory
- * @param dexOptCacheDir where optimized .dex files are to be written
- */
- public ClassLoader load(ClassLoader parent, File dexOutputDir, File dexOptCacheDir)
- throws IOException {
- byte[] dex = generate();
-
- /*
- * This implementation currently dumps the dex to the filesystem. It
- * jars the emitted .dex for the benefit of Gingerbread and earlier
- * devices, which can't load .dex files directly.
- *
- * TODO: load the dex from memory where supported.
- */
- File result = File.createTempFile("Generated", ".jar", dexOutputDir);
- result.deleteOnExit();
- JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(result));
- jarOut.putNextEntry(new JarEntry(DexFormat.DEX_IN_JAR_NAME));
- jarOut.write(dex);
- jarOut.closeEntry();
- jarOut.close();
- try {
- return (ClassLoader) Class.forName("dalvik.system.DexClassLoader")
- .getConstructor(String.class, String.class, String.class, ClassLoader.class)
- .newInstance(result.getPath(), dexOptCacheDir.getAbsolutePath(), null, parent);
- } catch (ClassNotFoundException e) {
- throw new UnsupportedOperationException("load() requires a Dalvik VM", e);
- } catch (InvocationTargetException e) {
- throw new RuntimeException(e.getCause());
- } catch (InstantiationException e) {
- throw new AssertionError();
- } catch (NoSuchMethodException e) {
- throw new AssertionError();
- } catch (IllegalAccessException e) {
- throw new AssertionError();
- }
- }
-
- private static class TypeDeclaration {
- private final Type<?> type;
-
- /** declared state */
- private boolean declared;
- private int flags;
- private Type<?> supertype;
- private String sourceFile;
- private TypeList interfaces;
-
- private final Map<FieldId, FieldDeclaration> fields
- = new LinkedHashMap<FieldId, FieldDeclaration>();
- private final Map<MethodId, MethodDeclaration> methods
- = new LinkedHashMap<MethodId, MethodDeclaration>();
-
- TypeDeclaration(Type<?> type) {
- this.type = type;
- }
-
- ClassDefItem toClassDefItem() {
- if (!declared) {
- throw new IllegalStateException("Undeclared type " + type + " declares members: "
- + fields.keySet() + " " + methods.keySet());
- }
-
- DexOptions dexOptions = new DexOptions();
- dexOptions.targetApiLevel = DexFormat.API_NO_EXTENDED_OPCODES;
-
- CstType thisType = type.constant;
-
- ClassDefItem out = new ClassDefItem(thisType, flags, supertype.constant,
- interfaces.ropTypes, new CstString(sourceFile));
-
- for (MethodDeclaration method : methods.values()) {
- EncodedMethod encoded = method.toEncodedMethod(dexOptions);
- if (method.isDirect()) {
- out.addDirectMethod(encoded);
- } else {
- out.addVirtualMethod(encoded);
- }
- }
- for (FieldDeclaration field : fields.values()) {
- EncodedField encoded = field.toEncodedField();
- if (field.isStatic()) {
- out.addStaticField(encoded, Constants.getConstant(field.staticValue));
- } else {
- out.addInstanceField(encoded);
- }
- }
-
- return out;
- }
- }
-
- static class FieldDeclaration {
- final FieldId<?, ?> fieldId;
- private final int accessFlags;
- private final Object staticValue;
-
- FieldDeclaration(FieldId<?, ?> fieldId, int accessFlags, Object staticValue) {
- if ((accessFlags & (AccessFlags.ACC_STATIC)) == 0 && staticValue != null) {
- throw new IllegalArgumentException("instance fields may not have a value");
- }
- this.fieldId = fieldId;
- this.accessFlags = accessFlags;
- this.staticValue = staticValue;
- }
-
- EncodedField toEncodedField() {
- return new EncodedField(fieldId.constant, accessFlags);
- }
-
- public boolean isStatic() {
- return (accessFlags & (AccessFlags.ACC_STATIC)) != 0;
- }
- }
-
- static class MethodDeclaration {
- final MethodId<?, ?> method;
- private final int flags;
- private final Code code;
-
- public MethodDeclaration(MethodId<?, ?> method, int flags) {
- this.method = method;
- this.flags = flags;
- this.code = new Code(this);
- }
-
- boolean isStatic() {
- return (flags & ACC_STATIC) != 0;
- }
-
- boolean isDirect() {
- return (flags & (ACC_STATIC | ACC_PRIVATE | ACC_CONSTRUCTOR)) != 0;
- }
-
- EncodedMethod toEncodedMethod(DexOptions dexOptions) {
- RopMethod ropMethod = new RopMethod(code.toBasicBlocks(), 0);
- LocalVariableInfo locals = null;
- DalvCode dalvCode = RopTranslator.translate(
- ropMethod, PositionList.NONE, locals, code.paramSize(), dexOptions);
- return new EncodedMethod(method.constant, flags, dalvCode, StdTypeList.EMPTY);
- }
- }
-}