1 11 package org.eclipse.pde.internal.core.builders; 12 13 import java.io.StringReader ; 14 import java.util.ArrayList ; 15 import java.util.HashMap ; 16 import java.util.Stack ; 17 18 import javax.xml.parsers.DocumentBuilderFactory ; 19 import javax.xml.parsers.ParserConfigurationException ; 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 ; 37 import org.w3c.dom.Element ; 38 import org.w3c.dom.Node ; 39 import org.w3c.dom.Text ; 40 import org.xml.sax.Attributes ; 41 import org.xml.sax.InputSource ; 42 import org.xml.sax.Locator ; 43 import org.xml.sax.SAXException ; 44 import org.xml.sax.SAXParseException ; 45 import org.xml.sax.helpers.DefaultHandler ; 46 47 public class XMLErrorReporter extends DefaultHandler { 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 fXMLDocument; 72 73 private IDocument fTextDocument; 74 75 private Stack fElementStack; 76 77 private Element fRootElement; 78 79 private Locator fLocator; 80 81 private int fHighestOffset; 82 83 private HashMap 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 (); 99 fElementStack = new Stack (); 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 message, int lineNumber, int severity, int fixId, String 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 e, int severity) { 134 addMarker(e.getMessage(), e.getLineNumber(), severity, PDEMarkerFactory.NO_RESOLUTION, PDEMarkerFactory.CAT_OTHER); 135 } 136 137 public void error(SAXParseException exception) throws SAXException { 138 addMarker(exception, IMarker.SEVERITY_ERROR); 139 generateErrorElementHierarchy(); 140 } 141 142 public void fatalError(SAXParseException exception) throws SAXException { 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 message, int line, int severity, int fixId, Element element, String attrName, String 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 generateLocationPath(Node node, String attrName) { 174 if (node == null) 175 return new String (); 176 177 int childIndex = 0; 178 for (Node previousSibling = node.getPreviousSibling(); 179 previousSibling != null; 180 previousSibling = previousSibling.getPreviousSibling()) 181 childIndex += 1; 182 183 StringBuffer sb = new StringBuffer (); 184 Node 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 composeNodeString(Node node, int index, String attrName, StringBuffer 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 message, int line, int severity, int fixId, String 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 message, int line, int severity, String category) { 215 return report(message, line, severity, PDEMarkerFactory.NO_RESOLUTION, category); 216 } 217 218 public void warning(SAXParseException exception) throws SAXException { 219 addMarker(exception, IMarker.SEVERITY_WARNING); 220 } 221 222 225 public void startDocument() throws SAXException { 226 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 227 try { 228 fXMLDocument = factory.newDocumentBuilder().newDocument(); 229 } catch (ParserConfigurationException e) { 230 } 231 } 232 233 236 public void endDocument() throws SAXException { 237 fXMLDocument.appendChild(fRootElement); 238 } 239 240 243 public void startElement(String uri, String localName, String qName, 244 Attributes attributes) throws SAXException { 245 Element 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 )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 265 public void endElement(String uri, String localName, String qName) 266 throws SAXException { 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 282 public void characters(char[] characters, int start, int length) 283 throws SAXException { 284 StringBuffer buff = new StringBuffer (); 285 for (int i = 0; i < length; i++) { 286 buff.append(characters[start + i]); 287 } 288 Text text = fXMLDocument.createTextNode(buff.toString()); 289 if (fRootElement == null) 290 fXMLDocument.appendChild(text); 291 else 292 ((Element )fElementStack.peek()).appendChild(text); 293 } 294 295 298 public void setDocumentLocator(Locator locator) { 299 fLocator = locator; 300 } 301 302 private int getStartOffset(String elementName) throws BadLocationException { 303 int line = fLocator.getLineNumber(); 304 int col = fLocator.getColumnNumber(); 305 if (col < 0) 306 col = fTextDocument.getLineLength(line); 307 String text = fTextDocument.get(fHighestOffset + 1, fTextDocument.getLineOffset(line) - fHighestOffset - 1); 308 309 ArrayList commentPositions = new ArrayList (); 310 for (int idx = 0; idx < text.length();) { 311 idx = text.indexOf("<!--", idx); if (idx == -1) 313 break; 314 int end = text.indexOf("-->", idx); 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); 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 name, String value, int offset) throws BadLocationException { 344 IRegion nameRegion = fFindReplaceAdapter.find(offset, name+"=\""+getWritableString(value), true, false, false, false); if (nameRegion != null) { 346 return nameRegion.getOffset(); 347 } 348 return -1; 349 } 350 351 private String getWritableString(String source) { 352 StringBuffer buf = new StringBuffer (); 353 for (int i = 0; i < source.length(); i++) { 354 char c = source.charAt(i); 355 switch (c) { 356 case '&' : 357 buf.append("&"); break; 359 case '<' : 360 buf.append("<"); break; 362 case '>' : 363 buf.append(">"); break; 365 case '\'' : 366 buf.append("'"); break; 368 case '\"' : 369 buf.append("""); break; 371 default : 372 buf.append(c); 373 break; 374 } 375 } 376 return buf.toString(); 377 } 378 379 380 protected String getTextContent(Element element) { 381 ElementData data = (ElementData)fOffsetTable.get(element); 382 try { 383 IRegion nameRegion = fFindReplaceAdapter.find(data.offset, "</"+element.getNodeName()+">", true, true, false, false); 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 element) { 394 ElementData data = (ElementData)fOffsetTable.get(element); 395 try { 396 return (data == null) ? 1 : fTextDocument.getLineOfOffset(data.offset) + 1; 397 } catch (Exception e) { 398 return 1; 399 } 400 } 401 402 protected int getLine(Element element, String 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 getDocumentRoot() { 418 if (fRootElement != null) 419 fRootElement.normalize(); 420 return fRootElement; 421 } 422 423 public void processingInstruction(String target, String data) throws SAXException { 424 if ("eclipse".equals(target)) { if ("version=\"3.0\"".equals(data)) { fSchemaVersion = 3.0; 427 } else if ("version=\"3.2\"".equals(data)) { fSchemaVersion = 3.2; 429 } 430 } 431 } 432 433 protected double getSchemaVersion() { 434 return fSchemaVersion ; 435 } 436 437 public InputSource resolveEntity(String publicId, String systemId) throws SAXException { 438 int x = fTextDocument.get().indexOf("!DOCTYPE"); 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 return new InputSource (new StringReader ("")); } 451 452 } 453 | Popular Tags |