View Javadoc

1   package org.apache.maven.plugin.gpg;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.util.ArrayList;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  import java.util.List;
28  import java.util.Map;
29  
30  import org.apache.maven.artifact.Artifact;
31  import org.apache.maven.artifact.handler.ArtifactHandler;
32  import org.apache.maven.artifact.handler.DefaultArtifactHandler;
33  import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
34  import org.apache.maven.plugin.MojoExecutionException;
35  import org.apache.maven.plugin.MojoFailureException;
36  import org.apache.maven.project.MavenProject;
37  import org.apache.maven.project.MavenProjectHelper;
38  import org.codehaus.plexus.util.FileUtils;
39  import org.codehaus.plexus.util.SelectorUtils;
40  
41  /**
42   * Sign project artifact, the POM, and attached artifacts with GnuPG for deployment.
43   * 
44   * @author Jason van Zyl
45   * @author Jason Dillon
46   * @author Daniel Kulp
47   * @goal sign
48   * @phase verify
49   */
50  public class GpgSignAttachedMojo
51      extends AbstractGpgMojo
52  {
53  
54      private static final String DEFAULT_EXCLUDES[] = new String[] { "**/*.md5", "**/*.sha1", "**/*.asc" };
55  
56      /**
57       * Skip doing the gpg signing.
58       * 
59       * @parameter expression="${gpg.skip}" default-value="false"
60       */
61      private boolean skip;
62  
63      /**
64       * A list of files to exclude from being signed. Can contain Ant-style wildcards and double wildcards. The default
65       * excludes are <code>**&#47;*.md5   **&#47;*.sha1    **&#47;*.asc</code>.
66       * 
67       * @parameter
68       * @since 1.0-alpha-4
69       */
70      private String[] excludes;
71  
72      /**
73       * The directory where to store signature files.
74       * 
75       * @parameter default-value="${project.build.directory}/gpg" alias="outputDirectory"
76       * @since 1.0-alpha-4
77       */
78      private File ascDirectory;
79  
80      /**
81       * The maven project.
82       * 
83       * @parameter default-value="${project}"
84       * @required
85       * @readonly
86       */
87      protected MavenProject project;
88  
89      /**
90       * Maven ProjectHelper
91       * 
92       * @component
93       * @required
94       * @readonly
95       */
96      private MavenProjectHelper projectHelper;
97  
98      /**
99       * Maven ArtifactHandlerManager
100      * 
101      * @component
102      * @required
103      * @readonly
104      */
105     private ArtifactHandlerManager artifactHandlerManager;
106 
107     public void execute()
108         throws MojoExecutionException, MojoFailureException
109     {
110         if ( skip )
111         {
112             // We're skipping the signing stuff
113             return;
114         }
115 
116         if ( excludes == null || excludes.length == 0 )
117         {
118             excludes = DEFAULT_EXCLUDES;
119         }
120         String newExcludes[] = new String[excludes.length];
121         for ( int i = 0; i < excludes.length; i++ )
122         {
123             String pattern;
124             pattern = excludes[i].trim().replace( '/', File.separatorChar ).replace( '\\', File.separatorChar );
125             if ( pattern.endsWith( File.separator ) )
126             {
127                 pattern += "**";
128             }
129             newExcludes[i] = pattern;
130         }
131         excludes = newExcludes;
132 
133         GpgSigner signer = newSigner( project );
134 
135         // ----------------------------------------------------------------------------
136         // What we need to generateSignatureForArtifact here
137         // ----------------------------------------------------------------------------
138 
139         signer.setOutputDirectory( ascDirectory );
140         signer.setBuildDirectory( new File( project.getBuild().getDirectory() ) );
141         signer.setBaseDirectory( project.getBasedir() );
142 
143         List signingBundles = new ArrayList();
144 
145         if ( !"pom".equals( project.getPackaging() ) )
146         {
147             // ----------------------------------------------------------------------------
148             // Project artifact
149             // ----------------------------------------------------------------------------
150 
151             File projectArtifact = project.getArtifact().getFile();
152 
153             if ( projectArtifact == null )
154             {
155                 throw new MojoFailureException( "The project artifact has not been assembled yet. "
156                     + "Please do not invoke this goal before the lifecycle phase \"package\"." );
157             }
158 
159             File projectArtifactSignature = signer.generateSignatureForArtifact( projectArtifact );
160 
161             if ( projectArtifactSignature != null )
162             {
163                 signingBundles.add( new SigningBundle( project.getArtifact().getType(), projectArtifactSignature ) );
164             }
165         }
166 
167         // ----------------------------------------------------------------------------
168         // POM
169         // ----------------------------------------------------------------------------
170 
171         File pomToSign = new File( project.getBuild().getDirectory(), project.getBuild().getFinalName() + ".pom" );
172 
173         try
174         {
175             FileUtils.copyFile( project.getFile(), pomToSign );
176         }
177         catch ( IOException e )
178         {
179             throw new MojoExecutionException( "Error copying POM for signing.", e );
180         }
181 
182         File pomSignature = signer.generateSignatureForArtifact( pomToSign );
183 
184         if ( pomSignature != null )
185         {
186             signingBundles.add( new SigningBundle( "pom", pomSignature ) );
187         }
188 
189         // ----------------------------------------------------------------------------
190         // Attached artifacts
191         // ----------------------------------------------------------------------------
192 
193         for ( Iterator i = project.getAttachedArtifacts().iterator(); i.hasNext(); )
194         {
195             Artifact artifact = (Artifact) i.next();
196 
197             File file = artifact.getFile();
198 
199             File signature = signer.generateSignatureForArtifact( file );
200 
201             if ( signature != null )
202             {
203                 signingBundles.add( new SigningBundle( artifact.getType(), artifact.getClassifier(), signature ) );
204             }
205         }
206 
207         // ----------------------------------------------------------------------------
208         // Attach all the signatures
209         // ----------------------------------------------------------------------------
210 
211         ArtifactHandler handler = new DefaultArtifactHandler( "asc" );
212 
213         Map map = new HashMap();
214 
215         map.put( "asc", handler );
216 
217         artifactHandlerManager.addHandlers( map );
218 
219         for ( Iterator i = signingBundles.iterator(); i.hasNext(); )
220         {
221             SigningBundle bundle = (SigningBundle) i.next();
222 
223             ArtifactHandler ah = artifactHandlerManager.getArtifactHandler( bundle.getArtifactType() );
224 
225             if ( bundle.getClassifier() != null && !"".equals( bundle.getClassifier() ) )
226             {
227                 projectHelper.attachArtifact( project, "asc", bundle.getClassifier() + "." + ah.getExtension(),
228                                               bundle.getSignature() );
229             }
230             else
231             {
232                 projectHelper.attachArtifact( project, ah.getExtension() + ".asc", null, bundle.getSignature() );
233             }
234         }
235     }
236 
237     /**
238      * Tests whether or not a name matches against at least one exclude pattern.
239      * 
240      * @param name The name to match. Must not be <code>null</code>.
241      * @return <code>true</code> when the name matches against at least one exclude pattern, or <code>false</code>
242      *         otherwise.
243      */
244     protected boolean isExcluded( String name )
245     {
246         for ( int i = 0; i < excludes.length; i++ )
247         {
248             if ( SelectorUtils.matchPath( excludes[i], name ) )
249             {
250                 return true;
251             }
252         }
253         return false;
254     }
255 
256 }