1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.openpgp.ant;
18
19 import org.apache.tools.ant.Task;
20 import org.apache.tools.ant.BuildException;
21 import org.apache.tools.ant.DirectoryScanner;
22 import org.apache.tools.ant.util.FileNameMapper;
23 import org.apache.tools.ant.util.GlobPatternMapper;
24 import org.apache.tools.ant.util.FileUtils;
25 import org.apache.tools.ant.types.FileSet;
26 import org.apache.tools.ant.types.Mapper;
27 import org.apache.commons.openpgp.*;
28 import org.bouncycastle.openpgp.PGPException;
29
30 import java.io.*;
31 import java.util.Collection;
32 import java.util.ArrayList;
33 import java.util.Iterator;
34
35
36
37 public class OpenPgpSignerTask extends Task {
38 private File secring;
39 private File pubring;
40 private String password;
41 private String keyId;
42 private Collection<FileSet> tosign = new ArrayList<FileSet>();
43 private File artefact;
44 private boolean asciiarmor = true;
45 private Mapper mapperElement;
46
47
48
49
50
51 public void setSecring(File secring) {
52 this.secring = secring;
53 }
54
55
56
57
58
59 public void setPubring(File pubring) {
60 this.pubring = pubring;
61 }
62
63
64
65
66
67 public void setKeyId(String keyId) {
68 this.keyId = keyId;
69 }
70
71
72
73
74
75 public void setAsciiarmor(boolean asciiarmor) {
76 this.asciiarmor = asciiarmor;
77 }
78
79
80
81
82
83 public void setPassword(String password) {
84 this.password = password;
85 }
86
87
88
89
90
91 public void setArtefact(File artefact) {
92 this.artefact = artefact;
93 }
94
95
96 public void add(FileSet fs) {
97 tosign.add(fs);
98 }
99
100
101
102
103
104
105 public Mapper createMapper() throws BuildException {
106 if (mapperElement != null) {
107 throw new BuildException("Cannot define more than one mapper",
108 getLocation());
109 }
110 mapperElement = new Mapper(getProject());
111 return mapperElement;
112 }
113
114 public void execute() {
115 if (secring == null) {
116 throw new BuildException("secring attribute compulsory");
117 }
118 if (pubring == null) {
119 throw new BuildException("pubring attribute compulsory");
120 }
121 if (password == null) {
122 throw new BuildException("password attribute compulsory");
123 }
124 if (tosign.size() == 0 && artefact == null) {
125 throw new BuildException("supply the attribute 'artefact' or one nested fileset");
126 }
127 if (!secring.exists() || !secring.canRead()) {
128 throw new BuildException("secret keyring file '" + secring.getAbsolutePath() + "' does not exist or is not readable");
129 }
130 if (!pubring.exists() || !pubring.canRead()) {
131 throw new BuildException("public keyring file '" + pubring.getAbsolutePath() + "' does not exist or is not readable");
132 }
133 FileInputStream secStream;
134 FileInputStream pubStream;
135 KeyRing keyRing = null;
136 try {
137 secStream = new FileInputStream(secring);
138 pubStream = new FileInputStream(pubring);
139 keyRing = new BouncyCastleKeyRing(secStream,
140 pubStream, password.toCharArray() );
141 } catch (IOException ioe) {
142 throw new BuildException(ioe);
143 } catch (PGPException pgpe) {
144 throw new BuildException(pgpe);
145 }
146 if (artefact != null) {
147 dosign(keyRing, artefact);
148 }
149 if (tosign.size() != 0) {
150 for (FileSet fileset : tosign) {
151 dosign(keyRing, fileset);
152 }
153 }
154 FileUtils.close(secStream);
155 FileUtils.close(pubStream);
156 }
157 private void dosign(KeyRing keyRing, FileSet fs) {
158 DirectoryScanner ds = fs.getDirectoryScanner(getProject());
159 String[] artefacts = ds.getIncludedFiles();
160 for (String artefact : artefacts) {
161 dosign(keyRing, new File(fs.getDir(getProject()), artefact), fs.getDir(getProject()), artefact);
162 }
163 }
164 private void dosign(KeyRing keyRing, File oneartefact) {
165 dosign(keyRing, oneartefact, oneartefact.getParentFile(), oneartefact.getName());
166 }
167 private void dosign(KeyRing keyRing, File oneartefact, File basedir, String relpath) {
168 FileInputStream fis = null;
169 FileOutputStream fos = null;
170 File signature;
171
172 try {
173 fis = new FileInputStream(oneartefact);
174 FileNameMapper mapper = getMapper();
175 String [] mappedFiles = mapper.mapFileName(relpath);
176 if (mappedFiles == null || mappedFiles.length != 1) {
177 throw new BuildException("mapper returned more or less than one output");
178 }
179 signature = new File(basedir, mappedFiles[0]);
180 fos = new FileOutputStream(signature);
181 OpenPgpSigner signer = new BouncyCastleOpenPgpSigner();
182 signer.detachedSign(fis, fos, keyId, keyRing, asciiarmor);
183 } catch (FileNotFoundException fnfe) {
184 throw new BuildException(fnfe);
185 } catch (IOException ioe) {
186 throw new BuildException(ioe);
187 } catch (OpenPgpException opgpe) {
188 throw new BuildException(opgpe);
189 }
190 FileUtils.close(fos);
191 FileUtils.close(fis);
192
193 }
194
195
196
197 private FileNameMapper getMapper() {
198 FileNameMapper mapper = null;
199 if (mapperElement != null) {
200 mapper = mapperElement.getImplementation();
201 } else {
202 mapper = new GlobPatternMapper();
203 mapper.setFrom("*");
204 if (asciiarmor) {
205 mapper.setTo("*.asc");
206 } else {
207 mapper.setTo("*.sig");
208 }
209 }
210 return mapper;
211 }
212
213 }