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
044    private boolean isV4;
045
046    public PluginDescriptor build(Reader reader) throws PlexusConfigurationException {
047        return build(reader, null);
048    }
049
050    public PluginDescriptor build(Reader reader, String source) throws PlexusConfigurationException {
051        PlexusConfiguration c = buildConfiguration(reader);
052
053        PluginDescriptor pluginDescriptor = new PluginDescriptor();
054
055        pluginDescriptor.setSource(source);
056        pluginDescriptor.setGroupId(c.getChild("groupId").getValue());
057        pluginDescriptor.setArtifactId(c.getChild("artifactId").getValue());
058        pluginDescriptor.setVersion(c.getChild("version").getValue());
059        pluginDescriptor.setGoalPrefix(c.getChild("goalPrefix").getValue());
060
061        pluginDescriptor.setName(c.getChild("name").getValue());
062        pluginDescriptor.setDescription(c.getChild("description").getValue());
063
064        String isolatedRealm = c.getChild("isolatedRealm").getValue();
065
066        if (isolatedRealm != null) {
067            pluginDescriptor.setIsolatedRealm(Boolean.parseBoolean(isolatedRealm));
068        }
069
070        String inheritedByDefault = c.getChild("inheritedByDefault").getValue();
071
072        if (inheritedByDefault != null) {
073            pluginDescriptor.setInheritedByDefault(Boolean.parseBoolean(inheritedByDefault));
074        }
075
076        String requiredMavenVersion = c.getChild("requiredMavenVersion").getValue();
077        if (requiredMavenVersion != null) {
078            isV4 = requiredMavenVersion.startsWith("4");
079        } else {
080            isV4 = false;
081        }
082
083        // ----------------------------------------------------------------------
084        // Components
085        // ----------------------------------------------------------------------
086
087        PlexusConfiguration[] mojoConfigurations = c.getChild("mojos").getChildren("mojo");
088
089        for (PlexusConfiguration component : mojoConfigurations) {
090            MojoDescriptor mojoDescriptor = buildComponentDescriptor(component, pluginDescriptor);
091
092            pluginDescriptor.addMojo(mojoDescriptor);
093        }
094
095        // ----------------------------------------------------------------------
096        // Dependencies
097        // ----------------------------------------------------------------------
098
099        PlexusConfiguration[] dependencyConfigurations =
100                c.getChild("dependencies").getChildren("dependency");
101
102        List<ComponentDependency> dependencies = new ArrayList<>();
103
104        for (PlexusConfiguration d : dependencyConfigurations) {
105            ComponentDependency cd = new ComponentDependency();
106
107            cd.setArtifactId(d.getChild("artifactId").getValue());
108
109            cd.setGroupId(d.getChild("groupId").getValue());
110
111            cd.setType(d.getChild("type").getValue());
112
113            cd.setVersion(d.getChild("version").getValue());
114
115            dependencies.add(cd);
116        }
117
118        pluginDescriptor.setDependencies(dependencies);
119
120        return pluginDescriptor;
121    }
122
123    @SuppressWarnings("checkstyle:methodlength")
124    public MojoDescriptor buildComponentDescriptor(PlexusConfiguration c, PluginDescriptor pluginDescriptor)
125            throws PlexusConfigurationException {
126        MojoDescriptor mojo = new MojoDescriptor();
127        mojo.setPluginDescriptor(pluginDescriptor);
128
129        mojo.setGoal(c.getChild("goal").getValue());
130
131        mojo.setImplementation(c.getChild("implementation").getValue());
132
133        PlexusConfiguration langConfig = c.getChild("language");
134
135        if (langConfig != null) {
136            mojo.setLanguage(langConfig.getValue());
137        }
138
139        PlexusConfiguration configuratorConfig = c.getChild("configurator");
140
141        if (configuratorConfig != null) {
142            mojo.setComponentConfigurator(configuratorConfig.getValue());
143        }
144
145        PlexusConfiguration composerConfig = c.getChild("composer");
146
147        if (composerConfig != null) {
148            mojo.setComponentComposer(composerConfig.getValue());
149        }
150
151        String since = c.getChild("since").getValue();
152
153        if (since != null) {
154            mojo.setSince(since);
155        }
156
157        PlexusConfiguration deprecated = c.getChild("deprecated", false);
158
159        if (deprecated != null) {
160            mojo.setDeprecated(deprecated.getValue());
161        }
162
163        String phase = c.getChild("phase").getValue();
164
165        if (phase != null) {
166            mojo.setPhase(phase);
167        }
168
169        String executePhase = c.getChild("executePhase").getValue();
170
171        if (executePhase != null) {
172            mojo.setExecutePhase(executePhase);
173        }
174
175        String executeMojo = c.getChild("executeGoal").getValue();
176
177        if (executeMojo != null) {
178            mojo.setExecuteGoal(executeMojo);
179        }
180
181        String executeLifecycle = c.getChild("executeLifecycle").getValue();
182
183        if (executeLifecycle != null) {
184            mojo.setExecuteLifecycle(executeLifecycle);
185        }
186
187        mojo.setInstantiationStrategy(c.getChild("instantiationStrategy").getValue());
188
189        mojo.setDescription(c.getChild("description").getValue());
190
191        PlexusConfiguration dependencyResolution = c.getChild("requiresDependencyResolution", false);
192
193        if (dependencyResolution != null) {
194            mojo.setDependencyResolutionRequired(dependencyResolution.getValue());
195        }
196
197        PlexusConfiguration dependencyCollection = c.getChild("requiresDependencyCollection", false);
198
199        if (dependencyCollection != null) {
200            mojo.setDependencyCollectionRequired(dependencyCollection.getValue());
201        }
202
203        String directInvocationOnly = c.getChild("requiresDirectInvocation").getValue();
204
205        if (directInvocationOnly != null) {
206            mojo.setDirectInvocationOnly(Boolean.parseBoolean(directInvocationOnly));
207        }
208
209        String requiresProject = c.getChild("requiresProject").getValue();
210
211        if (requiresProject != null) {
212            mojo.setProjectRequired(Boolean.parseBoolean(requiresProject));
213        }
214
215        String requiresReports = c.getChild("requiresReports").getValue();
216
217        if (requiresReports != null) {
218            mojo.setRequiresReports(Boolean.parseBoolean(requiresReports));
219        }
220
221        String aggregator = c.getChild("aggregator").getValue();
222
223        if (aggregator != null) {
224            mojo.setAggregator(Boolean.parseBoolean(aggregator));
225        }
226
227        String requiresOnline = c.getChild("requiresOnline").getValue();
228
229        if (requiresOnline != null) {
230            mojo.setOnlineRequired(Boolean.parseBoolean(requiresOnline));
231        }
232
233        String inheritedByDefault = c.getChild("inheritedByDefault").getValue();
234
235        if (inheritedByDefault != null) {
236            mojo.setInheritedByDefault(Boolean.parseBoolean(inheritedByDefault));
237        }
238
239        String threadSafe = c.getChild("threadSafe").getValue();
240
241        if (threadSafe != null) {
242            mojo.setThreadSafe(Boolean.parseBoolean(threadSafe));
243        }
244
245        // ----------------------------------------------------------------------
246        // Configuration
247        // ----------------------------------------------------------------------
248
249        PlexusConfiguration mojoConfig = c.getChild("configuration");
250        mojo.setMojoConfiguration(mojoConfig);
251
252        // ----------------------------------------------------------------------
253        // Parameters
254        // ----------------------------------------------------------------------
255
256        PlexusConfiguration[] parameterConfigurations = c.getChild("parameters").getChildren("parameter");
257
258        List<Parameter> parameters = new ArrayList<>();
259
260        for (PlexusConfiguration d : parameterConfigurations) {
261            Parameter parameter = new Parameter();
262
263            parameter.setName(d.getChild("name").getValue());
264
265            parameter.setAlias(d.getChild("alias").getValue());
266
267            parameter.setType(d.getChild("type").getValue());
268
269            String required = d.getChild("required").getValue();
270
271            parameter.setRequired(Boolean.parseBoolean(required));
272
273            PlexusConfiguration editableConfig = d.getChild("editable");
274
275            // we need the null check for pre-build legacy plugins...
276            if (editableConfig != null) {
277                String editable = d.getChild("editable").getValue();
278
279                parameter.setEditable(editable == null || Boolean.parseBoolean(editable));
280            }
281
282            parameter.setDescription(d.getChild("description").getValue());
283
284            parameter.setDeprecated(d.getChild("deprecated").getValue());
285
286            parameter.setImplementation(d.getChild("implementation").getValue());
287
288            parameter.setSince(d.getChild("since").getValue());
289
290            if (isV4) {
291                parameter.setExpression(d.getChild("expression").getValue());
292                parameter.setDefaultValue(d.getChild("defaultValue").getValue());
293            } else {
294                PlexusConfiguration paramConfig = mojoConfig.getChild(parameter.getName(), false);
295                if (paramConfig != null) {
296                    parameter.setExpression(paramConfig.getValue(null));
297                    parameter.setDefaultValue(paramConfig.getAttribute("default-value"));
298                }
299            }
300
301            parameters.add(parameter);
302        }
303
304        mojo.setParameters(parameters);
305
306        // TODO this should not need to be handed off...
307
308        // ----------------------------------------------------------------------
309        // Requirements
310        // ----------------------------------------------------------------------
311
312        PlexusConfiguration[] requirements = c.getChild("requirements").getChildren("requirement");
313
314        for (PlexusConfiguration requirement : requirements) {
315            ComponentRequirement cr = new ComponentRequirement();
316
317            cr.setRole(requirement.getChild("role").getValue());
318
319            cr.setRoleHint(requirement.getChild("role-hint").getValue());
320
321            cr.setFieldName(requirement.getChild("field-name").getValue());
322
323            mojo.addRequirement(cr);
324        }
325
326        return mojo;
327    }
328
329    // ----------------------------------------------------------------------
330    //
331    // ----------------------------------------------------------------------
332
333    public PlexusConfiguration buildConfiguration(Reader configuration) throws PlexusConfigurationException {
334        try {
335            return new XmlPlexusConfiguration(Xpp3DomBuilder.build(configuration));
336        } catch (IOException | XmlPullParserException e) {
337            throw new PlexusConfigurationException(e.getMessage(), e);
338        }
339    }
340}