Lines 17-64
Link Here
|
17 |
import org.eclipse.core.resources.IProject; |
17 |
import org.eclipse.core.resources.IProject; |
18 |
import org.eclipse.core.resources.IResource; |
18 |
import org.eclipse.core.resources.IResource; |
19 |
import org.eclipse.core.resources.IResourceDelta; |
19 |
import org.eclipse.core.resources.IResourceDelta; |
|
|
20 |
import org.eclipse.core.resources.IResourceDeltaVisitor; |
20 |
import org.eclipse.core.resources.IncrementalProjectBuilder; |
21 |
import org.eclipse.core.resources.IncrementalProjectBuilder; |
21 |
import org.eclipse.core.runtime.CoreException; |
22 |
import org.eclipse.core.runtime.CoreException; |
|
|
23 |
import org.eclipse.core.runtime.IPath; |
22 |
import org.eclipse.core.runtime.IProgressMonitor; |
24 |
import org.eclipse.core.runtime.IProgressMonitor; |
|
|
25 |
import org.eclipse.core.runtime.Path; |
26 |
import org.eclipse.core.runtime.Platform; |
23 |
import org.eclipse.osgi.util.NLS; |
27 |
import org.eclipse.osgi.util.NLS; |
|
|
28 |
import org.eclipse.pde.core.plugin.IPluginModelBase; |
29 |
import org.eclipse.pde.core.plugin.PluginRegistry; |
30 |
import org.eclipse.pde.internal.core.ICoreConstants; |
24 |
import org.eclipse.pde.internal.core.PDECore; |
31 |
import org.eclipse.pde.internal.core.PDECore; |
25 |
import org.eclipse.pde.internal.core.WorkspaceModelManager; |
|
|
26 |
import org.eclipse.pde.internal.core.PDECoreMessages; |
32 |
import org.eclipse.pde.internal.core.PDECoreMessages; |
|
|
33 |
import org.eclipse.pde.internal.core.WorkspaceModelManager; |
34 |
import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase; |
27 |
import org.osgi.framework.Bundle; |
35 |
import org.osgi.framework.Bundle; |
28 |
|
36 |
|
29 |
public class ManifestConsistencyChecker extends IncrementalProjectBuilder { |
37 |
public class ManifestConsistencyChecker extends IncrementalProjectBuilder { |
30 |
protected IProject[] build(int kind, Map args, IProgressMonitor monitor) |
38 |
|
31 |
throws CoreException { |
39 |
private int MANIFEST = 0x1; |
|
|
40 |
private int EXTENSIONS = 0x2; |
41 |
private int BUILD = 0x4; |
42 |
|
43 |
private static boolean DEBUG = false; |
44 |
private static IProject[] EMPTY_LIST = new IProject[0]; |
45 |
|
46 |
static { |
47 |
DEBUG = PDECore.getDefault().isDebugging() |
48 |
&& "true".equals(Platform.getDebugOption("org.eclipse.pde.core/validation")); //$NON-NLS-1$ //$NON-NLS-2$ |
49 |
} |
50 |
|
51 |
private SelfVisitor fSelfVisitor = new SelfVisitor(); |
52 |
|
53 |
private ClassChangeVisitor fClassFileVisitor = new ClassChangeVisitor(); |
54 |
|
55 |
class ClassChangeVisitor implements IResourceDeltaVisitor { |
56 |
boolean hasChanged = false; |
57 |
boolean veto = false; |
58 |
|
59 |
public boolean visit(IResourceDelta delta) throws CoreException { |
60 |
if (delta != null && !veto) { |
61 |
int kind = delta.getKind(); |
62 |
if (kind == IResourceDelta.CHANGED) { |
63 |
IResource resource = delta.getResource(); |
64 |
if (resource instanceof IFile) { |
65 |
String extension = resource.getFileExtension(); |
66 |
// do nothing if a java file has changed. |
67 |
if ("java".equals(extension)) { //$NON-NLS-1$ |
68 |
veto = true; |
69 |
} else if ("class".equals(extension) && !hasChanged) { //$NON-NLS-1$ |
70 |
// only interested in .class file changes |
71 |
hasChanged = true; |
72 |
} |
73 |
} |
74 |
return !veto; |
75 |
} |
76 |
} |
77 |
return false; |
78 |
} |
79 |
|
80 |
public void reset() { |
81 |
veto = false; |
82 |
hasChanged = false; |
83 |
} |
32 |
|
84 |
|
33 |
if (PDECore.getDefault().getBundle().getState() != Bundle.ACTIVE || monitor.isCanceled()) |
85 |
public boolean hasChanged() { |
34 |
return new IProject[0]; |
86 |
return hasChanged && !veto; |
|
|
87 |
} |
88 |
|
89 |
} |
90 |
|
91 |
class SelfVisitor implements IResourceDeltaVisitor { |
92 |
int type = 0; |
93 |
public boolean visit(IResourceDelta delta) throws CoreException { |
94 |
if (delta != null && type != (MANIFEST|EXTENSIONS|BUILD)) { |
95 |
int kind = delta.getKind(); |
96 |
if (kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED) { |
97 |
type = MANIFEST | EXTENSIONS | BUILD; |
98 |
if (DEBUG) { |
99 |
System.out.print("Needs to rebuild project [" + getProject().getName() + "]: "); //$NON-NLS-1$ //$NON-NLS-2$ |
100 |
System.out.print(delta.getResource().getProjectRelativePath().toString()); |
101 |
System.out.print(" - "); //$NON-NLS-1$ |
102 |
System.out.println(kind == IResourceDelta.ADDED ? "added" : "removed"); //$NON-NLS-1$ //$NON-NLS-2$ |
103 |
} |
104 |
return false; |
105 |
} |
106 |
IResource resource = delta.getResource(); |
107 |
if (resource instanceof IFile) { |
108 |
String name = resource.getName(); |
109 |
IPath path = resource.getProjectRelativePath(); |
110 |
if (isLocalizationFile(resource)) { |
111 |
type |= MANIFEST | EXTENSIONS; |
112 |
if (DEBUG) { |
113 |
System.out.print("Needs to rebuild manifest and extensions in project [" + getProject().getName() + "]: "); //$NON-NLS-1$ //$NON-NLS-2$ |
114 |
System.out.print(delta.getResource().getProjectRelativePath().toString()); |
115 |
System.out.println(" - changed"); //$NON-NLS-1$ |
116 |
} |
117 |
} else if (path.equals(ICoreConstants.MANIFEST_PATH)) { |
118 |
type |= MANIFEST | EXTENSIONS | BUILD; |
119 |
if (DEBUG) { |
120 |
System.out.print("Needs to rebuild project [" + getProject().getName() + "]: "); //$NON-NLS-1$ //$NON-NLS-2$ |
121 |
System.out.print(delta.getResource().getProjectRelativePath().toString()); |
122 |
System.out.println(" - changed"); //$NON-NLS-1$ |
123 |
} |
124 |
} else if (name.endsWith(".exsd") || path.equals(ICoreConstants.PLUGIN_PATH) || path.equals(ICoreConstants.FRAGMENT_PATH)) { //$NON-NLS-1$ |
125 |
type |= EXTENSIONS; |
126 |
if (DEBUG) { |
127 |
System.out.print("Needs to rebuild extensions in project [" + getProject().getName() + "]: "); //$NON-NLS-1$ //$NON-NLS-2$ |
128 |
System.out.print(delta.getResource().getProjectRelativePath().toString()); |
129 |
System.out.println(" - changed"); //$NON-NLS-1$ |
130 |
} |
131 |
} else if (path.equals(ICoreConstants.BUILD_PROPERTIES_PATH)) { |
132 |
type |= BUILD; |
133 |
if (DEBUG) { |
134 |
System.out.print("Needs to rebuild build.properties in project [" + getProject().getName() + "]: "); //$NON-NLS-1$ //$NON-NLS-2$ |
135 |
System.out.print(delta.getResource().getProjectRelativePath().toString()); |
136 |
System.out.println(" - changed"); //$NON-NLS-1$ |
137 |
} |
138 |
} |
139 |
} |
140 |
} |
141 |
return type != (MANIFEST|EXTENSIONS|BUILD); |
142 |
} |
143 |
public int getType() { |
144 |
return type; |
145 |
} |
146 |
public void reset() { |
147 |
type = 0; |
148 |
} |
149 |
} |
150 |
|
151 |
private boolean isLocalizationFile(IResource file) { |
152 |
IPluginModelBase model = PluginRegistry.findModel(getProject()); |
153 |
String localization = null; |
154 |
if (model instanceof IBundlePluginModelBase) { |
155 |
localization = ((IBundlePluginModelBase)model).getBundleLocalization(); |
156 |
} else { |
157 |
localization = "plugin"; //$NON-NLS-1$ |
158 |
} |
159 |
if (localization != null) |
160 |
return file.getProjectRelativePath().equals(new Path(localization + ".properties")); //$NON-NLS-1$ |
161 |
return false; |
162 |
} |
163 |
|
164 |
protected IProject[] build(int kind, Map args, IProgressMonitor monitor) |
165 |
throws CoreException { |
166 |
if (PDECore.getDefault().getBundle().getState() != Bundle.ACTIVE |
167 |
|| monitor.isCanceled()) |
168 |
return EMPTY_LIST; |
35 |
|
169 |
|
36 |
IProject project = getProject(); |
170 |
IProject project = getProject(); |
37 |
IResourceDelta delta = getDelta(project); |
171 |
if (!WorkspaceModelManager.isBinaryProject(project)) { |
38 |
boolean shouldBuild = delta == null || delta.getAffectedChildren().length > 0; |
172 |
int type = getDeltaType(project); |
39 |
if (shouldBuild && !WorkspaceModelManager.isBinaryProject(project)) |
173 |
if (type != 0) { |
40 |
checkThisProject(monitor); |
174 |
validateProject(type, monitor); |
41 |
return new IProject[0]; |
175 |
} |
|
|
176 |
} |
177 |
return EMPTY_LIST; |
42 |
} |
178 |
} |
|
|
179 |
|
180 |
private int getDeltaType(IProject project) throws CoreException { |
181 |
IResourceDelta delta = getDelta(project); |
43 |
|
182 |
|
44 |
private void checkThisProject(IProgressMonitor monitor) { |
183 |
// always do a build of the project if a full build or an unspecified change has occurred |
45 |
IProject project = getProject(); |
184 |
if (delta == null) { |
46 |
IFile file = project.getFile("plugin.xml"); //$NON-NLS-1$ |
185 |
if (DEBUG) { |
47 |
if (!file.exists()) |
186 |
System.out.println("Project [" + getProject().getName() + "] - full build"); //$NON-NLS-1$ //$NON-NLS-2$ |
48 |
file = project.getFile("fragment.xml"); //$NON-NLS-1$ |
187 |
} |
49 |
|
188 |
return MANIFEST|EXTENSIONS|BUILD; |
50 |
if (file.exists()) { |
189 |
} |
51 |
checkFile(file, monitor); |
190 |
|
52 |
} else { |
191 |
// the project has been "touched" by PluginRebuilder to indicate |
53 |
IFile manifestFile = project.getFile("META-INF/MANIFEST.MF"); //$NON-NLS-1$ |
192 |
// that one of the dependencies (either in the target or workspace) |
54 |
if (manifestFile.exists()) |
193 |
// has changed and a StateDelta was fired |
55 |
checkManifestFile(manifestFile, monitor); |
194 |
if (Boolean.TRUE.equals(project.getSessionProperty(PDECore.TOUCH_PROJECT))) { |
|
|
195 |
project.setSessionProperty(PDECore.TOUCH_PROJECT, null); |
196 |
if (DEBUG) { |
197 |
System.out.println("Dependencies Changed: Project [" + getProject().getName() + "] - full build"); //$NON-NLS-1$ //$NON-NLS-2$ |
198 |
} |
199 |
return MANIFEST|EXTENSIONS|BUILD; |
200 |
} |
201 |
|
202 |
// check if any "significant" files have been changed/added/removed |
203 |
// and build a subset or all manifest files accordingly |
204 |
fSelfVisitor.reset(); |
205 |
delta.accept(fSelfVisitor); |
206 |
int type = fSelfVisitor.getType(); |
207 |
|
208 |
// catch anything we have missed |
209 |
// For example, upon startup, when target has changed since shutdown |
210 |
// we depend on class file changes in the project that have resulted |
211 |
// from the Java compiler detecting the change in classpath. |
212 |
// Note that we do NOT validate anything if there was a change |
213 |
// in a .java file. A change in a .java file means that the user has modified |
214 |
// its content and this does not warrant a rebuild of manifest files. |
215 |
if ((type & MANIFEST|EXTENSIONS) != (MANIFEST|EXTENSIONS)) { |
216 |
fClassFileVisitor.reset(); |
217 |
delta.accept(fClassFileVisitor); |
218 |
if (fClassFileVisitor.hasChanged()) { |
219 |
type |= MANIFEST|EXTENSIONS; |
220 |
if (DEBUG) { |
221 |
System.out.println("Class files changed due to dependency changes: Project [" + getProject().getName() + "] - rebuild manifest files"); //$NON-NLS-1$ //$NON-NLS-2$ |
222 |
} |
223 |
} |
224 |
} |
225 |
return type; |
226 |
} |
227 |
|
228 |
private void validateProject(int type, IProgressMonitor monitor) { |
229 |
if ((type & MANIFEST|EXTENSIONS) != 0) { |
230 |
IProject project = getProject(); |
231 |
IFile file = project.getFile("plugin.xml"); //$NON-NLS-1$ |
232 |
if (!file.exists()) |
233 |
file = project.getFile("fragment.xml"); //$NON-NLS-1$ |
234 |
|
235 |
if (file.exists()) { |
236 |
validateFiles(file, type, monitor); |
237 |
} else if ((type & MANIFEST) != 0){ |
238 |
IFile manifestFile = project.getFile("META-INF/MANIFEST.MF"); //$NON-NLS-1$ |
239 |
if (manifestFile.exists()) |
240 |
validateManifestFile(manifestFile, monitor); |
241 |
} |
56 |
} |
242 |
} |
57 |
checkProjectDescription(monitor); |
243 |
if ((type & BUILD) != 0) |
58 |
checkBuildProperties(monitor); |
244 |
validateBuildProperties(monitor); |
59 |
} |
245 |
} |
60 |
|
246 |
|
61 |
private void checkManifestFile(IFile file, IProgressMonitor monitor) { |
247 |
private void validateManifestFile(IFile file, IProgressMonitor monitor) { |
62 |
if (monitor.isCanceled()) |
248 |
if (monitor.isCanceled()) |
63 |
return; |
249 |
return; |
64 |
String message = NLS.bind(PDECoreMessages.Builders_verifying, file.getFullPath().toString()); |
250 |
String message = NLS.bind(PDECoreMessages.Builders_verifying, file.getFullPath().toString()); |
Lines 72-78
Link Here
|
72 |
monitor.done(); |
258 |
monitor.done(); |
73 |
} |
259 |
} |
74 |
|
260 |
|
75 |
private void checkFile(IFile file, IProgressMonitor monitor) { |
261 |
private void validateFiles(IFile file, int type, IProgressMonitor monitor) { |
76 |
if (monitor.isCanceled()) |
262 |
if (monitor.isCanceled()) |
77 |
return; |
263 |
return; |
78 |
String message = NLS.bind(PDECoreMessages.Builders_verifying, file.getFullPath().toString()); |
264 |
String message = NLS.bind(PDECoreMessages.Builders_verifying, file.getFullPath().toString()); |
Lines 82-93
Link Here
|
82 |
XMLErrorReporter reporter = null; |
268 |
XMLErrorReporter reporter = null; |
83 |
BundleErrorReporter bundleReporter = null; |
269 |
BundleErrorReporter bundleReporter = null; |
84 |
if (bundleManifest.exists()) { |
270 |
if (bundleManifest.exists()) { |
85 |
reporter = new ExtensionsErrorReporter(file); |
271 |
if ((type & EXTENSIONS) != 0) |
86 |
bundleReporter = new BundleErrorReporter(bundleManifest); |
272 |
reporter = new ExtensionsErrorReporter(file); |
87 |
} else if (file.getName().equals("plugin.xml")) { //$NON-NLS-1$ |
273 |
if ((type & MANIFEST) != 0) |
88 |
reporter = new PluginErrorReporter(file); |
274 |
bundleReporter = new BundleErrorReporter(bundleManifest); |
89 |
} else if (file.getName().equals("fragment.xml")){ //$NON-NLS-1$ |
275 |
} else if ((type & MANIFEST) != 0 || (type & EXTENSIONS) != 0){ |
90 |
reporter = new FragmentErrorReporter(file); |
276 |
if (file.getName().equals("plugin.xml")) { //$NON-NLS-1$ |
|
|
277 |
reporter = new PluginErrorReporter(file); |
278 |
} else if (file.getName().equals("fragment.xml")){ //$NON-NLS-1$ |
279 |
reporter = new FragmentErrorReporter(file); |
280 |
} |
91 |
} |
281 |
} |
92 |
if (reporter != null) { |
282 |
if (reporter != null) { |
93 |
DefaultSAXParser.parse(file, reporter); |
283 |
DefaultSAXParser.parse(file, reporter); |
Lines 101-133
Link Here
|
101 |
monitor.done(); |
291 |
monitor.done(); |
102 |
} |
292 |
} |
103 |
|
293 |
|
104 |
private void checkProjectDescription(IProgressMonitor monitor) { |
294 |
private void validateBuildProperties(IProgressMonitor monitor) { |
105 |
if (monitor.isCanceled()) |
|
|
106 |
return; |
107 |
monitor.subTask(NLS.bind(PDECoreMessages.Builders_verifying, ".project")); //$NON-NLS-1$ |
108 |
IProject project = getProject(); |
109 |
IFile file = project.getFile(".project"); //$NON-NLS-1$ |
110 |
if (!file.exists()) |
111 |
return; |
112 |
try { |
113 |
file.deleteMarkers(PDEMarkerFactory.MARKER_ID, true, IResource.DEPTH_ZERO); |
114 |
IProject[] refProjects = project.getDescription().getReferencedProjects(); |
115 |
if (refProjects.length > 0) { |
116 |
try { |
117 |
IMarker marker = new PDEMarkerFactory().createMarker(file, PDEMarkerFactory.M_PROJECT_BUILD_ORDER_ENTRIES, PDEMarkerFactory.CAT_OTHER); |
118 |
marker.setAttribute(IMarker.MESSAGE, PDECoreMessages.ManifestConsistencyChecker_projectCheck); |
119 |
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING); |
120 |
marker.setAttribute(IMarker.LINE_NUMBER, 5); |
121 |
} catch (CoreException e) { |
122 |
PDECore.logException(e); |
123 |
} |
124 |
} |
125 |
} catch (CoreException e) { |
126 |
} |
127 |
monitor.done(); |
128 |
} |
129 |
|
130 |
private void checkBuildProperties(IProgressMonitor monitor) { |
131 |
if (monitor.isCanceled()) |
295 |
if (monitor.isCanceled()) |
132 |
return; |
296 |
return; |
133 |
IProject project = getProject(); |
297 |
IProject project = getProject(); |
Lines 153-156
Link Here
|
153 |
ber.validateContent(monitor); |
317 |
ber.validateContent(monitor); |
154 |
} |
318 |
} |
155 |
} |
319 |
} |
|
|
320 |
|
156 |
} |
321 |
} |