1 22 package org.jboss.xb.binding.parser.sax; 23 24 import java.io.InputStream ; 25 import java.io.Reader ; 26 import java.lang.reflect.Method ; 27 28 import javax.xml.parsers.SAXParser ; 29 import javax.xml.parsers.SAXParserFactory ; 30 import org.jboss.logging.Logger; 31 import org.jboss.util.JBossStringBuilder; 32 import org.jboss.util.xml.JBossEntityResolver; 33 import org.jboss.xb.binding.JBossXBException; 34 import org.jboss.xb.binding.JBossXBRuntimeException; 35 import org.jboss.xb.binding.parser.JBossXBParser; 36 import org.xml.sax.Attributes ; 37 import org.xml.sax.EntityResolver ; 38 import org.xml.sax.ErrorHandler ; 39 import org.xml.sax.InputSource ; 40 import org.xml.sax.Locator ; 41 import org.xml.sax.SAXException ; 42 import org.xml.sax.SAXParseException ; 43 import org.xml.sax.XMLReader ; 44 45 49 public class SaxJBossXBParser 50 implements JBossXBParser 51 { 52 private static final Logger log = Logger.getLogger(SaxJBossXBParser.class); 53 54 private static final SAXParserFactory saxFactory = SAXParserFactory.newInstance(); 55 static 56 { 57 saxFactory.setValidating(true); 58 saxFactory.setNamespaceAware(true); 59 enableXInclude(); 60 } 61 62 private final XMLReader reader; 63 private JBossXBParser.ContentHandler contentHandler; 64 private DelegatingContentHandler delegateHandler; 65 private boolean trace; 66 67 72 private static void enableXInclude() 73 { 74 try 75 { 76 Class clazz = saxFactory.getClass(); 77 Method method = clazz.getMethod("setXIncludeAware", new Class [] { Boolean.TYPE }); 78 method.invoke(saxFactory, new Object [] { Boolean.TRUE }); 79 } 80 catch (Exception e) 81 { 82 log.trace("Not setting XIncludeAware", e); 83 } 84 } 85 86 public SaxJBossXBParser() 87 throws JBossXBException 88 { 89 SAXParser parser; 90 try 91 { 92 parser = saxFactory.newSAXParser(); 93 } 94 catch(Exception e) 95 { 96 throw new JBossXBException("Failed to create a new SAX parser", e); 97 } 98 99 try 100 { 101 reader = parser.getXMLReader(); 102 } 103 catch(SAXException e1) 104 { 105 throw new JBossXBRuntimeException("Failed to get parser's XMLReader", e1); 106 } 107 108 delegateHandler = new DelegatingContentHandler(); 109 reader.setContentHandler(delegateHandler); 110 reader.setErrorHandler(MetaDataErrorHandler.INSTANCE); 111 reader.setEntityResolver(new JBossEntityResolver()); 112 113 120 } 121 122 124 public void setEntityResolver(EntityResolver entityResolver) 125 throws JBossXBException 126 { 127 reader.setEntityResolver(entityResolver); 128 } 129 130 public void setProperty(String name, Object value) 131 { 132 try 133 { 134 reader.setProperty(name, value); 135 } 136 catch(SAXException e) 137 { 138 throw new JBossXBRuntimeException("Failed to set property on the XML reader", e); 139 } 140 } 141 142 public void setFeature(String name, boolean value) 143 { 144 try 145 { 146 reader.setFeature(name, value); 147 } 148 catch(SAXException e) 149 { 150 throw new JBossXBRuntimeException("Failed to set feature on the XMLReader", e); 151 } 152 } 153 154 public void parse(String systemId, ContentHandler handler) throws JBossXBException 155 { 156 this.contentHandler = handler; 157 trace = log.isTraceEnabled(); 158 try 159 { 160 reader.parse(systemId); 161 } 162 catch(Exception e) 163 { 164 throw new JBossXBException("Failed to parse source: " + getLocationAsString(systemId), e); 165 } 166 } 167 168 public void parse(InputStream is, ContentHandler handler) throws JBossXBException 169 { 170 this.contentHandler = handler; 171 trace = log.isTraceEnabled(); 172 try 173 { 174 reader.parse(new InputSource (is)); 175 } 176 catch(Exception e) 177 { 178 throw new JBossXBException("Failed to parse source: " + e.getMessage(), e); 179 } 180 } 181 182 public void parse(Reader reader, ContentHandler handler) throws JBossXBException 183 { 184 this.contentHandler = handler; 185 trace = log.isTraceEnabled(); 186 try 187 { 188 this.reader.parse(new InputSource (reader)); 189 } 190 catch(Exception e) 191 { 192 throw new JBossXBException("Failed to parse source: " + e.getMessage(), e); 193 } 194 } 195 196 public String getLocationAsString(String fileName) 197 { 198 Locator locator = delegateHandler.getDocumentLocator(); 199 if (locator == null) 200 return fileName; 201 else 202 { 203 JBossStringBuilder buffer = new JBossStringBuilder(); 204 String id = locator.getSystemId(); 205 if (id == null) 206 id = locator.getPublicId(); 207 buffer.append(id).append('@'); 208 buffer.append(locator.getLineNumber()); 209 buffer.append(','); 210 buffer.append(locator.getColumnNumber()); 211 return buffer.toString(); 212 } 213 } 214 215 217 private final class DelegatingContentHandler 218 implements org.xml.sax.ContentHandler 219 { 220 Locator locator; 221 222 public void endDocument() 223 { 224 } 225 226 public void startDocument() 227 { 228 } 229 230 public void characters(char ch[], int start, int length) 231 { 232 int i = start; 235 while(i < start + length) 236 { 237 if(!Character.isWhitespace(ch[i++])) 238 { 239 contentHandler.characters(ch, start, length); 240 break; 241 } 242 } 243 } 244 245 public void ignorableWhitespace(char ch[], int start, int length) 246 { 247 } 248 249 public void endPrefixMapping(String prefix) 250 { 251 contentHandler.endPrefixMapping(prefix); 252 } 253 254 public void skippedEntity(String name) 255 { 256 } 257 258 public Locator getDocumentLocator() 259 { 260 return locator; 261 } 262 263 public void setDocumentLocator(Locator locator) 264 { 265 this.locator = locator; 266 } 267 268 public void processingInstruction(String target, String data) 269 { 270 contentHandler.processingInstruction(target, data); 271 } 272 273 public void startPrefixMapping(String prefix, String uri) 274 { 275 contentHandler.startPrefixMapping(prefix, uri); 276 } 277 278 public void endElement(String namespaceURI, String localName, String qName) 279 { 280 String name = null; 281 if(trace) 282 { 283 if(localName.length() == 0) 284 { 285 name = qName; 286 } 287 else 288 { 289 name = namespaceURI + ':' + localName; 290 } 291 log.trace("Enter endElement " + name); 292 } 293 try 294 { 295 contentHandler.endElement(namespaceURI, localName, qName); 296 } 297 finally 298 { 299 if(trace) 300 { 301 log.trace("Exit endElement " + name); 302 } 303 } 304 } 305 306 public void startElement(String namespaceURI, String localName, String qName, Attributes atts) 307 { 308 String name = null; 309 if(trace) 310 { 311 if(localName.length() == 0) 312 { 313 name = qName; 314 } 315 else 316 { 317 name = namespaceURI + ':' + localName; 318 } 319 log.trace("Enter startElement " + name); 320 } 321 try 322 { 323 contentHandler.startElement(namespaceURI, localName, qName, atts, null); 324 } 325 finally 326 { 327 if(trace) 328 { 329 log.trace("Exit startElement " + name); 330 } 331 } 332 } 333 } 334 335 private static final class MetaDataErrorHandler 336 implements ErrorHandler 337 { 338 public static final ErrorHandler INSTANCE = new MetaDataErrorHandler(); 339 340 public void warning(SAXParseException exception) 341 { 342 log.warn(formatMessage(exception)); 343 } 344 345 public void error(SAXParseException exception) 346 throws SAXException 347 { 348 throw new SAXException (formatMessage(exception)); 349 } 350 351 public void fatalError(SAXParseException exception) 352 throws SAXException 353 { 354 throw new SAXException (formatMessage(exception)); 355 } 356 357 public String formatMessage(SAXParseException exception) 358 { 359 StringBuffer buffer = new StringBuffer (50); 360 buffer.append(exception.getMessage()).append(" @ "); 361 String location = exception.getPublicId(); 362 if(location != null) 363 { 364 buffer.append(location); 365 } 366 else 367 { 368 location = exception.getSystemId(); 369 if(location != null) 370 { 371 buffer.append(location); 372 } 373 else 374 { 375 buffer.append("*unknown*"); 376 } 377 } 378 buffer.append('['); 379 buffer.append(exception.getLineNumber()).append(','); 380 buffer.append(exception.getColumnNumber()).append(']'); 381 return buffer.toString(); 382 } 383 } 384 } 385 | Popular Tags |