1 /* 2 * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved 28 * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved 29 * 30 * The original version of this source code and documentation 31 * is copyrighted and owned by Taligent, Inc., a wholly-owned 32 * subsidiary of IBM. These materials are provided under terms 33 * of a License Agreement between Taligent and Sun. This technology 34 * is protected by multiple US and International patents. 35 * 36 * This notice and attribution to Taligent may not be removed. 37 * Taligent is a registered trademark of Taligent, Inc. 38 * 39 */ 40 41 package sun.util.resources; 42 43 import java.util.Enumeration; 44 import java.util.HashMap; 45 import java.util.HashSet; 46 import java.util.Map; 47 import java.util.ResourceBundle; 48 import java.util.Set; 49 import sun.util.ResourceBundleEnumeration; 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 */ OpenListResourceBundle()66 protected OpenListResourceBundle() { 67 } 68 69 // Implements java.util.ResourceBundle.handleGetObject; inherits javadoc specification. 70 @Override handleGetObject(String key)71 protected 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 getKeys()84 public Enumeration<String> getKeys() { 85 ResourceBundle parentBundle = this.parent; 86 return new ResourceBundleEnumeration(handleKeySet(), 87 (parentBundle != null) ? parentBundle.getKeys() : null); 88 } 89 90 /** 91 * Returns a set of keys provided in this resource bundle, 92 * including no parents. 93 */ 94 @Override handleKeySet()95 protected Set<String> handleKeySet() { 96 loadLookupTablesIfNecessary(); 97 return lookup.keySet(); 98 } 99 100 @Override keySet()101 public Set<String> keySet() { 102 if (keyset != null) { 103 return keyset; 104 } 105 Set<String> ks = createSet(); 106 ks.addAll(handleKeySet()); 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 */ getContents()121 protected abstract Object[][] getContents(); 122 123 /** 124 * Load lookup tables if they haven't been loaded already. 125 */ loadLookupTablesIfNecessary()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 */ loadLookup()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 */ createMap(int size)159 protected <K, V> Map<K, V> createMap(int size) { 160 return new HashMap<>(size); 161 } 162 createSet()163 protected <E> Set<E> createSet() { 164 return new HashSet<>(); 165 } 166 167 private volatile Map<String, Object> lookup; 168 private volatile Set<String> keyset; 169 } 170