Lines 11-16
Link Here
|
11 |
package org.eclipse.core.internal.resources; |
11 |
package org.eclipse.core.internal.resources; |
12 |
|
12 |
|
13 |
import java.io.*; |
13 |
import java.io.*; |
|
|
14 |
import org.eclipse.core.internal.events.ILifecycleListener; |
15 |
import org.eclipse.core.internal.events.LifecycleEvent; |
14 |
import org.eclipse.core.internal.utils.*; |
16 |
import org.eclipse.core.internal.utils.*; |
15 |
import org.eclipse.core.internal.watson.*; |
17 |
import org.eclipse.core.internal.watson.*; |
16 |
import org.eclipse.core.resources.*; |
18 |
import org.eclipse.core.resources.*; |
Lines 18-24
Link Here
|
18 |
import org.eclipse.core.runtime.content.*; |
20 |
import org.eclipse.core.runtime.content.*; |
19 |
import org.eclipse.core.runtime.content.IContentTypeManager.ContentTypeChangeEvent; |
21 |
import org.eclipse.core.runtime.content.IContentTypeManager.ContentTypeChangeEvent; |
20 |
import org.eclipse.core.runtime.jobs.ISchedulingRule; |
22 |
import org.eclipse.core.runtime.jobs.ISchedulingRule; |
21 |
import org.eclipse.core.runtime.jobs.Job; |
|
|
22 |
import org.eclipse.osgi.util.NLS; |
23 |
import org.eclipse.osgi.util.NLS; |
23 |
|
24 |
|
24 |
/** |
25 |
/** |
Lines 27-39
Link Here
|
27 |
* @since 3.0 |
28 |
* @since 3.0 |
28 |
* @see IFile#getContentDescription() |
29 |
* @see IFile#getContentDescription() |
29 |
*/ |
30 |
*/ |
30 |
public class ContentDescriptionManager implements IManager, IRegistryChangeListener, IContentTypeManager.IContentTypeChangeListener { |
31 |
public class ContentDescriptionManager implements IManager, IRegistryChangeListener, IContentTypeManager.IContentTypeChangeListener, ILifecycleListener { |
31 |
|
|
|
32 |
/** |
32 |
/** |
33 |
* This job causes the content description cache and the related flags |
33 |
* This job causes the content description cache and the related flags |
34 |
* in the resource tree to be flushed. |
34 |
* in the resource tree to be flushed. |
35 |
*/ |
35 |
*/ |
36 |
private class FlushJob extends WorkspaceJob { |
36 |
private class FlushJob extends WorkspaceJob { |
|
|
37 |
private Queue toFlush; |
38 |
private boolean fullFlush; |
37 |
|
39 |
|
38 |
public FlushJob() { |
40 |
public FlushJob() { |
39 |
super(Messages.resources_flushingContentDescriptionCache); |
41 |
super(Messages.resources_flushingContentDescriptionCache); |
Lines 41-46
Link Here
|
41 |
setUser(false); |
43 |
setUser(false); |
42 |
setPriority(LONG); |
44 |
setPriority(LONG); |
43 |
setRule(workspace.getRoot()); |
45 |
setRule(workspace.getRoot()); |
|
|
46 |
toFlush = new Queue(); |
44 |
} |
47 |
} |
45 |
|
48 |
|
46 |
/* (non-Javadoc) |
49 |
/* (non-Javadoc) |
Lines 64-70
Link Here
|
64 |
try { |
67 |
try { |
65 |
workspace.prepareOperation(rule, monitor); |
68 |
workspace.prepareOperation(rule, monitor); |
66 |
workspace.beginOperation(true); |
69 |
workspace.beginOperation(true); |
67 |
doFlushCache(monitor); |
70 |
doFlushCache(monitor, getPathsToFlush()); |
68 |
} finally { |
71 |
} finally { |
69 |
workspace.endOperation(rule, false, Policy.subMonitorFor(monitor, Policy.endOpWork)); |
72 |
workspace.endOperation(rule, false, Policy.subMonitorFor(monitor, Policy.endOpWork)); |
70 |
} |
73 |
} |
Lines 77-82
Link Here
|
77 |
} |
80 |
} |
78 |
return Status.OK_STATUS; |
81 |
return Status.OK_STATUS; |
79 |
} |
82 |
} |
|
|
83 |
|
84 |
private IPath[] getPathsToFlush() { |
85 |
synchronized (toFlush) { |
86 |
if (fullFlush) |
87 |
return null; |
88 |
int size = toFlush.size(); |
89 |
return (size == 0) ? null : (IPath[]) toFlush.copyTo(new IPath[size]); |
90 |
} |
91 |
} |
92 |
|
93 |
/** |
94 |
* @param project project to flush, or null for a full flush |
95 |
*/ |
96 |
void flush(IProject project) { |
97 |
synchronized (toFlush) { |
98 |
if (!fullFlush) |
99 |
if (project != null) { |
100 |
fullFlush = true; |
101 |
toFlush.clear(); |
102 |
} else |
103 |
toFlush.add(project.getFullPath()); |
104 |
} |
105 |
schedule(1000); |
106 |
} |
107 |
|
80 |
} |
108 |
} |
81 |
|
109 |
|
82 |
/** |
110 |
/** |
Lines 144-150
Link Here
|
144 |
|
172 |
|
145 |
private byte cacheState; |
173 |
private byte cacheState; |
146 |
|
174 |
|
147 |
private Job flushJob; |
175 |
private FlushJob flushJob; |
|
|
176 |
private ProjectContentTypes projectContentTypes; |
148 |
|
177 |
|
149 |
Workspace workspace; |
178 |
Workspace workspace; |
150 |
|
179 |
|
Lines 152-167
Link Here
|
152 |
* @see IContentTypeManager.IContentTypeChangeListener#contentTypeChanged(ContentTypeChangeEvent) |
181 |
* @see IContentTypeManager.IContentTypeChangeListener#contentTypeChanged(ContentTypeChangeEvent) |
153 |
*/ |
182 |
*/ |
154 |
public void contentTypeChanged(ContentTypeChangeEvent event) { |
183 |
public void contentTypeChanged(ContentTypeChangeEvent event) { |
155 |
invalidateCache(true); |
184 |
invalidateCache(true, null); |
156 |
} |
185 |
} |
157 |
|
186 |
|
158 |
synchronized void doFlushCache(final IProgressMonitor monitor) throws CoreException { |
187 |
synchronized void doFlushCache(final IProgressMonitor monitor, IPath[] toClean) throws CoreException { |
159 |
// nothing to be done if no information cached |
188 |
// nothing to be done if no information cached |
160 |
if (getCacheState() == EMPTY_CACHE) |
189 |
if (getCacheState() != INVALID_CACHE) |
161 |
return; |
190 |
return; |
162 |
setCacheState(FLUSHING_CACHE); |
191 |
try { |
163 |
// flush the MRU cache |
192 |
setCacheState(FLUSHING_CACHE); |
164 |
cache.discardAll(); |
193 |
// flush the MRU cache |
|
|
194 |
cache.discardAll(); |
195 |
if (toClean == null || toClean.length == 0) |
196 |
// no project was added, must be a global flush |
197 |
clearContentFlags(Path.ROOT, monitor); |
198 |
else { |
199 |
// flush a project at a time |
200 |
MultiStatus result = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, Messages.resources_errorFlushingContentDescriptionCache, null); |
201 |
for (int i = 0; i < toClean.length; i++) |
202 |
try { |
203 |
clearContentFlags(toClean[i], monitor); |
204 |
} catch (CoreException ce) { |
205 |
result.add(ce.getStatus()); |
206 |
} |
207 |
if (!result.isOK()) |
208 |
throw new CoreException(result); |
209 |
} |
210 |
} catch (CoreException ce) { |
211 |
setCacheState(INVALID_CACHE); |
212 |
throw ce; |
213 |
} |
214 |
// done cleaning (only if we didn't fail) |
215 |
setCacheState(EMPTY_CACHE); |
216 |
} |
217 |
|
218 |
/** |
219 |
* Clears the content related flags for every file under the given root. |
220 |
*/ |
221 |
private void clearContentFlags(IPath root, final IProgressMonitor monitor) throws CoreException { |
165 |
// discard content type related flags for all files in the tree |
222 |
// discard content type related flags for all files in the tree |
166 |
IElementContentVisitor visitor = new IElementContentVisitor() { |
223 |
IElementContentVisitor visitor = new IElementContentVisitor() { |
167 |
public boolean visitElement(ElementTree tree, IPathRequestor requestor, Object elementContents) { |
224 |
public boolean visitElement(ElementTree tree, IPathRequestor requestor, Object elementContents) { |
Lines 180-191
Link Here
|
180 |
} |
237 |
} |
181 |
}; |
238 |
}; |
182 |
try { |
239 |
try { |
183 |
new ElementTreeIterator(workspace.getElementTree(), Path.ROOT).iterate(visitor); |
240 |
new ElementTreeIterator(workspace.getElementTree(), root).iterate(visitor); |
184 |
} catch (WrappedRuntimeException e) { |
241 |
} catch (WrappedRuntimeException e) { |
185 |
throw (CoreException) e.getTargetException(); |
242 |
throw (CoreException) e.getTargetException(); |
186 |
} |
243 |
} |
187 |
// done cleaning |
|
|
188 |
setCacheState(EMPTY_CACHE); |
189 |
} |
244 |
} |
190 |
|
245 |
|
191 |
Cache getCache() { |
246 |
Cache getCache() { |
Lines 288-294
Link Here
|
288 |
return Platform.getPlatformAdmin().getState(false).getTimeStamp(); |
343 |
return Platform.getPlatformAdmin().getState(false).getTimeStamp(); |
289 |
} |
344 |
} |
290 |
|
345 |
|
291 |
public synchronized void invalidateCache(boolean flush) { |
346 |
/** |
|
|
347 |
* Marks the cache as invalid. Does not do anything if the cache is new. |
348 |
* Optionally causes the cached information to be actually flushed. |
349 |
* |
350 |
* @param flush whether the cached information should be flushed |
351 |
* @see #doFlushCache(IProgressMonitor, IPath[]) |
352 |
*/ |
353 |
public synchronized void invalidateCache(boolean flush, IProject project) { |
292 |
if (getCacheState() == EMPTY_CACHE) |
354 |
if (getCacheState() == EMPTY_CACHE) |
293 |
// cache has not been touched, nothing to do |
355 |
// cache has not been touched, nothing to do |
294 |
return; |
356 |
return; |
Lines 298-306
Link Here
|
298 |
} catch (CoreException e) { |
360 |
} catch (CoreException e) { |
299 |
ResourcesPlugin.getPlugin().getLog().log(e.getStatus()); |
361 |
ResourcesPlugin.getPlugin().getLog().log(e.getStatus()); |
300 |
} |
362 |
} |
301 |
if (!flush) |
363 |
if (flush) |
302 |
return; |
364 |
flushJob.flush(project); |
303 |
flushJob.schedule(1000); |
|
|
304 |
} |
365 |
} |
305 |
|
366 |
|
306 |
/** |
367 |
/** |
Lines 310-317
Link Here
|
310 |
// tries to obtain a description for this file contents |
371 |
// tries to obtain a description for this file contents |
311 |
InputStream contents = new LazyFileInputStream(file.getLocation()); |
372 |
InputStream contents = new LazyFileInputStream(file.getLocation()); |
312 |
try { |
373 |
try { |
313 |
IContentTypeManager contentTypeManager = Platform.getContentTypeManager(); |
374 |
IContentTypeMatcher matcher = projectContentTypes.getMatcherFor((Project) file.getProject()); |
314 |
return contentTypeManager.getDescriptionFor(contents, file.getName(), IContentDescription.ALL); |
375 |
return matcher.getDescriptionFor(contents, file.getName(), IContentDescription.ALL); |
315 |
} catch (IOException e) { |
376 |
} catch (IOException e) { |
316 |
String message = NLS.bind(Messages.resources_errorContentDescription, file.getFullPath()); |
377 |
String message = NLS.bind(Messages.resources_errorContentDescription, file.getFullPath()); |
317 |
throw new ResourceException(IResourceStatus.FAILED_DESCRIBING_CONTENTS, file.getFullPath(), message, e); |
378 |
throw new ResourceException(IResourceStatus.FAILED_DESCRIBING_CONTENTS, file.getFullPath(), message, e); |
Lines 327-333
Link Here
|
327 |
// no changes related to the content type registry |
388 |
// no changes related to the content type registry |
328 |
if (event.getExtensionDeltas(Platform.PI_RUNTIME, PT_CONTENTTYPES).length == 0) |
389 |
if (event.getExtensionDeltas(Platform.PI_RUNTIME, PT_CONTENTTYPES).length == 0) |
329 |
return; |
390 |
return; |
330 |
invalidateCache(true); |
391 |
invalidateCache(true, null); |
|
|
392 |
} |
393 |
|
394 |
/** |
395 |
* @see ILifecycleListener#handleEvent(LifecycleEvent) |
396 |
*/ |
397 |
public void handleEvent(LifecycleEvent event) { |
398 |
//TODO are these the only events we care about? |
399 |
switch (event.kind) { |
400 |
case LifecycleEvent.PRE_PROJECT_CHANGE : |
401 |
case LifecycleEvent.PRE_PROJECT_CLOSE : |
402 |
case LifecycleEvent.PRE_PROJECT_DELETE : |
403 |
case LifecycleEvent.PRE_PROJECT_MOVE : |
404 |
case LifecycleEvent.PRE_PROJECT_OPEN : |
405 |
invalidateCache(true, (IProject) event.resource); |
406 |
} |
331 |
} |
407 |
} |
332 |
|
408 |
|
333 |
synchronized void setCacheState(byte newCacheState) throws CoreException { |
409 |
synchronized void setCacheState(byte newCacheState) throws CoreException { |
Lines 351-368
Link Here
|
351 |
cache = null; |
427 |
cache = null; |
352 |
flushJob.cancel(); |
428 |
flushJob.cancel(); |
353 |
flushJob = null; |
429 |
flushJob = null; |
|
|
430 |
projectContentTypes = null; |
354 |
} |
431 |
} |
355 |
|
432 |
|
356 |
public void startup(IProgressMonitor monitor) throws CoreException { |
433 |
public void startup(IProgressMonitor monitor) throws CoreException { |
357 |
workspace = (Workspace) ResourcesPlugin.getWorkspace(); |
434 |
workspace = (Workspace) ResourcesPlugin.getWorkspace(); |
358 |
cache = new Cache(100, 1000, 0.1); |
435 |
cache = new Cache(100, 1000, 0.1); |
|
|
436 |
projectContentTypes = new ProjectContentTypes(workspace); |
359 |
getCacheState(); |
437 |
getCacheState(); |
360 |
if (cacheState == FLUSHING_CACHE) |
438 |
if (cacheState == FLUSHING_CACHE) |
361 |
// in case we died before completing the last flushing |
439 |
// in case we died before completing the last flushing |
362 |
setCacheState(INVALID_CACHE); |
440 |
setCacheState(INVALID_CACHE); |
363 |
flushJob = new FlushJob(); |
441 |
flushJob = new FlushJob(); |
|
|
442 |
// the cache is stale (plug-ins that might be contributing content types were added/removed) |
364 |
if (getCacheTimestamp() != getPlatformTimeStamp()) |
443 |
if (getCacheTimestamp() != getPlatformTimeStamp()) |
365 |
invalidateCache(false); |
444 |
invalidateCache(false, null); |
|
|
445 |
// register a lifecycle listener |
446 |
workspace.addLifecycleListener(this); |
366 |
// register a content type change listener |
447 |
// register a content type change listener |
367 |
Platform.getContentTypeManager().addContentTypeChangeListener(this); |
448 |
Platform.getContentTypeManager().addContentTypeChangeListener(this); |
368 |
// register a registry change listener |
449 |
// register a registry change listener |