1 /*******************************************************************************
2  * Copyright (c) 2000, 2015 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *     James Blackburn (Broadcom Corp.) - ongoing development
14  *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 473427
15  *******************************************************************************/
16 package org.eclipse.core.internal.resources;
17 
18 import java.util.HashMap;
19 import org.eclipse.core.internal.events.BuildCommand;
20 import org.eclipse.core.resources.ICommand;
21 import org.eclipse.core.resources.IProjectNature;
22 import org.eclipse.core.runtime.content.IContentTypeMatcher;
23 
24 public class ProjectInfo extends ResourceInfo {
25 
26 	/** The description of this object */
27 	protected ProjectDescription description;
28 
29 	/** The list of natures for this project */
30 	protected HashMap<String, IProjectNature> natures;
31 
32 	/** The property store for this resource (used only by the compatibility fragment) */
33 	protected Object propertyStore;
34 
35 	/** The content type matcher for this project. */
36 	protected IContentTypeMatcher matcher;
37 
38 	/**
39 	 * Discards stale natures on this project after project description
40 	 * has changed.
41 	 */
discardNatures()42 	public synchronized void discardNatures() {
43 		natures = null;
44 	}
45 
46 	/**
47 	 * Default constructor (for easier debugging)
48 	 */
ProjectInfo()49 	public ProjectInfo() {
50 		super();
51 	}
52 
53 	/**
54 	 * Discards any stale state on this project after it has been moved.  Builder
55 	 * instances must be cleared because they reference the old project handle.
56 	 */
fixupAfterMove()57 	public synchronized void fixupAfterMove() {
58 		natures = null;
59 		// note that the property store instance will be recreated lazily
60 		propertyStore = null;
61 		if (description != null) {
62 			ICommand[] buildSpec = description.getBuildSpec(false);
63 			for (ICommand element : buildSpec)
64 				((BuildCommand) element).setBuilders(null);
65 		}
66 	}
67 
68 	/**
69 	 * Returns the description associated with this info.  The return value may be null.
70 	 */
getDescription()71 	public ProjectDescription getDescription() {
72 		return description;
73 	}
74 
75 	/**
76 	 * Returns the content type matcher associated with this info.  The return value may be null.
77 	 */
getMatcher()78 	public IContentTypeMatcher getMatcher() {
79 		return matcher;
80 	}
81 
getNature(String natureId)82 	public IProjectNature getNature(String natureId) {
83 		// thread safety: (Concurrency001)
84 		HashMap<String, IProjectNature> temp = natures;
85 		if (temp == null)
86 			return null;
87 		return temp.get(natureId);
88 	}
89 
90 	/**
91 	 * Returns the property store associated with this info.  The return value may be null.
92 	 */
93 	@Override
getPropertyStore()94 	public Object getPropertyStore() {
95 		return propertyStore;
96 	}
97 
98 	/**
99 	 * Sets the description associated with this info.  The value may be null.
100 	 */
setDescription(ProjectDescription value)101 	public void setDescription(ProjectDescription value) {
102 		if (description != null) {
103 			//if we already have a description, assign the new
104 			//build spec on top of the old one to ensure we maintain
105 			//any existing builder instances in the old build commands
106 			ICommand[] oldSpec = description.buildSpec;
107 			ICommand[] newSpec = value.buildSpec;
108 			value.buildSpec = oldSpec;
109 			value.setBuildSpec(newSpec);
110 		}
111 		description = value;
112 	}
113 
114 	/**
115 	 * Sets the content type matcher to be associated with this info.  The value may be null.
116 	 */
setMatcher(IContentTypeMatcher matcher)117 	public void setMatcher(IContentTypeMatcher matcher) {
118 		this.matcher = matcher;
119 	}
120 
121 	@SuppressWarnings({"unchecked"})
setNature(String natureId, IProjectNature value)122 	public synchronized void setNature(String natureId, IProjectNature value) {
123 		// thread safety: (Concurrency001)
124 		if (value == null) {
125 			if (natures == null)
126 				return;
127 			HashMap<String, IProjectNature> temp = (HashMap<String, IProjectNature>) natures.clone();
128 			temp.remove(natureId);
129 			if (temp.isEmpty())
130 				natures = null;
131 			else
132 				natures = temp;
133 		} else {
134 			HashMap<String, IProjectNature> temp = natures;
135 			if (temp == null)
136 				temp = new HashMap<>(5);
137 			else
138 				temp = (HashMap<String, IProjectNature>) natures.clone();
139 			temp.put(natureId, value);
140 			natures = temp;
141 		}
142 	}
143 
144 	/**
145 	 * Sets the property store associated with this info.  The value may be null.
146 	 */
147 	@Override
setPropertyStore(Object value)148 	public void setPropertyStore(Object value) {
149 		propertyStore = value;
150 	}
151 }
152