62 * IExecutablesProvider. |
62 * IExecutablesProvider. |
63 * |
63 * |
64 * @author Ken Ryall |
64 * @author Ken Ryall |
65 * |
65 * |
66 */ |
66 */ |
67 public class ExecutablesManager extends PlatformObject implements IResourceChangeListener, ICProjectDescriptionListener { |
67 public class ExecutablesManager extends PlatformObject implements IResourceChangeListener, ICProjectDescriptionListener { |
68 |
68 |
69 private static final String EXECUTABLES_MANAGER_DEBUG_TRACING = CDebugCorePlugin.PLUGIN_ID + "EXECUTABLES_MANAGER_DEBUG_TRACING"; //$NON-NLS-1$ |
69 private static final String EXECUTABLES_MANAGER_DEBUG_TRACING = CDebugCorePlugin.PLUGIN_ID + "EXECUTABLES_MANAGER_DEBUG_TRACING"; //$NON-NLS-1$ |
70 |
70 |
71 private Map<IProject, IProjectExecutablesProvider> executablesProviderMap = new HashMap<IProject, IProjectExecutablesProvider>(); |
71 private Map<IProject, IProjectExecutablesProvider> executablesProviderMap = new HashMap<IProject, IProjectExecutablesProvider>(); |
72 private Map<IProject, List<Executable>> executablesMap = new HashMap<IProject, List<Executable>>(); |
72 private Map<IProject, List<Executable>> executablesMap = new HashMap<IProject, List<Executable>>(); |
73 private List<IExecutablesChangeListener> changeListeners = Collections.synchronizedList(new ArrayList<IExecutablesChangeListener>()); |
73 private List<IExecutablesChangeListener> changeListeners = Collections.synchronizedList(new ArrayList<IExecutablesChangeListener>()); |
74 private List<IProjectExecutablesProvider> executableProviders; |
74 private List<IProjectExecutablesProvider> executableProviders; |
75 private List<ISourceFilesProvider> sourceFileProviders; |
75 private List<ISourceFilesProvider> sourceFileProviders; |
76 private List<ISourceFileRemapping> sourceFileRemappings; |
76 private List<ISourceFileRemapping> sourceFileRemappings; |
77 private List<IExecutableImporter> executableImporters; |
77 private List<IExecutableImporter> executableImporters; |
78 |
78 |
79 private boolean DEBUG; |
79 private boolean DEBUG; |
80 |
80 |
81 private final Job refreshJob = new Job("Get Executables") { |
81 private Job refreshJob = new Job("Get Executables") { |
82 |
82 |
83 @Override |
83 @Override |
84 public IStatus run(IProgressMonitor monitor) { |
84 public IStatus run(IProgressMonitor monitor) { |
85 |
85 |
86 trace("Get Executables job started at " |
86 trace("Get Executables job started at " + getStringFromTimestamp(System.currentTimeMillis())); |
87 + getStringFromTimestamp(System.currentTimeMillis())); |
87 |
88 List<IProject> projects = getProjectsToCheck(); |
88 List<IProject> projects = getProjectsToCheck(); |
89 SubMonitor subMonitor = SubMonitor |
89 |
90 .convert(monitor, projects.size()); |
90 SubMonitor subMonitor = SubMonitor.convert(monitor, projects.size()); |
|
91 |
91 for (IProject project : projects) { |
92 for (IProject project : projects) { |
92 if (subMonitor.isCanceled()) { |
93 if (subMonitor.isCanceled()) { |
93 trace("Get Executables job cancelled at " |
94 trace("Get Executables job cancelled at " + getStringFromTimestamp(System.currentTimeMillis())); |
94 + getStringFromTimestamp(System.currentTimeMillis())); |
|
95 return Status.CANCEL_STATUS; |
95 return Status.CANCEL_STATUS; |
96 } |
96 } |
97 |
97 |
98 subMonitor.subTask("Checking project: " + project.getName()); |
98 subMonitor.subTask("Checking project: " + project.getName()); |
99 |
99 |
100 // get the executables provider for this project |
100 // get the executables provider for this project |
101 IProjectExecutablesProvider provider = getExecutablesProviderForProject(project); |
101 IProjectExecutablesProvider provider = getExecutablesProviderForProject(project); |
102 if (provider != null) { |
102 if (provider != null) { |
103 trace("Getting executables for project: " |
103 trace("Getting executables for project: " + project.getName() + " using " + provider.toString()); |
104 + project.getName() + " using " |
|
105 + provider.toString()); |
|
106 |
104 |
107 // store the list of executables for this project |
105 // store the list of executables for this project |
108 synchronized (executablesMap) { |
106 synchronized (executablesMap) { |
109 executablesMap.put(project, provider.getExecutables( |
107 executablesMap.put(project, provider.getExecutables(project, subMonitor.newChild(1, SubMonitor.SUPPRESS_NONE))); |
110 project, subMonitor.newChild(1, |
108 } |
111 SubMonitor.SUPPRESS_NONE))); |
109 } |
112 } |
110 } |
113 } |
111 |
114 } |
|
115 |
|
116 // notify the listeners |
112 // notify the listeners |
117 synchronized (changeListeners) { |
113 synchronized (changeListeners) { |
118 for (IExecutablesChangeListener listener : changeListeners) { |
114 for (IExecutablesChangeListener listener : changeListeners) { |
119 listener.executablesListChanged(); |
115 listener.executablesListChanged(); |
120 } |
116 } |
121 } |
117 } |
122 |
118 |
123 trace("Get Executables job finished at " |
119 trace("Get Executables job finished at " + getStringFromTimestamp(System.currentTimeMillis())); |
124 + getStringFromTimestamp(System.currentTimeMillis())); |
|
125 |
120 |
126 return Status.OK_STATUS; |
121 return Status.OK_STATUS; |
127 } |
122 } |
128 }; |
123 }; |
129 |
124 |
130 private static ExecutablesManager executablesManager = null; |
125 private static ExecutablesManager executablesManager = null; |
131 |
126 |
132 /** |
127 /** |
133 * Get the executables manager instance |
128 * Get the executables manager instance |
134 * @return the executables manager |
129 * @return the executables manager |
135 * */ |
130 */ |
136 public static ExecutablesManager getExecutablesManager() { |
131 public static ExecutablesManager getExecutablesManager() { |
137 if (executablesManager == null) |
132 if (executablesManager == null) |
138 executablesManager = new ExecutablesManager(); |
133 executablesManager = new ExecutablesManager(); |
139 return executablesManager; |
134 return executablesManager; |
140 } |
135 } |
141 |
136 |
142 public ExecutablesManager() { |
137 public ExecutablesManager() { |
143 // check if debugging is enabled |
138 |
144 BundleContext context = CDebugCorePlugin.getDefault().getBundle().getBundleContext(); |
139 // check if debugging is enabled |
145 if (context != null) { |
140 BundleContext context = CDebugCorePlugin.getDefault().getBundle().getBundleContext(); |
146 ServiceReference reference = CDebugCorePlugin.getDefault().getBundle().getBundleContext().getServiceReference( |
141 if (context != null) { |
147 DebugOptions.class.getName()); |
142 ServiceReference reference = CDebugCorePlugin.getDefault().getBundle().getBundleContext().getServiceReference(DebugOptions.class.getName()); |
148 if (reference != null) { |
143 if (reference != null) { |
149 DebugOptions service = (DebugOptions) context.getService(reference); |
144 DebugOptions service = (DebugOptions) context.getService(reference); |
150 if (service != null) { |
145 if (service != null) { |
151 try { |
146 try { |
152 DEBUG = service.getBooleanOption(EXECUTABLES_MANAGER_DEBUG_TRACING, false); |
147 DEBUG = service.getBooleanOption(EXECUTABLES_MANAGER_DEBUG_TRACING, false); |
153 } finally { |
148 } finally { |
154 // we have what we want - release the service |
149 // we have what we want - release the service |
155 context.ungetService(reference); |
150 context.ungetService(reference); |
156 } |
151 } |
157 } |
152 } |
158 } |
153 } |
159 } |
154 } |
160 |
155 |
161 refreshJob.setPriority(Job.SHORT); |
156 refreshJob.setPriority(Job.SHORT); |
162 |
157 |
163 // load the extension points |
158 // load the extension points |
164 loadExecutableProviderExtensions(); |
159 loadExecutableProviderExtensions(); |
165 loadSoureFileProviderExtensions(); |
160 loadSoureFileProviderExtensions(); |
166 loadSoureRemappingExtensions(); |
161 loadSoureRemappingExtensions(); |
167 loadExecutableImporterExtensions(); |
162 loadExecutableImporterExtensions(); |
168 |
163 |
169 // add the standard providers |
164 // add the standard providers |
170 executableProviders.add(0, new StandardExecutableProvider()); |
165 executableProviders.add(0, new StandardExecutableProvider()); |
171 sourceFileProviders.add(0, new StandardSourceFilesProvider()); |
166 sourceFileProviders.add(0, new StandardSourceFilesProvider()); |
172 sourceFileRemappings.add(0, new StandardSourceFileRemapping()); |
167 sourceFileRemappings.add(0, new StandardSourceFileRemapping()); |
173 executableImporters.add(0, new StandardExecutableImporter()); |
168 executableImporters.add(0, new StandardExecutableImporter()); |
174 |
169 |
175 // listen for events we're interested in |
170 // listen for events we're interested in |
176 ResourcesPlugin.getWorkspace().addResourceChangeListener( |
171 ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.POST_BUILD); |
177 this, IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.POST_BUILD); |
172 CoreModel.getDefault().getProjectDescriptionManager().addCProjectDescriptionListener(this, |
178 CoreModel.getDefault().getProjectDescriptionManager().addCProjectDescriptionListener(this, CProjectDescriptionEvent.DATA_APPLIED); |
173 CProjectDescriptionEvent.DATA_APPLIED); |
179 |
174 |
180 // schedule a refresh so we get up to date |
175 // schedule a refresh so we get up to date |
181 scheduleRefresh(); |
176 scheduleRefresh(); |
182 } |
177 } |
183 |
178 |
184 |
179 /** |
185 /** |
180 * Adds an executable listener |
186 * Adds an executable listener |
|
187 * @param listener the listener to add |
181 * @param listener the listener to add |
188 */ |
182 */ |
189 public void addExecutablesChangeListener(IExecutablesChangeListener listener) { |
183 public void addExecutablesChangeListener(IExecutablesChangeListener listener) { |
190 changeListeners.add(listener); |
184 changeListeners.add(listener); |
191 } |
185 } |
192 |
186 |
193 /** |
187 /** |
194 * Removes an executable listener |
188 * Removes an executable listener |
195 * @param listener the listener to remove |
189 * @param listener the listener to remove |
196 */ |
190 */ |
197 public void removeExecutablesChangeListener(IExecutablesChangeListener listener) { |
191 public void removeExecutablesChangeListener(IExecutablesChangeListener listener) { |
198 changeListeners.remove(listener); |
192 changeListeners.remove(listener); |
199 } |
193 } |
200 |
194 |
201 /** |
195 /** |
202 * Gets the list of executables in the workspace. |
196 * Gets the list of executables in the workspace. |
203 * @return the list of executables which may be empty |
197 * @param wait whether or not to wait if the list is being refreshed when this |
204 */ |
198 * method is called. when true, this call will not return until the list is |
205 public Collection<Executable> getExecutables() { |
199 * complete. when false, it will return with the last known list. if calling |
206 trace("getExecutables called at " |
200 * from any UI, you should not block the UI waiting for this to return, but rather |
207 + getStringFromTimestamp(System.currentTimeMillis())); |
201 * register as an {@link IExecutablesChangeListener} to get notifications when the |
|
202 * list changes. |
|
203 * @return the list of executables which may be empty |
|
204 */ |
|
205 public Collection<Executable> getExecutables(boolean wait) { |
|
206 |
|
207 trace("getExecutables called at " + getStringFromTimestamp(System.currentTimeMillis())); |
|
208 |
208 List<Executable> executables = new ArrayList<Executable>(); |
209 List<Executable> executables = new ArrayList<Executable>(); |
209 |
210 |
|
211 if (wait && refreshJob.getState() != Job.NONE) { |
|
212 trace("waiting for refresh job to finish at " + getStringFromTimestamp(System.currentTimeMillis())); |
|
213 try { |
|
214 refreshJob.join(); |
|
215 } catch (InterruptedException e) { |
|
216 } |
|
217 trace("refresh job finished at " + getStringFromTimestamp(System.currentTimeMillis())); |
|
218 } |
|
219 |
210 synchronized (executablesMap) { |
220 synchronized (executablesMap) { |
211 for (List<Executable> exes : executablesMap.values()) { |
221 for (List<Executable> exes : executablesMap.values()) { |
212 for (Executable exe : exes) { |
222 for (Executable exe : exes) { |
213 if (!executables.contains(exe)) { |
223 if (!executables.contains(exe)) { |
214 executables.add(exe); |
224 executables.add(exe); |
215 } |
225 } |
216 } |
226 } |
217 } |
227 } |
218 } |
228 } |
219 trace("getExecutables returned at " |
229 |
220 + getStringFromTimestamp(System.currentTimeMillis())); |
230 trace("getExecutables returned at " + getStringFromTimestamp(System.currentTimeMillis())); |
|
231 |
221 return executables; |
232 return executables; |
222 } |
233 } |
223 |
234 |
224 /** |
235 /** |
225 * @since 6.0 |
236 * Gets the list of executables in the workspace. Equivalent to {@link ExecutablesManager}{@link #getExecutables(false)}. |
226 * Gets the collection of executables for the given project |
237 * Just kept for older API compatibility. |
227 * @param project the project |
238 * @return the list of executables which may be empty |
228 * @return collection of executables which may be empty |
239 */ |
229 * */ |
240 public Collection<Executable> getExecutables() { |
|
241 return getExecutables(false); |
|
242 } |
|
243 |
|
244 /** |
|
245 * @since 6.0 |
|
246 * Gets the collection of executables for the given project |
|
247 * @param project the project |
|
248 * @return collection of executables which may be empty |
|
249 */ |
230 public Collection<Executable> getExecutablesForProject(IProject project) { |
250 public Collection<Executable> getExecutablesForProject(IProject project) { |
231 List<Executable> executables = new ArrayList<Executable>(); |
251 List<Executable> executables = new ArrayList<Executable>(); |
|
252 |
232 synchronized (executablesMap) { |
253 synchronized (executablesMap) { |
233 List<Executable> exes = executablesMap.get(project); |
254 List<Executable> exes = executablesMap.get(project); |
234 if (exes != null) { |
255 if (exes != null) { |
235 for (Executable exe : exes) { |
256 for (Executable exe : exes) { |
236 if (!executables.contains(exe)) { |
257 if (!executables.contains(exe)) { |
237 executables.add(exe); |
258 executables.add(exe); |
238 } |
259 } |
239 } |
260 } |
240 } |
261 } |
241 } |
262 } |
|
263 |
242 return executables; |
264 return executables; |
243 } |
265 } |
244 |
266 |
245 /** Attempt to remap the path to the given source file in the given executable using |
267 /** |
246 * source file mapping extensions |
268 * Attempt to remap the path to the given source file in the given executable using |
247 * @param executable the executable |
269 * source file mapping extensions |
248 * @param filePath the absolute path to the source file |
270 * @param executable the executable |
249 * @return the new path to the source file, which was remapped if possible |
271 * @param filePath the absolute path to the source file |
|
272 * @return the new path to the source file, which was remapped if possible |
250 * |
273 * |
251 * @since 6.0 |
274 * @since 6.0 |
252 */ |
275 */ |
253 public String remapSourceFile(Executable executable, String filePath) { |
276 public String remapSourceFile(Executable executable, String filePath) { |
254 synchronized (sourceFileRemappings) { |
277 synchronized (sourceFileRemappings) { |
255 for (ISourceFileRemapping remapping : sourceFileRemappings) { |
278 for (ISourceFileRemapping remapping : sourceFileRemappings) { |
256 String remappedPath = remapping.remapSourceFile(executable, filePath); |
279 String remappedPath = remapping.remapSourceFile(executable.getPath(), filePath); |
257 if (!remappedPath.equals(filePath)) |
280 if (!remappedPath.equals(filePath)) |
258 return remappedPath; |
281 return remappedPath; |
259 } |
282 } |
260 } |
283 } |
261 return filePath; |
284 return filePath; |
262 } |
285 } |
263 /** |
286 |
264 * Import the given executables into the manager |
287 /** |
265 * @param fileNames the absolute paths of the executables to import |
288 * Import the given executables into the manager |
266 * @param monitor progress monitor |
289 * @param fileNames the absolute paths of the executables to import |
267 */ |
290 * @param monitor progress monitor |
|
291 */ |
268 public void importExecutables(final String[] fileNames, IProgressMonitor monitor) { |
292 public void importExecutables(final String[] fileNames, IProgressMonitor monitor) { |
|
293 |
269 boolean handled = false; |
294 boolean handled = false; |
270 |
295 monitor.beginTask("Import Executables", executableImporters.size()); |
271 monitor.beginTask("Import Executables", executableImporters.size()); |
296 synchronized (executableImporters) { |
272 synchronized (executableImporters) { |
297 Collections.sort(executableImporters, new Comparator<IExecutableImporter>() { |
273 Collections.sort(executableImporters, |
298 |
274 new Comparator<IExecutableImporter>() { |
299 public int compare(IExecutableImporter arg0, IExecutableImporter arg1) { |
275 |
300 int p0 = arg0.getPriority(fileNames); |
276 public int compare(IExecutableImporter arg0, |
301 int p1 = arg1.getPriority(fileNames); |
277 IExecutableImporter arg1) { |
302 if (p0 < p1) |
278 int p0 = arg0.getPriority(fileNames); |
303 return 1; |
279 int p1 = arg1.getPriority(fileNames); |
304 if (p0 > p1) |
280 if (p0 < p1) |
305 return -1; |
281 return 1; |
306 return 0; |
282 if (p0 > p1) |
307 }}); |
283 return -1; |
308 |
284 return 0; |
309 for (IExecutableImporter importer : executableImporters) { |
285 } |
310 handled = importer.importExecutables(fileNames, new SubProgressMonitor(monitor, 1)); |
286 }); |
311 if (handled || monitor.isCanceled()) { |
287 |
312 break; |
288 for (IExecutableImporter importer : executableImporters) { |
313 } |
289 if (handled || monitor.isCanceled()) { |
314 } |
290 break; |
315 } |
291 } |
316 |
292 } |
317 if (handled) |
293 } |
318 scheduleRefresh(); |
294 scheduleRefresh(); |
319 } |
295 } |
320 |
296 |
321 /** |
297 /** |
322 * Determines if the given executable is currently known by the manager |
298 * Determines if the given executable is currently known by the manager |
323 * @param exePath the absolute path to the executable |
299 * * @param exePath |
324 * @return true if the manager knows about it, false otherwise |
300 * the absolute path to the executable |
325 */ |
301 * @return true if the manager knows about it, false otherwise |
326 public boolean executableExists(IPath exePath) { |
302 */ |
327 synchronized (executablesMap) { |
303 public boolean executableExists(IPath exePath) { |
328 for (List<Executable> exes : executablesMap.values()) { |
304 synchronized (executablesMap) { |
329 for (Executable exe : exes) { |
305 for (List<Executable> exes : executablesMap.values()) { |
330 if (exe.getPath().equals(exePath)) { |
306 for (Executable exe : exes) { |
331 return true; |
307 if (exe.getPath().equals(exePath)) { |
332 } |
308 return true; } |
333 } |
309 } |
334 } |
310 } |
335 } |
311 } |
336 |
312 return false; |
337 return false; |
313 } |
338 } |
314 |
339 |
315 |
340 /** |
316 /** |
341 * Get the list of source files for the given executable |
317 * Get the list of source files for the given executable |
342 * @param executable the executable |
318 * @param executable the executable |
343 * @param monitor progress monitor |
319 * @param monitor progress monitor |
344 * @return an array of source files which may be empty |
320 * @return an array of source files which may be empty |
345 */ |
321 */ |
346 public String[] getSourceFiles(final Executable executable, IProgressMonitor monitor) { |
322 public String[] getSourceFiles(final Executable executable, IProgressMonitor monitor) { |
347 String[] result = new String[0]; |
323 String[] result = new String[0]; |
348 |
324 |
349 trace("getSourceFiles called at " + getStringFromTimestamp(System.currentTimeMillis()) + " for " + executable.getPath().toOSString()); |
325 trace("getSourceFiles called at " + getStringFromTimestamp(System.currentTimeMillis()) + " for " + executable.getPath().toOSString()); |
|
326 |
350 |
327 synchronized (sourceFileProviders) { |
351 synchronized (sourceFileProviders) { |
328 Collections.sort(sourceFileProviders, new Comparator<ISourceFilesProvider>() { |
352 Collections.sort(sourceFileProviders, new Comparator<ISourceFilesProvider>() { |
329 |
353 |
330 public int compare(ISourceFilesProvider arg0, ISourceFilesProvider arg1) { |
354 public int compare(ISourceFilesProvider arg0, ISourceFilesProvider arg1) { |
340 monitor.beginTask("Finding source files in " + executable.getName(), sourceFileProviders.size()); |
364 monitor.beginTask("Finding source files in " + executable.getName(), sourceFileProviders.size()); |
341 for (ISourceFilesProvider provider : sourceFileProviders) { |
365 for (ISourceFilesProvider provider : sourceFileProviders) { |
342 String[] sourceFiles = provider.getSourceFiles(executable, new SubProgressMonitor(monitor, 1)); |
366 String[] sourceFiles = provider.getSourceFiles(executable, new SubProgressMonitor(monitor, 1)); |
343 if (sourceFiles.length > 0) { |
367 if (sourceFiles.length > 0) { |
344 result = sourceFiles; |
368 result = sourceFiles; |
345 |
369 |
346 trace("getSourceFiles got " + sourceFiles.length + " files from " + provider.toString()); |
370 trace("getSourceFiles got " + sourceFiles.length + " files from " + provider.toString()); |
347 |
371 |
348 break; |
372 break; |
349 } |
373 } |
350 } |
374 } |
351 monitor.done(); |
375 monitor.done(); |
352 } |
376 } |
353 |
377 |
354 trace("getSourceFiles returned at " + getStringFromTimestamp(System.currentTimeMillis())); |
378 trace("getSourceFiles returned at " + getStringFromTimestamp(System.currentTimeMillis())); |
355 |
379 |
356 return result; |
380 return result; |
357 } |
381 } |
358 |
382 |
359 /** |
383 /** |
360 * Removes the given executables |
384 * Removes the given executables |
361 * @param executables the array of executables to be removed |
385 * @param executables the array of executables to be removed |
362 * @param monitor progress monitor |
386 * @param monitor progress monitor |
363 * @return IStatus of the operation |
387 * @return IStatus of the operation |
364 * |
388 * |
365 * @since 6.0 |
389 * @since 6.0 |
366 */ |
390 */ |
367 public IStatus removeExecutables(Executable[] executables, IProgressMonitor monitor) { |
391 public IStatus removeExecutables(Executable[] executables, IProgressMonitor monitor) { |
368 |
|
369 MultiStatus status = new MultiStatus(CDebugCorePlugin.PLUGIN_ID, IStatus.WARNING, "Couldn't remove all of the selected executables", null); |
392 MultiStatus status = new MultiStatus(CDebugCorePlugin.PLUGIN_ID, IStatus.WARNING, "Couldn't remove all of the selected executables", null); |
370 |
393 |
371 monitor.beginTask("Remove Executables", executables.length); |
394 monitor.beginTask("Remove Executables", executables.length); |
372 for (Executable executable : executables) { |
395 for (Executable executable : executables) { |
373 IProjectExecutablesProvider provider = getExecutablesProviderForProject(executable |
396 |
374 .getProject()); |
397 IProjectExecutablesProvider provider = getExecutablesProviderForProject(executable.getProject()); |
375 if (provider != null) { |
398 if (provider != null) { |
376 IStatus result = provider.removeExecutable(executable, |
399 IStatus result = provider.removeExecutable(executable, new SubProgressMonitor(monitor, 1)); |
377 new SubProgressMonitor(monitor, 1)); |
|
378 if (result.isOK()) { |
400 if (result.isOK()) { |
379 // remove the exe from the list |
401 // remove the exe from the list |
380 List<Executable> exes = executablesMap.get(executable |
402 List<Executable> exes = executablesMap.get(executable.getProject()); |
381 .getProject()); |
|
382 if (exes != null) { |
403 if (exes != null) { |
383 exes.remove(executable); |
404 exes.remove(executable); |
384 } |
405 } |
385 } else { |
406 } else { |
386 status.add(result); |
407 status.add(result); |
387 } |
408 } |
388 } |
409 } |
389 } |
410 } |
|
411 |
390 // notify listeners that the list has changed. only do this if at least one delete succeeded. |
412 // notify listeners that the list has changed. only do this if at least one delete succeeded. |
391 if (status.getChildren().length != executables.length) { |
413 if (status.getChildren().length != executables.length) { |
392 synchronized (changeListeners) { |
414 synchronized (changeListeners) { |
393 for (IExecutablesChangeListener listener : changeListeners) { |
415 for (IExecutablesChangeListener listener : changeListeners) { |
394 listener.executablesListChanged(); |
416 listener.executablesListChanged(); |
395 } |
417 } |
396 } |
418 } |
397 } |
419 } |
398 |
420 |
399 return status; |
421 return status; |
400 } |
422 } |
401 |
423 |
402 /** |
424 /** |
403 * Refresh the list of executables for the given projects |
425 * Refresh the list of executables for the given projects |
404 * |
426 * @param projects the list of projects, or null. if null or the list |
405 * @param projects |
427 * is empty, all projects will be refreshed. |
406 * the list of projects, or null. if null or the list is empty, |
|
407 * all projects will be refreshed. |
|
408 */ |
428 */ |
409 public void refresh(List<IProject> projects) { |
429 public void refresh(List<IProject> projects) { |
410 if (projects == null || projects.size() == 0) { |
430 if (projects == null || projects.size() == 0) { |
411 // clear the entire cache |
431 // clear the entire cache |
412 executablesMap.clear(); |
432 executablesMap.clear(); |
413 } else { |
433 } else { |
414 for (IProject project : projects) { |
434 for (IProject project : projects) { |
415 executablesMap.remove(project); |
435 executablesMap.remove(project); |
416 } |
436 } |
417 } |
437 } |
418 |
438 |
419 scheduleRefresh(); |
439 scheduleRefresh(); |
420 } |
440 } |
421 |
441 |
422 public void resourceChanged(IResourceChangeEvent event) { |
442 public void resourceChanged(IResourceChangeEvent event) { |
423 |
443 |
424 synchronized (executablesMap) { |
444 synchronized (executablesMap) { |
425 // project needs to be refreshed after a build/clean as the binary |
445 // project needs to be refreshed after a build/clean as the binary may |
426 // may |
|
427 // be added/removed/renamed etc. |
446 // be added/removed/renamed etc. |
428 if (event.getType() == IResourceChangeEvent.POST_BUILD) { |
447 if (event.getType() == IResourceChangeEvent.POST_BUILD) { |
429 Object obj = event.getSource(); |
448 Object obj = event.getSource(); |
430 if (obj != null && obj instanceof IProject) { |
449 if (obj != null && obj instanceof IProject) { |
431 if (executablesMap.containsKey(obj)) { |
450 try { |
432 List<Executable> executables = executablesMap |
451 // make sure there's at least one builder for the project. this gets called even |
433 .remove(obj); |
452 // when there are no builder (e.g. the Executables project for imported executables). |
434 |
453 IProject project = (IProject)obj; |
435 trace("Scheduling refresh because project " |
454 if (project.getDescription().getBuildSpec().length > 0) { |
436 + ((IProject) obj).getName() |
455 if (executablesMap.containsKey(obj)) { |
437 + " built or cleaned"); |
456 List<Executable> executables = executablesMap.remove(obj); |
438 |
457 |
439 scheduleRefresh(); |
458 trace("Scheduling refresh because project " + ((IProject)obj).getName() + " built or cleaned"); |
440 |
459 |
441 // notify the listeners that these executables have |
460 scheduleRefresh(); |
442 // possibly changed |
461 |
443 if (executables != null && executables.size() > 0) { |
462 // notify the listeners that these executables have possibly changed |
444 synchronized (changeListeners) { |
463 if (executables != null && executables.size() > 0) { |
445 for (IExecutablesChangeListener listener : changeListeners) { |
464 synchronized (changeListeners) { |
446 listener.executablesChanged(executables); |
465 for (IExecutablesChangeListener listener : changeListeners) { |
|
466 listener.executablesChanged(executables); |
|
467 } |
|
468 } |
447 } |
469 } |
448 } |
470 } |
449 } |
471 } |
|
472 } catch (CoreException e) { |
|
473 e.printStackTrace(); |
450 } |
474 } |
451 } |
475 } |
452 return; |
476 return; |
453 } |
477 } |
454 |
478 |
455 // refresh when projects are opened or closed. note that deleted |
479 // refresh when projects are opened or closed. note that deleted |
456 // projects are handled later in this method. new projects are |
480 // projects are handled later in this method. new projects are handled |
457 // handled |
481 // in handleEvent. resource changed events always start at the workspace |
458 // in handleEvent. resource changed events always start at the |
|
459 // workspace |
|
460 // root, so projects are the next level down |
482 // root, so projects are the next level down |
461 boolean refreshNeeded = false; |
483 boolean refreshNeeded = false; |
462 IResourceDelta[] projects = event.getDelta().getAffectedChildren(); |
484 IResourceDelta[] projects = event.getDelta().getAffectedChildren(); |
463 for (IResourceDelta projectDelta : projects) { |
485 for (IResourceDelta projectDelta : projects) { |
464 if ((projectDelta.getFlags() & IResourceDelta.OPEN) != 0) { |
486 if ((projectDelta.getFlags() & IResourceDelta.OPEN) != 0) { |
465 if (projectDelta.getKind() == IResourceDelta.CHANGED) { |
487 if (projectDelta.getKind() == IResourceDelta.CHANGED) { |
466 // project was opened or closed |
488 // project was opened or closed |
467 if (executablesMap.containsKey(projectDelta |
489 if (executablesMap.containsKey(projectDelta.getResource())) { |
468 .getResource())) { |
|
469 executablesMap.remove(projectDelta.getResource()); |
490 executablesMap.remove(projectDelta.getResource()); |
470 } |
491 } |
471 refreshNeeded = true; |
492 refreshNeeded = true; |
472 } |
493 } |
473 } |
494 } |
474 } |
495 } |
475 |
496 |
476 if (refreshNeeded) { |
497 if (refreshNeeded) { |
477 trace("Scheduling refresh because project(s) opened or closed"); |
498 trace("Scheduling refresh because project(s) opened or closed"); |
478 |
499 |
479 scheduleRefresh(); |
500 scheduleRefresh(); |
480 return; |
501 return; |
481 } |
502 } |
482 |
503 |
483 try { |
504 try { |
484 event.getDelta().accept(new IResourceDeltaVisitor() { |
505 event.getDelta().accept(new IResourceDeltaVisitor() { |
485 |
506 |
486 public boolean visit(IResourceDelta delta) |
507 public boolean visit(IResourceDelta delta) throws CoreException { |
487 throws CoreException { |
508 if (delta.getKind() == IResourceDelta.ADDED || delta.getKind() == IResourceDelta.REMOVED) { |
488 if (delta.getKind() == IResourceDelta.ADDED |
|
489 || delta.getKind() == IResourceDelta.REMOVED) { |
|
490 IResource deltaResource = delta.getResource(); |
509 IResource deltaResource = delta.getResource(); |
491 if (deltaResource != null) { |
510 if (deltaResource != null) { |
492 boolean refresh = false; |
511 boolean refresh = false; |
493 if (delta.getKind() == IResourceDelta.REMOVED |
512 if (delta.getKind() == IResourceDelta.REMOVED && deltaResource instanceof IProject) { |
494 && deltaResource instanceof IProject) { |
|
495 // project deleted |
513 // project deleted |
496 if (executablesMap |
514 if (executablesMap.containsKey(deltaResource)) { |
497 .containsKey(deltaResource)) { |
|
498 executablesMap.remove(deltaResource); |
515 executablesMap.remove(deltaResource); |
499 refresh = true; |
516 refresh = true; |
500 |
517 |
501 trace("Scheduling refresh because project " |
518 trace("Scheduling refresh because project " + deltaResource.getName() + " deleted"); |
502 + deltaResource.getName() |
|
503 + " deleted"); |
|
504 } |
519 } |
505 } else { |
520 } else { |
506 // see if a binary has been added/removed |
521 // see if a binary has been added/removed |
507 IPath resourcePath = deltaResource |
522 IPath resourcePath = deltaResource.getLocation(); |
508 .getLocation(); |
523 if (resourcePath != null && Executable.isExecutableFile(resourcePath)) { |
509 if (resourcePath != null |
524 if (executablesMap.containsKey(deltaResource.getProject())) { |
510 && Executable |
525 executablesMap.remove(deltaResource.getProject()); |
511 .isExecutableFile(resourcePath)) { |
|
512 if (executablesMap |
|
513 .containsKey(deltaResource |
|
514 .getProject())) { |
|
515 executablesMap.remove(deltaResource |
|
516 .getProject()); |
|
517 refresh = true; |
526 refresh = true; |
518 |
527 |
519 trace("Scheduling refresh because a binary was added/removed"); |
528 trace("Scheduling refresh because a binary was added/removed"); |
520 } |
529 } |
521 } |
530 } |
637 |
636 |
638 } catch (CoreException e) { |
637 } catch (CoreException e) { |
639 e.printStackTrace(); |
638 e.printStackTrace(); |
640 } |
639 } |
641 } |
640 } |
642 |
641 |
643 return provider; |
642 return provider; |
644 } |
643 } |
645 |
644 |
646 private void loadExecutableProviderExtensions() { |
645 private void loadExecutableProviderExtensions() { |
647 executableProviders = Collections |
646 executableProviders = Collections.synchronizedList(new ArrayList<IProjectExecutablesProvider>()); |
648 .synchronizedList(new ArrayList<IProjectExecutablesProvider>()); |
|
649 |
647 |
650 IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); |
648 IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); |
651 IExtensionPoint extensionPoint = extensionRegistry |
649 IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(CDebugCorePlugin.PLUGIN_ID + ".ExecutablesProvider"); //$NON-NLS-1$ |
652 .getExtensionPoint(CDebugCorePlugin.PLUGIN_ID |
|
653 + ".ExecutablesProvider"); //$NON-NLS-1$ |
|
654 IExtension[] extensions = extensionPoint.getExtensions(); |
650 IExtension[] extensions = extensionPoint.getExtensions(); |
655 |
651 |
656 for (int i = 0; i < extensions.length; i++) { |
652 for (int i = 0; i < extensions.length; i++) { |
657 IExtension extension = extensions[i]; |
653 IExtension extension = extensions[i]; |
658 IConfigurationElement[] elements = extension |
654 IConfigurationElement[] elements = extension.getConfigurationElements(); |
659 .getConfigurationElements(); |
|
660 IConfigurationElement element = elements[0]; |
655 IConfigurationElement element = elements[0]; |
661 |
656 |
662 boolean failed = false; |
657 boolean failed = false; |
663 try { |
658 try { |
664 Object extObject = element.createExecutableExtension("class"); //$NON-NLS-1$ |
659 Object extObject = element.createExecutableExtension("class"); //$NON-NLS-1$ |
665 if (extObject instanceof IProjectExecutablesProvider) { |
660 if (extObject instanceof IProjectExecutablesProvider) { |
666 executableProviders |
661 executableProviders.add((IProjectExecutablesProvider)extObject); |
667 .add((IProjectExecutablesProvider) extObject); |
|
668 } else { |
662 } else { |
669 failed = true; |
663 failed = true; |
670 } |
664 } |
671 } catch (CoreException e) { |
665 } |
|
666 catch (CoreException e) { |
672 failed = true; |
667 failed = true; |
673 } |
668 } |
674 |
669 |
675 if (failed) { |
670 if (failed) { |
676 CDebugCorePlugin |
671 CDebugCorePlugin.log("Unable to load ExecutablesProvider extension from " + extension.getContributor().getName()); |
677 .log("Unable to load ExecutablesProvider extension from " |
672 } |
678 + extension.getContributor().getName()); |
673 } |
679 } |
674 } |
680 } |
675 |
681 } |
|
682 |
|
683 private void loadSoureFileProviderExtensions() { |
676 private void loadSoureFileProviderExtensions() { |
684 sourceFileProviders = Collections |
677 sourceFileProviders = Collections.synchronizedList(new ArrayList<ISourceFilesProvider>()); |
685 .synchronizedList(new ArrayList<ISourceFilesProvider>()); |
|
686 |
678 |
687 IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); |
679 IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); |
688 IExtensionPoint extensionPoint = extensionRegistry |
680 IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(CDebugCorePlugin.PLUGIN_ID + ".SourceFilesProvider"); //$NON-NLS-1$ |
689 .getExtensionPoint(CDebugCorePlugin.PLUGIN_ID |
|
690 + ".SourceFilesProvider"); //$NON-NLS-1$ |
|
691 IExtension[] extensions = extensionPoint.getExtensions(); |
681 IExtension[] extensions = extensionPoint.getExtensions(); |
692 |
682 |
693 for (int i = 0; i < extensions.length; i++) { |
683 for (int i = 0; i < extensions.length; i++) { |
694 IExtension extension = extensions[i]; |
684 IExtension extension = extensions[i]; |
695 IConfigurationElement[] elements = extension |
685 IConfigurationElement[] elements = extension.getConfigurationElements(); |
696 .getConfigurationElements(); |
|
697 IConfigurationElement element = elements[0]; |
686 IConfigurationElement element = elements[0]; |
698 |
687 |
699 boolean failed = false; |
688 boolean failed = false; |
700 try { |
689 try { |
701 Object extObject = element.createExecutableExtension("class"); //$NON-NLS-1$ |
690 Object extObject = element.createExecutableExtension("class"); //$NON-NLS-1$ |
702 if (extObject instanceof ISourceFilesProvider) { |
691 if (extObject instanceof ISourceFilesProvider) { |
703 sourceFileProviders.add((ISourceFilesProvider) extObject); |
692 sourceFileProviders.add((ISourceFilesProvider)extObject); |
704 } else { |
693 } else { |
705 failed = true; |
694 failed = true; |
706 } |
695 } |
707 } catch (CoreException e) { |
696 } |
|
697 catch (CoreException e) { |
708 failed = true; |
698 failed = true; |
709 } |
699 } |
710 |
700 |
711 if (failed) { |
701 if (failed) { |
712 CDebugCorePlugin |
702 CDebugCorePlugin.log("Unable to load SourceFilesProvider extension from " + extension.getContributor().getName()); |
713 .log("Unable to load SourceFilesProvider extension from " |
|
714 + extension.getContributor().getName()); |
|
715 } |
703 } |
716 } |
704 } |
717 } |
705 } |
718 |
706 |
719 private void loadSoureRemappingExtensions() { |
707 private void loadSoureRemappingExtensions() { |
720 sourceFileRemappings = Collections |
708 sourceFileRemappings = Collections.synchronizedList(new ArrayList<ISourceFileRemapping>()); |
721 .synchronizedList(new ArrayList<ISourceFileRemapping>()); |
|
722 |
709 |
723 IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); |
710 IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); |
724 IExtensionPoint extensionPoint = extensionRegistry |
711 IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(CDebugCorePlugin.PLUGIN_ID + ".SourceRemappingProvider"); //$NON-NLS-1$ |
725 .getExtensionPoint(CDebugCorePlugin.PLUGIN_ID |
|
726 + ".SourceRemappingProvider"); //$NON-NLS-1$ |
|
727 IExtension[] extensions = extensionPoint.getExtensions(); |
712 IExtension[] extensions = extensionPoint.getExtensions(); |
728 |
713 |
729 for (int i = 0; i < extensions.length; i++) { |
714 for (int i = 0; i < extensions.length; i++) { |
730 IExtension extension = extensions[i]; |
715 IExtension extension = extensions[i]; |
731 IConfigurationElement[] elements = extension |
716 IConfigurationElement[] elements = extension.getConfigurationElements(); |
732 .getConfigurationElements(); |
|
733 IConfigurationElement element = elements[0]; |
717 IConfigurationElement element = elements[0]; |
734 |
718 |
735 boolean failed = false; |
719 boolean failed = false; |
736 try { |
720 try { |
737 Object extObject = element.createExecutableExtension("class"); //$NON-NLS-1$ |
721 Object extObject = element.createExecutableExtension("class"); //$NON-NLS-1$ |
738 if (extObject instanceof ISourceFileRemapping) { |
722 if (extObject instanceof ISourceFileRemapping) { |
739 sourceFileRemappings.add((ISourceFileRemapping) extObject); |
723 sourceFileRemappings.add((ISourceFileRemapping)extObject); |
740 } else { |
724 } else { |
741 failed = true; |
725 failed = true; |
742 } |
726 } |
743 } catch (CoreException e) { |
727 } |
|
728 catch (CoreException e) { |
744 failed = true; |
729 failed = true; |
745 } |
730 } |
746 |
731 |
747 if (failed) { |
732 if (failed) { |
748 CDebugCorePlugin |
733 CDebugCorePlugin.log("Unable to load SourceRemappingProvider extension from " + extension.getContributor().getName()); |
749 .log("Unable to load SourceRemappingProvider extension from " |
|
750 + extension.getContributor().getName()); |
|
751 } |
734 } |
752 } |
735 } |
753 } |
736 } |
754 |
737 |
755 private void loadExecutableImporterExtensions() { |
738 private void loadExecutableImporterExtensions() { |
756 executableImporters = Collections |
739 executableImporters = Collections.synchronizedList(new ArrayList<IExecutableImporter>()); |
757 .synchronizedList(new ArrayList<IExecutableImporter>()); |
|
758 |
740 |
759 IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); |
741 IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); |
760 IExtensionPoint extensionPoint = extensionRegistry |
742 IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(CDebugCorePlugin.PLUGIN_ID + ".ExecutablesImporter"); //$NON-NLS-1$ |
761 .getExtensionPoint(CDebugCorePlugin.PLUGIN_ID |
|
762 + ".ExecutablesImporter"); //$NON-NLS-1$ |
|
763 IExtension[] extensions = extensionPoint.getExtensions(); |
743 IExtension[] extensions = extensionPoint.getExtensions(); |
764 |
744 |
765 for (int i = 0; i < extensions.length; i++) { |
745 for (int i = 0; i < extensions.length; i++) { |
766 IExtension extension = extensions[i]; |
746 IExtension extension = extensions[i]; |
767 IConfigurationElement[] elements = extension |
747 IConfigurationElement[] elements = extension.getConfigurationElements(); |
768 .getConfigurationElements(); |
|
769 IConfigurationElement element = elements[0]; |
748 IConfigurationElement element = elements[0]; |
770 |
749 |
771 boolean failed = false; |
750 boolean failed = false; |
772 try { |
751 try { |
773 Object extObject = element.createExecutableExtension("class"); //$NON-NLS-1$ |
752 Object extObject = element.createExecutableExtension("class"); //$NON-NLS-1$ |
774 if (extObject instanceof IExecutableImporter) { |
753 if (extObject instanceof IExecutableImporter) { |
775 executableImporters.add((IExecutableImporter) extObject); |
754 executableImporters.add((IExecutableImporter)extObject); |
776 } else { |
755 } else { |
777 failed = true; |
756 failed = true; |
778 } |
757 } |
779 } catch (CoreException e) { |
758 } |
|
759 catch (CoreException e) { |
780 failed = true; |
760 failed = true; |
781 } |
761 } |
782 |
762 |
783 if (failed) { |
763 if (failed) { |
784 CDebugCorePlugin |
764 CDebugCorePlugin.log("Unable to load ExecutablesImporter extension from " + extension.getContributor().getName()); |
785 .log("Unable to load ExecutablesImporter extension from " |
|
786 + extension.getContributor().getName()); |
|
787 } |
765 } |
788 } |
766 } |
789 } |
767 } |
790 |
768 |
791 private void trace(String msg) { |
769 private void trace(String msg) { |
792 if (DEBUG) { |
770 if (DEBUG) { |
793 // TODO use Logger? |
771 // TODO use Logger? |
794 System.out.println(msg); |
772 System.out.println(msg); |
795 } |
773 } |
796 } |
774 } |
797 |
775 |
798 private String getStringFromTimestamp(long timestamp) { |
776 private String getStringFromTimestamp(long timestamp) { |
799 return DateFormat.getTimeInstance(DateFormat.MEDIUM).format( |
777 return DateFormat.getTimeInstance(DateFormat.MEDIUM).format(new Date(timestamp)); |
800 new Date(timestamp)); |
|
801 } |
778 } |
802 } |
779 } |