50 51 /** 52 * Subclass of <code>ResourceBundle</code> which mimics 53 * <code>ListResourceBundle</code>, but provides more hooks 54 * for specialized subclass behavior. For general description, 55 * see {@link java.util.ListResourceBundle}. 56 * <p> 57 * This class leaves handleGetObject non-final, and 58 * adds a method createMap which allows subclasses to 59 * use specialized Map implementations. 60 */ 61 public abstract class OpenListResourceBundle extends ResourceBundle { 62 /** 63 * Sole constructor. (For invocation by subclass constructors, typically 64 * implicit.) 65 */ 66 protected OpenListResourceBundle() { 67 } 68 69 // Implements java.util.ResourceBundle.handleGetObject; inherits javadoc specification. 70 public Object handleGetObject(String key) { 71 if (key == null) { 72 throw new NullPointerException(); 73 } 74 75 loadLookupTablesIfNecessary(); 76 return lookup.get(key); // this class ignores locales 77 } 78 79 /** 80 * Implementation of ResourceBundle.getKeys. 81 */ 82 public Enumeration<String> getKeys() { 83 ResourceBundle parent = this.parent; 84 return new ResourceBundleEnumeration(handleGetKeys(), 85 (parent != null) ? parent.getKeys() : null); 86 } 87 88 /** 89 * Returns a set of keys provided in this resource bundle 90 */ 91 public Set<String> handleGetKeys() { 92 loadLookupTablesIfNecessary(); 93 94 return lookup.keySet(); 95 } 96 97 @Override 98 public Set<String> keySet() { 99 if (keyset != null) { 100 return keyset; 101 } 102 Set<String> ks = new HashSet<>(); 103 ks.addAll(handleGetKeys()); 104 if (parent != null) { 105 ks.addAll(parent.keySet()); 106 } 107 synchronized (this) { 108 if (keyset == null) { 109 keyset = ks; 110 } 111 } 112 return keyset; 113 } 114 115 /** 116 * Returns the parent bundle 117 */ 118 public OpenListResourceBundle getParent() { 119 return (OpenListResourceBundle)parent; 120 } 121 122 /** 123 * See ListResourceBundle class description. 124 */ 125 abstract protected Object[][] getContents(); 126 127 /** 128 * Load lookup tables if they haven't been loaded already. 129 */ 130 void loadLookupTablesIfNecessary() { 131 if (lookup == null) { 132 loadLookup(); 133 } 134 } 135 136 /** 137 * We lazily load the lookup hashtable. This function does the 138 * loading. 139 */ 140 private void loadLookup() { 141 Object[][] contents = getContents(); 142 Map<String, Object> temp = createMap(contents.length); 143 for (int i = 0; i < contents.length; ++i) { 144 // key must be non-null String, value must be non-null 145 String key = (String) contents[i][0]; 146 Object value = contents[i][1]; 147 if (key == null || value == null) { 148 throw new NullPointerException(); 149 } 150 temp.put(key, value); 151 } 152 synchronized (this) { 153 if (lookup == null) { 154 lookup = temp; 155 } 156 } 157 } 158 159 /** 160 * Lets subclasses provide specialized Map implementations. 161 * Default uses HashMap. 162 */ 163 protected Map<String, Object> createMap(int size) { 164 return new HashMap<>(size); 165 } 166 167 private volatile Map<String, Object> lookup = null; 168 private volatile Set<String> keyset; 169 } | 50 51 /** 52 * Subclass of <code>ResourceBundle</code> which mimics 53 * <code>ListResourceBundle</code>, but provides more hooks 54 * for specialized subclass behavior. For general description, 55 * see {@link java.util.ListResourceBundle}. 56 * <p> 57 * This class leaves handleGetObject non-final, and 58 * adds a method createMap which allows subclasses to 59 * use specialized Map implementations. 60 */ 61 public abstract class OpenListResourceBundle extends ResourceBundle { 62 /** 63 * Sole constructor. (For invocation by subclass constructors, typically 64 * implicit.) 65 */ 66 protected OpenListResourceBundle() { 67 } 68 69 // Implements java.util.ResourceBundle.handleGetObject; inherits javadoc specification. 70 @Override 71 public Object handleGetObject(String key) { 72 if (key == null) { 73 throw new NullPointerException(); 74 } 75 76 loadLookupTablesIfNecessary(); 77 return lookup.get(key); // this class ignores locales 78 } 79 80 /** 81 * Implementation of ResourceBundle.getKeys. 82 */ 83 @Override 84 public Enumeration<String> getKeys() { 85 ResourceBundle parent = this.parent; 86 return new ResourceBundleEnumeration(handleGetKeys(), 87 (parent != null) ? parent.getKeys() : null); 88 } 89 90 /** 91 * Returns a set of keys provided in this resource bundle, 92 * including no parents. 93 */ 94 public Set<String> handleGetKeys() { 95 loadLookupTablesIfNecessary(); 96 97 return lookup.keySet(); 98 } 99 100 @Override 101 public Set<String> keySet() { 102 if (keyset != null) { 103 return keyset; 104 } 105 Set<String> ks = createSet(); 106 ks.addAll(handleGetKeys()); 107 if (parent != null) { 108 ks.addAll(parent.keySet()); 109 } 110 synchronized (this) { 111 if (keyset == null) { 112 keyset = ks; 113 } 114 } 115 return keyset; 116 } 117 118 /** 119 * See ListResourceBundle class description. 120 */ 121 abstract protected Object[][] getContents(); 122 123 /** 124 * Load lookup tables if they haven't been loaded already. 125 */ 126 void loadLookupTablesIfNecessary() { 127 if (lookup == null) { 128 loadLookup(); 129 } 130 } 131 132 /** 133 * We lazily load the lookup hashtable. This function does the 134 * loading. 135 */ 136 private void loadLookup() { 137 Object[][] contents = getContents(); 138 Map<String, Object> temp = createMap(contents.length); 139 for (int i = 0; i < contents.length; ++i) { 140 // key must be non-null String, value must be non-null 141 String key = (String) contents[i][0]; 142 Object value = contents[i][1]; 143 if (key == null || value == null) { 144 throw new NullPointerException(); 145 } 146 temp.put(key, value); 147 } 148 synchronized (this) { 149 if (lookup == null) { 150 lookup = temp; 151 } 152 } 153 } 154 155 /** 156 * Lets subclasses provide specialized Map implementations. 157 * Default uses HashMap. 158 */ 159 protected <K, V> Map<K, V> createMap(int size) { 160 return new HashMap<>(size); 161 } 162 163 protected <E> Set<E> createSet() { 164 return new HashSet<>(); 165 } 166 167 private volatile Map<String, Object> lookup = null; 168 private volatile Set<String> keyset; 169 } |