View Javadoc
1   /*
2    * Copyright (C) 2007 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.codehaus.plexus.metadata;
18  
19  import java.io.File;
20  import java.io.StringReader;
21  import java.io.StringWriter;
22  import java.util.Collections;
23  import java.util.LinkedList;
24  import java.util.List;
25  
26  import org.codehaus.plexus.PlexusTestCase;
27  import org.codehaus.plexus.classworlds.ClassWorld;
28  import org.codehaus.plexus.classworlds.realm.ClassRealm;
29  import org.codehaus.plexus.component.repository.*;
30  import org.codehaus.plexus.configuration.PlexusConfiguration;
31  import org.codehaus.plexus.configuration.PlexusConfigurationException;
32  import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
33  import org.codehaus.plexus.metadata.merge.ComponentsXmlMerger;
34  import org.codehaus.plexus.metadata.merge.Merger;
35  import org.codehaus.plexus.metadata.merge.PlexusXmlMerger;
36  import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
37  import org.jdom2.Document;
38  import org.jdom2.Element;
39  import org.jdom2.input.SAXBuilder;
40  
41  /**
42   * Test for the {@link DefaultComponentDescriptorWriter} class.
43   *
44   * @version $Rev$ $Date$
45   */
46  public class DefaultComponentDescriptorWriterTest extends PlexusTestCase {
47      private DefaultComponentDescriptorWriter descriptorWriter;
48  
49      // @Override
50      protected void setUp() throws Exception {
51          super.setUp();
52  
53          descriptorWriter = (DefaultComponentDescriptorWriter) lookup(ComponentDescriptorWriter.class);
54          assertNotNull(descriptorWriter);
55      }
56  
57      // @Override
58      protected void tearDown() throws Exception {
59          descriptorWriter = null;
60  
61          super.tearDown();
62      }
63  
64      public void testBasic() throws Exception {
65          ComponentSetDescriptor set = new ComponentSetDescriptor();
66  
67          ComponentDescriptor component = new ComponentDescriptor();
68          component.setImplementation("java.lang.String");
69          component.setRole("foo");
70          component.setRoleHint("bar");
71          component.setComponentFactory("baz");
72  
73          set.addComponentDescriptor(component);
74  
75          StringWriter writer = new StringWriter();
76          descriptorWriter.writeDescriptorSet(writer, set, false);
77          writer.flush();
78          writer.close();
79  
80          String xml = writer.toString();
81  
82          assertTrue(xml.length() != 0);
83  
84          PlexusConfiguration config = new XmlPlexusConfiguration(Xpp3DomBuilder.build(new StringReader(xml)));
85          assertNotNull(config);
86  
87          ClassWorld classWorld = new ClassWorld("test", Thread.currentThread().getContextClassLoader());
88          ClassRealm realm = classWorld.getRealm("test");
89          ComponentSetDescriptor set2 = buildComponentSet(config, realm);
90          assertNotNull(set2);
91  
92          List<ComponentDescriptor<?>> components = set2.getComponents();
93          assertNotNull(components);
94          assertEquals(1, components.size());
95  
96          ComponentDescriptor<?> component2 = components.get(0);
97          assertNotNull(component2);
98  
99          assertEquals(component.getRole(), component2.getRole());
100         assertEquals(component.getRoleHint(), component2.getRoleHint());
101         assertEquals(component.getComponentFactory(), component2.getComponentFactory());
102 
103         //
104         // TODO: Verify requirements and configuration too... but I'm too lazy for that right now
105         //
106     }
107 
108     public void testComponentsOrder() throws Exception {
109         MetadataGenerator generator = lookup(MetadataGenerator.class);
110         assertNotNull(generator);
111 
112         MetadataGenerationRequest request = new MetadataGenerationRequest();
113         request.sourceDirectories = Collections.singletonList("src/main/java");
114         request.classesDirectory = new File("target/classes");
115         request.outputFile = new File("target/test-classes/components-sorted.xml");
116         request.sourceEncoding = "UTF-8";
117         request.useContextClassLoader = true;
118 
119         generator.generateDescriptor(request);
120 
121         assertTrue("Descriptor not generated", request.outputFile.exists());
122 
123         Document doc = new SAXBuilder().build(request.outputFile);
124 
125         // check if the components are sorted by role+impl
126         List<Element> components = doc.getRootElement().getChild("components").getChildren();
127         assertEquals("Number of components", 5, components.size());
128 
129         assertEquals(
130                 "Component 1 role",
131                 ComponentDescriptorExtractor.class.getName(),
132                 components.get(0).getChild("role").getText());
133         assertEquals(
134                 "Component 1 impl",
135                 ClassComponentDescriptorExtractor.class.getName(),
136                 components.get(0).getChild("implementation").getText());
137 
138         assertEquals(
139                 "Component 2 role",
140                 ComponentDescriptorExtractor.class.getName(),
141                 components.get(1).getChild("role").getText());
142         assertEquals(
143                 "Component 2 impl",
144                 SourceComponentDescriptorExtractor.class.getName(),
145                 components.get(1).getChild("implementation").getText());
146 
147         assertEquals(
148                 "Component 3 role",
149                 MetadataGenerator.class.getName(),
150                 components.get(2).getChild("role").getText());
151         assertEquals(
152                 "Component 3 impl",
153                 DefaultMetadataGenerator.class.getName(),
154                 components.get(2).getChild("implementation").getText());
155 
156         assertEquals(
157                 "Component 4 role",
158                 Merger.class.getName(),
159                 components.get(3).getChild("role").getText());
160         assertEquals(
161                 "Component 4 impl",
162                 ComponentsXmlMerger.class.getName(),
163                 components.get(3).getChild("implementation").getText());
164 
165         assertEquals(
166                 "Component 5 role",
167                 Merger.class.getName(),
168                 components.get(4).getChild("role").getText());
169         assertEquals(
170                 "Component 5 impl",
171                 PlexusXmlMerger.class.getName(),
172                 components.get(4).getChild("implementation").getText());
173     }
174 
175     // TODO copied from PlexusTools.buildConfiguration() - find a better way to do this
176     // we have duplication here, but we don't want to depend on plexus-container-default
177     // similar code in AnnotationComponentGleaner.glean() and QDoxComponentGleaner.findRequirements()
178     private static ComponentSetDescriptor buildComponentSet(PlexusConfiguration c, ClassRealm realm)
179             throws PlexusConfigurationException {
180         ComponentSetDescriptor csd = new ComponentSetDescriptor();
181         for (PlexusConfiguration component : c.getChild("components").getChildren("component")) {
182             csd.addComponentDescriptor(buildComponentDescriptorImpl(component, realm));
183         }
184 
185         for (PlexusConfiguration d : c.getChild("dependencies").getChildren("dependency")) {
186             ComponentDependency cd = new ComponentDependency();
187             cd.setArtifactId(d.getChild("artifact-id").getValue());
188             cd.setGroupId(d.getChild("group-id").getValue());
189             String type = d.getChild("type").getValue();
190             if (type != null) {
191                 cd.setType(type);
192             }
193             cd.setVersion(d.getChild("version").getValue());
194             csd.addDependency(cd);
195         }
196         return csd;
197     }
198 
199     private static ComponentDescriptor<?> buildComponentDescriptorImpl(
200             PlexusConfiguration configuration, ClassRealm realm) throws PlexusConfigurationException {
201         String implementation = configuration.getChild("implementation").getValue();
202         if (implementation == null) {
203             throw new PlexusConfigurationException("implementation is null");
204         }
205 
206         ComponentDescriptor<?> cd;
207         try {
208             if (realm != null) {
209                 Class<?> implementationClass = realm.loadClass(implementation);
210                 cd = new ComponentDescriptor<>(implementationClass, realm);
211             } else {
212                 cd = new ComponentDescriptor<>();
213                 cd.setImplementation(implementation);
214             }
215         } catch (Throwable e) {
216             throw new PlexusConfigurationException(
217                     "Can not load implementation class " + implementation + " from realm " + realm, e);
218         }
219         cd.setRole(configuration.getChild("role").getValue());
220         cd.setRoleHint(configuration.getChild("role-hint").getValue());
221         cd.setVersion(configuration.getChild("version").getValue());
222         cd.setComponentType(configuration.getChild("component-type").getValue());
223         cd.setInstantiationStrategy(
224                 configuration.getChild("instantiation-strategy").getValue());
225         cd.setLifecycleHandler(configuration.getChild("lifecycle-handler").getValue());
226         cd.setComponentProfile(configuration.getChild("component-profile").getValue());
227         cd.setComponentComposer(configuration.getChild("component-composer").getValue());
228         cd.setComponentConfigurator(
229                 configuration.getChild("component-configurator").getValue());
230         cd.setComponentFactory(configuration.getChild("component-factory").getValue());
231         cd.setDescription(configuration.getChild("description").getValue());
232         cd.setAlias(configuration.getChild("alias").getValue());
233         String s = configuration.getChild("isolated-realm").getValue();
234 
235         if (s != null) {
236             cd.setIsolatedRealm(s.equals("true"));
237         }
238 
239         // ----------------------------------------------------------------------
240         // Here we want to look for directives for inlining external
241         // configurations. we probably want to take them from files or URLs.
242         // ----------------------------------------------------------------------
243         cd.setConfiguration(configuration.getChild("configuration"));
244         // ----------------------------------------------------------------------
245         // Requirements
246         // ----------------------------------------------------------------------
247         for (PlexusConfiguration requirement :
248                 configuration.getChild("requirements").getChildren("requirement")) {
249             ComponentRequirement cr;
250 
251             PlexusConfiguration[] hints = requirement.getChild("role-hints").getChildren("role-hint");
252             if (hints != null && hints.length > 0) {
253                 cr = new ComponentRequirementList();
254 
255                 List<String> hintList = new LinkedList<>();
256                 for (PlexusConfiguration hint : hints) {
257                     hintList.add(hint.getValue());
258                 }
259 
260                 ((ComponentRequirementList) cr).setRoleHints(hintList);
261             } else {
262                 cr = new ComponentRequirement();
263 
264                 cr.setRoleHint(requirement.getChild("role-hint").getValue());
265             }
266             cr.setRole(requirement.getChild("role").getValue());
267             cr.setOptional(Boolean.parseBoolean(requirement.getChild("optional").getValue()));
268             cr.setFieldName(requirement.getChild("field-name").getValue());
269             cd.addRequirement(cr);
270         }
271         return cd;
272     }
273 }