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