001    package org.apache.maven.plugin.plugin;
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 org.apache.maven.artifact.ArtifactUtils;
023    import org.apache.maven.plugin.AbstractMojo;
024    import org.apache.maven.plugin.MojoExecutionException;
025    import org.apache.maven.plugin.MojoFailureException;
026    import org.apache.maven.plugin.registry.MavenPluginRegistryBuilder;
027    import org.apache.maven.plugin.registry.Plugin;
028    import org.apache.maven.plugin.registry.PluginRegistry;
029    import org.apache.maven.plugin.registry.PluginRegistryUtils;
030    import org.apache.maven.plugin.registry.TrackableBase;
031    import org.apache.maven.plugin.registry.io.xpp3.PluginRegistryXpp3Writer;
032    import org.apache.maven.plugins.annotations.Component;
033    import org.apache.maven.plugins.annotations.LifecyclePhase;
034    import org.apache.maven.plugins.annotations.Mojo;
035    import org.apache.maven.plugins.annotations.Parameter;
036    import org.codehaus.plexus.util.IOUtil;
037    import org.codehaus.plexus.util.WriterFactory;
038    import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
039    
040    import java.io.File;
041    import java.io.IOException;
042    import java.io.Writer;
043    import java.text.SimpleDateFormat;
044    import java.util.Date;
045    
046    /**
047     * Update the user plugin registry (if it's in use) to reflect the version we're installing.
048     *
049     * @version $Id: UpdatePluginRegistryMojo.java 1345787 2012-06-03 21:58:22Z hboutemy $
050     * @since 2.0
051     */
052    @Mojo( name = "updateRegistry", defaultPhase = LifecyclePhase.INSTALL, threadSafe = true )
053    public class UpdatePluginRegistryMojo
054        extends AbstractMojo
055    {
056        /**
057         * Indicates whether the <code>plugin-registry.xml</code> file is used by Maven or not
058         * to manage plugin versions.
059         */
060        @Parameter( defaultValue = "${settings.usePluginRegistry}", required = true, readonly = true )
061        private boolean usePluginRegistry;
062    
063        /**
064         * The group id of the project currently being built.
065         */
066        @Parameter( defaultValue = "${project.groupId}", required = true, readonly = true )
067        private String groupId;
068    
069        /**
070         * The artifact id of the project currently being built.
071         */
072        @Parameter( defaultValue = "${project.artifactId}", required = true, readonly = true )
073        private String artifactId;
074    
075        /**
076         * The version of the project currently being built.
077         */
078        @Parameter( defaultValue = "${project.artifact.version}", required = true, readonly = true )
079        private String version;
080    
081        /**
082         * Plexus component for retrieving the plugin registry info.
083         */
084        @Component
085        private MavenPluginRegistryBuilder pluginRegistryBuilder;
086    
087        /**
088         * Set this to "true" to skip invoking any goals or reports of the plugin.
089         *
090         * @since 2.8
091         */
092        @Parameter( defaultValue = "false", property = "maven.plugin.skip" )
093        private boolean skip;
094    
095        /**
096         * Set this to "true" to skip updating the plugin registry.
097         *
098         * @since 2.8
099         */
100        @Parameter( defaultValue = "false", property = "maven.plugin.update.registry.skip" )
101        private boolean skipUpdatePluginRegistry;
102    
103        /** {@inheritDoc} */
104        public void execute()
105            throws MojoExecutionException, MojoFailureException
106        {
107            if ( usePluginRegistry )
108            {
109                if ( skip || skipUpdatePluginRegistry )
110                {
111                    getLog().warn( "Execution skipped" );
112                    return;
113                }
114                updatePluginVersionInRegistry( groupId, artifactId, version );
115            }
116        }
117    
118        /**
119         * @param aGroupId not null
120         * @param anArtifactId not null
121         * @param aVersion not null
122         * @throws MojoExecutionException if any
123         */
124        private void updatePluginVersionInRegistry( String aGroupId, String anArtifactId, String aVersion )
125            throws MojoExecutionException
126        {
127            PluginRegistry pluginRegistry;
128            try
129            {
130                pluginRegistry = getPluginRegistry( aGroupId, anArtifactId );
131            }
132            catch ( IOException e )
133            {
134                throw new MojoExecutionException( "Failed to read plugin registry.", e );
135            }
136            catch ( XmlPullParserException e )
137            {
138                throw new MojoExecutionException( "Failed to parse plugin registry.", e );
139            }
140    
141            String pluginKey = ArtifactUtils.versionlessKey( aGroupId, anArtifactId );
142            Plugin plugin = (Plugin) pluginRegistry.getPluginsByKey().get( pluginKey );
143    
144            // if we can find the plugin, but we've gotten here, the useVersion must be missing; fill it in.
145            if ( plugin != null )
146            {
147                if ( TrackableBase.GLOBAL_LEVEL.equals( plugin.getSourceLevel() ) )
148                {
149                    // do nothing. We don't rewrite the globals, under any circumstances.
150                    getLog().warn( "Cannot update registered version for plugin {" + aGroupId + ":" + anArtifactId
151                        + "}; it is specified in the global registry." );
152                }
153                else
154                {
155                    plugin.setUseVersion( aVersion );
156    
157                    SimpleDateFormat format =
158                        new SimpleDateFormat( org.apache.maven.plugin.registry.Plugin.LAST_CHECKED_DATE_FORMAT );
159    
160                    plugin.setLastChecked( format.format( new Date() ) );
161                }
162            }
163            else
164            {
165                plugin = new org.apache.maven.plugin.registry.Plugin();
166    
167                plugin.setGroupId( aGroupId );
168                plugin.setArtifactId( anArtifactId );
169                plugin.setUseVersion( aVersion );
170    
171                pluginRegistry.addPlugin( plugin );
172    
173                pluginRegistry.flushPluginsByKey();
174            }
175    
176            writeUserRegistry( aGroupId, anArtifactId, pluginRegistry );
177        }
178    
179        /**
180         * @param aGroupId not null
181         * @param anArtifactId not null
182         * @param pluginRegistry not null
183         */
184        private void writeUserRegistry( String aGroupId, String anArtifactId, PluginRegistry pluginRegistry )
185        {
186            File pluginRegistryFile = pluginRegistry.getRuntimeInfo().getFile();
187    
188            PluginRegistry extractedUserRegistry = PluginRegistryUtils.extractUserPluginRegistry( pluginRegistry );
189    
190            // only rewrite the user-level registry if one existed before, or if we've created user-level data here.
191            if ( extractedUserRegistry != null )
192            {
193                Writer fWriter = null;
194    
195                try
196                {
197                    pluginRegistryFile.getParentFile().mkdirs();
198                    fWriter = WriterFactory.newXmlWriter( pluginRegistryFile );
199    
200                    PluginRegistryXpp3Writer writer = new PluginRegistryXpp3Writer();
201    
202                    writer.write( fWriter, extractedUserRegistry );
203                }
204                catch ( IOException e )
205                {
206                    getLog().warn( "Cannot rewrite user-level plugin-registry.xml with new plugin version of plugin: \'"
207                        + aGroupId + ":" + anArtifactId + "\'.", e );
208                }
209                finally
210                {
211                    IOUtil.close( fWriter );
212                }
213            }
214        }
215    
216        /**
217         * @param aGroupId not null
218         * @param anArtifactId not null
219         * @return the plugin registry instance
220         * @throws IOException if any
221         * @throws XmlPullParserException if any
222         */
223        private PluginRegistry getPluginRegistry( String aGroupId, String anArtifactId )
224            throws IOException, XmlPullParserException
225        {
226            PluginRegistry pluginRegistry = null;
227    
228            pluginRegistry = pluginRegistryBuilder.buildPluginRegistry();
229    
230            if ( pluginRegistry == null )
231            {
232                pluginRegistry = pluginRegistryBuilder.createUserPluginRegistry();
233            }
234    
235            return pluginRegistry;
236        }
237    }