Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 307587 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/core/internal/resources/NatureManager.java (-44 / +54 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2007 IBM Corporation and others.
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 25-38 Link Here
25
 */
25
 */
26
public class NatureManager implements ILifecycleListener, IManager {
26
public class NatureManager implements ILifecycleListener, IManager {
27
	//maps String (nature ID) -> descriptor objects
27
	//maps String (nature ID) -> descriptor objects
28
	protected Map descriptors;
28
	private Map descriptors;
29
29
30
	//maps IProject -> String[] of enabled natures for that project
30
	//maps IProject -> String[] of enabled natures for that project
31
	protected Map natureEnablements;
31
	private Map natureEnablements;
32
32
33
	//maps String (builder ID) -> String (nature ID)
33
	//maps String (builder ID) -> String (nature ID)
34
	protected Map buildersToNatures = null;
34
	private Map buildersToNatures = null;
35
	//colour constants used in cycle detection algorithm
35
	//color constants used in cycle detection algorithm
36
	private static final byte WHITE = 0;
36
	private static final byte WHITE = 0;
37
	private static final byte GREY = 1;
37
	private static final byte GREY = 1;
38
	private static final byte BLACK = 2;
38
	private static final byte BLACK = 2;
Lines 43-52 Link Here
43
43
44
	/**
44
	/**
45
	 * Computes the list of natures that are enabled for the given project.
45
	 * Computes the list of natures that are enabled for the given project.
46
	 * Enablement computation is subtlely different from nature set
46
	 * Enablement computation is subtlety different from nature set
47
	 * validation, because it must find and remove all inconsistencies.
47
	 * validation, because it must find and remove all inconsistencies.
48
	 */
48
	 */
49
	protected String[] computeNatureEnablements(Project project) {
49
	private String[] computeNatureEnablements(Project project) {
50
		final ProjectDescription description = project.internalGetDescription();
50
		final ProjectDescription description = project.internalGetDescription();
51
		if (description == null)
51
		if (description == null)
52
			return new String[0];//project deleted concurrently
52
			return new String[0];//project deleted concurrently
Lines 136-142 Link Here
136
	/**
136
	/**
137
	 * Configures the nature with the given ID for the given project.
137
	 * Configures the nature with the given ID for the given project.
138
	 */
138
	 */
139
	protected void configureNature(final Project project, final String natureID, final MultiStatus errors) {
139
	private void configureNature(final Project project, final String natureID, final MultiStatus errors) {
140
		ISafeRunnable code = new ISafeRunnable() {
140
		ISafeRunnable code = new ISafeRunnable() {
141
			public void run() throws Exception {
141
			public void run() throws Exception {
142
				IProjectNature nature = createNature(project, natureID);
142
				IProjectNature nature = createNature(project, natureID);
Lines 240-246 Link Here
240
	/**
240
	/**
241
	 * Deconfigures the nature with the given ID for the given project.
241
	 * Deconfigures the nature with the given ID for the given project.
242
	 */
242
	 */
243
	protected void deconfigureNature(final Project project, final String natureID, final MultiStatus status) {
243
	private void deconfigureNature(final Project project, final String natureID, final MultiStatus status) {
244
		final ProjectInfo info = (ProjectInfo) project.getResourceInfo(false, true);
244
		final ProjectInfo info = (ProjectInfo) project.getResourceInfo(false, true);
245
		IProjectNature existingNature = info.getNature(natureID);
245
		IProjectNature existingNature = info.getNature(natureID);
246
		if (existingNature == null) {
246
		if (existingNature == null) {
Lines 275-282 Link Here
275
	/**
275
	/**
276
	 * Marks all nature descriptors that are involved in cycles
276
	 * Marks all nature descriptors that are involved in cycles
277
	 */
277
	 */
278
	protected void detectCycles() {
278
	private void detectCycles(Map tempDescriptors) {
279
		Collection values = descriptors.values();
279
		Collection values = tempDescriptors.values();
280
		ProjectNatureDescriptor[] natures = (ProjectNatureDescriptor[]) values.toArray(new ProjectNatureDescriptor[values.size()]);
280
		ProjectNatureDescriptor[] natures = (ProjectNatureDescriptor[]) values.toArray(new ProjectNatureDescriptor[values.size()]);
281
		for (int i = 0; i < natures.length; i++)
281
		for (int i = 0; i < natures.length; i++)
282
			if (natures[i].colour == WHITE)
282
			if (natures[i].colour == WHITE)
Lines 286-292 Link Here
286
	/**
286
	/**
287
	 * Returns a status indicating failure to configure natures.
287
	 * Returns a status indicating failure to configure natures.
288
	 */
288
	 */
289
	protected IStatus failure(String reason) {
289
	private IStatus failure(String reason) {
290
		return new ResourceStatus(IResourceStatus.INVALID_NATURE_SET, reason);
290
		return new ResourceStatus(IResourceStatus.INVALID_NATURE_SET, reason);
291
	}
291
	}
292
292
Lines 296-316 Link Here
296
	 */
296
	 */
297
	public String findNatureForBuilder(String builderID) {
297
	public String findNatureForBuilder(String builderID) {
298
		if (buildersToNatures == null) {
298
		if (buildersToNatures == null) {
299
			buildersToNatures = new HashMap(10);
299
			synchronized (this) {
300
			IProjectNatureDescriptor[] descs = getNatureDescriptors();
300
				if (buildersToNatures == null) {
301
			for (int i = 0; i < descs.length; i++) {
301
					Map tempNatureForBuilders = new HashMap(10);
302
				String natureId = descs[i].getNatureId();
302
					IProjectNatureDescriptor[] descs = getNatureDescriptors();
303
				String[] builders = ((ProjectNatureDescriptor) descs[i]).getBuilderIds();
303
					for (int i = 0; i < descs.length; i++) {
304
				for (int j = 0; j < builders.length; j++) {
304
						String natureId = descs[i].getNatureId();
305
					//FIXME: how to handle multiple natures specifying same builder
305
						String[] builders = ((ProjectNatureDescriptor) descs[i]).getBuilderIds();
306
					buildersToNatures.put(builders[j], natureId);
306
						for (int j = 0; j < builders.length; j++) {
307
							//FIXME: how to handle multiple natures specifying same builder
308
							tempNatureForBuilders.put(builders[j], natureId);
309
						}
310
					}
311
					buildersToNatures = tempNatureForBuilders;
307
				}
312
				}
308
			}
313
			}
309
		}
314
		}
310
		return (String) buildersToNatures.get(builderID);
315
		return (String) buildersToNatures.get(builderID);
311
	}
316
	}
312
317
313
	protected void flushEnablements(IProject project) {
318
	private synchronized void flushEnablements(IProject project) {
314
		if (natureEnablements != null) {
319
		if (natureEnablements != null) {
315
			natureEnablements.remove(project);
320
			natureEnablements.remove(project);
316
			if (natureEnablements.size() == 0) {
321
			if (natureEnablements.size() == 0) {
Lines 323-329 Link Here
323
	 * Returns the cached array of enabled natures for this project,
328
	 * Returns the cached array of enabled natures for this project,
324
	 * or null if there is nothing in the cache.
329
	 * or null if there is nothing in the cache.
325
	 */
330
	 */
326
	protected String[] getEnabledNatures(Project project) {
331
	protected synchronized String[] getEnabledNatures(Project project) {
327
		String[] enabled;
332
		String[] enabled;
328
		if (natureEnablements != null) {
333
		if (natureEnablements != null) {
329
			enabled = (String[]) natureEnablements.get(project);
334
			enabled = (String[]) natureEnablements.get(project);
Lines 340-346 Link Here
340
	 * dependencies starting at root i.  Returns false otherwise.
345
	 * dependencies starting at root i.  Returns false otherwise.
341
	 * Marks all descriptors that are involved in the cycle as invalid.
346
	 * Marks all descriptors that are involved in the cycle as invalid.
342
	 */
347
	 */
343
	protected boolean hasCycles(ProjectNatureDescriptor desc) {
348
	private boolean hasCycles(ProjectNatureDescriptor desc) {
344
		if (desc.colour == BLACK) {
349
		if (desc.colour == BLACK) {
345
			//this subgraph has already been traversed, so we know the answer
350
			//this subgraph has already been traversed, so we know the answer
346
			return desc.hasCycle;
351
			return desc.hasCycle;
Lines 373-379 Link Here
373
	/**
378
	/**
374
	 * Returns true if the given project has linked resources, and false otherwise.
379
	 * Returns true if the given project has linked resources, and false otherwise.
375
	 */
380
	 */
376
	protected boolean hasLinks(IProject project) {
381
	private boolean hasLinks(IProject project) {
377
		try {
382
		try {
378
			IResource[] children = project.members();
383
			IResource[] children = project.members();
379
			for (int i = 0; i < children.length; i++)
384
			for (int i = 0; i < children.length; i++)
Lines 391-397 Link Here
391
	 * memberships.  Returns the name of one such overlap, or null if
396
	 * memberships.  Returns the name of one such overlap, or null if
392
	 * there is no set overlap.
397
	 * there is no set overlap.
393
	 */
398
	 */
394
	protected String hasSetOverlap(IProjectNatureDescriptor one, IProjectNatureDescriptor two) {
399
	private String hasSetOverlap(IProjectNatureDescriptor one, IProjectNatureDescriptor two) {
395
		if (one == null || two == null) {
400
		if (one == null || two == null) {
396
			return null;
401
			return null;
397
		}
402
		}
Lines 411-417 Link Here
411
	/**
416
	/**
412
	 * Perform depth-first insertion of the given nature ID into the result list.
417
	 * Perform depth-first insertion of the given nature ID into the result list.
413
	 */
418
	 */
414
	protected void insert(ArrayList list, Set seen, String id) {
419
	private void insert(ArrayList list, Set seen, String id) {
415
		if (seen.contains(id))
420
		if (seen.contains(id))
416
			return;
421
			return;
417
		seen.add(id);
422
		seen.add(id);
Lines 443-473 Link Here
443
	 * Only initialize the descriptor cache when we know it is actually needed.
448
	 * Only initialize the descriptor cache when we know it is actually needed.
444
	 * Running programs may never need to refer to this cache.
449
	 * Running programs may never need to refer to this cache.
445
	 */
450
	 */
446
	protected void lazyInitialize() {
451
	private void lazyInitialize() {
447
		if (descriptors != null)
452
		if (descriptors != null)
448
			return;
453
			return;
449
		IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PT_NATURES);
454
		synchronized (this) {
450
		IExtension[] extensions = point.getExtensions();
455
			if (descriptors != null)
451
		descriptors = new HashMap(extensions.length * 2 + 1);
456
				return;
452
		for (int i = 0, imax = extensions.length; i < imax; i++) {
457
			IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PT_NATURES);
453
			IProjectNatureDescriptor desc = null;
458
			IExtension[] extensions = point.getExtensions();
454
			try {
459
			Map tempDescriptors = new HashMap(extensions.length * 2 + 1);
455
				desc = new ProjectNatureDescriptor(extensions[i]);
460
			for (int i = 0, imax = extensions.length; i < imax; i++) {
456
			} catch (CoreException e) {
461
				IProjectNatureDescriptor desc = null;
457
				Policy.log(e.getStatus());
462
				try {
463
					desc = new ProjectNatureDescriptor(extensions[i]);
464
				} catch (CoreException e) {
465
					Policy.log(e.getStatus());
466
				}
467
				if (desc != null)
468
					tempDescriptors.put(desc.getNatureId(), desc);
458
			}
469
			}
459
			if (desc != null)
470
			//do cycle detection now so it only has to be done once
460
				descriptors.put(desc.getNatureId(), desc);
471
			//cycle detection on a graph subset is a pain
472
			detectCycles(tempDescriptors);
473
			descriptors = tempDescriptors;
461
		}
474
		}
462
		//do cycle detection now so it only has to be done once
463
		//cycle detection on a graph subset is a pain
464
		detectCycles();
465
	}
475
	}
466
476
467
	/**
477
	/**
468
	 * Sets the cached array of enabled natures for this project.
478
	 * Sets the cached array of enabled natures for this project.
469
	 */
479
	 */
470
	protected void setEnabledNatures(IProject project, String[] enablements) {
480
	private void setEnabledNatures(IProject project, String[] enablements) {
471
		if (natureEnablements == null)
481
		if (natureEnablements == null)
472
			natureEnablements = Collections.synchronizedMap(new HashMap(20));
482
			natureEnablements = Collections.synchronizedMap(new HashMap(20));
473
		natureEnablements.put(project, enablements);
483
		natureEnablements.put(project, enablements);
Lines 513-519 Link Here
513
	 * @return An OK status if all additions are valid, and an error status 
523
	 * @return An OK status if all additions are valid, and an error status 
514
	 * 	if any of the additions introduce new inconsistencies.
524
	 * 	if any of the additions introduce new inconsistencies.
515
	 */
525
	 */
516
	protected IStatus validateAdditions(HashSet newNatures, HashSet additions, IProject project) {
526
	private IStatus validateAdditions(HashSet newNatures, HashSet additions, IProject project) {
517
		Boolean hasLinks = null;//three states: true, false, null (not yet computed)
527
		Boolean hasLinks = null;//three states: true, false, null (not yet computed)
518
		//perform checks in order from least expensive to most expensive
528
		//perform checks in order from least expensive to most expensive
519
		for (Iterator added = additions.iterator(); added.hasNext();) {
529
		for (Iterator added = additions.iterator(); added.hasNext();) {
Lines 585-591 Link Here
585
	 * @return An OK status if all removals are valid, and a not OK status 
595
	 * @return An OK status if all removals are valid, and a not OK status 
586
	 * 	if any of the deletions introduce new inconsistencies.
596
	 * 	if any of the deletions introduce new inconsistencies.
587
	 */
597
	 */
588
	protected IStatus validateRemovals(HashSet newNatures, HashSet deletions) {
598
	private IStatus validateRemovals(HashSet newNatures, HashSet deletions) {
589
		//iterate over new nature set, and ensure that none of their prerequisites are being deleted
599
		//iterate over new nature set, and ensure that none of their prerequisites are being deleted
590
		for (Iterator it = newNatures.iterator(); it.hasNext();) {
600
		for (Iterator it = newNatures.iterator(); it.hasNext();) {
591
			String currentID = (String) it.next();
601
			String currentID = (String) it.next();

Return to bug 307587