1 18 19 package org.apache.tools.ant.taskdefs; 20 21 import java.io.File ; 22 import java.io.IOException ; 23 import java.util.Hashtable ; 24 import javax.xml.parsers.DocumentBuilderFactory ; 25 import javax.xml.parsers.DocumentBuilder ; 26 import javax.xml.parsers.ParserConfigurationException ; 27 import org.apache.tools.ant.BuildException; 28 import org.apache.tools.ant.Project; 29 import org.apache.tools.ant.types.Path; 30 import org.apache.tools.ant.types.Resource; 31 import org.apache.tools.ant.types.ResourceCollection; 32 import org.apache.tools.ant.types.XMLCatalog; 33 import org.apache.tools.ant.types.resources.FileResource; 34 import org.apache.tools.ant.util.FileUtils; 35 import org.w3c.dom.Document ; 36 import org.w3c.dom.Element ; 37 import org.w3c.dom.NamedNodeMap ; 38 import org.w3c.dom.Node ; 39 import org.w3c.dom.NodeList ; 40 import org.xml.sax.SAXException ; 41 import org.xml.sax.EntityResolver ; 42 43 175 176 public class XmlProperty extends org.apache.tools.ant.Task { 177 178 private Resource src; 179 private String prefix = ""; 180 private boolean keepRoot = true; 181 private boolean validate = false; 182 private boolean collapseAttributes = false; 183 private boolean semanticAttributes = false; 184 private boolean includeSemanticAttribute = false; 185 private File rootDirectory = null; 186 private Hashtable addedAttributes = new Hashtable (); 187 private XMLCatalog xmlCatalog = new XMLCatalog(); 188 189 private static final String ID = "id"; 190 private static final String REF_ID = "refid"; 191 private static final String LOCATION = "location"; 192 private static final String VALUE = "value"; 193 private static final String PATH = "path"; 194 private static final String PATHID = "pathid"; 195 private static final String [] ATTRIBUTES = new String [] { 196 ID, REF_ID, LOCATION, VALUE, PATH, PATHID 197 }; 198 private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); 199 200 203 public XmlProperty() { 204 super(); 205 } 206 207 210 211 public void init() { 212 super.init(); 213 xmlCatalog.setProject(getProject()); 214 } 215 216 217 220 protected EntityResolver getEntityResolver() { 221 return xmlCatalog; 222 } 223 224 230 public void execute() 231 throws BuildException { 232 233 Resource r = getResource(); 234 235 if (r == null) { 236 String msg = "XmlProperty task requires a source resource"; 237 throw new BuildException(msg); 238 } 239 240 try { 241 log("Loading " + src, Project.MSG_VERBOSE); 242 243 if (r.isExists()) { 244 245 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 246 factory.setValidating(validate); 247 factory.setNamespaceAware(false); 248 DocumentBuilder builder = factory.newDocumentBuilder(); 249 builder.setEntityResolver(getEntityResolver()); 250 Document document = null; 251 if (src instanceof FileResource) { 252 document = builder.parse(((FileResource) src).getFile()); 253 } else { 254 document = builder.parse(src.getInputStream()); 255 } 256 Element topElement = document.getDocumentElement(); 257 258 addedAttributes = new Hashtable (); 263 264 if (keepRoot) { 265 addNodeRecursively(topElement, prefix, null); 266 } else { 267 NodeList topChildren = topElement.getChildNodes(); 268 int numChildren = topChildren.getLength(); 269 for (int i = 0; i < numChildren; i++) { 270 addNodeRecursively(topChildren.item(i), prefix, null); 271 } 272 } 273 274 } else { 275 log("Unable to find property resource: " + r, 276 Project.MSG_VERBOSE); 277 } 278 279 } catch (SAXException sxe) { 280 Exception x = sxe; 282 if (sxe.getException() != null) { 283 x = sxe.getException(); 284 } 285 throw new BuildException("Failed to load " + src, x); 286 287 } catch (ParserConfigurationException pce) { 288 throw new BuildException(pce); 290 } catch (IOException ioe) { 291 throw new BuildException("Failed to load " + src, ioe); 293 } 294 } 295 296 297 private void addNodeRecursively(Node node, String prefix, 298 Object container) { 299 300 String nodePrefix = prefix; 302 if (node.getNodeType() != Node.TEXT_NODE) { 303 if (prefix.trim().length() > 0) { 304 nodePrefix += "."; 305 } 306 nodePrefix += node.getNodeName(); 307 } 308 309 Object nodeObject = processNode(node, nodePrefix, container); 311 312 if (node.hasChildNodes()) { 314 315 NodeList nodeChildren = node.getChildNodes(); 316 int numChildren = nodeChildren.getLength(); 317 318 for (int i = 0; i < numChildren; i++) { 319 addNodeRecursively(nodeChildren.item(i), nodePrefix, 323 nodeObject); 324 } 325 } 326 } 327 328 void addNodeRecursively(org.w3c.dom.Node node, String prefix) { 329 addNodeRecursively(node, prefix, null); 330 } 331 332 347 public Object processNode (Node node, String prefix, Object container) { 348 349 Object addedPath = null; 354 355 String id = null; 357 358 if (node.hasAttributes()) { 359 360 NamedNodeMap nodeAttributes = node.getAttributes(); 361 362 Node idNode = nodeAttributes.getNamedItem(ID); 364 id = (semanticAttributes && idNode != null 365 ? idNode.getNodeValue() : null); 366 367 for (int i = 0; i < nodeAttributes.getLength(); i++) { 369 370 Node attributeNode = nodeAttributes.item(i); 371 372 if (!semanticAttributes) { 373 String attributeName = getAttributeName(attributeNode); 374 String attributeValue = getAttributeValue(attributeNode); 375 addProperty(prefix + attributeName, attributeValue, null); 376 } else { 377 378 String nodeName = attributeNode.getNodeName(); 379 String attributeValue = getAttributeValue(attributeNode); 380 381 Path containingPath = (container != null 382 && container instanceof Path ? (Path) container : null); 383 384 390 if (nodeName.equals(ID)) { 391 continue; 393 } else if (containingPath != null 394 && nodeName.equals(PATH)) { 395 containingPath.setPath(attributeValue); 397 } else if (container instanceof Path 398 && nodeName.equals(REF_ID)) { 399 containingPath.setPath(attributeValue); 401 } else if (container instanceof Path 402 && nodeName.equals(LOCATION)) { 403 containingPath.setLocation(resolveFile(attributeValue)); 406 } else if (nodeName.equals(PATHID)) { 407 if (container != null) { 409 throw new BuildException("XmlProperty does not " 410 + "support nested paths"); 411 } 412 413 addedPath = new Path(getProject()); 414 getProject().addReference(attributeValue, addedPath); 415 } else { 416 String attributeName = getAttributeName(attributeNode); 418 addProperty(prefix + attributeName, attributeValue, id); 419 } 420 } 421 } 422 } 423 424 String nodeText = null; 425 boolean emptyNode = false; 426 boolean semanticEmptyOverride = false; 427 if (node.getNodeType() == Node.ELEMENT_NODE 428 && semanticAttributes 429 && node.hasAttributes() 430 && (node.getAttributes().getNamedItem(VALUE) != null 431 || node.getAttributes().getNamedItem(LOCATION) != null 432 || node.getAttributes().getNamedItem(REF_ID) != null 433 || node.getAttributes().getNamedItem(PATH) != null 434 || node.getAttributes().getNamedItem(PATHID) != null)) { 435 semanticEmptyOverride = true; 436 } 437 if (node.getNodeType() == Node.TEXT_NODE) { 438 nodeText = getAttributeValue(node); 440 } else if ((node.getNodeType() == Node.ELEMENT_NODE) 441 && (node.getChildNodes().getLength() == 1) 442 && (node.getFirstChild().getNodeType() == Node.CDATA_SECTION_NODE)) { 443 444 nodeText = node.getFirstChild().getNodeValue(); 445 if ("".equals(nodeText) && !semanticEmptyOverride) { 446 emptyNode = true; 447 } 448 } else if ((node.getNodeType() == Node.ELEMENT_NODE) 449 && (node.getChildNodes().getLength() == 0) 450 && !semanticEmptyOverride) { 451 nodeText = ""; 452 emptyNode = true; 453 } else if ((node.getNodeType() == Node.ELEMENT_NODE) 454 && (node.getChildNodes().getLength() == 1) 455 && (node.getFirstChild().getNodeType() == Node.TEXT_NODE) 456 && ("".equals(node.getFirstChild().getNodeValue())) 457 && !semanticEmptyOverride) { 458 nodeText = ""; 459 emptyNode = true; 460 } 461 462 if (nodeText != null) { 463 if (semanticAttributes && id == null 465 && container instanceof String ) { 466 id = (String ) container; 467 } 468 if (nodeText.trim().length() != 0 || emptyNode) { 469 addProperty(prefix, nodeText, id); 470 } 471 } 472 473 return (addedPath != null ? addedPath : id); 478 } 479 480 484 private void addProperty (String name, String value, String id) { 485 String msg = name + ":" + value; 486 if (id != null) { 487 msg += ("(id=" + id + ")"); 488 } 489 log(msg, Project.MSG_DEBUG); 490 491 if (addedAttributes.containsKey(name)) { 492 value = (String ) addedAttributes.get(name) + "," + value; 501 getProject().setProperty(name, value); 502 addedAttributes.put(name, value); 503 } else if (getProject().getProperty(name) == null) { 504 getProject().setNewProperty(name, value); 505 addedAttributes.put(name, value); 506 } else { 507 log("Override ignored for property " + name, Project.MSG_VERBOSE); 508 } 509 if (id != null) { 510 getProject().addReference(id, value); 511 } 512 } 513 514 521 private String getAttributeName (Node attributeNode) { 522 String attributeName = attributeNode.getNodeName(); 523 524 if (semanticAttributes) { 525 if (attributeName.equals(REF_ID)) { 528 return ""; 529 } else if (!isSemanticAttribute(attributeName) 531 || includeSemanticAttribute) { 532 return "." + attributeName; 533 } else { 534 return ""; 535 } 536 } else if (collapseAttributes) { 537 return "." + attributeName; 538 } else { 539 return "(" + attributeName + ")"; 540 } 541 } 542 543 546 private static boolean isSemanticAttribute (String attributeName) { 547 for (int i = 0; i < ATTRIBUTES.length; i++) { 548 if (attributeName.equals(ATTRIBUTES[i])) { 549 return true; 550 } 551 } 552 return false; 553 } 554 555 567 private String getAttributeValue (Node attributeNode) { 568 String nodeValue = attributeNode.getNodeValue().trim(); 569 if (semanticAttributes) { 570 String attributeName = attributeNode.getNodeName(); 571 nodeValue = getProject().replaceProperties(nodeValue); 572 if (attributeName.equals(LOCATION)) { 573 File f = resolveFile(nodeValue); 574 return f.getPath(); 575 } else if (attributeName.equals(REF_ID)) { 576 Object ref = getProject().getReference(nodeValue); 577 if (ref != null) { 578 return ref.toString(); 579 } 580 } 581 } 582 return nodeValue; 583 } 584 585 589 public void setFile(File src) { 590 setSrcResource(new FileResource(src)); 591 } 592 593 597 public void setSrcResource(Resource src) { 598 if (src.isDirectory()) { 599 throw new BuildException("the source can't be a directory"); 600 } 601 if (src instanceof FileResource && !supportsNonFileResources()) { 602 throw new BuildException("Only FileSystem resources are" 603 + " supported."); 604 } 605 this.src = src; 606 } 607 608 612 public void addConfigured(ResourceCollection a) { 613 if (a.size() != 1) { 614 throw new BuildException("only single argument resource collections" 615 + " are supported as archives"); 616 } 617 setSrcResource((Resource) a.iterator().next()); 618 } 619 620 624 public void setPrefix(String prefix) { 625 this.prefix = prefix.trim(); 626 } 627 628 634 public void setKeeproot(boolean keepRoot) { 635 this.keepRoot = keepRoot; 636 } 637 638 642 public void setValidate(boolean validate) { 643 this.validate = validate; 644 } 645 646 651 public void setCollapseAttributes(boolean collapseAttributes) { 652 this.collapseAttributes = collapseAttributes; 653 } 654 655 659 public void setSemanticAttributes(boolean semanticAttributes) { 660 this.semanticAttributes = semanticAttributes; 661 } 662 663 668 public void setRootDirectory(File rootDirectory) { 669 this.rootDirectory = rootDirectory; 670 } 671 672 678 public void setIncludeSemanticAttribute(boolean includeSemanticAttribute) { 679 this.includeSemanticAttribute = includeSemanticAttribute; 680 } 681 682 686 public void addConfiguredXMLCatalog(XMLCatalog catalog) { 687 xmlCatalog.addConfiguredXMLCatalog(catalog); 688 } 689 690 691 692 695 protected File getFile () { 696 if (src instanceof FileResource) { 697 return ((FileResource) src).getFile(); 698 } else { 699 return null; 700 } 701 } 702 703 706 protected Resource getResource() { 707 File f = getFile(); 710 if (f != null) { 711 return new FileResource(f); 712 } else { 713 return src; 714 } 715 } 716 717 720 protected String getPrefix () { 721 return this.prefix; 722 } 723 724 727 protected boolean getKeeproot () { 728 return this.keepRoot; 729 } 730 731 734 protected boolean getValidate () { 735 return this.validate; 736 } 737 738 741 protected boolean getCollapseAttributes () { 742 return this.collapseAttributes; 743 } 744 745 748 protected boolean getSemanticAttributes () { 749 return this.semanticAttributes; 750 } 751 752 755 protected File getRootDirectory () { 756 return this.rootDirectory; 757 } 758 759 762 protected boolean getIncludeSementicAttribute () { 763 return this.includeSemanticAttribute; 764 } 765 766 770 private File resolveFile(String fileName) { 771 if (rootDirectory == null) { 772 return FILE_UTILS.resolveFile(getProject().getBaseDir(), fileName); 773 } 774 return FILE_UTILS.resolveFile(rootDirectory, fileName); 775 } 776 777 788 protected boolean supportsNonFileResources() { 789 return getClass().equals(XmlProperty.class); 790 } 791 } 792 | Popular Tags |