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