1 /*
2 * Copyright (c) 2012, 2017, 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
119 writer.writeCharacters((String)v);
120 writer.writeEndElement();
121 }
122 }
123 }
124
125 writer.writeEndElement();
126 writer.writeEndDocument();
127 writer.flush();
128 } catch (XMLStreamException e) {
129 if (e.getCause() instanceof UnsupportedEncodingException) {
130 throw (UnsupportedEncodingException) e.getCause();
131 }
132 throw new IOException(e);
133 }
134
135 }
136 ////////////////////////////////////////////////////////////////////
137 // Validate while parsing
138 ////////////////////////////////////////////////////////////////////
139 static final String ALLOWED_ELEMENTS = "properties, comment, entry";
140 static final String ALLOWED_COMMENT = "comment";
141 ////////////////////////////////////////////////////////////////////
142 // Handler methods
143 ////////////////////////////////////////////////////////////////////
144 StringBuffer buf = new StringBuffer();
145 boolean sawComment = false;
146 boolean validEntry = false;
147 int rootElem = 0;
148 String key;
149 String rootElm;
150
151 @Override
152 public void startElement(String uri, String localName, String qName, Attributes attributes)
153 throws SAXException
154 {
155 if (rootElem < 2) {
156 rootElem++;
157 }
158
159 if (rootElm == null) {
160 fatalError(new SAXParseException("An XML properties document must contain"
161 + " the DOCTYPE declaration as defined by java.util.Properties.", null));
162 }
163
164 if (rootElem == 1 && !rootElm.equals(qName)) {
165 fatalError(new SAXParseException("Document root element \"" + qName
166 + "\", must match DOCTYPE root \"" + rootElm + "\"", null));
167 }
168 if (!ALLOWED_ELEMENTS.contains(qName)) {
169 fatalError(new SAXParseException("Element type \"" + qName + "\" must be declared.", null));
170 }
171 if (qName.equals(ELEMENT_ENTRY)) {
172 validEntry = true;
173 key = attributes.getValue(ATTR_KEY);
174 if (key == null) {
175 fatalError(new SAXParseException("Attribute \"key\" is required and must be specified for element type \"entry\"", null));
176 }
177 } else if (qName.equals(ALLOWED_COMMENT)) {
178 if (sawComment) {
179 fatalError(new SAXParseException("Only one comment element may be allowed. "
180 + "The content of element type \"properties\" must match \"(comment?,entry*)\"", null));
181 }
182 sawComment = true;
183 }
184 }
185
186 @Override
187 public void characters(char[] ch, int start, int length) throws SAXException {
188 if (validEntry) {
189 buf.append(ch, start, length);
190 }
191 }
192
193 @Override
194 public void endElement(String uri, String localName, String qName) throws SAXException {
195 if (!ALLOWED_ELEMENTS.contains(qName)) {
196 fatalError(new SAXParseException("Element: " + qName + " is invalid, must match \"(comment?,entry*)\".", null));
197 }
198
199 if (validEntry) {
200 properties.setProperty(key, buf.toString());
201 buf.delete(0, buf.length());
202 validEntry = false;
203 }
204 }
205
206 @Override
207 public void notationDecl(String name, String publicId, String systemId) throws SAXException {
208 rootElm = name;
209 }
210
211 @Override
212 public InputSource resolveEntity(String pubid, String sysid)
213 throws SAXException, IOException {
214 {
215 if (sysid.equals(PROPS_DTD_URI)) {
216 InputSource is;
217 is = new InputSource(new StringReader(PROPS_DTD));
218 is.setSystemId(PROPS_DTD_URI);
219 return is;
220 }
221 throw new SAXException("Invalid system identifier: " + sysid);
222 }
223 }
224
225 @Override
226 public void error(SAXParseException x) throws SAXException {
227 throw x;
228 }
229
230 @Override
231 public void fatalError(SAXParseException x) throws SAXException {
232 throw x;
233 }
234
235 @Override
236 public void warning(SAXParseException x) throws SAXException {
237 throw x;
238 }
239 }
|
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
119 writer.writeCharacters((String)v);
120 writer.writeEndElement();
121 }
122 }
123 }
124
125 writer.writeEndElement();
126 writer.writeEndDocument();
127 writer.flush();
128 } catch (XMLStreamException e) {
129 if (e.getCause() instanceof UnsupportedEncodingException) {
130 throw (UnsupportedEncodingException) e.getCause();
131 }
132 throw new IOException(e);
133 }
134
135 }
136 ////////////////////////////////////////////////////////////////////
137 // Validate while parsing
138 ////////////////////////////////////////////////////////////////////
139 static final String ALLOWED_ELEMENTS = "comment, entry";
140 static final String ALLOWED_COMMENT = "comment";
141 ////////////////////////////////////////////////////////////////////
142 // Handler methods
143 ////////////////////////////////////////////////////////////////////
144 StringBuilder buf = new StringBuilder();
145 boolean sawRoot = false; // whether a valid root element exists
146 boolean sawComment = false;
147 boolean validEntry = false;
148 String key;
149 String rootElm;
150
151 @Override
152 public void startElement(String uri, String localName, String qName, Attributes attributes)
153 throws SAXException
154 {
155 if (sawRoot) {
156 if (!ALLOWED_ELEMENTS.contains(qName)) {
157 fatalError(new SAXParseException("Element type \"" + qName + "\" must be declared.", null));
158 }
159 } else {
160 // check whether the root has been declared in the DTD
161 if (rootElm == null) {
162 fatalError(new SAXParseException("An XML properties document must contain"
163 + " the DOCTYPE declaration as defined by java.util.Properties.", null));
164 }
165
166 // check whether the element name matches the declaration
167 if (!rootElm.equals(qName)) {
168 fatalError(new SAXParseException("Document root element \"" + qName
169 + "\", must match DOCTYPE root \"" + rootElm + "\"", null));
170 }
171
172 // this is a valid root element
173 sawRoot = true;
174 }
175
176 if (qName.equals(ELEMENT_ENTRY)) {
177 validEntry = true;
178 key = attributes.getValue(ATTR_KEY);
179 if (key == null) {
180 fatalError(new SAXParseException("Attribute \"key\" is required and " +
181 "must be specified for element type \"entry\"", null));
182 }
183 } else if (qName.equals(ALLOWED_COMMENT)) {
184 if (sawComment) {
185 fatalError(new SAXParseException("Only one comment element may be allowed. "
186 + "The content of element type \"properties\" must match \"(comment?,entry*)\"", null));
187 }
188 sawComment = true;
189 }
190 }
191
192 @Override
193 public void characters(char[] ch, int start, int length) throws SAXException {
194 if (validEntry) {
195 buf.append(ch, start, length);
196 }
197 }
198
199 @Override
200 public void endElement(String uri, String localName, String qName) throws SAXException {
201 if (!ALLOWED_ELEMENTS.contains(qName) && !ELEMENT_ROOT.equals(qName)) {
202 fatalError(new SAXParseException("Element: " + qName +
203 " is invalid, must match \"(comment?,entry*)\".", null));
204 }
205
206 if (validEntry) {
207 properties.setProperty(key, buf.toString());
208 buf.delete(0, buf.length());
209 validEntry = false;
210 }
211 }
212
213 @Override
214 public InputSource resolveEntity(String pubid, String sysid)
215 throws SAXException, IOException {
216 {
217 if (sysid.equals(PROPS_DTD_URI)) {
218 // The properties DTD is known to the handler, no need to parse it
219 return null;
220 }
221 throw new SAXException("Invalid system identifier: " + sysid);
222 }
223 }
224
225 @Override
226 public void error(SAXParseException x) throws SAXException {
227 throw x;
228 }
229
230 @Override
231 public void fatalError(SAXParseException x) throws SAXException {
232 throw x;
233 }
234
235 @Override
236 public void warning(SAXParseException x) throws SAXException {
237 throw x;
238 }
239
240 // SAX2 extension from DTDHandler
241
242 @Override
243 public void startDTD (String name, String publicId, String systemId) throws SAXException
244 {
245 if (!ELEMENT_ROOT.equals(name) || !PROPS_DTD_URI.equals(systemId)) {
246 fatalError(new SAXParseException("An XML properties document must contain"
247 + " the DOCTYPE declaration as defined by java.util.Properties.", null));
248 }
249 rootElm = name;
250 }
251
252 @Override
253 public void startInternalSub () throws SAXException
254 {
255 fatalError(new SAXParseException("Internal DTD subset is not allowed. " +
256 "The Properties XML document must have the following DOCTYPE declaration: \n" +
257 PROPS_DTD_DECL, null));
258 }
259 }
|