10 *******************************************************************************/ |
10 *******************************************************************************/ |
11 |
11 |
12 package org.eclipse.cdt.debug.core.executables; |
12 package org.eclipse.cdt.debug.core.executables; |
13 |
13 |
14 import java.util.ArrayList; |
14 import java.util.ArrayList; |
|
15 import java.util.List; |
15 |
16 |
|
17 import org.eclipse.cdt.core.CCProjectNature; |
|
18 import org.eclipse.cdt.core.CProjectNature; |
16 import org.eclipse.cdt.core.model.CModelException; |
19 import org.eclipse.cdt.core.model.CModelException; |
17 import org.eclipse.cdt.core.model.CoreModel; |
|
18 import org.eclipse.cdt.core.model.IBinary; |
20 import org.eclipse.cdt.core.model.IBinary; |
19 import org.eclipse.cdt.core.model.ICProject; |
21 import org.eclipse.cdt.core.model.ICProject; |
20 import org.eclipse.cdt.core.settings.model.CProjectDescriptionEvent; |
|
21 import org.eclipse.cdt.core.settings.model.ICProjectDescription; |
|
22 import org.eclipse.cdt.core.settings.model.ICProjectDescriptionListener; |
|
23 import org.eclipse.cdt.debug.core.CDebugCorePlugin; |
22 import org.eclipse.cdt.debug.core.CDebugCorePlugin; |
24 import org.eclipse.cdt.internal.core.model.CModelManager; |
23 import org.eclipse.cdt.internal.core.model.CModelManager; |
25 import org.eclipse.core.resources.IProject; |
24 import org.eclipse.core.resources.IProject; |
26 import org.eclipse.core.resources.IResource; |
25 import org.eclipse.core.resources.IResource; |
27 import org.eclipse.core.resources.IResourceChangeEvent; |
|
28 import org.eclipse.core.resources.IResourceChangeListener; |
|
29 import org.eclipse.core.resources.IResourceDelta; |
|
30 import org.eclipse.core.resources.IResourceDeltaVisitor; |
|
31 import org.eclipse.core.resources.IWorkspaceRoot; |
|
32 import org.eclipse.core.resources.ResourcesPlugin; |
|
33 import org.eclipse.core.runtime.CoreException; |
26 import org.eclipse.core.runtime.CoreException; |
34 import org.eclipse.core.runtime.IPath; |
27 import org.eclipse.core.runtime.IPath; |
35 import org.eclipse.core.runtime.IProgressMonitor; |
28 import org.eclipse.core.runtime.IProgressMonitor; |
36 import org.eclipse.core.runtime.IStatus; |
29 import org.eclipse.core.runtime.IStatus; |
37 import org.eclipse.core.runtime.Status; |
30 import org.eclipse.core.runtime.Status; |
|
31 import org.eclipse.core.runtime.SubMonitor; |
38 import org.eclipse.debug.core.DebugPlugin; |
32 import org.eclipse.debug.core.DebugPlugin; |
39 |
33 |
40 public class StandardExecutableProvider implements IResourceChangeListener, ICProjectDescriptionListener, IExecutableProvider { |
34 public class StandardExecutableProvider implements IProjectExecutablesProvider { |
41 |
35 |
42 private ArrayList<Executable> executables = new ArrayList<Executable>(); |
36 List<String> supportedNatureIds = new ArrayList<String>(); |
43 |
37 |
44 public StandardExecutableProvider() { |
38 public StandardExecutableProvider() { |
45 ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE); |
39 supportedNatureIds.add(CProjectNature.C_NATURE_ID); |
46 CoreModel.getDefault().getProjectDescriptionManager().addCProjectDescriptionListener(this, |
40 supportedNatureIds.add(CCProjectNature.CC_NATURE_ID); |
47 CProjectDescriptionEvent.DATA_APPLIED | CProjectDescriptionEvent.LOADED); |
41 } |
|
42 |
|
43 public List<String> getProjectNatures() { |
|
44 return supportedNatureIds; |
48 } |
45 } |
49 |
46 |
50 public void resourceChanged(IResourceChangeEvent event) { |
47 public List<Executable> getExecutables(IProject project, IProgressMonitor monitor) { |
|
48 List<Executable> executables = new ArrayList<Executable>(); |
|
49 |
|
50 ICProject cproject = CModelManager.getDefault().create(project); |
|
51 try { |
|
52 IBinary[] binaries = cproject.getBinaryContainer().getBinaries(); |
51 |
53 |
52 // refresh when projects are opened or closed. note that deleted |
54 SubMonitor progress = SubMonitor.convert(monitor, binaries.length); |
53 // projects are handled later |
55 |
54 // in this method. new projects are handled in handleEvent. |
56 for (IBinary binary : binaries) { |
55 // resource changed events always start at the workspace root, so |
57 if (progress.isCanceled()) { |
56 // projects |
58 break; |
57 // are the next level down |
|
58 IResourceDelta[] projects = event.getDelta().getAffectedChildren(); |
|
59 for (IResourceDelta projectDelta : projects) { |
|
60 if ((projectDelta.getFlags() & IResourceDelta.OPEN) != 0) { |
|
61 if (projectDelta.getKind() == IResourceDelta.CHANGED) { |
|
62 // project was opened or closed |
|
63 ExecutablesManager.getExecutablesManager().scheduleRefresh(this, 0); |
|
64 return; |
|
65 } |
59 } |
|
60 |
|
61 if (binary.isExecutable() || binary.isSharedLib()) { |
|
62 IPath exePath = binary.getResource().getLocation(); |
|
63 if (exePath == null) |
|
64 exePath = binary.getPath(); |
|
65 executables.add(new Executable(exePath, project, binary.getResource())); |
|
66 } |
|
67 |
|
68 progress.worked(1); |
66 } |
69 } |
|
70 } catch (CModelException e) { |
67 } |
71 } |
68 |
72 |
69 try { |
73 return executables; |
70 final StandardExecutableProvider provider = this; |
|
71 event.getDelta().accept(new IResourceDeltaVisitor() { |
|
72 |
|
73 public boolean visit(IResourceDelta delta) throws CoreException { |
|
74 if (delta.getKind() == IResourceDelta.ADDED || delta.getKind() == IResourceDelta.REMOVED) { |
|
75 IResource deltaResource = delta.getResource(); |
|
76 if (deltaResource != null) { |
|
77 boolean refresh = false; |
|
78 if (delta.getKind() == IResourceDelta.REMOVED && deltaResource instanceof IProject) { |
|
79 // project deleted |
|
80 refresh = true; |
|
81 } else { |
|
82 // see if a binary has been added/removed |
|
83 IPath resourcePath = delta.getResource().getLocation(); |
|
84 if (resourcePath != null && Executable.isExecutableFile(resourcePath)) { |
|
85 refresh = true; |
|
86 } |
|
87 } |
|
88 if (refresh) { |
|
89 ExecutablesManager.getExecutablesManager().scheduleRefresh(provider, 0); |
|
90 return false; |
|
91 } |
|
92 } |
|
93 } |
|
94 return true; |
|
95 } |
|
96 }); |
|
97 } catch (CoreException e) { |
|
98 } |
|
99 } |
|
100 |
|
101 public void handleEvent(CProjectDescriptionEvent event) { |
|
102 // this handles the cases where the active build configuration changes, |
|
103 // and when new |
|
104 // projects are created. |
|
105 boolean refresh = false; |
|
106 |
|
107 int eventType = event.getEventType(); |
|
108 |
|
109 if (eventType == CProjectDescriptionEvent.DATA_APPLIED) { |
|
110 // see if the active build config has changed |
|
111 ICProjectDescription newDesc = event.getNewCProjectDescription(); |
|
112 ICProjectDescription oldDesc = event.getOldCProjectDescription(); |
|
113 if (oldDesc != null && newDesc != null) { |
|
114 String newConfigName = newDesc.getActiveConfiguration().getName(); |
|
115 String oldConfigName = oldDesc.getActiveConfiguration().getName(); |
|
116 refresh = (!newConfigName.equals(oldConfigName)); |
|
117 } else if (newDesc != null && oldDesc == null) { |
|
118 // project just created |
|
119 refresh = true; |
|
120 } |
|
121 } |
|
122 |
|
123 if (refresh) { |
|
124 ExecutablesManager.getExecutablesManager().scheduleRefresh(this, 0); |
|
125 } |
|
126 } |
|
127 |
|
128 public Executable[] getExecutables(IProgressMonitor monitor) { |
|
129 synchronized (executables) { |
|
130 executables.clear(); |
|
131 |
|
132 IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); |
|
133 IProject[] projects = root.getProjects(); |
|
134 |
|
135 monitor.beginTask("Checking C/C++ Projects", projects.length); |
|
136 |
|
137 for (IProject project : projects) { |
|
138 |
|
139 if (monitor.isCanceled()) |
|
140 break; |
|
141 |
|
142 try { |
|
143 if (CoreModel.hasCNature(project)) { |
|
144 CModelManager manager = CModelManager.getDefault(); |
|
145 ICProject cproject = manager.create(project); |
|
146 try { |
|
147 IBinary[] binaries = cproject.getBinaryContainer().getBinaries(); |
|
148 for (IBinary binary : binaries) { |
|
149 if (binary.isExecutable() || binary.isSharedLib()) { |
|
150 IPath exePath = binary.getResource().getLocation(); |
|
151 if (exePath == null) |
|
152 exePath = binary.getPath(); |
|
153 Executable exe = new Executable(exePath, project, binary.getResource()); |
|
154 executables.add(exe); |
|
155 } |
|
156 } |
|
157 } catch (CModelException e) { |
|
158 } |
|
159 } |
|
160 } catch (Exception e) { |
|
161 DebugPlugin.log( e ); |
|
162 } |
|
163 monitor.worked(1); |
|
164 } |
|
165 monitor.done(); |
|
166 } |
|
167 return executables.toArray(new Executable[executables.size()]); |
|
168 } |
|
169 |
|
170 public int getPriority() { |
|
171 return NORMAL_PRIORITY; |
|
172 } |
74 } |
173 |
75 |
174 public IStatus removeExecutable(Executable executable, IProgressMonitor monitor) { |
76 public IStatus removeExecutable(Executable executable, IProgressMonitor monitor) { |
175 IResource exeResource = executable.getResource(); |
77 IResource exeResource = executable.getResource(); |
176 if (exeResource != null) |
78 if (exeResource != null) { |
177 { |
79 try { |
178 if (exeResource.isLinked()) |
80 exeResource.delete(true, monitor); |
179 { |
81 } catch (CoreException e) { |
180 try { |
82 DebugPlugin.log( e ); |
181 exeResource.delete(true, monitor); |
|
182 } catch (CoreException e) { |
|
183 DebugPlugin.log( e ); |
|
184 } |
|
185 } |
83 } |
186 return Status.OK_STATUS; |
84 return Status.OK_STATUS; |
187 } |
85 } |
188 return new Status(IStatus.WARNING, CDebugCorePlugin.PLUGIN_ID, "Can't remove " + executable.getName() + ": it is built by project \"" + executable.getProject().getName() + "\""); |
86 return new Status(IStatus.WARNING, CDebugCorePlugin.PLUGIN_ID, "Can't remove " + executable.getName() + ": it is built by project \"" + executable.getProject().getName() + "\""); |
189 } |
87 } |
190 |
|
191 } |
88 } |