libdex \
vm \
dalvikvm \
+ dexgen \
dexlist \
dexopt \
dexdump \
--- /dev/null
+# 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))
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+ }
+}