1 package org.codehaus.plexus.context;
2
3 /*
4 * Copyright 2001-2006 Codehaus Foundation.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 import java.util.Collections;
20 import java.util.Map;
21 import java.util.Map.Entry;
22 import java.util.concurrent.ConcurrentHashMap;
23 import java.util.concurrent.ConcurrentMap;
24 import java.util.concurrent.atomic.AtomicBoolean;
25
26 /**
27 * Default implementation of Context.
28 *
29 * This implementation is a static hierarchial store. It has the normal <code>get()</code>
30 * and <code>put</code> methods. The <code>hide</code> method will hide a property. When
31 * a property has been hidden the containerContext will not search in the parent containerContext for the value.
32 *
33 * @author <a href="mailto:dev@avalon.codehaus.org">Avalon Development Team</a>
34 */
35 public class DefaultContext implements Context {
36 /**
37 * Context data.
38 */
39 private final ConcurrentMap<Object, Object> contextData = new ConcurrentHashMap<Object, Object>();
40
41 /**
42 * Is the containerContext read only.
43 */
44 private final AtomicBoolean readOnly = new AtomicBoolean(false);
45
46 /**
47 * Create an empty Context.
48 */
49 public DefaultContext() {}
50
51 /**
52 * Create a Context with specified data. The specified data is copied into the context so any subsequent updates
53 * to supplied map are not reflected in this context. Additionally, changes to this context are not reflected in
54 * the specified map.
55 *
56 * @param contextData the containerContext data
57 */
58 public DefaultContext(Map<Object, Object> contextData) {
59 if (contextData == null) {
60 throw new NullPointerException("contextData is null");
61 }
62
63 // check for nulls in key and value
64 for (Entry<Object, Object> entry : contextData.entrySet()) {
65 Object key = entry.getKey();
66 Object value = entry.getValue();
67 if (key == null) {
68 throw new IllegalArgumentException("Key is null");
69 }
70 if (value != null) {
71 this.contextData.put(key, value);
72 }
73 }
74 }
75
76 public boolean contains(Object key) {
77 Object data = contextData.get(key);
78
79 return data != null;
80 }
81
82 public Object get(Object key) throws ContextException {
83 Object data = contextData.get(key);
84
85 if (data == null) {
86 // There is no data for the key
87 throw new ContextException("Unable to resolve context key: " + key);
88 }
89 return data;
90 }
91
92 public void put(Object key, Object value) throws IllegalStateException {
93 checkWriteable();
94
95 // check for a null key
96 if (key == null) {
97 throw new IllegalArgumentException("Key is null");
98 }
99
100 if (value == null) {
101 contextData.remove(key);
102 } else {
103 contextData.put(key, value);
104 }
105 }
106
107 public void hide(Object key) throws IllegalStateException {
108 checkWriteable();
109
110 contextData.remove(key);
111 }
112
113 /**
114 * Utility method to retrieve containerContext data
115 *
116 * @return the containerContext data
117 */
118 public Map<Object, Object> getContextData() {
119 return Collections.unmodifiableMap(contextData);
120 }
121
122 /**
123 * Make the containerContext read-only.
124 * Any attempt to write to the containerContext via put()
125 * will result in an IllegalStateException.
126 */
127 public void makeReadOnly() {
128 readOnly.set(true);
129 }
130
131 /**
132 * Utility method to check if containerContext is writeable and if not throw exception.
133 *
134 * @throws java.lang.IllegalStateException if containerContext is read only
135 */
136 protected void checkWriteable() throws IllegalStateException {
137 if (readOnly.get()) {
138 throw new IllegalStateException("Context is read only and can not be modified");
139 }
140 }
141
142 public String toString() {
143 return contextData.toString();
144 }
145 }