aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java740
1 files changed, 0 insertions, 740 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java
deleted file mode 100644
index 74c985784..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java
+++ /dev/null
@@ -1,740 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.eclipse.org/org/documents/epl-v10.php
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ide.eclipse.adt.internal.sdk;
-
-import com.android.annotations.NonNull;
-import com.android.annotations.Nullable;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.sdklib.BuildToolInfo;
-import com.android.sdklib.IAndroidTarget;
-import com.android.sdklib.internal.project.ProjectProperties;
-import com.android.sdklib.internal.project.ProjectPropertiesWorkingCopy;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.regex.Matcher;
-
-/**
- * Centralized state for Android Eclipse project.
- * <p>This gives raw access to the properties (from <code>project.properties</code>), as well
- * as direct access to target and library information.
- *
- * This also gives access to library information.
- *
- * {@link #isLibrary()} indicates if the project is a library.
- * {@link #hasLibraries()} and {@link #getLibraries()} give access to the libraries through
- * instances of {@link LibraryState}. A {@link LibraryState} instance is a link between a main
- * project and its library. Theses instances are owned by the {@link ProjectState}.
- *
- * {@link #isMissingLibraries()} will indicate if the project has libraries that are not resolved.
- * Unresolved libraries are libraries that do not have any matching opened Eclipse project.
- * When there are missing libraries, the {@link LibraryState} instance for them will return null
- * for {@link LibraryState#getProjectState()}.
- *
- */
-public final class ProjectState {
-
- /**
- * A class that represents a library linked to a project.
- * <p/>It does not represent the library uniquely. Instead the {@link LibraryState} is linked
- * to the main project which is accessible through {@link #getMainProjectState()}.
- * <p/>If a library is used by two different projects, then there will be two different
- * instances of {@link LibraryState} for the library.
- *
- * @see ProjectState#getLibrary(IProject)
- */
- public final class LibraryState {
- private String mRelativePath;
- private ProjectState mProjectState;
- private String mPath;
-
- private LibraryState(String relativePath) {
- mRelativePath = relativePath;
- }
-
- /**
- * Returns the {@link ProjectState} of the main project using this library.
- */
- public ProjectState getMainProjectState() {
- return ProjectState.this;
- }
-
- /**
- * Closes the library. This resets the IProject from this object ({@link #getProjectState()} will
- * return <code>null</code>), and updates the main project data so that the library
- * {@link IProject} object does not show up in the return value of
- * {@link ProjectState#getFullLibraryProjects()}.
- */
- public void close() {
- mProjectState.removeParentProject(getMainProjectState());
- mProjectState = null;
- mPath = null;
-
- getMainProjectState().updateFullLibraryList();
- }
-
- private void setRelativePath(String relativePath) {
- mRelativePath = relativePath;
- }
-
- private void setProject(ProjectState project) {
- mProjectState = project;
- mPath = project.getProject().getLocation().toOSString();
- mProjectState.addParentProject(getMainProjectState());
-
- getMainProjectState().updateFullLibraryList();
- }
-
- /**
- * Returns the relative path of the library from the main project.
- * <p/>This is identical to the value defined in the main project's project.properties.
- */
- public String getRelativePath() {
- return mRelativePath;
- }
-
- /**
- * Returns the {@link ProjectState} item for the library. This can be null if the project
- * is not actually opened in Eclipse.
- */
- public ProjectState getProjectState() {
- return mProjectState;
- }
-
- /**
- * Returns the OS-String location of the library project.
- * <p/>This is based on location of the Eclipse project that matched
- * {@link #getRelativePath()}.
- *
- * @return The project location, or null if the project is not opened in Eclipse.
- */
- public String getProjectLocation() {
- return mPath;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof LibraryState) {
- // the only thing that's always non-null is the relative path.
- LibraryState objState = (LibraryState)obj;
- return mRelativePath.equals(objState.mRelativePath) &&
- getMainProjectState().equals(objState.getMainProjectState());
- } else if (obj instanceof ProjectState || obj instanceof IProject) {
- return mProjectState != null && mProjectState.equals(obj);
- } else if (obj instanceof String) {
- return normalizePath(mRelativePath).equals(normalizePath((String) obj));
- }
-
- return false;
- }
-
- @Override
- public int hashCode() {
- return normalizePath(mRelativePath).hashCode();
- }
- }
-
- private final IProject mProject;
- private final ProjectProperties mProperties;
- private IAndroidTarget mTarget;
- private BuildToolInfo mBuildToolInfo;
-
- /**
- * list of libraries. Access to this list must be protected by
- * <code>synchronized(mLibraries)</code>, but it is important that such code do not call
- * out to other classes (especially those protected by {@link Sdk#getLock()}.)
- */
- private final ArrayList<LibraryState> mLibraries = new ArrayList<LibraryState>();
- /** Cached list of all IProject instances representing the resolved libraries, including
- * indirect dependencies. This must never be null. */
- private List<IProject> mLibraryProjects = Collections.emptyList();
- /**
- * List of parent projects. When this instance is a library ({@link #isLibrary()} returns
- * <code>true</code>) then this is filled with projects that depends on this project.
- */
- private final ArrayList<ProjectState> mParentProjects = new ArrayList<ProjectState>();
-
- ProjectState(IProject project, ProjectProperties properties) {
- if (project == null || properties == null) {
- throw new NullPointerException();
- }
-
- mProject = project;
- mProperties = properties;
-
- // load the libraries
- synchronized (mLibraries) {
- int index = 1;
- while (true) {
- String propName = ProjectProperties.PROPERTY_LIB_REF + Integer.toString(index++);
- String rootPath = mProperties.getProperty(propName);
-
- if (rootPath == null) {
- break;
- }
-
- mLibraries.add(new LibraryState(convertPath(rootPath)));
- }
- }
- }
-
- public IProject getProject() {
- return mProject;
- }
-
- public ProjectProperties getProperties() {
- return mProperties;
- }
-
- public @Nullable String getProperty(@NonNull String name) {
- if (mProperties != null) {
- return mProperties.getProperty(name);
- }
-
- return null;
- }
-
- public void setTarget(IAndroidTarget target) {
- mTarget = target;
- }
-
- /**
- * Returns the project's target's hash string.
- * <p/>If {@link #getTarget()} returns a valid object, then this returns the value of
- * {@link IAndroidTarget#hashString()}.
- * <p/>Otherwise this will return the value of the property
- * {@link ProjectProperties#PROPERTY_TARGET} from {@link #getProperties()} (if valid).
- * @return the target hash string or null if not found.
- */
- public String getTargetHashString() {
- if (mTarget != null) {
- return mTarget.hashString();
- }
-
- return mProperties.getProperty(ProjectProperties.PROPERTY_TARGET);
- }
-
- public IAndroidTarget getTarget() {
- return mTarget;
- }
-
- public void setBuildToolInfo(BuildToolInfo buildToolInfo) {
- mBuildToolInfo = buildToolInfo;
- }
-
- public BuildToolInfo getBuildToolInfo() {
- return mBuildToolInfo;
- }
-
- /**
- * Returns the build tools version from the project's properties.
- * @return the value or null
- */
- @Nullable
- public String getBuildToolInfoVersion() {
- return mProperties.getProperty(ProjectProperties.PROPERTY_BUILD_TOOLS);
- }
-
- public boolean getRenderScriptSupportMode() {
- String supportModeValue = mProperties.getProperty(ProjectProperties.PROPERTY_RS_SUPPORT);
- if (supportModeValue != null) {
- return Boolean.parseBoolean(supportModeValue);
- }
-
- return false;
- }
-
- public static class LibraryDifference {
- public boolean removed = false;
- public boolean added = false;
-
- public boolean hasDiff() {
- return removed || added;
- }
- }
-
- /**
- * Reloads the content of the properties.
- * <p/>This also reset the reference to the target as it may have changed, therefore this
- * should be followed by a call to {@link Sdk#loadTarget(ProjectState)}.
- *
- * <p/>If the project libraries changes, they are updated to a certain extent.<br>
- * Removed libraries are removed from the state list, and added to the {@link LibraryDifference}
- * object that is returned so that they can be processed.<br>
- * Added libraries are added to the state (as new {@link LibraryState} objects), but their
- * IProject is not resolved. {@link ProjectState#needs(ProjectState)} should be called
- * afterwards to properly initialize the libraries.
- *
- * @return an instance of {@link LibraryDifference} describing the change in libraries.
- */
- public LibraryDifference reloadProperties() {
- mTarget = null;
- mProperties.reload();
-
- // compare/reload the libraries.
-
- // if the order change it won't impact the java part, so instead try to detect removed/added
- // libraries.
-
- LibraryDifference diff = new LibraryDifference();
-
- synchronized (mLibraries) {
- List<LibraryState> oldLibraries = new ArrayList<LibraryState>(mLibraries);
- mLibraries.clear();
-
- // load the libraries
- int index = 1;
- while (true) {
- String propName = ProjectProperties.PROPERTY_LIB_REF + Integer.toString(index++);
- String rootPath = mProperties.getProperty(propName);
-
- if (rootPath == null) {
- break;
- }
-
- // search for a library with the same path (not exact same string, but going
- // to the same folder).
- String convertedPath = convertPath(rootPath);
- boolean found = false;
- for (int i = 0 ; i < oldLibraries.size(); i++) {
- LibraryState libState = oldLibraries.get(i);
- if (libState.equals(convertedPath)) {
- // it's a match. move it back to mLibraries and remove it from the
- // old library list.
- found = true;
- mLibraries.add(libState);
- oldLibraries.remove(i);
- break;
- }
- }
-
- if (found == false) {
- diff.added = true;
- mLibraries.add(new LibraryState(convertedPath));
- }
- }
-
- // whatever's left in oldLibraries is removed.
- diff.removed = oldLibraries.size() > 0;
-
- // update the library with what IProjet are known at the time.
- updateFullLibraryList();
- }
-
- return diff;
- }
-
- /**
- * Returns the list of {@link LibraryState}.
- */
- public List<LibraryState> getLibraries() {
- synchronized (mLibraries) {
- return Collections.unmodifiableList(mLibraries);
- }
- }
-
- /**
- * Returns all the <strong>resolved</strong> library projects, including indirect dependencies.
- * The list is ordered to match the library priority order for resource processing with
- * <code>aapt</code>.
- * <p/>If some dependencies are not resolved (or their projects is not opened in Eclipse),
- * they will not show up in this list.
- * @return the resolved projects as an unmodifiable list. May be an empty.
- */
- public List<IProject> getFullLibraryProjects() {
- return mLibraryProjects;
- }
-
- /**
- * Returns whether this is a library project.
- */
- public boolean isLibrary() {
- String value = mProperties.getProperty(ProjectProperties.PROPERTY_LIBRARY);
- return value != null && Boolean.valueOf(value);
- }
-
- /**
- * Returns whether the project depends on one or more libraries.
- */
- public boolean hasLibraries() {
- synchronized (mLibraries) {
- return mLibraries.size() > 0;
- }
- }
-
- /**
- * Returns whether the project is missing some required libraries.
- */
- public boolean isMissingLibraries() {
- synchronized (mLibraries) {
- for (LibraryState state : mLibraries) {
- if (state.getProjectState() == null) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- /**
- * Returns the {@link LibraryState} object for a given {@link IProject}.
- * </p>This can only return a non-null object if the link between the main project's
- * {@link IProject} and the library's {@link IProject} was done.
- *
- * @return the matching LibraryState or <code>null</code>
- *
- * @see #needs(ProjectState)
- */
- public LibraryState getLibrary(IProject library) {
- synchronized (mLibraries) {
- for (LibraryState state : mLibraries) {
- ProjectState ps = state.getProjectState();
- if (ps != null && ps.getProject().equals(library)) {
- return state;
- }
- }
- }
-
- return null;
- }
-
- /**
- * Returns the {@link LibraryState} object for a given <var>name</var>.
- * </p>This can only return a non-null object if the link between the main project's
- * {@link IProject} and the library's {@link IProject} was done.
- *
- * @return the matching LibraryState or <code>null</code>
- *
- * @see #needs(IProject)
- */
- public LibraryState getLibrary(String name) {
- synchronized (mLibraries) {
- for (LibraryState state : mLibraries) {
- ProjectState ps = state.getProjectState();
- if (ps != null && ps.getProject().getName().equals(name)) {
- return state;
- }
- }
- }
-
- return null;
- }
-
-
- /**
- * Returns whether a given library project is needed by the receiver.
- * <p/>If the library is needed, this finds the matching {@link LibraryState}, initializes it
- * so that it contains the library's {@link IProject} object (so that
- * {@link LibraryState#getProjectState()} does not return null) and then returns it.
- *
- * @param libraryProject the library project to check.
- * @return a non null object if the project is a library dependency,
- * <code>null</code> otherwise.
- *
- * @see LibraryState#getProjectState()
- */
- public LibraryState needs(ProjectState libraryProject) {
- // compute current location
- File projectFile = mProject.getLocation().toFile();
-
- // get the location of the library.
- File libraryFile = libraryProject.getProject().getLocation().toFile();
-
- // loop on all libraries and check if the path match
- synchronized (mLibraries) {
- for (LibraryState state : mLibraries) {
- if (state.getProjectState() == null) {
- File library = new File(projectFile, state.getRelativePath());
- try {
- File absPath = library.getCanonicalFile();
- if (absPath.equals(libraryFile)) {
- state.setProject(libraryProject);
- return state;
- }
- } catch (IOException e) {
- // ignore this library
- }
- }
- }
- }
-
- return null;
- }
-
- /**
- * Returns whether the project depends on a given <var>library</var>
- * @param library the library to check.
- * @return true if the project depends on the library. This is not affected by whether the link
- * was done through {@link #needs(ProjectState)}.
- */
- public boolean dependsOn(ProjectState library) {
- synchronized (mLibraries) {
- for (LibraryState state : mLibraries) {
- if (state != null && state.getProjectState() != null &&
- library.getProject().equals(state.getProjectState().getProject())) {
- return true;
- }
- }
- }
-
- return false;
- }
-
-
- /**
- * Updates a library with a new path.
- * <p/>This method acts both as a check and an action. If the project does not depend on the
- * given <var>oldRelativePath</var> then no action is done and <code>null</code> is returned.
- * <p/>If the project depends on the library, then the project is updated with the new path,
- * and the {@link LibraryState} for the library is returned.
- * <p/>Updating the project does two things:<ul>
- * <li>Update LibraryState with new relative path and new {@link IProject} object.</li>
- * <li>Update the main project's <code>project.properties</code> with the new relative path
- * for the changed library.</li>
- * </ul>
- *
- * @param oldRelativePath the old library path relative to this project
- * @param newRelativePath the new library path relative to this project
- * @param newLibraryState the new {@link ProjectState} object.
- * @return a non null object if the project depends on the library.
- *
- * @see LibraryState#getProjectState()
- */
- public LibraryState updateLibrary(String oldRelativePath, String newRelativePath,
- ProjectState newLibraryState) {
- // compute current location
- File projectFile = mProject.getLocation().toFile();
-
- // loop on all libraries and check if the path matches
- synchronized (mLibraries) {
- for (LibraryState state : mLibraries) {
- if (state.getProjectState() == null) {
- try {
- // oldRelativePath may not be the same exact string as the
- // one in the project properties (trailing separator could be different
- // for instance).
- // Use java.io.File to deal with this and also do a platform-dependent
- // path comparison
- File library1 = new File(projectFile, oldRelativePath);
- File library2 = new File(projectFile, state.getRelativePath());
- if (library1.getCanonicalPath().equals(library2.getCanonicalPath())) {
- // save the exact property string to replace.
- String oldProperty = state.getRelativePath();
-
- // then update the LibraryPath.
- state.setRelativePath(newRelativePath);
- state.setProject(newLibraryState);
-
- // update the project.properties file
- IStatus status = replaceLibraryProperty(oldProperty, newRelativePath);
- if (status != null) {
- if (status.getSeverity() != IStatus.OK) {
- // log the error somehow.
- }
- } else {
- // This should not happen since the library wouldn't be here in the
- // first place
- }
-
- // return the LibraryState object.
- return state;
- }
- } catch (IOException e) {
- // ignore this library
- }
- }
- }
- }
-
- return null;
- }
-
-
- private void addParentProject(ProjectState parentState) {
- mParentProjects.add(parentState);
- }
-
- private void removeParentProject(ProjectState parentState) {
- mParentProjects.remove(parentState);
- }
-
- public List<ProjectState> getParentProjects() {
- return Collections.unmodifiableList(mParentProjects);
- }
-
- /**
- * Computes the transitive closure of projects referencing this project as a
- * library project
- *
- * @return a collection (in any order) of project states for projects that
- * directly or indirectly include this project state's project as a
- * library project
- */
- public Collection<ProjectState> getFullParentProjects() {
- Set<ProjectState> result = new HashSet<ProjectState>();
- addParentProjects(result, this);
- return result;
- }
-
- /** Adds all parent projects of the given project, transitively, into the given parent set */
- private static void addParentProjects(Set<ProjectState> parents, ProjectState state) {
- for (ProjectState s : state.mParentProjects) {
- if (!parents.contains(s)) {
- parents.add(s);
- addParentProjects(parents, s);
- }
- }
- }
-
- /**
- * Update the value of a library dependency.
- * <p/>This loops on all current dependency looking for the value to replace and then replaces
- * it.
- * <p/>This both updates the in-memory {@link #mProperties} values and on-disk
- * project.properties file.
- * @param oldValue the old value to replace
- * @param newValue the new value to set.
- * @return the status of the replacement. If null, no replacement was done (value not found).
- */
- private IStatus replaceLibraryProperty(String oldValue, String newValue) {
- int index = 1;
- while (true) {
- String propName = ProjectProperties.PROPERTY_LIB_REF + Integer.toString(index++);
- String rootPath = mProperties.getProperty(propName);
-
- if (rootPath == null) {
- break;
- }
-
- if (rootPath.equals(oldValue)) {
- // need to update the properties. Get a working copy to change it and save it on
- // disk since ProjectProperties is read-only.
- ProjectPropertiesWorkingCopy workingCopy = mProperties.makeWorkingCopy();
- workingCopy.setProperty(propName, newValue);
- try {
- workingCopy.save();
-
- // reload the properties with the new values from the disk.
- mProperties.reload();
- } catch (Exception e) {
- return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, String.format(
- "Failed to save %1$s for project %2$s",
- mProperties.getType() .getFilename(), mProject.getName()),
- e);
-
- }
- return Status.OK_STATUS;
- }
- }
-
- return null;
- }
-
- /**
- * Update the full library list, including indirect dependencies. The result is returned by
- * {@link #getFullLibraryProjects()}.
- */
- void updateFullLibraryList() {
- ArrayList<IProject> list = new ArrayList<IProject>();
- synchronized (mLibraries) {
- buildFullLibraryDependencies(mLibraries, list);
- }
-
- mLibraryProjects = Collections.unmodifiableList(list);
- }
-
- /**
- * Resolves a given list of libraries, finds out if they depend on other libraries, and
- * returns a full list of all the direct and indirect dependencies in the proper order (first
- * is higher priority when calling aapt).
- * @param inLibraries the libraries to resolve
- * @param outLibraries where to store all the libraries.
- */
- private void buildFullLibraryDependencies(List<LibraryState> inLibraries,
- ArrayList<IProject> outLibraries) {
- // loop in the inverse order to resolve dependencies on the libraries, so that if a library
- // is required by two higher level libraries it can be inserted in the correct place
- for (int i = inLibraries.size() - 1 ; i >= 0 ; i--) {
- LibraryState library = inLibraries.get(i);
-
- // get its libraries if possible
- ProjectState libProjectState = library.getProjectState();
- if (libProjectState != null) {
- List<LibraryState> dependencies = libProjectState.getLibraries();
-
- // build the dependencies for those libraries
- buildFullLibraryDependencies(dependencies, outLibraries);
-
- // and add the current library (if needed) in front (higher priority)
- if (outLibraries.contains(libProjectState.getProject()) == false) {
- outLibraries.add(0, libProjectState.getProject());
- }
- }
- }
- }
-
-
- /**
- * Converts a path containing only / by the proper platform separator.
- */
- private String convertPath(String path) {
- return path.replaceAll("/", Matcher.quoteReplacement(File.separator)); //$NON-NLS-1$
- }
-
- /**
- * Normalizes a relative path.
- */
- private String normalizePath(String path) {
- path = convertPath(path);
- if (path.endsWith("/")) { //$NON-NLS-1$
- path = path.substring(0, path.length() - 1);
- }
- return path;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof ProjectState) {
- return mProject.equals(((ProjectState) obj).mProject);
- } else if (obj instanceof IProject) {
- return mProject.equals(obj);
- }
-
- return false;
- }
-
- @Override
- public int hashCode() {
- return mProject.hashCode();
- }
-
- @Override
- public String toString() {
- return mProject.getName();
- }
-}