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  */