1 18 package org.enhydra.snapper.business.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 SearchImpl extends DefaultHandler implements Cloneable , Unmarshallable, LexicalHandler , Search { 46 47 private SearchSummary searchSummary; 48 private SearchResult searchResult; 49 50 51 private String docTypeString; 52 53 54 private String outputEncoding; 55 56 57 private Unmarshallable zeus_currentUNode; 58 59 60 private Unmarshallable zeus_parentUNode; 61 62 63 private boolean zeus_thisNodeHandled = false; 64 65 66 private boolean hasDTD; 67 68 69 private boolean validate; 70 71 72 private Map namespaceMappings; 73 74 75 private static EntityResolver entityResolver; 76 77 78 private static ErrorHandler errorHandler; 79 80 private static SearchImpl prototype = null; 81 82 public static void setPrototype(SearchImpl prototype) { 83 SearchImpl.prototype = prototype; 84 } 85 public static SearchImpl newInstance() { 86 try { 87 return (prototype!=null)?(SearchImpl)prototype.clone(): new SearchImpl(); 88 } catch (CloneNotSupportedException e) { 89 return null; } 91 } 92 public SearchImpl() { 93 docTypeString = ""; 94 hasDTD = false; 95 validate = false; 96 namespaceMappings = new HashMap (); 97 } 98 99 public SearchSummary getSearchSummary() { 100 return searchSummary; 101 } 102 103 public void setSearchSummary(SearchSummary searchSummary) { 104 this.searchSummary = searchSummary; 105 } 106 107 public SearchResult getSearchResult() { 108 return searchResult; 109 } 110 111 public void setSearchResult(SearchResult searchResult) { 112 this.searchResult = searchResult; 113 } 114 115 public void setDocType(String name, String publicID, String systemID) { 116 try { 117 startDTD(name, publicID, systemID); 118 } catch (SAXException neverHappens) { } 119 } 120 121 public void setOutputEncoding(String outputEncoding) { 122 this.outputEncoding = outputEncoding; 123 } 124 125 public void marshal(File file) throws IOException { 126 marshal(new FileWriter (file)); 128 } 129 130 public void marshal(OutputStream outputStream) throws IOException { 131 marshal(new OutputStreamWriter (outputStream)); 133 } 134 135 public void marshal(Writer writer) throws IOException { 136 writer.write("<?xml version=\"1.0\" "); 138 if (outputEncoding != null) { 139 writer.write("encoding=\""); 140 writer.write(outputEncoding); 141 writer.write("\"?>\n\n"); 142 143 } else { 144 writer.write("encoding=\"UTF-8\"?>\n\n"); 145 146 } 147 writer.write(docTypeString); 149 writer.write("\n"); 150 writeXMLRepresentation(writer, ""); 152 153 writer.flush(); 155 writer.close(); 156 } 157 158 protected void writeXMLRepresentation(Writer writer, 159 String indent) 160 throws IOException { 161 162 writer.write(indent); 163 writer.write("<Search"); 164 165 for (Iterator i = namespaceMappings.keySet().iterator(); i.hasNext(); ) { 167 String prefix = (String )i.next(); 168 String uri = (String )namespaceMappings.get(prefix); 169 writer.write(" xmlns"); 170 if (!prefix.trim().equals("")) { 171 writer.write(":"); 172 writer.write(prefix); 173 } 174 writer.write("=\""); 175 writer.write(uri); 176 writer.write("\"\n "); 177 } 178 179 writer.write(">"); 181 writer.write("\n"); 182 183 if (searchSummary != null) { 185 ((SearchSummaryImpl)searchSummary).writeXMLRepresentation(writer, 186 new StringBuffer (indent).append(" ").toString()); 187 } 188 189 if (searchResult != null) { 190 ((SearchResultImpl)searchResult).writeXMLRepresentation(writer, 191 new StringBuffer (indent).append(" ").toString()); 192 } 193 194 writer.write(indent); 195 writer.write("</Search>\n"); 196 } 197 198 private String escapeAttributeValue(String attributeValue) { 199 String returnValue = attributeValue; 200 for (int i = 0; i < returnValue.length(); i++) { 201 char ch = returnValue.charAt(i); 202 if (ch == '"') { 203 returnValue = new StringBuffer () 204 .append(returnValue.substring(0, i)) 205 .append(""") 206 .append(returnValue.substring(i+1)) 207 .toString(); 208 } 209 } 210 return returnValue; 211 } 212 213 private String escapeTextValue(String textValue) { 214 String returnValue = textValue; 215 for (int i = 0; i < returnValue.length(); i++) { 216 char ch = returnValue.charAt(i); 217 if (ch == '<') { 218 returnValue = new StringBuffer () 219 .append(returnValue.substring(0, i)) 220 .append("<") 221 .append(returnValue.substring(i+1)) 222 .toString(); 223 } else if (ch == '>') { 224 returnValue = new StringBuffer () 225 .append(returnValue.substring(0, i)) 226 .append(">") 227 .append(returnValue.substring(i+1)) 228 .toString(); 229 } 230 } 231 return returnValue; 232 } 233 234 241 public static void setEntityResolver(EntityResolver resolver) { 242 entityResolver = resolver; 243 } 244 245 252 public static void setErrorHandler(ErrorHandler handler) { 253 errorHandler = handler; 254 } 255 256 public static Search unmarshal(File file) throws IOException { 257 return unmarshal(new FileReader (file)); 259 } 260 261 public static Search unmarshal(File file, boolean validate) throws IOException { 262 return unmarshal(new FileReader (file), validate); 264 } 265 266 public static Search unmarshal(InputStream inputStream) throws IOException { 267 return unmarshal(new InputStreamReader (inputStream)); 269 } 270 271 public static Search unmarshal(InputStream inputStream, boolean validate) throws IOException { 272 return unmarshal(new InputStreamReader (inputStream), validate); 274 } 275 276 public static Search unmarshal(Reader reader) throws IOException { 277 return unmarshal(reader, false); 279 } 280 281 public static Search unmarshal(Reader reader, boolean validate) throws IOException { 282 SearchImpl search = SearchImpl.newInstance(); 283 search.setValidating(validate); 284 search.setCurrentUNode(search); 285 search.setParentUNode(null); 286 XMLReader parser = null; 288 String parserClass = System.getProperty("org.xml.sax.driver", 289 "org.apache.xerces.parsers.SAXParser"); 290 try { 291 parser = XMLReaderFactory.createXMLReader(parserClass); 292 293 if (entityResolver != null) { 295 parser.setEntityResolver(entityResolver); 296 } 297 298 parser.setErrorHandler(search); 300 301 parser.setProperty("http://xml.org/sax/properties/lexical-handler", search); 303 304 parser.setContentHandler(search); 306 } catch (SAXException e) { 307 throw new IOException ("Could not load XML parser: " + 308 e.getMessage()); 309 } 310 CustomResolver temp = new CustomResolver(); 311 312 InputSource inputSource = new InputSource (reader); 313 try { 314 parser.setFeature("http://xml.org/sax/features/validation", new Boolean (validate).booleanValue()); 315 parser.setFeature("http://xml.org/sax/features/namespaces", true); 316 parser.setFeature("http://xml.org/sax/features/namespace-prefixes", false); 317 parser.parse(inputSource); 318 } catch (SAXException e) { 319 throw new IOException ("Error parsing XML document: " + 320 e.getMessage()); 321 } 322 323 return search; 325 } 326 327 public Unmarshallable getParentUNode() { 328 return zeus_parentUNode; 329 } 330 331 public void setParentUNode(Unmarshallable parentUNode) { 332 this.zeus_parentUNode = parentUNode; 333 } 334 335 public Unmarshallable getCurrentUNode() { 336 return zeus_currentUNode; 337 } 338 339 public void setCurrentUNode(Unmarshallable currentUNode) { 340 this.zeus_currentUNode = currentUNode; 341 } 342 343 public void setValidating(boolean validate) { 344 this.validate = validate; 345 } 346 347 public void startDocument() throws SAXException { 348 } 350 351 public void setDocumentLocator(Locator locator) { 352 } 354 355 public void startPrefixMapping(String prefix, String uri) 356 throws SAXException { 357 namespaceMappings.put(prefix, uri); 358 } 359 360 public void startElement(String namespaceURI, String localName, 361 String qName, org.xml.sax.Attributes atts) 362 throws SAXException { 363 364 Unmarshallable current = getCurrentUNode(); 366 if (current != this) { 367 current.startElement(namespaceURI, localName, qName, atts); 368 return; 369 } 370 371 if ((localName.equals("Search")) && (!zeus_thisNodeHandled)) { 373 for (int i=0, len=atts.getLength(); i<len; i++) { 375 String attName= atts.getLocalName(i); 376 String attValue = atts.getValue(i); 377 } 378 zeus_thisNodeHandled = true; 379 return; 380 } else { 381 if (localName.equals("SearchSummary") && (searchSummary==null)) { 383 SearchSummaryImpl searchSummary = SearchSummaryImpl.newInstance(); 384 current = getCurrentUNode(); 385 searchSummary.setParentUNode(current); 386 searchSummary.setCurrentUNode(searchSummary); 387 this.setCurrentUNode(searchSummary); 388 searchSummary.startElement(namespaceURI, localName, qName, atts); 389 this.searchSummary = searchSummary; 391 return; 392 } 393 if (localName.equals("SearchResult") && (searchResult==null)) { 394 SearchResultImpl searchResult = SearchResultImpl.newInstance(); 395 current = getCurrentUNode(); 396 searchResult.setParentUNode(current); 397 searchResult.setCurrentUNode(searchResult); 398 this.setCurrentUNode(searchResult); 399 searchResult.startElement(namespaceURI, localName, qName, atts); 400 this.searchResult = searchResult; 402 return; 403 } 404 } 405 } 406 407 public void endElement(String namespaceURI, String localName, 408 String qName) 409 throws SAXException { 410 411 Unmarshallable current = getCurrentUNode(); 412 if (current != this) { 413 current.endElement(namespaceURI, localName, qName); 414 return; 415 } 416 417 Unmarshallable parent = getCurrentUNode().getParentUNode(); 418 if (parent != null) { 419 parent.setCurrentUNode(parent); 420 } 421 } 422 423 public void characters(char[] ch, int start, int len) 424 throws SAXException { 425 426 Unmarshallable current = getCurrentUNode(); 428 if (current != this) { 429 current.characters(ch, start, len); 430 return; 431 } 432 433 String text = new String (ch, start, len); 434 } 435 436 public void comment(char ch[], int start, int len) throws SAXException { 437 } 439 440 public void warning(SAXParseException e) throws SAXException { 441 if (errorHandler != null) { 442 errorHandler.warning(e); 443 } 444 } 445 446 public void error(SAXParseException e) throws SAXException { 447 if ((validate) && (!hasDTD)) { 448 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."); 449 } 450 if (errorHandler != null) { 451 errorHandler.error(e); 452 } 453 } 454 455 public void fatalError(SAXParseException e) throws SAXException { 456 if ((validate) && (!hasDTD)) { 457 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."); 458 } 459 if (errorHandler != null) { 460 errorHandler.fatalError(e); 461 } 462 } 463 464 public void startDTD(String name, String publicID, String systemID) 465 throws SAXException { 466 467 if ((name == null) || (name.equals(""))) { 468 docTypeString = ""; 469 return; 470 } 471 472 hasDTD = true; 473 StringBuffer docTypeSB = new StringBuffer (); 474 boolean hasPublic = false; 475 476 docTypeSB.append("<!DOCTYPE ") 477 .append(name); 478 479 if ((publicID != null) && (!publicID.equals(""))) { 480 docTypeSB.append(" PUBLIC \"") 481 .append(publicID) 482 .append("\""); 483 hasPublic = true; 484 } 485 486 if ((systemID != null) && (!systemID.equals(""))) { 487 if (!hasPublic) { 488 docTypeSB.append(" SYSTEM"); 489 } 490 docTypeSB.append(" \"") 491 .append(systemID) 492 .append("\""); 493 494 } 495 496 docTypeSB.append(">"); 497 498 docTypeString = docTypeSB.toString(); 499 } 500 501 public void endDTD() throws SAXException { 502 } 504 505 public void startEntity(String name) throws SAXException { 506 } 508 509 public void endEntity(String name) throws SAXException { 510 } 512 513 public void startCDATA() throws SAXException { 514 } 516 517 public void endCDATA() throws SAXException { 518 } 520 521 522 523 } 524 525 | Popular Tags |