--- /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