/* |
|
* 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(); |
|
} |
|
} |