diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceManager.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceManager.java | 655 |
1 files changed, 0 insertions, 655 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceManager.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceManager.java deleted file mode 100644 index e407b6a78..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceManager.java +++ /dev/null @@ -1,655 +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.resources.manager; - -import com.android.SdkConstants; -import com.android.ide.common.resources.FrameworkResources; -import com.android.ide.common.resources.ResourceFile; -import com.android.ide.common.resources.ResourceFolder; -import com.android.ide.common.resources.ResourceRepository; -import com.android.ide.common.resources.ScanningContext; -import com.android.ide.eclipse.adt.AdtConstants; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.resources.ResourceHelper; -import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IProjectListener; -import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IRawDeltaListener; -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.ide.eclipse.adt.io.IFolderWrapper; -import com.android.io.FolderWrapper; -import com.android.resources.ResourceFolderType; -import com.android.sdklib.IAndroidTarget; - -import org.eclipse.core.resources.IContainer; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IMarkerDelta; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceDelta; -import org.eclipse.core.resources.IResourceDeltaVisitor; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.QualifiedName; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -/** - * The ResourceManager tracks resources for all opened projects. - * <p/> - * It provide direct access to all the resources of a project as a {@link ProjectResources} - * object that allows accessing the resources through their file representation or as Android - * resources (similar to what is seen by an Android application). - * <p/> - * The ResourceManager automatically tracks file changes to update its internal representation - * of the resources so that they are always up to date. - * <p/> - * It also gives access to a monitor that is more resource oriented than the - * {@link GlobalProjectMonitor}. - * This monitor will let you track resource changes by giving you direct access to - * {@link ResourceFile}, or {@link ResourceFolder}. - * - * @see ProjectResources - */ -public final class ResourceManager { - public final static boolean DEBUG = false; - - private final static ResourceManager sThis = new ResourceManager(); - - /** - * Map associating project resource with project objects. - * <p/><b>All accesses must be inside a synchronized(mMap) block</b>, and do as a little as - * possible and <b>not call out to other classes</b>. - */ - private final Map<IProject, ProjectResources> mMap = - new HashMap<IProject, ProjectResources>(); - - /** - * Interface to be notified of resource changes. - * - * @see ResourceManager#addListener(IResourceListener) - * @see ResourceManager#removeListener(IResourceListener) - */ - public interface IResourceListener { - /** - * Notification for resource file change. - * @param project the project of the file. - * @param file the {@link ResourceFile} representing the file. - * @param eventType the type of event. See {@link IResourceDelta}. - */ - void fileChanged(IProject project, ResourceFile file, int eventType); - /** - * Notification for resource folder change. - * @param project the project of the file. - * @param folder the {@link ResourceFolder} representing the folder. - * @param eventType the type of event. See {@link IResourceDelta}. - */ - void folderChanged(IProject project, ResourceFolder folder, int eventType); - } - - private final ArrayList<IResourceListener> mListeners = new ArrayList<IResourceListener>(); - - /** - * Sets up the resource manager with the global project monitor. - * @param monitor The global project monitor - */ - public static void setup(GlobalProjectMonitor monitor) { - monitor.addProjectListener(sThis.mProjectListener); - monitor.addRawDeltaListener(sThis.mRawDeltaListener); - - CompiledResourcesMonitor.setupMonitor(monitor); - } - - /** - * Returns the singleton instance. - */ - public static ResourceManager getInstance() { - return sThis; - } - - /** - * Adds a new {@link IResourceListener} to be notified of resource changes. - * @param listener the listener to be added. - */ - public void addListener(IResourceListener listener) { - synchronized (mListeners) { - mListeners.add(listener); - } - } - - /** - * Removes an {@link IResourceListener}, so that it's not notified of resource changes anymore. - * @param listener the listener to be removed. - */ - public void removeListener(IResourceListener listener) { - synchronized (mListeners) { - mListeners.remove(listener); - } - } - - /** - * Returns the resources of a project. - * @param project The project - * @return a ProjectResources object - */ - public ProjectResources getProjectResources(IProject project) { - synchronized (mMap) { - ProjectResources resources = mMap.get(project); - - if (resources == null) { - resources = ProjectResources.create(project); - mMap.put(project, resources); - } - - return resources; - } - } - - /** - * Update the resource repository with a delta - * - * @param delta the resource changed delta to process. - * @param context a context object with state for the current update, such - * as a place to stash errors encountered - */ - public void processDelta(IResourceDelta delta, IdeScanningContext context) { - doProcessDelta(delta, context); - - // when a project is added to the workspace it is possible this is called before the - // repo is actually created so this will return null. - ResourceRepository repo = context.getRepository(); - if (repo != null) { - repo.postUpdateCleanUp(); - } - } - - /** - * Update the resource repository with a delta - * - * @param delta the resource changed delta to process. - * @param context a context object with state for the current update, such - * as a place to stash errors encountered - */ - private void doProcessDelta(IResourceDelta delta, IdeScanningContext context) { - // Skip over deltas that don't fit our mask - int mask = IResourceDelta.ADDED | IResourceDelta.REMOVED | IResourceDelta.CHANGED; - int kind = delta.getKind(); - if ( (mask & kind) == 0) { - return; - } - - // Process this delta first as we need to make sure new folders are created before - // we process their content - IResource r = delta.getResource(); - int type = r.getType(); - - if (type == IResource.FILE) { - context.startScanning(r); - updateFile((IFile)r, delta.getMarkerDeltas(), kind, context); - context.finishScanning(r); - } else if (type == IResource.FOLDER) { - updateFolder((IFolder)r, kind, context); - } // We only care about files and folders. - // Project deltas are handled by our project listener - - // Now, process children recursively - IResourceDelta[] children = delta.getAffectedChildren(); - for (IResourceDelta child : children) { - processDelta(child, context); - } - } - - /** - * Update a resource folder that we know about - * @param folder the folder that was updated - * @param kind the delta type (added/removed/updated) - */ - private void updateFolder(IFolder folder, int kind, IdeScanningContext context) { - ProjectResources resources; - - final IProject project = folder.getProject(); - - try { - if (project.hasNature(AdtConstants.NATURE_DEFAULT) == false) { - return; - } - } catch (CoreException e) { - // can't get the project nature? return! - return; - } - - switch (kind) { - case IResourceDelta.ADDED: - // checks if the folder is under res. - IPath path = folder.getFullPath(); - - // the path will be project/res/<something> - if (path.segmentCount() == 3) { - if (isInResFolder(path)) { - // get the project and its resource object. - synchronized (mMap) { - resources = mMap.get(project); - - // if it doesn't exist, we create it. - if (resources == null) { - resources = ProjectResources.create(project); - mMap.put(project, resources); - } - } - - ResourceFolder newFolder = resources.processFolder( - new IFolderWrapper(folder)); - if (newFolder != null) { - notifyListenerOnFolderChange(project, newFolder, kind); - } - } - } - break; - case IResourceDelta.CHANGED: - // only call the listeners. - synchronized (mMap) { - resources = mMap.get(folder.getProject()); - } - if (resources != null) { - ResourceFolder resFolder = resources.getResourceFolder(folder); - if (resFolder != null) { - notifyListenerOnFolderChange(project, resFolder, kind); - } - } - break; - case IResourceDelta.REMOVED: - synchronized (mMap) { - resources = mMap.get(folder.getProject()); - } - if (resources != null) { - // lets get the folder type - ResourceFolderType type = ResourceFolderType.getFolderType( - folder.getName()); - - context.startScanning(folder); - ResourceFolder removedFolder = resources.removeFolder(type, - new IFolderWrapper(folder), context); - context.finishScanning(folder); - if (removedFolder != null) { - notifyListenerOnFolderChange(project, removedFolder, kind); - } - } - break; - } - } - - /** - * Called when a delta indicates that a file has changed. Depending on the - * file being changed, and the type of change (ADDED, REMOVED, CHANGED), the - * file change is processed to update the resource manager data. - * - * @param file The file that changed. - * @param markerDeltas The marker deltas for the file. - * @param kind The change kind. This is equivalent to - * {@link IResourceDelta#accept(IResourceDeltaVisitor)} - * @param context a context object with state for the current update, such - * as a place to stash errors encountered - */ - private void updateFile(IFile file, IMarkerDelta[] markerDeltas, int kind, - ScanningContext context) { - final IProject project = file.getProject(); - - try { - if (project.hasNature(AdtConstants.NATURE_DEFAULT) == false) { - return; - } - } catch (CoreException e) { - // can't get the project nature? return! - return; - } - - // get the project resources - ProjectResources resources; - synchronized (mMap) { - resources = mMap.get(project); - } - - if (resources == null) { - return; - } - - // checks if the file is under res/something or bin/res/something - IPath path = file.getFullPath(); - - if (path.segmentCount() == 4 || path.segmentCount() == 5) { - if (isInResFolder(path)) { - IContainer container = file.getParent(); - if (container instanceof IFolder) { - - ResourceFolder folder = resources.getResourceFolder( - (IFolder)container); - - // folder can be null as when the whole folder is deleted, the - // REMOVED event for the folder comes first. In this case, the - // folder will have taken care of things. - if (folder != null) { - ResourceFile resFile = folder.processFile( - new IFileWrapper(file), - ResourceHelper.getResourceDeltaKind(kind), context); - notifyListenerOnFileChange(project, resFile, kind); - } - } - } - } - } - - /** - * Implementation of the {@link IProjectListener} as an internal class so that the methods - * do not appear in the public API of {@link ResourceManager}. - */ - private final IProjectListener mProjectListener = new IProjectListener() { - @Override - public void projectClosed(IProject project) { - synchronized (mMap) { - mMap.remove(project); - } - } - - @Override - public void projectDeleted(IProject project) { - synchronized (mMap) { - mMap.remove(project); - } - } - - @Override - public void projectOpened(IProject project) { - createProject(project); - } - - @Override - public void projectOpenedWithWorkspace(IProject project) { - createProject(project); - } - - @Override - public void allProjectsOpenedWithWorkspace() { - // nothing to do. - } - - @Override - public void projectRenamed(IProject project, IPath from) { - // renamed project get a delete/open event too, so this can be ignored. - } - }; - - /** - * Implementation of {@link IRawDeltaListener} as an internal class so that the methods - * do not appear in the public API of {@link ResourceManager}. Delta processing can be - * accessed through the {@link ResourceManager#visitDelta(IResourceDelta delta)} method. - */ - private final IRawDeltaListener mRawDeltaListener = new IRawDeltaListener() { - @Override - public void visitDelta(IResourceDelta workspaceDelta) { - // If we're auto-building, then PreCompilerBuilder will pass us deltas and - // they will be processed as part of the build. - if (isAutoBuilding()) { - return; - } - - // When *not* auto building, we need to process the deltas immediately on save, - // even if the user is not building yet, such that for example resource ids - // are updated in the resource repositories so rendering etc. can work for - // those new ids. - - IResourceDelta[] projectDeltas = workspaceDelta.getAffectedChildren(); - for (IResourceDelta delta : projectDeltas) { - if (delta.getResource() instanceof IProject) { - IProject project = (IProject) delta.getResource(); - - try { - if (project.hasNature(AdtConstants.NATURE_DEFAULT) == false) { - continue; - } - } catch (CoreException e) { - // only happens if the project is closed or doesn't exist. - } - - IdeScanningContext context = - new IdeScanningContext(getProjectResources(project), project, true); - - processDelta(delta, context); - - Collection<IProject> projects = context.getAaptRequestedProjects(); - if (projects != null) { - for (IProject p : projects) { - markAaptRequested(p); - } - } - } else { - AdtPlugin.log(IStatus.WARNING, "Unexpected delta type: %1$s", - delta.getResource().toString()); - } - } - } - }; - - /** - * Returns the {@link ResourceFolder} for the given file or <code>null</code> if none exists. - */ - public ResourceFolder getResourceFolder(IFile file) { - IContainer container = file.getParent(); - if (container.getType() == IResource.FOLDER) { - IFolder parent = (IFolder)container; - IProject project = file.getProject(); - - ProjectResources resources = getProjectResources(project); - if (resources != null) { - return resources.getResourceFolder(parent); - } - } - - return null; - } - - /** - * Returns the {@link ResourceFolder} for the given folder or <code>null</code> if none exists. - */ - public ResourceFolder getResourceFolder(IFolder folder) { - IProject project = folder.getProject(); - - ProjectResources resources = getProjectResources(project); - if (resources != null) { - return resources.getResourceFolder(folder); - } - - return null; - } - - /** - * Loads and returns the resources for a given {@link IAndroidTarget} - * @param androidTarget the target from which to load the framework resources - */ - public ResourceRepository loadFrameworkResources(IAndroidTarget androidTarget) { - String osResourcesPath = androidTarget.getPath(IAndroidTarget.RESOURCES); - - FolderWrapper frameworkRes = new FolderWrapper(osResourcesPath); - if (frameworkRes.exists()) { - FrameworkResources resources = new FrameworkResources(frameworkRes); - - resources.loadResources(); - resources.loadPublicResources(AdtPlugin.getDefault()); - return resources; - } - - return null; - } - - /** - * Initial project parsing to gather resource info. - * @param project - */ - private void createProject(IProject project) { - if (project.isOpen()) { - synchronized (mMap) { - ProjectResources projectResources = mMap.get(project); - if (projectResources == null) { - projectResources = ProjectResources.create(project); - mMap.put(project, projectResources); - } - } - } - } - - - /** - * Returns true if the path is under /project/res/ - * @param path a workspace relative path - * @return true if the path is under /project res/ - */ - private boolean isInResFolder(IPath path) { - return SdkConstants.FD_RESOURCES.equalsIgnoreCase(path.segment(1)); - } - - private void notifyListenerOnFolderChange(IProject project, ResourceFolder folder, - int eventType) { - synchronized (mListeners) { - for (IResourceListener listener : mListeners) { - try { - listener.folderChanged(project, folder, eventType); - } catch (Throwable t) { - AdtPlugin.log(t, - "Failed to execute ResourceManager.IResouceListener.folderChanged()"); //$NON-NLS-1$ - } - } - } - } - - private void notifyListenerOnFileChange(IProject project, ResourceFile file, int eventType) { - synchronized (mListeners) { - for (IResourceListener listener : mListeners) { - try { - listener.fileChanged(project, file, eventType); - } catch (Throwable t) { - AdtPlugin.log(t, - "Failed to execute ResourceManager.IResouceListener.fileChanged()"); //$NON-NLS-1$ - } - } - } - } - - /** - * Private constructor to enforce singleton design. - */ - private ResourceManager() { - } - - // debug only - @SuppressWarnings("unused") - private String getKindString(int kind) { - if (DEBUG) { - switch (kind) { - case IResourceDelta.ADDED: return "ADDED"; - case IResourceDelta.REMOVED: return "REMOVED"; - case IResourceDelta.CHANGED: return "CHANGED"; - } - } - - return Integer.toString(kind); - } - - /** - * Returns true if the Project > Build Automatically option is turned on - * (default). - * - * @return true if the Project > Build Automatically option is turned on - * (default). - */ - public static boolean isAutoBuilding() { - return ResourcesPlugin.getWorkspace().getDescription().isAutoBuilding(); - } - - /** Qualified name for the per-project persistent property "needs aapt" */ - private final static QualifiedName NEED_AAPT = new QualifiedName(AdtPlugin.PLUGIN_ID, - "aapt");//$NON-NLS-1$ - - /** - * Mark the given project, and any projects which depend on it as a library - * project, as needing a full aapt build the next time the project is built. - * - * @param project the project to mark as needing aapt - */ - public static void markAaptRequested(IProject project) { - try { - String needsAapt = Boolean.TRUE.toString(); - project.setPersistentProperty(NEED_AAPT, needsAapt); - - ProjectState state = Sdk.getProjectState(project); - if (state.isLibrary()) { - // For library projects also mark the dependent projects as needing full aapt - for (ProjectState parent : state.getFullParentProjects()) { - IProject parentProject = parent.getProject(); - // Mark the project, but only if it's open. Resource#setPersistentProperty - // only works on open projects. - if (parentProject.isOpen()) { - parentProject.setPersistentProperty(NEED_AAPT, needsAapt); - } - } - } - } catch (CoreException e) { - AdtPlugin.log(e, null); - } - } - - /** - * Clear the "needs aapt" flag set by {@link #markAaptRequested(IProject)}. - * This is usually called when a project is built. Note that this will only - * clean the build flag on the given project, not on any downstream projects - * that depend on this project as a library project. - * - * @param project the project to clear from the needs aapt list - */ - public static void clearAaptRequest(IProject project) { - try { - project.setPersistentProperty(NEED_AAPT, null); - // Note that even if this project is a library project, we -don't- clear - // the aapt flags on the dependent projects since they may still depend - // on other dirty projects. When they are built, they will issue their - // own clear flag requests. - } catch (CoreException e) { - AdtPlugin.log(e, null); - } - } - - /** - * Returns whether the given project needs a full aapt build. - * - * @param project the project to check - * @return true if the project needs a full aapt run - */ - public static boolean isAaptRequested(IProject project) { - try { - String b = project.getPersistentProperty(NEED_AAPT); - return b != null && Boolean.valueOf(b); - } catch (CoreException e) { - AdtPlugin.log(e, null); - } - - return false; - } -} |