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