1 /* |
|
2 * Licensed to the Apache Software Foundation (ASF) under one or more |
|
3 * contributor license agreements. See the NOTICE file distributed with |
|
4 * this work for additional information regarding copyright ownership. |
|
5 * The ASF licenses this file to You under the Apache License, Version 2.0 |
|
6 * (the "License"); you may not use this file except in compliance with |
|
7 * the License. You may obtain a copy of the License at |
|
8 * |
|
9 * http://www.apache.org/licenses/LICENSE-2.0 |
|
10 * |
|
11 * Unless required by applicable law or agreed to in writing, software |
|
12 * distributed under the License is distributed on an "AS IS" BASIS, |
|
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
14 * See the License for the specific language governing permissions and |
|
15 * limitations under the License. |
|
16 */ |
|
17 |
|
18 package com.sun.org.apache.xml.internal.resolver.helpers; |
|
19 |
|
20 /** |
|
21 * Static methods for dealing with public identifiers. |
|
22 * |
|
23 * <p>This class defines a set of static methods that can be called |
|
24 * to handle public identifiers.</p> |
|
25 * |
|
26 * @author Norman Walsh |
|
27 * <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a> |
|
28 * |
|
29 */ |
|
30 public abstract class PublicId { |
|
31 |
|
32 protected PublicId() {} |
|
33 |
|
34 /** |
|
35 * Normalize a public identifier. |
|
36 * |
|
37 * <p>Public identifiers must be normalized according to the following |
|
38 * rules before comparisons between them can be made:</p> |
|
39 * |
|
40 * <ul> |
|
41 * <li>Whitespace characters are normalized to spaces (e.g., line feeds, |
|
42 * tabs, etc. become spaces).</li> |
|
43 * <li>Leading and trailing whitespace is removed.</li> |
|
44 * <li>Multiple internal whitespaces are normalized to a single |
|
45 * space.</li> |
|
46 * </ul> |
|
47 * |
|
48 * <p>This method is declared static so that other classes |
|
49 * can use it directly.</p> |
|
50 * |
|
51 * @param publicId The unnormalized public identifier. |
|
52 * |
|
53 * @return The normalized identifier. |
|
54 */ |
|
55 public static String normalize(String publicId) { |
|
56 String normal = publicId.replace('\t', ' '); |
|
57 normal = normal.replace('\r', ' '); |
|
58 normal = normal.replace('\n', ' '); |
|
59 normal = normal.trim(); |
|
60 |
|
61 int pos; |
|
62 |
|
63 while ((pos = normal.indexOf(" ")) >= 0) { |
|
64 normal = normal.substring(0, pos) + normal.substring(pos+1); |
|
65 } |
|
66 return normal; |
|
67 } |
|
68 |
|
69 /** |
|
70 * Encode a public identifier as a "publicid" URN. |
|
71 * |
|
72 * <p>This method is declared static so that other classes |
|
73 * can use it directly.</p> |
|
74 * |
|
75 * @param publicId The unnormalized public identifier. |
|
76 * |
|
77 * @return The normalized identifier. |
|
78 */ |
|
79 public static String encodeURN(String publicId) { |
|
80 String urn = PublicId.normalize(publicId); |
|
81 |
|
82 urn = PublicId.stringReplace(urn, "%", "%25"); |
|
83 urn = PublicId.stringReplace(urn, ";", "%3B"); |
|
84 urn = PublicId.stringReplace(urn, "'", "%27"); |
|
85 urn = PublicId.stringReplace(urn, "?", "%3F"); |
|
86 urn = PublicId.stringReplace(urn, "#", "%23"); |
|
87 urn = PublicId.stringReplace(urn, "+", "%2B"); |
|
88 urn = PublicId.stringReplace(urn, " ", "+"); |
|
89 urn = PublicId.stringReplace(urn, "::", ";"); |
|
90 urn = PublicId.stringReplace(urn, ":", "%3A"); |
|
91 urn = PublicId.stringReplace(urn, "//", ":"); |
|
92 urn = PublicId.stringReplace(urn, "/", "%2F"); |
|
93 |
|
94 StringBuilder buffer = new StringBuilder(13 + urn.length()); |
|
95 buffer.append("urn:publicid:"); |
|
96 buffer.append(urn); |
|
97 return buffer.toString(); |
|
98 } |
|
99 |
|
100 /** |
|
101 * Decode a "publicid" URN into a public identifier. |
|
102 * |
|
103 * <p>This method is declared static so that other classes |
|
104 * can use it directly.</p> |
|
105 * |
|
106 * @param urn The urn:publicid: URN |
|
107 * |
|
108 * @return The normalized identifier. |
|
109 */ |
|
110 public static String decodeURN(String urn) { |
|
111 String publicId; |
|
112 if (urn.startsWith("urn:publicid:")) { |
|
113 publicId = urn.substring(13); |
|
114 } |
|
115 else { |
|
116 return urn; |
|
117 } |
|
118 |
|
119 final boolean hasEscape = (publicId.indexOf('%') >= 0); |
|
120 if (hasEscape) { |
|
121 publicId = PublicId.stringReplace(publicId, "%2F", "/"); |
|
122 } |
|
123 publicId = PublicId.stringReplace(publicId, ":", "//"); |
|
124 if (hasEscape) { |
|
125 publicId = PublicId.stringReplace(publicId, "%3A", ":"); |
|
126 } |
|
127 publicId = PublicId.stringReplace(publicId, ";", "::"); |
|
128 publicId = PublicId.stringReplace(publicId, "+", " "); |
|
129 if (hasEscape) { |
|
130 publicId = PublicId.stringReplace(publicId, "%2B", "+"); |
|
131 publicId = PublicId.stringReplace(publicId, "%23", "#"); |
|
132 publicId = PublicId.stringReplace(publicId, "%3F", "?"); |
|
133 publicId = PublicId.stringReplace(publicId, "%27", "'"); |
|
134 publicId = PublicId.stringReplace(publicId, "%3B", ";"); |
|
135 publicId = PublicId.stringReplace(publicId, "%25", "%"); |
|
136 } |
|
137 |
|
138 return publicId; |
|
139 } |
|
140 |
|
141 /** |
|
142 * Replace one string with another. |
|
143 */ |
|
144 private static String stringReplace(String str, |
|
145 String oldStr, |
|
146 String newStr) { |
|
147 int pos = str.indexOf(oldStr); |
|
148 if (pos >= 0) { |
|
149 final StringBuilder buffer = new StringBuilder(); |
|
150 final int oldStrLength = oldStr.length(); |
|
151 int start = 0; |
|
152 do { |
|
153 for (int i = start; i < pos; ++i) { |
|
154 buffer.append(str.charAt(i)); |
|
155 } |
|
156 buffer.append(newStr); |
|
157 start = pos + oldStrLength; |
|
158 pos = str.indexOf(oldStr, start); |
|
159 } |
|
160 while (pos >= 0); |
|
161 final int strLength = str.length(); |
|
162 for (int i = start; i < strLength; ++i) { |
|
163 buffer.append(str.charAt(i)); |
|
164 } |
|
165 return buffer.toString(); |
|
166 } |
|
167 return str; |
|
168 } |
|
169 } |
|