1 package com.ctc.wstx.util;
2
3 import java.util.LinkedHashMap;
4 import java.util.Map;
5
6 /**
7  * Singleton class that implements "fast intern" functionality, essentially
8  * adding a layer that caches Strings that have been previously intern()ed,
9  * but that probably shouldn't be added to symbol tables.
10  * This is usually used by improving intern()ing of things like namespace
11  * URIs.
12  *<p>
13  * Note: that this class extends {@link LinkedHashMap} is an implementation
14  * detail -- no code should ever directly call Map methods.
15  */

16 @SuppressWarnings("serial")
17 public final class InternCache extends LinkedHashMap<String,String>
18 {
19     /**
20      * Let's create cache big enough to usually have enough space for
21      * all entries... (assuming NS URIs only)
22      */

23     private final static int DEFAULT_SIZE = 64;
24
25     /**
26      * Let's limit to hash area size of 1024.
27      */

28     private final static int MAX_SIZE = 660;
29
30     private final static InternCache sInstance = new InternCache();
31
32     private InternCache() {
33         /* Let's also try to seriously minimize collisions... since
34          * collisions are likely to be more costly here, with longer
35          * Strings; so let's use 2/3 ratio (67%) instead of default
36          * (75%)
37          */

38         super(DEFAULT_SIZE, 0.6666f, false);
39     }
40
41     public static InternCache getInstance() {
42         return sInstance;
43     }
44
45     public String intern(String input)
46     {
47         String result;
48
49         /* Let's split sync block to help in edge cases like
50          * [WSTX-220]
51          */

52         synchronized (this) {
53             result = get(input);
54         }
55         if (result == null) {
56             result = input.intern();
57             synchronized (this) {
58                 put(result, result);
59             }
60         }
61         return result;
62     }
63
64     // We will force maximum size here (for [WSTX-237])
65     @Override protected boolean removeEldestEntry(Map.Entry<String,String> eldest)
66     {
67         return size() > MAX_SIZE;
68     }
69 }
70
71