1 21 22 package org.armedbear.j; 23 24 import java.io.FileInputStream ; 25 import java.io.FileNotFoundException ; 26 import java.io.IOException ; 27 import java.io.InputStream ; 28 import java.io.Reader ; 29 import java.util.Stack ; 30 import javax.swing.tree.DefaultMutableTreeNode ; 31 import javax.swing.tree.DefaultTreeModel ; 32 import javax.swing.tree.TreeModel ; 33 import org.xml.sax.Attributes ; 34 import org.xml.sax.ContentHandler ; 35 import org.xml.sax.EntityResolver ; 36 import org.xml.sax.InputSource ; 37 import org.xml.sax.Locator ; 38 import org.xml.sax.SAXException ; 39 import org.xml.sax.SAXNotRecognizedException ; 40 import org.xml.sax.SAXNotSupportedException ; 41 import org.xml.sax.SAXParseException ; 42 import org.xml.sax.XMLReader ; 43 import org.xml.sax.helpers.DefaultHandler ; 44 import org.xml.sax.helpers.XMLReaderFactory ; 45 46 public final class XmlParserImpl extends DefaultHandler implements Runnable , 47 ContentHandler , EntityResolver 48 { 49 private static final String VALIDATION = 50 "http://xml.org/sax/features/validation"; 51 52 private String parserClassName; 53 private boolean aelfred; 54 private final Buffer buffer; 55 private Reader reader; 56 private XMLReader xmlReader; 57 private TreeModel treeModel; 58 private Stack stack; 59 private Exception exception; 60 private DefaultMutableTreeNode current; 61 private Locator locator; 62 private FastStringBuffer output; 63 64 public XmlParserImpl(Buffer buffer) 65 { 66 Debug.assertTrue(buffer != null); 67 this.buffer = buffer; 68 } 69 70 public boolean initialize() 71 { 72 String className = 73 Editor.preferences().getStringProperty("org.xml.sax.driver"); 74 if (className == null) 75 className = System.getProperty("org.xml.sax.driver"); 76 if (className != null) { 77 try { 78 xmlReader = XMLReaderFactory.createXMLReader(className); 79 } 80 catch (Exception e) { 81 Log.debug(e); 82 } 83 } 84 if (xmlReader == null) 85 xmlReader = Utilities.getDefaultXMLReader(); 86 if (xmlReader == null) { 87 parserClassName = null; 88 aelfred = false; 89 Log.error("no parser found"); 90 } else { 91 parserClassName = xmlReader.getClass().getName(); 92 if (parserClassName.equals("org.armedbear.j.aelfred.SAXDriver")) 93 aelfred = true; 94 else 95 aelfred = false; 96 } 97 return xmlReader != null; 98 } 99 100 public String getParserClassName() 101 { 102 return parserClassName; 103 } 104 105 public void setReader(Reader reader) 106 { 107 this.reader = reader; 108 } 109 110 public boolean enableValidation(boolean enable) 111 { 112 if (xmlReader == null) { 113 Debug.bug(); 114 return false; 115 } 116 try { 117 xmlReader.setFeature(VALIDATION, enable); 118 } 119 catch (SAXNotRecognizedException e) { 120 Log.error(e); 121 return false; 122 } 123 catch (SAXNotSupportedException e) { 124 Log.error(e); 125 return false; 126 } 127 return true; 128 } 129 130 private boolean isValidating() 131 { 132 if (xmlReader == null) { 133 Debug.bug(); 134 return false; 135 } 136 try { 137 return xmlReader.getFeature(VALIDATION); 138 } 139 catch (SAXNotRecognizedException e) {} 140 catch (SAXNotSupportedException e) {} 141 return false; 142 } 143 144 public Exception getException() 145 { 146 return exception; 147 } 148 149 public String getOutput() 150 { 151 return output != null ? output.toString() : ""; 152 } 153 154 public void run() 155 { 156 if (xmlReader == null) { 157 Debug.bug(); 158 initialize(); 159 } 160 161 if (xmlReader == null) { 162 Log.error("no XML reader available"); 163 return; 164 } 165 166 exception = null; 167 output = new FastStringBuffer(); 168 169 final boolean validating = isValidating(); 170 171 output.append("Using "); 172 output.append(xmlReader.getClass().getName()); 173 output.append(" ("); 174 if (!validating) 175 output.append("not "); 176 output.append("validating)\n"); 177 178 if (buffer == null) { 180 Debug.bug(); 181 return; 182 } 183 184 InputSource inputSource = null; 185 final File file = buffer.getFile(); 186 if (reader != null) { 187 inputSource = new InputSource (reader); 188 } else if (file != null) { 189 try { 190 InputStream inputStream = file.getInputStream(); 191 if (inputStream != null) { 192 inputSource = new InputSource (inputStream); 193 String encoding = file.getEncoding(); 194 if (encoding != null) { 195 inputSource.setEncoding(encoding); 196 Log.debug("parser encoding is " + encoding); 197 } 198 } 199 } 200 catch (IOException e) { 201 Log.error(e); 202 } 203 } 204 if (inputSource == null) 205 return; 206 if (file != null) { 207 if (file.isRemote()) 208 inputSource.setSystemId(file.netPath()); 209 else 210 inputSource.setSystemId("file://".concat(file.canonicalPath())); 211 } 212 treeModel = null; 213 stack = new Stack (); 214 215 if (xmlReader != null) { 216 xmlReader.setContentHandler(this); 217 xmlReader.setErrorHandler(this); 218 xmlReader.setEntityResolver(this); 219 long start = System.currentTimeMillis(); 220 try { 221 xmlReader.parse(inputSource); 222 } 223 catch (Exception e) { 224 exception = e; 225 } 226 long elapsed = System.currentTimeMillis() - start; 227 output.append('\n'); 228 output.append(validating ? "Validation" : "Parsing"); 229 output.append(" finished ("); 230 output.append(elapsed); 231 output.append(" ms)"); 232 } 233 } 234 235 public InputSource resolveEntity(String publicId, String systemId) 236 { 237 if (systemId == null) 238 return null; 239 if (Platform.isPlatformWindows() && systemId.startsWith("file://")) { 240 String filename = systemId.substring(7); 242 if (filename.length() > 2 && filename.charAt(1) == '/') 244 filename = filename.substring(0, 1) + ':' + filename.substring(1); 245 filename = File.normalize(filename); 247 try { 248 return new InputSource (new FileInputStream (filename)); 249 } 250 catch (FileNotFoundException e) {} 251 if (filename.length() > 3 && filename.charAt(1) == ':' 253 && filename.charAt(2) == '\\') { 254 File file = File.getInstance(buffer.getFile().getParentFile(), 256 filename.substring(3)); 257 try { 258 return new InputSource (new FileInputStream (file.canonicalPath())); 259 } 260 catch (Exception e) {} 261 } 262 } 263 if (aelfred) { 264 Log.debug("using aelfred - cache not supported"); 269 return null; 270 } 271 if (!buffer.getBooleanProperty(Property.ENABLE_CACHE)) { 272 Log.debug("cache disabled"); 273 return null; 274 } 275 if (systemId.startsWith("http://")) { 276 Cache cache = Cache.getCache(); 277 if (cache != null) { 278 Log.debug("checking cache for ".concat(systemId)); 279 File file = cache.get(systemId); 280 if (file == null) { 281 Log.debug("caching ".concat(systemId)); 282 file = cache.put(systemId); 283 } 284 if (file != null) { 285 try { 286 Log.debug("returning input stream from cache"); 287 InputSource inputSource = 288 new InputSource (file.getInputStream()); 289 inputSource.setSystemId(systemId); 290 return inputSource; 291 } 292 catch (Exception e) { 293 Log.error(e); 294 } 295 } 296 } 297 } 298 return null; 299 } 300 301 public void setDocumentLocator(Locator locator) 302 { 303 this.locator = locator; 304 } 305 306 public void startElement(String uri, String localName, String qName, 307 Attributes attributes) throws SAXException 308 { 309 int lineNumber = 0; 310 int columnNumber = 0; 311 if (locator != null) { 312 lineNumber = locator.getLineNumber(); 313 columnNumber = locator.getColumnNumber(); 314 } 315 DefaultMutableTreeNode node = 316 new DefaultMutableTreeNode (new XmlTreeElement(localName, 317 attributes, lineNumber, columnNumber)); 318 if (treeModel == null) { 319 treeModel = new DefaultTreeModel (node); 320 } else { 321 Debug.assertTrue(current != null); 322 current.insert(node, current.getChildCount()); 323 stack.push(current); 324 } 325 current = node; 326 } 327 328 public void endElement(String uri, String localName, String qName) 329 { 330 if (stack.empty()) 331 current = null; 332 else 333 current = (DefaultMutableTreeNode ) stack.pop(); 334 } 335 336 public void warning(SAXParseException e) 337 throws SAXException 338 { 339 appendMessage("Warning", e); 340 } 341 342 public void error(SAXParseException e) 343 throws SAXException 344 { 345 appendMessage("Error", e); 346 } 347 348 public void fatalError(SAXParseException e) 349 throws SAXException 350 { 351 appendMessage("Fatal error", e); 352 } 353 354 private void appendMessage(String what, SAXParseException e) 355 { 356 FastStringBuffer sb = new FastStringBuffer(); 357 final String systemId = e.getSystemId(); 358 final int lineNumber = e.getLineNumber(); 359 if (systemId.startsWith("file://")) { 360 sb.append(systemId.substring(7)); 361 sb.append(':'); 362 sb.append(lineNumber); 363 } else if (systemId.startsWith("file:")) { 364 sb.append(systemId.substring(5)); 365 sb.append(':'); 366 sb.append(lineNumber); 367 } else { 368 sb.append(systemId); 369 sb.append(" line "); 370 sb.append(lineNumber); 371 } 372 sb.append(": "); 373 sb.append(what); 374 sb.append(": "); 375 sb.append(e.getMessage()); 376 sb.append('\n'); 377 output.append(sb.toString()); 378 } 379 380 public TreeModel getTreeModel() 381 { 382 return treeModel; 383 } 384 } 385 | Popular Tags |