OSDN Git Service

original
[gb-231r1-is01/GB_2.3_IS01.git] / sdk / eclipse / plugins / com.android.ide.eclipse.adt / src / com / android / ide / eclipse / adt / internal / build / builders / PostCompilerBuilder.java
diff --git a/sdk/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java b/sdk/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java
new file mode 100644 (file)
index 0000000..1d3d13b
--- /dev/null
@@ -0,0 +1,661 @@
+/*
+ * Copyright (C) 2007 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.builders;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.AndroidConstants;
+import com.android.ide.eclipse.adt.AndroidPrintStream;
+import com.android.ide.eclipse.adt.internal.build.AaptExecException;
+import com.android.ide.eclipse.adt.internal.build.AaptParser;
+import com.android.ide.eclipse.adt.internal.build.AaptResultException;
+import com.android.ide.eclipse.adt.internal.build.BuildHelper;
+import com.android.ide.eclipse.adt.internal.build.DexException;
+import com.android.ide.eclipse.adt.internal.build.Messages;
+import com.android.ide.eclipse.adt.internal.build.NativeLibInJarException;
+import com.android.ide.eclipse.adt.internal.build.BuildHelper.ResourceMarker;
+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.ApkInstallManager;
+import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
+import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
+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.SdkConstants;
+import com.android.sdklib.build.ApkCreationException;
+import com.android.sdklib.build.DuplicateFileException;
+import com.android.sdklib.internal.build.DebugKeyProvider.KeytoolException;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jdt.core.IJavaModelMarker;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class PostCompilerBuilder extends BaseBuilder {
+
+    /** This ID is used in plugin.xml and in each project's .project file.
+     * It cannot be changed even if the class is renamed/moved */
+    public static final String ID = "com.android.ide.eclipse.adt.ApkBuilder"; //$NON-NLS-1$
+
+    private static final String PROPERTY_CONVERT_TO_DEX = "convertToDex"; //$NON-NLS-1$
+    private static final String PROPERTY_PACKAGE_RESOURCES = "packageResources"; //$NON-NLS-1$
+    private static final String PROPERTY_BUILD_APK = "buildApk"; //$NON-NLS-1$
+
+    /**
+     * Dex conversion flag. This is set to true if one of the changed/added/removed
+     * file is a .class file. Upon visiting all the delta resource, if this
+     * flag is true, then we know we'll have to make the "classes.dex" file.
+     */
+    private boolean mConvertToDex = false;
+
+    /**
+     * Package resources flag. This is set to true if one of the changed/added/removed
+     * file is a resource file. Upon visiting all the delta resource, if
+     * this flag is true, then we know we'll have to repackage the resources.
+     */
+    private boolean mPackageResources = false;
+
+    /**
+     * Final package build flag.
+     */
+    private boolean mBuildFinalPackage = false;
+
+    private AndroidPrintStream mOutStream = null;
+    private AndroidPrintStream mErrStream = null;
+
+    /**
+     * Basic Resource Delta Visitor class to check if a referenced project had a change in its
+     * compiled java files.
+     */
+    private static class ReferencedProjectDeltaVisitor implements IResourceDeltaVisitor {
+
+        private boolean mConvertToDex = false;
+        private boolean mMakeFinalPackage;
+
+        private IPath mOutputFolder;
+        private List<IPath> mSourceFolders;
+
+        private ReferencedProjectDeltaVisitor(IJavaProject javaProject) {
+            try {
+                mOutputFolder = javaProject.getOutputLocation();
+                mSourceFolders = BaseProjectHelper.getSourceClasspaths(javaProject);
+            } catch (JavaModelException e) {
+            } finally {
+            }
+        }
+
+        /**
+         * {@inheritDoc}
+         * @throws CoreException
+         */
+        public boolean visit(IResourceDelta delta) throws CoreException {
+            //  no need to keep looking if we already know we need to convert
+            // to dex and make the final package.
+            if (mConvertToDex && mMakeFinalPackage) {
+                return false;
+            }
+
+            // get the resource and the path segments.
+            IResource resource = delta.getResource();
+            IPath resourceFullPath = resource.getFullPath();
+
+            if (mOutputFolder.isPrefixOf(resourceFullPath)) {
+                int type = resource.getType();
+                if (type == IResource.FILE) {
+                    String ext = resource.getFileExtension();
+                    if (AndroidConstants.EXT_CLASS.equals(ext)) {
+                        mConvertToDex = true;
+                    }
+                }
+                return true;
+            } else {
+                for (IPath sourceFullPath : mSourceFolders) {
+                    if (sourceFullPath.isPrefixOf(resourceFullPath)) {
+                        int type = resource.getType();
+                        if (type == IResource.FILE) {
+                            // check if the file is a valid file that would be
+                            // included during the final packaging.
+                            if (BuildHelper.checkFileForPackaging((IFile)resource)) {
+                                mMakeFinalPackage = true;
+                            }
+
+                            return false;
+                        } else if (type == IResource.FOLDER) {
+                            // if this is a folder, we check if this is a valid folder as well.
+                            // If this is a folder that needs to be ignored, we must return false,
+                            // so that we ignore its content.
+                            return BuildHelper.checkFolderForPackaging((IFolder)resource);
+                        }
+                    }
+                }
+            }
+
+            return true;
+        }
+
+        /**
+         * Returns if one of the .class file was modified.
+         */
+        boolean needDexConvertion() {
+            return mConvertToDex;
+        }
+
+        boolean needMakeFinalPackage() {
+            return mMakeFinalPackage;
+        }
+    }
+
+    private ResourceMarker mResourceMarker = new ResourceMarker() {
+        public void setWarning(IResource resource, String message) {
+            BaseProjectHelper.markResource(resource, AndroidConstants.MARKER_PACKAGING,
+                    message, IMarker.SEVERITY_WARNING);
+        }
+    };
+
+
+    public PostCompilerBuilder() {
+        super();
+    }
+
+    @Override
+    protected void clean(IProgressMonitor monitor) throws CoreException {
+        super.clean(monitor);
+
+        // Get the project.
+        IProject project = getProject();
+
+        // Clear the project of the generic markers
+        removeMarkersFromContainer(project, AndroidConstants.MARKER_AAPT_PACKAGE);
+        removeMarkersFromContainer(project, AndroidConstants.MARKER_PACKAGING);
+    }
+
+    // build() returns a list of project from which this project depends for future compilation.
+    @SuppressWarnings({"unchecked"})
+    @Override
+    protected IProject[] build(int kind, Map args, IProgressMonitor monitor)
+            throws CoreException {
+        // get a project object
+        IProject project = getProject();
+
+        // list of referenced projects. This is a mix of java projects and library projects
+        // and is computed below.
+        IProject[] allRefProjects = null;
+
+        try {
+            // get the project info
+            ProjectState projectState = Sdk.getProjectState(project);
+            if (projectState == null || projectState.isLibrary()) {
+                // library project do not need to be dexified or packaged.
+                return null;
+            }
+
+            // get the libraries
+            List<IProject> libProjects = projectState.getFullLibraryProjects();
+
+            IJavaProject javaProject = JavaCore.create(project);
+
+            // get the list of referenced projects.
+            List<IProject> javaProjects = ProjectHelper.getReferencedProjects(project);
+            List<IJavaProject> referencedJavaProjects = BuildHelper.getJavaProjects(
+                    javaProjects);
+
+            // mix the java project and the library projects
+            final int size = libProjects.size() + javaProjects.size();
+            ArrayList<IProject> refList = new ArrayList<IProject>(size);
+            refList.addAll(libProjects);
+            refList.addAll(javaProjects);
+            allRefProjects = refList.toArray(new IProject[size]);
+
+            // Top level check to make sure the build can move forward.
+            abortOnBadSetup(javaProject);
+
+            // get the output folder, this method returns the path with a trailing
+            // separator
+            IFolder outputFolder = BaseProjectHelper.getOutputFolder(project);
+
+            // now we need to get the classpath list
+            List<IPath> sourceList = BaseProjectHelper.getSourceClasspaths(javaProject);
+
+            // First thing we do is go through the resource delta to not
+            // lose it if we have to abort the build for any reason.
+            PostCompilerDeltaVisitor dv = null;
+            if (kind == FULL_BUILD) {
+                AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project,
+                        Messages.Start_Full_Apk_Build);
+
+                mPackageResources = true;
+                mConvertToDex = true;
+                mBuildFinalPackage = true;
+            } else {
+                AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project,
+                        Messages.Start_Inc_Apk_Build);
+
+                // go through the resources and see if something changed.
+                IResourceDelta delta = getDelta(project);
+                if (delta == null) {
+                    mPackageResources = true;
+                    mConvertToDex = true;
+                    mBuildFinalPackage = true;
+                } else {
+                    dv = new PostCompilerDeltaVisitor(this, sourceList, outputFolder);
+                    delta.accept(dv);
+
+                    // save the state
+                    mPackageResources |= dv.getPackageResources();
+                    mConvertToDex |= dv.getConvertToDex();
+                    mBuildFinalPackage |= dv.getMakeFinalPackage();
+                }
+
+                // if the main resources didn't change, then we check for the library
+                // ones (will trigger resource repackaging too)
+                if ((mPackageResources == false || mBuildFinalPackage == false) &&
+                        libProjects.size() > 0) {
+                    for (IProject libProject : libProjects) {
+                        delta = getDelta(libProject);
+                        if (delta != null) {
+                            LibraryDeltaVisitor visitor = new LibraryDeltaVisitor();
+                            delta.accept(visitor);
+
+                            mPackageResources |= visitor.getResChange();
+                            mBuildFinalPackage |= visitor.getLibChange();
+
+                            if (mPackageResources && mBuildFinalPackage) {
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                // also go through the delta for all the referenced projects, until we are forced to
+                // compile anyway
+                final int referencedCount = referencedJavaProjects.size();
+                for (int i = 0 ; i < referencedCount &&
+                        (mBuildFinalPackage == false || mConvertToDex == false); i++) {
+                    IJavaProject referencedJavaProject = referencedJavaProjects.get(i);
+                    delta = getDelta(referencedJavaProject.getProject());
+                    if (delta != null) {
+                        ReferencedProjectDeltaVisitor refProjectDv =
+                                new ReferencedProjectDeltaVisitor(referencedJavaProject);
+
+                        delta.accept(refProjectDv);
+
+                        // save the state
+                        mConvertToDex |= refProjectDv.needDexConvertion();
+                        mBuildFinalPackage |= refProjectDv.needMakeFinalPackage();
+                    }
+                }
+            }
+
+            // store the build status in the persistent storage
+            saveProjectBooleanProperty(PROPERTY_CONVERT_TO_DEX , mConvertToDex);
+            saveProjectBooleanProperty(PROPERTY_PACKAGE_RESOURCES, mPackageResources);
+            saveProjectBooleanProperty(PROPERTY_BUILD_APK, mBuildFinalPackage);
+
+            if (dv != null && dv.mXmlError) {
+                AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project,
+                Messages.Xml_Error);
+
+                // if there was some XML errors, we just return w/o doing
+                // anything since we've put some markers in the files anyway
+                return allRefProjects;
+            }
+
+            // remove older packaging markers.
+            removeMarkersFromContainer(javaProject.getProject(), AndroidConstants.MARKER_PACKAGING);
+
+            if (outputFolder == null) {
+                // mark project and exit
+                markProject(AndroidConstants.MARKER_PACKAGING, Messages.Failed_To_Get_Output,
+                        IMarker.SEVERITY_ERROR);
+                return allRefProjects;
+            }
+
+            // first thing we do is check that the SDK directory has been setup.
+            String osSdkFolder = AdtPlugin.getOsSdkFolder();
+
+            if (osSdkFolder.length() == 0) {
+                // this has already been checked in the precompiler. Therefore,
+                // while we do have to cancel the build, we don't have to return
+                // any error or throw anything.
+                return allRefProjects;
+            }
+
+            // do some extra check, in case the output files are not present. This
+            // will force to recreate them.
+            IResource tmp = null;
+
+            if (mPackageResources == false) {
+                // check the full resource package
+                tmp = outputFolder.findMember(AndroidConstants.FN_RESOURCES_AP_);
+                if (tmp == null || tmp.exists() == false) {
+                    mPackageResources = true;
+                    mBuildFinalPackage = true;
+                }
+            }
+
+            // check classes.dex is present. If not we force to recreate it.
+            if (mConvertToDex == false) {
+                tmp = outputFolder.findMember(SdkConstants.FN_APK_CLASSES_DEX);
+                if (tmp == null || tmp.exists() == false) {
+                    mConvertToDex = true;
+                    mBuildFinalPackage = true;
+                }
+            }
+
+            // also check the final file(s)!
+            String finalPackageName = ProjectHelper.getApkFilename(project, null /*config*/);
+            if (mBuildFinalPackage == false) {
+                tmp = outputFolder.findMember(finalPackageName);
+                if (tmp == null || (tmp instanceof IFile &&
+                        tmp.exists() == false)) {
+                    String msg = String.format(Messages.s_Missing_Repackaging, finalPackageName);
+                    AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project, msg);
+                    mBuildFinalPackage = true;
+                }
+            }
+
+            // at this point we know if we need to recreate the temporary apk
+            // or the dex file, but we don't know if we simply need to recreate them
+            // because they are missing
+
+            // refresh the output directory first
+            IContainer ic = outputFolder.getParent();
+            if (ic != null) {
+                ic.refreshLocal(IResource.DEPTH_ONE, monitor);
+            }
+
+            // Get the DX output stream. Since the builder is created for the life of the
+            // project, they can be kept around.
+            if (mOutStream == null) {
+                mOutStream = new AndroidPrintStream(project, null /*prefix*/,
+                        AdtPlugin.getOutStream());
+                mErrStream = new AndroidPrintStream(project, null /*prefix*/,
+                        AdtPlugin.getOutStream());
+            }
+
+            // we need to test all three, as we may need to make the final package
+            // but not the intermediary ones.
+            if (mPackageResources || mConvertToDex || mBuildFinalPackage) {
+                BuildHelper helper = new BuildHelper(project,
+                        mOutStream, mErrStream,
+                        true /*debugMode*/,
+                        AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE);
+
+                // resource to the AndroidManifest.xml file
+                IFile manifestFile = project.getFile(SdkConstants.FN_ANDROID_MANIFEST_XML);
+
+                if (manifestFile == null || manifestFile.exists() == false) {
+                    // mark project and exit
+                    String msg = String.format(Messages.s_File_Missing,
+                            SdkConstants.FN_ANDROID_MANIFEST_XML);
+                    markProject(AndroidConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR);
+                    return allRefProjects;
+                }
+
+                IPath binLocation = outputFolder.getLocation();
+                if (binLocation == null) {
+                    markProject(AndroidConstants.MARKER_PACKAGING, Messages.Output_Missing,
+                            IMarker.SEVERITY_ERROR);
+                    return allRefProjects;
+                }
+                String osBinPath = binLocation.toOSString();
+
+                // Remove the old .apk.
+                // This make sure that if the apk is corrupted, then dx (which would attempt
+                // to open it), will not fail.
+                String osFinalPackagePath = osBinPath + File.separator + finalPackageName;
+                File finalPackage = new File(osFinalPackagePath);
+
+                // if delete failed, this is not really a problem, as the final package generation
+                // handle already present .apk, and if that one failed as well, the user will be
+                // notified.
+                finalPackage.delete();
+
+                // first we check if we need to package the resources.
+                if (mPackageResources) {
+                    // remove some aapt_package only markers.
+                    removeMarkersFromContainer(project, AndroidConstants.MARKER_AAPT_PACKAGE);
+
+                    try {
+                        helper.packageResources(manifestFile, libProjects, null /*resfilter*/,
+                                0 /*versionCode */, osBinPath,
+                                AndroidConstants.FN_RESOURCES_AP_);
+                    } catch (AaptExecException e) {
+                        BaseProjectHelper.markResource(project, AndroidConstants.MARKER_PACKAGING,
+                                e.getMessage(), IMarker.SEVERITY_ERROR);
+                        return allRefProjects;
+                    } catch (AaptResultException e) {
+                        // attempt to parse the error output
+                        String[] aaptOutput = e.getOutput();
+                        boolean parsingError = AaptParser.parseOutput(aaptOutput, project);
+
+                        // if we couldn't parse the output we display it in the console.
+                        if (parsingError) {
+                            AdtPlugin.printErrorToConsole(project, (Object[]) aaptOutput);
+
+                            // if the exec failed, and we couldn't parse the error output (and
+                            // therefore not all files that should have been marked, were marked),
+                            // we put a generic marker on the project and abort.
+                            BaseProjectHelper.markResource(project,
+                                    AndroidConstants.MARKER_PACKAGING,
+                                    Messages.Unparsed_AAPT_Errors,
+                                    IMarker.SEVERITY_ERROR);
+                        }
+                    }
+
+                    // build has been done. reset the state of the builder
+                    mPackageResources = false;
+
+                    // and store it
+                    saveProjectBooleanProperty(PROPERTY_PACKAGE_RESOURCES, mPackageResources);
+                }
+
+                // then we check if we need to package the .class into classes.dex
+                if (mConvertToDex) {
+                    try {
+                        String[] dxInputPaths = helper.getCompiledCodePaths(
+                                true /*includeProjectOutputs*/, mResourceMarker);
+
+                        helper.executeDx(javaProject, dxInputPaths, osBinPath + File.separator +
+                                SdkConstants.FN_APK_CLASSES_DEX);
+                    } catch (DexException e) {
+                        String message = e.getMessage();
+
+                        AdtPlugin.printErrorToConsole(project, message);
+                        BaseProjectHelper.markResource(project, AndroidConstants.MARKER_PACKAGING,
+                                message, IMarker.SEVERITY_ERROR);
+
+                        Throwable cause = e.getCause();
+
+                        if (cause instanceof NoClassDefFoundError
+                                || cause instanceof NoSuchMethodError) {
+                            AdtPlugin.printErrorToConsole(project, Messages.Incompatible_VM_Warning,
+                                    Messages.Requires_1_5_Error);
+                        }
+
+                        // dx failed, we return
+                        return allRefProjects;
+                    }
+
+                    // build has been done. reset the state of the builder
+                    mConvertToDex = false;
+
+                    // and store it
+                    saveProjectBooleanProperty(PROPERTY_CONVERT_TO_DEX, mConvertToDex);
+                }
+
+                // now we need to make the final package from the intermediary apk
+                // and classes.dex.
+                // This is the default package with all the resources.
+
+                String classesDexPath = osBinPath + File.separator +
+                        SdkConstants.FN_APK_CLASSES_DEX;
+                try {
+                    helper.finalDebugPackage(
+                        osBinPath + File.separator + AndroidConstants.FN_RESOURCES_AP_,
+                        classesDexPath, osFinalPackagePath,
+                        javaProject, libProjects, referencedJavaProjects, mResourceMarker);
+                } catch (KeytoolException e) {
+                    String eMessage = e.getMessage();
+
+                    // mark the project with the standard message
+                    String msg = String.format(Messages.Final_Archive_Error_s, eMessage);
+                    BaseProjectHelper.markResource(project, AndroidConstants.MARKER_PACKAGING, msg,
+                            IMarker.SEVERITY_ERROR);
+
+                    // output more info in the console
+                    AdtPlugin.printErrorToConsole(project,
+                            msg,
+                            String.format(Messages.ApkBuilder_JAVA_HOME_is_s, e.getJavaHome()),
+                            Messages.ApkBuilder_Update_or_Execute_manually_s,
+                            e.getCommandLine());
+
+                    return allRefProjects;
+                } catch (ApkCreationException e) {
+                    String eMessage = e.getMessage();
+
+                    // mark the project with the standard message
+                    String msg = String.format(Messages.Final_Archive_Error_s, eMessage);
+                    BaseProjectHelper.markResource(project, AndroidConstants.MARKER_PACKAGING, msg,
+                            IMarker.SEVERITY_ERROR);
+                } catch (AndroidLocationException e) {
+                    String eMessage = e.getMessage();
+
+                    // mark the project with the standard message
+                    String msg = String.format(Messages.Final_Archive_Error_s, eMessage);
+                    BaseProjectHelper.markResource(project, AndroidConstants.MARKER_PACKAGING, msg,
+                            IMarker.SEVERITY_ERROR);
+                } catch (NativeLibInJarException e) {
+                    String msg = e.getMessage();
+
+                    BaseProjectHelper.markResource(project, AndroidConstants.MARKER_PACKAGING,
+                            msg, IMarker.SEVERITY_ERROR);
+
+                    AdtPlugin.printErrorToConsole(project, (Object[]) e.getAdditionalInfo());
+                } catch (CoreException e) {
+                    // mark project and return
+                    String msg = String.format(Messages.Final_Archive_Error_s, e.getMessage());
+                    AdtPlugin.printErrorToConsole(project, msg);
+                    BaseProjectHelper.markResource(project, AndroidConstants.MARKER_PACKAGING, msg,
+                            IMarker.SEVERITY_ERROR);
+                } catch (DuplicateFileException e) {
+                    String msg1 = String.format(
+                            "Found duplicate file for APK: %1$s\nOrigin 1: %2$s\nOrigin 2: %3$s",
+                            e.getArchivePath(), e.getFile1(), e.getFile2());
+                    String msg2 = String.format(Messages.Final_Archive_Error_s, msg1);
+                    AdtPlugin.printErrorToConsole(project, msg2);
+                    BaseProjectHelper.markResource(project, AndroidConstants.MARKER_PACKAGING, msg2,
+                            IMarker.SEVERITY_ERROR);
+                }
+
+                // we are done.
+
+                // get the resource to bin
+                outputFolder.refreshLocal(IResource.DEPTH_ONE, monitor);
+
+                // build has been done. reset the state of the builder
+                mBuildFinalPackage = false;
+
+                // and store it
+                saveProjectBooleanProperty(PROPERTY_BUILD_APK, mBuildFinalPackage);
+
+                // reset the installation manager to force new installs of this project
+                ApkInstallManager.getInstance().resetInstallationFor(project);
+
+                AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, getProject(),
+                        "Build Success!");
+            }
+        } catch (AbortBuildException e) {
+            return allRefProjects;
+        } catch (Exception exception) {
+            // try to catch other exception to actually display an error. This will be useful
+            // if we get an NPE or something so that we can at least notify the user that something
+            // went wrong.
+
+            // first check if this is a CoreException we threw to cancel the build.
+            if (exception instanceof CoreException) {
+                if (((CoreException)exception).getStatus().getSeverity() == IStatus.CANCEL) {
+                    // Project is already marked with an error. Nothing to do
+                    return allRefProjects;
+                }
+            }
+
+            String msg = exception.getMessage();
+            if (msg == null) {
+                msg = exception.getClass().getCanonicalName();
+            }
+
+            msg = String.format("Unknown error: %1$s", msg);
+            AdtPlugin.logAndPrintError(exception, project.getName(), msg);
+            markProject(AndroidConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR);
+        }
+
+        return allRefProjects;
+    }
+
+    @Override
+    protected void startupOnInitialize() {
+        super.startupOnInitialize();
+
+        // load the build status. We pass true as the default value to
+        // force a recompile in case the property was not found
+        mConvertToDex = loadProjectBooleanProperty(PROPERTY_CONVERT_TO_DEX , true);
+        mPackageResources = loadProjectBooleanProperty(PROPERTY_PACKAGE_RESOURCES, true);
+        mBuildFinalPackage = loadProjectBooleanProperty(PROPERTY_BUILD_APK, true);
+    }
+
+    @Override
+    protected void abortOnBadSetup(IJavaProject javaProject) throws AbortBuildException {
+        super.abortOnBadSetup(javaProject);
+
+        IProject iProject = getProject();
+
+        // do a (hopefully quick) search for Precompiler type markers. Those are always only
+        // errors.
+        stopOnMarker(iProject, AndroidConstants.MARKER_AAPT_COMPILE, IResource.DEPTH_INFINITE,
+                false /*checkSeverity*/);
+        stopOnMarker(iProject, AndroidConstants.MARKER_AIDL, IResource.DEPTH_INFINITE,
+                false /*checkSeverity*/);
+        stopOnMarker(iProject, AndroidConstants.MARKER_RENDERSCRIPT, IResource.DEPTH_INFINITE,
+                false /*checkSeverity*/);
+        stopOnMarker(iProject, AndroidConstants.MARKER_ANDROID, IResource.DEPTH_ZERO,
+                false /*checkSeverity*/);
+
+        // do a search for JDT markers. Those can be errors or warnings
+        stopOnMarker(iProject, IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER,
+                IResource.DEPTH_INFINITE, true /*checkSeverity*/);
+        stopOnMarker(iProject, IJavaModelMarker.BUILDPATH_PROBLEM_MARKER,
+                IResource.DEPTH_INFINITE, true /*checkSeverity*/);
+    }
+}