blob: d5b19930c01d2ee4a0d4e066e8e62ef42fc682de [file] [log] [blame]
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.xml.catalog;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
/**
* The Normalizer is responsible for normalizing Public and System Identifiers
* as specified in section 6.2, 6.3 and 6.4 of the specification
* * <a
* href="https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html">
* XML Catalogs, OASIS Standard V1.1, 7 October 2005</a>.
*
* @since 9
*/
class Normalizer {
/**
* Normalize a public identifier in accordance with section 6.2 of the
* Catalog specification.
*
* <p>
* All strings of white space in public identifiers must be normalized to
* single space characters (#x20), and leading and trailing white space must
* be removed.
*
* @param publicId The unnormalized public identifier
*
* @return The normalized identifier
*/
static String normalizePublicId(String publicId) {
if (publicId == null) return null;
StringBuilder sb = new StringBuilder(publicId.length());
char last = 'a';
for (char c : publicId.toCharArray()) {
//skip beginning and duplicate space
if ((c == ' ') && (sb.length() == 0 || last == ' ')) {
continue;
}
//replace whitespace with space
if (c == '\t' || c == '\r' || c == '\n') {
if (last != ' ') {
sb.append(' ');
last = ' ';
}
} else {
sb.append(c);
last = c;
}
}
//remove the last space
if (last == ' ') {
sb.deleteCharAt(sb.length() - 1);
}
return sb.toString();
}
/**
* Encode a public identifier as a "publicid" URN.
*
* @param publicId The unnormalized public identifier
*
* @return The normalized identifier
* @throws CatalogException if encoding failed
*/
static String encodeURN(String publicId) {
String urn = normalizePublicId(publicId);
try {
urn = URLEncoder.encode(urn, "UTF-8");
urn = urn.replace("::", ";");
urn = urn.replace("//", ":");
} catch (UnsupportedEncodingException ex) {
CatalogMessages.reportRunTimeError(CatalogMessages.ERR_OTHER, ex);
}
return Util.URN + urn;
}
/**
* Decode a "publicid" URN into a public identifier.
*
* @param urn The urn:publicid: URN
*
* @return The normalized identifier
* @throws CatalogException if decoding failed
*/
static String decodeURN(String urn) {
String publicId;
if (urn != null && urn.startsWith(Util.URN)) {
publicId = urn.substring(13);
} else {
return urn;
}
try {
publicId = publicId.replace(":", "//");
publicId = publicId.replace(";", "::");
publicId = URLDecoder.decode(publicId, "UTF-8");
} catch (UnsupportedEncodingException ex) {
CatalogMessages.reportRunTimeError(CatalogMessages.ERR_OTHER, ex);
}
return publicId;
}
/**
* Perform character normalization on a URI reference.
*
* @param uriref The URI reference
* @return The normalized URI reference
*/
static String normalizeURI(String uriref) {
if (uriref == null) {
return null;
}
byte[] bytes;
uriref = uriref.trim();
try {
bytes = uriref.getBytes("UTF-8");
} catch (UnsupportedEncodingException uee) {
// this can't happen
return uriref;
}
StringBuilder newRef = new StringBuilder(bytes.length);
for (int count = 0; count < bytes.length; count++) {
int ch = bytes[count] & 0xFF;
if ((ch <= 0x20) // ctrl
|| (ch > 0x7F) // high ascii
|| (ch == 0x22) // "
|| (ch == 0x3C) // <
|| (ch == 0x3E) // >
|| (ch == 0x5C) // \
|| (ch == 0x5E) // ^
|| (ch == 0x60) // `
|| (ch == 0x7B) // {
|| (ch == 0x7C) // |
|| (ch == 0x7D) // }
|| (ch == 0x7F)) {
newRef.append("%").append(String.format("%02X", ch));
} else {
newRef.append((char) bytes[count]);
}
}
return newRef.toString().trim();
}
}