0
|
1 /*--
|
|
2
|
|
3 $Id: Namespace.java,v 1.44 2008/12/17 23:22:48 jhunter Exp $
|
|
4
|
|
5 Copyright (C) 2000-2007 Jason Hunter & Brett McLaughlin.
|
|
6 All rights reserved.
|
|
7
|
|
8 Redistribution and use in source and binary forms, with or without
|
|
9 modification, are permitted provided that the following conditions
|
|
10 are met:
|
|
11
|
|
12 1. Redistributions of source code must retain the above copyright
|
|
13 notice, this list of conditions, and the following disclaimer.
|
|
14
|
|
15 2. Redistributions in binary form must reproduce the above copyright
|
|
16 notice, this list of conditions, and the disclaimer that follows
|
|
17 these conditions in the documentation and/or other materials
|
|
18 provided with the distribution.
|
|
19
|
|
20 3. The name "JDOM" must not be used to endorse or promote products
|
|
21 derived from this software without prior written permission. For
|
|
22 written permission, please contact <request_AT_jdom_DOT_org>.
|
|
23
|
|
24 4. Products derived from this software may not be called "JDOM", nor
|
|
25 may "JDOM" appear in their name, without prior written permission
|
|
26 from the JDOM Project Management <request_AT_jdom_DOT_org>.
|
|
27
|
|
28 In addition, we request (but do not require) that you include in the
|
|
29 end-user documentation provided with the redistribution and/or in the
|
|
30 software itself an acknowledgement equivalent to the following:
|
|
31 "This product includes software developed by the
|
|
32 JDOM Project (http://www.jdom.org/)."
|
|
33 Alternatively, the acknowledgment may be graphical using the logos
|
|
34 available at http://www.jdom.org/images/logos.
|
|
35
|
|
36 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
|
37 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
38 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
39 DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT
|
|
40 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
41 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
42 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
|
43 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
44 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
45 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
46 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
47 SUCH DAMAGE.
|
|
48
|
|
49 This software consists of voluntary contributions made by many
|
|
50 individuals on behalf of the JDOM Project and was originally
|
|
51 created by Jason Hunter <jhunter_AT_jdom_DOT_org> and
|
|
52 Brett McLaughlin <brett_AT_jdom_DOT_org>. For more information
|
|
53 on the JDOM Project, please see <http://www.jdom.org/>.
|
|
54
|
|
55 */
|
|
56
|
|
57 package org.jdom;
|
|
58
|
|
59 import java.util.*;
|
|
60
|
|
61 /**
|
|
62 * An XML namespace representation, as well as a factory for creating XML
|
|
63 * namespace objects. Namespaces are not Serializable, however objects that use
|
|
64 * namespaces have special logic to handle serialization manually. These classes
|
|
65 * call the getNamespace() method on deserialization to ensure there is one
|
|
66 * unique Namespace object for any unique prefix/uri pair.
|
|
67 *
|
|
68 * @version $Revision: 1.44 $, $Date: 2008/12/17 23:22:48 $
|
|
69 * @author Brett McLaughlin
|
|
70 * @author Elliotte Rusty Harold
|
|
71 * @author Jason Hunter
|
|
72 * @author Wesley Biggs
|
|
73 */
|
|
74 public final class Namespace {
|
|
75
|
|
76 // XXX May want to use weak references to keep the maps from growing
|
|
77 // large with extended use
|
|
78
|
|
79 private static final String CVS_ID =
|
|
80 "@(#) $RCSfile: Namespace.java,v $ $Revision: 1.44 $ $Date: 2008/12/17 23:22:48 $ $Name: jdom_1_1_1 $";
|
|
81
|
|
82 /**
|
|
83 * Factory list of namespaces.
|
|
84 * Keys are <i>prefix</i>&<i>URI</i>.
|
|
85 * Values are Namespace objects
|
|
86 */
|
|
87 private static HashMap namespaces;
|
|
88
|
|
89 /** Define a <code>Namespace</code> for when <i>not</i> in a namespace */
|
|
90 public static final Namespace NO_NAMESPACE = new Namespace("", "");
|
|
91
|
|
92 /** Define a <code>Namespace</code> for the standard xml prefix. */
|
|
93 public static final Namespace XML_NAMESPACE =
|
|
94 new Namespace("xml", "http://www.w3.org/XML/1998/namespace");
|
|
95
|
|
96 /** The prefix mapped to this namespace */
|
|
97 private String prefix;
|
|
98
|
|
99 /** The URI for this namespace */
|
|
100 private String uri;
|
|
101
|
|
102 /**
|
|
103 * This static initializer acts as a factory contructor.
|
|
104 * It sets up storage and required initial values.
|
|
105 */
|
|
106 static {
|
|
107 namespaces = new HashMap(16);
|
|
108
|
|
109 // Add the "empty" namespace
|
|
110 namespaces.put(new NamespaceKey(NO_NAMESPACE), NO_NAMESPACE);
|
|
111 namespaces.put(new NamespaceKey(XML_NAMESPACE), XML_NAMESPACE);
|
|
112 }
|
|
113
|
|
114 /**
|
|
115 * This will retrieve (if in existence) or create (if not) a
|
|
116 * <code>Namespace</code> for the supplied prefix and URI.
|
|
117 *
|
|
118 * @param prefix <code>String</code> prefix to map to
|
|
119 * <code>Namespace</code>.
|
|
120 * @param uri <code>String</code> URI of new <code>Namespace</code>.
|
|
121 * @return <code>Namespace</code> - ready to use namespace.
|
|
122 * @throws IllegalNameException if the given prefix and uri make up
|
|
123 * an illegal namespace name.
|
|
124 */
|
|
125 public static Namespace getNamespace(String prefix, String uri) {
|
|
126 // Sanity checking
|
|
127 if ((prefix == null) || (prefix.trim().equals(""))) {
|
|
128 // Short-cut out for common case of no namespace
|
|
129 if ((uri == null) || (uri.trim().equals(""))) {
|
|
130 return NO_NAMESPACE;
|
|
131 }
|
|
132 prefix = "";
|
|
133 }
|
|
134 else if ((uri == null) || (uri.trim().equals(""))) {
|
|
135 uri = "";
|
|
136 }
|
|
137
|
|
138 // Return existing namespace if found. The preexisting namespaces
|
|
139 // should all be legal. In other words, an illegal namespace won't
|
|
140 // have been placed in this. Thus we can do this test before
|
|
141 // verifying the URI and prefix.
|
|
142 NamespaceKey lookup = new NamespaceKey(prefix, uri);
|
|
143 Namespace preexisting;
|
|
144 synchronized (namespaces) {
|
|
145 preexisting = (Namespace) namespaces.get(lookup);
|
|
146 }
|
|
147 if (preexisting != null) {
|
|
148 return preexisting;
|
|
149 }
|
|
150
|
|
151 // Ensure proper naming
|
|
152 String reason;
|
|
153 if ((reason = Verifier.checkNamespacePrefix(prefix)) != null) {
|
|
154 throw new IllegalNameException(prefix, "Namespace prefix", reason);
|
|
155 }
|
|
156 if ((reason = Verifier.checkNamespaceURI(uri)) != null) {
|
|
157 throw new IllegalNameException(uri, "Namespace URI", reason);
|
|
158 }
|
|
159
|
|
160 // Unless the "empty" Namespace (no prefix and no URI), require a URI
|
|
161 if ((!prefix.equals("")) && (uri.equals(""))) {
|
|
162 throw new IllegalNameException("", "namespace",
|
|
163 "Namespace URIs must be non-null and non-empty Strings");
|
|
164 }
|
|
165
|
|
166 // Handle XML namespace mislabels. If the user requested the correct
|
|
167 // namespace and prefix -- xml, http://www.w3.org/XML/1998/namespace
|
|
168 // -- then it was already returned from the preexisting namespaces.
|
|
169 // Thus any use of the xml prefix or the
|
|
170 // http://www.w3.org/XML/1998/namespace URI at this point must be
|
|
171 // incorrect.
|
|
172 if (prefix.equals("xml")) {
|
|
173 throw new IllegalNameException(prefix, "Namespace prefix",
|
|
174 "The xml prefix can only be bound to " +
|
|
175 "http://www.w3.org/XML/1998/namespace");
|
|
176 }
|
|
177
|
|
178 // The erratum to Namespaces in XML 1.0 that suggests this
|
|
179 // next check is controversial. Not everyone accepts it.
|
|
180 if (uri.equals("http://www.w3.org/XML/1998/namespace")) {
|
|
181 throw new IllegalNameException(uri, "Namespace URI",
|
|
182 "The http://www.w3.org/XML/1998/namespace must be bound to " +
|
|
183 "the xml prefix.");
|
|
184 }
|
|
185
|
|
186 // Finally, store and return
|
|
187 Namespace ns = new Namespace(prefix, uri);
|
|
188 synchronized (namespaces) {
|
|
189 namespaces.put(lookup, ns);
|
|
190 }
|
|
191 return ns;
|
|
192 }
|
|
193
|
|
194 /**
|
|
195 * This will retrieve (if in existence) or create (if not) a
|
|
196 * <code>Namespace</code> for the supplied URI, and make it usable
|
|
197 * as a default namespace, as no prefix is supplied.
|
|
198 *
|
|
199 * @param uri <code>String</code> URI of new <code>Namespace</code>.
|
|
200 * @return <code>Namespace</code> - ready to use namespace.
|
|
201 */
|
|
202 public static Namespace getNamespace(String uri) {
|
|
203 return getNamespace("", uri);
|
|
204 }
|
|
205
|
|
206 /**
|
|
207 * This constructor handles creation of a <code>Namespace</code> object
|
|
208 * with a prefix and URI; it is intentionally left <code>private</code>
|
|
209 * so that it cannot be invoked by external programs/code.
|
|
210 *
|
|
211 * @param prefix <code>String</code> prefix to map to this namespace.
|
|
212 * @param uri <code>String</code> URI for namespace.
|
|
213 */
|
|
214 private Namespace(String prefix, String uri) {
|
|
215 this.prefix = prefix;
|
|
216 this.uri = uri;
|
|
217 }
|
|
218
|
|
219 /**
|
|
220 * This returns the prefix mapped to this <code>Namespace</code>.
|
|
221 *
|
|
222 * @return <code>String</code> - prefix for this <code>Namespace</code>.
|
|
223 */
|
|
224 public String getPrefix() {
|
|
225 return prefix;
|
|
226 }
|
|
227
|
|
228 /**
|
|
229 * This returns the namespace URI for this <code>Namespace</code>.
|
|
230 *
|
|
231 * @return <code>String</code> - URI for this <code>Namespace</code>.
|
|
232 */
|
|
233 public String getURI() {
|
|
234 return uri;
|
|
235 }
|
|
236
|
|
237 /**
|
|
238 * This tests for equality - Two <code>Namespaces</code>
|
|
239 * are equal if and only if their URIs are byte-for-byte equals.
|
|
240 *
|
|
241 * @param ob <code>Object</code> to compare to this <code>Namespace</code>.
|
|
242 * @return <code>boolean</code> - whether the supplied object is equal to
|
|
243 * this <code>Namespace</code>.
|
|
244 */
|
|
245 public boolean equals(Object ob) {
|
|
246 if (this == ob) {
|
|
247 return true;
|
|
248 }
|
|
249 if (ob instanceof Namespace) { // instanceof returns false if null
|
|
250 return uri.equals(((Namespace)ob).uri);
|
|
251 }
|
|
252 return false;
|
|
253 }
|
|
254
|
|
255 /**
|
|
256 * This returns a <code>String</code> representation of this
|
|
257 * <code>Namespace</code>, suitable for use in debugging.
|
|
258 *
|
|
259 * @return <code>String</code> - information about this instance.
|
|
260 */
|
|
261 public String toString() {
|
|
262 return "[Namespace: prefix \"" + prefix + "\" is mapped to URI \"" +
|
|
263 uri + "\"]";
|
|
264 }
|
|
265
|
|
266 /**
|
|
267 * This returns a probably unique hash code for the <code>Namespace</code>.
|
|
268 * If two namespaces have the same URI, they are equal and have the same
|
|
269 * hash code, even if they have different prefixes.
|
|
270 *
|
|
271 * @return <code>int</code> - hash code for this <code>Namespace</code>.
|
|
272 */
|
|
273 public int hashCode() {
|
|
274 return uri.hashCode();
|
|
275 }
|
|
276 }
|