Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/jdom/Namespace.java


1   /*-- 
2   
3    $Id: Namespace.java,v 1.41 2004/02/27 11:32:57 jhunter Exp $
4   
5    Copyright (C) 2000-2004 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.41 $, $Date: 2004/02/27 11:32:57 $
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      // XXX We may need to make the namespaces HashMap synchronized with
80      // reader/writer locks or perhaps make Namespace no longer a flyweight.
81      // As written, multiple put() calls may happen from different threads 
82      // concurrently and cause a ConcurrentModificationException. See
83      // http://lists.denveronline.net/lists/jdom-interest/2000-September/003009.html.
84      // No one has ever reported this over the many years, so don't worry yet.
85  
86      private static final String CVS_ID =
87        "@(#) $RCSfile: Namespace.java,v $ $Revision: 1.41 $ $Date: 2004/02/27 11:32:57 $ $Name: jdom_1_0 $";
88  
89      /** 
90       * Factory list of namespaces. 
91       * Keys are <i>prefix</i>&amp;<i>URI</i>. 
92       * Values are Namespace objects 
93       */
94      private static HashMap namespaces;
95  
96      /** Define a <code>Namespace</code> for when <i>not</i> in a namespace */
97      public static final Namespace NO_NAMESPACE = new Namespace("", "");
98  
99      /** Define a <code>Namespace</code> for the standard xml prefix. */
100     public static final Namespace XML_NAMESPACE =
101         new Namespace("xml", "http://www.w3.org/XML/1998/namespace");
102 
103     /** The prefix mapped to this namespace */
104     private String prefix;
105 
106     /** The URI for this namespace */
107     private String uri;
108 
109     /**
110      * This static initializer acts as a factory contructor.
111      * It sets up storage and required initial values.
112      */
113     static {
114         namespaces = new HashMap();
115 
116         // Add the "empty" namespace
117         namespaces.put("&", NO_NAMESPACE);
118         namespaces.put("xml&http://www.w3.org/XML/1998/namespace",
119                        XML_NAMESPACE);
120     }
121 
122     /**
123      * This will retrieve (if in existence) or create (if not) a 
124      * <code>Namespace</code> for the supplied prefix and URI.
125      *
126      * @param prefix <code>String</code> prefix to map to 
127      *               <code>Namespace</code>.
128      * @param uri <code>String</code> URI of new <code>Namespace</code>.
129      * @return <code>Namespace</code> - ready to use namespace.
130      * @throws IllegalNameException if the given prefix and uri make up
131      *         an illegal namespace name.
132      */
133     public static Namespace getNamespace(String prefix, String uri) {
134         // Sanity checking
135         if ((prefix == null) || (prefix.trim().equals(""))) {
136             prefix = "";
137         }
138         if ((uri == null) || (uri.trim().equals(""))) {
139             uri = "";
140         }
141 
142         // Return existing namespace if found. The preexisting namespaces
143         // should all be legal. In other words, an illegal namespace won't
144         // have been placed in this.  Thus we can do this test before
145         // verifying the URI and prefix.
146         String lookup = new StringBuffer(64)
147             .append(prefix).append('&').append(uri).toString();
148         Namespace preexisting = (Namespace) namespaces.get(lookup);
149         if (preexisting != null) {
150             return preexisting;
151         }
152 
153         // Ensure proper naming
154         String reason;
155         if ((reason = Verifier.checkNamespacePrefix(prefix)) != null) {
156             throw new IllegalNameException(prefix, "Namespace prefix", reason);
157         }
158         if ((reason = Verifier.checkNamespaceURI(uri)) != null) {
159             throw new IllegalNameException(uri, "Namespace URI", reason);
160         }
161 
162         // Unless the "empty" Namespace (no prefix and no URI), require a URI
163         if ((!prefix.equals("")) && (uri.equals(""))) {
164             throw new IllegalNameException("", "namespace",
165                 "Namespace URIs must be non-null and non-empty Strings");
166         }
167 
168         // Handle XML namespace mislabels. If the user requested the correct
169         // namespace and prefix -- xml, http://www.w3.org/XML/1998/namespace
170         // -- then it was already returned from the preexisting namespaces.
171         // Thus any use of the xml prefix or the
172         // http://www.w3.org/XML/1998/namespace URI at this point must be
173         // incorrect. 
174         if (prefix.equals("xml")) {
175             throw new IllegalNameException(prefix, "Namespace prefix",
176              "The xml prefix can only be bound to " +
177              "http://www.w3.org/XML/1998/namespace");        
178         }
179         // The erratum to Namespaces in XML 1.0 that suggests this 
180         // next check is controversial. Not everyone accepts it. 
181         if (uri.equals("http://www.w3.org/XML/1998/namespace")) {
182             throw new IllegalNameException(uri, "Namespace URI",
183              "The http://www.w3.org/XML/1998/namespace must be bound to " +
184              "the xml prefix.");        
185         }
186 
187         // Finally, store and return
188         Namespace ns = new Namespace(prefix, uri);
189         namespaces.put(lookup, ns);
190         return ns;
191     }
192 
193     /**
194      * This will retrieve (if in existence) or create (if not) a 
195      * <code>Namespace</code> for the supplied URI, and make it usable 
196      * as a default namespace, as no prefix is supplied.
197      *
198      * @param uri <code>String</code> URI of new <code>Namespace</code>.
199      * @return <code>Namespace</code> - ready to use namespace.
200      */
201     public static Namespace getNamespace(String uri) {
202         return getNamespace("", uri);
203     }
204 
205     /**
206      * This constructor handles creation of a <code>Namespace</code> object
207      * with a prefix and URI; it is intentionally left <code>private</code>
208      * so that it cannot be invoked by external programs/code.
209      *
210      * @param prefix <code>String</code> prefix to map to this namespace.
211      * @param uri <code>String</code> URI for namespace.
212      */
213     private Namespace(String prefix, String uri) {
214         this.prefix = prefix;
215         this.uri = uri;
216     }
217 
218     /**
219      * This returns the prefix mapped to this <code>Namespace</code>.
220      *
221      * @return <code>String</code> - prefix for this <code>Namespace</code>.
222      */
223     public String getPrefix() {
224         return prefix;
225     }
226 
227     /**
228      * This returns the namespace URI for this <code>Namespace</code>.
229      *
230      * @return <code>String</code> - URI for this <code>Namespace</code>.
231      */
232     public String getURI() {
233         return uri;
234     }
235 
236     /**
237      * This tests for equality - Two <code>Namespaces</code>
238      * are equal if and only if their URIs are byte-for-byte equals.
239      *
240      * @param ob <code>Object</code> to compare to this <code>Namespace</code>.
241      * @return <code>boolean</code> - whether the supplied object is equal to
242      *         this <code>Namespace</code>.
243      */
244     public boolean equals(Object ob) {
245         if (this == ob) {
246             return true;
247         }
248         if (ob instanceof Namespace) {  // instanceof returns false if null
249             return uri.equals(((Namespace)ob).uri);
250         }
251         return false;
252     }
253 
254     /**
255      * This returns a <code>String</code> representation of this 
256      * <code>Namespace</code>, suitable for use in debugging.
257      *
258      * @return <code>String</code> - information about this instance.
259      */
260     public String toString() {
261         return "[Namespace: prefix \"" + prefix + "\" is mapped to URI \"" + 
262                uri + "\"]";
263     }
264 
265     /**
266      * This returns a probably unique hash code for the <code>Namespace</code>.
267      * If two namespaces have the same URI, they are equal and have the same
268      * hash code, even if they have different prefixes.
269      *
270      * @return <code>int</code> - hash code for this <code>Namespace</code>.
271      */
272     public int hashCode() {
273         return uri.hashCode();
274     }
275 }