1 /*
2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
118 writer.writeCharacters((String)v);
119 writer.writeEndElement();
120 }
121 }
122 }
123
124 writer.writeEndElement();
125 writer.writeEndDocument();
126 writer.close();
127 } catch (XMLStreamException e) {
128 if (e.getCause() instanceof UnsupportedEncodingException) {
129 throw (UnsupportedEncodingException) e.getCause();
130 }
131 throw new IOException(e);
132 }
133
134 }
135 ////////////////////////////////////////////////////////////////////
136 // Validate while parsing
137 ////////////////////////////////////////////////////////////////////
138 final static String ALLOWED_ELEMENTS = "properties, comment, entry";
139 final static String ALLOWED_COMMENT = "comment";
140 ////////////////////////////////////////////////////////////////////
141 // Handler methods
142 ////////////////////////////////////////////////////////////////////
143 StringBuffer buf = new StringBuffer();
144 boolean sawComment = false;
145 boolean validEntry = false;
146 int rootElem = 0;
147 String key;
148 String rootElm;
149
150 @Override
151 public void startElement(String uri, String localName, String qName, Attributes attributes)
152 throws SAXException
153 {
154 if (rootElem < 2) {
155 rootElem++;
156 }
157
158 if (rootElm == null) {
159 fatalError(new SAXParseException("An XML properties document must contain"
160 + " the DOCTYPE declaration as defined by java.util.Properties.", null));
161 }
162
163 if (rootElem == 1 && !rootElm.equals(qName)) {
164 fatalError(new SAXParseException("Document root element \"" + qName
165 + "\", must match DOCTYPE root \"" + rootElm + "\"", null));
166 }
167 if (!ALLOWED_ELEMENTS.contains(qName)) {
168 fatalError(new SAXParseException("Element type \"" + qName + "\" must be declared.", null));
169 }
170 if (qName.equals(ELEMENT_ENTRY)) {
171 validEntry = true;
172 key = attributes.getValue(ATTR_KEY);
173 if (key == null) {
174 fatalError(new SAXParseException("Attribute \"key\" is required and must be specified for element type \"entry\"", null));
175 }
176 } else if (qName.equals(ALLOWED_COMMENT)) {
177 if (sawComment) {
178 fatalError(new SAXParseException("Only one comment element may be allowed. "
179 + "The content of element type \"properties\" must match \"(comment?,entry*)\"", null));
180 }
181 sawComment = true;
182 }
183 }
184
185 @Override
186 public void characters(char[] ch, int start, int length) throws SAXException {
187 if (validEntry) {
188 buf.append(ch, start, length);
189 }
190 }
191
192 @Override
193 public void endElement(String uri, String localName, String qName) throws SAXException {
194 if (!ALLOWED_ELEMENTS.contains(qName)) {
195 fatalError(new SAXParseException("Element: " + qName + " is invalid, must match \"(comment?,entry*)\".", null));
196 }
197
198 if (validEntry) {
199 properties.setProperty(key, buf.toString());
200 buf.delete(0, buf.length());
201 validEntry = false;
202 }
203 }
204
205 @Override
206 public void notationDecl(String name, String publicId, String systemId) throws SAXException {
207 rootElm = name;
208 }
209
210 @Override
211 public InputSource resolveEntity(String pubid, String sysid)
212 throws SAXException, IOException {
213 {
214 if (sysid.equals(PROPS_DTD_URI)) {
215 InputSource is;
216 is = new InputSource(new StringReader(PROPS_DTD));
217 is.setSystemId(PROPS_DTD_URI);
218 return is;
219 }
220 throw new SAXException("Invalid system identifier: " + sysid);
221 }
222 }
223
224 @Override
225 public void error(SAXParseException x) throws SAXException {
226 throw x;
227 }
228
229 @Override
230 public void fatalError(SAXParseException x) throws SAXException {
231 throw x;
232 }
233
234 @Override
235 public void warning(SAXParseException x) throws SAXException {
236 throw x;
237 }
238 }
|
1 /*
2 * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
118 writer.writeCharacters((String)v);
119 writer.writeEndElement();
120 }
121 }
122 }
123
124 writer.writeEndElement();
125 writer.writeEndDocument();
126 writer.close();
127 } catch (XMLStreamException e) {
128 if (e.getCause() instanceof UnsupportedEncodingException) {
129 throw (UnsupportedEncodingException) e.getCause();
130 }
131 throw new IOException(e);
132 }
133
134 }
135 ////////////////////////////////////////////////////////////////////
136 // Validate while parsing
137 ////////////////////////////////////////////////////////////////////
138 static final String ALLOWED_ELEMENTS = "comment, entry";
139 final static String ALLOWED_COMMENT = "comment";
140 ////////////////////////////////////////////////////////////////////
141 // Handler methods
142 ////////////////////////////////////////////////////////////////////
143 StringBuilder buf = new StringBuilder();
144 boolean sawRoot = false; // whether a valid root element exists
145 boolean sawComment = false;
146 boolean validEntry = false;
147 String key;
148 String rootElm;
149
150 @Override
151 public void startElement(String uri, String localName, String qName, Attributes attributes)
152 throws SAXException
153 {
154 if (sawRoot) {
155 if (!ALLOWED_ELEMENTS.contains(qName)) {
156 fatalError(new SAXParseException("Element type \"" + qName + "\" must be declared.", null));
157 }
158 } else {
159 // check whether the root has been declared in the DTD
160 if (rootElm == null) {
161 fatalError(new SAXParseException("An XML properties document must contain"
162 + " the DOCTYPE declaration as defined by java.util.Properties.", null));
163 }
164
165 // check whether the element name matches the declaration
166 if (!rootElm.equals(qName)) {
167 fatalError(new SAXParseException("Document root element \"" + qName
168 + "\", must match DOCTYPE root \"" + rootElm + "\"", null));
169 }
170
171 // this is a valid root element
172 sawRoot = true;
173 }
174
175 if (qName.equals(ELEMENT_ENTRY)) {
176 validEntry = true;
177 key = attributes.getValue(ATTR_KEY);
178 if (key == null) {
179 fatalError(new SAXParseException("Attribute \"key\" is required and " +
180 "must be specified for element type \"entry\"", null));
181 }
182 } else if (qName.equals(ALLOWED_COMMENT)) {
183 if (sawComment) {
184 fatalError(new SAXParseException("Only one comment element may be allowed. "
185 + "The content of element type \"properties\" must match \"(comment?,entry*)\"", null));
186 }
187 sawComment = true;
188 }
189 }
190
191 @Override
192 public void characters(char[] ch, int start, int length) throws SAXException {
193 if (validEntry) {
194 buf.append(ch, start, length);
195 }
196 }
197
198 @Override
199 public void endElement(String uri, String localName, String qName) throws SAXException {
200 if (!ALLOWED_ELEMENTS.contains(qName) && !ELEMENT_ROOT.equals(qName)) {
201 fatalError(new SAXParseException("Element: " + qName +
202 " is invalid, must match \"(comment?,entry*)\".", null));
203 }
204
205 if (validEntry) {
206 properties.setProperty(key, buf.toString());
207 buf.delete(0, buf.length());
208 validEntry = false;
209 }
210 }
211
212 @Override
213 public InputSource resolveEntity(String pubid, String sysid)
214 throws SAXException, IOException {
215 {
216 if (sysid.equals(PROPS_DTD_URI)) {
217 // The properties DTD is known to the handler, no need to parse it
218 return null;
219 }
220 throw new SAXException("Invalid system identifier: " + sysid);
221 }
222 }
223
224 @Override
225 public void error(SAXParseException x) throws SAXException {
226 throw x;
227 }
228
229 @Override
230 public void fatalError(SAXParseException x) throws SAXException {
231 throw x;
232 }
233
234 @Override
235 public void warning(SAXParseException x) throws SAXException {
236 throw x;
237 }
238
239 // SAX2 extension from DTDHandler
240
241 @Override
242 public void startDTD (String name, String publicId, String systemId) throws SAXException
243 {
244 if (!ELEMENT_ROOT.equals(name) || !PROPS_DTD_URI.equals(systemId)) {
245 fatalError(new SAXParseException("An XML properties document must contain"
246 + " the DOCTYPE declaration as defined by java.util.Properties.", null));
247 }
248 rootElm = name;
249 }
250
251 @Override
252 public void startInternalSub () throws SAXException
253 {
254 fatalError(new SAXParseException("Internal DTD subset is not allowed. " +
255 "The Properties XML document must have the following DOCTYPE declaration: \n" +
256 PROPS_DTD_DECL, null));
257 }
258 }
|