/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
 *
 * 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.ide.eclipse.adt.internal.build;

import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AndroidPrintStream;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs.BuildVerbosity;
import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.prefs.AndroidLocation.AndroidLocationException;
import com.android.sdklib.BuildToolInfo;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.IAndroidTarget.IOptionalLibrary;
import com.android.sdklib.build.ApkBuilder;
import com.android.sdklib.build.ApkBuilder.JarStatus;
import com.android.sdklib.build.ApkBuilder.SigningInfo;
import com.android.sdklib.build.ApkCreationException;
import com.android.sdklib.build.DuplicateFileException;
import com.android.sdklib.build.RenderScriptProcessor;
import com.android.sdklib.build.SealedApkException;
import com.android.sdklib.internal.build.DebugKeyProvider;
import com.android.sdklib.internal.build.DebugKeyProvider.KeytoolException;
import com.android.utils.GrabProcessOutput;
import com.android.utils.GrabProcessOutput.IProcessOutput;
import com.android.utils.GrabProcessOutput.Wait;
import com.google.common.base.Charsets;
import com.google.common.hash.HashCode;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.preference.IPreferenceStore;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
 * Helper with methods for the last 3 steps of the generation of an APK.
 *
 * {@link #packageResources(IFile, IProject[], String, int, String, String)} packages the
 * application resources using aapt into a zip file that is ready to be integrated into the apk.
 *
 * {@link #executeDx(IJavaProject, String, String, IJavaProject[])} will convert the Java byte
 * code into the Dalvik bytecode.
 *
 * {@link #finalPackage(String, String, String, boolean, IJavaProject, IProject[], IJavaProject[], String, boolean)}
 * will make the apk from all the previous components.
 *
 * This class only executes the 3 above actions. It does not handle the errors, and simply sends
 * them back as custom exceptions.
 *
 * Warnings are handled by the {@link ResourceMarker} interface.
 *
 * Console output (verbose and non verbose) is handled through the {@link AndroidPrintStream} passed
 * to the constructor.
 *
 */
public class BuildHelper {

    private static final String CONSOLE_PREFIX_DX = "Dx";   //$NON-NLS-1$
    private final static String TEMP_PREFIX = "android_";   //$NON-NLS-1$

    private static final String COMMAND_CRUNCH = "crunch";  //$NON-NLS-1$
    private static final String COMMAND_PACKAGE = "package"; //$NON-NLS-1$

    @NonNull
    private final ProjectState mProjectState;
    @NonNull
    private final IProject mProject;
    @NonNull
    private final BuildToolInfo mBuildToolInfo;
    @NonNull
    private final AndroidPrintStream mOutStream;
    @NonNull
    private final AndroidPrintStream mErrStream;
    private final boolean mForceJumbo;
    private final boolean mDisableDexMerger;
    private final boolean mVerbose;
    private final boolean mDebugMode;

    private final Set<String> mCompiledCodePaths = new HashSet<String>();

    public static final boolean BENCHMARK_FLAG = false;
    public static long sStartOverallTime = 0;
    public static long sStartJavaCTime = 0;

    private final static int MILLION = 1000000;
    private String mProguardFile;

    /**
     * An object able to put a marker on a resource.
     */
    public interface ResourceMarker {
        void setWarning(IResource resource, String message);
    }

    /**
     * Creates a new post-compiler helper
     * @param project
     * @param outStream
     * @param errStream
     * @param debugMode whether this is a debug build
     * @param verbose
     * @throws CoreException
     */
    public BuildHelper(@NonNull ProjectState projectState,
            @NonNull BuildToolInfo buildToolInfo,
            @NonNull AndroidPrintStream outStream,
            @NonNull AndroidPrintStream errStream,
            boolean forceJumbo, boolean disableDexMerger, boolean debugMode,
            boolean verbose, ResourceMarker resMarker) throws CoreException {
        mProjectState = projectState;
        mProject = projectState.getProject();
        mBuildToolInfo = buildToolInfo;
        mOutStream = outStream;
        mErrStream = errStream;
        mDebugMode = debugMode;
        mVerbose = verbose;
        mForceJumbo = forceJumbo;
        mDisableDexMerger = disableDexMerger;

        gatherPaths(resMarker);
    }

    public void updateCrunchCache() throws AaptExecException, AaptResultException {
        // Benchmarking start
        long startCrunchTime = 0;
        if (BENCHMARK_FLAG) {
            String msg = "BENCHMARK ADT: Starting Initial Packaging (.ap_)"; //$NON-NLS-1$
            AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, mProject, msg);
            startCrunchTime = System.nanoTime();
        }

        // Get the resources folder to crunch from
        IFolder resFolder = mProject.getFolder(AdtConstants.WS_RESOURCES);
        List<String> resPaths = new ArrayList<String>();
        resPaths.add(resFolder.getLocation().toOSString());

        // Get the output folder where the cache is stored.
        IFolder binFolder = BaseProjectHelper.getAndroidOutputFolder(mProject);
        IFolder cacheFolder = binFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_CRUNCHCACHE);
        String cachePath = cacheFolder.getLocation().toOSString();

        /* For crunching, we don't need the osManifestPath, osAssetsPath, or the configFilter
         * parameters for executeAapt
         */
        executeAapt(COMMAND_CRUNCH, "", resPaths, "", cachePath, "", 0);

        // Benchmarking end
        if (BENCHMARK_FLAG) {
            String msg = "BENCHMARK ADT: Ending Initial Package (.ap_). \nTime Elapsed: " //$NON-NLS-1$
                            + ((System.nanoTime() - startCrunchTime)/MILLION) + "ms";     //$NON-NLS-1$
            AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, mProject, msg);
        }
    }

    /**
     * Packages the resources of the projet into a .ap_ file.
     * @param manifestFile the manifest of the project.
     * @param libProjects the list of library projects that this project depends on.
     * @param resFilter an optional resource filter to be used with the -c option of aapt. If null
     * no filters are used.
     * @param versionCode an optional versionCode to be inserted in the manifest during packaging.
     * If the value is <=0, no values are inserted.
     * @param outputFolder where to write the resource ap_ file.
     * @param outputFilename the name of the resource ap_ file.
     * @throws AaptExecException
     * @throws AaptResultException
     */
    public void packageResources(IFile manifestFile, List<IProject> libProjects, String resFilter,
            int versionCode, String outputFolder, String outputFilename)
            throws AaptExecException, AaptResultException {

        // Benchmarking start
        long startPackageTime = 0;
        if (BENCHMARK_FLAG) {
            String msg = "BENCHMARK ADT: Starting Initial Packaging (.ap_)";    //$NON-NLS-1$
            AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, mProject, msg);
            startPackageTime = System.nanoTime();
        }

        // need to figure out some path before we can execute aapt;
        IFolder binFolder = BaseProjectHelper.getAndroidOutputFolder(mProject);

        // get the cache folder
        IFolder cacheFolder = binFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_CRUNCHCACHE);

        // get the BC folder
        IFolder bcFolder = binFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_BC);

        // get the resource folder
        IFolder resFolder = mProject.getFolder(AdtConstants.WS_RESOURCES);

        // and the assets folder
        IFolder assetsFolder = mProject.getFolder(AdtConstants.WS_ASSETS);

        // we need to make sure this one exists.
        if (assetsFolder.exists() == false) {
            assetsFolder = null;
        }

        // list of res folder (main project + maybe libraries)
        ArrayList<String> osResPaths = new ArrayList<String>();

        IPath resLocation = resFolder.getLocation();
        IPath manifestLocation = manifestFile.getLocation();

        if (resLocation != null && manifestLocation != null) {

            // png cache folder first.
            addFolderToList(osResPaths, cacheFolder);
            addFolderToList(osResPaths, bcFolder);

            // regular res folder next.
            osResPaths.add(resLocation.toOSString());

            // then libraries
            if (libProjects != null) {
                for (IProject lib : libProjects) {
                    // png cache folder first
                    IFolder libBinFolder = BaseProjectHelper.getAndroidOutputFolder(lib);

                    IFolder libCacheFolder = libBinFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_CRUNCHCACHE);
                    addFolderToList(osResPaths, libCacheFolder);

                    IFolder libBcFolder = libBinFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_BC);
                    addFolderToList(osResPaths, libBcFolder);

                    // regular res folder next.
                    IFolder libResFolder = lib.getFolder(AdtConstants.WS_RESOURCES);
                    addFolderToList(osResPaths, libResFolder);
                }
            }

            String osManifestPath = manifestLocation.toOSString();

            String osAssetsPath = null;
            if (assetsFolder != null) {
                osAssetsPath = assetsFolder.getLocation().toOSString();
            }

            // build the default resource package
            executeAapt(COMMAND_PACKAGE, osManifestPath, osResPaths, osAssetsPath,
                    outputFolder + File.separator + outputFilename, resFilter,
                    versionCode);
        }

        // Benchmarking end
        if (BENCHMARK_FLAG) {
            String msg = "BENCHMARK ADT: Ending Initial Package (.ap_). \nTime Elapsed: " //$NON-NLS-1$
                            + ((System.nanoTime() - startPackageTime)/MILLION) + "ms";    //$NON-NLS-1$
            AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, mProject, msg);
        }
    }

    /**
     * Adds os path of a folder to a list only if the folder actually exists.
     * @param pathList
     * @param folder
     */
    private void addFolderToList(List<String> pathList, IFolder folder) {
        // use a File instead of the IFolder API to ignore workspace refresh issue.
        File testFile = new File(folder.getLocation().toOSString());
        if (testFile.isDirectory()) {
            pathList.add(testFile.getAbsolutePath());
        }
    }

    /**
     * Makes a final package signed with the debug key.
     *
     * Packages the dex files, the temporary resource file into the final package file.
     *
     * Whether the package is a debug package is controlled with the <var>debugMode</var> parameter
     * in {@link #PostCompilerHelper(IProject, PrintStream, PrintStream, boolean, boolean)}
     *
     * @param intermediateApk The path to the temporary resource file.
     * @param dex The path to the dex file.
     * @param output The path to the final package file to create.
     * @param libProjects an optional list of library projects (can be null)
     * @return true if success, false otherwise.
     * @throws ApkCreationException
     * @throws AndroidLocationException
     * @throws KeytoolException
     * @throws NativeLibInJarException
     * @throws CoreException
     * @throws DuplicateFileException
     */
    public void finalDebugPackage(String intermediateApk, String dex, String output,
            List<IProject> libProjects, ResourceMarker resMarker)
            throws ApkCreationException, KeytoolException, AndroidLocationException,
            NativeLibInJarException, DuplicateFileException, CoreException {

        AdtPlugin adt = AdtPlugin.getDefault();
        if (adt == null) {
            return;
        }

        // get the debug keystore to use.
        IPreferenceStore store = adt.getPreferenceStore();
        String keystoreOsPath = store.getString(AdtPrefs.PREFS_CUSTOM_DEBUG_KEYSTORE);
        if (keystoreOsPath == null || new File(keystoreOsPath).isFile() == false) {
            keystoreOsPath = DebugKeyProvider.getDefaultKeyStoreOsPath();
            AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, mProject,
                    Messages.ApkBuilder_Using_Default_Key);
        } else {
            AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, mProject,
                    String.format(Messages.ApkBuilder_Using_s_To_Sign, keystoreOsPath));
        }

        // from the keystore, get the signing info
        SigningInfo info = ApkBuilder.getDebugKey(keystoreOsPath, mVerbose ? mOutStream : null);

        finalPackage(intermediateApk, dex, output, libProjects,
                info != null ? info.key : null, info != null ? info.certificate : null, resMarker);
    }

    /**
     * Makes the final package.
     *
     * Packages the dex files, the temporary resource file into the final package file.
     *
     * Whether the package is a debug package is controlled with the <var>debugMode</var> parameter
     * in {@link #PostCompilerHelper(IProject, PrintStream, PrintStream, boolean, boolean)}
     *
     * @param intermediateApk The path to the temporary resource file.
     * @param dex The path to the dex file.
     * @param output The path to the final package file to create.
     * @param debugSign whether the apk must be signed with the debug key.
     * @param libProjects an optional list of library projects (can be null)
     * @param abiFilter an optional filter. If not null, then only the matching ABI is included in
     * the final archive
     * @return true if success, false otherwise.
     * @throws NativeLibInJarException
     * @throws ApkCreationException
     * @throws CoreException
     * @throws DuplicateFileException
     */
    public void finalPackage(String intermediateApk, String dex, String output,
            List<IProject> libProjects,
            PrivateKey key, X509Certificate certificate, ResourceMarker resMarker)
            throws NativeLibInJarException, ApkCreationException, DuplicateFileException,
            CoreException {

        try {
            ApkBuilder apkBuilder = new ApkBuilder(output, intermediateApk, dex,
                    key, certificate,
                    mVerbose ? mOutStream: null);
            apkBuilder.setDebugMode(mDebugMode);

            // either use the full compiled code paths or just the proguard file
            // if present
            Collection<String> pathsCollection = mCompiledCodePaths;
            if (mProguardFile != null) {
                pathsCollection = Collections.singletonList(mProguardFile);
                mProguardFile = null;
            }

            // Now we write the standard resources from all the output paths.
            for (String path : pathsCollection) {
                File file = new File(path);
                if (file.isFile()) {
                    JarStatus jarStatus = apkBuilder.addResourcesFromJar(file);

                    // check if we found native libraries in the external library. This
                    // constitutes an error or warning depending on if they are in lib/
                    if (jarStatus.getNativeLibs().size() > 0) {
                        String libName = file.getName();

                        String msg = String.format(
                                "Native libraries detected in '%1$s'. See console for more information.",
                                libName);

                        ArrayList<String> consoleMsgs = new ArrayList<String>();

                        consoleMsgs.add(String.format(
                                "The library '%1$s' contains native libraries that will not run on the device.",
                                libName));

                        if (jarStatus.hasNativeLibsConflicts()) {
                            consoleMsgs.add("Additionally some of those libraries will interfer with the installation of the application because of their location in lib/");
                            consoleMsgs.add("lib/ is reserved for NDK libraries.");
                        }

                        consoleMsgs.add("The following libraries were found:");

                        for (String lib : jarStatus.getNativeLibs()) {
                            consoleMsgs.add(" - " + lib);
                        }

                        String[] consoleStrings = consoleMsgs.toArray(new String[consoleMsgs.size()]);

                        // if there's a conflict or if the prefs force error on any native code in jar
                        // files, throw an exception
                        if (jarStatus.hasNativeLibsConflicts() ||
                                AdtPrefs.getPrefs().getBuildForceErrorOnNativeLibInJar()) {
                            throw new NativeLibInJarException(jarStatus, msg, libName, consoleStrings);
                        } else {
                            // otherwise, put a warning, and output to the console also.
                            if (resMarker != null) {
                                resMarker.setWarning(mProject, msg);
                            }

                            for (String string : consoleStrings) {
                                mOutStream.println(string);
                            }
                        }
                    }
                } else if (file.isDirectory()) {
                    // this is technically not a source folder (class folder instead) but since we
                    // only care about Java resources (ie non class/java files) this will do the
                    // same
                    apkBuilder.addSourceFolder(file);
                }
            }

            // now write the native libraries.
            // First look if the lib folder is there.
            IResource libFolder = mProject.findMember(SdkConstants.FD_NATIVE_LIBS);
            if (libFolder != null && libFolder.exists() &&
                    libFolder.getType() == IResource.FOLDER) {
                // get a File for the folder.
                apkBuilder.addNativeLibraries(libFolder.getLocation().toFile());
            }

            // next the native libraries for the renderscript support mode.
            if (mProjectState.getRenderScriptSupportMode()) {
                IFolder androidOutputFolder = BaseProjectHelper.getAndroidOutputFolder(mProject);
                IResource rsLibFolder = androidOutputFolder.getFolder(
                        AdtConstants.WS_BIN_RELATIVE_RS_LIBS);
                File rsLibFolderFile = rsLibFolder.getLocation().toFile();
                if (rsLibFolderFile.isDirectory()) {
                    apkBuilder.addNativeLibraries(rsLibFolderFile);
                }

                File rsLibs = RenderScriptProcessor.getSupportNativeLibFolder(
                        mBuildToolInfo.getLocation().getAbsolutePath());
                if (rsLibs.isDirectory()) {
                    apkBuilder.addNativeLibraries(rsLibs);
                }
            }

            // write the native libraries for the library projects.
            if (libProjects != null) {
                for (IProject lib : libProjects) {
                    libFolder = lib.findMember(SdkConstants.FD_NATIVE_LIBS);
                    if (libFolder != null && libFolder.exists() &&
                            libFolder.getType() == IResource.FOLDER) {
                        apkBuilder.addNativeLibraries(libFolder.getLocation().toFile());
                    }
                }
            }

            // seal the APK.
            apkBuilder.sealApk();
        } catch (SealedApkException e) {
            // this won't happen as we control when the apk is sealed.
        }
    }

    public void setProguardOutput(String proguardFile) {
        mProguardFile = proguardFile;
    }

    public Collection<String> getCompiledCodePaths() {
        return mCompiledCodePaths;
    }

    public void runProguard(List<File> proguardConfigs, File inputJar, Collection<String> jarFiles,
                            File obfuscatedJar, File logOutput)
            throws ProguardResultException, ProguardExecException, IOException {
        IAndroidTarget target = Sdk.getCurrent().getTarget(mProject);

        // prepare the command line for proguard
        List<String> command = new ArrayList<String>();
        command.add(AdtPlugin.getOsAbsoluteProguard());

        for (File configFile : proguardConfigs) {
            command.add("-include"); //$NON-NLS-1$
            command.add(quotePath(configFile.getAbsolutePath()));
        }

        command.add("-injars"); //$NON-NLS-1$
        StringBuilder sb = new StringBuilder(quotePath(inputJar.getAbsolutePath()));
        for (String jarFile : jarFiles) {
            sb.append(File.pathSeparatorChar);
            sb.append(quotePath(jarFile));
        }
        command.add(quoteWinArg(sb.toString()));

        command.add("-outjars"); //$NON-NLS-1$
        command.add(quotePath(obfuscatedJar.getAbsolutePath()));

        command.add("-libraryjars"); //$NON-NLS-1$
        sb = new StringBuilder(quotePath(target.getPath(IAndroidTarget.ANDROID_JAR)));
        IOptionalLibrary[] libraries = target.getOptionalLibraries();
        if (libraries != null) {
            for (IOptionalLibrary lib : libraries) {
                sb.append(File.pathSeparatorChar);
                sb.append(quotePath(lib.getJarPath()));
            }
        }
        command.add(quoteWinArg(sb.toString()));

        if (logOutput != null) {
            if (logOutput.isDirectory() == false) {
                logOutput.mkdirs();
            }

            command.add("-dump");                                              //$NON-NLS-1$
            command.add(new File(logOutput, "dump.txt").getAbsolutePath());    //$NON-NLS-1$

            command.add("-printseeds");                                        //$NON-NLS-1$
            command.add(new File(logOutput, "seeds.txt").getAbsolutePath());   //$NON-NLS-1$

            command.add("-printusage");                                        //$NON-NLS-1$
            command.add(new File(logOutput, "usage.txt").getAbsolutePath());   //$NON-NLS-1$

            command.add("-printmapping");                                      //$NON-NLS-1$
            command.add(new File(logOutput, "mapping.txt").getAbsolutePath()); //$NON-NLS-1$
        }

        String commandArray[] = null;

        if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_WINDOWS) {
            commandArray = createWindowsProguardConfig(command);
        }

        if (commandArray == null) {
            // For Mac & Linux, use a regular command string array.
            commandArray = command.toArray(new String[command.size()]);
        }

        // Define PROGUARD_HOME to point to $SDK/tools/proguard if it's not yet defined.
        // The Mac/Linux proguard.sh can infer it correctly but not the proguard.bat one.
        String[] envp = null;
        Map<String, String> envMap = new TreeMap<String, String>(System.getenv());
        if (!envMap.containsKey("PROGUARD_HOME")) {                                    //$NON-NLS-1$
            envMap.put("PROGUARD_HOME", Sdk.getCurrent().getSdkOsLocation() +          //$NON-NLS-1$
                                        SdkConstants.FD_TOOLS + File.separator +
                                        SdkConstants.FD_PROGUARD);
            envp = new String[envMap.size()];
            int i = 0;
            for (Map.Entry<String, String> entry : envMap.entrySet()) {
                envp[i++] = String.format("%1$s=%2$s",                                 //$NON-NLS-1$
                                          entry.getKey(),
                                          entry.getValue());
            }
        }

        if (AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE) {
            sb = new StringBuilder();
            for (String c : commandArray) {
                sb.append(c).append(' ');
            }
            AdtPlugin.printToConsole(mProject, sb.toString());
        }

        // launch
        int execError = 1;
        try {
            // launch the command line process
            Process process = Runtime.getRuntime().exec(commandArray, envp);

            // list to store each line of stderr
            ArrayList<String> results = new ArrayList<String>();

            // get the output and return code from the process
            execError = grabProcessOutput(mProject, process, results);

            if (mVerbose) {
                for (String resultString : results) {
                    mOutStream.println(resultString);
                }
            }

            if (execError != 0) {
                throw new ProguardResultException(execError,
                        results.toArray(new String[results.size()]));
            }

        } catch (IOException e) {
            String msg = String.format(Messages.Proguard_Exec_Error, commandArray[0]);
            throw new ProguardExecException(msg, e);
        } catch (InterruptedException e) {
            String msg = String.format(Messages.Proguard_Exec_Error, commandArray[0]);
            throw new ProguardExecException(msg, e);
        }
    }

    /**
     * For tools R8 up to R11, the proguard.bat launcher on Windows only accepts
     * arguments %1..%9. Since we generally have about 15 arguments, we were working
     * around this by generating a temporary config file for proguard and then using
     * that.
     * Starting with tools R12, the proguard.bat launcher has been fixed to take
     * all arguments using %* so we no longer need this hack.
     *
     * @param command
     * @return
     * @throws IOException
     */
    private String[] createWindowsProguardConfig(List<String> command) throws IOException {

        // Arg 0 is the proguard.bat path and arg 1 is the user config file
        String launcher = AdtPlugin.readFile(new File(command.get(0)));
        if (launcher.contains("%*")) {                                      //$NON-NLS-1$
            // This is the launcher from Tools R12. Don't work around it.
            return null;
        }

        // On Windows, proguard.bat can only pass %1...%9 to the java -jar proguard.jar
        // call, but we have at least 15 arguments here so some get dropped silently
        // and quoting is a big issue. So instead we'll work around that by writing
        // all the arguments to a temporary config file.

        String[] commandArray = new String[3];

        commandArray[0] = command.get(0);
        commandArray[1] = command.get(1);

        // Write all the other arguments to a config file
        File argsFile = File.createTempFile(TEMP_PREFIX, ".pro");           //$NON-NLS-1$
        // TODO FIXME this may leave a lot of temp files around on a long session.
        // Should have a better way to clean up e.g. before each build.
        argsFile.deleteOnExit();

        FileWriter fw = new FileWriter(argsFile);

        for (int i = 2; i < command.size(); i++) {
            String s = command.get(i);
            fw.write(s);
            fw.write(s.startsWith("-") ? ' ' : '\n');                       //$NON-NLS-1$
        }

        fw.close();

        commandArray[2] = "@" + argsFile.getAbsolutePath();                 //$NON-NLS-1$
        return commandArray;
    }

    /**
     * Quotes a single path for proguard to deal with spaces.
     *
     * @param path The path to quote.
     * @return The original path if it doesn't contain a space.
     *   Or the original path surrounded by single quotes if it contains spaces.
     */
    private String quotePath(String path) {
        if (path.indexOf(' ') != -1) {
            path = '\'' + path + '\'';
        }
        return path;
    }

    /**
     * Quotes a compound proguard argument to deal with spaces.
     * <p/>
     * Proguard takes multi-path arguments such as "path1;path2" for some options.
     * When the {@link #quotePath} methods adds quotes for such a path if it contains spaces,
     * the proguard shell wrapper will absorb the quotes, so we need to quote around the
     * quotes.
     *
     * @param path The path to quote.
     * @return The original path if it doesn't contain a single quote.
     *   Or on Windows the original path surrounded by double quotes if it contains a quote.
     */
    private String quoteWinArg(String path) {
        if (path.indexOf('\'') != -1 &&
                SdkConstants.currentPlatform() == SdkConstants.PLATFORM_WINDOWS) {
            path = '"' + path + '"';
        }
        return path;
    }


    /**
     * Execute the Dx tool for dalvik code conversion.
     * @param javaProject The java project
     * @param inputPaths the input paths for DX
     * @param osOutFilePath the path of the dex file to create.
     *
     * @throws CoreException
     * @throws DexException
     */
    public void executeDx(IJavaProject javaProject, Collection<String> inputPaths,
            String osOutFilePath)
            throws CoreException, DexException {

        // get the dex wrapper
        Sdk sdk = Sdk.getCurrent();
        DexWrapper wrapper = sdk.getDexWrapper(mBuildToolInfo);

        if (wrapper == null) {
            throw new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
                    Messages.ApkBuilder_UnableBuild_Dex_Not_loaded));
        }

        try {
            // set a temporary prefix on the print streams.
            mOutStream.setPrefix(CONSOLE_PREFIX_DX);
            mErrStream.setPrefix(CONSOLE_PREFIX_DX);

            IFolder binFolder = BaseProjectHelper.getAndroidOutputFolder(javaProject.getProject());
            File binFile = binFolder.getLocation().toFile();
            File dexedLibs = new File(binFile, "dexedLibs");
            if (dexedLibs.exists() == false) {
                dexedLibs.mkdir();
            }

            // replace the libs by their dexed versions (dexing them if needed.)
            List<String> finalInputPaths = new ArrayList<String>(inputPaths.size());
            if (mDisableDexMerger || inputPaths.size() == 1) {
                // only one input, no need to put a pre-dexed version, even if this path is
                // just a jar file (case for proguard'ed builds)
                finalInputPaths.addAll(inputPaths);
            } else {

                for (String input : inputPaths) {
                    File inputFile = new File(input);
                    if (inputFile.isDirectory()) {
                        finalInputPaths.add(input);
                    } else if (inputFile.isFile()) {
                        String fileName = getDexFileName(inputFile);

                        File dexedLib = new File(dexedLibs, fileName);
                        String dexedLibPath = dexedLib.getAbsolutePath();

                        if (dexedLib.isFile() == false ||
                                dexedLib.lastModified() < inputFile.lastModified()) {

                            if (mVerbose) {
                                mOutStream.println(
                                        String.format("Pre-Dexing %1$s -> %2$s", input, fileName));
                            }

                            if (dexedLib.isFile()) {
                                dexedLib.delete();
                            }

                            int res = wrapper.run(dexedLibPath, Collections.singleton(input),
                                    mForceJumbo, mVerbose, mOutStream, mErrStream);

                            if (res != 0) {
                                // output error message and mark the project.
                                String message = String.format(Messages.Dalvik_Error_d, res);
                                throw new DexException(message);
                            }
                        } else {
                            if (mVerbose) {
                                mOutStream.println(
                                        String.format("Using Pre-Dexed %1$s <- %2$s",
                                                fileName, input));
                            }
                        }

                        finalInputPaths.add(dexedLibPath);
                    }
                }
            }

            if (mVerbose) {
                for (String input : finalInputPaths) {
                    mOutStream.println("Input: " + input);
                }
            }

            int res = wrapper.run(osOutFilePath,
                    finalInputPaths,
                    mForceJumbo,
                    mVerbose,
                    mOutStream, mErrStream);

            mOutStream.setPrefix(null);
            mErrStream.setPrefix(null);

            if (res != 0) {
                // output error message and marker the project.
                String message = String.format(Messages.Dalvik_Error_d, res);
                throw new DexException(message);
            }
        } catch (DexException e) {
            throw e;
        } catch (Throwable t) {
            String message = t.getMessage();
            if (message == null) {
                message = t.getClass().getCanonicalName();
            }
            message = String.format(Messages.Dalvik_Error_s, message);

            throw new DexException(message, t);
        }
    }

    private String getDexFileName(File inputFile) {
        // get the filename
        String name = inputFile.getName();
        // remove the extension
        int pos = name.lastIndexOf('.');
        if (pos != -1) {
            name = name.substring(0, pos);
        }

        // add a hash of the original file path
        HashFunction hashFunction = Hashing.md5();
        HashCode hashCode = hashFunction.hashString(inputFile.getAbsolutePath(), Charsets.UTF_8);

        return name + "-" + hashCode.toString() + ".jar";
    }

    /**
     * Executes aapt. If any error happen, files or the project will be marked.
     * @param command The command for aapt to execute. Currently supported: package and crunch
     * @param osManifestPath The path to the manifest file
     * @param osResPath The path to the res folder
     * @param osAssetsPath The path to the assets folder. This can be null.
     * @param osOutFilePath The path to the temporary resource file to create,
     *   or in the case of crunching the path to the cache to create/update.
     * @param configFilter The configuration filter for the resources to include
     * (used with -c option, for example "port,en,fr" to include portrait, English and French
     * resources.)
     * @param versionCode optional version code to insert in the manifest during packaging. If <=0
     * then no value is inserted
     * @throws AaptExecException
     * @throws AaptResultException
     */
    private void executeAapt(String aaptCommand, String osManifestPath,
            List<String> osResPaths, String osAssetsPath, String osOutFilePath,
            String configFilter, int versionCode) throws AaptExecException, AaptResultException {
        IAndroidTarget target = Sdk.getCurrent().getTarget(mProject);

        String aapt = mBuildToolInfo.getPath(BuildToolInfo.PathId.AAPT);

        // Create the command line.
        ArrayList<String> commandArray = new ArrayList<String>();
        commandArray.add(aapt);
        commandArray.add(aaptCommand);
        if (AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE) {
            commandArray.add("-v"); //$NON-NLS-1$
        }

        // Common to all commands
        for (String path : osResPaths) {
            commandArray.add("-S"); //$NON-NLS-1$
            commandArray.add(path);
        }

        if (aaptCommand.equals(COMMAND_PACKAGE)) {
            commandArray.add("-f");          //$NON-NLS-1$
            commandArray.add("--no-crunch"); //$NON-NLS-1$

            // if more than one res, this means there's a library (or more) and we need
            // to activate the auto-add-overlay
            if (osResPaths.size() > 1) {
                commandArray.add("--auto-add-overlay"); //$NON-NLS-1$
            }

            if (mDebugMode) {
                commandArray.add("--debug-mode"); //$NON-NLS-1$
            }

            if (versionCode > 0) {
                commandArray.add("--version-code"); //$NON-NLS-1$
                commandArray.add(Integer.toString(versionCode));
            }

            if (configFilter != null) {
                commandArray.add("-c"); //$NON-NLS-1$
                commandArray.add(configFilter);
            }

            // never compress apks.
            commandArray.add("-0");
            commandArray.add("apk");

            commandArray.add("-M"); //$NON-NLS-1$
            commandArray.add(osManifestPath);

            if (osAssetsPath != null) {
                commandArray.add("-A"); //$NON-NLS-1$
                commandArray.add(osAssetsPath);
            }

            commandArray.add("-I"); //$NON-NLS-1$
            commandArray.add(target.getPath(IAndroidTarget.ANDROID_JAR));

            commandArray.add("-F"); //$NON-NLS-1$
            commandArray.add(osOutFilePath);
        } else if (aaptCommand.equals(COMMAND_CRUNCH)) {
            commandArray.add("-C"); //$NON-NLS-1$
            commandArray.add(osOutFilePath);
        }

        String command[] = commandArray.toArray(
                new String[commandArray.size()]);

        if (AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE) {
            StringBuilder sb = new StringBuilder();
            for (String c : command) {
                sb.append(c);
                sb.append(' ');
            }
            AdtPlugin.printToConsole(mProject, sb.toString());
        }

        // Benchmarking start
        long startAaptTime = 0;
        if (BENCHMARK_FLAG) {
            String msg = "BENCHMARK ADT: Starting " + aaptCommand  //$NON-NLS-1$
                         + " call to Aapt";                        //$NON-NLS-1$
            AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, mProject, msg);
            startAaptTime = System.nanoTime();
        }

        // launch
        try {
            // launch the command line process
            Process process = Runtime.getRuntime().exec(command);

            // list to store each line of stderr
            ArrayList<String> stdErr = new ArrayList<String>();

            // get the output and return code from the process
            int returnCode = grabProcessOutput(mProject, process, stdErr);

            if (mVerbose) {
                for (String stdErrString : stdErr) {
                    mOutStream.println(stdErrString);
                }
            }
            if (returnCode != 0) {
                throw new AaptResultException(returnCode,
                        stdErr.toArray(new String[stdErr.size()]));
            }
        } catch (IOException e) {
            String msg = String.format(Messages.AAPT_Exec_Error_s, command[0]);
            throw new AaptExecException(msg, e);
        } catch (InterruptedException e) {
            String msg = String.format(Messages.AAPT_Exec_Error_s, command[0]);
            throw new AaptExecException(msg, e);
        }

        // Benchmarking end
        if (BENCHMARK_FLAG) {
            String msg = "BENCHMARK ADT: Ending " + aaptCommand                  //$NON-NLS-1$
                         + " call to Aapt.\nBENCHMARK ADT: Time Elapsed: "       //$NON-NLS-1$
                         + ((System.nanoTime() - startAaptTime)/MILLION) + "ms"; //$NON-NLS-1$
            AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, mProject, msg);
        }
    }

    /**
     * Computes all the project output and dependencies that must go into building the apk.
     *
     * @param resMarker
     * @throws CoreException
     */
    private void gatherPaths(ResourceMarker resMarker)
            throws CoreException {
        IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();

        // get a java project for the project.
        IJavaProject javaProject = JavaCore.create(mProject);


        // get the output of the main project
        IPath path = javaProject.getOutputLocation();
        IResource outputResource = wsRoot.findMember(path);
        if (outputResource != null && outputResource.getType() == IResource.FOLDER) {
            mCompiledCodePaths.add(outputResource.getLocation().toOSString());
        }

        // we could use IJavaProject.getResolvedClasspath directly, but we actually
        // want to see the containers themselves.
        IClasspathEntry[] classpaths = javaProject.readRawClasspath();
        if (classpaths != null) {
            for (IClasspathEntry e : classpaths) {
                // ignore non exported entries, unless they're in the DEPEDENCIES container,
                // in which case we always want it (there may be some older projects that
                // have it as non exported).
                if (e.isExported() ||
                        (e.getEntryKind() == IClasspathEntry.CPE_CONTAINER &&
                         e.getPath().toString().equals(AdtConstants.CONTAINER_DEPENDENCIES))) {
                    handleCPE(e, javaProject, wsRoot, resMarker);
                }
            }
        }
    }

    private void handleCPE(IClasspathEntry entry, IJavaProject javaProject,
            IWorkspaceRoot wsRoot, ResourceMarker resMarker) {

        // if this is a classpath variable reference, we resolve it.
        if (entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
            entry = JavaCore.getResolvedClasspathEntry(entry);
        }

        if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
            IProject refProject = wsRoot.getProject(entry.getPath().lastSegment());
            try {
                // ignore if it's an Android project, or if it's not a Java Project
                if (refProject.hasNature(JavaCore.NATURE_ID) &&
                        refProject.hasNature(AdtConstants.NATURE_DEFAULT) == false) {
                    IJavaProject refJavaProject = JavaCore.create(refProject);

                    // get the output folder
                    IPath path = refJavaProject.getOutputLocation();
                    IResource outputResource = wsRoot.findMember(path);
                    if (outputResource != null && outputResource.getType() == IResource.FOLDER) {
                        mCompiledCodePaths.add(outputResource.getLocation().toOSString());
                    }
                }
            } catch (CoreException exception) {
                // can't query the project nature? ignore
            }

        } else if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
            handleClasspathLibrary(entry, wsRoot, resMarker);
        } else if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
            // get the container
            try {
                IClasspathContainer container = JavaCore.getClasspathContainer(
                        entry.getPath(), javaProject);
                // ignore the system and default_system types as they represent
                // libraries that are part of the runtime.
                if (container != null && container.getKind() == IClasspathContainer.K_APPLICATION) {
                    IClasspathEntry[] entries = container.getClasspathEntries();
                    for (IClasspathEntry cpe : entries) {
                        handleCPE(cpe, javaProject, wsRoot, resMarker);
                    }
                }
            } catch (JavaModelException jme) {
                // can't resolve the container? ignore it.
                AdtPlugin.log(jme, "Failed to resolve ClasspathContainer: %s", entry.getPath());
            }
        }
    }

    private void handleClasspathLibrary(IClasspathEntry e, IWorkspaceRoot wsRoot,
            ResourceMarker resMarker) {
        // get the IPath
        IPath path = e.getPath();

        IResource resource = wsRoot.findMember(path);

        if (resource != null && resource.getType() == IResource.PROJECT) {
            // if it's a project we should just ignore it because it's going to be added
            // later when we add all the referenced projects.

        } else if (SdkConstants.EXT_JAR.equalsIgnoreCase(path.getFileExtension())) {
            // case of a jar file (which could be relative to the workspace or a full path)
            if (resource != null && resource.exists() &&
                    resource.getType() == IResource.FILE) {
                mCompiledCodePaths.add(resource.getLocation().toOSString());
            } else {
                // if the jar path doesn't match a workspace resource,
                // then we get an OSString and check if this links to a valid file.
                String osFullPath = path.toOSString();

                File f = new File(osFullPath);
                if (f.isFile()) {
                    mCompiledCodePaths.add(osFullPath);
                } else {
                    String message = String.format( Messages.Couldnt_Locate_s_Error,
                            path);
                    // always output to the console
                    mOutStream.println(message);

                    // put a marker
                    if (resMarker != null) {
                        resMarker.setWarning(mProject, message);
                    }
                }
            }
        } else {
            // this can be the case for a class folder.
            if (resource != null && resource.exists() &&
                    resource.getType() == IResource.FOLDER) {
                mCompiledCodePaths.add(resource.getLocation().toOSString());
            } else {
                // if the path doesn't match a workspace resource,
                // then we get an OSString and check if this links to a valid folder.
                String osFullPath = path.toOSString();

                File f = new File(osFullPath);
                if (f.isDirectory()) {
                    mCompiledCodePaths.add(osFullPath);
                }
            }
        }
    }

    /**
     * Checks a {@link IFile} to make sure it should be packaged as standard resources.
     * @param file the IFile representing the file.
     * @return true if the file should be packaged as standard java resources.
     */
    public static boolean checkFileForPackaging(IFile file) {
        String name = file.getName();

        String ext = file.getFileExtension();
        return ApkBuilder.checkFileForPackaging(name, ext);
    }

    /**
     * Checks whether an {@link IFolder} and its content is valid for packaging into the .apk as
     * standard Java resource.
     * @param folder the {@link IFolder} to check.
     */
    public static boolean checkFolderForPackaging(IFolder folder) {
        String name = folder.getName();
        return ApkBuilder.checkFolderForPackaging(name);
    }

    /**
     * Returns a list of {@link IJavaProject} matching the provided {@link IProject} objects.
     * @param projects the IProject objects.
     * @return a new list object containing the IJavaProject object for the given IProject objects.
     * @throws CoreException
     */
    public static List<IJavaProject> getJavaProjects(List<IProject> projects) throws CoreException {
        ArrayList<IJavaProject> list = new ArrayList<IJavaProject>();

        for (IProject p : projects) {
            if (p.isOpen() && p.hasNature(JavaCore.NATURE_ID)) {

                list.add(JavaCore.create(p));
            }
        }

        return list;
    }

    /**
     * Get the stderr output of a process and return when the process is done.
     * @param process The process to get the output from
     * @param stderr The array to store the stderr output
     * @return the process return code.
     * @throws InterruptedException
     */
    public final static int grabProcessOutput(
            final IProject project,
            final Process process,
            final ArrayList<String> stderr)
            throws InterruptedException {

        return GrabProcessOutput.grabProcessOutput(
                process,
                Wait.WAIT_FOR_READERS, // we really want to make sure we get all the output!
                new IProcessOutput() {

                    @SuppressWarnings("unused")
                    @Override
                    public void out(@Nullable String line) {
                        if (line != null) {
                            // If benchmarking always print the lines that
                            // correspond to benchmarking info returned by ADT
                            if (BENCHMARK_FLAG && line.startsWith("BENCHMARK:")) {    //$NON-NLS-1$
                                AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS,
                                        project, line);
                            } else {
                                AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE,
                                        project, line);
                            }
                        }
                    }

                    @Override
                    public void err(@Nullable String line) {
                        if (line != null) {
                            stderr.add(line);
                            if (BuildVerbosity.VERBOSE == AdtPrefs.getPrefs().getBuildVerbosity()) {
                                AdtPlugin.printErrorToConsole(project, line);
                            }
                        }
                    }
                });
    }
}
