Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/jdk/internal/util/xml/PropertiesDefaultHandler.java
41161 views
1
/*
2
* Copyright (c) 2012, 2020, 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
23
* questions.
24
*/
25
26
package jdk.internal.util.xml;
27
28
import java.io.*;
29
import java.nio.charset.Charset;
30
import java.util.InvalidPropertiesFormatException;
31
import java.util.Map.Entry;
32
import java.util.Properties;
33
import jdk.internal.org.xml.sax.Attributes;
34
import jdk.internal.org.xml.sax.InputSource;
35
import jdk.internal.org.xml.sax.SAXException;
36
import jdk.internal.org.xml.sax.SAXParseException;
37
import jdk.internal.org.xml.sax.helpers.DefaultHandler;
38
import jdk.internal.util.xml.impl.SAXParserImpl;
39
import jdk.internal.util.xml.impl.XMLStreamWriterImpl;
40
41
/**
42
* A class used to aid in Properties load and save in XML. This class is
43
* re-implemented using a subset of SAX
44
*
45
* @author Joe Wang
46
* @since 1.8
47
*/
48
public class PropertiesDefaultHandler extends DefaultHandler {
49
50
// Elements specified in the properties.dtd
51
private static final String ELEMENT_ROOT = "properties";
52
private static final String ELEMENT_COMMENT = "comment";
53
private static final String ELEMENT_ENTRY = "entry";
54
private static final String ATTR_KEY = "key";
55
// The required DTD URI for exported properties
56
private static final String PROPS_DTD_DECL =
57
"<!DOCTYPE properties SYSTEM \"http://java.sun.com/dtd/properties.dtd\">";
58
private static final String PROPS_DTD_URI =
59
"http://java.sun.com/dtd/properties.dtd";
60
private static final String PROPS_DTD =
61
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
62
+ "<!-- DTD for properties -->"
63
+ "<!ELEMENT properties ( comment?, entry* ) >"
64
+ "<!ATTLIST properties"
65
+ " version CDATA #FIXED \"1.0\">"
66
+ "<!ELEMENT comment (#PCDATA) >"
67
+ "<!ELEMENT entry (#PCDATA) >"
68
+ "<!ATTLIST entry "
69
+ " key CDATA #REQUIRED>";
70
/**
71
* Version number for the format of exported properties files.
72
*/
73
private static final String EXTERNAL_XML_VERSION = "1.0";
74
private Properties properties;
75
76
public void load(Properties props, InputStream in)
77
throws IOException, InvalidPropertiesFormatException, UnsupportedEncodingException
78
{
79
this.properties = props;
80
81
try {
82
SAXParser parser = new SAXParserImpl();
83
parser.parse(in, this);
84
} catch (SAXException saxe) {
85
throw new InvalidPropertiesFormatException(saxe);
86
}
87
88
/**
89
* String xmlVersion = propertiesElement.getAttribute("version"); if
90
* (xmlVersion.compareTo(EXTERNAL_XML_VERSION) > 0) throw new
91
* InvalidPropertiesFormatException( "Exported Properties file format
92
* version " + xmlVersion + " is not supported. This java installation
93
* can read" + " versions " + EXTERNAL_XML_VERSION + " or older. You" +
94
* " may need to install a newer version of JDK.");
95
*/
96
}
97
98
public void store(Properties props, OutputStream os, String comment, Charset charset)
99
throws IOException
100
{
101
try {
102
XMLStreamWriter writer = new XMLStreamWriterImpl(os, charset);
103
writer.writeStartDocument();
104
writer.writeDTD(PROPS_DTD_DECL);
105
writer.writeStartElement(ELEMENT_ROOT);
106
if (comment != null && !comment.isEmpty()) {
107
writer.writeStartElement(ELEMENT_COMMENT);
108
writer.writeCharacters(comment);
109
writer.writeEndElement();
110
}
111
112
synchronized(props) {
113
for (Entry<Object, Object> e : props.entrySet()) {
114
final Object k = e.getKey();
115
final Object v = e.getValue();
116
if (k instanceof String && v instanceof String) {
117
writer.writeStartElement(ELEMENT_ENTRY);
118
writer.writeAttribute(ATTR_KEY, (String)k);
119
writer.writeCharacters((String)v);
120
writer.writeEndElement();
121
} else {
122
throw new ClassCastException(
123
"Keys and values in Properties must be Strings");
124
}
125
}
126
}
127
128
writer.writeEndElement();
129
writer.writeEndDocument();
130
writer.flush();
131
} catch (XMLStreamException e) {
132
if (e.getCause() instanceof UnsupportedEncodingException) {
133
throw (UnsupportedEncodingException) e.getCause();
134
}
135
throw new IOException(e);
136
}
137
138
}
139
////////////////////////////////////////////////////////////////////
140
// Validate while parsing
141
////////////////////////////////////////////////////////////////////
142
static final String ALLOWED_ELEMENTS = "comment, entry";
143
static final String ALLOWED_COMMENT = "comment";
144
////////////////////////////////////////////////////////////////////
145
// Handler methods
146
////////////////////////////////////////////////////////////////////
147
StringBuilder buf = new StringBuilder();
148
boolean sawRoot = false; // whether a valid root element exists
149
boolean sawComment = false;
150
boolean validEntry = false;
151
String key;
152
String rootElm;
153
154
@Override
155
public void startElement(String uri, String localName, String qName, Attributes attributes)
156
throws SAXException
157
{
158
if (sawRoot) {
159
if (!ALLOWED_ELEMENTS.contains(qName)) {
160
fatalError(new SAXParseException("Element type \"" + qName + "\" must be declared.", null));
161
}
162
} else {
163
// check whether the root has been declared in the DTD
164
if (rootElm == null) {
165
fatalError(new SAXParseException("An XML properties document must contain"
166
+ " the DOCTYPE declaration as defined by java.util.Properties.", null));
167
}
168
169
// check whether the element name matches the declaration
170
if (!rootElm.equals(qName)) {
171
fatalError(new SAXParseException("Document root element \"" + qName
172
+ "\", must match DOCTYPE root \"" + rootElm + "\"", null));
173
}
174
175
// this is a valid root element
176
sawRoot = true;
177
}
178
179
if (qName.equals(ELEMENT_ENTRY)) {
180
validEntry = true;
181
key = attributes.getValue(ATTR_KEY);
182
if (key == null) {
183
fatalError(new SAXParseException("Attribute \"key\" is required and " +
184
"must be specified for element type \"entry\"", null));
185
}
186
} else if (qName.equals(ALLOWED_COMMENT)) {
187
if (sawComment) {
188
fatalError(new SAXParseException("Only one comment element may be allowed. "
189
+ "The content of element type \"properties\" must match \"(comment?,entry*)\"", null));
190
}
191
sawComment = true;
192
}
193
}
194
195
@Override
196
public void characters(char[] ch, int start, int length) throws SAXException {
197
if (validEntry) {
198
buf.append(ch, start, length);
199
}
200
}
201
202
@Override
203
public void endElement(String uri, String localName, String qName) throws SAXException {
204
if (!ALLOWED_ELEMENTS.contains(qName) && !ELEMENT_ROOT.equals(qName)) {
205
fatalError(new SAXParseException("Element: " + qName +
206
" is invalid, must match \"(comment?,entry*)\".", null));
207
}
208
209
if (validEntry) {
210
properties.setProperty(key, buf.toString());
211
buf.delete(0, buf.length());
212
validEntry = false;
213
}
214
}
215
216
@Override
217
public InputSource resolveEntity(String pubid, String sysid)
218
throws SAXException, IOException {
219
{
220
if (sysid.equals(PROPS_DTD_URI)) {
221
// The properties DTD is known to the handler, no need to parse it
222
return null;
223
}
224
throw new SAXException("Invalid system identifier: " + sysid);
225
}
226
}
227
228
@Override
229
public void error(SAXParseException x) throws SAXException {
230
throw x;
231
}
232
233
@Override
234
public void fatalError(SAXParseException x) throws SAXException {
235
throw x;
236
}
237
238
@Override
239
public void warning(SAXParseException x) throws SAXException {
240
throw x;
241
}
242
243
// SAX2 extension from DTDHandler
244
245
@Override
246
public void startDTD (String name, String publicId, String systemId) throws SAXException
247
{
248
if (!ELEMENT_ROOT.equals(name) || !PROPS_DTD_URI.equals(systemId)) {
249
fatalError(new SAXParseException("An XML properties document must contain"
250
+ " the DOCTYPE declaration as defined by java.util.Properties.", null));
251
}
252
rootElm = name;
253
}
254
255
@Override
256
public void startInternalSub () throws SAXException
257
{
258
fatalError(new SAXParseException("Internal DTD subset is not allowed. " +
259
"The Properties XML document must have the following DOCTYPE declaration: \n" +
260
PROPS_DTD_DECL, null));
261
}
262
}
263
264