OSDN Git Service

Add dexgen helper classes and Android.mk
authorPiotr Gurgul <pgurgul@google.com>
Fri, 3 Sep 2010 02:15:30 +0000 (19:15 -0700)
committerPiotr Gurgul <pgurgul@google.com>
Thu, 9 Sep 2010 22:09:24 +0000 (15:09 -0700)
This commit adds the very first classes to the dexgen project together with
its Android.mk file. These are the helper classes needed by dex class builder.

Change-Id: I47f8132443f43881826d24a854ab6bafb14181bd

Android.mk
dexgen/Android.mk [new file with mode: 0644]
dexgen/src/com/android/dexgen/util/DexClassLoaderHelper.java [new file with mode: 0644]
dexgen/src/com/android/dexgen/util/DexClassLoadingException.java [new file with mode: 0644]
dexgen/src/com/android/dexgen/util/DexJarMaker.java [new file with mode: 0644]
dexgen/src/com/android/dexgen/util/PathHolder.java [new file with mode: 0644]

index e70e5f5..7a950a1 100644 (file)
@@ -18,6 +18,7 @@ subdirs := $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
                libdex \
                vm \
                dalvikvm \
+               dexgen \
                dexlist \
                dexopt \
                dexdump \
diff --git a/dexgen/Android.mk b/dexgen/Android.mk
new file mode 100644 (file)
index 0000000..c4d84a0
--- /dev/null
@@ -0,0 +1,25 @@
+# Copyright (C) 2010 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SDK_VERSION := 4
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_MODULE := dexgen
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/dexgen/src/com/android/dexgen/util/DexClassLoaderHelper.java b/dexgen/src/com/android/dexgen/util/DexClassLoaderHelper.java
new file mode 100644 (file)
index 0000000..92a2eb6
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010 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.dexgen.util;
+
+import dalvik.system.DexClassLoader;
+
+/**
+ * Class used indirectly for loading generated dex classes. It allows the caller
+ * to obtain appropriate {@code DexClassLoader} instance, which can be then used for
+ * loading classes.
+ */
+public class DexClassLoaderHelper {
+
+    private DexClassLoaderHelper() {
+        // intentionally empty to disable direct instantiation
+    }
+
+    /**
+     * Returns the sole instance of {@code DexClassLoaderHelper}.
+     *
+     * @return dex {@code DexClassLoaderHelper} sole instance
+     */
+    public static DexClassLoaderHelper getInstance() {
+        return DexClassLoaderHelperHolder.INSTANCE;
+    }
+
+    /**
+     * Creates and returns DexClassLoader instance with its classpath
+     * set to {@code pathHolder}.
+     *
+     * @param pathHolder {@code non-null;} location of jar archive containing dex
+     * classes canned into a working PathHolder instance.
+     * @return dex class loader instance with its classpath set to location
+     * indicated by {@code pathHolder}
+     */
+    public ClassLoader getDexClassLoader(PathHolder pathHolder) {
+        ClassLoader myLoader = DexClassLoaderHelper.class.getClassLoader();
+        return new DexClassLoader(pathHolder.getJarFilePath(), pathHolder.getDirLocation(),
+                null, myLoader);
+    }
+
+    private static class DexClassLoaderHelperHolder {
+        private static final DexClassLoaderHelper INSTANCE = new DexClassLoaderHelper();
+    }
+}
\ No newline at end of file
diff --git a/dexgen/src/com/android/dexgen/util/DexClassLoadingException.java b/dexgen/src/com/android/dexgen/util/DexClassLoadingException.java
new file mode 100644 (file)
index 0000000..ba4d350
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010 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.dexgen.util;
+
+/**
+ * An exception type used to aggregate all the unexpected situations while
+ * trying to save dex file with generated class and load the class afterwards.
+ */
+public class DexClassLoadingException extends Exception {
+
+    /**
+     * Encapsulates any checked exception being thrown in time between saving
+     * generated dex class to a file and loading it via DexClassLoader with
+     * an user-friendly message and passing the original exception as well.
+     *
+     * @param thr {@code non-null;} lower level exception with more detailed
+     * error message
+     */
+    public DexClassLoadingException(Throwable thr) {
+        super("Loading generated dex class has failed", thr);
+    }
+}
\ No newline at end of file
diff --git a/dexgen/src/com/android/dexgen/util/DexJarMaker.java b/dexgen/src/com/android/dexgen/util/DexJarMaker.java
new file mode 100644 (file)
index 0000000..4fe5a56
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2010 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.dexgen.util;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+/**
+ * Helper class used to encapsulate generated .dex file into .jar
+ * so that it fits {@code DexClassLoader} constructor.
+ */
+public class DexJarMaker {
+
+    /** indicates name of the dex file added to jar */
+    public static final String DEX_FILE_NAME_IN_JAR = "classes" + PathHolder.DEX_FILE_EXTENSION;
+
+    /** {@code non-null;} storage for all the paths related to current dex file */
+    private final PathHolder pathHolder;
+
+    public DexJarMaker(PathHolder pathHolder) {
+        this.pathHolder = pathHolder;
+    }
+
+    /** Packs previously added files into a single jar archive. */
+    public void create() throws DexClassLoadingException {
+        Manifest manifest = new Manifest();
+        manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
+        JarOutputStream target = null;
+        try {
+            target = new JarOutputStream(
+                    new BufferedOutputStream(new FileOutputStream(pathHolder.getJarFilePath())),
+                    manifest);
+            add(new File(pathHolder.getDexFilePath()), target);
+
+        } catch (IOException e) {
+            throw new DexClassLoadingException(e);
+        }
+        finally {
+            try {
+                if (target != null) {
+                    target.close();
+                }
+            } catch(IOException e) {
+                // Ignoring deliberately in order to keep the original exception clear.
+            }
+        }
+    }
+
+    /**
+     * Adds indicated file to the requested archive.
+     *
+     * @param source {@code non-null;} dex file to add
+     * @param target {@code non-null;} target jar archive
+     * @throws IOException
+     */
+    private void add(File source, JarOutputStream target) throws IOException {
+
+        if (!source.isFile()) {
+            throw new IllegalArgumentException("Wrong source dex file provided");
+        }
+
+        BufferedInputStream in = new BufferedInputStream(new FileInputStream(source));
+        JarEntry entry = new JarEntry(DEX_FILE_NAME_IN_JAR);
+        entry.setTime(source.lastModified());
+        target.putNextEntry(entry);
+
+        int curr = -1;
+        while ((curr = in.read()) != -1) {
+            target.write(curr);
+        }
+        target.closeEntry();
+    }
+}
\ No newline at end of file
diff --git a/dexgen/src/com/android/dexgen/util/PathHolder.java b/dexgen/src/com/android/dexgen/util/PathHolder.java
new file mode 100644 (file)
index 0000000..b23ce66
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2010 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.dexgen.util;
+
+import java.io.File;
+
+/**
+ *  Helper class used primarily for holding path on the device of different
+ *  files arising in the dex class generation process.
+ */
+public class PathHolder {
+
+    public static final String DEX_FILE_EXTENSION = ".dex";
+
+    public static final String JAR_FILE_EXTENSION = ".jar";
+
+    /** {@code non-null;} directory location of the dex-related files */
+    private final String dirLocation;
+
+    /** {@code non-null;} common file name prefix of the created files */
+    private final String fileNamePrefix;
+
+    /**
+     * Creates an instance of {@code PathHolder} initialized with the directory
+     * location for storage of temporary files and common file name prefix for these
+     * files.
+     *
+     * @param dirLocation {@code non-null;} path to directory used for storage of temporary files
+     * @param fileNamePrefix {@code non-null;} common file name prefix across all the temporary
+     * files involved in the dex class generation and loading process
+     */
+    public PathHolder(String dirLocation, String fileNamePrefix) {
+        if (dirLocation == null) {
+            throw new NullPointerException("dirLocation == null");
+        }
+        if (fileNamePrefix == null) {
+            throw new NullPointerException("fileNamePrefix == null");
+        }
+
+        this.dirLocation = dirLocation;
+        this.fileNamePrefix = fileNamePrefix;
+    }
+
+    public String getFileName() {
+        return fileNamePrefix;
+    }
+
+    public String getDexFilePath() {
+        return dirLocation + File.separator + fileNamePrefix + DEX_FILE_EXTENSION;
+    }
+
+    public String getDexFileName() {
+        return fileNamePrefix + DEX_FILE_EXTENSION;
+    }
+
+    public String getJarFilePath() {
+        return dirLocation + File.separator + fileNamePrefix + JAR_FILE_EXTENSION;
+    }
+
+    public String getJarFileName() {
+        return fileNamePrefix + JAR_FILE_EXTENSION;
+    }
+
+    public String getDirLocation() {
+        return dirLocation;
+    }
+}