Lines 16-29
Link Here
|
16 |
import java.util.HashMap; |
16 |
import java.util.HashMap; |
17 |
import java.util.Map; |
17 |
import java.util.Map; |
18 |
import java.util.Set; |
18 |
import java.util.Set; |
19 |
import org.eclipse.core.resources.IWorkspaceRoot; |
|
|
20 |
import org.eclipse.core.resources.ResourcesPlugin; |
19 |
import org.eclipse.core.resources.ResourcesPlugin; |
21 |
import org.eclipse.core.runtime.Assert; |
|
|
22 |
import org.eclipse.core.runtime.IPath; |
20 |
import org.eclipse.core.runtime.IPath; |
23 |
import org.eclipse.core.runtime.IProgressMonitor; |
|
|
24 |
import org.eclipse.core.runtime.NullProgressMonitor; |
25 |
import org.eclipse.core.runtime.Path; |
21 |
import org.eclipse.core.runtime.Path; |
26 |
import org.eclipse.core.runtime.SubProgressMonitor; |
|
|
27 |
import org.eclipse.core.runtime.preferences.IEclipsePreferences; |
22 |
import org.eclipse.core.runtime.preferences.IEclipsePreferences; |
28 |
import org.eclipse.jdt.core.IClasspathContainer; |
23 |
import org.eclipse.jdt.core.IClasspathContainer; |
29 |
import org.eclipse.jdt.core.IClasspathEntry; |
24 |
import org.eclipse.jdt.core.IClasspathEntry; |
Lines 36-275
Link Here
|
36 |
/** |
31 |
/** |
37 |
* |
32 |
* |
38 |
*/ |
33 |
*/ |
39 |
public class UserLibraryManager { |
34 |
public class UserLibraryManager implements IEclipsePreferences.IPreferenceChangeListener { |
40 |
|
35 |
|
41 |
public final static String CP_USERLIBRARY_PREFERENCES_PREFIX = JavaCore.PLUGIN_ID+".userLibrary."; //$NON-NLS-1$ |
36 |
public final static String CP_USERLIBRARY_PREFERENCES_PREFIX = JavaCore.PLUGIN_ID+".userLibrary."; //$NON-NLS-1$ |
42 |
public final static String CP_ENTRY_IGNORE = "##<cp entry ignore>##"; //$NON-NLS-1$ |
|
|
43 |
|
37 |
|
44 |
private static Map UserLibraries; |
38 |
private Map userLibraries; |
45 |
private static ThreadLocal InitializingLibraries = new ThreadLocal(); |
|
|
46 |
private static final boolean logProblems= false; |
47 |
private static IEclipsePreferences.IPreferenceChangeListener listener= new IEclipsePreferences.IPreferenceChangeListener() { |
48 |
|
39 |
|
49 |
public void preferenceChange(IEclipsePreferences.PreferenceChangeEvent event) { |
40 |
public UserLibraryManager() { |
50 |
String key= event.getKey(); |
41 |
initialize(); |
51 |
if (key.startsWith(CP_USERLIBRARY_PREFERENCES_PREFIX)) { |
|
|
52 |
try { |
53 |
recreatePersistedUserLibraryEntry(key, (String) event.getNewValue(), false, true); |
54 |
} catch (JavaModelException e) { |
55 |
if (logProblems) { |
56 |
Util.log(e, "Exception while rebinding user library '"+ key.substring(CP_USERLIBRARY_PREFERENCES_PREFIX.length()) +"'."); //$NON-NLS-1$ //$NON-NLS-2$ |
57 |
} |
58 |
|
59 |
} |
60 |
} |
61 |
} |
62 |
}; |
63 |
|
64 |
private UserLibraryManager() { |
65 |
// do not instantiate |
66 |
} |
42 |
} |
67 |
|
43 |
|
68 |
/** |
44 |
/* |
69 |
* Returns the names of all defined user libraries. The corresponding classpath container path |
|
|
70 |
* is the name appended to the CONTAINER_ID. |
71 |
* @return Return an array containing the names of all known user defined. |
72 |
*/ |
73 |
public static String[] getUserLibraryNames() { |
74 |
Set set= getLibraryMap().keySet(); |
75 |
return (String[]) set.toArray(new String[set.size()]); |
76 |
} |
77 |
|
78 |
/** |
79 |
* Gets the library for a given name or <code>null</code> if no such library exists. |
45 |
* Gets the library for a given name or <code>null</code> if no such library exists. |
80 |
* @param name The name of the library |
|
|
81 |
* @return The library registered for the given name or <code>null</code>. |
82 |
*/ |
83 |
public static UserLibrary getUserLibrary(String name) { |
84 |
return (UserLibrary) getLibraryMap().get(name); |
85 |
} |
86 |
|
87 |
/** |
88 |
* Registers user libraries for given names. If a library for the given name already exists, its value will be updated. |
89 |
* This call will also rebind all related classpath container. |
90 |
* @param newNames The names to register the libraries for |
91 |
* @param newLibs The libraries to register |
92 |
* @param monitor A progress monitor used when rebinding the classpath containers |
93 |
* @throws JavaModelException |
94 |
*/ |
46 |
*/ |
95 |
public static void setUserLibraries(String[] newNames, UserLibrary[] newLibs, IProgressMonitor monitor) throws JavaModelException { |
47 |
public synchronized UserLibrary getUserLibrary(String libName) { |
96 |
Assert.isTrue(newNames.length == newLibs.length, "names and libraries should have the same length"); //$NON-NLS-1$ |
48 |
return (UserLibrary) this.userLibraries.get(libName); |
97 |
|
|
|
98 |
if (monitor == null) { |
99 |
monitor= new NullProgressMonitor(); |
100 |
} |
101 |
|
102 |
try { |
103 |
monitor.beginTask("", newNames.length); //$NON-NLS-1$ |
104 |
int last= newNames.length - 1; |
105 |
for (int i= 0; i < newLibs.length; i++) { |
106 |
internalSetUserLibrary(newNames[i], newLibs[i], i == last, true, new SubProgressMonitor(monitor, 1)); |
107 |
} |
108 |
} finally { |
109 |
monitor.done(); |
110 |
} |
111 |
} |
49 |
} |
112 |
|
50 |
|
113 |
/** |
51 |
/* |
114 |
* Registers a user library for a given name. If a library for the given name already exists, its value will be updated. |
52 |
* Returns the names of all defined user libraries. The corresponding classpath container path |
115 |
* This call will also rebind all related classpath container. |
53 |
* is the name appended to the CONTAINER_ID. |
116 |
* @param name The name to register the library for |
|
|
117 |
* @param library The library to register |
118 |
* @param monitor A progress monitor used when rebinding the classpath containers |
119 |
* @throws JavaModelException |
120 |
*/ |
54 |
*/ |
121 |
public static void setUserLibrary(String name, UserLibrary library, IProgressMonitor monitor) throws JavaModelException { |
55 |
public synchronized String[] getUserLibraryNames() { |
122 |
internalSetUserLibrary(name, library, true, true, monitor); |
56 |
Set set = this.userLibraries.keySet(); |
|
|
57 |
return (String[]) set.toArray(new String[set.size()]); |
123 |
} |
58 |
} |
124 |
|
59 |
|
125 |
static Map getLibraryMap() { |
60 |
private void initialize() { |
126 |
if (UserLibraries == null) { |
61 |
this.userLibraries = new HashMap(); |
127 |
HashMap libraries = (HashMap) InitializingLibraries.get(); |
62 |
IEclipsePreferences instancePreferences = JavaModelManager.getJavaModelManager().getInstancePreferences(); |
128 |
if (libraries != null) |
63 |
String[] propertyNames; |
129 |
return libraries; |
64 |
try { |
130 |
try { |
65 |
propertyNames = instancePreferences.keys(); |
131 |
InitializingLibraries.set(libraries = new HashMap()); |
66 |
} catch (BackingStoreException e) { |
132 |
// load variables and containers from preferences into cache |
67 |
Util.log(e, "Exception while initializing user libraries"); //$NON-NLS-1$ |
133 |
IEclipsePreferences instancePreferences = JavaModelManager.getJavaModelManager().getInstancePreferences(); |
68 |
return; |
134 |
instancePreferences.addPreferenceChangeListener(listener); |
69 |
} |
135 |
|
70 |
|
136 |
// only get variable from preferences not set to their default |
71 |
boolean preferencesNeedFlush = false; |
137 |
try { |
72 |
for (int i = 0, length = propertyNames.length; i < length; i++) { |
138 |
String[] propertyNames = instancePreferences.keys(); |
73 |
String propertyName = propertyNames[i]; |
139 |
for (int i = 0; i < propertyNames.length; i++) { |
74 |
if (propertyName.startsWith(CP_USERLIBRARY_PREFERENCES_PREFIX)) { |
140 |
String propertyName = propertyNames[i]; |
75 |
String propertyValue = instancePreferences.get(propertyName, null); |
141 |
if (propertyName.startsWith(CP_USERLIBRARY_PREFERENCES_PREFIX)) { |
76 |
if (propertyValue != null) { |
142 |
try { |
77 |
String libName= propertyName.substring(CP_USERLIBRARY_PREFERENCES_PREFIX.length()); |
143 |
String propertyValue = instancePreferences.get(propertyName, null); |
78 |
StringReader reader = new StringReader(propertyValue); |
144 |
if (propertyValue != null) |
79 |
UserLibrary library; |
145 |
recreatePersistedUserLibraryEntry(propertyName,propertyValue, false, false); |
80 |
try { |
146 |
} catch (JavaModelException e) { |
81 |
library = UserLibrary.createFromString(reader); |
147 |
// won't happen: no rebinding |
82 |
} catch (IOException e) { |
148 |
} |
83 |
Util.log(e, "Exception while initializing user library " + libName); //$NON-NLS-1$ |
149 |
} |
84 |
instancePreferences.remove(propertyName); |
|
|
85 |
preferencesNeedFlush = true; |
86 |
continue; |
150 |
} |
87 |
} |
151 |
} catch (BackingStoreException e) { |
88 |
this.userLibraries.put(libName, library); |
152 |
// nothing to do in this case |
|
|
153 |
} |
89 |
} |
154 |
UserLibraries = libraries; |
|
|
155 |
} finally { |
156 |
InitializingLibraries.set(null); |
157 |
} |
90 |
} |
158 |
} |
91 |
} |
159 |
return UserLibraries; |
92 |
if (preferencesNeedFlush) { |
160 |
} |
|
|
161 |
|
162 |
static void recreatePersistedUserLibraryEntry(String propertyName, String savedString, boolean save, boolean rebind) throws JavaModelException { |
163 |
String libName= propertyName.substring(CP_USERLIBRARY_PREFERENCES_PREFIX.length()); |
164 |
if (savedString == null || savedString.equals(CP_ENTRY_IGNORE)) { |
165 |
internalSetUserLibrary(libName, null, save, rebind, null); |
166 |
} else { |
167 |
try { |
93 |
try { |
168 |
StringReader reader = new StringReader(savedString); |
94 |
instancePreferences.flush(); |
169 |
UserLibrary library= UserLibrary.createFromString(reader); |
95 |
} catch (BackingStoreException e) { |
170 |
internalSetUserLibrary(libName, library, save, rebind, null); |
96 |
Util.log(e, "Exception while flusing instance preferences"); //$NON-NLS-1$ |
171 |
} catch (IOException e) { |
|
|
172 |
if (logProblems) { |
173 |
Util.log(e, "Exception while retrieving user library '"+ propertyName +"', library will be removed."); //$NON-NLS-1$ //$NON-NLS-2$ |
174 |
} |
175 |
internalSetUserLibrary(libName, null, save, rebind, null); |
176 |
} |
97 |
} |
177 |
} |
98 |
} |
178 |
} |
99 |
} |
179 |
|
100 |
|
180 |
|
101 |
public void preferenceChange(IEclipsePreferences.PreferenceChangeEvent event) { |
181 |
|
102 |
String key = event.getKey(); |
182 |
static void internalSetUserLibrary(String name, UserLibrary library, boolean save, boolean rebind, IProgressMonitor monitor) throws JavaModelException { |
103 |
if (key.startsWith(CP_USERLIBRARY_PREFERENCES_PREFIX)) { |
183 |
if (library == null) { |
104 |
String libName = key.substring(CP_USERLIBRARY_PREFERENCES_PREFIX.length()); |
184 |
Object previous= getLibraryMap().remove(name); |
|
|
185 |
if (previous == null) { |
186 |
return; // no change |
187 |
} |
188 |
} else { |
189 |
Object previous= getLibraryMap().put(name, library); |
190 |
if (library.equals(previous)) { |
191 |
return; // no change |
192 |
} |
193 |
} |
194 |
|
195 |
IEclipsePreferences instancePreferences = JavaModelManager.getJavaModelManager().getInstancePreferences(); |
196 |
String containerKey = CP_USERLIBRARY_PREFERENCES_PREFIX+name; |
197 |
String containerString = CP_ENTRY_IGNORE; |
198 |
if (library != null) { |
199 |
try { |
105 |
try { |
200 |
containerString= library.serialize(); |
106 |
// find affected projects |
|
|
107 |
IPath containerPath = new Path(JavaCore.USER_LIBRARY_CONTAINER_ID).append(libName); |
108 |
IJavaProject[] allJavaProjects = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot()).getJavaProjects(); |
109 |
ArrayList affectedProjects = new ArrayList(); |
110 |
for (int i= 0; i < allJavaProjects.length; i++) { |
111 |
IJavaProject javaProject = allJavaProjects[i]; |
112 |
IClasspathEntry[] entries= javaProject.getRawClasspath(); |
113 |
for (int j= 0; j < entries.length; j++) { |
114 |
IClasspathEntry entry = entries[j]; |
115 |
if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) { |
116 |
if (containerPath.equals(entry.getPath())) { |
117 |
affectedProjects.add(javaProject); |
118 |
break; |
119 |
} |
120 |
} |
121 |
} |
122 |
} |
123 |
|
124 |
// decode user library |
125 |
String encodedUserLibrary = (String) event.getNewValue(); |
126 |
UserLibrary userLibrary = encodedUserLibrary == null ? null : UserLibrary.createFromString(new StringReader(encodedUserLibrary)); |
127 |
|
128 |
// update user libraries map |
129 |
if (userLibrary != null) { |
130 |
this.userLibraries.put(libName, userLibrary); |
131 |
} else { |
132 |
this.userLibraries.remove(libName); |
133 |
} |
134 |
|
135 |
// update affected projects |
136 |
int length = affectedProjects.size(); |
137 |
if (length == 0) |
138 |
return; |
139 |
IJavaProject[] projects = new IJavaProject[length]; |
140 |
affectedProjects.toArray(projects); |
141 |
IClasspathContainer[] containers = new IClasspathContainer[length]; |
142 |
if (userLibrary != null) { |
143 |
UserLibraryClasspathContainer container = new UserLibraryClasspathContainer(libName); |
144 |
for (int i = 0; i < length; i++) { |
145 |
containers[i] = container; |
146 |
} |
147 |
} |
148 |
JavaCore.setClasspathContainer(containerPath, projects, containers, null); |
201 |
} catch (IOException e) { |
149 |
} catch (IOException e) { |
202 |
// could not encode entry: leave it as CP_ENTRY_IGNORE |
150 |
Util.log(e, "Exception while decoding user library '"+ libName +"'."); //$NON-NLS-1$ //$NON-NLS-2$ |
|
|
151 |
} catch (JavaModelException e) { |
152 |
Util.log(e, "Exception while setting user library '"+ libName +"'."); //$NON-NLS-1$ //$NON-NLS-2$ |
203 |
} |
153 |
} |
204 |
} |
154 |
} |
205 |
instancePreferences.removePreferenceChangeListener(listener); |
155 |
} |
|
|
156 |
|
157 |
public synchronized void removeUserLibrary(String libName) { |
158 |
IEclipsePreferences instancePreferences = JavaModelManager.getJavaModelManager().getInstancePreferences(); |
159 |
String propertyName = CP_USERLIBRARY_PREFERENCES_PREFIX+libName; |
160 |
instancePreferences.remove(propertyName); |
206 |
try { |
161 |
try { |
207 |
instancePreferences.put(containerKey, containerString); |
162 |
instancePreferences.flush(); |
208 |
if (save) { |
163 |
} catch (BackingStoreException e) { |
209 |
try { |
164 |
Util.log(e, "Exception while removing user library " + libName); //$NON-NLS-1$ |
210 |
instancePreferences.flush(); |
|
|
211 |
} catch (BackingStoreException e) { |
212 |
// nothing to do in this case |
213 |
} |
214 |
} |
215 |
if (rebind) { |
216 |
rebindClasspathEntries(name, library==null, monitor); |
217 |
} |
218 |
|
219 |
} finally { |
220 |
instancePreferences.addPreferenceChangeListener(listener); |
221 |
} |
165 |
} |
|
|
166 |
// this.userLibraries was updated during the PreferenceChangeEvent (see preferenceChange(...)) |
222 |
} |
167 |
} |
223 |
|
168 |
|
224 |
private static void rebindClasspathEntries(String name, boolean remove, IProgressMonitor monitor) throws JavaModelException { |
169 |
public synchronized void setUserLibrary(String libName, IClasspathEntry[] entries, boolean isSystemLibrary) { |
|
|
170 |
IEclipsePreferences instancePreferences = JavaModelManager.getJavaModelManager().getInstancePreferences(); |
171 |
String propertyName = CP_USERLIBRARY_PREFERENCES_PREFIX+libName; |
225 |
try { |
172 |
try { |
226 |
if (monitor != null) { |
173 |
String propertyValue = UserLibrary.serialize(entries, isSystemLibrary); |
227 |
monitor.beginTask("", 1); //$NON-NLS-1$ |
174 |
instancePreferences.put(propertyName, propertyValue); // sends out a PreferenceChangeEvent (see preferenceChange(...)) |
228 |
} |
175 |
} catch (IOException e) { |
229 |
IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot(); |
176 |
Util.log(e, "Exception while serializing user library " + libName); //$NON-NLS-1$ |
230 |
IJavaProject[] projects= JavaCore.create(root).getJavaProjects(); |
177 |
return; |
231 |
IPath containerPath= new Path(JavaCore.USER_LIBRARY_CONTAINER_ID).append(name); |
|
|
232 |
|
233 |
ArrayList affectedProjects= new ArrayList(); |
234 |
|
235 |
for (int i= 0; i < projects.length; i++) { |
236 |
IJavaProject project= projects[i]; |
237 |
IClasspathEntry[] entries= project.getRawClasspath(); |
238 |
for (int k= 0; k < entries.length; k++) { |
239 |
IClasspathEntry curr= entries[k]; |
240 |
if (curr.getEntryKind() == IClasspathEntry.CPE_CONTAINER) { |
241 |
if (containerPath.equals(curr.getPath())) { |
242 |
affectedProjects.add(project); |
243 |
break; |
244 |
} |
245 |
} |
246 |
} |
247 |
} |
248 |
if (!affectedProjects.isEmpty()) { |
249 |
IJavaProject[] affected= (IJavaProject[]) affectedProjects.toArray(new IJavaProject[affectedProjects.size()]); |
250 |
IClasspathContainer[] containers= new IClasspathContainer[affected.length]; |
251 |
if (!remove) { |
252 |
// Previously, containers array only contained a null value. Then, user library classpath entry was first removed |
253 |
// and then added a while after when post change delta event on .classpath file was fired... |
254 |
// Unfortunately, in some cases, this event was fired a little bit too late and missed the refresh of Package Explorer |
255 |
// (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=61872) |
256 |
// So now, instanciate a new user library classpath container instead which allow to refresh its content immediately |
257 |
// as there's no classpath entry removal... |
258 |
// Note that it works because equals(Object) method is not overridden for UserLibraryClasspathContainer. |
259 |
// If it was, the update wouldn't happen while setting classpath container |
260 |
// @see javaCore.setClasspathContainer(IPath, IJavaProject[], IClasspathContainer[], IProgressMonitor) |
261 |
UserLibraryClasspathContainer container= new UserLibraryClasspathContainer(name); |
262 |
containers[0] = container; |
263 |
} |
264 |
JavaCore.setClasspathContainer(containerPath, affected, containers, monitor == null ? null : new SubProgressMonitor(monitor, 1)); |
265 |
} |
266 |
} finally { |
267 |
if (monitor != null) { |
268 |
monitor.done(); |
269 |
} |
270 |
} |
178 |
} |
|
|
179 |
try { |
180 |
instancePreferences.flush(); |
181 |
} catch (BackingStoreException e) { |
182 |
Util.log(e, "Exception while saving user library " + libName); //$NON-NLS-1$ |
183 |
} |
184 |
// this.userLibraries was updated during the PreferenceChangeEvent (see preferenceChange(...)) |
271 |
} |
185 |
} |
272 |
|
|
|
273 |
|
274 |
|
186 |
|
275 |
} |
187 |
} |