1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.catalina.util;
18
19 import java.io.Serializable;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.LinkedHashMap;
23 import java.util.Map;
24 import java.util.Set;
25
26 import org.apache.tomcat.util.res.StringManager;
27
28 /**
29  * Implementation of <strong>java.util.Map</strong> that includes a
30  * <code>locked</code> property.  This class can be used to safely expose
31  * Catalina internal parameter map objects to user classes without having
32  * to clone them in order to avoid modifications.  When first created, a
33  * <code>ParmaeterMap</code> instance is not locked.
34  *
35  * @param <K> The type of Key
36  * @param <V> The type of Value
37  *
38  * @author Craig R. McClanahan
39  */

40 public final class ParameterMap<K,V> implements Map<K,V>, Serializable {
41
42     private static final long serialVersionUID = 2L;
43
44     private final Map<K,V> delegatedMap;
45
46     private final Map<K,V> unmodifiableDelegatedMap;
47
48
49     /**
50      * Construct a new, empty map with the default initial capacity and
51      * load factor.
52      */

53     public ParameterMap() {
54         delegatedMap = new LinkedHashMap<>();
55         unmodifiableDelegatedMap = Collections.unmodifiableMap(delegatedMap);
56     }
57
58
59     /**
60      * Construct a new, empty map with the specified initial capacity and
61      * default load factor.
62      *
63      * @param initialCapacity The initial capacity of this map
64      */

65     public ParameterMap(int initialCapacity) {
66         delegatedMap = new LinkedHashMap<>(initialCapacity);
67         unmodifiableDelegatedMap = Collections.unmodifiableMap(delegatedMap);
68     }
69
70
71     /**
72      * Construct a new, empty map with the specified initial capacity and
73      * load factor.
74      *
75      * @param initialCapacity The initial capacity of this map
76      * @param loadFactor The load factor of this map
77      */

78     public ParameterMap(int initialCapacity, float loadFactor) {
79         delegatedMap = new LinkedHashMap<>(initialCapacity, loadFactor);
80         unmodifiableDelegatedMap = Collections.unmodifiableMap(delegatedMap);
81     }
82
83
84     /**
85      * Construct a new map with the same mappings as the given map.
86      *
87      * @param map Map whose contents are duplicated in the new map
88      */

89     public ParameterMap(Map<K,V> map) {
90         delegatedMap = new LinkedHashMap<>(map);
91         unmodifiableDelegatedMap = Collections.unmodifiableMap(delegatedMap);
92     }
93
94
95     /**
96      * The current lock state of this parameter map.
97      */

98     private boolean locked = false;
99
100
101     /**
102      * @return the locked state of this parameter map.
103      */

104     public boolean isLocked() {
105         return locked;
106     }
107
108
109     /**
110      * Set the locked state of this parameter map.
111      *
112      * @param locked The new locked state
113      */

114     public void setLocked(boolean locked) {
115         this.locked = locked;
116     }
117
118
119     /**
120      * The string manager for this package.
121      */

122     private static final StringManager sm = StringManager.getManager("org.apache.catalina.util");
123
124
125     /**
126      * {@inheritDoc}
127      *
128      * @exception IllegalStateException if this map is currently locked
129      */

130     @Override
131     public void clear() {
132         checkLocked();
133         delegatedMap.clear();
134     }
135
136
137     /**
138      * {@inheritDoc}
139      *
140      * @exception IllegalStateException if this map is currently locked
141      */

142     @Override
143     public V put(K key, V value) {
144         checkLocked();
145         return delegatedMap.put(key, value);
146     }
147
148
149     /**
150      * {@inheritDoc}
151      *
152      * @exception IllegalStateException if this map is currently locked
153      */

154     @Override
155     public void putAll(Map<? extends K,? extends V> map) {
156         checkLocked();
157         delegatedMap.putAll(map);
158     }
159
160
161     /**
162      * {@inheritDoc}
163      *
164      * @exception IllegalStateException if this map is currently locked
165      */

166     @Override
167     public V remove(Object key) {
168         checkLocked();
169         return delegatedMap.remove(key);
170     }
171
172
173     private void checkLocked() {
174         if (locked) {
175             throw new IllegalStateException(sm.getString("parameterMap.locked"));
176         }
177     }
178
179
180     @Override
181     public int size() {
182         return delegatedMap.size();
183     }
184
185
186     @Override
187     public boolean isEmpty() {
188         return delegatedMap.isEmpty();
189     }
190
191
192     @Override
193     public boolean containsKey(Object key) {
194         return delegatedMap.containsKey(key);
195     }
196
197
198     @Override
199     public boolean containsValue(Object value) {
200         return delegatedMap.containsValue(value);
201     }
202
203
204     @Override
205     public V get(Object key) {
206         return delegatedMap.get(key);
207     }
208
209
210     /**
211      * {@inheritDoc}
212      * <p>
213      * Returns an <strong>unmodifiable</strong> {@link Set} view of the keys
214      * contained in this map if it is locked.
215      */

216     @Override
217     public Set<K> keySet() {
218         if (locked) {
219             return unmodifiableDelegatedMap.keySet();
220         }
221
222         return delegatedMap.keySet();
223     }
224
225
226     /**
227      * {@inheritDoc}
228      * <p>
229      * Returns an <strong>unmodifiable</strong> {@link Collection} view of the
230      * values contained in this map if it is locked.
231      */

232     @Override
233     public Collection<V> values() {
234         if (locked) {
235             return unmodifiableDelegatedMap.values();
236         }
237
238         return delegatedMap.values();
239     }
240
241
242     /**
243      * {@inheritDoc}
244      * <p>
245      * Returns an <strong>unmodifiable</strong> {@link Set} view of the mappings
246      * contained in this map if it is locked.
247      */

248     @Override
249     public Set<java.util.Map.Entry<K, V>> entrySet() {
250         if (locked) {
251             return unmodifiableDelegatedMap.entrySet();
252         }
253
254         return delegatedMap.entrySet();
255     }
256 }
257