1 18 package org.enhydra.convert.xml; 19 20 import java.io.File ; 22 import java.io.FileReader ; 23 import java.io.FileWriter ; 24 import java.io.InputStream ; 25 import java.io.InputStreamReader ; 26 import java.io.IOException ; 27 import java.io.OutputStream ; 28 import java.io.OutputStreamWriter ; 29 import java.io.Reader ; 30 import java.io.Writer ; 31 import java.util.HashMap ; 32 import java.util.Iterator ; 33 import java.util.Map ; 34 import org.xml.sax.EntityResolver ; 35 import org.xml.sax.ErrorHandler ; 36 import org.xml.sax.InputSource ; 37 import org.xml.sax.Locator ; 38 import org.xml.sax.SAXException ; 39 import org.xml.sax.SAXParseException ; 40 import org.xml.sax.XMLReader ; 41 import org.xml.sax.ext.LexicalHandler ; 42 import org.xml.sax.helpers.DefaultHandler ; 43 import org.xml.sax.helpers.XMLReaderFactory ; 44 45 public class LocalImpl extends DefaultHandler implements Cloneable , Unmarshallable, LexicalHandler , Local { 46 47 private String value; 48 private boolean zeus_ValueSet; 49 private String id; 50 private boolean zeus_IdSet; 51 52 53 private String docTypeString; 54 55 56 private String outputEncoding; 57 58 59 private Unmarshallable zeus_currentUNode; 60 61 62 private Unmarshallable zeus_parentUNode; 63 64 65 private boolean zeus_thisNodeHandled = false; 66 67 68 private boolean hasDTD; 69 70 71 private boolean validate; 72 73 74 private Map namespaceMappings; 75 76 77 private static EntityResolver entityResolver; 78 79 80 private static ErrorHandler errorHandler; 81 82 private static LocalImpl prototype = null; 83 84 public static void setPrototype(LocalImpl prototype) { 85 LocalImpl.prototype = prototype; 86 } 87 public static LocalImpl newInstance() { 88 try { 89 return (prototype!=null)?(LocalImpl)prototype.clone(): new LocalImpl(); 90 } catch (CloneNotSupportedException e) { 91 return null; } 93 } 94 public LocalImpl() { 95 zeus_ValueSet = false; 96 zeus_IdSet = false; 97 docTypeString = ""; 98 hasDTD = false; 99 validate = false; 100 namespaceMappings = new HashMap (); 101 } 102 103 public String getValue() { 104 return value; 105 } 106 107 public void setValue(String value) { 108 this.value = value; 109 zeus_ValueSet = true; 110 } 111 112 public String getId() { 113 return id; 114 } 115 116 public void setId(String id) { 117 this.id = id; 118 zeus_IdSet = true; 119 } 120 121 public void setDocType(String name, String publicID, String systemID) { 122 try { 123 startDTD(name, publicID, systemID); 124 } catch (SAXException neverHappens) { } 125 } 126 127 public void setOutputEncoding(String outputEncoding) { 128 this.outputEncoding = outputEncoding; 129 } 130 131 public void marshal(File file) throws IOException { 132 marshal(new FileWriter (file)); 134 } 135 136 public void marshal(OutputStream outputStream) throws IOException { 137 marshal(new OutputStreamWriter (outputStream)); 139 } 140 141 public void marshal(Writer writer) throws IOException { 142 writer.write("<?xml version=\"1.0\" "); 144 if (outputEncoding != null) { 145 writer.write("encoding=\""); 146 writer.write(outputEncoding); 147 writer.write("\"?>\n\n"); 148 149 } else { 150 writer.write("encoding=\"UTF-8\"?>\n\n"); 151 152 } 153 writer.write(docTypeString); 155 writer.write("\n"); 156 writeXMLRepresentation(writer, ""); 158 159 writer.flush(); 161 writer.close(); 162 } 163 164 protected void writeXMLRepresentation(Writer writer, 165 String indent) 166 throws IOException { 167 168 writer.write(indent); 169 writer.write("<local"); 170 171 for (Iterator i = namespaceMappings.keySet().iterator(); i.hasNext(); ) { 173 String prefix = (String )i.next(); 174 String uri = (String )namespaceMappings.get(prefix); 175 writer.write(" xmlns"); 176 if (!prefix.trim().equals("")) { 177 writer.write(":"); 178 writer.write(prefix); 179 } 180 writer.write("=\""); 181 writer.write(uri); 182 writer.write("\"\n "); 183 } 184 185 if (zeus_IdSet) { 187 writer.write(" id=\""); 188 writer.write(escapeAttributeValue(id)); 189 writer.write("\""); 190 } 191 if (getValue() != null) { 192 writer.write(">"); 194 writer.write(escapeTextValue(getValue())); 195 writer.write("</local>\n"); 196 } else { 197 writer.write("/>\n"); 198 } 199 } 200 201 private String escapeAttributeValue(String attributeValue) { 202 String returnValue = attributeValue; 203 for (int i = 0; i < returnValue.length(); i++) { 204 char ch = returnValue.charAt(i); 205 if (ch == '"') { 206 returnValue = new StringBuffer () 207 .append(returnValue.substring(0, i)) 208 .append(""") 209 .append(returnValue.substring(i+1)) 210 .toString(); 211 } 212 } 213 return returnValue; 214 } 215 216 private String escapeTextValue(String textValue) { 217 String returnValue = textValue; 218 for (int i = 0; i < returnValue.length(); i++) { 219 char ch = returnValue.charAt(i); 220 if (ch == '<') { 221 returnValue = new StringBuffer () 222 .append(returnValue.substring(0, i)) 223 .append("<") 224 .append(returnValue.substring(i+1)) 225 .toString(); 226 } else if (ch == '>') { 227 returnValue = new StringBuffer () 228 .append(returnValue.substring(0, i)) 229 .append(">") 230 .append(returnValue.substring(i+1)) 231 .toString(); 232 } 233 } 234 return returnValue; 235 } 236 237 244 public static void setEntityResolver(EntityResolver resolver) { 245 entityResolver = resolver; 246 } 247 248 255 public static void setErrorHandler(ErrorHandler handler) { 256 errorHandler = handler; 257 } 258 259 public static Local unmarshal(File file) throws IOException { 260 return unmarshal(new FileReader (file)); 262 } 263 264 public static Local unmarshal(File file, boolean validate) throws IOException { 265 return unmarshal(new FileReader (file), validate); 267 } 268 269 public static Local unmarshal(InputStream inputStream) throws IOException { 270 return unmarshal(new InputStreamReader (inputStream)); 272 } 273 274 public static Local unmarshal(InputStream inputStream, boolean validate) throws IOException { 275 return unmarshal(new InputStreamReader (inputStream), validate); 277 } 278 279 public static Local unmarshal(Reader reader) throws IOException { 280 return unmarshal(reader, false); 282 } 283 284 public static Local unmarshal(Reader reader, boolean validate) throws IOException { 285 LocalImpl local = LocalImpl.newInstance(); 286 local.setValidating(validate); 287 local.setCurrentUNode(local); 288 local.setParentUNode(null); 289 XMLReader parser = null; 291 String parserClass = System.getProperty("org.xml.sax.driver", 292 "org.apache.xerces.parsers.SAXParser"); 293 try { 294 parser = XMLReaderFactory.createXMLReader(parserClass); 295 296 if (entityResolver != null) { 298 parser.setEntityResolver(entityResolver); 299 } 300 301 parser.setErrorHandler(local); 303 304 parser.setProperty("http://xml.org/sax/properties/lexical-handler", local); 306 307 parser.setContentHandler(local); 309 } catch (SAXException e) { 310 throw new IOException ("Could not load XML parser: " + 311 e.getMessage()); 312 } 313 314 InputSource inputSource = new InputSource (reader); 315 try { 316 parser.setFeature("http://xml.org/sax/features/validation", new Boolean (validate).booleanValue()); 317 parser.setFeature("http://xml.org/sax/features/namespaces", true); 318 parser.setFeature("http://xml.org/sax/features/namespace-prefixes", false); 319 parser.parse(inputSource); 320 } catch (SAXException e) { 321 throw new IOException ("Error parsing XML document: " + 322 e.getMessage()); 323 } 324 325 return local; 327 } 328 329 public Unmarshallable getParentUNode() { 330 return zeus_parentUNode; 331 } 332 333 public void setParentUNode(Unmarshallable parentUNode) { 334 this.zeus_parentUNode = parentUNode; 335 } 336 337 public Unmarshallable getCurrentUNode() { 338 return zeus_currentUNode; 339 } 340 341 public void setCurrentUNode(Unmarshallable currentUNode) { 342 this.zeus_currentUNode = currentUNode; 343 } 344 345 public void setValidating(boolean validate) { 346 this.validate = validate; 347 } 348 349 public void startDocument() throws SAXException { 350 } 352 353 public void setDocumentLocator(Locator locator) { 354 } 356 357 public void startPrefixMapping(String prefix, String uri) 358 throws SAXException { 359 namespaceMappings.put(prefix, uri); 360 } 361 362 public void startElement(String namespaceURI, String localName, 363 String qName, org.xml.sax.Attributes atts) 364 throws SAXException { 365 366 Unmarshallable current = getCurrentUNode(); 368 if (current != this) { 369 current.startElement(namespaceURI, localName, qName, atts); 370 return; 371 } 372 373 if ((localName.equals("local")) && (!zeus_thisNodeHandled)) { 375 for (int i=0, len=atts.getLength(); i<len; i++) { 377 String attName= atts.getLocalName(i); 378 String attValue = atts.getValue(i); 379 if (attName.equals("id")) { 380 setId(attValue); 381 } 382 } 383 zeus_thisNodeHandled = true; 384 return; 385 } else { 386 } 388 } 389 390 public void endElement(String namespaceURI, String localName, 391 String qName) 392 throws SAXException { 393 394 Unmarshallable current = getCurrentUNode(); 395 if (current != this) { 396 current.endElement(namespaceURI, localName, qName); 397 return; 398 } 399 400 if (this.value == null) { 402 this.value = ""; 403 } 404 Unmarshallable parent = getCurrentUNode().getParentUNode(); 405 if (parent != null) { 406 parent.setCurrentUNode(parent); 407 } 408 } 409 410 public void characters(char[] ch, int start, int len) 411 throws SAXException { 412 413 Unmarshallable current = getCurrentUNode(); 415 if (current != this) { 416 current.characters(ch, start, len); 417 return; 418 } 419 420 String text = new String (ch, start, len); 421 if (this.value == null) { 422 this.value = text; 423 } else { 424 this.value = new StringBuffer (this.value).append(text).toString(); 425 } 426 } 427 428 public void comment(char ch[], int start, int len) throws SAXException { 429 } 431 432 public void warning(SAXParseException e) throws SAXException { 433 if (errorHandler != null) { 434 errorHandler.warning(e); 435 } 436 } 437 438 public void error(SAXParseException e) throws SAXException { 439 if ((validate) && (!hasDTD)) { 440 throw new SAXException ("Validation is turned on, but no DTD has been specified in the input XML document. Please supply a DTD through a DOCTYPE reference."); 441 } 442 if (errorHandler != null) { 443 errorHandler.error(e); 444 } 445 } 446 447 public void fatalError(SAXParseException e) throws SAXException { 448 if ((validate) && (!hasDTD)) { 449 throw new SAXException ("Validation is turned on, but no DTD has been specified in the input XML document. Please supply a DTD through a DOCTYPE reference."); 450 } 451 if (errorHandler != null) { 452 errorHandler.fatalError(e); 453 } 454 } 455 456 public void startDTD(String name, String publicID, String systemID) 457 throws SAXException { 458 459 if ((name == null) || (name.equals(""))) { 460 docTypeString = ""; 461 return; 462 } 463 464 hasDTD = true; 465 StringBuffer docTypeSB = new StringBuffer (); 466 boolean hasPublic = false; 467 468 docTypeSB.append("<!DOCTYPE ") 469 .append(name); 470 471 if ((publicID != null) && (!publicID.equals(""))) { 472 docTypeSB.append(" PUBLIC \"") 473 .append(publicID) 474 .append("\""); 475 hasPublic = true; 476 } 477 478 if ((systemID != null) && (!systemID.equals(""))) { 479 if (!hasPublic) { 480 docTypeSB.append(" SYSTEM"); 481 } 482 docTypeSB.append(" \"") 483 .append(systemID) 484 .append("\""); 485 486 } 487 488 docTypeSB.append(">"); 489 490 docTypeString = docTypeSB.toString(); 491 } 492 493 public void endDTD() throws SAXException { 494 } 496 497 public void startEntity(String name) throws SAXException { 498 } 500 501 public void endEntity(String name) throws SAXException { 502 } 504 505 public void startCDATA() throws SAXException { 506 } 508 509 public void endCDATA() throws SAXException { 510 } 512 513 } 514 | Popular Tags |