1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.tobago.util;
21
22 import org.w3c.dom.Document;
23 import org.w3c.dom.Element;
24 import org.w3c.dom.Node;
25 import org.w3c.dom.NodeList;
26 import org.xml.sax.EntityResolver;
27 import org.xml.sax.InputSource;
28 import org.xml.sax.SAXException;
29
30 import javax.xml.parsers.DocumentBuilder;
31 import javax.xml.parsers.DocumentBuilderFactory;
32 import javax.xml.parsers.ParserConfigurationException;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.StringReader;
36 import java.util.Properties;
37
38 public final class XmlUtils {
39
40 public static String escape(final String s) {
41 return escape(s, true);
42 }
43
44 public static String escape(final String s, final boolean isAttributeValue) {
45 if (null == s) {
46 return "";
47 }
48 int len = s.length();
49 StringBuilder buffer = new StringBuilder(len);
50 for (int i = 0; i < len; i++) {
51 appendEntityRef(buffer, s.charAt(i), isAttributeValue);
52 }
53 return buffer.toString();
54 }
55
56 public static String escape(final char[] chars, final int offset, final int length, final boolean isAttributeValue) {
57 if (null == chars) {
58 return "";
59 }
60 StringBuilder buffer = new StringBuilder(length);
61 for (int i = offset; i < length; i++) {
62 appendEntityRef(buffer, chars[i], isAttributeValue);
63 }
64 return buffer.toString();
65 }
66
67 private static void appendEntityRef(final StringBuilder buffer, final char ch,
68 final boolean isAttributeValue) {
69
70
71 switch (ch) {
72 case '<':
73 buffer.append("<");
74 break;
75 case '&':
76 buffer.append("&");
77 break;
78 case '"':
79 if (isAttributeValue) {
80 buffer.append(""");
81 } else {
82 buffer.append(ch);
83 }
84 break;
85 case '\'':
86 if (isAttributeValue) {
87 buffer.append("'");
88 } else {
89 buffer.append(ch);
90 }
91 break;
92 case '>':
93 buffer.append(">");
94 break;
95 default:
96 buffer.append(ch);
97 }
98 }
99
100
101 @Deprecated
102 public static void load(final Properties properties, final InputStream stream)
103 throws IOException {
104 Document document;
105 try {
106 document = createDocument(stream);
107 } catch (SAXException e) {
108 throw new RuntimeException("Invalid properties format", e);
109 }
110 Element propertiesElement = (Element) document.getChildNodes().item(
111 document.getChildNodes().getLength() - 1);
112 importProperties(properties, propertiesElement);
113 }
114
115 private static Document createDocument(final InputStream stream)
116 throws SAXException, IOException {
117 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
118 factory.setIgnoringElementContentWhitespace(true);
119 factory.setValidating(false);
120 factory.setCoalescing(true);
121 factory.setIgnoringComments(true);
122 try {
123 DocumentBuilder builder = factory.newDocumentBuilder();
124 builder.setEntityResolver(new Resolver());
125 InputSource source = new InputSource(stream);
126 return builder.parse(source);
127 } catch (ParserConfigurationException e) {
128 throw new Error(e);
129 }
130 }
131
132 static void importProperties(final Properties properties, final Element propertiesElement) {
133 NodeList entries = propertiesElement.getChildNodes();
134 int numEntries = entries.getLength();
135 int start = numEntries > 0
136 && entries.item(0).getNodeName().equals("comment") ? 1 : 0;
137 for (int i = start; i < numEntries; i++) {
138 Node child = entries.item(i);
139 if (child instanceof Element) {
140 Element entry = (Element) child;
141 if (entry.hasAttribute("key")) {
142 Node node = entry.getFirstChild();
143 String value = (node == null) ? "" : node.getNodeValue();
144 properties.setProperty(entry.getAttribute("key"), value);
145 }
146 }
147 }
148 }
149
150 private static class Resolver implements EntityResolver {
151
152 public InputSource resolveEntity(final String publicId, final String systemId)
153 throws SAXException {
154 String dtd = "<!ELEMENT properties (comment?, entry*)>"
155 + "<!ATTLIST properties version CDATA #FIXED '1.0'>"
156 + "<!ELEMENT comment (#PCDATA)>"
157 + "<!ELEMENT entry (#PCDATA)>"
158 + "<!ATTLIST entry key CDATA #REQUIRED>";
159 InputSource inputSource = new InputSource(new StringReader(dtd));
160 inputSource.setSystemId("http://java.sun.com/dtd/properties.dtd");
161 return inputSource;
162 }
163 }
164
165 }