View Javadoc
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 }