View Javadoc
1   package org.codehaus.plexus.component.collections;
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.Collection;
20  import java.util.LinkedHashMap;
21  import java.util.List;
22  import java.util.Map;
23  import java.util.Set;
24  
25  import org.codehaus.plexus.MutablePlexusContainer;
26  import org.codehaus.plexus.component.repository.ComponentDescriptor;
27  import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
28  
29  /**
30   * @author Jason van Zyl FIXME: [jdcasey] We need to review the efficiency (in speed and memory) of this collection...
31   */
32  public class ComponentMap<T> extends AbstractComponentCollection<T> implements Map<String, T> {
33      private Map<String, T> components;
34  
35      private Map<String, T> customAdditions = new LinkedHashMap<String, T>();
36  
37      public ComponentMap(
38              MutablePlexusContainer container,
39              Class<T> type,
40              String role,
41              List<String> roleHints,
42              String hostComponent) {
43          super(container, type, role, roleHints, hostComponent);
44      }
45  
46      public int size() {
47          return getComponentDescriptorMap().size();
48      }
49  
50      public boolean isEmpty() {
51          return getComponentDescriptorMap().isEmpty();
52      }
53  
54      public boolean containsKey(Object key) {
55          return getComponentDescriptorMap().containsKey(key);
56      }
57  
58      public boolean containsValue(Object value) {
59          return getMap().containsValue(value);
60      }
61  
62      public T get(Object k) {
63          return getMap().get(k);
64      }
65  
66      public synchronized T put(String key, T value) {
67          logger.warn("Custom "
68                  + role
69                  + " implementations should NOT be added directly to this Map. Instead, add them as Plexus components.");
70  
71          T prev = customAdditions.put(key, value);
72          if (prev == null) {
73              prev = getComponentMap().get(key);
74          }
75  
76          return prev;
77      }
78  
79      public synchronized void putAll(Map<? extends String, ? extends T> map) {
80          logger.warn("Custom "
81                  + role
82                  + " implementations should NOT be added directly to this Map. Instead, add them as Plexus components.");
83  
84          customAdditions.putAll(map);
85      }
86  
87      public Set<String> keySet() {
88          return getMap().keySet();
89      }
90  
91      public Collection<T> values() {
92          return getMap().values();
93      }
94  
95      public Set<Map.Entry<String, T>> entrySet() {
96          return getMap().entrySet();
97      }
98  
99      public boolean equals(Object o) {
100         if (this == o) {
101             return true;
102         }
103         if (!(o instanceof Map)) {
104             return false;
105         }
106 
107         Map<?, ?> object = (Map<?, ?>) o;
108         return getMap().equals(object);
109     }
110 
111     public int hashCode() {
112         return getMap().hashCode();
113     }
114 
115     public synchronized T remove(Object key) {
116         logger.warn(
117                 "Items in this Map should NOT be removed directly. If the matching entry is a component, it will NOT be removed.");
118 
119         if (key instanceof String) {
120             if (customAdditions.containsKey(key)) {
121                 return customAdditions.remove(key);
122             }
123         }
124 
125         return null;
126     }
127 
128     private synchronized Map<String, T> getMap() {
129         Map<String, T> result = getComponentMap();
130 
131         if (!customAdditions.isEmpty()) {
132             result.putAll(customAdditions);
133         }
134 
135         return result;
136     }
137 
138     private synchronized Map<String, T> getComponentMap() {
139         if ((components == null) || checkUpdate()) {
140             Map<String, T> componentMap = new LinkedHashMap<String, T>();
141 
142             Map<String, ComponentDescriptor<T>> descriptorMap = getComponentDescriptorMap();
143 
144             if (roleHints != null) {
145                 // we must follow the order given in roleHints
146                 for (String roleHint : roleHints) {
147                     ComponentDescriptor<T> componentDescriptor = descriptorMap.get(roleHint);
148 
149                     T component = lookup(componentDescriptor);
150 
151                     if (component != null) {
152                         componentMap.put(roleHint, component);
153                     }
154                 }
155             } else {
156                 for (Entry<String, ComponentDescriptor<T>> entry : descriptorMap.entrySet()) {
157                     String roleHint = entry.getKey();
158 
159                     ComponentDescriptor<T> componentDescriptor = entry.getValue();
160 
161                     T component = lookup(componentDescriptor);
162 
163                     if (component != null) {
164                         componentMap.put(roleHint, component);
165                     }
166                 }
167             }
168             components = componentMap;
169         }
170 
171         return components;
172     }
173 
174     @Override
175     protected boolean checkUpdate() {
176         if (super.checkUpdate()) {
177             components = null;
178 
179             return true;
180         }
181 
182         return false;
183     }
184 
185     protected void releaseAllCallback() {
186         if (components != null) {
187             try {
188                 container.releaseAll(components);
189             } catch (ComponentLifecycleException e) {
190                 logger.debug("Error releasing components in active collection: " + e.getMessage(), e);
191             }
192 
193             components = null;
194         }
195     }
196 }