View Javadoc
1   package org.codehaus.plexus.component.repository;
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.Collections;
22  import java.util.HashSet;
23  import java.util.LinkedHashMap;
24  import java.util.LinkedHashSet;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Map.Entry;
28  import java.util.Set;
29  import java.util.SortedMap;
30  import java.util.TreeMap;
31  
32  import org.codehaus.plexus.ClassRealmUtil;
33  import org.codehaus.plexus.PlexusConstants;
34  import org.codehaus.plexus.classworlds.realm.ClassRealm;
35  import org.codehaus.plexus.component.composition.CompositionResolver;
36  import org.codehaus.plexus.component.composition.CycleDetectedInComponentGraphException;
37  import org.codehaus.plexus.component.composition.DefaultCompositionResolver;
38  import org.codehaus.plexus.logging.AbstractLogEnabled;
39  import org.codehaus.plexus.util.StringUtils;
40  
41  import static org.codehaus.plexus.component.CastUtils.isAssignableFrom;
42  
43  /**
44   * @author Jason van Zyl
45   */
46  public class DefaultComponentRepository extends AbstractLogEnabled implements ComponentRepository {
47      private final Map<ClassRealm, SortedMap<String, Map<String, Set<ComponentDescriptor<?>>>>> index =
48              new LinkedHashMap<ClassRealm, SortedMap<String, Map<String, Set<ComponentDescriptor<?>>>>>();
49  
50      private final CompositionResolver compositionResolver = new DefaultCompositionResolver();
51  
52      public DefaultComponentRepository() {}
53  
54      // ----------------------------------------------------------------------
55      // Accessors
56      // ----------------------------------------------------------------------
57  
58      private Map<String, Set<ComponentDescriptor<?>>> getComponentDescriptors(String role) {
59          // verify arguments
60          if (role == null) {
61              throw new NullPointerException("role is null");
62          }
63  
64          // determine realms to search
65          Set<ClassRealm> realms = ClassRealmUtil.getContextRealms(null);
66          if (realms.isEmpty()) {
67              realms.addAll(index.keySet());
68          }
69  
70          // Get all valid component descriptors
71          Map<String, Set<ComponentDescriptor<?>>> roleHintIndex =
72                  new LinkedHashMap<String, Set<ComponentDescriptor<?>>>();
73          for (ClassRealm realm : realms) {
74              SortedMap<String, Map<String, Set<ComponentDescriptor<?>>>> roleIndex = index.get(realm);
75              if (roleIndex != null) {
76                  Map<String, Set<ComponentDescriptor<?>>> descriptors = roleIndex.get(role);
77                  if (descriptors != null) {
78                      for (Entry<String, Set<ComponentDescriptor<?>>> descriptor : descriptors.entrySet()) {
79                          Set<ComponentDescriptor<?>> componentDescriptors = roleHintIndex.get(descriptor.getKey());
80                          if (componentDescriptors == null) {
81                              componentDescriptors = new LinkedHashSet<ComponentDescriptor<?>>();
82                              roleHintIndex.put(descriptor.getKey(), componentDescriptors);
83                          }
84                          componentDescriptors.addAll(descriptor.getValue());
85                      }
86                  }
87              }
88          }
89          return Collections.unmodifiableMap(roleHintIndex);
90      }
91  
92      public <T> ComponentDescriptor<T> getComponentDescriptor(Class<T> type, String role, String roleHint) {
93          Map<String, Set<ComponentDescriptor<?>>> roleHintIndex = getComponentDescriptors(role);
94  
95          Collection<ComponentDescriptor<?>> descriptors;
96  
97          if (StringUtils.isNotEmpty(roleHint)) {
98              // specific role hint -> get only those
99              descriptors = roleHintIndex.get(roleHint);
100         } else {
101             // missing role hint -> get all (wildcard)
102             Collection<ComponentDescriptor<?>> allDescriptors = new ArrayList<ComponentDescriptor<?>>();
103 
104             descriptors = roleHintIndex.get(PlexusConstants.PLEXUS_DEFAULT_HINT);
105             if (descriptors != null) {
106                 allDescriptors.addAll(descriptors);
107             }
108 
109             for (String hint : roleHintIndex.keySet()) {
110                 descriptors = roleHintIndex.get(hint);
111                 if (descriptors != null) {
112                     allDescriptors.addAll(descriptors);
113                 }
114             }
115 
116             descriptors = allDescriptors;
117         }
118 
119         if (descriptors != null) {
120             for (ComponentDescriptor<?> descriptor : descriptors) {
121                 Class<?> implClass = descriptor.getImplementationClass();
122                 if (isAssignableFrom(type, implClass) || Object.class == implClass && role.equals(type.getName())) {
123                     return (ComponentDescriptor<T>) descriptor;
124                 }
125             }
126         }
127 
128         return null;
129     }
130 
131     public <T> Map<String, ComponentDescriptor<T>> getComponentDescriptorMap(Class<T> type, String role) {
132         Map<String, ComponentDescriptor<T>> descriptors = new TreeMap<String, ComponentDescriptor<T>>();
133         for (Set<ComponentDescriptor<?>> componentDescriptors :
134                 getComponentDescriptors(role).values()) {
135             for (ComponentDescriptor<?> descriptor : componentDescriptors) {
136                 if (!descriptors.containsKey(descriptor.getRoleHint())
137                         && isAssignableFrom(type, descriptor.getImplementationClass())) {
138                     descriptors.put(descriptor.getRoleHint(), (ComponentDescriptor<T>) descriptor);
139                 }
140             }
141         }
142         return descriptors;
143     }
144 
145     public <T> List<ComponentDescriptor<T>> getComponentDescriptorList(Class<T> type, String role) {
146         List<ComponentDescriptor<T>> descriptors = new ArrayList<ComponentDescriptor<T>>();
147         for (Set<ComponentDescriptor<?>> componentDescriptors :
148                 getComponentDescriptors(role).values()) {
149             for (ComponentDescriptor<?> descriptor : componentDescriptors) {
150                 if (isAssignableFrom(type, descriptor.getImplementationClass())) {
151                     descriptors.add((ComponentDescriptor<T>) descriptor);
152                 }
153             }
154         }
155         return descriptors;
156     }
157 
158     @Deprecated
159     public ComponentDescriptor<?> getComponentDescriptor(String role, String roleHint, ClassRealm realm) {
160         // find all realms from our realm to the root realm
161         Set<ClassRealm> realms = new HashSet<ClassRealm>();
162         for (ClassRealm r = realm; r != null; r = r.getParentRealm()) {
163             realms.add(r);
164         }
165 
166         // get the component descriptors by roleHint
167         for (ComponentDescriptor<?> componentDescriptor :
168                 getComponentDescriptors(role).get(roleHint)) {
169             // return the first descriptor from our target realms
170             if (realms.contains(componentDescriptor.getRealm())) {
171                 return componentDescriptor;
172             }
173         }
174 
175         return null;
176     }
177 
178     public void removeComponentRealm(ClassRealm classRealm) {
179         index.remove(classRealm);
180     }
181 
182     // ----------------------------------------------------------------------
183     // Lifecylce Management
184     // ----------------------------------------------------------------------
185 
186     // ----------------------------------------------------------------------
187     // Component Descriptor processing.
188     // ----------------------------------------------------------------------
189 
190     public void addComponentDescriptor(ComponentDescriptor<?> componentDescriptor)
191             throws CycleDetectedInComponentGraphException {
192         ClassRealm classRealm = componentDescriptor.getRealm();
193         SortedMap<String, Map<String, Set<ComponentDescriptor<?>>>> roleIndex = index.get(classRealm);
194         if (roleIndex == null) {
195             roleIndex = new TreeMap<String, Map<String, Set<ComponentDescriptor<?>>>>();
196             index.put(classRealm, roleIndex);
197         }
198 
199         String role = componentDescriptor.getRole();
200         Map<String, Set<ComponentDescriptor<?>>> roleHintIndex = roleIndex.get(role);
201         if (roleHintIndex == null) {
202             roleHintIndex = new LinkedHashMap<String, Set<ComponentDescriptor<?>>>();
203             roleIndex.put(role, roleHintIndex);
204         }
205         String roleHint = componentDescriptor.getRoleHint();
206         Set<ComponentDescriptor<?>> componentDescriptors = roleHintIndex.get(roleHint);
207         if (componentDescriptors == null) {
208             componentDescriptors = new LinkedHashSet<ComponentDescriptor<?>>();
209             roleHintIndex.put(roleHint, componentDescriptors);
210         }
211         componentDescriptors.add(componentDescriptor);
212 
213         compositionResolver.addComponentDescriptor(componentDescriptor);
214     }
215 }