diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java | 946 |
1 files changed, 0 insertions, 946 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java deleted file mode 100644 index 8aacb44ef..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java +++ /dev/null @@ -1,946 +0,0 @@ -/* - * 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.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.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.BuildHelper.ResourceMarker; -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.lint.LintDeltaProcessor; -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.LibraryClasspathContainerInitializer; -import com.android.ide.eclipse.adt.internal.project.ProjectHelper; -import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; -import com.android.ide.eclipse.adt.internal.sdk.ProjectState; -import com.android.ide.eclipse.adt.internal.sdk.Sdk; -import com.android.ide.eclipse.adt.io.IFileWrapper; -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.sdklib.build.ApkBuilder; -import com.android.sdklib.build.ApkCreationException; -import com.android.sdklib.build.DuplicateFileException; -import com.android.sdklib.build.IArchiveBuilder; -import com.android.sdklib.build.SealedApkException; -import com.android.sdklib.internal.build.DebugKeyProvider.KeytoolException; -import com.android.xml.AndroidManifest; - -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.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 java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.jar.Attributes; -import java.util.jar.JarEntry; -import java.util.jar.JarOutputStream; -import java.util.jar.Manifest; -import java.util.regex.Pattern; - -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$ - - /** Flag to pass to PostCompiler builder that sets if it runs or not. - * Set this flag whenever calling build if PostCompiler is to run - */ - public final static String POST_C_REQUESTED = "RunPostCompiler"; //$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; - - - private ResourceMarker mResourceMarker = new ResourceMarker() { - @Override - public void setWarning(IResource resource, String message) { - BaseProjectHelper.markResource(resource, AdtConstants.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(); - - if (DEBUG_LOG) { - AdtPlugin.log(IStatus.INFO, "%s CLEAN(POST)", project.getName()); - } - - // Clear the project of the generic markers - removeMarkersFromContainer(project, AdtConstants.MARKER_AAPT_PACKAGE); - removeMarkersFromContainer(project, AdtConstants.MARKER_PACKAGING); - - // also remove the files in the output folder (but not the Eclipse output folder). - IFolder javaOutput = BaseProjectHelper.getJavaOutputFolder(project); - IFolder androidOutput = BaseProjectHelper.getAndroidOutputFolder(project); - - if (javaOutput.equals(androidOutput) == false) { - // get the content - IResource[] members = androidOutput.members(); - for (IResource member : members) { - if (member.equals(javaOutput) == false) { - member.delete(true /*force*/, monitor); - } - } - } - } - - // build() returns a list of project from which this project depends for future compilation. - @Override - protected IProject[] build( - int kind, - @SuppressWarnings("rawtypes") Map args, - IProgressMonitor monitor) - throws CoreException { - // get a project object - IProject project = getProject(); - - if (DEBUG_LOG) { - AdtPlugin.log(IStatus.INFO, "%s BUILD(POST)", project.getName()); - } - - // Benchmarking start - long startBuildTime = 0; - if (BuildHelper.BENCHMARK_FLAG) { - // End JavaC Timer - String msg = "BENCHMARK ADT: Ending Compilation \n BENCHMARK ADT: Time Elapsed: " + //$NON-NLS-1$ - (System.nanoTime() - BuildHelper.sStartJavaCTime)/Math.pow(10, 6) + "ms"; //$NON-NLS-1$ - AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, project, msg); - msg = "BENCHMARK ADT: Starting PostCompilation"; //$NON-NLS-1$ - AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, project, msg); - startBuildTime = System.nanoTime(); - } - - // 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); - - // this can happen if the project has no project.properties. - if (projectState == null) { - return null; - } - - boolean isLibrary = projectState.isLibrary(); - - // 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]); - - // get the android output folder - IFolder androidOutputFolder = BaseProjectHelper.getAndroidOutputFolder(project); - IFolder resOutputFolder = androidOutputFolder.getFolder(SdkConstants.FD_RES); - - // First thing we do is go through the resource delta to not - // lose it if we have to abort the build for any reason. - if (args.containsKey(POST_C_REQUESTED) - && AdtPrefs.getPrefs().getBuildSkipPostCompileOnFileSave()) { - // Skip over flag setting - } else if (kind == FULL_BUILD) { - AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project, - Messages.Start_Full_Apk_Build); - - if (DEBUG_LOG) { - AdtPlugin.log(IStatus.INFO, "%s full build!", project.getName()); - } - - // Full build: we do all the steps. - 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) { - // no delta? Same as full build: we do all the steps. - mPackageResources = true; - mConvertToDex = true; - mBuildFinalPackage = true; - } else { - - if (ResourceManager.isAutoBuilding() && AdtPrefs.getPrefs().isLintOnSave()) { - // Check for errors on save/build, if enabled - LintDeltaProcessor.create().process(delta); - } - - PatternBasedDeltaVisitor dv = new PatternBasedDeltaVisitor( - project, project, - "POST:Main"); - - ChangedFileSet manifestCfs = ChangedFileSetHelper.getMergedManifestCfs(project); - dv.addSet(manifestCfs); - - ChangedFileSet resCfs = ChangedFileSetHelper.getResCfs(project); - dv.addSet(resCfs); - - ChangedFileSet androidCodeCfs = ChangedFileSetHelper.getCodeCfs(project); - dv.addSet(androidCodeCfs); - - ChangedFileSet javaResCfs = ChangedFileSetHelper.getJavaResCfs(project); - dv.addSet(javaResCfs); - dv.addSet(ChangedFileSetHelper.NATIVE_LIBS); - - delta.accept(dv); - - // save the state - mPackageResources |= dv.checkSet(manifestCfs) || dv.checkSet(resCfs); - - mConvertToDex |= dv.checkSet(androidCodeCfs); - - mBuildFinalPackage |= dv.checkSet(javaResCfs) || - dv.checkSet(ChangedFileSetHelper.NATIVE_LIBS); - } - - // check the libraries - if (libProjects.size() > 0) { - for (IProject libProject : libProjects) { - delta = getDelta(libProject); - if (delta != null) { - PatternBasedDeltaVisitor visitor = new PatternBasedDeltaVisitor( - project, libProject, - "POST:Lib"); - - ChangedFileSet libResCfs = ChangedFileSetHelper.getFullResCfs( - libProject); - visitor.addSet(libResCfs); - visitor.addSet(ChangedFileSetHelper.NATIVE_LIBS); - // FIXME: add check on the library.jar? - - delta.accept(visitor); - - mPackageResources |= visitor.checkSet(libResCfs); - mBuildFinalPackage |= visitor.checkSet( - ChangedFileSetHelper.NATIVE_LIBS); - } - } - } - - // also go through the delta for all the referenced projects - final int referencedCount = referencedJavaProjects.size(); - for (int i = 0 ; i < referencedCount; i++) { - IJavaProject referencedJavaProject = referencedJavaProjects.get(i); - delta = getDelta(referencedJavaProject.getProject()); - if (delta != null) { - IProject referencedProject = referencedJavaProject.getProject(); - PatternBasedDeltaVisitor visitor = new PatternBasedDeltaVisitor( - project, referencedProject, - "POST:RefedProject"); - - ChangedFileSet javaResCfs = ChangedFileSetHelper.getJavaResCfs(referencedProject); - visitor.addSet(javaResCfs); - - ChangedFileSet bytecodeCfs = ChangedFileSetHelper.getByteCodeCfs(referencedProject); - visitor.addSet(bytecodeCfs); - - delta.accept(visitor); - - // save the state - mConvertToDex |= visitor.checkSet(bytecodeCfs); - mBuildFinalPackage |= visitor.checkSet(javaResCfs); - } - } - } - - // store the build status in the persistent storage - saveProjectBooleanProperty(PROPERTY_CONVERT_TO_DEX, mConvertToDex); - saveProjectBooleanProperty(PROPERTY_PACKAGE_RESOURCES, mPackageResources); - saveProjectBooleanProperty(PROPERTY_BUILD_APK, mBuildFinalPackage); - - // Top level check to make sure the build can move forward. Only do this after recording - // delta changes. - abortOnBadSetup(javaProject, projectState); - - // Get the 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()); - } - - // remove older packaging markers. - removeMarkersFromContainer(javaProject.getProject(), AdtConstants.MARKER_PACKAGING); - - // finished with the common init and tests. Special case of the library. - if (isLibrary) { - // check the jar output file is present, if not create it. - IFile jarIFile = androidOutputFolder.getFile( - project.getName().toLowerCase() + SdkConstants.DOT_JAR); - if (mConvertToDex == false && jarIFile.exists() == false) { - mConvertToDex = true; - } - - // also update the crunch cache always since aapt does it smartly only - // on the files that need it. - if (DEBUG_LOG) { - AdtPlugin.log(IStatus.INFO, "%s running crunch!", project.getName()); - } - BuildHelper helper = new BuildHelper( - projectState, - mBuildToolInfo, - mOutStream, mErrStream, - false /*jumbo mode doesn't matter here*/, - false /*dex merger doesn't matter here*/, - true /*debugMode*/, - AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE, - mResourceMarker); - updateCrunchCache(project, helper); - - // refresh recursively bin/res folder - resOutputFolder.refreshLocal(IResource.DEPTH_INFINITE, monitor); - - if (mConvertToDex) { // in this case this means some class files changed and - // we need to update the jar file. - if (DEBUG_LOG) { - AdtPlugin.log(IStatus.INFO, "%s updating jar!", project.getName()); - } - - // resource to the AndroidManifest.xml file - IFile manifestFile = project.getFile(SdkConstants.FN_ANDROID_MANIFEST_XML); - String appPackage = AndroidManifest.getPackage(new IFileWrapper(manifestFile)); - - IFolder javaOutputFolder = BaseProjectHelper.getJavaOutputFolder(project); - - writeLibraryPackage(jarIFile, project, appPackage, javaOutputFolder); - saveProjectBooleanProperty(PROPERTY_CONVERT_TO_DEX, mConvertToDex = false); - - // refresh the bin folder content with no recursion to update the library - // jar file. - androidOutputFolder.refreshLocal(IResource.DEPTH_ONE, monitor); - - // Also update the projects. The only way to force recompile them is to - // reset the library container. - List<ProjectState> parentProjects = projectState.getParentProjects(); - LibraryClasspathContainerInitializer.updateProject(parentProjects); - } - - return allRefProjects; - } - - // Check to see if we're going to launch or export. If not, we can skip - // the packaging and dexing process. - if (!args.containsKey(POST_C_REQUESTED) - && AdtPrefs.getPrefs().getBuildSkipPostCompileOnFileSave()) { - AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project, - Messages.Skip_Post_Compiler); - return allRefProjects; - } else { - AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project, - Messages.Start_Full_Post_Compiler); - } - - // 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 = androidOutputFolder.findMember(AdtConstants.FN_RESOURCES_AP_); - if (tmp == null || tmp.exists() == false) { - mPackageResources = true; - } - } - - // check classes.dex is present. If not we force to recreate it. - if (mConvertToDex == false) { - tmp = androidOutputFolder.findMember(SdkConstants.FN_APK_CLASSES_DEX); - if (tmp == null || tmp.exists() == false) { - mConvertToDex = true; - } - } - - // also check the final file(s)! - String finalPackageName = ProjectHelper.getApkFilename(project, null /*config*/); - if (mBuildFinalPackage == false) { - tmp = androidOutputFolder.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 = androidOutputFolder.getParent(); - if (ic != null) { - ic.refreshLocal(IResource.DEPTH_ONE, monitor); - } - - // we need to test all three, as we may need to make the final package - // but not the intermediary ones. - if (mPackageResources || mConvertToDex || mBuildFinalPackage) { - String forceJumboStr = projectState.getProperty( - AdtConstants.DEX_OPTIONS_FORCEJUMBO); - Boolean jumbo = Boolean.valueOf(forceJumboStr); - - String dexMergerStr = projectState.getProperty( - AdtConstants.DEX_OPTIONS_DISABLE_MERGER); - Boolean dexMerger = Boolean.valueOf(dexMergerStr); - - BuildHelper helper = new BuildHelper( - projectState, - mBuildToolInfo, - mOutStream, mErrStream, - jumbo.booleanValue(), - dexMerger.booleanValue(), - true /*debugMode*/, - AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE, - mResourceMarker); - - IPath androidBinLocation = androidOutputFolder.getLocation(); - if (androidBinLocation == null) { - markProject(AdtConstants.MARKER_PACKAGING, Messages.Output_Missing, - IMarker.SEVERITY_ERROR); - return allRefProjects; - } - String osAndroidBinPath = androidBinLocation.toOSString(); - - // resource to the AndroidManifest.xml file - IFile manifestFile = androidOutputFolder.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(AdtConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR); - return allRefProjects; - } - - // 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 = osAndroidBinPath + 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(); - - // Check if we need to package the resources. - if (mPackageResources) { - // also update the crunch cache always since aapt does it smartly only - // on the files that need it. - if (DEBUG_LOG) { - AdtPlugin.log(IStatus.INFO, "%s running crunch!", project.getName()); - } - if (updateCrunchCache(project, helper) == false) { - return allRefProjects; - } - - // refresh recursively bin/res folder - resOutputFolder.refreshLocal(IResource.DEPTH_INFINITE, monitor); - - if (DEBUG_LOG) { - AdtPlugin.log(IStatus.INFO, "%s packaging resources!", project.getName()); - } - // remove some aapt_package only markers. - removeMarkersFromContainer(project, AdtConstants.MARKER_AAPT_PACKAGE); - - try { - helper.packageResources(manifestFile, libProjects, null /*resfilter*/, - 0 /*versionCode */, osAndroidBinPath, - AdtConstants.FN_RESOURCES_AP_); - } catch (AaptExecException e) { - BaseProjectHelper.markResource(project, AdtConstants.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, - AdtConstants.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); - } - - String classesDexPath = osAndroidBinPath + File.separator + - SdkConstants.FN_APK_CLASSES_DEX; - - // then we check if we need to package the .class into classes.dex - if (mConvertToDex) { - if (DEBUG_LOG) { - AdtPlugin.log(IStatus.INFO, "%s running dex!", project.getName()); - } - try { - Collection<String> dxInputPaths = helper.getCompiledCodePaths(); - - helper.executeDx(javaProject, dxInputPaths, classesDexPath); - } catch (DexException e) { - String message = e.getMessage(); - - AdtPlugin.printErrorToConsole(project, message); - BaseProjectHelper.markResource(project, AdtConstants.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. - - try { - if (DEBUG_LOG) { - AdtPlugin.log(IStatus.INFO, "%s making final package!", project.getName()); - } - helper.finalDebugPackage( - osAndroidBinPath + File.separator + AdtConstants.FN_RESOURCES_AP_, - classesDexPath, osFinalPackagePath, libProjects, 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, AdtConstants.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()); - - AdtPlugin.log(e, msg); - - 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, AdtConstants.MARKER_PACKAGING, msg, - IMarker.SEVERITY_ERROR); - - AdtPlugin.log(e, msg); - } 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, AdtConstants.MARKER_PACKAGING, msg, - IMarker.SEVERITY_ERROR); - AdtPlugin.log(e, msg); - } catch (NativeLibInJarException e) { - String msg = e.getMessage(); - - BaseProjectHelper.markResource(project, AdtConstants.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, AdtConstants.MARKER_PACKAGING, msg, - IMarker.SEVERITY_ERROR); - AdtPlugin.log(e, msg); - } 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, AdtConstants.MARKER_PACKAGING, msg2, - IMarker.SEVERITY_ERROR); - } - - // we are done. - - // refresh the bin folder content with no recursion. - androidOutputFolder.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(AdtConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR); - } - - // Benchmarking end - if (BuildHelper.BENCHMARK_FLAG) { - String msg = "BENCHMARK ADT: Ending PostCompilation. \n BENCHMARK ADT: Time Elapsed: " + //$NON-NLS-1$ - ((System.nanoTime() - startBuildTime)/Math.pow(10, 6)) + "ms"; //$NON-NLS-1$ - AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, project, msg); - // End Overall Timer - msg = "BENCHMARK ADT: Done with everything! \n BENCHMARK ADT: Time Elapsed: " + //$NON-NLS-1$ - (System.nanoTime() - BuildHelper.sStartOverallTime)/Math.pow(10, 6) + "ms"; //$NON-NLS-1$ - AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, project, msg); - } - - return allRefProjects; - } - - private static class JarBuilder implements IArchiveBuilder { - - private static Pattern R_PATTERN = Pattern.compile("R(\\$.*)?\\.class"); //$NON-NLS-1$ - private static String BUILD_CONFIG_CLASS = "BuildConfig.class"; //$NON-NLS-1$ - - private final byte[] buffer = new byte[1024]; - private final JarOutputStream mOutputStream; - private final String mAppPackage; - - JarBuilder(JarOutputStream outputStream, String appPackage) { - mOutputStream = outputStream; - mAppPackage = appPackage.replace('.', '/'); - } - - public void addFile(IFile file, IFolder rootFolder) throws ApkCreationException { - // we only package class file from the output folder - if (SdkConstants.EXT_CLASS.equals(file.getFileExtension()) == false) { - return; - } - - IPath packageApp = file.getParent().getFullPath().makeRelativeTo( - rootFolder.getFullPath()); - - String name = file.getName(); - // Ignore the library's R/Manifest/BuildConfig classes. - if (mAppPackage.equals(packageApp.toString()) && - (BUILD_CONFIG_CLASS.equals(name) || - R_PATTERN.matcher(name).matches())) { - return; - } - - IPath path = file.getFullPath().makeRelativeTo(rootFolder.getFullPath()); - try { - addFile(file.getContents(), file.getLocalTimeStamp(), path.toString()); - } catch (ApkCreationException e) { - throw e; - } catch (Exception e) { - throw new ApkCreationException(e, "Failed to add %s", file); - } - } - - @Override - public void addFile(File file, String archivePath) throws ApkCreationException, - SealedApkException, DuplicateFileException { - try { - FileInputStream inputStream = new FileInputStream(file); - long lastModified = file.lastModified(); - addFile(inputStream, lastModified, archivePath); - } catch (ApkCreationException e) { - throw e; - } catch (Exception e) { - throw new ApkCreationException(e, "Failed to add %s", file); - } - } - - private void addFile(InputStream content, long lastModified, String archivePath) - throws IOException, ApkCreationException { - // create the jar entry - JarEntry entry = new JarEntry(archivePath); - entry.setTime(lastModified); - - try { - // add the entry to the jar archive - mOutputStream.putNextEntry(entry); - - // read the content of the entry from the input stream, and write - // it into the archive. - int count; - while ((count = content.read(buffer)) != -1) { - mOutputStream.write(buffer, 0, count); - } - } finally { - try { - if (content != null) { - content.close(); - } - } catch (Exception e) { - throw new ApkCreationException(e, "Failed to close stream"); - } - } - } - } - - /** - * Updates the crunch cache if needed and return true if the build must continue. - */ - private boolean updateCrunchCache(IProject project, BuildHelper helper) { - try { - helper.updateCrunchCache(); - } catch (AaptExecException e) { - BaseProjectHelper.markResource(project, AdtConstants.MARKER_PACKAGING, - e.getMessage(), IMarker.SEVERITY_ERROR); - return false; - } 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); - } - } - - return true; - } - - /** - * Writes the library jar file. - * @param jarIFile the destination file - * @param project the library project - * @param appPackage the library android package - * @param javaOutputFolder the JDT output folder. - */ - private void writeLibraryPackage(IFile jarIFile, IProject project, String appPackage, - IFolder javaOutputFolder) { - - JarOutputStream jos = null; - try { - Manifest manifest = new Manifest(); - Attributes mainAttributes = manifest.getMainAttributes(); - mainAttributes.put(Attributes.Name.CLASS_PATH, "Android ADT"); //$NON-NLS-1$ - mainAttributes.putValue("Created-By", "1.0 (Android)"); //$NON-NLS-1$ //$NON-NLS-2$ - jos = new JarOutputStream( - new FileOutputStream(jarIFile.getLocation().toFile()), manifest); - - JarBuilder jarBuilder = new JarBuilder(jos, appPackage); - - // write the class files - writeClassFilesIntoJar(jarBuilder, javaOutputFolder, javaOutputFolder); - - // now write the standard Java resources from the output folder - ApkBuilder.addSourceFolder(jarBuilder, javaOutputFolder.getLocation().toFile()); - - saveProjectBooleanProperty(PROPERTY_CONVERT_TO_DEX, mConvertToDex); - } catch (Exception e) { - AdtPlugin.log(e, "Failed to write jar file %s", jarIFile.getLocation().toOSString()); - } finally { - if (jos != null) { - try { - jos.close(); - } catch (IOException e) { - // pass - } - } - } - } - - private void writeClassFilesIntoJar(JarBuilder builder, IFolder folder, IFolder rootFolder) - throws CoreException, IOException, ApkCreationException { - IResource[] members = folder.members(); - for (IResource member : members) { - if (member.getType() == IResource.FOLDER) { - writeClassFilesIntoJar(builder, (IFolder) member, rootFolder); - } else if (member.getType() == IResource.FILE) { - IFile file = (IFile) member; - builder.addFile(file, rootFolder); - } - } - } - - @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( - @NonNull IJavaProject javaProject, - @Nullable ProjectState projectState) throws AbortBuildException, CoreException { - super.abortOnBadSetup(javaProject, projectState); - - IProject iProject = getProject(); - - // do a (hopefully quick) search for Precompiler type markers. Those are always only - // errors. - stopOnMarker(iProject, AdtConstants.MARKER_AAPT_COMPILE, IResource.DEPTH_INFINITE, - false /*checkSeverity*/); - stopOnMarker(iProject, AdtConstants.MARKER_AIDL, IResource.DEPTH_INFINITE, - false /*checkSeverity*/); - stopOnMarker(iProject, AdtConstants.MARKER_RENDERSCRIPT, IResource.DEPTH_INFINITE, - false /*checkSeverity*/); - stopOnMarker(iProject, AdtConstants.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*/); - } -} |