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 ResourceRefImpl extends DefaultHandler implements Cloneable , Unmarshallable, LexicalHandler , ResourceRef { 46 47 private Description description; 48 private ResRefName resRefName; 49 private ResType resType; 50 private ResAuth resAuth; 51 private ResSharingScope resSharingScope; 52 private String id; 53 private boolean zeus_IdSet; 54 55 56 private String docTypeString; 57 58 59 private String outputEncoding; 60 61 62 private Unmarshallable zeus_currentUNode; 63 64 65 private Unmarshallable zeus_parentUNode; 66 67 68 private boolean zeus_thisNodeHandled = false; 69 70 71 private boolean hasDTD; 72 73 74 private boolean validate; 75 76 77 private Map namespaceMappings; 78 79 80 private static EntityResolver entityResolver; 81 82 83 private static ErrorHandler errorHandler; 84 85 private static ResourceRefImpl prototype = null; 86 87 public static void setPrototype(ResourceRefImpl prototype) { 88 ResourceRefImpl.prototype = prototype; 89 } 90 public static ResourceRefImpl newInstance() { 91 try { 92 return (prototype!=null)?(ResourceRefImpl)prototype.clone(): new ResourceRefImpl(); 93 } catch (CloneNotSupportedException e) { 94 return null; } 96 } 97 public ResourceRefImpl() { 98 zeus_IdSet = false; 99 docTypeString = ""; 100 hasDTD = false; 101 validate = false; 102 namespaceMappings = new HashMap (); 103 } 104 105 public Description getDescription() { 106 return description; 107 } 108 109 public void setDescription(Description description) { 110 this.description = description; 111 } 112 113 public ResRefName getResRefName() { 114 return resRefName; 115 } 116 117 public void setResRefName(ResRefName resRefName) { 118 this.resRefName = resRefName; 119 } 120 121 public ResType getResType() { 122 return resType; 123 } 124 125 public void setResType(ResType resType) { 126 this.resType = resType; 127 } 128 129 public ResAuth getResAuth() { 130 return resAuth; 131 } 132 133 public void setResAuth(ResAuth resAuth) { 134 this.resAuth = resAuth; 135 } 136 137 public ResSharingScope getResSharingScope() { 138 return resSharingScope; 139 } 140 141 public void setResSharingScope(ResSharingScope resSharingScope) { 142 this.resSharingScope = resSharingScope; 143 } 144 145 public String getId() { 146 return id; 147 } 148 149 public void setId(String id) { 150 this.id = id; 151 zeus_IdSet = true; 152 } 153 154 public void setDocType(String name, String publicID, String systemID) { 155 try { 156 startDTD(name, publicID, systemID); 157 } catch (SAXException neverHappens) { } 158 } 159 160 public void setOutputEncoding(String outputEncoding) { 161 this.outputEncoding = outputEncoding; 162 } 163 164 public void marshal(File file) throws IOException { 165 marshal(new FileWriter (file)); 167 } 168 169 public void marshal(OutputStream outputStream) throws IOException { 170 marshal(new OutputStreamWriter (outputStream)); 172 } 173 174 public void marshal(Writer writer) throws IOException { 175 writer.write("<?xml version=\"1.0\" "); 177 if (outputEncoding != null) { 178 writer.write("encoding=\""); 179 writer.write(outputEncoding); 180 writer.write("\"?>\n\n"); 181 182 } else { 183 writer.write("encoding=\"UTF-8\"?>\n\n"); 184 185 } 186 writer.write(docTypeString); 188 writer.write("\n"); 189 writeXMLRepresentation(writer, ""); 191 192 writer.flush(); 194 writer.close(); 195 } 196 197 protected void writeXMLRepresentation(Writer writer, 198 String indent) 199 throws IOException { 200 201 writer.write(indent); 202 writer.write("<resource-ref"); 203 204 for (Iterator i = namespaceMappings.keySet().iterator(); i.hasNext(); ) { 206 String prefix = (String )i.next(); 207 String uri = (String )namespaceMappings.get(prefix); 208 writer.write(" xmlns"); 209 if (!prefix.trim().equals("")) { 210 writer.write(":"); 211 writer.write(prefix); 212 } 213 writer.write("=\""); 214 writer.write(uri); 215 writer.write("\"\n "); 216 } 217 218 if (zeus_IdSet) { 220 writer.write(" id=\""); 221 writer.write(escapeAttributeValue(id)); 222 writer.write("\""); 223 } 224 writer.write(">"); 225 writer.write("\n"); 226 227 if (description != null) { 229 ((DescriptionImpl)description).writeXMLRepresentation(writer, 230 new StringBuffer (indent).append(" ").toString()); 231 } 232 233 if (resRefName != null) { 234 ((ResRefNameImpl)resRefName).writeXMLRepresentation(writer, 235 new StringBuffer (indent).append(" ").toString()); 236 } 237 238 if (resType != null) { 239 ((ResTypeImpl)resType).writeXMLRepresentation(writer, 240 new StringBuffer (indent).append(" ").toString()); 241 } 242 243 if (resAuth != null) { 244 ((ResAuthImpl)resAuth).writeXMLRepresentation(writer, 245 new StringBuffer (indent).append(" ").toString()); 246 } 247 248 if (resSharingScope != null) { 249 ((ResSharingScopeImpl)resSharingScope).writeXMLRepresentation(writer, 250 new StringBuffer (indent).append(" ").toString()); 251 } 252 253 writer.write(indent); 254 writer.write("</resource-ref>\n"); 255 } 256 257 private String escapeAttributeValue(String attributeValue) { 258 String returnValue = attributeValue; 259 for (int i = 0; i < returnValue.length(); i++) { 260 char ch = returnValue.charAt(i); 261 if (ch == '"') { 262 returnValue = new StringBuffer () 263 .append(returnValue.substring(0, i)) 264 .append(""") 265 .append(returnValue.substring(i+1)) 266 .toString(); 267 } 268 } 269 return returnValue; 270 } 271 272 private String escapeTextValue(String textValue) { 273 String returnValue = textValue; 274 for (int i = 0; i < returnValue.length(); i++) { 275 char ch = returnValue.charAt(i); 276 if (ch == '<') { 277 returnValue = new StringBuffer () 278 .append(returnValue.substring(0, i)) 279 .append("<") 280 .append(returnValue.substring(i+1)) 281 .toString(); 282 } else if (ch == '>') { 283 returnValue = new StringBuffer () 284 .append(returnValue.substring(0, i)) 285 .append(">") 286 .append(returnValue.substring(i+1)) 287 .toString(); 288 } 289 } 290 return returnValue; 291 } 292 293 300 public static void setEntityResolver(EntityResolver resolver) { 301 entityResolver = resolver; 302 } 303 304 311 public static void setErrorHandler(ErrorHandler handler) { 312 errorHandler = handler; 313 } 314 315 public static ResourceRef unmarshal(File file) throws IOException { 316 return unmarshal(new FileReader (file)); 318 } 319 320 public static ResourceRef unmarshal(File file, boolean validate) throws IOException { 321 return unmarshal(new FileReader (file), validate); 323 } 324 325 public static ResourceRef unmarshal(InputStream inputStream) throws IOException { 326 return unmarshal(new InputStreamReader (inputStream)); 328 } 329 330 public static ResourceRef unmarshal(InputStream inputStream, boolean validate) throws IOException { 331 return unmarshal(new InputStreamReader (inputStream), validate); 333 } 334 335 public static ResourceRef unmarshal(Reader reader) throws IOException { 336 return unmarshal(reader, false); 338 } 339 340 public static ResourceRef unmarshal(Reader reader, boolean validate) throws IOException { 341 ResourceRefImpl resourceRef = ResourceRefImpl.newInstance(); 342 resourceRef.setValidating(validate); 343 resourceRef.setCurrentUNode(resourceRef); 344 resourceRef.setParentUNode(null); 345 XMLReader parser = null; 347 String parserClass = System.getProperty("org.xml.sax.driver", 348 "org.apache.xerces.parsers.SAXParser"); 349 try { 350 parser = XMLReaderFactory.createXMLReader(parserClass); 351 352 if (entityResolver != null) { 354 parser.setEntityResolver(entityResolver); 355 } 356 357 parser.setErrorHandler(resourceRef); 359 360 parser.setProperty("http://xml.org/sax/properties/lexical-handler", resourceRef); 362 363 parser.setContentHandler(resourceRef); 365 } catch (SAXException e) { 366 throw new IOException ("Could not load XML parser: " + 367 e.getMessage()); 368 } 369 370 InputSource inputSource = new InputSource (reader); 371 try { 372 parser.setFeature("http://xml.org/sax/features/validation", new Boolean (validate).booleanValue()); 373 parser.setFeature("http://xml.org/sax/features/namespaces", true); 374 parser.setFeature("http://xml.org/sax/features/namespace-prefixes", false); 375 parser.parse(inputSource); 376 } catch (SAXException e) { 377 throw new IOException ("Error parsing XML document: " + 378 e.getMessage()); 379 } 380 381 return resourceRef; 383 } 384 385 public Unmarshallable getParentUNode() { 386 return zeus_parentUNode; 387 } 388 389 public void setParentUNode(Unmarshallable parentUNode) { 390 this.zeus_parentUNode = parentUNode; 391 } 392 393 public Unmarshallable getCurrentUNode() { 394 return zeus_currentUNode; 395 } 396 397 public void setCurrentUNode(Unmarshallable currentUNode) { 398 this.zeus_currentUNode = currentUNode; 399 } 400 401 public void setValidating(boolean validate) { 402 this.validate = validate; 403 } 404 405 public void startDocument() throws SAXException { 406 } 408 409 public void setDocumentLocator(Locator locator) { 410 } 412 413 public void startPrefixMapping(String prefix, String uri) 414 throws SAXException { 415 namespaceMappings.put(prefix, uri); 416 } 417 418 public void startElement(String namespaceURI, String localName, 419 String qName, org.xml.sax.Attributes atts) 420 throws SAXException { 421 422 Unmarshallable current = getCurrentUNode(); 424 if (current != this) { 425 current.startElement(namespaceURI, localName, qName, atts); 426 return; 427 } 428 429 if ((localName.equals("resource-ref")) && (!zeus_thisNodeHandled)) { 431 for (int i=0, len=atts.getLength(); i<len; i++) { 433 String attName= atts.getLocalName(i); 434 String attValue = atts.getValue(i); 435 if (attName.equals("id")) { 436 setId(attValue); 437 } 438 } 439 zeus_thisNodeHandled = true; 440 return; 441 } else { 442 if (localName.equals("description") && (description==null)) { 444 DescriptionImpl description = DescriptionImpl.newInstance(); 445 current = getCurrentUNode(); 446 description.setParentUNode(current); 447 description.setCurrentUNode(description); 448 this.setCurrentUNode(description); 449 description.startElement(namespaceURI, localName, qName, atts); 450 this.description = description; 452 return; 453 } 454 if (localName.equals("res-ref-name") && (resRefName==null)) { 455 ResRefNameImpl resRefName = ResRefNameImpl.newInstance(); 456 current = getCurrentUNode(); 457 resRefName.setParentUNode(current); 458 resRefName.setCurrentUNode(resRefName); 459 this.setCurrentUNode(resRefName); 460 resRefName.startElement(namespaceURI, localName, qName, atts); 461 this.resRefName = resRefName; 463 return; 464 } 465 if (localName.equals("res-type") && (resType==null)) { 466 ResTypeImpl resType = ResTypeImpl.newInstance(); 467 current = getCurrentUNode(); 468 resType.setParentUNode(current); 469 resType.setCurrentUNode(resType); 470 this.setCurrentUNode(resType); 471 resType.startElement(namespaceURI, localName, qName, atts); 472 this.resType = resType; 474 return; 475 } 476 if (localName.equals("res-auth") && (resAuth==null)) { 477 ResAuthImpl resAuth = ResAuthImpl.newInstance(); 478 current = getCurrentUNode(); 479 resAuth.setParentUNode(current); 480 resAuth.setCurrentUNode(resAuth); 481 this.setCurrentUNode(resAuth); 482 resAuth.startElement(namespaceURI, localName, qName, atts); 483 this.resAuth = resAuth; 485 return; 486 } 487 if (localName.equals("res-sharing-scope") && (resSharingScope==null)) { 488 ResSharingScopeImpl resSharingScope = ResSharingScopeImpl.newInstance(); 489 current = getCurrentUNode(); 490 resSharingScope.setParentUNode(current); 491 resSharingScope.setCurrentUNode(resSharingScope); 492 this.setCurrentUNode(resSharingScope); 493 resSharingScope.startElement(namespaceURI, localName, qName, atts); 494 this.resSharingScope = resSharingScope; 496 return; 497 } 498 } 499 } 500 501 public void endElement(String namespaceURI, String localName, 502 String qName) 503 throws SAXException { 504 505 Unmarshallable current = getCurrentUNode(); 506 if (current != this) { 507 current.endElement(namespaceURI, localName, qName); 508 return; 509 } 510 511 Unmarshallable parent = getCurrentUNode().getParentUNode(); 512 if (parent != null) { 513 parent.setCurrentUNode(parent); 514 } 515 } 516 517 public void characters(char[] ch, int start, int len) 518 throws SAXException { 519 520 Unmarshallable current = getCurrentUNode(); 522 if (current != this) { 523 current.characters(ch, start, len); 524 return; 525 } 526 527 String text = new String (ch, start, len); 528 } 529 530 public void comment(char ch[], int start, int len) throws SAXException { 531 } 533 534 public void warning(SAXParseException e) throws SAXException { 535 if (errorHandler != null) { 536 errorHandler.warning(e); 537 } 538 } 539 540 public void error(SAXParseException e) throws SAXException { 541 if ((validate) && (!hasDTD)) { 542 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."); 543 } 544 if (errorHandler != null) { 545 errorHandler.error(e); 546 } 547 } 548 549 public void fatalError(SAXParseException e) throws SAXException { 550 if ((validate) && (!hasDTD)) { 551 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."); 552 } 553 if (errorHandler != null) { 554 errorHandler.fatalError(e); 555 } 556 } 557 558 public void startDTD(String name, String publicID, String systemID) 559 throws SAXException { 560 561 if ((name == null) || (name.equals(""))) { 562 docTypeString = ""; 563 return; 564 } 565 566 hasDTD = true; 567 StringBuffer docTypeSB = new StringBuffer (); 568 boolean hasPublic = false; 569 570 docTypeSB.append("<!DOCTYPE ") 571 .append(name); 572 573 if ((publicID != null) && (!publicID.equals(""))) { 574 docTypeSB.append(" PUBLIC \"") 575 .append(publicID) 576 .append("\""); 577 hasPublic = true; 578 } 579 580 if ((systemID != null) && (!systemID.equals(""))) { 581 if (!hasPublic) { 582 docTypeSB.append(" SYSTEM"); 583 } 584 docTypeSB.append(" \"") 585 .append(systemID) 586 .append("\""); 587 588 } 589 590 docTypeSB.append(">"); 591 592 docTypeString = docTypeSB.toString(); 593 } 594 595 public void endDTD() throws SAXException { 596 } 598 599 public void startEntity(String name) throws SAXException { 600 } 602 603 public void endEntity(String name) throws SAXException { 604 } 606 607 public void startCDATA() throws SAXException { 608 } 610 611 public void endCDATA() throws SAXException { 612 } 614 615 } 616 | Popular Tags |