View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugins.gpg;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.util.List;
24  
25  import org.apache.maven.plugin.MojoExecutionException;
26  import org.apache.maven.plugin.logging.Log;
27  import org.apache.maven.project.MavenProject;
28  
29  /**
30   * A base class for all classes that implements signing of files.
31   *
32   * @author Dennis Lundberg
33   * @since 1.5
34   */
35  public abstract class AbstractGpgSigner {
36      private static final String GPG_PASSPHRASE = "gpg.passphrase";
37  
38      public static final String SIGNATURE_EXTENSION = ".asc";
39  
40      protected boolean useAgent;
41  
42      protected boolean isInteractive = true;
43  
44      protected boolean defaultKeyring = true;
45  
46      protected String keyname;
47  
48      private Log log;
49  
50      protected String passphrase;
51  
52      private File outputDir;
53  
54      private File buildDir;
55  
56      private File baseDir;
57  
58      protected File homeDir;
59  
60      protected String secretKeyring;
61  
62      protected String publicKeyring;
63  
64      protected String lockMode;
65  
66      protected List<String> args;
67  
68      public Log getLog() {
69          return log;
70      }
71  
72      public void setArgs(List<String> args) {
73          this.args = args;
74      }
75  
76      public void setInteractive(boolean b) {
77          isInteractive = b;
78      }
79  
80      public void setLockMode(String lockMode) {
81          this.lockMode = lockMode;
82      }
83  
84      public void setUseAgent(boolean b) {
85          useAgent = b;
86      }
87  
88      public void setDefaultKeyring(boolean enabled) {
89          defaultKeyring = enabled;
90      }
91  
92      public void setKeyName(String s) {
93          keyname = s;
94      }
95  
96      public void setLog(Log log) {
97          this.log = log;
98      }
99  
100     public void setPassPhrase(String s) {
101         passphrase = s;
102     }
103 
104     public void setOutputDirectory(File out) {
105         outputDir = out;
106     }
107 
108     public void setBuildDirectory(File out) {
109         buildDir = out;
110     }
111 
112     public void setBaseDirectory(File out) {
113         baseDir = out;
114     }
115 
116     public void setHomeDirectory(File homeDirectory) {
117         homeDir = homeDirectory;
118     }
119 
120     public void setSecretKeyring(String path) {
121         secretKeyring = path;
122     }
123 
124     public void setPublicKeyring(String path) {
125         publicKeyring = path;
126     }
127 
128     /**
129      * Create a detached signature file for the provided file.
130      *
131      * @param file The file to sign
132      * @return A reference to the generated signature file
133      * @throws MojoExecutionException if signature generation fails
134      */
135     public File generateSignatureForArtifact(File file) throws MojoExecutionException {
136         // ----------------------------------------------------------------------------
137         // Set up the file and directory for the signature file
138         // ----------------------------------------------------------------------------
139 
140         File signature = new File(file + SIGNATURE_EXTENSION);
141 
142         boolean isInBuildDir = false;
143         if (buildDir != null) {
144             File parent = signature.getParentFile();
145             if (buildDir.equals(parent)) {
146                 isInBuildDir = true;
147             }
148         }
149         if (!isInBuildDir && outputDir != null) {
150             String fileDirectory = "";
151             File signatureDirectory = signature;
152 
153             while ((signatureDirectory = signatureDirectory.getParentFile()) != null) {
154                 if (isPossibleRootOfArtifact(signatureDirectory)) {
155                     break;
156                 }
157                 fileDirectory = signatureDirectory.getName() + File.separatorChar + fileDirectory;
158             }
159             signatureDirectory = new File(outputDir, fileDirectory);
160             if (!signatureDirectory.exists()) {
161                 signatureDirectory.mkdirs();
162             }
163             signature = new File(signatureDirectory, file.getName() + SIGNATURE_EXTENSION);
164         }
165 
166         if (signature.exists()) {
167             signature.delete();
168         }
169 
170         // ----------------------------------------------------------------------------
171         // Generate the signature file
172         // ----------------------------------------------------------------------------
173 
174         generateSignatureForFile(file, signature);
175 
176         return signature;
177     }
178 
179     /**
180      * Generate the detached signature file for the provided file.
181      *
182      * @param file The file to sign
183      * @param signature The file in which the generate signature will be put
184      * @throws MojoExecutionException if signature generation fails
185      */
186     protected abstract void generateSignatureForFile(File file, File signature) throws MojoExecutionException;
187 
188     private MavenProject findReactorProject(MavenProject prj) {
189         if (prj.getParent() != null
190                 && prj.getParent().getBasedir() != null
191                 && prj.getParent().getBasedir().exists()) {
192             return findReactorProject(prj.getParent());
193         }
194         return prj;
195     }
196 
197     public String getPassphrase(MavenProject project) throws IOException {
198         String pass = null;
199 
200         if (project != null) {
201             pass = project.getProperties().getProperty(GPG_PASSPHRASE);
202             if (pass == null) {
203                 MavenProject prj2 = findReactorProject(project);
204                 pass = prj2.getProperties().getProperty(GPG_PASSPHRASE);
205             }
206         }
207         if (pass == null) {
208             pass = new String(readPassword("GPG Passphrase: "));
209         }
210         if (project != null) {
211             findReactorProject(project).getProperties().setProperty(GPG_PASSPHRASE, pass);
212         }
213         return pass;
214     }
215 
216     private char[] readPassword(String prompt) throws IOException {
217         return System.console().readPassword();
218     }
219 
220     private boolean isPossibleRootOfArtifact(File signatureDirectory) {
221         return signatureDirectory.equals(outputDir)
222                 || signatureDirectory.equals(buildDir)
223                 || signatureDirectory.equals(baseDir);
224     }
225 }