KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > pde > internal > core > builders > XMLErrorReporter


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.pde.internal.core.builders;
12
13 import java.io.StringReader JavaDoc;
14 import java.util.ArrayList JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.Stack JavaDoc;
17
18 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
19 import javax.xml.parsers.ParserConfigurationException JavaDoc;
20
21 import org.eclipse.core.filebuffers.FileBuffers;
22 import org.eclipse.core.filebuffers.ITextFileBufferManager;
23 import org.eclipse.core.resources.IFile;
24 import org.eclipse.core.resources.IMarker;
25 import org.eclipse.core.resources.IProject;
26 import org.eclipse.core.resources.IResource;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.core.runtime.IProgressMonitor;
29 import org.eclipse.jface.text.BadLocationException;
30 import org.eclipse.jface.text.FindReplaceDocumentAdapter;
31 import org.eclipse.jface.text.IDocument;
32 import org.eclipse.jface.text.IRegion;
33 import org.eclipse.jface.text.Position;
34 import org.eclipse.pde.internal.core.PDECore;
35 import org.eclipse.pde.internal.core.PDECoreMessages;
36 import org.w3c.dom.Document JavaDoc;
37 import org.w3c.dom.Element JavaDoc;
38 import org.w3c.dom.Node JavaDoc;
39 import org.w3c.dom.Text JavaDoc;
40 import org.xml.sax.Attributes JavaDoc;
41 import org.xml.sax.InputSource JavaDoc;
42 import org.xml.sax.Locator JavaDoc;
43 import org.xml.sax.SAXException JavaDoc;
44 import org.xml.sax.SAXParseException JavaDoc;
45 import org.xml.sax.helpers.DefaultHandler JavaDoc;
46
47 public class XMLErrorReporter extends DefaultHandler JavaDoc {
48     
49     public static final char F_ATT_PREFIX = '@';
50     public static final char F_ATT_VALUE_PREFIX = '!';
51     public static final char F_CHILD_SEP = '>';
52     
53     class ElementData {
54         int offset;
55         boolean fErrorNode;
56         
57         public ElementData(int offset) {
58             this.offset = offset;
59         }
60     }
61     
62     
63     protected IFile fFile;
64     
65     protected IProject fProject;
66     
67     private int fErrorCount;
68
69     private PDEMarkerFactory fMarkerFactory;
70
71     private org.w3c.dom.Document JavaDoc fXMLDocument;
72     
73     private IDocument fTextDocument;
74
75     private Stack JavaDoc fElementStack;
76
77     private Element JavaDoc fRootElement;
78
79     private Locator JavaDoc fLocator;
80     
81     private int fHighestOffset;
82     
83     private HashMap JavaDoc fOffsetTable;
84
85     private FindReplaceDocumentAdapter fFindReplaceAdapter;
86
87     private double fSchemaVersion = 2.1;
88
89     public XMLErrorReporter(IFile file) {
90         ITextFileBufferManager manager = FileBuffers.getTextFileBufferManager();
91         try {
92             fFile = file;
93             fProject = file.getProject();
94             manager.connect(file.getFullPath(), null);
95             fTextDocument = manager.getTextFileBuffer(file.getFullPath()).getDocument();
96             manager.disconnect(file.getFullPath(), null);
97             fFindReplaceAdapter = new FindReplaceDocumentAdapter(fTextDocument);
98             fOffsetTable = new HashMap JavaDoc();
99             fElementStack = new Stack JavaDoc();
100             removeFileMarkers();
101         } catch (CoreException e) {
102             PDECore.log(e);
103         }
104     }
105
106     public IFile getFile() {
107         return fFile;
108     }
109
110     private IMarker addMarker(String JavaDoc message, int lineNumber, int severity, int fixId, String JavaDoc category) {
111         try {
112             IMarker marker = getMarkerFactory().createMarker(fFile, fixId, category);
113             marker.setAttribute(IMarker.MESSAGE, message);
114             marker.setAttribute(IMarker.SEVERITY, severity);
115             if (lineNumber == -1)
116                 lineNumber = 1;
117             marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
118             if (severity == IMarker.SEVERITY_ERROR)
119                 fErrorCount += 1;
120             return marker;
121         } catch (CoreException e) {
122             PDECore.logException(e);
123         }
124         return null;
125     }
126     
127     private PDEMarkerFactory getMarkerFactory() {
128         if (fMarkerFactory == null)
129             fMarkerFactory = new PDEMarkerFactory();
130         return fMarkerFactory;
131     }
132
133     private void addMarker(SAXParseException JavaDoc e, int severity) {
134         addMarker(e.getMessage(), e.getLineNumber(), severity, PDEMarkerFactory.NO_RESOLUTION, PDEMarkerFactory.CAT_OTHER);
135     }
136
137     public void error(SAXParseException JavaDoc exception) throws SAXException JavaDoc {
138         addMarker(exception, IMarker.SEVERITY_ERROR);
139         generateErrorElementHierarchy();
140     }
141
142     public void fatalError(SAXParseException JavaDoc exception) throws SAXException JavaDoc {
143         addMarker(exception, IMarker.SEVERITY_ERROR);
144         generateErrorElementHierarchy();
145     }
146
147     public int getErrorCount() {
148         return fErrorCount;
149     }
150
151     private void removeFileMarkers() {
152         try {
153             fFile.deleteMarkers(IMarker.PROBLEM, false, IResource.DEPTH_ZERO);
154             fFile.deleteMarkers(PDEMarkerFactory.MARKER_ID, false,
155                     IResource.DEPTH_ZERO);
156         } catch (CoreException e) {
157             PDECore.logException(e);
158         }
159     }
160
161     public void report(String JavaDoc message, int line, int severity, int fixId, Element JavaDoc element, String JavaDoc attrName, String JavaDoc category) {
162         IMarker marker = report(message, line, severity, fixId, category);
163         if (marker == null)
164             return;
165         try {
166             marker.setAttribute(
167                     PDEMarkerFactory.MPK_LOCATION_PATH,
168                     generateLocationPath(element, attrName));
169         } catch (CoreException e) {
170         }
171     }
172
173     private String JavaDoc generateLocationPath(Node JavaDoc node, String JavaDoc attrName) {
174         if (node == null)
175             return new String JavaDoc();
176         
177         int childIndex = 0;
178         for (Node JavaDoc previousSibling = node.getPreviousSibling();
179              previousSibling != null;
180              previousSibling = previousSibling.getPreviousSibling())
181             childIndex += 1;
182         
183         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
184         Node JavaDoc parent = node.getParentNode();
185         if (parent != null && !(parent instanceof Document)) {
186             sb.append(generateLocationPath(parent, null));
187             sb.append(F_CHILD_SEP);
188         }
189         composeNodeString(node, childIndex, attrName, sb);
190         return sb.toString();
191     }
192     
193     private String JavaDoc composeNodeString(Node JavaDoc node, int index, String JavaDoc attrName, StringBuffer JavaDoc sb) {
194         sb.append('(');
195         sb.append(index);
196         sb.append(')');
197         sb.append(node.getNodeName());
198         if (attrName != null) {
199             sb.append(F_ATT_PREFIX);
200             sb.append(attrName);
201         }
202         return sb.toString();
203     }
204     
205     
206     public IMarker report(String JavaDoc message, int line, int severity, int fixId, String JavaDoc category) {
207         if (severity == CompilerFlags.ERROR)
208             return addMarker(message, line, IMarker.SEVERITY_ERROR, fixId, category);
209         if (severity == CompilerFlags.WARNING)
210             return addMarker(message, line, IMarker.SEVERITY_WARNING, fixId, category);
211         return null;
212     }
213     
214     public IMarker report(String JavaDoc message, int line, int severity, String JavaDoc category) {
215         return report(message, line, severity, PDEMarkerFactory.NO_RESOLUTION, category);
216     }
217
218     public void warning(SAXParseException JavaDoc exception) throws SAXException JavaDoc {
219         addMarker(exception, IMarker.SEVERITY_WARNING);
220     }
221     
222     /* (non-Javadoc)
223      * @see org.xml.sax.helpers.DefaultHandler#startDocument()
224      */

225     public void startDocument() throws SAXException JavaDoc {
226         DocumentBuilderFactory JavaDoc factory = DocumentBuilderFactory.newInstance();
227         try {
228             fXMLDocument = factory.newDocumentBuilder().newDocument();
229         } catch (ParserConfigurationException JavaDoc e) {
230         }
231     }
232     
233     /* (non-Javadoc)
234      * @see org.xml.sax.helpers.DefaultHandler#endDocument()
235      */

236     public void endDocument() throws SAXException JavaDoc {
237         fXMLDocument.appendChild(fRootElement);
238     }
239     
240     /* (non-Javadoc)
241      * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
242      */

243     public void startElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName,
244             Attributes JavaDoc attributes) throws SAXException JavaDoc {
245         Element JavaDoc element = fXMLDocument.createElement(qName);
246         for (int i = 0; i < attributes.getLength(); i++) {
247             element.setAttribute(attributes.getQName(i), attributes.getValue(i));
248         }
249         
250         if (fRootElement == null)
251             fRootElement = element;
252         else
253             ((Element JavaDoc)fElementStack.peek()).appendChild(element);
254         fElementStack.push(element);
255         try {
256             if (fTextDocument != null)
257                 fOffsetTable.put(element, new ElementData(getStartOffset(qName)));
258         } catch (BadLocationException e) {
259         }
260     }
261     
262     /* (non-Javadoc)
263      * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
264      */

265     public void endElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName)
266             throws SAXException JavaDoc {
267         fElementStack.pop();
268     }
269     
270     private void generateErrorElementHierarchy() {
271         while (!fElementStack.isEmpty()) {
272             ElementData data = (ElementData) fOffsetTable.get(fElementStack.pop());
273             if (data != null)
274                 data.fErrorNode = true;
275         }
276     }
277
278     
279     /* (non-Javadoc)
280      * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
281      */

282     public void characters(char[] characters, int start, int length)
283             throws SAXException JavaDoc {
284         StringBuffer JavaDoc buff = new StringBuffer JavaDoc();
285         for (int i = 0; i < length; i++) {
286             buff.append(characters[start + i]);
287         }
288         Text JavaDoc text = fXMLDocument.createTextNode(buff.toString());
289         if (fRootElement == null)
290             fXMLDocument.appendChild(text);
291         else
292             ((Element JavaDoc)fElementStack.peek()).appendChild(text);
293     }
294     
295     /* (non-Javadoc)
296      * @see org.xml.sax.helpers.DefaultHandler#setDocumentLocator(org.xml.sax.Locator)
297      */

298     public void setDocumentLocator(Locator JavaDoc locator) {
299         fLocator = locator;
300     }
301     
302     private int getStartOffset(String JavaDoc elementName) throws BadLocationException {
303         int line = fLocator.getLineNumber();
304         int col = fLocator.getColumnNumber();
305         if (col < 0)
306             col = fTextDocument.getLineLength(line);
307         String JavaDoc text = fTextDocument.get(fHighestOffset + 1, fTextDocument.getLineOffset(line) - fHighestOffset - 1);
308
309         ArrayList JavaDoc commentPositions = new ArrayList JavaDoc();
310         for (int idx = 0; idx < text.length();) {
311             idx = text.indexOf("<!--", idx); //$NON-NLS-1$
312
if (idx == -1)
313                 break;
314             int end = text.indexOf("-->", idx); //$NON-NLS-1$
315
if (end == -1)
316                 break;
317             
318             commentPositions.add(new Position(idx, end - idx));
319             idx = end + 1;
320         }
321
322         int idx = 0;
323         for (; idx < text.length(); idx += 1) {
324             idx = text.indexOf("<" + elementName, idx); //$NON-NLS-1$
325
if (idx == -1)
326                 break;
327             boolean valid = true;
328             for (int i = 0; i < commentPositions.size(); i++) {
329                 Position pos = (Position)commentPositions.get(i);
330                 if (pos.includes(idx)) {
331                     valid = false;
332                     break;
333                 }
334             }
335             if (valid)
336                 break;
337         }
338         if (idx > -1)
339             fHighestOffset += idx + 1;
340         return fHighestOffset;
341     }
342     
343     private int getAttributeOffset(String JavaDoc name, String JavaDoc value, int offset) throws BadLocationException {
344         IRegion nameRegion = fFindReplaceAdapter.find(offset, name+"=\""+getWritableString(value), true, false, false, false); //$NON-NLS-1$
345
if (nameRegion != null) {
346             return nameRegion.getOffset();
347         }
348         return -1;
349     }
350     
351     private String JavaDoc getWritableString(String JavaDoc source) {
352         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
353         for (int i = 0; i < source.length(); i++) {
354             char c = source.charAt(i);
355             switch (c) {
356                 case '&' :
357                     buf.append("&amp;"); //$NON-NLS-1$
358
break;
359                 case '<' :
360                     buf.append("&lt;"); //$NON-NLS-1$
361
break;
362                 case '>' :
363                     buf.append("&gt;"); //$NON-NLS-1$
364
break;
365                 case '\'' :
366                     buf.append("&apos;"); //$NON-NLS-1$
367
break;
368                 case '\"' :
369                     buf.append("&quot;"); //$NON-NLS-1$
370
break;
371                 default :
372                     buf.append(c);
373                     break;
374             }
375         }
376         return buf.toString();
377     }
378
379     
380     protected String JavaDoc getTextContent(Element JavaDoc element) {
381         ElementData data = (ElementData)fOffsetTable.get(element);
382         try {
383             IRegion nameRegion = fFindReplaceAdapter.find(data.offset, "</"+element.getNodeName()+">", true, true, false, false); //$NON-NLS-1$ //$NON-NLS-2$
384
int offset = data.offset + element.getNodeName().length() + 2;
385             if (nameRegion != null)
386                 return fTextDocument.get(offset, nameRegion.getOffset() - offset).trim();
387         } catch (BadLocationException e) {
388         }
389         return null;
390     }
391
392     
393     protected int getLine(Element JavaDoc element) {
394         ElementData data = (ElementData)fOffsetTable.get(element);
395         try {
396             return (data == null) ? 1 : fTextDocument.getLineOfOffset(data.offset) + 1;
397         } catch (Exception JavaDoc e) {
398             return 1;
399         }
400     }
401     
402     protected int getLine(Element JavaDoc element, String JavaDoc attName) {
403         ElementData data = (ElementData)fOffsetTable.get(element);
404         try {
405             int offset = getAttributeOffset(attName, element.getAttribute(attName), data.offset);
406             if (offset != -1)
407                 return fTextDocument.getLineOfOffset(offset) + 1;
408         } catch (BadLocationException e) {
409         }
410         return getLine(element);
411     }
412     
413     public void validateContent(IProgressMonitor monitor) {
414         
415     }
416     
417     public Element JavaDoc getDocumentRoot() {
418         if (fRootElement != null)
419             fRootElement.normalize();
420         return fRootElement;
421     }
422     
423     public void processingInstruction(String JavaDoc target, String JavaDoc data) throws SAXException JavaDoc {
424         if ("eclipse".equals(target)) { //$NON-NLS-1$
425
if ("version=\"3.0\"".equals(data)) { //$NON-NLS-1$
426
fSchemaVersion = 3.0;
427             } else if ("version=\"3.2\"".equals(data)) { //$NON-NLS-1$
428
fSchemaVersion = 3.2;
429             }
430         }
431     }
432     
433     protected double getSchemaVersion() {
434         return fSchemaVersion ;
435     }
436     
437     public InputSource JavaDoc resolveEntity(String JavaDoc publicId, String JavaDoc systemId) throws SAXException JavaDoc {
438         int x = fTextDocument.get().indexOf("!DOCTYPE"); //$NON-NLS-1$
439
if (x > 0) {
440             try {
441                 int line = fTextDocument.getLineOfOffset(x) + 1;
442                 report(PDECoreMessages.XMLErrorReporter_ExternalEntityResolution, line, CompilerFlags.WARNING, PDEMarkerFactory.CAT_OTHER);
443             } catch (BadLocationException e) {
444             }
445         }
446         // Prevent the resolution of external entities in order to
447
// prevent the parser from accessing the Internet
448
// This will prevent huge workbench performance degradations and hangs
449
return new InputSource JavaDoc(new StringReader JavaDoc("")); //$NON-NLS-1$
450
}
451
452 }
453
Popular Tags