1   
2   
3   
4   
5   
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          
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              
57              try {
58                  Class clazz = Class.forName(CONCURRENTREADERHASHMAP_CLASS);
59                  cache = (Map) clazz.newInstance();
60                  noPrefixCache = (Map) clazz.newInstance();
61              } catch (Throwable t2) {
62                  
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 
183 
184 
185 
186 
187 
188 
189 
190 
191 
192 
193 
194 
195 
196 
197 
198 
199 
200 
201 
202 
203 
204 
205 
206 
207 
208 
209 
210 
211 
212 
213 
214 
215 
216