View Javadoc

1   /*
2    * Copyright 2005 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.vafer.jdeb.ant;
17  
18  import java.io.File;
19  import java.io.FileInputStream;
20  import java.io.FileOutputStream;
21  import java.util.ArrayList;
22  import java.util.Collection;
23  
24  import org.apache.tools.ant.BuildException;
25  import org.apache.tools.ant.taskdefs.MatchingTask;
26  import org.apache.tools.ant.taskdefs.Tar;
27  import org.apache.tools.ant.types.FileSet;
28  import org.vafer.jdeb.Console;
29  import org.vafer.jdeb.DataProducer;
30  import org.vafer.jdeb.Processor;
31  import org.vafer.jdeb.changes.TextfileChangesProvider;
32  import org.vafer.jdeb.descriptors.PackageDescriptor;
33  import org.vafer.jdeb.producers.FileSetDataProducer;
34  
35  /**
36   * AntTask for creating debian archives.
37   * Even supports signed changes files.
38   * 
39   * @author Torsten Curdt <tcurdt@vafer.org>
40   */
41  		
42  public class DebAntTask extends MatchingTask {
43  
44  	/** The Debian package produced */
45  	private File deb;
46  
47  	/** The directory containing the control files to build the package */
48  	private File control;
49  
50  	/** The file containing the PGP keys */
51  	private File keyring;
52  
53  	/** The key to use in the keyring */
54  	private String key;
55  
56  	/** The passphrase for the key to sign the changes file */
57  	private String passphrase;
58  
59  	/** The file to read the changes from */
60  	private File changesIn;
61  
62  	/** The file where to write the changes to */
63  	private File changesOut;
64  
65  	/** The file where to write the changes of the changes input to */
66  	private File changesSave;
67  
68  	/** The compression method used for the data file (none, gzip or bzip2) */
69  	private String compression = "gzip";
70  
71  	/** Trigger the verbose mode detailing all operations */
72  	private boolean verbose;
73  
74  	private Collection dataProducers = new ArrayList();
75  
76  
77  	public void setDestfile( File deb ) {
78      	this.deb = deb;
79      }
80      
81      public void setControl( File control ) {
82      	this.control = control;
83      }
84  
85      public void setChangesIn( File changes ) {
86      	this.changesIn = changes;
87      }
88  
89      public void setChangesOut( File changes ) {
90      	this.changesOut = changes;
91      }
92  
93      public void setChangesSave( File changes ) {
94      	this.changesSave = changes;
95      }
96  
97      public void setKeyring( File keyring ) {
98      	this.keyring = keyring;
99      }
100 
101     public void setKey( String key ) {
102     	this.key = key;
103     }
104     
105     public void setPassphrase( String passphrase ) {
106     	this.passphrase = passphrase;
107     }
108 
109 	public void setCompression(String compression) {
110 		this.compression = compression;
111 	}
112 
113 	public void setVerbose(boolean verbose) {
114 		this.verbose = verbose;
115 	}
116 
117 	public void addFileSet(FileSet fileset) {
118 		dataProducers.add(new FileSetDataProducer(fileset));
119 	}
120 
121 	public void addTarFileSet(Tar.TarFileSet fileset) {
122 		dataProducers.add(new FileSetDataProducer(fileset));
123 	}
124 
125 	public void addData( Data data ) {
126     	dataProducers.add(data);
127     }
128     
129     private boolean isPossibleOutput( File file ) {
130 
131     	if (file.exists()) {
132     		return file.isFile() && file.canWrite();
133     	}
134 
135     	return true;
136     }
137     
138 	public void execute() {
139 		
140 		if (control == null || !control.isDirectory()) {
141 			throw new BuildException("You need to point the 'control' attribute to the control directory.");
142 		}
143 
144 		if (changesIn != null) {
145 			
146 			if (!changesIn.isFile() || !changesIn.canRead()) {
147 				throw new BuildException("The 'changesIn' attribute needs to point to a readable file. " + changesIn + " was not found/readable.");				
148 			}
149 
150 			if (changesOut == null) {
151 				throw new BuildException("A 'changesIn' without a 'changesOut' does not make much sense.");
152 			}
153 			
154 			if (!isPossibleOutput(changesOut)) {
155 				throw new BuildException("Cannot write the output for 'changesOut' to " + changesOut);				
156 			}
157 
158 			if (changesSave != null && !isPossibleOutput(changesSave)) {
159 				throw new BuildException("Cannot write the output for 'changesSave' to " + changesSave);				
160 			}
161 			
162 		} else {
163 			if (changesOut != null || changesSave != null) {
164 				throw new BuildException("The 'changesOut' or 'changesSave' attributes may only be used when there is a 'changesIn' specified.");							
165 			}
166 		}
167 
168 		if (!"gzip".equals(compression) && !"bzip2".equals(compression) && !"none".equals(compression)) {
169 			throw new BuildException("The compression method '" + compression + "' is not supported");
170 		}
171 				
172 		if (dataProducers.size() == 0) {
173 			throw new BuildException("You need to provide at least one reference to a tgz or directory with data.");
174 		}
175 
176 		if (deb == null) {
177 			throw new BuildException("You need to point the 'destfile' attribute to where the deb is supposed to be created.");
178 		}
179 		
180 		final File[] controlFiles = control.listFiles();
181 		
182 		final DataProducer[] data = new DataProducer[dataProducers.size()];
183 		dataProducers.toArray(data);
184 		
185 		final Processor processor = new Processor(new Console() {
186 			public void println(String s) {
187 				if (verbose) {
188 					log(s);
189 				}
190 			}
191 		}, null);
192 		
193 		final PackageDescriptor packageDescriptor;
194 		try {
195 			
196 			log("Creating debian package: " + deb);
197 			
198 			packageDescriptor = processor.createDeb(controlFiles, data, deb, compression);
199 
200 		} catch (Exception e) {
201 			throw new BuildException("Failed to create debian package " + deb, e);
202 		}
203 
204 		final TextfileChangesProvider changesProvider;
205 		
206 		try {
207 			if (changesOut == null) {
208 				return;
209 			}
210 
211 			log("Creating changes file: " + changesOut);
212 
213 			// for now only support reading the changes form a textfile provider
214 			changesProvider = new TextfileChangesProvider(new FileInputStream(changesIn), packageDescriptor);
215 			
216 			processor.createChanges(packageDescriptor, changesProvider, (keyring!=null)?new FileInputStream(keyring):null, key, passphrase, new FileOutputStream(changesOut));
217 						
218 		} catch (Exception e) {
219 			throw new BuildException("Failed to create debian changes file " + changesOut, e);
220 		}
221 
222 		try {
223 			if (changesSave == null) {
224 				return;
225 			}
226 
227 			log("Saving changes to file: " + changesSave);
228 
229 			changesProvider.save(new FileOutputStream(changesSave));
230 			
231 		} catch (Exception e) {
232 			throw new BuildException("Failed to save debian changes file " + changesSave, e);
233 		}
234 				
235 	}
236 }