Lines 10-16
Link Here
|
10 |
*******************************************************************************/ |
10 |
*******************************************************************************/ |
11 |
package org.eclipse.releng.tools.pomversion; |
11 |
package org.eclipse.releng.tools.pomversion; |
12 |
|
12 |
|
|
|
13 |
import java.io.IOException; |
14 |
import java.util.HashMap; |
13 |
import java.util.Stack; |
15 |
import java.util.Stack; |
|
|
16 |
import java.util.jar.JarFile; |
17 |
import java.util.jar.Manifest; |
14 |
|
18 |
|
15 |
import javax.xml.parsers.SAXParser; |
19 |
import javax.xml.parsers.SAXParser; |
16 |
import javax.xml.parsers.SAXParserFactory; |
20 |
import javax.xml.parsers.SAXParserFactory; |
Lines 21-37
Link Here
|
21 |
import org.eclipse.core.filebuffers.LocationKind; |
25 |
import org.eclipse.core.filebuffers.LocationKind; |
22 |
import org.eclipse.core.resources.IFile; |
26 |
import org.eclipse.core.resources.IFile; |
23 |
import org.eclipse.core.resources.IMarker; |
27 |
import org.eclipse.core.resources.IMarker; |
24 |
import org.eclipse.core.resources.ProjectScope; |
28 |
import org.eclipse.core.resources.IProject; |
|
|
29 |
import org.eclipse.core.resources.IResource; |
30 |
import org.eclipse.core.resources.IResourceChangeEvent; |
31 |
import org.eclipse.core.resources.IResourceChangeListener; |
32 |
import org.eclipse.core.resources.IResourceDelta; |
33 |
import org.eclipse.core.resources.IResourceDeltaVisitor; |
34 |
import org.eclipse.core.resources.IWorkspaceRoot; |
35 |
import org.eclipse.core.resources.ResourcesPlugin; |
25 |
import org.eclipse.core.runtime.CoreException; |
36 |
import org.eclipse.core.runtime.CoreException; |
26 |
import org.eclipse.core.runtime.IProgressMonitor; |
37 |
import org.eclipse.core.runtime.IPath; |
27 |
import org.eclipse.core.runtime.Platform; |
38 |
import org.eclipse.core.runtime.Path; |
28 |
import org.eclipse.core.runtime.SubMonitor; |
39 |
import org.eclipse.core.runtime.preferences.IEclipsePreferences; |
29 |
import org.eclipse.core.runtime.preferences.IPreferencesService; |
40 |
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; |
30 |
import org.eclipse.core.runtime.preferences.IScopeContext; |
|
|
31 |
import org.eclipse.jface.text.BadLocationException; |
41 |
import org.eclipse.jface.text.BadLocationException; |
32 |
import org.eclipse.jface.text.IDocument; |
42 |
import org.eclipse.jface.text.IDocument; |
33 |
import org.eclipse.osgi.util.NLS; |
43 |
import org.eclipse.osgi.util.NLS; |
34 |
import org.eclipse.releng.tools.RelEngPlugin; |
44 |
import org.eclipse.releng.tools.RelEngPlugin; |
|
|
45 |
import org.eclipse.ui.texteditor.MarkerUtilities; |
35 |
import org.osgi.framework.Version; |
46 |
import org.osgi.framework.Version; |
36 |
import org.xml.sax.Attributes; |
47 |
import org.xml.sax.Attributes; |
37 |
import org.xml.sax.Locator; |
48 |
import org.xml.sax.Locator; |
Lines 43-129
Link Here
|
43 |
* version specified in pom.xml matches the bundle version. |
54 |
* version specified in pom.xml matches the bundle version. |
44 |
* |
55 |
* |
45 |
*/ |
56 |
*/ |
46 |
public class PomVersionErrorReporter { |
57 |
public class PomVersionErrorReporter implements IResourceChangeListener, IEclipsePreferences.IPreferenceChangeListener { |
47 |
|
58 |
|
48 |
private static final String ELEMENT_PROJECT = "project"; //$NON-NLS-1$ |
59 |
class PomResourceDeltaVisitor implements IResourceDeltaVisitor { |
49 |
private static final String ELEMENT_VERSION = "version"; //$NON-NLS-1$ |
|
|
50 |
private static final String SNAPSHOT_SUFFIX = "-SNAPSHOT"; //$NON-NLS-1$ |
51 |
|
60 |
|
52 |
private SAXParserFactory parserFactory = SAXParserFactory.newInstance(); |
61 |
public boolean visit(IResourceDelta delta) { |
53 |
private String pomVersionSeverity; |
62 |
if (delta != null) { |
|
|
63 |
IResource resource = delta.getResource(); |
64 |
switch(resource.getType()) { |
65 |
case IResource.PROJECT: { |
66 |
//Should we not care about non-plugin projects? |
67 |
IProject project = (IProject) resource; |
68 |
try { |
69 |
if(project.getDescription().hasNature("org.eclipse.pde.PluginNature")) { //$NON-NLS-1$ |
70 |
if((delta.getFlags() & IResourceDelta.OPEN) > 0) { |
71 |
validate(project); |
72 |
return false; |
73 |
} |
74 |
return true; |
75 |
} |
76 |
} |
77 |
catch(CoreException ce) { |
78 |
RelEngPlugin.log(ce); |
79 |
} |
80 |
return false; |
81 |
} |
82 |
case IResource.ROOT: |
83 |
case IResource.FOLDER: { |
84 |
return true; |
85 |
} |
86 |
case IResource.FILE: { |
87 |
switch(delta.getKind()) { |
88 |
case IResourceDelta.REMOVED: { |
89 |
//if manifest removed, clean up markers |
90 |
if(delta.getProjectRelativePath().equals(MANIFEST_PATH)) { |
91 |
//manifest content changed |
92 |
IProject p = resource.getProject(); |
93 |
if(p.isAccessible()) { |
94 |
cleanMarkers(p); |
95 |
} |
96 |
} |
97 |
break; |
98 |
} |
99 |
case IResourceDelta.ADDED: { |
100 |
//if the POM or manifest has been added scan them |
101 |
if(delta.getProjectRelativePath().equals(MANIFEST_PATH) || |
102 |
delta.getProjectRelativePath().equals(POM_PATH)) { |
103 |
validate(resource.getProject()); |
104 |
} |
105 |
break; |
106 |
} |
107 |
case IResourceDelta.CHANGED: { |
108 |
//if the content has changed clean + scan |
109 |
if((delta.getFlags() & IResourceDelta.CONTENT) > 0) { |
110 |
if(delta.getProjectRelativePath().equals(MANIFEST_PATH) || |
111 |
delta.getProjectRelativePath().equals(POM_PATH)) { |
112 |
validate(resource.getProject()); |
113 |
} |
114 |
} |
115 |
break; |
116 |
} |
117 |
default: { |
118 |
break; |
119 |
} |
120 |
} |
121 |
return false; |
122 |
} |
123 |
} |
124 |
} |
125 |
return false; |
126 |
} |
127 |
} |
54 |
|
128 |
|
55 |
private IFile manifestFile; |
129 |
/** |
56 |
private IFile pomFile; |
130 |
* XML parsing handler to check the POM version infos |
57 |
|
131 |
*/ |
58 |
public PomVersionErrorReporter(IFile manifest, IFile pom) { |
|
|
59 |
manifestFile = manifest; |
60 |
pomFile = pom; |
61 |
} |
62 |
|
63 |
protected void validate(IProgressMonitor monitor) { |
64 |
SubMonitor subMon = SubMonitor.convert(monitor, 10); |
65 |
try { |
66 |
if (subMon.isCanceled()) { |
67 |
return; |
68 |
} |
69 |
if (!manifestFile.exists() || !pomFile.exists()){ |
70 |
return; |
71 |
} |
72 |
|
73 |
IPreferencesService service = Platform.getPreferencesService(); |
74 |
pomVersionSeverity = service.getString(RelEngPlugin.ID, IPomVersionConstants.POM_VERSION_ERROR_LEVEL, IPomVersionConstants.VALUE_IGNORE, new IScopeContext[] {new ProjectScope(manifestFile.getProject())}); |
75 |
if (pomVersionSeverity == IPomVersionConstants.VALUE_IGNORE) { |
76 |
return; |
77 |
} |
78 |
|
79 |
// Get the manifest version |
80 |
Version bundleVersion = Version.emptyVersion; |
81 |
|
82 |
// Compare it to the pom file version |
83 |
try { |
84 |
SAXParser parser = parserFactory.newSAXParser(); |
85 |
PomVersionHandler handler = new PomVersionHandler(pomFile, bundleVersion); |
86 |
parser.parse(pomFile.getContents(), handler); |
87 |
} catch (Exception e1) { |
88 |
// Ignored, if there is a problem with the pom file don't create a marker |
89 |
} |
90 |
|
91 |
} finally { |
92 |
subMon.done(); |
93 |
if (monitor != null) { |
94 |
monitor.done(); |
95 |
} |
96 |
} |
97 |
|
98 |
} |
99 |
|
100 |
private void reportMarker(String message, int lineNumber, int charStart, int charEnd, String correctedVersion) { |
101 |
try { |
102 |
IMarker marker = pomFile.createMarker(IPomVersionConstants.PROBLEM_MARKER_TYPE); |
103 |
marker.setAttribute(IMarker.MESSAGE, message); |
104 |
if (pomVersionSeverity != null && pomVersionSeverity.equals(IPomVersionConstants.VALUE_WARNING)){ |
105 |
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING); |
106 |
} else { |
107 |
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); |
108 |
} |
109 |
if (lineNumber == -1) |
110 |
lineNumber = 1; |
111 |
marker.setAttribute(IMarker.LINE_NUMBER, lineNumber); |
112 |
marker.setAttribute(IMarker.CHAR_START, charStart); |
113 |
marker.setAttribute(IMarker.CHAR_END, charEnd); |
114 |
marker.setAttribute(IPomVersionConstants.POM_CORRECT_VERSION, correctedVersion); |
115 |
} catch (CoreException e){ |
116 |
RelEngPlugin.log(e); |
117 |
} |
118 |
} |
119 |
|
120 |
class PomVersionHandler extends DefaultHandler { |
132 |
class PomVersionHandler extends DefaultHandler { |
121 |
private Version bundleVersion; |
133 |
private Version bundleVersion; |
122 |
private Stack elements = new Stack(); |
134 |
private Stack elements = new Stack(); |
123 |
private boolean checkVersion = false; |
135 |
private boolean checkVersion = false; |
124 |
private Locator locator; |
136 |
private Locator locator; |
|
|
137 |
IFile pom = null; |
138 |
String severity = null; |
125 |
|
139 |
|
126 |
public PomVersionHandler(IFile file, Version bundleVersion) { |
140 |
public PomVersionHandler(IFile file, Version bundleVersion, String pref) { |
|
|
141 |
pom = file; |
142 |
severity = pref; |
127 |
this.bundleVersion = bundleVersion; |
143 |
this.bundleVersion = bundleVersion; |
128 |
} |
144 |
} |
129 |
|
145 |
|
Lines 149-154
Link Here
|
149 |
checkVersion = false; |
165 |
checkVersion = false; |
150 |
// Compare the versions |
166 |
// Compare the versions |
151 |
String versionString = new String(ch, start, length); |
167 |
String versionString = new String(ch, start, length); |
|
|
168 |
String origVer = versionString; |
152 |
try { |
169 |
try { |
153 |
// Remove snapshot suffix |
170 |
// Remove snapshot suffix |
154 |
int index = versionString.indexOf(SNAPSHOT_SUFFIX); |
171 |
int index = versionString.indexOf(SNAPSHOT_SUFFIX); |
Lines 168-178
Link Here
|
168 |
|
185 |
|
169 |
try { |
186 |
try { |
170 |
// Need to create a document to calculate the markers charstart and charend |
187 |
// Need to create a document to calculate the markers charstart and charend |
171 |
IDocument doc = createDocument(pomFile); |
188 |
IDocument doc = createDocument(pom); |
172 |
int offset = doc.getLineOffset(locator.getLineNumber() - 1); // locator lines start at 1 |
189 |
int lineOffset = doc.getLineOffset(locator.getLineNumber() - 1); // locator lines start at 1 |
173 |
int charEnd = offset + locator.getColumnNumber() - 1; // returns column at end of character string, columns start at 1 |
190 |
int linLength = doc.getLineLength(locator.getLineNumber() - 1); |
174 |
int charStart = charEnd - length; |
191 |
String str = doc.get(lineOffset, linLength); |
175 |
reportMarker(NLS.bind("POM artifact version {0} does not match bundle version {1}", pomVersion2.toString(), bundleVersion2.toString()), locator.getLineNumber(), charStart, charEnd, correctedVersion); |
192 |
index = str.indexOf(origVer); |
|
|
193 |
int charStart = lineOffset + index; |
194 |
int charEnd = charStart + origVer.length(); |
195 |
reportMarker(NLS.bind(Messages.PomVersionErrorReporter_pom_version_error_marker_message, pomVersion2.toString(), bundleVersion2.toString()), |
196 |
locator.getLineNumber(), |
197 |
charStart, |
198 |
charEnd, |
199 |
correctedVersion, |
200 |
pom, |
201 |
severity); |
176 |
} catch (BadLocationException e) { |
202 |
} catch (BadLocationException e) { |
177 |
RelEngPlugin.log(e); |
203 |
RelEngPlugin.log(e); |
178 |
} |
204 |
} |
Lines 184-189
Link Here
|
184 |
} |
210 |
} |
185 |
} |
211 |
} |
186 |
|
212 |
|
|
|
213 |
/** |
214 |
* Project relative path to the pom.xml file |
215 |
*/ |
216 |
public static final IPath POM_PATH = new Path("pom.xml"); //$NON-NLS-1$ |
217 |
|
218 |
/** |
219 |
* Project relative path to the manifest file. |
220 |
*/ |
221 |
public static final IPath MANIFEST_PATH = new Path(JarFile.MANIFEST_NAME); |
222 |
private static final String ELEMENT_PROJECT = "project"; //$NON-NLS-1$ |
223 |
private static final String ELEMENT_VERSION = "version"; //$NON-NLS-1$ |
224 |
private static final String SNAPSHOT_SUFFIX = "-SNAPSHOT"; //$NON-NLS-1$ |
225 |
|
226 |
|
227 |
/** |
228 |
* Clean up all markers |
229 |
* |
230 |
* @param project |
231 |
*/ |
232 |
void cleanMarkers(IResource resource) { |
233 |
try { |
234 |
resource.deleteMarkers(IPomVersionConstants.PROBLEM_MARKER_TYPE, false, IResource.DEPTH_INFINITE); |
235 |
} |
236 |
catch(CoreException e) { |
237 |
RelEngPlugin.log(e); |
238 |
} |
239 |
} |
240 |
|
241 |
/** |
242 |
* Validates the version in the Manifest.MF file against the version in the <code>pom.xml</code> file |
243 |
* |
244 |
* @param project |
245 |
* @param severity |
246 |
*/ |
247 |
public void validate(IProject project) { |
248 |
if(project == null || !project.isAccessible()) { |
249 |
return; |
250 |
} |
251 |
//clean up existing markers |
252 |
cleanMarkers(project); |
253 |
|
254 |
String severity = RelEngPlugin.getPlugin().getPreferenceStore().getString(IPomVersionConstants.POM_VERSION_ERROR_LEVEL); |
255 |
if (IPomVersionConstants.VALUE_IGNORE.equals(severity)) { |
256 |
return; |
257 |
} |
258 |
IFile manifest = project.getFile(MANIFEST_PATH); |
259 |
if(!manifest.exists()) { |
260 |
return; |
261 |
} |
262 |
IFile pom = project.getFile(POM_PATH); |
263 |
if(!pom.exists()) { |
264 |
return; |
265 |
} |
266 |
|
267 |
// Get the manifest version |
268 |
Version bundleVersion = Version.emptyVersion; |
269 |
try { |
270 |
Manifest mani = new Manifest(manifest.getContents()); |
271 |
java.util.jar.Attributes attributes = mani.getMainAttributes(); |
272 |
String ver = attributes.getValue("Bundle-Version"); //$NON-NLS-1$ |
273 |
if(ver == null) { |
274 |
return; |
275 |
} |
276 |
bundleVersion = new Version(ver); |
277 |
} catch (IOException e) { |
278 |
RelEngPlugin.log(e); |
279 |
return; |
280 |
} catch (CoreException e) { |
281 |
RelEngPlugin.log(e); |
282 |
return; |
283 |
} |
284 |
// Compare it to the POM file version |
285 |
try { |
286 |
SAXParserFactory parserFactory = SAXParserFactory.newInstance(); |
287 |
SAXParser parser = parserFactory.newSAXParser(); |
288 |
PomVersionHandler handler = new PomVersionHandler(pom, bundleVersion, severity); |
289 |
parser.parse(pom.getContents(), handler); |
290 |
} catch (Exception e1) { |
291 |
// Ignored, if there is a problem with the POM file don't create a marker |
292 |
} |
293 |
} |
294 |
|
295 |
/** |
296 |
* Creates a new POM version problem marker with the given attributes |
297 |
* @param message the message for the marker |
298 |
* @param lineNumber the line number of the problem |
299 |
* @param charStart the starting character offset |
300 |
* @param charEnd the ending character offset |
301 |
* @param correctedVersion the correct version to be inserted |
302 |
* @param pom the handle to the POM file |
303 |
* @param severity the severity of the marker to create |
304 |
*/ |
305 |
void reportMarker(String message, int lineNumber, int charStart, int charEnd, String correctedVersion, IFile pom, String severity) { |
306 |
try { |
307 |
HashMap attributes = new HashMap(); |
308 |
attributes.put(IMarker.MESSAGE, message); |
309 |
if (severity.equals(IPomVersionConstants.VALUE_WARNING)){ |
310 |
attributes.put(IMarker.SEVERITY, Integer.valueOf(IMarker.SEVERITY_WARNING)); |
311 |
} else { |
312 |
attributes.put(IMarker.SEVERITY, Integer.valueOf(IMarker.SEVERITY_ERROR)); |
313 |
} |
314 |
if (lineNumber == -1) { |
315 |
lineNumber = 1; |
316 |
} |
317 |
attributes.put(IMarker.LINE_NUMBER, Integer.valueOf(lineNumber)); |
318 |
attributes.put(IMarker.CHAR_START, Integer.valueOf(charStart)); |
319 |
attributes.put(IMarker.CHAR_END, Integer.valueOf(charEnd)); |
320 |
attributes.put(IPomVersionConstants.POM_CORRECT_VERSION, correctedVersion); |
321 |
MarkerUtilities.createMarker(pom, attributes, IPomVersionConstants.PROBLEM_MARKER_TYPE); |
322 |
} catch (CoreException e){ |
323 |
RelEngPlugin.log(e); |
324 |
} |
325 |
} |
326 |
|
327 |
/** |
328 |
* Creates a new {@link IDocument} for the given {@link IFile}. <code>null</code> |
329 |
* is returned if the {@link IFile} does not exist or the {@link ITextFileBufferManager} |
330 |
* cannot be acquired or there was an exception trying to create the {@link IDocument}. |
331 |
* |
332 |
* @param file |
333 |
* @return a new {@link IDocument} or <code>null</code> |
334 |
*/ |
187 |
protected IDocument createDocument(IFile file) { |
335 |
protected IDocument createDocument(IFile file) { |
188 |
if (!file.exists()) { |
336 |
if (!file.exists()) { |
189 |
return null; |
337 |
return null; |
Lines 203-206
Link Here
|
203 |
} |
351 |
} |
204 |
return null; |
352 |
return null; |
205 |
} |
353 |
} |
|
|
354 |
|
355 |
/* (non-Javadoc) |
356 |
* @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent) |
357 |
*/ |
358 |
public void resourceChanged(IResourceChangeEvent event) { |
359 |
IResourceDelta delta = event.getDelta(); |
360 |
if(delta != null) { |
361 |
final PomResourceDeltaVisitor visitor = new PomResourceDeltaVisitor(); |
362 |
try { |
363 |
delta.accept(visitor); |
364 |
} catch (CoreException e) { |
365 |
RelEngPlugin.log(e); |
366 |
} |
367 |
} |
368 |
} |
369 |
|
370 |
/* (non-Javadoc) |
371 |
* @see org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener#preferenceChange(org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent) |
372 |
*/ |
373 |
public void preferenceChange(PreferenceChangeEvent event) { |
374 |
if(IPomVersionConstants.POM_VERSION_ERROR_LEVEL.equals(event.getKey())) { |
375 |
final String severity = (String) event.getNewValue(); |
376 |
if(severity != null) { |
377 |
if(IPomVersionConstants.VALUE_IGNORE.equals(severity)) { |
378 |
//we turned it off |
379 |
ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); |
380 |
} |
381 |
else if(IPomVersionConstants.VALUE_IGNORE.equals(event.getOldValue())) { |
382 |
// we turned it on |
383 |
ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_BUILD); |
384 |
} |
385 |
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); |
386 |
IProject[] projects = root.getProjects(); |
387 |
for (int i = 0; i < projects.length; i++) { |
388 |
validate(projects[i]); |
389 |
} |
390 |
} |
391 |
} |
392 |
} |
206 |
} |
393 |
} |