001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package org.apache.hadoop.hdfs.util; 020 021 import org.apache.hadoop.classification.InterfaceAudience; 022 import org.apache.hadoop.classification.InterfaceStability; 023 import org.xml.sax.ContentHandler; 024 import org.xml.sax.SAXException; 025 import org.xml.sax.helpers.AttributesImpl; 026 027 import java.util.LinkedList; 028 import java.util.List; 029 import java.util.Map; 030 import java.util.TreeMap; 031 032 /** 033 * General xml utilities. 034 * 035 */ 036 @InterfaceAudience.Private 037 @InterfaceStability.Unstable 038 public class XMLUtils { 039 /** 040 * Exception that reflects an invalid XML document. 041 */ 042 static public class InvalidXmlException extends RuntimeException { 043 private static final long serialVersionUID = 1L; 044 public InvalidXmlException(String s) { 045 super(s); 046 } 047 } 048 049 /** 050 * Add a SAX tag with a string inside. 051 * 052 * @param contentHandler the SAX content handler 053 * @param tag the element tag to use 054 * @param value the string to put inside the tag 055 */ 056 public static void addSaxString(ContentHandler contentHandler, 057 String tag, String val) throws SAXException { 058 contentHandler.startElement("", "", tag, new AttributesImpl()); 059 char c[] = val.toString().toCharArray(); 060 contentHandler.characters(c, 0, c.length); 061 contentHandler.endElement("", "", tag); 062 } 063 064 /** 065 * Represents a bag of key-value pairs encountered during parsing an XML 066 * file. 067 */ 068 static public class Stanza { 069 private TreeMap<String, LinkedList <Stanza > > subtrees; 070 private String value; 071 072 public Stanza() { 073 subtrees = new TreeMap<String, LinkedList <Stanza > >(); 074 value = ""; 075 } 076 077 public void setValue(String value) { 078 this.value = value; 079 } 080 081 public String getValue() { 082 return this.value; 083 } 084 085 /** 086 * Discover if a stanza has a given entry. 087 * 088 * @param name entry to look for 089 * 090 * @return true if the entry was found 091 */ 092 public boolean hasChildren(String name) { 093 return subtrees.containsKey(name); 094 } 095 096 /** 097 * Pull an entry from a stanza. 098 * 099 * @param name entry to look for 100 * 101 * @return the entry 102 */ 103 public List<Stanza> getChildren(String name) throws InvalidXmlException { 104 LinkedList <Stanza> children = subtrees.get(name); 105 if (children == null) { 106 throw new InvalidXmlException("no entry found for " + name); 107 } 108 return children; 109 } 110 111 /** 112 * Pull a string entry from a stanza. 113 * 114 * @param name entry to look for 115 * 116 * @return the entry 117 */ 118 public String getValue(String name) throws InvalidXmlException { 119 if (!subtrees.containsKey(name)) { 120 throw new InvalidXmlException("no entry found for " + name); 121 } 122 LinkedList <Stanza> l = subtrees.get(name); 123 if (l.size() != 1) { 124 throw new InvalidXmlException("More than one value found for " + name); 125 } 126 return l.get(0).getValue(); 127 } 128 129 /** 130 * Add an entry to a stanza. 131 * 132 * @param name name of the entry to add 133 * @param child the entry to add 134 */ 135 public void addChild(String name, Stanza child) { 136 LinkedList<Stanza> l; 137 if (subtrees.containsKey(name)) { 138 l = subtrees.get(name); 139 } else { 140 l = new LinkedList<Stanza>(); 141 subtrees.put(name, l); 142 } 143 l.add(child); 144 } 145 146 /** 147 * Convert a stanza to a human-readable string. 148 */ 149 public String toString() { 150 StringBuilder bld = new StringBuilder(); 151 bld.append("{"); 152 if (!value.equals("")) { 153 bld.append("\"").append(value).append("\""); 154 } 155 String prefix = ""; 156 for (Map.Entry<String, LinkedList <Stanza > > entry : 157 subtrees.entrySet()) { 158 String key = entry.getKey(); 159 LinkedList <Stanza > ll = entry.getValue(); 160 for (Stanza child : ll) { 161 bld.append(prefix); 162 bld.append("<").append(key).append(">"); 163 bld.append(child.toString()); 164 prefix = ", "; 165 } 166 } 167 bld.append("}"); 168 return bld.toString(); 169 } 170 } 171 }