--- /dev/null
+/*
+ * 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*/);
+ }
+}