001    package org.apache.maven.plugin.tools.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    
022    import java.io.File;
023    import java.io.IOException;
024    import java.io.Reader;
025    import java.util.HashSet;
026    import java.util.List;
027    import java.util.Set;
028    
029    import org.apache.maven.plugin.descriptor.DuplicateParameterException;
030    import org.apache.maven.plugin.descriptor.MojoDescriptor;
031    import org.apache.maven.plugin.descriptor.Parameter;
032    import org.apache.maven.plugin.tools.model.io.xpp3.PluginMetadataXpp3Reader;
033    import org.codehaus.plexus.component.repository.ComponentRequirement;
034    import org.codehaus.plexus.util.IOUtil;
035    import org.codehaus.plexus.util.ReaderFactory;
036    import org.codehaus.plexus.util.StringUtils;
037    import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
038    
039    /**
040     * Parser for plugin metadata.
041     *
042     * @version $Id: PluginMetadataParser.java 1133707 2011-06-09 08:28:59Z stephenc $
043     */
044    public class PluginMetadataParser
045    {
046        /** Default implementation path which will be replaced in
047         * AbstractScriptedMojoDescriptorExtractor#extractMojoDescriptorsFromMetadata(Map, PluginDescriptor) */
048        public static final String IMPL_BASE_PLACEHOLDER = "<REPLACE-WITH-MOJO-PATH>";
049    
050        /**
051         * @param metadataFile the metadata file to be parse
052         * @return a set of <code>MojoDescriptor</code>
053         * @throws PluginMetadataParseException if any
054         */
055        public Set<MojoDescriptor> parseMojoDescriptors( File metadataFile )
056            throws PluginMetadataParseException
057        {
058            Set<MojoDescriptor> descriptors = new HashSet<MojoDescriptor>();
059    
060            Reader reader = null;
061    
062            try
063            {
064                reader = ReaderFactory.newXmlReader( metadataFile );
065    
066                PluginMetadataXpp3Reader metadataReader = new PluginMetadataXpp3Reader();
067    
068                PluginMetadata pluginMetadata = metadataReader.read( reader );
069    
070                List<Mojo> mojos = pluginMetadata.getMojos();
071    
072                if ( mojos != null && !mojos.isEmpty() )
073                {
074                    for ( Mojo mojo :mojos )
075                    {
076                        MojoDescriptor descriptor = asDescriptor( metadataFile, mojo );
077    
078                        descriptors.add( descriptor );
079                    }
080                }
081            }
082            catch ( IOException e )
083            {
084                throw new PluginMetadataParseException( metadataFile, "Cannot parse plugin metadata from file.", e );
085            }
086            catch ( XmlPullParserException e )
087            {
088                throw new PluginMetadataParseException( metadataFile, "Cannot parse plugin metadata from file.", e );
089            }
090            finally
091            {
092                IOUtil.close( reader );
093            }
094    
095            return descriptors;
096        }
097    
098        /**
099         * @param metadataFile not null
100         * @param mojo not null
101         * @return a mojo descriptor instance
102         * @throws PluginMetadataParseException if any
103         */
104        private MojoDescriptor asDescriptor( File metadataFile, Mojo mojo )
105            throws PluginMetadataParseException
106        {
107            MojoDescriptor descriptor = new MojoDescriptor();
108    
109            if ( mojo.getCall() != null )
110            {
111                descriptor.setImplementation( IMPL_BASE_PLACEHOLDER + ":" + mojo.getCall() );
112            }
113            else
114            {
115                descriptor.setImplementation( IMPL_BASE_PLACEHOLDER );
116            }
117    
118            descriptor.setGoal( mojo.getGoal() );
119            descriptor.setPhase( mojo.getPhase() );
120            descriptor.setDependencyResolutionRequired( mojo.getRequiresDependencyResolution() );
121            descriptor.setAggregator( mojo.isAggregator() );
122            descriptor.setInheritedByDefault( mojo.isInheritByDefault() );
123            descriptor.setDirectInvocationOnly( mojo.isRequiresDirectInvocation() );
124            descriptor.setOnlineRequired( mojo.isRequiresOnline() );
125            descriptor.setProjectRequired( mojo.isRequiresProject() );
126            descriptor.setRequiresReports( mojo.isRequiresReports() );
127            descriptor.setDescription( mojo.getDescription() );
128            descriptor.setDeprecated( mojo.getDeprecation() );
129    
130            LifecycleExecution le = mojo.getExecution();
131            if ( le != null )
132            {
133                descriptor.setExecuteLifecycle( le.getLifecycle() );
134                descriptor.setExecutePhase( le.getPhase() );
135            }
136    
137            List<org.apache.maven.plugin.tools.model.Parameter> parameters = mojo.getParameters();
138    
139            if ( parameters != null && !parameters.isEmpty() )
140            {
141                for ( org.apache.maven.plugin.tools.model.Parameter param : parameters )
142                {
143                    Parameter dParam = new Parameter();
144                    dParam.setAlias( param.getAlias() );
145                    dParam.setDeprecated( param.getDeprecation() );
146                    dParam.setDescription( param.getDescription() );
147                    dParam.setEditable( !param.isReadonly() );
148                    dParam.setExpression( param.getExpression() );
149                    dParam.setDefaultValue( param.getDefaultValue() );
150    
151                    String property = param.getProperty();
152                    if ( StringUtils.isNotEmpty( property ) )
153                    {
154                        dParam.setName( property );
155                    }
156                    else
157                    {
158                        dParam.setName( param.getName() );
159                    }
160    
161                    if ( StringUtils.isEmpty( dParam.getName() ) )
162                    {
163                        throw new PluginMetadataParseException( metadataFile, "Mojo: \'" + mojo.getGoal()
164                            + "\' has a parameter without either property or name attributes. Please specify one." );
165                    }
166    
167                    dParam.setRequired( param.isRequired() );
168                    dParam.setType( param.getType() );
169    
170                    try
171                    {
172                        descriptor.addParameter( dParam );
173                    }
174                    catch ( DuplicateParameterException e )
175                    {
176                        throw new PluginMetadataParseException( metadataFile,
177                                                                "Duplicate parameters detected for mojo: "
178                                                                    + mojo.getGoal(), e );
179                    }
180                }
181            }
182    
183            List<Component> components = mojo.getComponents();
184    
185            if ( components != null && !components.isEmpty() )
186            {
187                for ( Component component : components )
188                {
189                    ComponentRequirement cr = new ComponentRequirement();
190                    cr.setRole( component.getRole() );
191                    cr.setRoleHint( component.getHint() );
192    
193                    descriptor.addRequirement( cr );
194                }
195            }
196    
197            return descriptor;
198        }
199    }