001package org.apache.maven.tools.plugin.extractor.model;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.maven.plugin.descriptor.DuplicateParameterException;
023import org.apache.maven.plugin.descriptor.MojoDescriptor;
024import org.apache.maven.plugin.descriptor.Parameter;
025import org.apache.maven.tools.plugin.extractor.model.io.xpp3.PluginMetadataXpp3Reader;
026import org.codehaus.plexus.component.repository.ComponentRequirement;
027import org.codehaus.plexus.util.ReaderFactory;
028import org.codehaus.plexus.util.StringUtils;
029import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
030
031import java.io.File;
032import java.io.IOException;
033import java.io.Reader;
034import java.util.HashSet;
035import java.util.List;
036import java.util.Set;
037
038/**
039 * Parser for plugin metadata.
040 */
041public class PluginMetadataParser
042{
043    /**
044     * Default implementation path which will be replaced in
045     * AbstractScriptedMojoDescriptorExtractor#extractMojoDescriptorsFromMetadata(Map, PluginDescriptor)
046     */
047    public static final String IMPL_BASE_PLACEHOLDER = "<REPLACE-WITH-MOJO-PATH>";
048
049    /**
050     * @param metadataFile the metadata file to be parse
051     * @return a set of <code>MojoDescriptor</code>
052     * @throws PluginMetadataParseException if any
053     */
054    public Set<MojoDescriptor> parseMojoDescriptors( File metadataFile )
055        throws PluginMetadataParseException
056    {
057        Set<MojoDescriptor> descriptors = new HashSet<>();
058
059        try ( Reader reader = ReaderFactory.newXmlReader( metadataFile ) )
060        {
061
062            PluginMetadataXpp3Reader metadataReader = new PluginMetadataXpp3Reader();
063
064            PluginMetadata pluginMetadata = metadataReader.read( reader );
065
066            List<Mojo> mojos = pluginMetadata.getMojos();
067
068            if ( mojos != null )
069            {
070                for ( Mojo mojo : mojos )
071                {
072                    MojoDescriptor descriptor = asDescriptor( metadataFile, mojo );
073
074                    descriptors.add( descriptor );
075                }
076            }
077        }
078        catch ( IOException | XmlPullParserException e )
079        {
080            throw new PluginMetadataParseException( metadataFile, "Cannot parse plugin metadata from file.", e );
081        }
082
083        return descriptors;
084    }
085
086    /**
087     * @param metadataFile not null
088     * @param mojo         not null
089     * @return a mojo descriptor instance
090     * @throws PluginMetadataParseException if any
091     */
092    private MojoDescriptor asDescriptor( File metadataFile, Mojo mojo )
093        throws PluginMetadataParseException
094    {
095        MojoDescriptor descriptor = new MojoDescriptor();
096
097        if ( mojo.getCall() != null )
098        {
099            descriptor.setImplementation( IMPL_BASE_PLACEHOLDER + ":" + mojo.getCall() );
100        }
101        else
102        {
103            descriptor.setImplementation( IMPL_BASE_PLACEHOLDER );
104        }
105
106        descriptor.setGoal( mojo.getGoal() );
107        descriptor.setPhase( mojo.getPhase() );
108        descriptor.setDependencyResolutionRequired( mojo.getRequiresDependencyResolution() );
109        descriptor.setAggregator( mojo.isAggregator() );
110        descriptor.setInheritedByDefault( mojo.isInheritByDefault() );
111        descriptor.setDirectInvocationOnly( mojo.isRequiresDirectInvocation() );
112        descriptor.setOnlineRequired( mojo.isRequiresOnline() );
113        descriptor.setProjectRequired( mojo.isRequiresProject() );
114        descriptor.setRequiresReports( mojo.isRequiresReports() );
115        descriptor.setDescription( mojo.getDescription() );
116        descriptor.setDeprecated( mojo.getDeprecation() );
117        descriptor.setSince( mojo.getSince() );
118
119        LifecycleExecution le = mojo.getExecution();
120        if ( le != null )
121        {
122            descriptor.setExecuteLifecycle( le.getLifecycle() );
123            descriptor.setExecutePhase( le.getPhase() );
124            descriptor.setExecuteGoal( le.getGoal() );
125        }
126
127        List<org.apache.maven.tools.plugin.extractor.model.Parameter> parameters = mojo.getParameters();
128
129        if ( parameters != null && !parameters.isEmpty() )
130        {
131            for ( org.apache.maven.tools.plugin.extractor.model.Parameter param : parameters )
132            {
133                Parameter dParam = new Parameter();
134                dParam.setAlias( param.getAlias() );
135                dParam.setDeprecated( param.getDeprecation() );
136                dParam.setDescription( param.getDescription() );
137                dParam.setEditable( !param.isReadonly() );
138                dParam.setExpression( param.getExpression() );
139                dParam.setDefaultValue( param.getDefaultValue() );
140                dParam.setSince( param.getSince() );
141
142                String property = param.getProperty();
143                if ( StringUtils.isNotEmpty( property ) )
144                {
145                    dParam.setName( property );
146                }
147                else
148                {
149                    dParam.setName( param.getName() );
150                }
151
152                if ( StringUtils.isEmpty( dParam.getName() ) )
153                {
154                    throw new PluginMetadataParseException( metadataFile, "Mojo: \'" + mojo.getGoal()
155                        + "\' has a parameter without either property or name attributes. Please specify one." );
156                }
157
158                dParam.setRequired( param.isRequired() );
159                dParam.setType( param.getType() );
160
161                try
162                {
163                    descriptor.addParameter( dParam );
164                }
165                catch ( DuplicateParameterException e )
166                {
167                    throw new PluginMetadataParseException( metadataFile,
168                                                            "Duplicate parameters detected for mojo: " + mojo.getGoal(),
169                                                            e );
170                }
171            }
172        }
173
174        List<Component> components = mojo.getComponents();
175
176        if ( components != null && !components.isEmpty() )
177        {
178            for ( Component component : components )
179            {
180                ComponentRequirement cr = new ComponentRequirement();
181                cr.setRole( component.getRole() );
182                cr.setRoleHint( component.getHint() );
183
184                descriptor.addRequirement( cr );
185            }
186        }
187
188        return descriptor;
189    }
190}