001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.maven.plugins.plugin.descriptor;
020
021import java.io.IOException;
022import java.io.Reader;
023import java.util.ArrayList;
024import java.util.List;
025
026import org.apache.maven.plugin.descriptor.MojoDescriptor;
027import org.apache.maven.plugin.descriptor.Parameter;
028import org.apache.maven.plugin.descriptor.PluginDescriptor;
029import org.codehaus.plexus.component.repository.ComponentDependency;
030import org.codehaus.plexus.component.repository.ComponentRequirement;
031import org.codehaus.plexus.configuration.PlexusConfiguration;
032import org.codehaus.plexus.configuration.PlexusConfigurationException;
033import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
034import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
035import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
036
037/**
038 * Build plugin descriptor object from {@code plugin.xml}.
039 *
040 * @author Jason van Zyl
041 */
042public class PluginDescriptorBuilder {
043    public PluginDescriptor build(Reader reader) throws PlexusConfigurationException {
044        return build(reader, null);
045    }
046
047    public PluginDescriptor build(Reader reader, String source) throws PlexusConfigurationException {
048        PlexusConfiguration c = buildConfiguration(reader);
049
050        PluginDescriptor pluginDescriptor = new PluginDescriptor();
051
052        pluginDescriptor.setSource(source);
053        pluginDescriptor.setGroupId(c.getChild("groupId").getValue());
054        pluginDescriptor.setArtifactId(c.getChild("artifactId").getValue());
055        pluginDescriptor.setVersion(c.getChild("version").getValue());
056        pluginDescriptor.setGoalPrefix(c.getChild("goalPrefix").getValue());
057
058        pluginDescriptor.setName(c.getChild("name").getValue());
059        pluginDescriptor.setDescription(c.getChild("description").getValue());
060
061        String isolatedRealm = c.getChild("isolatedRealm").getValue();
062
063        if (isolatedRealm != null) {
064            pluginDescriptor.setIsolatedRealm(Boolean.parseBoolean(isolatedRealm));
065        }
066
067        String inheritedByDefault = c.getChild("inheritedByDefault").getValue();
068
069        if (inheritedByDefault != null) {
070            pluginDescriptor.setInheritedByDefault(Boolean.parseBoolean(inheritedByDefault));
071        }
072
073        // ----------------------------------------------------------------------
074        // Components
075        // ----------------------------------------------------------------------
076
077        PlexusConfiguration[] mojoConfigurations = c.getChild("mojos").getChildren("mojo");
078
079        for (PlexusConfiguration component : mojoConfigurations) {
080            MojoDescriptor mojoDescriptor = buildComponentDescriptor(component, pluginDescriptor);
081
082            pluginDescriptor.addMojo(mojoDescriptor);
083        }
084
085        // ----------------------------------------------------------------------
086        // Dependencies
087        // ----------------------------------------------------------------------
088
089        PlexusConfiguration[] dependencyConfigurations =
090                c.getChild("dependencies").getChildren("dependency");
091
092        List<ComponentDependency> dependencies = new ArrayList<>();
093
094        for (PlexusConfiguration d : dependencyConfigurations) {
095            ComponentDependency cd = new ComponentDependency();
096
097            cd.setArtifactId(d.getChild("artifactId").getValue());
098
099            cd.setGroupId(d.getChild("groupId").getValue());
100
101            cd.setType(d.getChild("type").getValue());
102
103            cd.setVersion(d.getChild("version").getValue());
104
105            dependencies.add(cd);
106        }
107
108        pluginDescriptor.setDependencies(dependencies);
109
110        return pluginDescriptor;
111    }
112
113    @SuppressWarnings("checkstyle:methodlength")
114    public MojoDescriptor buildComponentDescriptor(PlexusConfiguration c, PluginDescriptor pluginDescriptor)
115            throws PlexusConfigurationException {
116        MojoDescriptor mojo = new MojoDescriptor();
117        mojo.setPluginDescriptor(pluginDescriptor);
118
119        mojo.setGoal(c.getChild("goal").getValue());
120
121        mojo.setImplementation(c.getChild("implementation").getValue());
122
123        PlexusConfiguration langConfig = c.getChild("language");
124
125        if (langConfig != null) {
126            mojo.setLanguage(langConfig.getValue());
127        }
128
129        PlexusConfiguration configuratorConfig = c.getChild("configurator");
130
131        if (configuratorConfig != null) {
132            mojo.setComponentConfigurator(configuratorConfig.getValue());
133        }
134
135        PlexusConfiguration composerConfig = c.getChild("composer");
136
137        if (composerConfig != null) {
138            mojo.setComponentComposer(composerConfig.getValue());
139        }
140
141        String since = c.getChild("since").getValue();
142
143        if (since != null) {
144            mojo.setSince(since);
145        }
146
147        PlexusConfiguration deprecated = c.getChild("deprecated", false);
148
149        if (deprecated != null) {
150            mojo.setDeprecated(deprecated.getValue());
151        }
152
153        String phase = c.getChild("phase").getValue();
154
155        if (phase != null) {
156            mojo.setPhase(phase);
157        }
158
159        String executePhase = c.getChild("executePhase").getValue();
160
161        if (executePhase != null) {
162            mojo.setExecutePhase(executePhase);
163        }
164
165        String executeMojo = c.getChild("executeGoal").getValue();
166
167        if (executeMojo != null) {
168            mojo.setExecuteGoal(executeMojo);
169        }
170
171        String executeLifecycle = c.getChild("executeLifecycle").getValue();
172
173        if (executeLifecycle != null) {
174            mojo.setExecuteLifecycle(executeLifecycle);
175        }
176
177        mojo.setInstantiationStrategy(c.getChild("instantiationStrategy").getValue());
178
179        mojo.setDescription(c.getChild("description").getValue());
180
181        PlexusConfiguration dependencyResolution = c.getChild("requiresDependencyResolution", false);
182
183        if (dependencyResolution != null) {
184            mojo.setDependencyResolutionRequired(dependencyResolution.getValue());
185        }
186
187        PlexusConfiguration dependencyCollection = c.getChild("requiresDependencyCollection", false);
188
189        if (dependencyCollection != null) {
190            mojo.setDependencyCollectionRequired(dependencyCollection.getValue());
191        }
192
193        String directInvocationOnly = c.getChild("requiresDirectInvocation").getValue();
194
195        if (directInvocationOnly != null) {
196            mojo.setDirectInvocationOnly(Boolean.parseBoolean(directInvocationOnly));
197        }
198
199        String requiresProject = c.getChild("requiresProject").getValue();
200
201        if (requiresProject != null) {
202            mojo.setProjectRequired(Boolean.parseBoolean(requiresProject));
203        }
204
205        String requiresReports = c.getChild("requiresReports").getValue();
206
207        if (requiresReports != null) {
208            mojo.setRequiresReports(Boolean.parseBoolean(requiresReports));
209        }
210
211        String aggregator = c.getChild("aggregator").getValue();
212
213        if (aggregator != null) {
214            mojo.setAggregator(Boolean.parseBoolean(aggregator));
215        }
216
217        String requiresOnline = c.getChild("requiresOnline").getValue();
218
219        if (requiresOnline != null) {
220            mojo.setOnlineRequired(Boolean.parseBoolean(requiresOnline));
221        }
222
223        String inheritedByDefault = c.getChild("inheritedByDefault").getValue();
224
225        if (inheritedByDefault != null) {
226            mojo.setInheritedByDefault(Boolean.parseBoolean(inheritedByDefault));
227        }
228
229        String threadSafe = c.getChild("threadSafe").getValue();
230
231        if (threadSafe != null) {
232            mojo.setThreadSafe(Boolean.parseBoolean(threadSafe));
233        }
234
235        // ----------------------------------------------------------------------
236        // Configuration
237        // ----------------------------------------------------------------------
238
239        PlexusConfiguration mojoConfig = c.getChild("configuration");
240        mojo.setMojoConfiguration(mojoConfig);
241
242        // ----------------------------------------------------------------------
243        // Parameters
244        // ----------------------------------------------------------------------
245
246        PlexusConfiguration[] parameterConfigurations = c.getChild("parameters").getChildren("parameter");
247
248        List<Parameter> parameters = new ArrayList<>();
249
250        for (PlexusConfiguration d : parameterConfigurations) {
251            Parameter parameter = new Parameter();
252
253            parameter.setName(d.getChild("name").getValue());
254
255            parameter.setAlias(d.getChild("alias").getValue());
256
257            parameter.setType(d.getChild("type").getValue());
258
259            String required = d.getChild("required").getValue();
260
261            parameter.setRequired(Boolean.parseBoolean(required));
262
263            PlexusConfiguration editableConfig = d.getChild("editable");
264
265            // we need the null check for pre-build legacy plugins...
266            if (editableConfig != null) {
267                String editable = d.getChild("editable").getValue();
268
269                parameter.setEditable(editable == null || Boolean.parseBoolean(editable));
270            }
271
272            parameter.setDescription(d.getChild("description").getValue());
273
274            parameter.setDeprecated(d.getChild("deprecated").getValue());
275
276            parameter.setImplementation(d.getChild("implementation").getValue());
277
278            parameter.setSince(d.getChild("since").getValue());
279
280            PlexusConfiguration paramConfig = mojoConfig.getChild(parameter.getName(), false);
281            if (paramConfig != null) {
282                parameter.setExpression(paramConfig.getValue(null));
283                parameter.setDefaultValue(paramConfig.getAttribute("default-value"));
284            }
285
286            parameters.add(parameter);
287        }
288
289        mojo.setParameters(parameters);
290
291        // TODO this should not need to be handed off...
292
293        // ----------------------------------------------------------------------
294        // Requirements
295        // ----------------------------------------------------------------------
296
297        PlexusConfiguration[] requirements = c.getChild("requirements").getChildren("requirement");
298
299        for (PlexusConfiguration requirement : requirements) {
300            ComponentRequirement cr = new ComponentRequirement();
301
302            cr.setRole(requirement.getChild("role").getValue());
303
304            cr.setRoleHint(requirement.getChild("role-hint").getValue());
305
306            cr.setFieldName(requirement.getChild("field-name").getValue());
307
308            mojo.addRequirement(cr);
309        }
310
311        return mojo;
312    }
313
314    // ----------------------------------------------------------------------
315    //
316    // ----------------------------------------------------------------------
317
318    public PlexusConfiguration buildConfiguration(Reader configuration) throws PlexusConfigurationException {
319        try {
320            return new XmlPlexusConfiguration(Xpp3DomBuilder.build(configuration));
321        } catch (IOException | XmlPullParserException e) {
322            throw new PlexusConfigurationException(e.getMessage(), e);
323        }
324    }
325}