View Javadoc
1   package org.codehaus.plexus.component.composition;
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.List;
20  
21  import junit.framework.TestCase;
22  import org.codehaus.plexus.classworlds.ClassWorld;
23  import org.codehaus.plexus.classworlds.realm.ClassRealm;
24  import org.codehaus.plexus.component.repository.ComponentDescriptor;
25  import org.codehaus.plexus.component.repository.io.PlexusTools;
26  
27  /**
28   *
29   *
30   * @author Jason van Zyl
31   *
32   */
33  public abstract class AbstractCompositionResolverTest extends TestCase {
34  
35      /**
36       *
37       * @return {@link CompositionResolver}
38       */
39      protected abstract CompositionResolver getCompositionResolver();
40  
41      // ------------------------------------------------------------------------
42      //
43      //     +-------+           +-------+
44      //     |  c1   | --------> |  c2   |
45      //     +-------+           +-------+
46      //         |
47      //         |
48      //         V
49      //     +-------+
50      //     |  c3   |
51      //     +-------+
52      //
53      // ------------------------------------------------------------------------
54      public void testSimpleComponentResolution() throws Exception {
55          String cc1 = "<component>" + "  <implementation>java.lang.String</implementation>"
56                  + "  <role>c1</role>"
57                  + "  <requirements>"
58                  + "    <requirement>"
59                  + "      <role>c2</role>"
60                  + "   </requirement>"
61                  + "    <requirement>"
62                  + "      <role>c3</role>"
63                  + "   </requirement>"
64                  + "  </requirements>"
65                  + "</component>";
66  
67          String cc2 = "<component>" + "  <implementation>java.lang.String</implementation>"
68                  + "  <role>c2</role>"
69                  + "</component>";
70  
71          String cc3 = "<component>" + "  <implementation>java.lang.String</implementation>"
72                  + "  <role>c3</role>"
73                  + "</component>";
74  
75          ClassWorld classWorld = new ClassWorld("test", Thread.currentThread().getContextClassLoader());
76          ClassRealm realm = classWorld.getRealm("test");
77  
78          CompositionResolver compositionResolver = getCompositionResolver();
79  
80          ComponentDescriptor<?> c1 = PlexusTools.buildComponentDescriptor(cc1, realm);
81  
82          ComponentDescriptor<?> c2 = PlexusTools.buildComponentDescriptor(cc2, realm);
83  
84          ComponentDescriptor<?> c3 = PlexusTools.buildComponentDescriptor(cc3, realm);
85  
86          compositionResolver.addComponentDescriptor(c1);
87  
88          compositionResolver.addComponentDescriptor(c2);
89  
90          compositionResolver.addComponentDescriptor(c3);
91  
92          List dependencies = compositionResolver.getRequirements(c1.getRole(), c1.getRoleHint());
93  
94          assertEquals(2, dependencies.size());
95  
96          assertTrue(dependencies.contains(c2.getRole() + CompositionResolver.SEPARATOR_CHAR + c2.getRoleHint()));
97  
98          assertTrue(dependencies.contains(c3.getRole() + CompositionResolver.SEPARATOR_CHAR + c2.getRoleHint()));
99  
100         assertEquals(2, dependencies.size());
101     }
102 
103     // ------------------------------------------------------------------------
104     //
105     //     +-------+           +-------+
106     //     |  c1   | --------> |  c2   |
107     //     +-------+           +-------+
108     //         |
109     //         |
110     //         V
111     //     +-------+           +-------+
112     //     |  c3   | --------> |  c4   |
113     //     +-------+           +-------+
114     //         |
115     //         |
116     //         V
117     //     +-------+
118     //     |  c5   |
119     //     +-------+
120     //
121     // ------------------------------------------------------------------------
122     public void testComplexComponentResolution() throws Exception {
123         String cc1 = "<component>" + "  <implementation>java.lang.String</implementation>"
124                 + "  <role>c1</role>"
125                 + "  <requirements>"
126                 + "    <requirement>"
127                 + "      <role>c2</role>"
128                 + "   </requirement>"
129                 + "   <requirement>"
130                 + "      <role>c3</role>"
131                 + "   </requirement>"
132                 + "  </requirements>"
133                 + "</component>";
134 
135         String cc2 = "<component>" + "  <implementation>java.lang.String</implementation>"
136                 + "  <role>c2</role>"
137                 + "</component>";
138 
139         String cc3 = "<component>" + "  <implementation>java.lang.String</implementation>"
140                 + "  <role>c3</role>"
141                 + "  <requirements>"
142                 + "    <requirement>"
143                 + "      <role>c4</role>"
144                 + "   </requirement>"
145                 + "    <requirement>"
146                 + "      <role>c5</role>"
147                 + "   </requirement>"
148                 + "  </requirements>"
149                 + "</component>";
150 
151         String cc4 = "<component>" + "  <implementation>java.lang.String</implementation>"
152                 + "  <role>c4</role>"
153                 + "</component>";
154 
155         String cc5 = "<component>" + "  <implementation>java.lang.String</implementation>"
156                 + "  <role>c5</role>"
157                 + "</component>";
158 
159         ClassWorld classWorld = new ClassWorld("test", Thread.currentThread().getContextClassLoader());
160         ClassRealm realm = classWorld.getRealm("test");
161 
162         CompositionResolver compositionResolver = getCompositionResolver();
163 
164         ComponentDescriptor<?> c1 = PlexusTools.buildComponentDescriptor(cc1, realm);
165 
166         ComponentDescriptor<?> c2 = PlexusTools.buildComponentDescriptor(cc2, realm);
167 
168         ComponentDescriptor<?> c3 = PlexusTools.buildComponentDescriptor(cc3, realm);
169 
170         ComponentDescriptor<?> c4 = PlexusTools.buildComponentDescriptor(cc4, realm);
171 
172         ComponentDescriptor<?> c5 = PlexusTools.buildComponentDescriptor(cc5, realm);
173 
174         compositionResolver.addComponentDescriptor(c1);
175 
176         compositionResolver.addComponentDescriptor(c2);
177 
178         compositionResolver.addComponentDescriptor(c3);
179 
180         compositionResolver.addComponentDescriptor(c4);
181 
182         compositionResolver.addComponentDescriptor(c5);
183 
184         List dependencies = compositionResolver.getRequirements(c1.getRole(), c1.getRoleHint());
185 
186         assertEquals(2, dependencies.size());
187 
188         // I just leave this at the moment as I am just 99% sure that this is not needed and not
189         // correct. compositionResolver.getComponentDependencies() should return only direct dependencies
190         //
191         // I will need to add a method like getSortedComponents()
192         // which will do topological sort of DAG and return list of ordered component which can be used
193         // by ComponentComposer.
194         // Possibility of checking if there are cycles probably also must be exposed in API (DAG has it alredy)
195         // and it should be used
196         // I can implement cycle detecting from single node (source) as after adding new component
197         // we don't have to probably check entire graph but we will probably have to check
198         // if there are cycles.
199 
200         /**
201          * // c5 must come before c3
202          * assertTrue( dependencies.indexOf( "c5" ) < dependencies.indexOf( "c3" ) );
203          *
204          * // c4 must come before c3
205          * assertTrue( dependencies.indexOf( "c4" ) < dependencies.indexOf( "c3" ) );
206          */
207     }
208 }