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.List;
26  
27  import org.apache.maven.artifact.Artifact;
28  import org.apache.maven.plugin.MojoExecutionException;
29  import org.apache.maven.plugin.MojoFailureException;
30  import org.apache.maven.plugins.annotations.Component;
31  import org.apache.maven.plugins.annotations.LifecyclePhase;
32  import org.apache.maven.plugins.annotations.Mojo;
33  import org.apache.maven.plugins.annotations.Parameter;
34  import org.apache.maven.project.MavenProject;
35  import org.apache.maven.project.MavenProjectHelper;
36  import org.codehaus.plexus.util.FileUtils;
37  import org.codehaus.plexus.util.SelectorUtils;
38  
39  /**
40   * Sign project artifact, the POM, and attached artifacts with GnuPG for deployment.
41   * 
42   * @author Jason van Zyl
43   * @author Jason Dillon
44   * @author Daniel Kulp
45   */
46  @Mojo( name = "sign", defaultPhase = LifecyclePhase.VERIFY, threadSafe = true )
47  public class GpgSignAttachedMojo
48      extends AbstractGpgMojo
49  {
50  
51      private static final String DEFAULT_EXCLUDES[] = new String[]{ "**/*.md5", "**/*.sha1", "**/*.asc" };
52  
53      /**
54       * Skip doing the gpg signing.
55       */
56      @Parameter( property = "gpg.skip", defaultValue = "false" )
57      private boolean skip;
58  
59      /**
60       * A list of files to exclude from being signed. Can contain Ant-style wildcards and double wildcards. The default
61       * excludes are <code>**&#47;*.md5   **&#47;*.sha1    **&#47;*.asc</code>.
62       *
63       * @since 1.0-alpha-4
64       */
65      @Parameter
66      private String[] excludes;
67  
68      /**
69       * The directory where to store signature files.
70       *
71       * @since 1.0-alpha-4
72       */
73      @Parameter( defaultValue = "${project.build.directory}/gpg", alias = "outputDirectory" )
74      private File ascDirectory;
75  
76      /**
77       * The maven project.
78       */
79      @Component
80      protected MavenProject project;
81  
82      /**
83       * Maven ProjectHelper
84       */
85      @Component
86      private MavenProjectHelper projectHelper;
87  
88      public void execute()
89          throws MojoExecutionException, MojoFailureException
90      {
91          if ( skip )
92          {
93              // We're skipping the signing stuff
94              return;
95          }
96  
97          if ( excludes == null || excludes.length == 0 )
98          {
99              excludes = DEFAULT_EXCLUDES;
100         }
101         String newExcludes[] = new String[excludes.length];
102         for ( int i = 0; i < excludes.length; i++ )
103         {
104             String pattern;
105             pattern = excludes[i].trim().replace( '/', File.separatorChar ).replace( '\\', File.separatorChar );
106             if ( pattern.endsWith( File.separator ) )
107             {
108                 pattern += "**";
109             }
110             newExcludes[i] = pattern;
111         }
112         excludes = newExcludes;
113 
114         AbstractGpgSigner signer = newSigner( project );
115 
116         // ----------------------------------------------------------------------------
117         // What we need to generateSignatureForArtifact here
118         // ----------------------------------------------------------------------------
119 
120         signer.setOutputDirectory( ascDirectory );
121         signer.setBuildDirectory( new File( project.getBuild().getDirectory() ) );
122         signer.setBaseDirectory( project.getBasedir() );
123 
124         List signingBundles = new ArrayList();
125 
126         if ( !"pom".equals( project.getPackaging() ) )
127         {
128             // ----------------------------------------------------------------------------
129             // Project artifact
130             // ----------------------------------------------------------------------------
131 
132             Artifact artifact = project.getArtifact();
133 
134             File file = artifact.getFile();
135 
136             if ( file != null && file.isFile() )
137             {
138                 getLog().debug( "Generating signature for " + file );
139 
140                 File projectArtifactSignature = signer.generateSignatureForArtifact( file );
141 
142                 if ( projectArtifactSignature != null )
143                 {
144                     signingBundles.add( new SigningBundle( artifact.getArtifactHandler().getExtension(),
145                                                            projectArtifactSignature ) );
146                 }
147             }
148             else if ( project.getAttachedArtifacts().isEmpty() )
149             {
150                 throw new MojoFailureException( "The project artifact has not been assembled yet. "
151                     + "Please do not invoke this goal before the lifecycle phase \"package\"." );
152             }
153             else
154             {
155                 getLog().debug( "Main artifact not assembled, skipping signature generation" );
156             }
157         }
158 
159         // ----------------------------------------------------------------------------
160         // POM
161         // ----------------------------------------------------------------------------
162 
163         File pomToSign = new File( project.getBuild().getDirectory(), project.getBuild().getFinalName() + ".pom" );
164 
165         try
166         {
167             FileUtils.copyFile( project.getFile(), pomToSign );
168         }
169         catch ( IOException e )
170         {
171             throw new MojoExecutionException( "Error copying POM for signing.", e );
172         }
173 
174         getLog().debug( "Generating signature for " + pomToSign );
175 
176         File pomSignature = signer.generateSignatureForArtifact( pomToSign );
177 
178         if ( pomSignature != null )
179         {
180             signingBundles.add( new SigningBundle( "pom", pomSignature ) );
181         }
182 
183         // ----------------------------------------------------------------------------
184         // Attached artifacts
185         // ----------------------------------------------------------------------------
186 
187         for (Object o : project.getAttachedArtifacts()) {
188             Artifact artifact = (Artifact) o;
189 
190             File file = artifact.getFile();
191 
192             getLog().debug("Generating signature for " + file);
193 
194             File signature = signer.generateSignatureForArtifact(file);
195 
196             if (signature != null) {
197                 signingBundles.add(new SigningBundle(artifact.getArtifactHandler().getExtension(),
198                         artifact.getClassifier(), signature));
199             }
200         }
201 
202         // ----------------------------------------------------------------------------
203         // Attach all the signatures
204         // ----------------------------------------------------------------------------
205 
206         for (Object signingBundle : signingBundles) {
207             SigningBundle bundle = (SigningBundle) signingBundle;
208 
209             projectHelper.attachArtifact(project, bundle.getExtension() + GpgSigner.SIGNATURE_EXTENSION,
210                     bundle.getClassifier(), bundle.getSignature());
211         }
212     }
213 
214     /**
215      * Tests whether or not a name matches against at least one exclude pattern.
216      * 
217      * @param name The name to match. Must not be <code>null</code>.
218      * @return <code>true</code> when the name matches against at least one exclude pattern, or <code>false</code>
219      *         otherwise.
220      */
221     protected boolean isExcluded( String name )
222     {
223         for (String exclude : excludes) {
224             if (SelectorUtils.matchPath(exclude, name)) {
225                 return true;
226             }
227         }
228         return false;
229     }
230 
231 }