aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/CyclicDependencyValidator.java66
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java628
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java242
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/CompiledResourcesMonitor.java313
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/DynamicIdMap.java75
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/GlobalProjectMonitor.java546
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/IdeScanningContext.java234
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectClassLoader.java376
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java271
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceManager.java655
10 files changed, 0 insertions, 3406 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/CyclicDependencyValidator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/CyclicDependencyValidator.java
deleted file mode 100644
index a2b13c6a8..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/CyclicDependencyValidator.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2011 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;
-
-import com.android.annotations.Nullable;
-import com.android.ide.eclipse.adt.internal.editors.layout.gle2.IncludeFinder;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.jface.dialogs.IInputValidator;
-
-import java.util.Collection;
-
-/** A validator which checks for cyclic dependencies */
-public class CyclicDependencyValidator implements IInputValidator {
- private final Collection<String> mInvalidIds;
-
- private CyclicDependencyValidator(Collection<String> invalid) {
- this.mInvalidIds = invalid;
- }
-
- @Override
- public String isValid(String newText) {
- if (mInvalidIds.contains(newText)) {
- return "Cyclic include, not valid";
- }
- return null;
- }
-
- /**
- * Creates a validator which ensures that the chosen id is not for a layout that is
- * directly or indirectly including the given layout. Used to avoid cyclic
- * dependencies when offering layouts to be included within a given file, etc.
- *
- * @param file the target file that candidate layouts should not directly or
- * indirectly include
- * @return a validator which checks whether resource ids are valid or whether they
- * could result in a cyclic dependency
- */
- @Nullable
- public static IInputValidator create(@Nullable IFile file) {
- if (file == null) {
- return null;
- }
-
- IProject project = file.getProject();
- IncludeFinder includeFinder = IncludeFinder.get(project);
- final Collection<String> invalid =
- includeFinder.getInvalidIncludes(file);
-
- return new CyclicDependencyValidator(invalid);
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java
deleted file mode 100644
index b0e3d43d0..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java
+++ /dev/null
@@ -1,628 +0,0 @@
-/*
- * Copyright (C) 2011 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;
-
-import static com.android.SdkConstants.ANDROID_PREFIX;
-import static com.android.SdkConstants.ANDROID_STYLE_RESOURCE_PREFIX;
-import static com.android.SdkConstants.ANDROID_URI;
-import static com.android.SdkConstants.ATTR_COLOR;
-import static com.android.SdkConstants.ATTR_NAME;
-import static com.android.SdkConstants.ATTR_TYPE;
-import static com.android.SdkConstants.DOT_XML;
-import static com.android.SdkConstants.EXT_XML;
-import static com.android.SdkConstants.FD_RESOURCES;
-import static com.android.SdkConstants.FD_RES_VALUES;
-import static com.android.SdkConstants.PREFIX_RESOURCE_REF;
-import static com.android.SdkConstants.STYLE_RESOURCE_PREFIX;
-import static com.android.SdkConstants.TAG_ITEM;
-import static com.android.SdkConstants.TAG_RESOURCES;
-import static com.android.ide.eclipse.adt.AdtConstants.WS_SEP;
-
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.ide.common.resources.ResourceDeltaKind;
-import com.android.ide.common.resources.ResourceResolver;
-import com.android.ide.common.resources.ResourceUrl;
-import com.android.ide.common.resources.configuration.CountryCodeQualifier;
-import com.android.ide.common.resources.configuration.DensityQualifier;
-import com.android.ide.common.resources.configuration.FolderConfiguration;
-import com.android.ide.common.resources.configuration.KeyboardStateQualifier;
-import com.android.ide.common.resources.configuration.LayoutDirectionQualifier;
-import com.android.ide.common.resources.configuration.LocaleQualifier;
-import com.android.ide.common.resources.configuration.NavigationMethodQualifier;
-import com.android.ide.common.resources.configuration.NavigationStateQualifier;
-import com.android.ide.common.resources.configuration.NetworkCodeQualifier;
-import com.android.ide.common.resources.configuration.NightModeQualifier;
-import com.android.ide.common.resources.configuration.ResourceQualifier;
-import com.android.ide.common.resources.configuration.ScreenDimensionQualifier;
-import com.android.ide.common.resources.configuration.ScreenHeightQualifier;
-import com.android.ide.common.resources.configuration.ScreenOrientationQualifier;
-import com.android.ide.common.resources.configuration.ScreenRatioQualifier;
-import com.android.ide.common.resources.configuration.ScreenSizeQualifier;
-import com.android.ide.common.resources.configuration.ScreenWidthQualifier;
-import com.android.ide.common.resources.configuration.SmallestScreenWidthQualifier;
-import com.android.ide.common.resources.configuration.TextInputMethodQualifier;
-import com.android.ide.common.resources.configuration.TouchScreenQualifier;
-import com.android.ide.common.resources.configuration.UiModeQualifier;
-import com.android.ide.common.resources.configuration.VersionQualifier;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
-import com.android.ide.eclipse.adt.internal.editors.Hyperlinks;
-import com.android.ide.eclipse.adt.internal.editors.IconFactory;
-import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageUtils;
-import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.VisualRefactoring;
-import com.android.ide.eclipse.adt.internal.wizards.newxmlfile.NewXmlFileWizard;
-import com.android.resources.FolderTypeRelationship;
-import com.android.resources.ResourceFolderType;
-import com.android.resources.ResourceType;
-import com.android.utils.Pair;
-
-import org.eclipse.core.resources.IFile;
-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.Path;
-import org.eclipse.jface.text.IRegion;
-import org.eclipse.jface.text.Region;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.RGB;
-import org.eclipse.wst.sse.core.StructuredModelManager;
-import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
-import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
-import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
-import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
-import org.eclipse.wst.xml.core.internal.document.ElementImpl;
-import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
-import org.w3c.dom.Attr;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.Text;
-import org.xml.sax.InputSource;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-
-/**
- * Helper class to deal with SWT specifics for the resources.
- */
-@SuppressWarnings("restriction") // XML model
-public class ResourceHelper {
-
- private final static Map<Class<?>, Image> sIconMap = new HashMap<Class<?>, Image>(
- FolderConfiguration.getQualifierCount());
-
- static {
- try {
- IconFactory factory = IconFactory.getInstance();
- sIconMap.put(CountryCodeQualifier.class, factory.getIcon("mcc")); //$NON-NLS-1$
- sIconMap.put(NetworkCodeQualifier.class, factory.getIcon("mnc")); //$NON-NLS-1$
- sIconMap.put(LocaleQualifier.class, factory.getIcon("language")); //$NON-NLS-1$
- sIconMap.put(LayoutDirectionQualifier.class, factory.getIcon("bidi")); //$NON-NLS-1$
- sIconMap.put(ScreenSizeQualifier.class, factory.getIcon("size")); //$NON-NLS-1$
- sIconMap.put(ScreenRatioQualifier.class, factory.getIcon("ratio")); //$NON-NLS-1$
- sIconMap.put(ScreenOrientationQualifier.class, factory.getIcon("orientation")); //$NON-NLS-1$
- sIconMap.put(UiModeQualifier.class, factory.getIcon("dockmode")); //$NON-NLS-1$
- sIconMap.put(NightModeQualifier.class, factory.getIcon("nightmode")); //$NON-NLS-1$
- sIconMap.put(DensityQualifier.class, factory.getIcon("dpi")); //$NON-NLS-1$
- sIconMap.put(TouchScreenQualifier.class, factory.getIcon("touch")); //$NON-NLS-1$
- sIconMap.put(KeyboardStateQualifier.class, factory.getIcon("keyboard")); //$NON-NLS-1$
- sIconMap.put(TextInputMethodQualifier.class, factory.getIcon("text_input")); //$NON-NLS-1$
- sIconMap.put(NavigationStateQualifier.class, factory.getIcon("navpad")); //$NON-NLS-1$
- sIconMap.put(NavigationMethodQualifier.class, factory.getIcon("navpad")); //$NON-NLS-1$
- sIconMap.put(ScreenDimensionQualifier.class, factory.getIcon("dimension")); //$NON-NLS-1$
- sIconMap.put(VersionQualifier.class, factory.getIcon("version")); //$NON-NLS-1$
- sIconMap.put(ScreenWidthQualifier.class, factory.getIcon("width")); //$NON-NLS-1$
- sIconMap.put(ScreenHeightQualifier.class, factory.getIcon("height")); //$NON-NLS-1$
- sIconMap.put(SmallestScreenWidthQualifier.class,factory.getIcon("swidth")); //$NON-NLS-1$
- } catch (Throwable t) {
- AdtPlugin.log(t , null);
- }
- }
-
- /**
- * Returns the icon for the qualifier.
- */
- public static Image getIcon(Class<? extends ResourceQualifier> theClass) {
- return sIconMap.get(theClass);
- }
-
- /**
- * Returns a {@link ResourceDeltaKind} from an {@link IResourceDelta} value.
- * @param kind a {@link IResourceDelta} integer constant.
- * @return a matching {@link ResourceDeltaKind} or null.
- *
- * @see IResourceDelta#ADDED
- * @see IResourceDelta#REMOVED
- * @see IResourceDelta#CHANGED
- */
- public static ResourceDeltaKind getResourceDeltaKind(int kind) {
- switch (kind) {
- case IResourceDelta.ADDED:
- return ResourceDeltaKind.ADDED;
- case IResourceDelta.REMOVED:
- return ResourceDeltaKind.REMOVED;
- case IResourceDelta.CHANGED:
- return ResourceDeltaKind.CHANGED;
- }
-
- return null;
- }
-
- /**
- * Is this a resource that can be defined in any file within the "values" folder?
- * <p>
- * Some resource types can be defined <b>both</b> as a separate XML file as well
- * as defined within a value XML file. This method will return true for these types
- * as well. In other words, a ResourceType can return true for both
- * {@link #isValueBasedResourceType} and {@link #isFileBasedResourceType}.
- *
- * @param type the resource type to check
- * @return true if the given resource type can be represented as a value under the
- * values/ folder
- */
- public static boolean isValueBasedResourceType(ResourceType type) {
- List<ResourceFolderType> folderTypes = FolderTypeRelationship.getRelatedFolders(type);
- for (ResourceFolderType folderType : folderTypes) {
- if (folderType == ResourceFolderType.VALUES) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Is this a resource that is defined in a file named by the resource plus the XML
- * extension?
- * <p>
- * Some resource types can be defined <b>both</b> as a separate XML file as well as
- * defined within a value XML file along with other properties. This method will
- * return true for these resource types as well. In other words, a ResourceType can
- * return true for both {@link #isValueBasedResourceType} and
- * {@link #isFileBasedResourceType}.
- *
- * @param type the resource type to check
- * @return true if the given resource type is stored in a file named by the resource
- */
- public static boolean isFileBasedResourceType(ResourceType type) {
- List<ResourceFolderType> folderTypes = FolderTypeRelationship.getRelatedFolders(type);
- for (ResourceFolderType folderType : folderTypes) {
- if (folderType != ResourceFolderType.VALUES) {
-
- if (type == ResourceType.ID) {
- // The folder types for ID is not only VALUES but also
- // LAYOUT and MENU. However, unlike resources, they are only defined
- // inline there so for the purposes of isFileBasedResourceType
- // (where the intent is to figure out files that are uniquely identified
- // by a resource's name) this method should return false anyway.
- return false;
- }
-
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Returns true if this class can create the given resource
- *
- * @param resource the resource to be created
- * @return true if the {@link #createResource} method can create this resource
- */
- public static boolean canCreateResource(String resource) {
- // Cannot create framework resources
- if (resource.startsWith(ANDROID_PREFIX)) {
- return false;
- }
-
- ResourceUrl parsed = ResourceUrl.parse(resource);
- if (parsed != null) {
- if (parsed.framework) {
- return false;
- }
- ResourceType type = parsed.type;
- String name = parsed.name;
-
- // Make sure the name is valid
- ResourceNameValidator validator =
- ResourceNameValidator.create(false, (Set<String>) null /* existing */, type);
- if (validator.isValid(name) != null) {
- return false;
- }
-
- return canCreateResourceType(type);
- }
-
- return false;
- }
-
- /**
- * Returns true if this class can create resources of the given resource
- * type
- *
- * @param type the type of resource to be created
- * @return true if the {@link #createResource} method can create resources
- * of this type (provided the name parameter is also valid)
- */
- public static boolean canCreateResourceType(ResourceType type) {
- // We can create all value types
- if (isValueBasedResourceType(type)) {
- return true;
- }
-
- // We can create -some- file-based types - those supported by the New XML wizard:
- for (ResourceFolderType folderType : FolderTypeRelationship.getRelatedFolders(type)) {
- if (NewXmlFileWizard.canCreateXmlFile(folderType)) {
- return true;
- }
- }
-
- return false;
- }
-
- /** Creates a file-based resource, like a layout. Used by {@link #createResource} */
- private static Pair<IFile,IRegion> createFileResource(IProject project, ResourceType type,
- String name) {
-
- ResourceFolderType folderType = null;
- for (ResourceFolderType f : FolderTypeRelationship.getRelatedFolders(type)) {
- if (NewXmlFileWizard.canCreateXmlFile(f)) {
- folderType = f;
- break;
- }
- }
- if (folderType == null) {
- return null;
- }
-
- // Find "dimens.xml" file in res/values/ (or corresponding name for other
- // value types)
- IPath projectPath = new Path(FD_RESOURCES + WS_SEP + folderType.getName() + WS_SEP
- + name + '.' + EXT_XML);
- IFile file = project.getFile(projectPath);
- return NewXmlFileWizard.createXmlFile(project, file, folderType);
- }
-
- /**
- * Creates a resource of a given type, name and (if applicable) value
- *
- * @param project the project to contain the resource
- * @param type the type of resource
- * @param name the name of the resource
- * @param value the value of the resource, if it is a value-type resource
- * @return a pair of the file containing the resource and a region where the value
- * appears
- */
- public static Pair<IFile,IRegion> createResource(IProject project, ResourceType type,
- String name, String value) {
- if (!isValueBasedResourceType(type)) {
- return createFileResource(project, type, name);
- }
-
- // Find "dimens.xml" file in res/values/ (or corresponding name for other
- // value types)
- String typeName = type.getName();
- String fileName = typeName + 's';
- String projectPath = FD_RESOURCES + WS_SEP + FD_RES_VALUES + WS_SEP
- + fileName + '.' + EXT_XML;
- Object editRequester = project;
- IResource member = project.findMember(projectPath);
- String tagName = Hyperlinks.getTagName(type);
- boolean createEmptyTag = type == ResourceType.ID;
- if (member != null) {
- if (member instanceof IFile) {
- IFile file = (IFile) member;
- // File exists: Must add item to the XML
- IModelManager manager = StructuredModelManager.getModelManager();
- IStructuredModel model = null;
- try {
- model = manager.getExistingModelForEdit(file);
- if (model == null) {
- model = manager.getModelForEdit(file);
- }
- if (model instanceof IDOMModel) {
- model.beginRecording(editRequester, String.format("Add %1$s",
- type.getDisplayName()));
- IDOMModel domModel = (IDOMModel) model;
- Document document = domModel.getDocument();
- Element root = document.getDocumentElement();
- IStructuredDocument structuredDocument = model.getStructuredDocument();
- Node lastElement = null;
- NodeList childNodes = root.getChildNodes();
- String indent = null;
- for (int i = childNodes.getLength() - 1; i >= 0; i--) {
- Node node = childNodes.item(i);
- if (node.getNodeType() == Node.ELEMENT_NODE) {
- lastElement = node;
- indent = AndroidXmlEditor.getIndent(structuredDocument, node);
- break;
- }
- }
- if (indent == null || indent.length() == 0) {
- indent = " "; //$NON-NLS-1$
- }
- Node nextChild = lastElement != null ? lastElement.getNextSibling() : null;
- Text indentNode = document.createTextNode('\n' + indent);
- root.insertBefore(indentNode, nextChild);
- Element element = document.createElement(tagName);
- if (createEmptyTag) {
- if (element instanceof ElementImpl) {
- ElementImpl elementImpl = (ElementImpl) element;
- elementImpl.setEmptyTag(true);
- }
- }
- element.setAttribute(ATTR_NAME, name);
- if (!tagName.equals(typeName)) {
- element.setAttribute(ATTR_TYPE, typeName);
- }
- root.insertBefore(element, nextChild);
- IRegion region = null;
-
- if (createEmptyTag) {
- IndexedRegion domRegion = VisualRefactoring.getRegion(element);
- int endOffset = domRegion.getEndOffset();
- region = new Region(endOffset, 0);
- } else {
- Node valueNode = document.createTextNode(value);
- element.appendChild(valueNode);
-
- IndexedRegion domRegion = VisualRefactoring.getRegion(valueNode);
- int startOffset = domRegion.getStartOffset();
- int length = domRegion.getLength();
- region = new Region(startOffset, length);
- }
- model.save();
- return Pair.of(file, region);
- }
- } catch (Exception e) {
- AdtPlugin.log(e, "Cannot access XML value model");
- } finally {
- if (model != null) {
- model.endRecording(editRequester);
- model.releaseFromEdit();
- }
- }
- }
-
- return null;
- } else {
- // No such file exists: just create it
- String prolog = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; //$NON-NLS-1$
- StringBuilder sb = new StringBuilder(prolog);
-
- String root = TAG_RESOURCES;
- sb.append('<').append(root).append('>').append('\n');
- sb.append(" "); //$NON-NLS-1$
- sb.append('<');
- sb.append(tagName);
- sb.append(" name=\""); //$NON-NLS-1$
- sb.append(name);
- sb.append('"');
- if (!tagName.equals(typeName)) {
- sb.append(" type=\""); //$NON-NLS-1$
- sb.append(typeName);
- sb.append('"');
- }
- int start, end;
- if (createEmptyTag) {
- sb.append("/>"); //$NON-NLS-1$
- start = sb.length();
- end = sb.length();
- } else {
- sb.append('>');
- start = sb.length();
- sb.append(value);
- end = sb.length();
- sb.append('<').append('/');
- sb.append(tagName);
- sb.append('>');
- }
- sb.append('\n').append('<').append('/').append(root).append('>').append('\n');
- String result = sb.toString();
- // TODO: Pretty print string (wait until that CL is integrated)
- String error = null;
- try {
- byte[] buf = result.getBytes("UTF8"); //$NON-NLS-1$
- InputStream stream = new ByteArrayInputStream(buf);
- IFile file = project.getFile(new Path(projectPath));
- file.create(stream, true /*force*/, null /*progress*/);
- IRegion region = new Region(start, end - start);
- return Pair.of(file, region);
- } catch (UnsupportedEncodingException e) {
- error = e.getMessage();
- } catch (CoreException e) {
- error = e.getMessage();
- }
-
- error = String.format("Failed to generate %1$s: %2$s", name, error);
- AdtPlugin.displayError("New Android XML File", error);
- }
- return null;
- }
-
- /**
- * Returns the theme name to be shown for theme styles, e.g. for "@style/Theme" it
- * returns "Theme"
- *
- * @param style a theme style string
- * @return the user visible theme name
- */
- public static String styleToTheme(String style) {
- if (style.startsWith(STYLE_RESOURCE_PREFIX)) {
- style = style.substring(STYLE_RESOURCE_PREFIX.length());
- } else if (style.startsWith(ANDROID_STYLE_RESOURCE_PREFIX)) {
- style = style.substring(ANDROID_STYLE_RESOURCE_PREFIX.length());
- } else if (style.startsWith(PREFIX_RESOURCE_REF)) {
- // @package:style/foo
- int index = style.indexOf('/');
- if (index != -1) {
- style = style.substring(index + 1);
- }
- }
- return style;
- }
-
- /**
- * Returns true if the given style represents a project theme
- *
- * @param style a theme style string
- * @return true if the style string represents a project theme, as opposed
- * to a framework theme
- */
- public static boolean isProjectStyle(String style) {
- assert style.startsWith(STYLE_RESOURCE_PREFIX)
- || style.startsWith(ANDROID_STYLE_RESOURCE_PREFIX) : style;
-
- return style.startsWith(STYLE_RESOURCE_PREFIX);
- }
-
- /**
- * Returns the layout resource name for the given layout file, e.g. for
- * /res/layout/foo.xml returns foo.
- *
- * @param layoutFile the layout file whose name we want to look up
- * @return the layout name
- */
- public static String getLayoutName(IFile layoutFile) {
- String layoutName = layoutFile.getName();
- int dotIndex = layoutName.indexOf('.');
- if (dotIndex != -1) {
- layoutName = layoutName.substring(0, dotIndex);
- }
- return layoutName;
- }
-
- /**
- * Tries to resolve the given resource value to an actual RGB color. For state lists
- * it will pick the simplest/fallback color.
- *
- * @param resources the resource resolver to use to follow color references
- * @param color the color to resolve
- * @return the corresponding {@link RGB} color, or null
- */
- public static RGB resolveColor(ResourceResolver resources, ResourceValue color) {
- color = resources.resolveResValue(color);
- if (color == null) {
- return null;
- }
- String value = color.getValue();
-
- while (value != null) {
- if (value.startsWith("#")) { //$NON-NLS-1$
- try {
- int rgba = ImageUtils.getColor(value);
- // Drop alpha channel
- return ImageUtils.intToRgb(rgba);
- } catch (NumberFormatException nfe) {
- // Pass
- }
- return null;
- }
- if (value.startsWith(PREFIX_RESOURCE_REF)) {
- boolean isFramework = color.isFramework();
- color = resources.findResValue(value, isFramework);
- if (color != null) {
- value = color.getValue();
- } else {
- break;
- }
- } else {
- File file = new File(value);
- if (file.exists() && file.getName().endsWith(DOT_XML)) {
- // Parse
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- BufferedInputStream bis = null;
- try {
- bis = new BufferedInputStream(new FileInputStream(file));
- InputSource is = new InputSource(bis);
- factory.setNamespaceAware(true);
- factory.setValidating(false);
- DocumentBuilder builder = factory.newDocumentBuilder();
- Document document = builder.parse(is);
- NodeList items = document.getElementsByTagName(TAG_ITEM);
-
- value = findColorValue(items);
- continue;
- } catch (Exception e) {
- AdtPlugin.log(e, "Failed parsing color file %1$s", file.getName());
- } finally {
- if (bis != null) {
- try {
- bis.close();
- } catch (IOException e) {
- // Nothing useful can be done here
- }
- }
- }
- }
-
- return null;
- }
- }
-
- return null;
- }
-
- /**
- * Searches a color XML file for the color definition element that does not
- * have an associated state and returns its color
- */
- private static String findColorValue(NodeList items) {
- for (int i = 0, n = items.getLength(); i < n; i++) {
- // Find non-state color definition
- Node item = items.item(i);
- boolean hasState = false;
- if (item.getNodeType() == Node.ELEMENT_NODE) {
- Element element = (Element) item;
- if (element.hasAttributeNS(ANDROID_URI, ATTR_COLOR)) {
- NamedNodeMap attributes = element.getAttributes();
- for (int j = 0, m = attributes.getLength(); j < m; j++) {
- Attr attribute = (Attr) attributes.item(j);
- if (attribute.getLocalName().startsWith("state_")) { //$NON-NLS-1$
- hasState = true;
- break;
- }
- }
-
- if (!hasState) {
- return element.getAttributeNS(ANDROID_URI, ATTR_COLOR);
- }
- }
- }
- }
-
- return null;
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java
deleted file mode 100644
index 5ea1edc0e..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java
+++ /dev/null
@@ -1,242 +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.resources;
-
-import static com.android.SdkConstants.DOT_XML;
-
-import com.android.annotations.NonNull;
-import com.android.annotations.Nullable;
-import com.android.ide.common.resources.ResourceItem;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageUtils;
-import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
-import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
-import com.android.resources.ResourceFolderType;
-import com.android.resources.ResourceType;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.jdt.core.JavaConventions;
-import org.eclipse.jface.dialogs.IInputValidator;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Validator which ensures that new Android resource names are valid.
- */
-public class ResourceNameValidator implements IInputValidator {
- /** Set of existing names to check for conflicts with */
- private Set<String> mExisting;
-
- /** If true, the validated name must be unique */
- private boolean mUnique = true;
-
- /** If true, the validated name must exist */
- private boolean mExist;
-
- /**
- * True if the resource name being considered is a "file" based resource (where the
- * resource name is the actual file name, rather than just a value attribute inside an
- * XML file name of arbitrary name
- */
- private boolean mIsFileType;
-
- /**
- * True if the resource type can point to image resources
- */
- private boolean mIsImageType;
-
- /** If true, allow .xml as a name suffix */
- private boolean mAllowXmlExtension;
-
- private ResourceNameValidator(boolean allowXmlExtension, Set<String> existing,
- boolean isFileType, boolean isImageType) {
- mAllowXmlExtension = allowXmlExtension;
- mExisting = existing;
- mIsFileType = isFileType;
- mIsImageType = isImageType;
- }
-
- /**
- * Makes the resource name validator require that names are unique.
- *
- * @return this, for construction chaining
- */
- public ResourceNameValidator unique() {
- mUnique = true;
- mExist = false;
-
- return this;
- }
-
- /**
- * Makes the resource name validator require that names already exist
- *
- * @return this, for construction chaining
- */
- public ResourceNameValidator exist() {
- mExist = true;
- mUnique = false;
-
- return this;
- }
-
- @Override
- public String isValid(String newText) {
- // IValidator has the same interface as SWT's IInputValidator
- try {
- if (newText == null || newText.trim().length() == 0) {
- return "Enter a new name";
- }
-
- if (mAllowXmlExtension && newText.endsWith(DOT_XML)) {
- newText = newText.substring(0, newText.length() - DOT_XML.length());
- }
-
- if (mAllowXmlExtension && mIsImageType
- && ImageUtils.hasImageExtension(newText)) {
- newText = newText.substring(0, newText.lastIndexOf('.'));
- }
-
- if (!mIsFileType) {
- newText = newText.replace('.', '_');
- }
-
- if (newText.indexOf('.') != -1 && !newText.endsWith(DOT_XML)) {
- if (mIsImageType) {
- return "The filename must end with .xml or .png";
- } else {
- return "The filename must end with .xml";
- }
- }
-
- // Resource names must be valid Java identifiers, since they will
- // be represented as Java identifiers in the R file:
- if (!Character.isJavaIdentifierStart(newText.charAt(0))) {
- return "The resource name must begin with a character";
- }
- for (int i = 1, n = newText.length(); i < n; i++) {
- char c = newText.charAt(i);
- if (!Character.isJavaIdentifierPart(c)) {
- return String.format("'%1$c' is not a valid resource name character", c);
- }
- }
-
- if (mIsFileType) {
- char first = newText.charAt(0);
- if (!(first >= 'a' && first <= 'z')) {
- return String.format(
- "File-based resource names must start with a lowercase letter.");
- }
-
- // AAPT only allows lowercase+digits+_:
- // "%s: Invalid file name: must contain only [a-z0-9_.]","
- for (int i = 0, n = newText.length(); i < n; i++) {
- char c = newText.charAt(i);
- if (!((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_')) {
- return String.format(
- "File-based resource names must contain only lowercase a-z, 0-9, or _.");
- }
- }
- }
-
- String level = "1.5"; //$NON-NLS-1$
- IStatus validIdentifier = JavaConventions.validateIdentifier(newText, level, level);
- if (!validIdentifier.isOK()) {
- return String.format("%1$s is not a valid name (reserved Java keyword)", newText);
- }
-
-
- if (mExisting != null && (mUnique || mExist)) {
- boolean exists = mExisting.contains(newText);
- if (mUnique && exists) {
- return String.format("%1$s already exists", newText);
- } else if (mExist && !exists) {
- return String.format("%1$s does not exist", newText);
- }
- }
-
- return null;
- } catch (Exception e) {
- AdtPlugin.log(e, "Validation failed: %s", e.toString());
- return ""; //$NON-NLS-1$
- }
- }
-
- /**
- * Creates a new {@link ResourceNameValidator}
- *
- * @param allowXmlExtension if true, allow .xml to be entered as a suffix for the
- * resource name
- * @param type the resource type of the resource name being validated
- * @return a new {@link ResourceNameValidator}
- */
- public static ResourceNameValidator create(boolean allowXmlExtension,
- ResourceFolderType type) {
- boolean isFileType = type != ResourceFolderType.VALUES;
- return new ResourceNameValidator(allowXmlExtension, null, isFileType,
- type == ResourceFolderType.DRAWABLE);
- }
-
- /**
- * Creates a new {@link ResourceNameValidator}
- *
- * @param allowXmlExtension if true, allow .xml to be entered as a suffix for the
- * resource name
- * @param existing An optional set of names that already exist (and therefore will not
- * be considered valid if entered as the new name)
- * @param type the resource type of the resource name being validated
- * @return a new {@link ResourceNameValidator}
- */
- public static ResourceNameValidator create(boolean allowXmlExtension, Set<String> existing,
- ResourceType type) {
- boolean isFileType = ResourceHelper.isFileBasedResourceType(type);
- return new ResourceNameValidator(allowXmlExtension, existing, isFileType,
- type == ResourceType.DRAWABLE).unique();
- }
-
- /**
- * Creates a new {@link ResourceNameValidator}. By default, the name will need to be
- * unique in the project.
- *
- * @param allowXmlExtension if true, allow .xml to be entered as a suffix for the
- * resource name
- * @param project the project to validate new resource names for
- * @param type the resource type of the resource name being validated
- * @return a new {@link ResourceNameValidator}
- */
- public static ResourceNameValidator create(boolean allowXmlExtension,
- @Nullable IProject project,
- @NonNull ResourceType type) {
- Set<String> existing = null;
- if (project != null) {
- existing = new HashSet<String>();
- ResourceManager manager = ResourceManager.getInstance();
- ProjectResources projectResources = manager.getProjectResources(project);
- Collection<ResourceItem> items = projectResources.getResourceItemsOfType(type);
- for (ResourceItem item : items) {
- existing.add(item.getName());
- }
- }
-
- boolean isFileType = ResourceHelper.isFileBasedResourceType(type);
- return new ResourceNameValidator(allowXmlExtension, existing, isFileType,
- type == ResourceType.DRAWABLE);
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/CompiledResourcesMonitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/CompiledResourcesMonitor.java
deleted file mode 100644
index ab5ae4070..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/CompiledResourcesMonitor.java
+++ /dev/null
@@ -1,313 +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.annotations.NonNull;
-import com.android.annotations.Nullable;
-import com.android.ide.common.resources.IntArrayWrapper;
-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.project.AndroidManifestHelper;
-import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
-import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IFileListener;
-import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IProjectListener;
-import com.android.resources.ResourceType;
-import com.android.util.Pair;
-
-import org.eclipse.core.resources.IFile;
-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.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IStatus;
-
-import java.io.File;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.EnumMap;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Pattern;
-
-/**
- * A monitor for the compiled resources. This only monitors changes in the resources of type
- * {@link ResourceType#ID}.
- */
-public final class CompiledResourcesMonitor implements IFileListener, IProjectListener {
-
- private final static CompiledResourcesMonitor sThis = new CompiledResourcesMonitor();
-
- /**
- * Sets up the monitoring system.
- * @param monitor The main Resource Monitor.
- */
- public static void setupMonitor(GlobalProjectMonitor monitor) {
- monitor.addFileListener(sThis, IResourceDelta.ADDED | IResourceDelta.CHANGED);
- monitor.addProjectListener(sThis);
- }
-
- /**
- * private constructor to prevent construction.
- */
- private CompiledResourcesMonitor() {
- }
-
-
- /* (non-Javadoc)
- * Sent when a file changed : if the file is the R class, then it is parsed again to update
- * the internal 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)}
- *
- * @see IFileListener#fileChanged
- */
- @Override
- public void fileChanged(@NonNull IFile file, @NonNull IMarkerDelta[] markerDeltas,
- int kind, @Nullable String extension, int flags, boolean isAndroidProject) {
- if (!isAndroidProject || flags == IResourceDelta.MARKERS) {
- // Not Android or only the markers changed: not relevant
- return;
- }
-
- IProject project = file.getProject();
-
- if (file.getName().equals(SdkConstants.FN_COMPILED_RESOURCE_CLASS)) {
- // create the classname
- String className = getRClassName(project);
- if (className == null) {
- // We need to abort.
- AdtPlugin.log(IStatus.ERROR,
- "fileChanged: failed to find manifest package for project %1$s", //$NON-NLS-1$
- project.getName());
- return;
- }
- // path will begin with /projectName/bin/classes so we'll ignore that
- IPath relativeClassPath = file.getFullPath().removeFirstSegments(3);
- if (packagePathMatches(relativeClassPath.toString(), className)) {
- loadAndParseRClass(project, className);
- }
- }
- }
-
- /**
- * Check to see if the package section of the given path matches the packageName.
- * For example, /project/bin/classes/com/foo/app/R.class should match com.foo.app.R
- * @param path the pathname of the file to look at
- * @param packageName the package qualified name of the class
- * @return true if the package section of the path matches the package qualified name
- */
- private boolean packagePathMatches(String path, String packageName) {
- // First strip the ".class" off the end of the path
- String pathWithoutExtension = path.substring(0, path.indexOf(SdkConstants.DOT_CLASS));
-
- // then split the components of each path by their separators
- String [] pathArray = pathWithoutExtension.split(Pattern.quote(File.separator));
- String [] packageArray = packageName.split(AdtConstants.RE_DOT);
-
-
- int pathIndex = 0;
- int packageIndex = 0;
-
- while (pathIndex < pathArray.length && packageIndex < packageArray.length) {
- if (pathArray[pathIndex].equals(packageArray[packageIndex]) == false) {
- return false;
- }
- pathIndex++;
- packageIndex++;
- }
- // We may have matched all the way up to this point, but we're not sure it's a match
- // unless BOTH paths done
- return (pathIndex == pathArray.length && packageIndex == packageArray.length);
- }
-
- /**
- * Processes project close event.
- */
- @Override
- public void projectClosed(IProject project) {
- // the ProjectResources object will be removed by the ResourceManager.
- }
-
- /**
- * Processes project delete event.
- */
- @Override
- public void projectDeleted(IProject project) {
- // the ProjectResources object will be removed by the ResourceManager.
- }
-
- /**
- * Processes project open event.
- */
- @Override
- public void projectOpened(IProject project) {
- // when the project is opened, we get an ADDED event for each file, so we don't
- // need to do anything here.
- }
-
- @Override
- public void projectRenamed(IProject project, IPath from) {
- // renamed projects also trigger delete/open event,
- // so nothing to be done here.
- }
-
- /**
- * Processes existing project at init time.
- */
- @Override
- public void projectOpenedWithWorkspace(IProject project) {
- try {
- // check this is an android project
- if (project.hasNature(AdtConstants.NATURE_DEFAULT)) {
- String className = getRClassName(project);
- // Find the classname
- if (className == null) {
- // We need to abort.
- AdtPlugin.log(IStatus.ERROR,
- "projectOpenedWithWorkspace: failed to find manifest package for project %1$s", //$NON-NLS-1$
- project.getName());
- return;
- }
- loadAndParseRClass(project, className);
- }
- } catch (CoreException e) {
- // pass
- }
- }
-
- @Override
- public void allProjectsOpenedWithWorkspace() {
- // nothing to do.
- }
-
-
- private void loadAndParseRClass(IProject project, String className) {
- try {
- // first check there's a ProjectResources to store the content
- ProjectResources projectResources = ResourceManager.getInstance().getProjectResources(
- project);
-
- if (projectResources != null) {
- // create a temporary class loader to load the class
- ProjectClassLoader loader = new ProjectClassLoader(null /* parentClassLoader */,
- project);
-
- try {
- Class<?> clazz = loader.loadClass(className);
-
- if (clazz != null) {
- // create the maps to store the result of the parsing
- Map<ResourceType, Map<String, Integer>> resourceValueMap =
- new EnumMap<ResourceType, Map<String, Integer>>(ResourceType.class);
- Map<Integer, Pair<ResourceType, String>> genericValueToNameMap =
- new HashMap<Integer, Pair<ResourceType, String>>();
- Map<IntArrayWrapper, String> styleableValueToNameMap =
- new HashMap<IntArrayWrapper, String>();
-
- // parse the class
- if (parseClass(clazz, genericValueToNameMap, styleableValueToNameMap,
- resourceValueMap)) {
- // now we associate the maps to the project.
- projectResources.setCompiledResources(genericValueToNameMap,
- styleableValueToNameMap, resourceValueMap);
- }
- }
- } catch (Error e) {
- // Log this error with the class name we're trying to load and abort.
- AdtPlugin.log(e, "loadAndParseRClass failed to find class %1$s", className); //$NON-NLS-1$
- }
- }
- } catch (ClassNotFoundException e) {
- // pass
- }
- }
-
- /**
- * Parses a R class, and fills maps.
- * @param rClass the class to parse
- * @param genericValueToNameMap
- * @param styleableValueToNameMap
- * @param resourceValueMap
- * @return True if we managed to parse the R class.
- */
- private boolean parseClass(Class<?> rClass,
- Map<Integer, Pair<ResourceType, String>> genericValueToNameMap,
- Map<IntArrayWrapper, String> styleableValueToNameMap, Map<ResourceType,
- Map<String, Integer>> resourceValueMap) {
- try {
- for (Class<?> inner : rClass.getDeclaredClasses()) {
- String resTypeName = inner.getSimpleName();
- ResourceType resType = ResourceType.getEnum(resTypeName);
-
- if (resType != null) {
- Map<String, Integer> fullMap = new HashMap<String, Integer>();
- resourceValueMap.put(resType, fullMap);
-
- for (Field f : inner.getDeclaredFields()) {
- // only process static final fields.
- int modifiers = f.getModifiers();
- if (Modifier.isStatic(modifiers)) {
- Class<?> type = f.getType();
- if (type.isArray() && type.getComponentType() == int.class) {
- // if the object is an int[] we put it in the styleable map
- styleableValueToNameMap.put(
- new IntArrayWrapper((int[]) f.get(null)),
- f.getName());
- } else if (type == int.class) {
- Integer value = (Integer) f.get(null);
- genericValueToNameMap.put(value, Pair.of(resType, f.getName()));
- fullMap.put(f.getName(), value);
- } else {
- assert false;
- }
- }
- }
- }
- }
-
- return true;
- } catch (IllegalArgumentException e) {
- } catch (IllegalAccessException e) {
- }
- return false;
- }
-
- /**
- * Returns the class name of the R class, based on the project's manifest's package.
- *
- * @return A class name (e.g. "my.app.R") or null if there's no valid package in the manifest.
- */
- private String getRClassName(IProject project) {
- IFile manifestFile = ProjectHelper.getManifest(project);
- if (manifestFile != null && manifestFile.isSynchronized(IResource.DEPTH_ZERO)) {
- ManifestData data = AndroidManifestHelper.parseForData(manifestFile);
- if (data != null) {
- String javaPackage = data.getPackage();
- return javaPackage + ".R"; //$NON-NLS-1$
- }
- }
- return null;
- }
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/DynamicIdMap.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/DynamicIdMap.java
deleted file mode 100644
index 7bab4fd54..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/DynamicIdMap.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2012 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.resources.ResourceType;
-import com.android.util.Pair;
-import com.android.utils.SparseArray;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class DynamicIdMap {
-
- private final Map<Pair<ResourceType, String>, Integer> mDynamicIds = new HashMap<Pair<ResourceType, String>, Integer>();
- private final SparseArray<Pair<ResourceType, String>> mRevDynamicIds = new SparseArray<Pair<ResourceType, String>>();
- private int mDynamicSeed;
-
- public DynamicIdMap(int seed) {
- mDynamicSeed = seed;
- }
-
- public void reset(int seed) {
- mDynamicIds.clear();
- mRevDynamicIds.clear();
- mDynamicSeed = seed;
- }
-
- /**
- * Returns a dynamic integer for the given resource type/name, creating it if it doesn't
- * already exist.
- *
- * @param type the type of the resource
- * @param name the name of the resource
- * @return an integer.
- */
- public Integer getId(ResourceType type, String name) {
- return getId(Pair.of(type, name));
- }
-
- /**
- * Returns a dynamic integer for the given resource type/name, creating it if it doesn't
- * already exist.
- *
- * @param resource the type/name of the resource
- * @return an integer.
- */
- public Integer getId(Pair<ResourceType, String> resource) {
- Integer value = mDynamicIds.get(resource);
- if (value == null) {
- value = Integer.valueOf(++mDynamicSeed);
- mDynamicIds.put(resource, value);
- mRevDynamicIds.put(value, resource);
- }
-
- return value;
- }
-
- public Pair<ResourceType, String> resolveId(int id) {
- return mRevDynamicIds.get(id);
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/GlobalProjectMonitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/GlobalProjectMonitor.java
deleted file mode 100644
index 674a601d0..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/GlobalProjectMonitor.java
+++ /dev/null
@@ -1,546 +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.annotations.NonNull;
-import com.android.annotations.Nullable;
-import com.android.ide.common.resources.ResourceFile;
-import com.android.ide.common.resources.ResourceFolder;
-import com.android.ide.eclipse.adt.AdtConstants;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
-
-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.IResourceChangeEvent;
-import org.eclipse.core.resources.IResourceChangeListener;
-import org.eclipse.core.resources.IResourceDelta;
-import org.eclipse.core.resources.IResourceDeltaVisitor;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.jdt.core.IJavaModel;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaCore;
-
-import java.util.ArrayList;
-
-/**
- * The Global Project Monitor tracks project file changes, and forward them to simple project,
- * file, and folder listeners.
- * Those listeners can be setup with masks to listen to particular events.
- * <p/>
- * To track project resource changes, use the monitor in the {@link ResourceManager}. It is more
- * efficient and while the global ProjectMonitor can track any file, deleted resource files
- * cannot be matched to previous {@link ResourceFile} or {@link ResourceFolder} objects by the
- * time the listeners get the event notifications.
- *
- * @see IProjectListener
- * @see IFolderListener
- * @see IFileListener
- */
-public final class GlobalProjectMonitor {
-
- private final static GlobalProjectMonitor sThis = new GlobalProjectMonitor();
-
- /**
- * Classes which implement this interface provide a method that deals
- * with file change events.
- */
- public interface IFileListener {
- /**
- * Sent when a file changed.
- *
- * @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 extension the extension of the file or null if the file does
- * not have an extension
- * @param flags the {@link IResourceDelta#getFlags()} value with details
- * on what changed in the file
- * @param isAndroidProject whether the parent project is an Android Project
- */
- public void fileChanged(@NonNull IFile file, @NonNull IMarkerDelta[] markerDeltas,
- int kind, @Nullable String extension, int flags, boolean isAndroidProject);
- }
-
- /**
- * Classes which implements this interface provide methods dealing with project events.
- */
- public interface IProjectListener {
- /**
- * Sent for each opened android project at the time the listener is put in place.
- * @param project the opened project.
- */
- public void projectOpenedWithWorkspace(IProject project);
-
- /**
- * Sent once after all Android projects have been opened,
- * at the time the listener is put in place.
- * <p/>
- * This is called after {@link #projectOpenedWithWorkspace(IProject)} has
- * been called on all known Android projects.
- */
- public void allProjectsOpenedWithWorkspace();
-
- /**
- * Sent when a project is opened.
- * @param project the project being opened.
- */
- public void projectOpened(IProject project);
-
- /**
- * Sent when a project is closed.
- * @param project the project being closed.
- */
- public void projectClosed(IProject project);
-
- /**
- * Sent when a project is deleted.
- * @param project the project about to be deleted.
- */
- public void projectDeleted(IProject project);
-
- /**
- * Sent when a project is renamed. During a project rename
- * {@link #projectDeleted(IProject)} and {@link #projectOpened(IProject)} are also called.
- * This is called last.
- *
- * @param project the new {@link IProject} object.
- * @param from the path of the project before the rename action.
- */
- public void projectRenamed(IProject project, IPath from);
- }
-
- /**
- * Classes which implement this interface provide a method that deals
- * with folder change events
- */
- public interface IFolderListener {
- /**
- * Sent when a folder changed.
- * @param folder The file that was changed
- * @param kind The change kind. This is equivalent to {@link IResourceDelta#getKind()}
- * @param isAndroidProject whether the parent project is an Android Project
- */
- public void folderChanged(IFolder folder, int kind, boolean isAndroidProject);
- }
-
- /**
- * Interface for a listener to be notified when resource change event starts and ends.
- */
- public interface IResourceEventListener {
- public void resourceChangeEventStart();
- public void resourceChangeEventEnd();
- }
-
- /**
- * Interface for a listener that gets passed the raw delta without processing.
- */
- public interface IRawDeltaListener {
- public void visitDelta(IResourceDelta delta);
- }
-
- /**
- * Base listener bundle to associate a listener to an event mask.
- */
- private static class ListenerBundle {
- /** Mask value to accept all events */
- public final static int MASK_NONE = -1;
-
- /**
- * Event mask. Values accepted are IResourceDelta.###
- * @see IResourceDelta#ADDED
- * @see IResourceDelta#REMOVED
- * @see IResourceDelta#CHANGED
- * @see IResourceDelta#ADDED_PHANTOM
- * @see IResourceDelta#REMOVED_PHANTOM
- * */
- int kindMask;
- }
-
- /**
- * Listener bundle for file event.
- */
- private static class FileListenerBundle extends ListenerBundle {
-
- /** The file listener */
- IFileListener listener;
- }
-
- /**
- * Listener bundle for folder event.
- */
- private static class FolderListenerBundle extends ListenerBundle {
- /** The file listener */
- IFolderListener listener;
- }
-
- private final ArrayList<FileListenerBundle> mFileListeners =
- new ArrayList<FileListenerBundle>();
-
- private final ArrayList<FolderListenerBundle> mFolderListeners =
- new ArrayList<FolderListenerBundle>();
-
- private final ArrayList<IProjectListener> mProjectListeners = new ArrayList<IProjectListener>();
-
- private final ArrayList<IResourceEventListener> mEventListeners =
- new ArrayList<IResourceEventListener>();
-
- private final ArrayList<IRawDeltaListener> mRawDeltaListeners =
- new ArrayList<IRawDeltaListener>();
-
- private IWorkspace mWorkspace;
-
- private boolean mIsAndroidProject;
-
- /**
- * Delta visitor for resource changes.
- */
- private final class DeltaVisitor implements IResourceDeltaVisitor {
-
- @Override
- public boolean visit(IResourceDelta delta) {
- // Find the other resource listeners to notify
- IResource r = delta.getResource();
- int type = r.getType();
- if (type == IResource.FILE) {
- int kind = delta.getKind();
- // notify the listeners.
- for (FileListenerBundle bundle : mFileListeners) {
- if (bundle.kindMask == ListenerBundle.MASK_NONE
- || (bundle.kindMask & kind) != 0) {
- try {
- bundle.listener.fileChanged((IFile)r, delta.getMarkerDeltas(), kind,
- r.getFileExtension(), delta.getFlags(), mIsAndroidProject);
- } catch (Throwable t) {
- AdtPlugin.log(t,"Failed to call IFileListener.fileChanged");
- }
- }
- }
- return false;
- } else if (type == IResource.FOLDER) {
- int kind = delta.getKind();
- // notify the listeners.
- for (FolderListenerBundle bundle : mFolderListeners) {
- if (bundle.kindMask == ListenerBundle.MASK_NONE
- || (bundle.kindMask & kind) != 0) {
- try {
- bundle.listener.folderChanged((IFolder)r, kind, mIsAndroidProject);
- } catch (Throwable t) {
- AdtPlugin.log(t,"Failed to call IFileListener.folderChanged");
- }
- }
- }
- return true;
- } else if (type == IResource.PROJECT) {
- IProject project = (IProject)r;
-
- try {
- mIsAndroidProject = project.hasNature(AdtConstants.NATURE_DEFAULT);
- } catch (CoreException e) {
- // this can only happen if the project does not exist or is not open, neither
- // of which can happen here since we are processing changes in the project
- // or at worst a project post-open event.
- return false;
- }
-
- if (mIsAndroidProject == false) {
- // for non android project, skip the project listeners but return true
- // to visit the children and notify the IFileListeners
- return true;
- }
-
- int flags = delta.getFlags();
-
- if ((flags & IResourceDelta.OPEN) != 0) {
- // the project is opening or closing.
-
- if (project.isOpen()) {
- // notify the listeners.
- for (IProjectListener pl : mProjectListeners) {
- try {
- pl.projectOpened(project);
- } catch (Throwable t) {
- AdtPlugin.log(t,"Failed to call IProjectListener.projectOpened");
- }
- }
- } else {
- // notify the listeners.
- for (IProjectListener pl : mProjectListeners) {
- try {
- pl.projectClosed(project);
- } catch (Throwable t) {
- AdtPlugin.log(t,"Failed to call IProjectListener.projectClosed");
- }
- }
- }
-
- if ((flags & IResourceDelta.MOVED_FROM) != 0) {
- IPath from = delta.getMovedFromPath();
- // notify the listeners.
- for (IProjectListener pl : mProjectListeners) {
- try {
- pl.projectRenamed(project, from);
- } catch (Throwable t) {
- AdtPlugin.log(t,"Failed to call IProjectListener.projectRenamed");
- }
- }
- }
- }
- }
-
- return true;
- }
- }
-
- public static GlobalProjectMonitor getMonitor() {
- return sThis;
- }
-
-
- /**
- * Starts the resource monitoring.
- * @param ws The current workspace.
- * @return The monitor object.
- */
- public static GlobalProjectMonitor startMonitoring(IWorkspace ws) {
- if (sThis != null) {
- ws.addResourceChangeListener(sThis.mResourceChangeListener,
- IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_DELETE);
- sThis.mWorkspace = ws;
- }
- return sThis;
- }
-
- /**
- * Stops the resource monitoring.
- * @param ws The current workspace.
- */
- public static void stopMonitoring(IWorkspace ws) {
- if (sThis != null) {
- ws.removeResourceChangeListener(sThis.mResourceChangeListener);
-
- synchronized (sThis) {
- sThis.mFileListeners.clear();
- sThis.mProjectListeners.clear();
- }
- }
- }
-
- /**
- * Adds a file listener.
- * @param listener The listener to receive the events.
- * @param kindMask The event mask to filter out specific events.
- * {@link ListenerBundle#MASK_NONE} will forward all events.
- * See {@link ListenerBundle#kindMask} for more values.
- */
- public synchronized void addFileListener(IFileListener listener, int kindMask) {
- FileListenerBundle bundle = new FileListenerBundle();
- bundle.listener = listener;
- bundle.kindMask = kindMask;
-
- mFileListeners.add(bundle);
- }
-
- /**
- * Removes an existing file listener.
- * @param listener the listener to remove.
- */
- public synchronized void removeFileListener(IFileListener listener) {
- for (int i = 0 ; i < mFileListeners.size() ; i++) {
- FileListenerBundle bundle = mFileListeners.get(i);
- if (bundle.listener == listener) {
- mFileListeners.remove(i);
- return;
- }
- }
- }
-
- /**
- * Adds a folder listener.
- * @param listener The listener to receive the events.
- * @param kindMask The event mask to filter out specific events.
- * {@link ListenerBundle#MASK_NONE} will forward all events.
- * See {@link ListenerBundle#kindMask} for more values.
- */
- public synchronized void addFolderListener(IFolderListener listener, int kindMask) {
- FolderListenerBundle bundle = new FolderListenerBundle();
- bundle.listener = listener;
- bundle.kindMask = kindMask;
-
- mFolderListeners.add(bundle);
- }
-
- /**
- * Removes an existing folder listener.
- * @param listener the listener to remove.
- */
- public synchronized void removeFolderListener(IFolderListener listener) {
- for (int i = 0 ; i < mFolderListeners.size() ; i++) {
- FolderListenerBundle bundle = mFolderListeners.get(i);
- if (bundle.listener == listener) {
- mFolderListeners.remove(i);
- return;
- }
- }
- }
-
- /**
- * Adds a project listener.
- * @param listener The listener to receive the events.
- */
- public synchronized void addProjectListener(IProjectListener listener) {
- mProjectListeners.add(listener);
-
- // we need to look at the opened projects and give them to the listener.
-
- // get the list of opened android projects.
- IWorkspaceRoot workspaceRoot = mWorkspace.getRoot();
- IJavaModel javaModel = JavaCore.create(workspaceRoot);
- IJavaProject[] androidProjects = BaseProjectHelper.getAndroidProjects(javaModel,
- null /*filter*/);
-
-
- notifyResourceEventStart();
-
- for (IJavaProject androidProject : androidProjects) {
- listener.projectOpenedWithWorkspace(androidProject.getProject());
- }
-
- listener.allProjectsOpenedWithWorkspace();
-
- notifyResourceEventEnd();
- }
-
- /**
- * Removes an existing project listener.
- * @param listener the listener to remove.
- */
- public synchronized void removeProjectListener(IProjectListener listener) {
- mProjectListeners.remove(listener);
- }
-
- /**
- * Adds a resource event listener.
- * @param listener The listener to receive the events.
- */
- public synchronized void addResourceEventListener(IResourceEventListener listener) {
- mEventListeners.add(listener);
- }
-
- /**
- * Removes an existing Resource Event listener.
- * @param listener the listener to remove.
- */
- public synchronized void removeResourceEventListener(IResourceEventListener listener) {
- mEventListeners.remove(listener);
- }
-
- /**
- * Adds a raw delta listener.
- * @param listener The listener to receive the deltas.
- */
- public synchronized void addRawDeltaListener(IRawDeltaListener listener) {
- mRawDeltaListeners.add(listener);
- }
-
- /**
- * Removes an existing Raw Delta listener.
- * @param listener the listener to remove.
- */
- public synchronized void removeRawDeltaListener(IRawDeltaListener listener) {
- mRawDeltaListeners.remove(listener);
- }
-
- private void notifyResourceEventStart() {
- for (IResourceEventListener listener : mEventListeners) {
- try {
- listener.resourceChangeEventStart();
- } catch (Throwable t) {
- AdtPlugin.log(t,"Failed to call IResourceEventListener.resourceChangeEventStart");
- }
- }
- }
-
- private void notifyResourceEventEnd() {
- for (IResourceEventListener listener : mEventListeners) {
- try {
- listener.resourceChangeEventEnd();
- } catch (Throwable t) {
- AdtPlugin.log(t,"Failed to call IResourceEventListener.resourceChangeEventEnd");
- }
- }
- }
-
- private IResourceChangeListener mResourceChangeListener = new IResourceChangeListener() {
- /**
- * Processes the workspace resource change events.
- *
- * @see IResourceChangeListener#resourceChanged(IResourceChangeEvent)
- */
- @Override
- public synchronized void resourceChanged(IResourceChangeEvent event) {
- // notify the event listeners of a start.
- notifyResourceEventStart();
-
- if (event.getType() == IResourceChangeEvent.PRE_DELETE) {
- // a project is being deleted. Lets get the project object and remove
- // its compiled resource list.
- IResource r = event.getResource();
- IProject project = r.getProject();
-
- // notify the listeners.
- for (IProjectListener pl : mProjectListeners) {
- try {
- if (project.hasNature(AdtConstants.NATURE_DEFAULT)) {
- try {
- pl.projectDeleted(project);
- } catch (Throwable t) {
- AdtPlugin.log(t,"Failed to call IProjectListener.projectDeleted");
- }
- }
- } catch (CoreException e) {
- // just ignore this project.
- }
- }
- } else {
- // this a regular resource change. We get the delta and go through it with a visitor.
- IResourceDelta delta = event.getDelta();
-
- // notify the raw delta listeners
- for (IRawDeltaListener listener : mRawDeltaListeners) {
- listener.visitDelta(delta);
- }
-
- DeltaVisitor visitor = new DeltaVisitor();
- try {
- delta.accept(visitor);
- } catch (CoreException e) {
- }
- }
-
- // we're done, notify the event listeners.
- notifyResourceEventEnd();
- }
- };
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/IdeScanningContext.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/IdeScanningContext.java
deleted file mode 100644
index d61324937..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/IdeScanningContext.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2011 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 static com.android.SdkConstants.ANDROID_URI;
-import static com.android.ide.eclipse.adt.AdtConstants.MARKER_AAPT_COMPILE;
-import static org.eclipse.core.resources.IResource.DEPTH_ONE;
-import static org.eclipse.core.resources.IResource.DEPTH_ZERO;
-
-import com.android.annotations.NonNull;
-import com.android.annotations.Nullable;
-import com.android.ide.common.resources.ResourceRepository;
-import com.android.ide.common.resources.ScanningContext;
-import com.android.ide.common.resources.platform.AttributeInfo;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.build.AaptParser;
-import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
-import com.android.ide.eclipse.adt.internal.sdk.Sdk;
-import com.android.utils.Pair;
-
-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.runtime.CoreException;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * An {@link IdeScanningContext} is a specialized {@link ScanningContext} which
- * carries extra information about the scanning state, such as which file is
- * currently being scanned, and which files have been scanned in the past, such
- * that at the end of a scan we can mark and clear errors, etc.
- */
-public class IdeScanningContext extends ScanningContext {
- private final IProject mProject;
- private final List<IResource> mScannedResources = new ArrayList<IResource>();
- private IResource mCurrentFile;
- private List<Pair<IResource, String>> mErrors;
- private Set<IProject> mFullAaptProjects;
- private boolean mValidate;
- private Map<String, AttributeInfo> mAttributeMap;
- private ResourceRepository mFrameworkResources;
-
- /**
- * Constructs a new {@link IdeScanningContext}
- *
- * @param repository the associated {@link ResourceRepository}
- * @param project the associated project
- * @param validate if true, check that the attributes and resources are
- * valid and if not request a full AAPT check
- */
- public IdeScanningContext(@NonNull ResourceRepository repository, @NonNull IProject project,
- boolean validate) {
- super(repository);
- mProject = project;
- mValidate = validate;
-
- Sdk sdk = Sdk.getCurrent();
- if (sdk != null) {
- AndroidTargetData targetData = sdk.getTargetData(project);
- if (targetData != null) {
- mAttributeMap = targetData.getAttributeMap();
- mFrameworkResources = targetData.getFrameworkResources();
- }
- }
- }
-
- @Override
- public void addError(@NonNull String error) {
- super.addError(error);
-
- if (mErrors == null) {
- mErrors = new ArrayList<Pair<IResource,String>>();
- }
- mErrors.add(Pair.of(mCurrentFile, error));
- }
-
- /**
- * Notifies the context that the given resource is about to be scanned.
- *
- * @param resource the resource about to be scanned
- */
- public void startScanning(@NonNull IResource resource) {
- assert mCurrentFile == null : mCurrentFile;
- mCurrentFile = resource;
- mScannedResources.add(resource);
- }
-
- /**
- * Notifies the context that the given resource has been scanned.
- *
- * @param resource the resource that was scanned
- */
- public void finishScanning(@NonNull IResource resource) {
- assert mCurrentFile != null;
- mCurrentFile = null;
- }
-
- /**
- * Process any errors found to add error markers in the affected files (and
- * also clear up any aapt errors in files that are no longer applicable)
- *
- * @param async if true, delay updating markers until the next display
- * thread event loop update
- */
- public void updateMarkers(boolean async) {
- // Run asynchronously? This is necessary for example when adding markers
- // as the result of a resource change notification, since at that point the
- // resource tree is locked for modifications and attempting to create a
- // marker will throw a org.eclipse.core.internal.resources.ResourceException.
- if (async) {
- AdtPlugin.getDisplay().asyncExec(new Runnable() {
- @Override
- public void run() {
- updateMarkers(false);
- }
- });
- return;
- }
-
- // First clear out old/previous markers
- for (IResource resource : mScannedResources) {
- try {
- if (resource.exists()) {
- int depth = resource instanceof IFolder ? DEPTH_ONE : DEPTH_ZERO;
- resource.deleteMarkers(MARKER_AAPT_COMPILE, true, depth);
- }
- } catch (CoreException ce) {
- // Pass
- }
- }
-
- // Add new errors
- if (mErrors != null && mErrors.size() > 0) {
- List<String> errors = new ArrayList<String>();
- for (Pair<IResource, String> pair : mErrors) {
- errors.add(pair.getSecond());
- }
- AaptParser.parseOutput(errors, mProject);
- }
- }
-
- @Override
- public boolean needsFullAapt() {
- // returns true if it was explicitly requested or if a file that has errors was modified.
- // This handles the case where an edit doesn't add any new id but fix a compile error.
- return super.needsFullAapt() || hasModifiedFilesWithErrors();
- }
-
- /**
- * Returns true if any of the scanned resources has an error marker on it.
- */
- private boolean hasModifiedFilesWithErrors() {
- for (IResource resource : mScannedResources) {
- try {
- int depth = resource instanceof IFolder ? DEPTH_ONE : DEPTH_ZERO;
- if (resource.exists()) {
- IMarker[] markers = resource.findMarkers(IMarker.PROBLEM,
- true /*includeSubtypes*/, depth);
- for (IMarker marker : markers) {
- if (marker.getAttribute(IMarker.SEVERITY, IMarker.SEVERITY_INFO) ==
- IMarker.SEVERITY_ERROR) {
- return true;
- }
- }
- }
- } catch (CoreException ce) {
- // Pass
- }
- }
-
- return false;
- }
-
- @Override
- protected void requestFullAapt() {
- super.requestFullAapt();
-
- if (mCurrentFile != null) {
- if (mFullAaptProjects == null) {
- mFullAaptProjects = new HashSet<IProject>();
- }
- mFullAaptProjects.add(mCurrentFile.getProject());
- } else {
- assert false : "No current context to apply IdeScanningContext to";
- }
- }
-
- /**
- * Returns the collection of projects that scanned resources have requested
- * a full aapt for.
- *
- * @return a collection of projects that scanned resources requested full
- * aapt runs for, or null
- */
- public Collection<IProject> getAaptRequestedProjects() {
- return mFullAaptProjects;
- }
-
- @Override
- public boolean checkValue(@Nullable String uri, @NonNull String name, @NonNull String value) {
- if (!mValidate) {
- return true;
- }
-
- if (!needsFullAapt() && mAttributeMap != null && ANDROID_URI.equals(uri)) {
- AttributeInfo info = mAttributeMap.get(name);
- if (info != null && !info.isValid(value, mRepository, mFrameworkResources)) {
- return false;
- }
- }
-
- return super.checkValue(uri, name, value);
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectClassLoader.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectClassLoader.java
deleted file mode 100644
index e07f09927..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectClassLoader.java
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Copyright (C) 2008 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.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.build.BuildHelper;
-import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
-import com.android.ide.eclipse.adt.internal.sdk.Sdk;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.jdt.core.IClasspathContainer;
-import org.eclipse.jdt.core.IClasspathEntry;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.core.JavaModelException;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.Opcodes;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * ClassLoader able to load class from output of an Eclipse project.
- */
-public final class ProjectClassLoader extends ClassLoader {
-
- private final IJavaProject mJavaProject;
- private URLClassLoader mJarClassLoader;
- private boolean mInsideJarClassLoader = false;
-
- public ProjectClassLoader(ClassLoader parentClassLoader, IProject project) {
- super(parentClassLoader);
- mJavaProject = JavaCore.create(project);
- }
-
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- // if we are here through a child classloader, throw an exception.
- if (mInsideJarClassLoader) {
- throw new ClassNotFoundException(name);
- }
-
- // attempt to load the class from the main project
- Class<?> clazz = loadFromProject(mJavaProject, name);
-
- if (clazz != null) {
- return clazz;
- }
-
- // attempt to load the class from the jar dependencies
- clazz = loadClassFromJar(name);
- if (clazz != null) {
- return clazz;
- }
-
- // attempt to load the class from the libraries
- try {
- // get the project info
- ProjectState projectState = Sdk.getProjectState(mJavaProject.getProject());
-
- // this can happen if the project has no project.properties.
- if (projectState != null) {
-
- List<IProject> libProjects = projectState.getFullLibraryProjects();
- List<IJavaProject> referencedJavaProjects = BuildHelper.getJavaProjects(
- libProjects);
-
- for (IJavaProject javaProject : referencedJavaProjects) {
- clazz = loadFromProject(javaProject, name);
-
- if (clazz != null) {
- return clazz;
- }
- }
- }
- } catch (CoreException e) {
- // log exception?
- }
-
- throw new ClassNotFoundException(name);
- }
-
- /**
- * Attempts to load a class from a project output folder.
- * @param project the project to load the class from
- * @param name the name of the class
- * @return a class object if found, null otherwise.
- */
- private Class<?> loadFromProject(IJavaProject project, String name) {
- try {
- // get the project output folder.
- IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
- IPath outputLocation = project.getOutputLocation();
- IResource outRes = root.findMember(outputLocation);
- if (outRes == null) {
- return null;
- }
-
- File outFolder = new File(outRes.getLocation().toOSString());
-
- // get the class name segments
- String[] segments = name.split("\\."); //$NON-NLS-1$
-
- // try to load the class from the bin folder of the project.
- File classFile = getFile(outFolder, segments, 0);
- if (classFile == null) {
- return null;
- }
-
- // load the content of the file and create the class.
- FileInputStream fis = new FileInputStream(classFile);
- byte[] data = new byte[(int)classFile.length()];
- int read = 0;
- try {
- read = fis.read(data);
- } catch (IOException e) {
- data = null;
- }
- fis.close();
-
- if (data != null) {
- try {
- Class<?> clazz = defineClass(null, data, 0, read);
- if (clazz != null) {
- return clazz;
- }
- } catch (UnsupportedClassVersionError e) {
- // Attempt to reload on lower version
- int maxVersion = 50; // JDK 1.6
- try {
- byte[] rewritten = rewriteClass(data, maxVersion, 0);
- return defineClass(null, rewritten, 0, rewritten.length);
- } catch (UnsupportedClassVersionError e2) {
- throw e; // throw *original* exception, not attempt to rewrite
- }
- }
- }
- } catch (Exception e) {
- // log the exception?
- }
-
- return null;
- }
-
- /**
- * Rewrites the given class to the given target class file version.
- */
- public static byte[] rewriteClass(byte[] classData, final int maxVersion, final int minVersion) {
- assert maxVersion >= minVersion;
- ClassWriter classWriter = new ClassWriter(0);
- ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM5, classWriter) {
- @Override
- public void visit(int version, int access, String name, String signature,
- String superName, String[] interfaces) {
- if (version > maxVersion) {
- version = maxVersion;
- }
- if (version < minVersion) {
- version = minVersion;
- }
- super.visit(version, access, name, signature, superName, interfaces);
- }
- };
- ClassReader reader = new ClassReader(classData);
- reader.accept(classVisitor, 0);
- return classWriter.toByteArray();
- }
-
- /**
- * Returns the File matching the a certain path from a root {@link File}.
- * <p/>The methods checks that the file ends in .class even though the last segment
- * does not.
- * @param parent the root of the file.
- * @param segments the segments containing the path of the file
- * @param index the offset at which to start looking into segments.
- * @throws FileNotFoundException
- */
- private File getFile(File parent, String[] segments, int index)
- throws FileNotFoundException {
- // reached the end with no match?
- if (index == segments.length) {
- throw new FileNotFoundException();
- }
-
- String toMatch = segments[index];
- File[] files = parent.listFiles();
-
- // we're at the last segments. we look for a matching <file>.class
- if (index == segments.length - 1) {
- toMatch = toMatch + ".class";
-
- if (files != null) {
- for (File file : files) {
- if (file.isFile() && file.getName().equals(toMatch)) {
- return file;
- }
- }
- }
-
- // no match? abort.
- throw new FileNotFoundException();
- }
-
- String innerClassName = null;
-
- if (files != null) {
- for (File file : files) {
- if (file.isDirectory()) {
- if (toMatch.equals(file.getName())) {
- return getFile(file, segments, index+1);
- }
- } else if (file.getName().startsWith(toMatch)) {
- if (innerClassName == null) {
- StringBuilder sb = new StringBuilder(segments[index]);
- for (int i = index + 1 ; i < segments.length ; i++) {
- sb.append('$');
- sb.append(segments[i]);
- }
- sb.append(".class");
-
- innerClassName = sb.toString();
- }
-
- if (file.getName().equals(innerClassName)) {
- return file;
- }
- }
- }
- }
-
- return null;
- }
-
- /**
- * Loads a class from the 3rd party jar present in the project
- *
- * @return the class loader or null if not found.
- */
- private Class<?> loadClassFromJar(String name) {
- if (mJarClassLoader == null) {
- // get the OS path to all the external jars
- URL[] jars = getExternalJars();
-
- mJarClassLoader = new URLClassLoader(jars, this /* parent */);
- }
-
- try {
- // because a class loader always look in its parent loader first, we need to know
- // that we are querying the jar classloader. This will let us know to not query
- // it again for classes we don't find, or this would create an infinite loop.
- mInsideJarClassLoader = true;
- return mJarClassLoader.loadClass(name);
- } catch (ClassNotFoundException e) {
- // not found? return null.
- return null;
- } finally {
- mInsideJarClassLoader = false;
- }
- }
-
- /**
- * Returns an array of external jar files used by the project.
- * @return an array of OS-specific absolute file paths
- */
- private final URL[] getExternalJars() {
- // get a java project from it
- IJavaProject javaProject = JavaCore.create(mJavaProject.getProject());
-
- ArrayList<URL> oslibraryList = new ArrayList<URL>();
- IClasspathEntry[] classpaths = javaProject.readRawClasspath();
- if (classpaths != null) {
- for (IClasspathEntry e : classpaths) {
- if (e.getEntryKind() == IClasspathEntry.CPE_LIBRARY ||
- e.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
- // if this is a classpath variable reference, we resolve it.
- if (e.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
- e = JavaCore.getResolvedClasspathEntry(e);
- }
-
- handleClassPathEntry(e, oslibraryList);
- } else if (e.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
- // get the container.
- try {
- IClasspathContainer container = JavaCore.getClasspathContainer(
- e.getPath(), javaProject);
- // ignore the system and default_system types as they represent
- // libraries that are part of the runtime.
- if (container != null &&
- container.getKind() == IClasspathContainer.K_APPLICATION) {
- IClasspathEntry[] entries = container.getClasspathEntries();
- for (IClasspathEntry entry : entries) {
- // TODO: Xav -- is this necessary?
- if (entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
- entry = JavaCore.getResolvedClasspathEntry(entry);
- }
-
- handleClassPathEntry(entry, oslibraryList);
- }
- }
- } catch (JavaModelException jme) {
- // can't resolve the container? ignore it.
- AdtPlugin.log(jme, "Failed to resolve ClasspathContainer: %s",
- e.getPath());
- }
- }
- }
- }
-
- return oslibraryList.toArray(new URL[oslibraryList.size()]);
- }
-
- private void handleClassPathEntry(IClasspathEntry e, ArrayList<URL> oslibraryList) {
- // get the IPath
- IPath path = e.getPath();
-
- // check the name ends with .jar
- if (SdkConstants.EXT_JAR.equalsIgnoreCase(path.getFileExtension())) {
- boolean local = false;
- IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
- if (resource != null && resource.exists() &&
- resource.getType() == IResource.FILE) {
- local = true;
- try {
- oslibraryList.add(new File(resource.getLocation().toOSString())
- .toURI().toURL());
- } catch (MalformedURLException mue) {
- // pass
- }
- }
-
- if (local == false) {
- // if the jar path doesn't match a workspace resource,
- // then we get an OSString and check if this links to a valid file.
- String osFullPath = path.toOSString();
-
- File f = new File(osFullPath);
- if (f.exists()) {
- try {
- oslibraryList.add(f.toURI().toURL());
- } catch (MalformedURLException mue) {
- // pass
- }
- }
- }
- }
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java
deleted file mode 100644
index 7c3fd4c13..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java
+++ /dev/null
@@ -1,271 +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.annotations.NonNull;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.ide.common.resources.IntArrayWrapper;
-import com.android.ide.common.resources.ResourceFolder;
-import com.android.ide.common.resources.ResourceItem;
-import com.android.ide.common.resources.ResourceRepository;
-import com.android.ide.common.resources.configuration.FolderConfiguration;
-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.IFolderWrapper;
-import com.android.io.IAbstractFolder;
-import com.android.resources.ResourceType;
-import com.android.util.Pair;
-
-import org.eclipse.core.resources.IFolder;
-import org.eclipse.core.resources.IProject;
-
-import java.util.EnumMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-/**
- * Represents the resources of a project.
- * On top of the regular {@link ResourceRepository} features it provides:
- *<ul>
- *<li>configured resources contain the resources coming from the libraries.</li>
- *<li>resolution to and from resource integer (compiled value in R.java).</li>
- *<li>handles resource integer for non existing values of type ID. This is used when rendering.</li>
- *<li>layouts that have no been saved yet. This is handled by generating dynamic IDs
- * on the fly.</li>
- *</ul>
- */
-@SuppressWarnings("deprecation")
-public class ProjectResources extends ResourceRepository {
- // project resources are defined as 0x7FXX#### where XX is the resource type (layout, drawable,
- // etc...). Using FF as the type allows for 255 resource types before we get a collision
- // which should be fine.
- private final static int DYNAMIC_ID_SEED_START = 0x7fff0000;
-
- /** Map of (name, id) for resources of type {@link ResourceType#ID} coming from R.java */
- private Map<ResourceType, Map<String, Integer>> mResourceValueMap;
- /** Map of (id, [name, resType]) for all resources coming from R.java */
- private Map<Integer, Pair<ResourceType, String>> mResIdValueToNameMap;
- /** Map of (int[], name) for styleable resources coming from R.java */
- private Map<IntArrayWrapper, String> mStyleableValueToNameMap;
-
- private final DynamicIdMap mDynamicIdMap = new DynamicIdMap(DYNAMIC_ID_SEED_START);
- private final IntArrayWrapper mWrapper = new IntArrayWrapper(null);
- private final IProject mProject;
-
- public static ProjectResources create(IProject project) {
- IFolder resFolder = project.getFolder(SdkConstants.FD_RESOURCES);
-
- return new ProjectResources(project, new IFolderWrapper(resFolder));
- }
-
- /**
- * Makes a ProjectResources for a given <var>project</var>.
- * @param project the project.
- */
- private ProjectResources(IProject project, IAbstractFolder resFolder) {
- super(resFolder, false /*isFrameworkRepository*/);
- mProject = project;
- }
-
- /**
- * Returns the resources values matching a given {@link FolderConfiguration}, this will
- * include library dependency.
- *
- * @param referenceConfig the configuration that each value must match.
- * @return a map with guaranteed to contain an entry for each {@link ResourceType}
- */
- @Override
- @NonNull
- public Map<ResourceType, Map<String, ResourceValue>> getConfiguredResources(
- @NonNull FolderConfiguration referenceConfig) {
- ensureInitialized();
-
- Map<ResourceType, Map<String, ResourceValue>> resultMap =
- new EnumMap<ResourceType, Map<String, ResourceValue>>(ResourceType.class);
-
- // if the project contains libraries, we need to add the libraries resources here
- // so that they are accessible to the layout rendering.
- if (mProject != null) {
- ProjectState state = Sdk.getProjectState(mProject);
- if (state != null) {
- List<IProject> libraries = state.getFullLibraryProjects();
-
- ResourceManager resMgr = ResourceManager.getInstance();
-
- // because aapt put all the library in their order in this array, the first
- // one will have priority over the 2nd one. So it's better to loop in the inverse
- // order and fill the map with resources that will be overwritten by higher
- // priority resources
- for (int i = libraries.size() - 1 ; i >= 0 ; i--) {
- IProject library = libraries.get(i);
-
- ProjectResources libRes = resMgr.getProjectResources(library);
- if (libRes != null) {
- // get the library resources, and only the library, not the dependencies
- // so call doGetConfiguredResources() directly.
- Map<ResourceType, Map<String, ResourceValue>> libMap =
- libRes.doGetConfiguredResources(referenceConfig);
-
- // we don't want to simply replace the whole map, but instead merge the
- // content of any sub-map
- for (Entry<ResourceType, Map<String, ResourceValue>> libEntry :
- libMap.entrySet()) {
-
- // get the map currently in the result map for this resource type
- Map<String, ResourceValue> tempMap = resultMap.get(libEntry.getKey());
- if (tempMap == null) {
- // since there's no current map for this type, just add the map
- // directly coming from the library resources
- resultMap.put(libEntry.getKey(), libEntry.getValue());
- } else {
- // already a map for this type. add the resources from the
- // library, this will override existing value, which is why
- // we loop in a specific library order.
- tempMap.putAll(libEntry.getValue());
- }
- }
- }
- }
- }
- }
-
- // now the project resources themselves.
- Map<ResourceType, Map<String, ResourceValue>> thisProjectMap =
- doGetConfiguredResources(referenceConfig);
-
- // now merge the maps.
- for (Entry<ResourceType, Map<String, ResourceValue>> entry : thisProjectMap.entrySet()) {
- ResourceType type = entry.getKey();
- Map<String, ResourceValue> typeMap = resultMap.get(type);
- if (typeMap == null) {
- resultMap.put(type, entry.getValue());
- } else {
- typeMap.putAll(entry.getValue());
- }
- }
-
- return resultMap;
- }
-
- /**
- * Returns the {@link ResourceFolder} associated with a {@link IFolder}.
- * @param folder The {@link IFolder} object.
- * @return the {@link ResourceFolder} or null if it was not found.
- *
- * @see ResourceRepository#getResourceFolder(com.android.io.IAbstractFolder)
- */
- public ResourceFolder getResourceFolder(IFolder folder) {
- return getResourceFolder(new IFolderWrapper(folder));
- }
-
- /**
- * Resolves a compiled resource id into the resource name and type
- * @param id the resource integer id.
- * @return a {@link Pair} of 2 strings { name, type } or null if the id could not be resolved
- */
- public Pair<ResourceType, String> resolveResourceId(int id) {
- Pair<ResourceType, String> result = null;
- if (mResIdValueToNameMap != null) {
- result = mResIdValueToNameMap.get(id);
- }
-
- if (result == null) {
- synchronized (mDynamicIdMap) {
- result = mDynamicIdMap.resolveId(id);
- }
- }
-
- return result;
- }
-
- /**
- * Resolves a compiled styleable id of type int[] into the styleable name.
- */
- public String resolveStyleable(int[] id) {
- if (mStyleableValueToNameMap != null) {
- mWrapper.set(id);
- return mStyleableValueToNameMap.get(mWrapper);
- }
-
- return null;
- }
-
- /**
- * Returns the integer id of a resource given its type and name.
- * <p/>If the resource is of type {@link ResourceType#ID} and does not exist in the
- * internal map, then new id values are dynamically generated (and stored so that queries
- * with the same names will return the same value).
- */
- public Integer getResourceId(ResourceType type, String name) {
- Integer result = null;
- if (mResourceValueMap != null) {
- Map<String, Integer> map = mResourceValueMap.get(type);
- if (map != null) {
- result = map.get(name);
- }
- }
-
- if (result == null) {
- synchronized (mDynamicIdMap) {
- result = mDynamicIdMap.getId(type, name);
- }
- }
-
- return result;
- }
-
- /**
- * Resets the list of dynamic Ids. This list is used by
- * {@link #getResourceId(String, String)} when the resource query is an ID that doesn't
- * exist (for example for ID automatically generated in layout files that are not saved yet.)
- * <p/>This method resets those dynamic ID and must be called whenever the actual list of IDs
- * change.
- */
- public void resetDynamicIds() {
- synchronized (mDynamicIdMap) {
- mDynamicIdMap.reset(DYNAMIC_ID_SEED_START);
- }
- }
-
- @Override
- @NonNull
- protected ResourceItem createResourceItem(@NonNull String name) {
- return new ResourceItem(name);
- }
-
- /**
- * Sets compiled resource information.
- *
- * @param resIdValueToNameMap a map of compiled resource id to resource name.
- * The map is acquired by the {@link ProjectResources} object.
- * @param styleableValueMap a map of (int[], name) for the styleable information. The map is
- * acquired by the {@link ProjectResources} object.
- * @param resourceValueMap a map of (name, id) for resources of type {@link ResourceType#ID}.
- * The list is acquired by the {@link ProjectResources} object.
- */
- void setCompiledResources(Map<Integer, Pair<ResourceType, String>> resIdValueToNameMap,
- Map<IntArrayWrapper, String> styleableValueMap,
- Map<ResourceType, Map<String, Integer>> resourceValueMap) {
- mResourceValueMap = resourceValueMap;
- mResIdValueToNameMap = resIdValueToNameMap;
- mStyleableValueToNameMap = styleableValueMap;
-
- resetDynamicIds();
- }
-}
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;
- }
-}