1 package org.apache.maven.plugin.gpg;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.BufferedReader;
23 import java.io.ByteArrayInputStream;
24 import java.io.File;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28
29 import org.apache.maven.plugin.MojoExecutionException;
30 import org.apache.maven.project.MavenProject;
31 import org.codehaus.plexus.util.Os;
32 import org.codehaus.plexus.util.cli.CommandLineException;
33 import org.codehaus.plexus.util.cli.CommandLineUtils;
34 import org.codehaus.plexus.util.cli.Commandline;
35 import org.codehaus.plexus.util.cli.DefaultConsumer;
36
37 public class GpgSigner
38 {
39
40 public static final String SIGNATURE_EXTENSION = ".asc";
41
42 private boolean useAgent;
43
44 private boolean isInteractive = true;
45
46 private String keyname;
47
48 private String passphrase;
49
50 private File outputDir;
51
52 private File buildDir;
53
54 private File baseDir;
55
56 private File homeDir;
57
58 public void setInteractive( boolean b )
59 {
60 isInteractive = b;
61 }
62
63 public void setUseAgent( boolean b )
64 {
65 useAgent = b;
66 }
67
68 public void setKeyName( String s )
69 {
70 keyname = s;
71 }
72
73 public void setPassPhrase( String s )
74 {
75 passphrase = s;
76 }
77
78 public void setOutputDirectory( File out )
79 {
80 outputDir = out;
81 }
82
83 public void setBuildDirectory( File out )
84 {
85 buildDir = out;
86 }
87
88 public void setBaseDirectory( File out )
89 {
90 baseDir = out;
91 }
92
93 public void setHomeDirectory( File homeDirectory )
94 {
95 homeDir = homeDirectory;
96 }
97
98 public File generateSignatureForArtifact( File file )
99 throws MojoExecutionException
100 {
101 File signature = new File( file + SIGNATURE_EXTENSION );
102
103 boolean isInBuildDir = false;
104 if ( buildDir != null )
105 {
106 File parent = signature.getParentFile();
107 if ( buildDir.equals( parent ) )
108 {
109 isInBuildDir = true;
110 }
111 }
112 if ( !isInBuildDir && outputDir != null )
113 {
114 String fileDirectory = "";
115 File signatureDirectory = signature;
116
117 while ( ( signatureDirectory = signatureDirectory.getParentFile() ) != null )
118 {
119 if ( !signatureDirectory.equals( baseDir ) )
120 {
121 fileDirectory = signatureDirectory.getName() + File.separatorChar + fileDirectory;
122 }
123 else
124 {
125 break;
126 }
127 }
128 signatureDirectory = new File( outputDir, fileDirectory );
129 if ( !signatureDirectory.exists() )
130 {
131 signatureDirectory.mkdirs();
132 }
133 signature = new File( signatureDirectory, file.getName() + SIGNATURE_EXTENSION );
134 }
135
136 if ( signature.exists() )
137 {
138 signature.delete();
139 }
140
141 Commandline cmd = new Commandline();
142
143 cmd.setExecutable( "gpg" + ( Os.isFamily( Os.FAMILY_WINDOWS ) ? ".exe" : "" ) );
144
145 if ( homeDir != null )
146 {
147 cmd.createArg().setValue( "--homedir" );
148 cmd.createArg().setFile( homeDir );
149 }
150
151 if ( useAgent )
152 {
153 cmd.createArg().setValue( "--use-agent" );
154 }
155 else
156 {
157 cmd.createArg().setValue( "--no-use-agent" );
158 }
159
160 InputStream in = null;
161 if ( null != passphrase )
162 {
163 cmd.createArg().setValue( "--passphrase-fd" );
164
165 cmd.createArg().setValue( "0" );
166
167
168 in = new ByteArrayInputStream( passphrase.getBytes() );
169 }
170
171 if ( null != keyname )
172 {
173 cmd.createArg().setValue( "--local-user" );
174
175 cmd.createArg().setValue( keyname );
176 }
177
178 cmd.createArg().setValue( "--armor" );
179
180 cmd.createArg().setValue( "--detach-sign" );
181
182 if ( !isInteractive )
183 {
184 cmd.createArg().setValue( "--no-tty" );
185 }
186
187 cmd.createArg().setValue( "--output" );
188 cmd.createArg().setFile( signature );
189
190 cmd.createArg().setFile( file );
191
192 try
193 {
194 int exitCode = CommandLineUtils.executeCommandLine( cmd, in, new DefaultConsumer(), new DefaultConsumer() );
195
196 if ( exitCode != 0 )
197 {
198 throw new MojoExecutionException( "Exit code: " + exitCode );
199 }
200 }
201 catch ( CommandLineException e )
202 {
203 throw new MojoExecutionException( "Unable to execute gpg command", e );
204 }
205
206 return signature;
207 }
208
209 private MavenProject findReactorProject( MavenProject prj )
210 {
211 if ( prj.getParent() != null )
212 {
213 if ( prj.getParent().getBasedir() != null && prj.getParent().getBasedir().exists() )
214 {
215 return findReactorProject( prj.getParent() );
216 }
217 }
218 return prj;
219 }
220
221 public String getPassphrase( MavenProject project )
222 throws IOException
223 {
224 String pass = null;
225
226 if ( project != null )
227 {
228 pass = project.getProperties().getProperty( "gpg.passphrase" );
229 if ( pass == null )
230 {
231 MavenProject prj2 = findReactorProject( project );
232 pass = prj2.getProperties().getProperty( "gpg.passphrase" );
233 }
234 }
235 if ( pass == null )
236 {
237
238
239 BufferedReader in = new BufferedReader( new InputStreamReader( System.in ) );
240 while ( System.in.available() != 0 )
241 {
242
243
244 System.in.read();
245 }
246
247 System.out.print( "GPG Passphrase: " );
248 MaskingThread thread = new MaskingThread();
249 thread.start();
250
251 pass = in.readLine();
252
253
254 thread.stopMasking();
255 }
256 if ( project != null )
257 {
258 findReactorProject( project ).getProperties().setProperty( "gpg.passphrase", pass );
259 }
260 return pass;
261 }
262
263
264 class MaskingThread
265 extends Thread
266 {
267 private volatile boolean stop;
268
269
270
271
272 public void run()
273 {
274
275
276
277 int priority = Thread.currentThread().getPriority();
278 Thread.currentThread().setPriority( Thread.MAX_PRIORITY );
279
280 try
281 {
282 stop = false;
283 while ( !stop )
284 {
285
286 System.out.print( "\010*" );
287 try
288 {
289
290 Thread.sleep( 1 );
291 }
292 catch ( InterruptedException iex )
293 {
294 Thread.currentThread().interrupt();
295 return;
296 }
297 }
298 }
299 finally
300 {
301
302 Thread.currentThread().setPriority( priority );
303 }
304 }
305
306
307
308
309 public void stopMasking()
310 {
311 this.stop = true;
312 }
313 }
314
315 }