View Javadoc

1    /*
2     * This is free software; you can redistribute it and/or modify it
3     * under the terms of the GNU Lesser General Public License as
4     * published by the Free Software Foundation; either version 2.1 of
5     * the License, or (at your option) any later version.
6     *
7     * This software is distributed in the hope that it will be useful,
8     * but WITHOUT ANY WARRANTY; without even the implied warranty of
9     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10    * Lesser General Public License for more details.
11    *
12    * You should have received a copy of the GNU Lesser General Public
13    * License along with this software; if not, write to the Free
14    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
15    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
16    */
17  
18  package installtoolkit;
19  
20  import installtoolkit.deb.CommandType;
21  import installtoolkit.deb.DebhelperTask;
22  import installtoolkit.deb.DebhelperType;
23  import installtoolkit.deb.LinkType;
24  import installtoolkit.deb.StartmenueLinksTask;
25  
26  import java.io.File;
27  import java.io.FileWriter;
28  import java.io.IOException;
29  import java.io.PrintWriter;
30  import java.text.SimpleDateFormat;
31  import java.util.ArrayList;
32  import java.util.Date;
33  import java.util.List;
34  import java.util.Locale;
35  
36  import org.apache.tools.ant.DirectoryScanner;
37  import org.apache.tools.ant.taskdefs.Copy;
38  import org.apache.tools.ant.taskdefs.Delete;
39  import org.apache.tools.ant.types.FileSet;
40  import org.apache.tools.ant.types.selectors.FilenameSelector;
41  import org.dom4j.Element;
42  
43  
44  
45  public class DebianPackageTask extends InstallerGeneratorTask {
46  
47  	protected File control;
48  	protected File changelog;
49  	protected File copyright;
50  	protected File conffiles;
51  	protected int compatlevel = 5;
52  	protected String desktopdir = "/usr/share/applications";
53  	protected String architecture = null;
54  	
55  	protected List<DebhelperType> debhelper = new ArrayList<DebhelperType>();	
56  	protected List<CommandType> commands = new ArrayList<CommandType>();	
57  
58  	protected List<Pattern> configfiles;
59  	protected String section = "contrib/misc";
60  	protected String priority = "optional";
61  	protected String depends = "";
62  	protected String recommends = "";
63  	protected String suggests = "";
64  	protected List<LinkType> startmenue = new ArrayList<LinkType>();
65  	
66  	
67  	// -- [ Task execution ] -------------------------------------------
68  	
69  	/**
70  	 * @see InstallerGeneratorTask#build()
71  	 */
72  	@Override
73  	protected void build() throws Exception {
74  
75  		if (debug) handleOutput("Starting build()");
76  		
77  		File debian = new File( this.workdir, "debian");		
78  		
79  		handleOutput("create Dir: "+debian.getAbsolutePath());
80  		debian.mkdirs();
81  		
82  		generateControl(debian);
83  		generateCompat(debian);
84  		generateChangelog(debian);
85  		generateCopyright(debian);
86  		generateConffiles(debian);
87  		
88  		if (this.startmenue.size() > 0) {
89  			
90  			if (debug) handleOutput("generating Startmenue links ...");
91  			
92  			if (this.desktopdir.startsWith("/")); this.desktopdir = this.desktopdir.substring(1);
93  			File links_dir = new File(this.workdir,this.desktopdir);
94  
95  			if (debug) handleOutput("Directory for Startmenue Links: "+links_dir.getAbsolutePath());
96  
97  			StartmenueLinksTask links = new StartmenueLinksTask();
98  			links.setProject(this.getProject());
99  			links.setTaskName("StartmenueLinks");
100 			links.setDebug(this.debug);
101 			links.setPackagename(this.packageName);
102 			links.setDestdir(links_dir);
103 			
104 			for (LinkType link : this.startmenue) links.addLink(link);
105 			
106 			links.execute();
107 		}
108 
109 
110 		handleOutput("Create Dir: "+this.workdir+"/debian/tmp");
111 		File tmp = new File(this.workdir,"debian/tmp");		
112 		tmp.mkdirs();
113 
114 		if (debug) handleOutput("Clening up Temp Directory "+this.workdir+"/debian/tmp");			
115 
116 		FileSet del_fileset = new FileSet();
117 		del_fileset.setDir(tmp);
118 
119 		Delete del = new Delete(); 
120 		del.setProject(getProject());
121 		del.setTaskName("delete");
122 		del.setVerbose(this.debug);
123 		del.addFileset(del_fileset);
124 		del.execute();
125 		
126 		if (debug) handleOutput("Copy Files to "+this.workdir+"/debian/tmp");			
127 		
128 		FilenameSelector copy_include = new FilenameSelector();
129 		copy_include.setName("**");
130 
131 		FilenameSelector copy_exclude = new FilenameSelector();
132 		copy_exclude.setName("debian/**");
133 		copy_exclude.setNegate(true);
134 				
135 		FileSet copy_fileset = new FileSet();
136 		copy_fileset.setDir(this.workdir);
137 		copy_fileset.add(copy_include);
138 		copy_fileset.add(copy_exclude);
139 		
140 		Copy copy_task = new Copy();
141 		copy_task.setProject(getProject());
142 		copy_task.setTaskName("copy");
143 		copy_task.setVerbose(this.debug);
144 		copy_task.setOverwrite(true);
145 		copy_task.setTodir(tmp);
146 		copy_task.addFileset(copy_fileset);
147 		copy_task.execute();		
148 		
149 		
150 		DebhelperTask debhelper = new DebhelperTask();
151 		debhelper.setProject(this.getProject());
152 		debhelper.setTaskName("debhelper");
153 		debhelper.setDebug(this.debug);
154 		debhelper.setSrcdir(this.workdir);
155 		debhelper.setDestdir(this.destdir);
156 		debhelper.setArchitecture(this.architecture);
157 		
158 		debhelper.addDh(new DebhelperType("dh_testdir"));
159 		debhelper.addDh(new DebhelperType("dh_testroot"));
160 		debhelper.addDh(new DebhelperType("dh_installdirs"));
161 		debhelper.addDh(new DebhelperType("dh_installchangelogs"));
162 		debhelper.addDh(new DebhelperType("dh_installdocs"));
163 		debhelper.addDh(new DebhelperType("dh_compress"));
164 		debhelper.addDh(new DebhelperType("dh_fixperms"));
165 		debhelper.addDh(new DebhelperType("dh_installdeb"));
166 		debhelper.addDh(new DebhelperType("dh_gencontrol"));
167 		debhelper.addDh(new DebhelperType("dh_md5sums"));
168 		
169 		for (DebhelperType dh : this.debhelper) {
170 			
171 			debhelper.addDh(dh);
172 		}
173 		
174 		for (CommandType cmd : this.commands) {
175 			
176 			debhelper.addCommand(cmd);
177 		}
178 		
179 		
180 		debhelper.execute();
181 		
182 		if (debug) handleOutput("build() finished");
183 
184 	}
185 
186 	/**
187 	 * Generate control file
188 	 * 
189 	 * @param debian The directory to create the file
190 	 * @throws IOException
191 	 */
192 	private void generateControl(File debian) throws IOException {
193 		
194 		File file = new File(debian, "control");
195 		
196 		if (this.control != null) {
197 		
198 			copy(this.control,file);
199 			return;
200 		}
201 		
202 		file.delete();
203 		file.createNewFile();
204 
205 		handleOutput("generating File: "+file.getName());
206 		
207 		PrintWriter w = new PrintWriter(new FileWriter(file));
208 		
209 		w.println("Source: "+this.packageName.toLowerCase());
210 		w.println("Section: "+this.section);
211 		w.println("Priority: "+this.priority);
212 		w.println("Maintainer: "+this.manufacturer+" <"+this.email+">");
213 		w.println();
214 		w.println("Package: "+this.packageName.toLowerCase());
215 		
216 		if (this.architecture != null)
217 			w.println("Architecture: "+this.architecture);
218 		else
219 			w.println("Architecture: all");
220 			
221 		w.println("Depends: "+this.depends);				
222 		w.println("Recommends: "+this.recommends);				
223 		w.println("Suggests: "+this.suggests);				
224 		w.println("Description: "+this.shortDescription);
225 
226 		for (String line : this.longDescription) {
227 			
228 			w.print(" ");
229 			w.println(line);
230 
231 		}
232 				
233 		w.println();
234 
235 		w.flush();
236 		w.close();
237 
238 	}
239 
240 	
241 	/**
242 	 * Generate changelog file
243 	 * 
244 	 * @param debian The directory to create the file
245 	 * @throws IOException
246 	 */
247 	private void generateChangelog(File debian) throws IOException {
248 		
249 		File file = new File(debian, "changelog");
250 		
251 		if (this.changelog != null) {
252 			
253 			copy(this.changelog,file);
254 			return;
255 		}
256 		
257 		file.delete();
258 		file.createNewFile();
259 		
260 		handleOutput("generating File: "+file.getName());
261 
262 		SimpleDateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z",Locale.US);
263 		
264 		PrintWriter w = new PrintWriter(new FileWriter(file));
265 						
266 		w.println(this.packageName.toLowerCase()+" ("+this.version+") unstable; urgency=low");
267 		w.println();
268 		w.println("  * Autogenerated Package");
269 		w.println();
270 		w.println(" -- "+this.manufacturer+" <"+this.email+">  "+df.format(new Date()));
271 		w.println();
272 
273 		w.flush();
274 		w.close();
275 
276 	}
277 	
278 	
279 	/**
280 	 * Generate copyright file
281 	 * 
282 	 * @param debian The directory to create the file
283 	 * @throws IOException
284 	 */
285 	private void generateCopyright(File debian) throws IOException {
286 		
287 		File file = new File(debian, "copyright");
288 				
289 		if (this.copyright != null) {
290 			
291 			copy(this.copyright,file);
292 			return;
293 		}
294 		
295 		file.delete();
296 		file.createNewFile();
297 
298 		handleOutput("generating File: "+file.getName());
299 
300 		PrintWriter w = new PrintWriter(new FileWriter(file));
301 						
302 		w.println();
303 		
304 		for (String line : this.license) w.println(line);
305 
306 		w.println();
307 		w.flush();
308 		w.close();
309 
310 	}
311 
312 	
313 	/**
314 	 * Generate compat file
315 	 * 
316 	 * @param debian The directory to create the file
317 	 * @throws IOException
318 	 */
319 	private void generateCompat(File debian) throws IOException {
320 		
321 		File file = new File(debian, "compat");
322 		file.delete();
323 		file.createNewFile();
324 
325 		handleOutput("generating File: "+file.getName());
326 
327 		PrintWriter w = new PrintWriter(new FileWriter(file));
328 						
329 		w.println(this.compatlevel);	// debhelper compatibility mode
330 
331 		w.flush();
332 		w.close();
333 
334 	}
335 
336 	/**
337 	 * Generate conffiles file
338 	 * 
339 	 * @param debian The directory to create the file
340 	 * @throws IOException
341 	 */
342 	private void generateConffiles(File debian) throws IOException {
343 		
344 		File file = new File(debian, "conffiles");
345 		
346 		if (this.conffiles != null) {
347 			
348 			copy(this.conffiles,file);
349 			return;
350 		}
351 		
352 		file.delete();
353 		file.createNewFile();
354 
355 		int workDirPathLength = this.workdir.getAbsolutePath().length();
356 		if (debug) handleOutput("WorkDir ["+this.workdir.getAbsolutePath()+"] -> Length: "+workDirPathLength);
357 		
358 		handleOutput("generating File: "+file.getName());
359 
360 		PrintWriter w = new PrintWriter(new FileWriter(file));
361 			
362 		FileSet configs = this.createFilesetFromPatterns(this.configfiles,this.workdir);
363 		
364 		// exclude the debian directory
365 		FilenameSelector debian_exclude = new FilenameSelector();
366 		debian_exclude.setName("debian/**");
367 		debian_exclude.setNegate(true);
368 		configs.add(debian_exclude);
369 		
370 		DirectoryScanner ds = configs.getDirectoryScanner(this.getProject());
371 		
372 		for (String cfilename : ds.getIncludedFiles()) {
373 			
374 			File cfile = new File(this.workdir,cfilename);			
375 			String cpath = cfile.getAbsolutePath().substring(workDirPathLength);
376 			w.println(cpath);
377 			
378 			if (debug) handleOutput("Config File: "+cpath+ "  <- Substring("+workDirPathLength+") of "+cfile.getAbsolutePath());
379 		}
380 
381 		w.flush();
382 		w.close();
383 		
384 	} // generateConffiles()
385 	
386 	
387 	//	 -- [ Decriptor file reading ] -------------------------------------------
388 	
389 	@Override
390 	public void readDebTag(Element root) {
391 		
392 
393 		this.section = root.attributeValue("Section",this.section);
394 	    if (debug) handleOutput("Section: "+this.section);
395 
396 		this.priority = root.attributeValue("Priority",this.priority);
397 	    if (debug) handleOutput("Priority: "+this.priority);
398 		
399 		for (Object obj : root.elements()) {
400 
401 			Element element = (Element) obj;
402 									
403 			if (element.getName() == "Configfiles") {
404 				
405 				if (debug) handleOutput("Reading Tag: Configfiles ...");
406 				this.configfiles = readPatterns(element);
407 			}
408 
409 			if (element.getName() == "Depends") {
410 
411 				this.depends = element.getText() + "";
412 			    if (debug) handleOutput("Depends: "+this.depends);
413 			}
414 						
415 			if (element.getName() == "Recommends") {
416 
417 				this.recommends = element.getText() + "";
418 			    if (debug) handleOutput("Recomments: "+this.recommends);
419 			}
420 						
421 			if (element.getName() == "Suggests") {
422 
423 				this.suggests = element.getText() + "";
424 			    if (debug) handleOutput("Suggests: "+this.suggests);
425 			}
426 			
427 			if (element.getName() == "Startmenue") {
428 				
429 				if (debug) handleOutput("reading Startmenue Tag ...");
430 				
431 				LinkType link = new LinkType(element);
432 				
433 				this.startmenue.add(link);
434 				if (debug) handleOutput(link.toString());
435 				
436 			}
437 												
438 		} // for
439 		
440 	} // readDebTag()
441 
442 	
443 	//	 -- [ Getter/Setter ] -------------------------------------------
444 	
445 	/**
446 	 * Additional debhelper scripts to execute
447 	 */
448 	public void addDebhelper(DebhelperType dh) {	
449 		this.debhelper.add(dh);
450 	}
451 
452 	/**
453 	 * Additional commands to execute
454 	 */
455 	public void addCommand(CommandType cmd) {	
456 		this.commands.add(cmd);
457 	}
458 
459 	/**
460 	 * Alternative changelog file
461 	 */
462 	public void setChangelog(File changelog) {
463 		this.changelog = changelog;
464 	}
465 
466 	/**
467 	 * Alternative debhelper cpmpatibility level
468 	 */
469 	public void setCompatlevel(int compatlevel) {
470 		this.compatlevel = compatlevel;
471 	}
472 
473 	/**
474 	 * Alternative conffiles file
475 	 */
476 	public void setConffiles(File conffiles) {
477 		this.conffiles = conffiles;
478 	}
479 
480 	/**
481 	 * Alternative control file
482 	 */
483 	public void setControl(File control) {
484 		this.control = control;
485 	}
486 
487 	/**
488 	 * Alternative copyright file 
489 	 */
490 	public void setCopyright(File copyright) {
491 		this.copyright = copyright;
492 	}
493 
494 	/**
495 	 * The Architecture to build the package for
496 	 */
497 	public void setArchitecture(String architecture) {
498 		this.architecture = architecture;
499 	}
500 	
501 
502 }