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.ArrayList;
24  import java.util.Collection;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.ListIterator;
28  import java.util.Map;
29  import java.util.Map.Entry;
30  
31  /**
32   * @author Jason van Zyl FIXME: [jdcasey] We need to review the efficiency (in speed and memory) of this collection...
33   */
34  public class ComponentList<T>
35      extends AbstractComponentCollection<T>
36      implements List<T>
37  {
38      private List<T> components;
39  
40      public ComponentList( 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 contains( Object object )
56      {
57          return getList().contains( object );
58      }
59  
60      public Iterator<T> iterator()
61      {
62          return getList().iterator();
63      }
64  
65      public Object[] toArray()
66      {
67          return getList().toArray();
68      }
69  
70      public <X> X[] toArray( X[] ts )
71      {
72          return getList().toArray( ts );
73      }
74  
75      public synchronized boolean add( T object )
76      {
77          getList().add( object );
78  
79          /*
80           * PLX-352 This is strictly to support the hack in the Ant Run plugin that tries to poke in a custom converter.
81           * We need a better way to register converters to plexus and not hit the default converter lookup directly.
82           * throw new UnsupportedOperationException( "You cannot modify this list. This list is a requirement of " +
83           * hostComponent + " and managed by the container." );
84           */
85  
86          return true;
87      }
88  
89      public boolean remove( Object object )
90      {
91          throw new UnsupportedOperationException( "You cannot modify this list. This list is a requirement of "
92              + hostComponent + " and managed by the container." );
93      }
94  
95      public boolean containsAll( Collection<?> collection )
96      {
97          return getList().containsAll( collection );
98      }
99  
100     public boolean addAll( Collection<? extends T> collection )
101     {
102         throw new UnsupportedOperationException( "You cannot modify this list. This list is a requirement of "
103             + hostComponent + " and managed by the container." );
104     }
105 
106     public boolean addAll( int i, Collection<? extends T> collection )
107     {
108         throw new UnsupportedOperationException( "You cannot modify this list. This list is a requirement of "
109             + hostComponent + " and managed by the container." );
110     }
111 
112     public synchronized boolean removeAll( Collection<?> collection )
113     {
114         return getList().removeAll( collection );
115     }
116 
117     public synchronized boolean retainAll( Collection<?> collection )
118     {
119         return getList().retainAll( collection );
120     }
121 
122     public boolean equals( Object o )
123     {
124         if ( this == o )
125         {
126             return true;
127         }
128         if ( !( o instanceof List ) )
129         {
130             return false;
131         }
132 
133         List<?> other = (List<?>) o;
134         return getList().equals( other );
135     }
136 
137     public int hashCode()
138     {
139         return getList().hashCode();
140     }
141 
142     public T get( int i )
143     {
144         return getList().get( i );
145     }
146 
147     public T set( int i, T object )
148     {
149         throw new UnsupportedOperationException( "You cannot modify this list. This list is a requirement of "
150             + hostComponent + " and managed by the container." );
151     }
152 
153     public void add( int i, T object )
154     {
155         throw new UnsupportedOperationException( "You cannot modify this list. This list is a requirement of "
156             + hostComponent + " and managed by the container." );
157     }
158 
159     public T remove( int i )
160     {
161         throw new UnsupportedOperationException( "You cannot modify this list. This list is a requirement of "
162             + hostComponent + " and managed by the container." );
163     }
164 
165     public int indexOf( Object object )
166     {
167         return getList().indexOf( object );
168     }
169 
170     public int lastIndexOf( Object object )
171     {
172         return getList().lastIndexOf( object );
173     }
174 
175     public ListIterator<T> listIterator()
176     {
177         return getList().listIterator();
178     }
179 
180     public ListIterator<T> listIterator( int index )
181     {
182         return getList().listIterator( index );
183     }
184 
185     public List<T> subList( int fromIndex, int toIndex )
186     {
187         return getList().subList( fromIndex, toIndex );
188     }
189 
190     private synchronized List<T> getList()
191     {
192         // NOTE: If we cache the component map, we have a problem with releasing any of the
193         // components in this map...we need to be able to release them all.
194         if ( ( components == null ) || checkUpdate() )
195         {
196             List<T> componentList = new ArrayList<T>();
197 
198             Map<String, ComponentDescriptor<T>> descriptorMap = getComponentDescriptorMap();
199 
200             if ( roleHints != null )
201             {
202                 // we must follow the order in roleHints
203                 for ( String roleHint : roleHints )
204                 {
205                     ComponentDescriptor<T> componentDescriptor = descriptorMap.get( roleHint );
206 
207                     T component = lookup( componentDescriptor );
208 
209                     if ( component != null )
210                     {
211                         componentList.add( component );
212                     }
213                 }
214             }
215             else
216             {
217                 for ( Entry<String, ComponentDescriptor<T>> entry : descriptorMap.entrySet() )
218                 {
219                     ComponentDescriptor<T> componentDescriptor = entry.getValue();
220 
221                     T component = lookup( componentDescriptor );
222 
223                     if ( component != null )
224                     {
225                         componentList.add( component );
226                     }
227                 }
228             }
229             components = componentList;
230         }
231 
232         return components;
233     }
234 
235     @Override
236     protected boolean checkUpdate()
237     {
238         if ( super.checkUpdate() )
239         {
240             components = null;
241 
242             return true;
243         }
244 
245         return false;
246     }
247 
248     protected void releaseAllCallback()
249     {
250         if ( components != null )
251         {
252             try
253             {
254                 container.releaseAll( components );
255             }
256             catch ( ComponentLifecycleException e )
257             {
258                 logger.debug( "Error releasing components in active collection: " + e.getMessage(), e );
259             }
260 
261             components = null;
262         }
263     }
264 }