View Javadoc

1   /*
2    * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
3    *
4    * This software is open source.
5    * See the bottom of this file for the licence.
6    */
7   
8   package org.dom4j.tree;
9   
10  import java.lang.ref.WeakReference;
11  import java.lang.reflect.Constructor;
12  import java.util.Map;
13  
14  import org.dom4j.Namespace;
15  
16  /***
17   * <p>
18   * <code>NamespaceCache</code> caches instances of
19   * <code>DefaultNamespace</code> for reuse both across documents and within
20   * documents.
21   * </p>
22   * 
23   * @author <a href="mailto:james.strachan@metastuff.com">James Strachan </a>
24   * @author Maarten Coene
25   * @author Brett Finnell
26   * @version $Revision: 1.15 $
27   */
28  public class NamespaceCache {
29      private static final String CONCURRENTREADERHASHMAP_CLASS
30              = "EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap";
31  
32      /***
33       * Cache of {@link Map}instances indexed by URI which contain caches of
34       * {@link Namespace}for each prefix
35       */
36      protected static Map cache;
37  
38      /***
39       * Cache of {@link Namespace}instances indexed by URI for default
40       * namespaces with no prefixes
41       */
42      protected static Map noPrefixCache;
43  
44      static {
45          /* Try the java.util.concurrent.ConcurrentHashMap first. */
46          try {
47              Class clazz = Class
48                      .forName("java.util.concurrent.ConcurrentHashMap");
49              Constructor construct = clazz.getConstructor(new Class[] {
50                      Integer.TYPE, Float.TYPE, Integer.TYPE });
51              cache = (Map) construct.newInstance(new Object[] {new Integer(11),
52                      new Float(0.75f), new Integer(1) });
53              noPrefixCache = (Map) construct.newInstance(new Object[] {
54                      new Integer(11), new Float(0.75f), new Integer(1) });
55          } catch (Throwable t1) {
56              /* Try to use the util.concurrent library (if in classpath) */
57              try {
58                  Class clazz = Class.forName(CONCURRENTREADERHASHMAP_CLASS);
59                  cache = (Map) clazz.newInstance();
60                  noPrefixCache = (Map) clazz.newInstance();
61              } catch (Throwable t2) {
62                  /* If previous implementations fail, use internal one */
63                  cache = new ConcurrentReaderHashMap();
64                  noPrefixCache = new ConcurrentReaderHashMap();
65              }
66          }
67      }
68  
69      /***
70       * DOCUMENT ME!
71       * 
72       * @param prefix
73       *            DOCUMENT ME!
74       * @param uri
75       *            DOCUMENT ME!
76       * 
77       * @return the namespace for the given prefix and uri
78       */
79      public Namespace get(String prefix, String uri) {
80          Map uriCache = getURICache(uri);
81          WeakReference ref = (WeakReference) uriCache.get(prefix);
82          Namespace answer = null;
83  
84          if (ref != null) {
85              answer = (Namespace) ref.get();
86          }
87  
88          if (answer == null) {
89              synchronized (uriCache) {
90                  ref = (WeakReference) uriCache.get(prefix);
91  
92                  if (ref != null) {
93                      answer = (Namespace) ref.get();
94                  }
95  
96                  if (answer == null) {
97                      answer = createNamespace(prefix, uri);
98                      uriCache.put(prefix, new WeakReference(answer));
99                  }
100             }
101         }
102 
103         return answer;
104     }
105 
106     /***
107      * DOCUMENT ME!
108      * 
109      * @param uri
110      *            DOCUMENT ME!
111      * 
112      * @return the name model for the given name and namepsace
113      */
114     public Namespace get(String uri) {
115         WeakReference ref = (WeakReference) noPrefixCache.get(uri);
116         Namespace answer = null;
117 
118         if (ref != null) {
119             answer = (Namespace) ref.get();
120         }
121 
122         if (answer == null) {
123             synchronized (noPrefixCache) {
124                 ref = (WeakReference) noPrefixCache.get(uri);
125 
126                 if (ref != null) {
127                     answer = (Namespace) ref.get();
128                 }
129 
130                 if (answer == null) {
131                     answer = createNamespace("", uri);
132                     noPrefixCache.put(uri, new WeakReference(answer));
133                 }
134             }
135         }
136 
137         return answer;
138     }
139 
140     /***
141      * DOCUMENT ME!
142      * 
143      * @param uri
144      *            DOCUMENT ME!
145      * 
146      * @return the cache for the given namespace URI. If one does not currently
147      *         exist it is created.
148      */
149     protected Map getURICache(String uri) {
150         Map answer = (Map) cache.get(uri);
151 
152         if (answer == null) {
153             synchronized (cache) {
154                 answer = (Map) cache.get(uri);
155 
156                 if (answer == null) {
157                     answer = new ConcurrentReaderHashMap();
158                     cache.put(uri, answer);
159                 }
160             }
161         }
162 
163         return answer;
164     }
165 
166     /***
167      * A factory method to create {@link Namespace}instance
168      * 
169      * @param prefix
170      *            DOCUMENT ME!
171      * @param uri
172      *            DOCUMENT ME!
173      * 
174      * @return a newly created {@link Namespace}instance.
175      */
176     protected Namespace createNamespace(String prefix, String uri) {
177         return new Namespace(prefix, uri);
178     }
179 }
180 
181 /*
182  * Redistribution and use of this software and associated documentation
183  * ("Software"), with or without modification, are permitted provided that the
184  * following conditions are met:
185  * 
186  * 1. Redistributions of source code must retain copyright statements and
187  * notices. Redistributions must also contain a copy of this document.
188  * 
189  * 2. Redistributions in binary form must reproduce the above copyright notice,
190  * this list of conditions and the following disclaimer in the documentation
191  * and/or other materials provided with the distribution.
192  * 
193  * 3. The name "DOM4J" must not be used to endorse or promote products derived
194  * from this Software without prior written permission of MetaStuff, Ltd. For
195  * written permission, please contact dom4j-info@metastuff.com.
196  * 
197  * 4. Products derived from this Software may not be called "DOM4J" nor may
198  * "DOM4J" appear in their names without prior written permission of MetaStuff,
199  * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
200  * 
201  * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
202  * 
203  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
204  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
205  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
206  * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
207  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
208  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
209  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
210  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
211  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
212  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
213  * POSSIBILITY OF SUCH DAMAGE.
214  * 
215  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
216  */