diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ProjectHelper.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ProjectHelper.java | 1153 |
1 files changed, 0 insertions, 1153 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ProjectHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ProjectHelper.java deleted file mode 100644 index a32b4ca8b..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ProjectHelper.java +++ /dev/null @@ -1,1153 +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.project; - -import static com.android.ide.eclipse.adt.AdtConstants.COMPILER_COMPLIANCE_PREFERRED; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.ide.common.xml.ManifestData; -import com.android.ide.eclipse.adt.AdtConstants; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.build.builders.PostCompilerBuilder; -import com.android.ide.eclipse.adt.internal.build.builders.PreCompilerBuilder; -import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; -import com.android.ide.eclipse.adt.internal.sdk.ProjectState; -import com.android.ide.eclipse.adt.internal.sdk.Sdk; -import com.android.sdklib.BuildToolInfo; -import com.android.sdklib.IAndroidTarget; -import com.android.utils.Pair; - -import org.eclipse.core.resources.ICommand; -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.IProjectDescription; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IWorkspace; -import org.eclipse.core.resources.IncrementalProjectBuilder; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.Path; -import org.eclipse.core.runtime.QualifiedName; -import org.eclipse.jdt.core.IClasspathEntry; -import org.eclipse.jdt.core.IJavaModel; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.internal.corext.util.JavaModelUtil; -import org.eclipse.jdt.launching.IVMInstall; -import org.eclipse.jdt.launching.IVMInstall2; -import org.eclipse.jdt.launching.IVMInstallType; -import org.eclipse.jdt.launching.JavaRuntime; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -/** - * Utility class to manipulate Project parameters/properties. - */ -public final class ProjectHelper { - public final static int COMPILER_COMPLIANCE_OK = 0; - public final static int COMPILER_COMPLIANCE_LEVEL = 1; - public final static int COMPILER_COMPLIANCE_SOURCE = 2; - public final static int COMPILER_COMPLIANCE_CODEGEN_TARGET = 3; - - /** - * Adds the given ClasspathEntry object to the class path entries. - * This method does not check whether the entry is already defined in the project. - * - * @param entries The class path entries to read. A copy will be returned. - * @param newEntry The new class path entry to add. - * @return A new class path entries array. - */ - public static IClasspathEntry[] addEntryToClasspath( - IClasspathEntry[] entries, IClasspathEntry newEntry) { - int n = entries.length; - IClasspathEntry[] newEntries = new IClasspathEntry[n + 1]; - System.arraycopy(entries, 0, newEntries, 0, n); - newEntries[n] = newEntry; - return newEntries; - } - - /** - * Replaces the given ClasspathEntry in the classpath entries. - * - * If the classpath does not yet exists (Check is based on entry path), then it is added. - * - * @param entries The class path entries to read. The same array (replace) or a copy (add) - * will be returned. - * @param newEntry The new class path entry to add. - * @return The same array (replace) or a copy (add) will be returned. - * - * @see IClasspathEntry#getPath() - */ - public static IClasspathEntry[] replaceEntryInClasspath( - IClasspathEntry[] entries, IClasspathEntry newEntry) { - - IPath path = newEntry.getPath(); - for (int i = 0, count = entries.length; i < count ; i++) { - if (path.equals(entries[i].getPath())) { - entries[i] = newEntry; - return entries; - } - } - - return addEntryToClasspath(entries, newEntry); - } - - /** - * Adds the corresponding source folder to the project's class path entries. - * This method does not check whether the entry is already defined in the project. - * - * @param javaProject The java project of which path entries to update. - * @param newEntry The new class path entry to add. - * @throws JavaModelException - */ - public static void addEntryToClasspath(IJavaProject javaProject, IClasspathEntry newEntry) - throws JavaModelException { - - IClasspathEntry[] entries = javaProject.getRawClasspath(); - entries = addEntryToClasspath(entries, newEntry); - javaProject.setRawClasspath(entries, new NullProgressMonitor()); - } - - /** - * Checks whether the given class path entry is already defined in the project. - * - * @param javaProject The java project of which path entries to check. - * @param newEntry The parent source folder to remove. - * @return True if the class path entry is already defined. - * @throws JavaModelException - */ - public static boolean isEntryInClasspath(IJavaProject javaProject, IClasspathEntry newEntry) - throws JavaModelException { - - IClasspathEntry[] entries = javaProject.getRawClasspath(); - for (IClasspathEntry entry : entries) { - if (entry.equals(newEntry)) { - return true; - } - } - return false; - } - - /** - * Remove a classpath entry from the array. - * @param entries The class path entries to read. A copy will be returned - * @param index The index to remove. - * @return A new class path entries array. - */ - public static IClasspathEntry[] removeEntryFromClasspath( - IClasspathEntry[] entries, int index) { - int n = entries.length; - IClasspathEntry[] newEntries = new IClasspathEntry[n-1]; - - // copy the entries before index - System.arraycopy(entries, 0, newEntries, 0, index); - - // copy the entries after index - System.arraycopy(entries, index + 1, newEntries, index, - entries.length - index - 1); - - return newEntries; - } - - /** - * Converts a OS specific path into a path valid for the java doc location - * attributes of a project. - * @param javaDocOSLocation The OS specific path. - * @return a valid path for the java doc location. - */ - public static String getJavaDocPath(String javaDocOSLocation) { - // first thing we do is convert the \ into / - String javaDoc = javaDocOSLocation.replaceAll("\\\\", //$NON-NLS-1$ - AdtConstants.WS_SEP); - - // then we add file: at the beginning for unix path, and file:/ for non - // unix path - if (javaDoc.startsWith(AdtConstants.WS_SEP)) { - return "file:" + javaDoc; //$NON-NLS-1$ - } - - return "file:/" + javaDoc; //$NON-NLS-1$ - } - - /** - * Look for a specific classpath entry by full path and return its index. - * @param entries The entry array to search in. - * @param entryPath The OS specific path of the entry. - * @param entryKind The kind of the entry. Accepted values are 0 - * (no filter), IClasspathEntry.CPE_LIBRARY, IClasspathEntry.CPE_PROJECT, - * IClasspathEntry.CPE_SOURCE, IClasspathEntry.CPE_VARIABLE, - * and IClasspathEntry.CPE_CONTAINER - * @return the index of the found classpath entry or -1. - */ - public static int findClasspathEntryByPath(IClasspathEntry[] entries, - String entryPath, int entryKind) { - for (int i = 0 ; i < entries.length ; i++) { - IClasspathEntry entry = entries[i]; - - int kind = entry.getEntryKind(); - - if (kind == entryKind || entryKind == 0) { - // get the path - IPath path = entry.getPath(); - - String osPathString = path.toOSString(); - if (osPathString.equals(entryPath)) { - return i; - } - } - } - - // not found, return bad index. - return -1; - } - - /** - * Look for a specific classpath entry for file name only and return its - * index. - * @param entries The entry array to search in. - * @param entryName The filename of the entry. - * @param entryKind The kind of the entry. Accepted values are 0 - * (no filter), IClasspathEntry.CPE_LIBRARY, IClasspathEntry.CPE_PROJECT, - * IClasspathEntry.CPE_SOURCE, IClasspathEntry.CPE_VARIABLE, - * and IClasspathEntry.CPE_CONTAINER - * @param startIndex Index where to start the search - * @return the index of the found classpath entry or -1. - */ - public static int findClasspathEntryByName(IClasspathEntry[] entries, - String entryName, int entryKind, int startIndex) { - if (startIndex < 0) { - startIndex = 0; - } - for (int i = startIndex ; i < entries.length ; i++) { - IClasspathEntry entry = entries[i]; - - int kind = entry.getEntryKind(); - - if (kind == entryKind || entryKind == 0) { - // get the path - IPath path = entry.getPath(); - String name = path.segment(path.segmentCount()-1); - - if (name.equals(entryName)) { - return i; - } - } - } - - // not found, return bad index. - return -1; - } - - public static boolean updateProject(IJavaProject project) { - return updateProjects(new IJavaProject[] { project}); - } - - /** - * Update the android-specific projects's classpath containers. - * @param projects the projects to update - * @return - */ - public static boolean updateProjects(IJavaProject[] projects) { - boolean r = AndroidClasspathContainerInitializer.updateProjects(projects); - if (r) { - return LibraryClasspathContainerInitializer.updateProjects(projects); - } - return false; - } - - /** - * Fix the project. This checks the SDK location. - * @param project The project to fix. - * @throws JavaModelException - */ - public static void fixProject(IProject project) throws JavaModelException { - if (AdtPlugin.getOsSdkFolder().length() == 0) { - AdtPlugin.printToConsole(project, "Unknown SDK Location, project not fixed."); - return; - } - - // get a java project - IJavaProject javaProject = JavaCore.create(project); - fixProjectClasspathEntries(javaProject); - } - - /** - * Fix the project classpath entries. The method ensures that: - * <ul> - * <li>The project does not reference any old android.zip/android.jar archive.</li> - * <li>The project does not use its output folder as a sourc folder.</li> - * <li>The project does not reference a desktop JRE</li> - * <li>The project references the AndroidClasspathContainer. - * </ul> - * @param javaProject The project to fix. - * @throws JavaModelException - */ - public static void fixProjectClasspathEntries(IJavaProject javaProject) - throws JavaModelException { - - // get the project classpath - IClasspathEntry[] entries = javaProject.getRawClasspath(); - IClasspathEntry[] oldEntries = entries; - boolean forceRewriteOfCPE = false; - - // check if the JRE is set as library - int jreIndex = ProjectHelper.findClasspathEntryByPath(entries, JavaRuntime.JRE_CONTAINER, - IClasspathEntry.CPE_CONTAINER); - if (jreIndex != -1) { - // the project has a JRE included, we remove it - entries = ProjectHelper.removeEntryFromClasspath(entries, jreIndex); - } - - // get the output folder - IPath outputFolder = javaProject.getOutputLocation(); - - boolean foundFrameworkContainer = false; - IClasspathEntry foundLibrariesContainer = null; - IClasspathEntry foundDependenciesContainer = null; - - for (int i = 0 ; i < entries.length ;) { - // get the entry and kind - IClasspathEntry entry = entries[i]; - int kind = entry.getEntryKind(); - - if (kind == IClasspathEntry.CPE_SOURCE) { - IPath path = entry.getPath(); - - if (path.equals(outputFolder)) { - entries = ProjectHelper.removeEntryFromClasspath(entries, i); - - // continue, to skip the i++; - continue; - } - } else if (kind == IClasspathEntry.CPE_CONTAINER) { - String path = entry.getPath().toString(); - if (AdtConstants.CONTAINER_FRAMEWORK.equals(path)) { - foundFrameworkContainer = true; - } else if (AdtConstants.CONTAINER_PRIVATE_LIBRARIES.equals(path)) { - foundLibrariesContainer = entry; - } else if (AdtConstants.CONTAINER_DEPENDENCIES.equals(path)) { - foundDependenciesContainer = entry; - } - } - - i++; - } - - // look to see if we have the m2eclipse nature - boolean m2eNature = false; - try { - m2eNature = javaProject.getProject().hasNature("org.eclipse.m2e.core.maven2Nature"); - } catch (CoreException e) { - AdtPlugin.log(e, "Failed to query project %s for m2e nature", - javaProject.getProject().getName()); - } - - - // if the framework container is not there, we add it - if (!foundFrameworkContainer) { - // add the android container to the array - entries = ProjectHelper.addEntryToClasspath(entries, - JavaCore.newContainerEntry(new Path(AdtConstants.CONTAINER_FRAMEWORK))); - } - - // same thing for the library container - if (foundLibrariesContainer == null) { - // add the exported libraries android container to the array - entries = ProjectHelper.addEntryToClasspath(entries, - JavaCore.newContainerEntry( - new Path(AdtConstants.CONTAINER_PRIVATE_LIBRARIES), true)); - } else if (!m2eNature && !foundLibrariesContainer.isExported()) { - // the container is present but it's not exported and since there's no m2e nature - // we do want it to be exported. - // keep all the other parameters the same. - entries = ProjectHelper.replaceEntryInClasspath(entries, - JavaCore.newContainerEntry( - new Path(AdtConstants.CONTAINER_PRIVATE_LIBRARIES), - foundLibrariesContainer.getAccessRules(), - foundLibrariesContainer.getExtraAttributes(), - true)); - forceRewriteOfCPE = true; - } - - // same thing for the dependencies container - if (foundDependenciesContainer == null) { - // add the android dependencies container to the array - entries = ProjectHelper.addEntryToClasspath(entries, - JavaCore.newContainerEntry( - new Path(AdtConstants.CONTAINER_DEPENDENCIES), true)); - } else if (!m2eNature && !foundDependenciesContainer.isExported()) { - // the container is present but it's not exported and since there's no m2e nature - // we do want it to be exported. - // keep all the other parameters the same. - entries = ProjectHelper.replaceEntryInClasspath(entries, - JavaCore.newContainerEntry( - new Path(AdtConstants.CONTAINER_DEPENDENCIES), - foundDependenciesContainer.getAccessRules(), - foundDependenciesContainer.getExtraAttributes(), - true)); - forceRewriteOfCPE = true; - } - - // set the new list of entries to the project - if (entries != oldEntries || forceRewriteOfCPE) { - javaProject.setRawClasspath(entries, new NullProgressMonitor()); - } - - // If needed, check and fix compiler compliance and source compatibility - ProjectHelper.checkAndFixCompilerCompliance(javaProject); - } - - - /** - * Checks the project compiler compliance level is supported. - * @param javaProject The project to check - * @return A pair with the first integer being an error code, and the second value - * being the invalid value found or null. The error code can be: <ul> - * <li><code>COMPILER_COMPLIANCE_OK</code> if the project is properly configured</li> - * <li><code>COMPILER_COMPLIANCE_LEVEL</code> for unsupported compiler level</li> - * <li><code>COMPILER_COMPLIANCE_SOURCE</code> for unsupported source compatibility</li> - * <li><code>COMPILER_COMPLIANCE_CODEGEN_TARGET</code> for unsupported .class format</li> - * </ul> - */ - public static final Pair<Integer, String> checkCompilerCompliance(IJavaProject javaProject) { - // get the project compliance level option - String compliance = javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true); - - // check it against a list of valid compliance level strings. - if (!checkCompliance(javaProject, compliance)) { - // if we didn't find the proper compliance level, we return an error - return Pair.of(COMPILER_COMPLIANCE_LEVEL, compliance); - } - - // otherwise we check source compatibility - String source = javaProject.getOption(JavaCore.COMPILER_SOURCE, true); - - // check it against a list of valid compliance level strings. - if (!checkCompliance(javaProject, source)) { - // if we didn't find the proper compliance level, we return an error - return Pair.of(COMPILER_COMPLIANCE_SOURCE, source); - } - - // otherwise check codegen level - String codeGen = javaProject.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true); - - // check it against a list of valid compliance level strings. - if (!checkCompliance(javaProject, codeGen)) { - // if we didn't find the proper compliance level, we return an error - return Pair.of(COMPILER_COMPLIANCE_CODEGEN_TARGET, codeGen); - } - - return Pair.of(COMPILER_COMPLIANCE_OK, null); - } - - /** - * Checks the project compiler compliance level is supported. - * @param project The project to check - * @return A pair with the first integer being an error code, and the second value - * being the invalid value found or null. The error code can be: <ul> - * <li><code>COMPILER_COMPLIANCE_OK</code> if the project is properly configured</li> - * <li><code>COMPILER_COMPLIANCE_LEVEL</code> for unsupported compiler level</li> - * <li><code>COMPILER_COMPLIANCE_SOURCE</code> for unsupported source compatibility</li> - * <li><code>COMPILER_COMPLIANCE_CODEGEN_TARGET</code> for unsupported .class format</li> - * </ul> - */ - public static final Pair<Integer, String> checkCompilerCompliance(IProject project) { - // get the java project from the IProject resource object - IJavaProject javaProject = JavaCore.create(project); - - // check and return the result. - return checkCompilerCompliance(javaProject); - } - - - /** - * Checks, and fixes if needed, the compiler compliance level, and the source compatibility - * level - * @param project The project to check and fix. - */ - public static final void checkAndFixCompilerCompliance(IProject project) { - // FIXME This method is never used. Shall we just removed it? - // {@link #checkAndFixCompilerCompliance(IJavaProject)} is used instead. - - // get the java project from the IProject resource object - IJavaProject javaProject = JavaCore.create(project); - - // Now we check the compiler compliance level and make sure it is valid - checkAndFixCompilerCompliance(javaProject); - } - - /** - * Checks, and fixes if needed, the compiler compliance level, and the source compatibility - * level - * @param javaProject The Java project to check and fix. - */ - public static final void checkAndFixCompilerCompliance(IJavaProject javaProject) { - Pair<Integer, String> result = checkCompilerCompliance(javaProject); - if (result.getFirst().intValue() != COMPILER_COMPLIANCE_OK) { - // setup the preferred compiler compliance level. - javaProject.setOption(JavaCore.COMPILER_COMPLIANCE, - AdtConstants.COMPILER_COMPLIANCE_PREFERRED); - javaProject.setOption(JavaCore.COMPILER_SOURCE, - AdtConstants.COMPILER_COMPLIANCE_PREFERRED); - javaProject.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, - AdtConstants.COMPILER_COMPLIANCE_PREFERRED); - - // clean the project to make sure we recompile - try { - javaProject.getProject().build(IncrementalProjectBuilder.CLEAN_BUILD, - new NullProgressMonitor()); - } catch (CoreException e) { - AdtPlugin.printErrorToConsole(javaProject.getProject(), - "Project compiler settings changed. Clean your project."); - } - } - } - - /** - * Makes the given project use JDK 6 (or more specifically, - * {@link AdtConstants#COMPILER_COMPLIANCE_PREFERRED} as the compilation - * target, regardless of what the default IDE JDK level is, provided a JRE - * of the given level is installed. - * - * @param javaProject the Java project - * @throws CoreException if the IDE throws an exception setting the compiler - * level - */ - @SuppressWarnings("restriction") // JDT API for setting compliance options - public static void enforcePreferredCompilerCompliance(@NonNull IJavaProject javaProject) - throws CoreException { - String compliance = javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true); - if (compliance == null || - JavaModelUtil.isVersionLessThan(compliance, COMPILER_COMPLIANCE_PREFERRED)) { - IVMInstallType[] types = JavaRuntime.getVMInstallTypes(); - for (int i = 0; i < types.length; i++) { - IVMInstallType type = types[i]; - IVMInstall[] installs = type.getVMInstalls(); - for (int j = 0; j < installs.length; j++) { - IVMInstall install = installs[j]; - if (install instanceof IVMInstall2) { - IVMInstall2 install2 = (IVMInstall2) install; - // Java version can be 1.6.0, and preferred is 1.6 - if (install2.getJavaVersion().startsWith(COMPILER_COMPLIANCE_PREFERRED)) { - Map<String, String> options = javaProject.getOptions(false); - JavaCore.setComplianceOptions(COMPILER_COMPLIANCE_PREFERRED, options); - JavaModelUtil.setDefaultClassfileOptions(options, - COMPILER_COMPLIANCE_PREFERRED); - javaProject.setOptions(options); - return; - } - } - } - } - } - } - - /** - * Returns a {@link IProject} by its running application name, as it returned by the AVD. - * <p/> - * <var>applicationName</var> will in most case be the package declared in the manifest, but - * can, in some cases, be a custom process name declared in the manifest, in the - * <code>application</code>, <code>activity</code>, <code>receiver</code>, or - * <code>service</code> nodes. - * @param applicationName The application name. - * @return a project or <code>null</code> if no matching project were found. - */ - public static IProject findAndroidProjectByAppName(String applicationName) { - // Get the list of project for the current workspace - IWorkspace workspace = ResourcesPlugin.getWorkspace(); - IProject[] projects = workspace.getRoot().getProjects(); - - // look for a project that matches the packageName of the app - // we're trying to debug - for (IProject p : projects) { - if (p.isOpen()) { - try { - if (p.hasNature(AdtConstants.NATURE_DEFAULT) == false) { - // ignore non android projects - continue; - } - } catch (CoreException e) { - // failed to get the nature? skip project. - continue; - } - - // check that there is indeed a manifest file. - IFile manifestFile = getManifest(p); - if (manifestFile == null) { - // no file? skip this project. - continue; - } - - ManifestData data = AndroidManifestHelper.parseForData(manifestFile); - if (data == null) { - // skip this project. - continue; - } - - String manifestPackage = data.getPackage(); - - if (manifestPackage != null && manifestPackage.equals(applicationName)) { - // this is the project we were looking for! - return p; - } else { - // if the package and application name don't match, - // we look for other possible process names declared in the manifest. - String[] processes = data.getProcesses(); - for (String process : processes) { - if (process.equals(applicationName)) { - return p; - } - } - } - } - } - - return null; - - } - - public static void fixProjectNatureOrder(IProject project) throws CoreException { - IProjectDescription description = project.getDescription(); - String[] natures = description.getNatureIds(); - - // if the android nature is not the first one, we reorder them - if (AdtConstants.NATURE_DEFAULT.equals(natures[0]) == false) { - // look for the index - for (int i = 0 ; i < natures.length ; i++) { - if (AdtConstants.NATURE_DEFAULT.equals(natures[i])) { - // if we try to just reorder the array in one pass, this doesn't do - // anything. I guess JDT check that we are actually adding/removing nature. - // So, first we'll remove the android nature, and then add it back. - - // remove the android nature - removeNature(project, AdtConstants.NATURE_DEFAULT); - - // now add it back at the first index. - description = project.getDescription(); - natures = description.getNatureIds(); - - String[] newNatures = new String[natures.length + 1]; - - // first one is android - newNatures[0] = AdtConstants.NATURE_DEFAULT; - - // next the rest that was before the android nature - System.arraycopy(natures, 0, newNatures, 1, natures.length); - - // set the new natures - description.setNatureIds(newNatures); - project.setDescription(description, null); - - // and stop - break; - } - } - } - } - - - /** - * Removes a specific nature from a project. - * @param project The project to remove the nature from. - * @param nature The nature id to remove. - * @throws CoreException - */ - public static void removeNature(IProject project, String nature) throws CoreException { - IProjectDescription description = project.getDescription(); - String[] natures = description.getNatureIds(); - - // check if the project already has the android nature. - for (int i = 0; i < natures.length; ++i) { - if (nature.equals(natures[i])) { - String[] newNatures = new String[natures.length - 1]; - if (i > 0) { - System.arraycopy(natures, 0, newNatures, 0, i); - } - System.arraycopy(natures, i + 1, newNatures, i, natures.length - i - 1); - description.setNatureIds(newNatures); - project.setDescription(description, null); - - return; - } - } - - } - - /** - * Returns if the project has error level markers. - * @param includeReferencedProjects flag to also test the referenced projects. - * @throws CoreException - */ - public static boolean hasError(IProject project, boolean includeReferencedProjects) - throws CoreException { - IMarker[] markers = project.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE); - if (markers != null && markers.length > 0) { - // the project has marker(s). even though they are "problem" we - // don't know their severity. so we loop on them and figure if they - // are warnings or errors - for (IMarker m : markers) { - int s = m.getAttribute(IMarker.SEVERITY, -1); - if (s == IMarker.SEVERITY_ERROR) { - return true; - } - } - } - - // test the referenced projects if needed. - if (includeReferencedProjects) { - List<IProject> projects = getReferencedProjects(project); - - for (IProject p : projects) { - if (hasError(p, false)) { - return true; - } - } - } - - return false; - } - - /** - * Saves a String property into the persistent storage of a resource. - * @param resource The resource into which the string value is saved. - * @param propertyName the name of the property. The id of the plug-in is added to this string. - * @param value the value to save - * @return true if the save succeeded. - */ - public static boolean saveStringProperty(IResource resource, String propertyName, - String value) { - QualifiedName qname = new QualifiedName(AdtPlugin.PLUGIN_ID, propertyName); - - try { - resource.setPersistentProperty(qname, value); - } catch (CoreException e) { - return false; - } - - return true; - } - - /** - * Loads a String property from the persistent storage of a resource. - * @param resource The resource from which the string value is loaded. - * @param propertyName the name of the property. The id of the plug-in is added to this string. - * @return the property value or null if it was not found. - */ - public static String loadStringProperty(IResource resource, String propertyName) { - QualifiedName qname = new QualifiedName(AdtPlugin.PLUGIN_ID, propertyName); - - try { - String value = resource.getPersistentProperty(qname); - return value; - } catch (CoreException e) { - return null; - } - } - - /** - * Saves a property into the persistent storage of a resource. - * @param resource The resource into which the boolean value is saved. - * @param propertyName the name of the property. The id of the plug-in is added to this string. - * @param value the value to save - * @return true if the save succeeded. - */ - public static boolean saveBooleanProperty(IResource resource, String propertyName, - boolean value) { - return saveStringProperty(resource, propertyName, Boolean.toString(value)); - } - - /** - * Loads a boolean property from the persistent storage of a resource. - * @param resource The resource from which the boolean value is loaded. - * @param propertyName the name of the property. The id of the plug-in is added to this string. - * @param defaultValue The default value to return if the property was not found. - * @return the property value or the default value if the property was not found. - */ - public static boolean loadBooleanProperty(IResource resource, String propertyName, - boolean defaultValue) { - String value = loadStringProperty(resource, propertyName); - if (value != null) { - return Boolean.parseBoolean(value); - } - - return defaultValue; - } - - public static Boolean loadBooleanProperty(IResource resource, String propertyName) { - String value = loadStringProperty(resource, propertyName); - if (value != null) { - return Boolean.valueOf(value); - } - - return null; - } - - /** - * Saves the path of a resource into the persistent storage of a resource. - * @param resource The resource into which the resource path is saved. - * @param propertyName the name of the property. The id of the plug-in is added to this string. - * @param value The resource to save. It's its path that is actually stored. If null, an - * empty string is stored. - * @return true if the save succeeded - */ - public static boolean saveResourceProperty(IResource resource, String propertyName, - IResource value) { - if (value != null) { - IPath iPath = value.getFullPath(); - return saveStringProperty(resource, propertyName, iPath.toString()); - } - - return saveStringProperty(resource, propertyName, ""); //$NON-NLS-1$ - } - - /** - * Loads the path of a resource from the persistent storage of a resource, and returns the - * corresponding IResource object. - * @param resource The resource from which the resource path is loaded. - * @param propertyName the name of the property. The id of the plug-in is added to this string. - * @return The corresponding IResource object (or children interface) or null - */ - public static IResource loadResourceProperty(IResource resource, String propertyName) { - String value = loadStringProperty(resource, propertyName); - - if (value != null && value.length() > 0) { - return ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(value)); - } - - return null; - } - - /** - * Returns the list of referenced project that are opened and Java projects. - * @param project - * @return a new list object containing the opened referenced java project. - * @throws CoreException - */ - public static List<IProject> getReferencedProjects(IProject project) throws CoreException { - IProject[] projects = project.getReferencedProjects(); - - ArrayList<IProject> list = new ArrayList<IProject>(); - - for (IProject p : projects) { - if (p.isOpen() && p.hasNature(JavaCore.NATURE_ID)) { - list.add(p); - } - } - - return list; - } - - - /** - * Checks a Java project compiler level option against a list of supported versions. - * @param optionValue the Compiler level option. - * @return true if the option value is supported. - */ - private static boolean checkCompliance(@NonNull IJavaProject project, String optionValue) { - for (String s : AdtConstants.COMPILER_COMPLIANCE) { - if (s != null && s.equals(optionValue)) { - return true; - } - } - - if (JavaCore.VERSION_1_7.equals(optionValue)) { - // Requires API 19 and buildTools 19 - Sdk currentSdk = Sdk.getCurrent(); - if (currentSdk != null) { - IProject p = project.getProject(); - IAndroidTarget target = currentSdk.getTarget(p); - if (target == null || target.getVersion().getApiLevel() < 19) { - return false; - } - - ProjectState projectState = Sdk.getProjectState(p); - if (projectState != null) { - BuildToolInfo buildToolInfo = projectState.getBuildToolInfo(); - if (buildToolInfo == null) { - buildToolInfo = currentSdk.getLatestBuildTool(); - } - if (buildToolInfo == null || buildToolInfo.getRevision().getMajor() < 19) { - return false; - } - } - - return true; - } - } - - return false; - } - - /** - * Returns the apk filename for the given project - * @param project The project. - * @param config An optional config name. Can be null. - */ - public static String getApkFilename(IProject project, String config) { - if (config != null) { - return project.getName() + "-" + config + SdkConstants.DOT_ANDROID_PACKAGE; //$NON-NLS-1$ - } - - return project.getName() + SdkConstants.DOT_ANDROID_PACKAGE; - } - - /** - * Find the list of projects on which this JavaProject is dependent on at the compilation level. - * - * @param javaProject Java project that we are looking for the dependencies. - * @return A list of Java projects for which javaProject depend on. - * @throws JavaModelException - */ - public static List<IJavaProject> getAndroidProjectDependencies(IJavaProject javaProject) - throws JavaModelException { - String[] requiredProjectNames = javaProject.getRequiredProjectNames(); - - // Go from java project name to JavaProject name - IJavaModel javaModel = javaProject.getJavaModel(); - - // loop through all dependent projects and keep only those that are Android projects - List<IJavaProject> projectList = new ArrayList<IJavaProject>(requiredProjectNames.length); - for (String javaProjectName : requiredProjectNames) { - IJavaProject androidJavaProject = javaModel.getJavaProject(javaProjectName); - - //Verify that the project has also the Android Nature - try { - if (!androidJavaProject.getProject().hasNature(AdtConstants.NATURE_DEFAULT)) { - continue; - } - } catch (CoreException e) { - continue; - } - - projectList.add(androidJavaProject); - } - - return projectList; - } - - /** - * Returns the android package file as an IFile object for the specified - * project. - * @param project The project - * @return The android package as an IFile object or null if not found. - */ - public static IFile getApplicationPackage(IProject project) { - // get the output folder - IFolder outputLocation = BaseProjectHelper.getAndroidOutputFolder(project); - - if (outputLocation == null) { - AdtPlugin.printErrorToConsole(project, - "Failed to get the output location of the project. Check build path properties" - ); - return null; - } - - - // get the package path - String packageName = project.getName() + SdkConstants.DOT_ANDROID_PACKAGE; - IResource r = outputLocation.findMember(packageName); - - // check the package is present - if (r instanceof IFile && r.exists()) { - return (IFile)r; - } - - String msg = String.format("Could not find %1$s!", packageName); - AdtPlugin.printErrorToConsole(project, msg); - - return null; - } - - /** - * Returns an {@link IFile} object representing the manifest for the given project. - * - * @param project The project containing the manifest file. - * @return An IFile object pointing to the manifest or null if the manifest - * is missing. - */ - public static IFile getManifest(IProject project) { - IResource r = project.findMember(AdtConstants.WS_SEP - + SdkConstants.FN_ANDROID_MANIFEST_XML); - - if (r == null || r.exists() == false || (r instanceof IFile) == false) { - return null; - } - return (IFile) r; - } - - /** - * Does a full release build of the application, including the libraries. Do not build the - * package. - * - * @param project The project to be built. - * @param monitor A eclipse runtime progress monitor to be updated by the builders. - * @throws CoreException - */ - @SuppressWarnings("unchecked") - public static void compileInReleaseMode(IProject project, IProgressMonitor monitor) - throws CoreException { - compileInReleaseMode(project, true /*includeDependencies*/, monitor); - } - - /** - * Does a full release build of the application, including the libraries. Do not build the - * package. - * - * @param project The project to be built. - * @param monitor A eclipse runtime progress monitor to be updated by the builders. - * @throws CoreException - */ - @SuppressWarnings("unchecked") - private static void compileInReleaseMode(IProject project, boolean includeDependencies, - IProgressMonitor monitor) - throws CoreException { - - if (includeDependencies) { - ProjectState projectState = Sdk.getProjectState(project); - - // this gives us all the library projects, direct and indirect dependencies, - // so no need to run this method recursively. - List<IProject> libraries = projectState.getFullLibraryProjects(); - - // build dependencies in reverse order to prevent libraries being rebuilt - // due to refresh of other libraries (they would be compiled in the wrong mode). - for (int i = libraries.size() - 1 ; i >= 0 ; i--) { - IProject lib = libraries.get(i); - compileInReleaseMode(lib, false /*includeDependencies*/, monitor); - - // force refresh of the dependency. - lib.refreshLocal(IResource.DEPTH_INFINITE, monitor); - } - } - - // do a full build on all the builders to guarantee that the builders are called. - // (Eclipse does an optimization where builders are not called if there aren't any - // deltas). - - ICommand[] commands = project.getDescription().getBuildSpec(); - for (ICommand command : commands) { - String name = command.getBuilderName(); - if (PreCompilerBuilder.ID.equals(name)) { - Map newArgs = new HashMap(); - newArgs.put(PreCompilerBuilder.RELEASE_REQUESTED, ""); - if (command.getArguments() != null) { - newArgs.putAll(command.getArguments()); - } - - project.build(IncrementalProjectBuilder.FULL_BUILD, - PreCompilerBuilder.ID, newArgs, monitor); - } else if (PostCompilerBuilder.ID.equals(name)) { - if (includeDependencies == false) { - // this is a library, we need to build it! - project.build(IncrementalProjectBuilder.FULL_BUILD, name, - command.getArguments(), monitor); - } - } else { - - project.build(IncrementalProjectBuilder.FULL_BUILD, name, - command.getArguments(), monitor); - } - } - } - - /** - * Force building the project and all its dependencies. - * - * @param project the project to build - * @param kind the build kind - * @param monitor - * @throws CoreException - */ - public static void buildWithDeps(IProject project, int kind, IProgressMonitor monitor) - throws CoreException { - // Get list of projects that we depend on - ProjectState projectState = Sdk.getProjectState(project); - - // this gives us all the library projects, direct and indirect dependencies, - // so no need to run this method recursively. - List<IProject> libraries = projectState.getFullLibraryProjects(); - - // build dependencies in reverse order to prevent libraries being rebuilt - // due to refresh of other libraries (they would be compiled in the wrong mode). - for (int i = libraries.size() - 1 ; i >= 0 ; i--) { - IProject lib = libraries.get(i); - lib.build(kind, monitor); - lib.refreshLocal(IResource.DEPTH_INFINITE, monitor); - } - - project.build(kind, monitor); - } - - - /** - * Build project incrementally, including making the final packaging even if it is disabled - * by default. - * - * @param project The project to be built. - * @param monitor A eclipse runtime progress monitor to be updated by the builders. - * @throws CoreException - */ - public static void doFullIncrementalDebugBuild(IProject project, IProgressMonitor monitor) - throws CoreException { - // Get list of projects that we depend on - List<IJavaProject> androidProjectList = new ArrayList<IJavaProject>(); - try { - androidProjectList = getAndroidProjectDependencies( - BaseProjectHelper.getJavaProject(project)); - } catch (JavaModelException e) { - AdtPlugin.printErrorToConsole(project, e); - } - // Recursively build dependencies - for (IJavaProject dependency : androidProjectList) { - doFullIncrementalDebugBuild(dependency.getProject(), monitor); - } - - // Do an incremental build to pick up all the deltas - project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor); - - // If the preferences indicate not to use post compiler optimization - // then the incremental build will have done everything necessary, otherwise, - // we have to run the final builder manually (if requested). - if (AdtPrefs.getPrefs().getBuildSkipPostCompileOnFileSave()) { - // Create the map to pass to the PostC builder - Map<String, String> args = new TreeMap<String, String>(); - args.put(PostCompilerBuilder.POST_C_REQUESTED, ""); //$NON-NLS-1$ - - // call the post compiler manually, forcing FULL_BUILD otherwise Eclipse won't - // call the builder since the delta is empty. - project.build(IncrementalProjectBuilder.FULL_BUILD, - PostCompilerBuilder.ID, args, monitor); - } - - // because the post compiler builder does a delayed refresh due to - // library not picking the refresh up if it's done during the build, - // we want to force a refresh here as this call is generally asking for - // a build to use the apk right after the call. - project.refreshLocal(IResource.DEPTH_INFINITE, monitor); - } -} |