Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 19913 Details for
Bug 69640
[content type] associate content types to natures
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
patch for org.eclipse.core.resources
org.eclipse.core.resources_bug69640.diff (text/plain), 21.57 KB, created by
Rafael Chaves
on 2005-04-14 11:47:10 EDT
(
hide
)
Description:
patch for org.eclipse.core.resources
Filename:
MIME Type:
Creator:
Rafael Chaves
Created:
2005-04-14 11:47:10 EDT
Size:
21.57 KB
patch
obsolete
>Index: src/org/eclipse/core/internal/resources/ContentDescriptionManager.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ContentDescriptionManager.java,v >retrieving revision 1.19 >diff -u -r1.19 ContentDescriptionManager.java >--- src/org/eclipse/core/internal/resources/ContentDescriptionManager.java 21 Feb 2005 23:10:23 -0000 1.19 >+++ src/org/eclipse/core/internal/resources/ContentDescriptionManager.java 14 Apr 2005 15:34:17 -0000 >@@ -11,6 +11,8 @@ > package org.eclipse.core.internal.resources; > > import java.io.*; >+import org.eclipse.core.internal.events.ILifecycleListener; >+import org.eclipse.core.internal.events.LifecycleEvent; > import org.eclipse.core.internal.utils.*; > import org.eclipse.core.internal.watson.*; > import org.eclipse.core.resources.*; >@@ -18,7 +20,6 @@ > import org.eclipse.core.runtime.content.*; > import org.eclipse.core.runtime.content.IContentTypeManager.ContentTypeChangeEvent; > import org.eclipse.core.runtime.jobs.ISchedulingRule; >-import org.eclipse.core.runtime.jobs.Job; > import org.eclipse.osgi.util.NLS; > > /** >@@ -27,13 +28,14 @@ > * @since 3.0 > * @see IFile#getContentDescription() > */ >-public class ContentDescriptionManager implements IManager, IRegistryChangeListener, IContentTypeManager.IContentTypeChangeListener { >- >+public class ContentDescriptionManager implements IManager, IRegistryChangeListener, IContentTypeManager.IContentTypeChangeListener, ILifecycleListener { > /** > * This job causes the content description cache and the related flags > * in the resource tree to be flushed. > */ > private class FlushJob extends WorkspaceJob { >+ private Queue toFlush; >+ private boolean fullFlush; > > public FlushJob() { > super(Messages.resources_flushingContentDescriptionCache); >@@ -41,6 +43,7 @@ > setUser(false); > setPriority(LONG); > setRule(workspace.getRoot()); >+ toFlush = new Queue(); > } > > /* (non-Javadoc) >@@ -64,7 +67,7 @@ > try { > workspace.prepareOperation(rule, monitor); > workspace.beginOperation(true); >- doFlushCache(monitor); >+ doFlushCache(monitor, getPathsToFlush()); > } finally { > workspace.endOperation(rule, false, Policy.subMonitorFor(monitor, Policy.endOpWork)); > } >@@ -77,6 +80,31 @@ > } > return Status.OK_STATUS; > } >+ >+ private IPath[] getPathsToFlush() { >+ synchronized (toFlush) { >+ if (fullFlush) >+ return null; >+ int size = toFlush.size(); >+ return (size == 0) ? null : (IPath[]) toFlush.copyTo(new IPath[size]); >+ } >+ } >+ >+ /** >+ * @param project project to flush, or null for a full flush >+ */ >+ void flush(IProject project) { >+ synchronized (toFlush) { >+ if (!fullFlush) >+ if (project != null) { >+ fullFlush = true; >+ toFlush.clear(); >+ } else >+ toFlush.add(project.getFullPath()); >+ } >+ schedule(1000); >+ } >+ > } > > /** >@@ -144,7 +172,8 @@ > > private byte cacheState; > >- private Job flushJob; >+ private FlushJob flushJob; >+ private ProjectContentTypes projectContentTypes; > > Workspace workspace; > >@@ -152,16 +181,44 @@ > * @see IContentTypeManager.IContentTypeChangeListener#contentTypeChanged(ContentTypeChangeEvent) > */ > public void contentTypeChanged(ContentTypeChangeEvent event) { >- invalidateCache(true); >+ invalidateCache(true, null); > } > >- synchronized void doFlushCache(final IProgressMonitor monitor) throws CoreException { >+ synchronized void doFlushCache(final IProgressMonitor monitor, IPath[] toClean) throws CoreException { > // nothing to be done if no information cached >- if (getCacheState() == EMPTY_CACHE) >+ if (getCacheState() != INVALID_CACHE) > return; >- setCacheState(FLUSHING_CACHE); >- // flush the MRU cache >- cache.discardAll(); >+ try { >+ setCacheState(FLUSHING_CACHE); >+ // flush the MRU cache >+ cache.discardAll(); >+ if (toClean == null || toClean.length == 0) >+ // no project was added, must be a global flush >+ clearContentFlags(Path.ROOT, monitor); >+ else { >+ // flush a project at a time >+ MultiStatus result = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, Messages.resources_errorFlushingContentDescriptionCache, null); >+ for (int i = 0; i < toClean.length; i++) >+ try { >+ clearContentFlags(toClean[i], monitor); >+ } catch (CoreException ce) { >+ result.add(ce.getStatus()); >+ } >+ if (!result.isOK()) >+ throw new CoreException(result); >+ } >+ } catch (CoreException ce) { >+ setCacheState(INVALID_CACHE); >+ throw ce; >+ } >+ // done cleaning (only if we didn't fail) >+ setCacheState(EMPTY_CACHE); >+ } >+ >+ /** >+ * Clears the content related flags for every file under the given root. >+ */ >+ private void clearContentFlags(IPath root, final IProgressMonitor monitor) throws CoreException { > // discard content type related flags for all files in the tree > IElementContentVisitor visitor = new IElementContentVisitor() { > public boolean visitElement(ElementTree tree, IPathRequestor requestor, Object elementContents) { >@@ -180,12 +237,10 @@ > } > }; > try { >- new ElementTreeIterator(workspace.getElementTree(), Path.ROOT).iterate(visitor); >+ new ElementTreeIterator(workspace.getElementTree(), root).iterate(visitor); > } catch (WrappedRuntimeException e) { > throw (CoreException) e.getTargetException(); > } >- // done cleaning >- setCacheState(EMPTY_CACHE); > } > > Cache getCache() { >@@ -288,7 +343,14 @@ > return Platform.getPlatformAdmin().getState(false).getTimeStamp(); > } > >- public synchronized void invalidateCache(boolean flush) { >+ /** >+ * Marks the cache as invalid. Does not do anything if the cache is new. >+ * Optionally causes the cached information to be actually flushed. >+ * >+ * @param flush whether the cached information should be flushed >+ * @see #doFlushCache(IProgressMonitor, IPath[]) >+ */ >+ public synchronized void invalidateCache(boolean flush, IProject project) { > if (getCacheState() == EMPTY_CACHE) > // cache has not been touched, nothing to do > return; >@@ -298,9 +360,8 @@ > } catch (CoreException e) { > ResourcesPlugin.getPlugin().getLog().log(e.getStatus()); > } >- if (!flush) >- return; >- flushJob.schedule(1000); >+ if (flush) >+ flushJob.flush(project); > } > > /** >@@ -310,8 +371,8 @@ > // tries to obtain a description for this file contents > InputStream contents = new LazyFileInputStream(file.getLocation()); > try { >- IContentTypeManager contentTypeManager = Platform.getContentTypeManager(); >- return contentTypeManager.getDescriptionFor(contents, file.getName(), IContentDescription.ALL); >+ IContentTypeMatcher matcher = projectContentTypes.getMatcherFor((Project) file.getProject()); >+ return matcher.getDescriptionFor(contents, file.getName(), IContentDescription.ALL); > } catch (IOException e) { > String message = NLS.bind(Messages.resources_errorContentDescription, file.getFullPath()); > throw new ResourceException(IResourceStatus.FAILED_DESCRIBING_CONTENTS, file.getFullPath(), message, e); >@@ -327,7 +388,22 @@ > // no changes related to the content type registry > if (event.getExtensionDeltas(Platform.PI_RUNTIME, PT_CONTENTTYPES).length == 0) > return; >- invalidateCache(true); >+ invalidateCache(true, null); >+ } >+ >+ /** >+ * @see ILifecycleListener#handleEvent(LifecycleEvent) >+ */ >+ public void handleEvent(LifecycleEvent event) { >+ //TODO are these the only events we care about? >+ switch (event.kind) { >+ case LifecycleEvent.PRE_PROJECT_CHANGE : >+ case LifecycleEvent.PRE_PROJECT_CLOSE : >+ case LifecycleEvent.PRE_PROJECT_DELETE : >+ case LifecycleEvent.PRE_PROJECT_MOVE : >+ case LifecycleEvent.PRE_PROJECT_OPEN : >+ invalidateCache(true, (IProject) event.resource); >+ } > } > > synchronized void setCacheState(byte newCacheState) throws CoreException { >@@ -351,18 +427,23 @@ > cache = null; > flushJob.cancel(); > flushJob = null; >+ projectContentTypes = null; > } > > public void startup(IProgressMonitor monitor) throws CoreException { > workspace = (Workspace) ResourcesPlugin.getWorkspace(); > cache = new Cache(100, 1000, 0.1); >+ projectContentTypes = new ProjectContentTypes(workspace); > getCacheState(); > if (cacheState == FLUSHING_CACHE) > // in case we died before completing the last flushing > setCacheState(INVALID_CACHE); > flushJob = new FlushJob(); >+ // the cache is stale (plug-ins that might be contributing content types were added/removed) > if (getCacheTimestamp() != getPlatformTimeStamp()) >- invalidateCache(false); >+ invalidateCache(false, null); >+ // register a lifecycle listener >+ workspace.addLifecycleListener(this); > // register a content type change listener > Platform.getContentTypeManager().addContentTypeChangeListener(this); > // register a registry change listener >Index: src/org/eclipse/core/internal/resources/NatureManager.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/NatureManager.java,v >retrieving revision 1.23 >diff -u -r1.23 NatureManager.java >--- src/org/eclipse/core/internal/resources/NatureManager.java 21 Feb 2005 23:10:23 -0000 1.23 >+++ src/org/eclipse/core/internal/resources/NatureManager.java 14 Apr 2005 15:34:17 -0000 >@@ -322,10 +322,16 @@ > * Returns the cached array of enabled natures for this project, > * or null if there is nothing in the cache. > */ >- protected String[] getEnabledNatures(IProject project) { >- if (natureEnablements != null) >- return (String[]) natureEnablements.get(project); >- return null; >+ protected String[] getEnabledNatures(Project project) { >+ String[] enabled; >+ if (natureEnablements != null) { >+ enabled = (String[]) natureEnablements.get(project); >+ if (enabled != null) >+ return enabled; >+ } >+ enabled = computeNatureEnablements(project); >+ setEnabledNatures(project, enabled); >+ return enabled; > } > > /** >@@ -425,10 +431,6 @@ > */ > public boolean isNatureEnabled(Project project, String id) { > String[] enabled = getEnabledNatures(project); >- if (enabled == null) { >- enabled = computeNatureEnablements(project); >- setEnabledNatures(project, enabled); >- } > for (int i = 0; i < enabled.length; i++) { > if (enabled[i].equals(id)) > return true; >Index: src/org/eclipse/core/internal/resources/ProjectNatureDescriptor.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ProjectNatureDescriptor.java,v >retrieving revision 1.13 >diff -u -r1.13 ProjectNatureDescriptor.java >--- src/org/eclipse/core/internal/resources/ProjectNatureDescriptor.java 21 Feb 2005 23:10:23 -0000 1.13 >+++ src/org/eclipse/core/internal/resources/ProjectNatureDescriptor.java 14 Apr 2005 15:34:18 -0000 >@@ -25,6 +25,7 @@ > protected String[] requiredNatures; > protected String[] natureSets; > protected String[] builderIds; >+ protected String[] contentTypeIds; > protected boolean allowLinking = true; > > //descriptors that are in a dependency cycle are never valid >@@ -57,6 +58,14 @@ > } > > /** >+ * Returns the IDs of the content types this nature declares to >+ * have affinity with. These content types do not necessarily exist in the registry. >+ */ >+ public String[] getContentTypeIds() { >+ return contentTypeIds; >+ } >+ >+ /** > * @see IProjectNatureDescriptor#getNatureId() > */ > public String getNatureId() { >@@ -106,6 +115,7 @@ > ArrayList requiredList = new ArrayList(count); > ArrayList setList = new ArrayList(count); > ArrayList builderList = new ArrayList(count); >+ ArrayList contentTypeList = new ArrayList(count); > for (int i = 0; i < count; i++) { > IConfigurationElement element = elements[i]; > String name = element.getName(); >@@ -124,6 +134,11 @@ > if (attribute == null) > fail(); > builderList.add(attribute); >+ } else if (name.equalsIgnoreCase("content-type")) { //$NON-NLS-1$ >+ String attribute = element.getAttribute("id"); //$NON-NLS-1$ >+ if (attribute == null) >+ fail(); >+ contentTypeList.add(attribute); > } else if (name.equalsIgnoreCase("options")) { //$NON-NLS-1$ > String attribute = element.getAttribute("allowLinking"); //$NON-NLS-1$ > //when in doubt (missing attribute, wrong value) default to allow linking >@@ -133,6 +148,7 @@ > requiredNatures = (String[]) requiredList.toArray(new String[requiredList.size()]); > natureSets = (String[]) setList.toArray(new String[setList.size()]); > builderIds = (String[]) builderList.toArray(new String[builderList.size()]); >+ contentTypeIds = (String[]) contentTypeList.toArray(new String[contentTypeList.size()]); > } > > /** >Index: src/org/eclipse/core/internal/utils/Messages.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/utils/Messages.java,v >retrieving revision 1.18 >diff -u -r1.18 Messages.java >--- src/org/eclipse/core/internal/utils/Messages.java 23 Feb 2005 20:08:21 -0000 1.18 >+++ src/org/eclipse/core/internal/utils/Messages.java 14 Apr 2005 15:34:18 -0000 >@@ -156,6 +156,7 @@ > public static String resources_destNotNull; > public static String resources_errorContentDescription; > public static String resources_errorDeleting; >+ public static String resources_errorFlushingContentDescriptionCache; > public static String resources_errorMarkersDelete; > public static String resources_errorMarkersMove; > public static String resources_errorMembers; >Index: src/org/eclipse/core/internal/utils/Queue.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/utils/Queue.java,v >retrieving revision 1.10 >diff -u -r1.10 Queue.java >--- src/org/eclipse/core/internal/utils/Queue.java 18 Mar 2005 17:27:48 -0000 1.10 >+++ src/org/eclipse/core/internal/utils/Queue.java 14 Apr 2005 15:34:18 -0000 >@@ -61,6 +61,23 @@ > } > tail = head = 0; > } >+ >+ /** >+ * Copies all elements to the given array. Returns the same array as >+ * convenience. >+ */ >+ public Object[] copyTo(Object[] newElements) { >+ if (head <= tail) { >+ // trivial case >+ System.arraycopy(elements, head, newElements, 0, newElements.length); >+ return newElements; >+ } >+ // queue wrapped array - has to reassemble segments >+ int end = (elements.length - head); >+ System.arraycopy(elements, head, newElements, 0, end); >+ System.arraycopy(elements, 0, newElements, end, tail); >+ return newElements; >+ } > > /** > * This method does not affect the queue itself. It is only a >Index: src/org/eclipse/core/internal/utils/messages.properties >=================================================================== >RCS file: /home/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/utils/messages.properties,v >retrieving revision 1.107 >diff -u -r1.107 messages.properties >--- src/org/eclipse/core/internal/utils/messages.properties 23 Feb 2005 20:08:20 -0000 1.107 >+++ src/org/eclipse/core/internal/utils/messages.properties 14 Apr 2005 15:34:18 -0000 >@@ -112,6 +112,7 @@ > resources_destNotNull = Destination path should not be null. > resources_errorContentDescription = Error retrieving content description for resource: {0}. > resources_errorDeleting = Error deleting resource {0} from the workspace tree. >+resources_errorFlushingContentDescriptionCache = Errors occurred while flushing content description cache. > resources_errorMarkersDelete = Error deleting markers for resource: {0}. > resources_errorMarkersMove = Error moving markers from resource: {0} to: {1}. > resources_errorMembers = Error retrieving members of container: {0}. >Index: src/org/eclipse/core/internal/resources/ProjectContentTypes.java >=================================================================== >RCS file: src/org/eclipse/core/internal/resources/ProjectContentTypes.java >diff -N src/org/eclipse/core/internal/resources/ProjectContentTypes.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/internal/resources/ProjectContentTypes.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,141 @@ >+/******************************************************************************* >+ * Copyright (c) 2005 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Common Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/cpl-v10.html >+ * >+ * Contributors: >+ * IBM Corporation - initial API and implementation >+ *******************************************************************************/ >+package org.eclipse.core.internal.resources; >+ >+import java.util.*; >+import org.eclipse.core.internal.utils.Cache; >+import org.eclipse.core.resources.ResourcesPlugin; >+import org.eclipse.core.runtime.*; >+import org.eclipse.core.runtime.content.IContentType; >+import org.eclipse.core.runtime.content.IContentTypeMatcher; >+import org.eclipse.core.runtime.content.IContentTypeManager.ISelectionPolicy; >+ >+/** >+ * Manages project-specific content type behavior. >+ * >+ * @see ContentDescriptionManager >+ * @see ISelectionPolicy >+ * @since 3.1 >+ */ >+public class ProjectContentTypes { >+ >+ /** >+ * A project-aware content type selection policy. >+ */ >+ private class ProjectContentTypeSelectionPolicy implements ISelectionPolicy { >+ >+ private Project project; >+ >+ public ProjectContentTypeSelectionPolicy(Project project) { >+ this.project = project; >+ } >+ >+ public IContentType[] select(IContentType[] candidates, boolean fileName, boolean content) { >+ return ProjectContentTypes.this.select(project, candidates, fileName, content); >+ } >+ >+ } >+ >+ private static final QualifiedName MATCHER_PROPERTY = new QualifiedName(ResourcesPlugin.PI_RESOURCES, "contentTypeMatcher"); //$NON-NLS-1$ >+ private Cache contentTypesPerProject; >+ private Workspace workspace; >+ >+ private static void swap(Object[] array, int i1, int i2) { >+ Object temp = array[i1]; >+ array[i1] = array[i2]; >+ array[i2] = temp; >+ } >+ >+ public ProjectContentTypes(Workspace workspace) { >+ this.workspace = workspace; >+ // keep cache small >+ this.contentTypesPerProject = new Cache(5, 30, 0.4); >+ } >+ >+ private Set getAssociatedContentTypes(Project project) { >+ final ResourceInfo info = project.getResourceInfo(false, false); >+ final String projectName = project.getName(); >+ synchronized (contentTypesPerProject) { >+ Cache.Entry entry = contentTypesPerProject.getEntry(projectName); >+ if (entry != null) >+ // we have an entry... >+ if (info != null && entry.getTimestamp() == info.getContentId()) >+ // ...and it is not stale, so just return it >+ return (Set) entry.getCached(); >+ // no cached information found, have to collect associated content types >+ Set result = collectAssociatedContentTypes(project); >+ if (entry == null) >+ // there was no entry before - create one >+ entry = contentTypesPerProject.addEntry(projectName, result, info.getContentId()); >+ else { >+ // just update the existing entry >+ entry.setTimestamp(info.getContentId()); >+ entry.setCached(result); >+ } >+ return result; >+ } >+ } >+ >+ IContentTypeMatcher getMatcherFor(Project project) throws CoreException { >+ //TODO is ProjectInfo a better place to keep the content type matcher? >+ IContentTypeMatcher matcher = (IContentTypeMatcher) project.getSessionProperty(MATCHER_PROPERTY); >+ if (matcher != null) >+ return matcher; >+ matcher = Platform.getContentTypeManager().getMatcher(new ProjectContentTypeSelectionPolicy(project), null); >+ project.setSessionProperty(MATCHER_PROPERTY, matcher); >+ return matcher; >+ } >+ >+ /** >+ * Collect content types associated to the natures configured for the given project. >+ */ >+ private Set collectAssociatedContentTypes(Project project) { >+ String[] enabledNatures = workspace.getNatureManager().getEnabledNatures(project); >+ if (enabledNatures.length == 0) >+ return Collections.EMPTY_SET; >+ Set related = new HashSet(enabledNatures.length); >+ for (int i = 0; i < enabledNatures.length; i++) { >+ ProjectNatureDescriptor descriptor = (ProjectNatureDescriptor) workspace.getNatureDescriptor(enabledNatures[i]); >+ if (descriptor == null) >+ // no descriptor found for the nature, skip it >+ continue; >+ String[] natureContentTypes = descriptor.getContentTypeIds(); >+ for (int j = 0; j < natureContentTypes.length; j++) >+ // collect associate content types >+ related.add(natureContentTypes[j]); >+ } >+ return related; >+ } >+ >+ /** >+ * Implements project specific, nature-based selection policy. No content types are vetoed. >+ * >+ * @see ISelectionPolicy >+ */ >+ final IContentType[] select(Project project, IContentType[] candidates, boolean fileName, boolean content) { >+ // since no vetoing is done here, don't go further if there is nothing to sort >+ if (candidates.length < 2) >+ return candidates; >+ final Set associated = getAssociatedContentTypes(project); >+ if (associated == null || associated.isEmpty()) >+ // project has no content types associated >+ return candidates; >+ // put content types that appear in related natures before those who don't >+ int relatedCount = 0; >+ for (int i = 0; i < candidates.length; i++) >+ if (associated.contains(candidates[i].getId())) { >+ if (relatedCount < i) >+ swap(candidates, i, relatedCount); >+ relatedCount++; >+ } >+ return candidates; >+ } >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 69640
: 19913 |
19915