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.maven;
17  
18  import java.io.File;
19  import java.io.FileInputStream;
20  import java.io.FileOutputStream;
21  import java.text.ParseException;
22  import java.util.HashMap;
23  import java.util.Map;
24  
25  import org.apache.maven.plugin.MojoExecutionException;
26  import org.apache.maven.project.MavenProjectHelper;
27  import org.apache.tools.tar.TarEntry;
28  import org.vafer.jdeb.Console;
29  import org.vafer.jdeb.DataConsumer;
30  import org.vafer.jdeb.DataProducer;
31  import org.vafer.jdeb.Processor;
32  import org.vafer.jdeb.changes.TextfileChangesProvider;
33  import org.vafer.jdeb.descriptors.PackageDescriptor;
34  import org.vafer.jdeb.utils.MapVariableResolver;
35  import org.vafer.jdeb.utils.Utils;
36  import org.vafer.jdeb.utils.VariableResolver;
37  
38  /**
39   * Creates deb archive
40   *
41   * @goal deb
42   * @requiresDependencyResolution compile
43   * @execute phase="package"
44   */
45  public final class DebMojo extends AbstractPluginMojo {
46  
47  	/**
48       * @component
49       */
50      private MavenProjectHelper projectHelper;
51  
52      /**
53       * Defines the pattern of the name of final artifacts.
54       * Possible substitutions are [[artifactId]] [[version]] [[extension]] and [[groupId]].
55       * 
56       * @parameter expression="${namePattern}" default-value="[[artifactId]]_[[version]].[[extension]]"
57       */
58      private String namePattern;
59  
60      /**
61       * Explicitly defines the final artifact name (without using the pattern) 
62       * 
63       * @parameter expression="${deb}"
64       */    
65      private File deb;
66      
67      /**
68       * Explicitly defines the path to the control directory. At least the control file is mandatory. 
69       * 
70       * @parameter expression="${controlDir}"
71       */    
72      private File controlDir;
73      
74      /**
75       * Explicitly define the file to read the changes from. 
76       * 
77       * @parameter expression="${changesIn}"
78       */    
79      private File changesIn = null;
80  
81      /**
82       * Explicitly define the file where to write the changes to. 
83       * 
84       * @parameter expression="${changesIn}"
85       */    
86      private File changesOut = null;
87  
88      /**
89       * Explicitly define the file where to write the changes of the changes input to. 
90       * 
91       * @parameter expression="${changesSave}"
92       */    
93      private File changesSave = null;
94      
95      /**
96       * The keyring file. Usually some/path/secring.gpg
97       * 
98       * @parameter expression="${keyring}"
99       */    	
100     private File keyring = null;
101 
102     /**
103      * The hex key id to use for signing. 
104      * 
105      * @parameter expression="${key}"
106      */    	
107 	private String key = null;
108 
109     /**
110      * The passphrase for the key to sign the changes file. 
111      * 
112      * @parameter expression="${passhrase}"
113      */    	
114 	private String passphrase = null;
115     
116     /**
117      * If not defaultPath is specified this  
118      * 
119      * @parameter expression="${defaultPath}" default-value="/srv/jetty/www"
120      */    	
121 	private String defaultPath = "/srv/jetty/www";
122 
123 	/**
124 	 * TODO: make configurable
125 	 */
126 	private DataProducer[] dataProducers = null;
127 	
128 	
129 	/**
130      * Main entry point
131      * @throws MojoExecutionException on error
132      */
133     public void execute()
134         throws MojoExecutionException
135     {
136     	// expand name pattern
137     	final String debName;
138     	final String changesName;    	
139 
140     	final Map variables = new HashMap();
141     	variables.put("name", getProject().getName());
142     	variables.put("artifactId", getProject().getArtifactId());
143     	variables.put("groupId", getProject().getGroupId());
144     	variables.put("version", getProject().getVersion().replace('-', '+'));
145     	variables.put("description", getProject().getDescription());
146     	variables.put("extension", "deb");    	
147     	final VariableResolver resolver = new MapVariableResolver(variables);
148 
149     	try
150     	{
151         	debName = Utils.replaceVariables(resolver, namePattern, "[[", "]]"); 
152         	
153         	variables.put("extension", "changes");    	
154         	changesName = Utils.replaceVariables(resolver, namePattern, "[[", "]]"); 
155 		}
156     	catch (ParseException e)
157     	{
158 			throw new MojoExecutionException("Failed parsing artifact name pattern", e);
159 		}
160 
161     	// if not specified try to the default
162     	if (deb == null)
163     	{
164 			deb = new File(buildDirectory, debName);
165     	}
166 
167     	// if not specified try to the default
168     	if (changesIn == null)
169     	{
170     		final File f = new File(getProject().getBasedir(), "CHANGES.txt");
171     		if (f.exists() && f.isFile() && f.canRead())
172     		{
173     			changesIn = f;
174     		}
175     	}
176     	
177     	// if not specified try to the default
178     	if (changesOut == null)
179     	{
180 			changesOut = new File(buildDirectory, changesName);
181     	}
182     	
183     	// if not specified try to the default
184     	if (controlDir == null)
185     	{
186     		controlDir = new File(getProject().getBasedir(), "src/deb/control");
187     		getLog().info("Using default path to control directory " + controlDir);
188     	}
189     	
190     	// make sure we have at least the mandatory control directory
191     	if (!controlDir.exists() || !controlDir.isDirectory())
192     	{
193     		throw new MojoExecutionException(controlDir + " needs to be a directory");
194     	}
195     	
196     	// make sure we have at least the mandatory control file
197     	final File controlFile = new File(controlDir, "control");
198     	if (!controlFile.exists() || !controlFile.isFile() || !controlFile.canRead())
199     	{
200     		throw new MojoExecutionException(controlFile + " is mandatory");
201     	}
202     	
203     	final File file = getProject().getArtifact().getFile();
204 		final File[] controlFiles = controlDir.listFiles();
205 		
206 		
207 		if (dataProducers == null)
208 		{
209 			dataProducers = new DataProducer[] { new DataProducer() {
210 			public void produce( final DataConsumer receiver ) {
211 				try {
212 					receiver.onEachFile(new FileInputStream(file), new File(new File(defaultPath), file.getName()).getAbsolutePath(), "", "root", 0, "root", 0, TarEntry.DEFAULT_FILE_MODE, file.length());
213 				} catch (Exception e) {
214 					getLog().error(e);
215 				}
216 			}}};
217 		}
218 
219 		
220 		final Processor processor = new Processor(
221 				new Console()
222 				{
223 					public void println( final String s )
224 					{
225 						getLog().info(s);
226 					}			
227 				},
228 				resolver
229 		);
230 		
231 		final PackageDescriptor packageDescriptor;
232 		try
233 		{
234 
235 			packageDescriptor = processor.createDeb(controlFiles, dataProducers, deb, "gzip");
236 
237 			getLog().info("Attaching created debian archive " + deb);
238 			projectHelper.attachArtifact( getProject(), "deb-archive", deb.getName(), deb );
239 		}
240 		catch (Exception e)
241 		{
242 			getLog().error("Failed to create debian package " + deb, e);
243 			throw new MojoExecutionException("Failed to create debian package " + deb, e);
244 		}    	
245 
246 		if (changesIn == null)
247 		{
248 			return;
249 		}
250 		
251 		
252 		final TextfileChangesProvider changesProvider;
253 		
254 		try
255 		{
256 
257 			// for now only support reading the changes form a text file provider
258 			changesProvider = new TextfileChangesProvider(new FileInputStream(changesIn), packageDescriptor);
259 			
260 			processor.createChanges(packageDescriptor, changesProvider, (keyring!=null)?new FileInputStream(keyring):null, key, passphrase, new FileOutputStream(changesOut));
261 
262 			getLog().info("Attaching created debian changes file " + changesOut);
263 			projectHelper.attachArtifact( getProject(), "deb-changes", changesOut.getName(), changesOut );
264 		}
265 		catch (Exception e)
266 		{
267 			getLog().error("Failed to create debian changes file " + changesOut, e);
268 			throw new MojoExecutionException("Failed to create debian changes file " + changesOut, e);
269 		}    	
270 
271     
272 		try {
273 			if (changesSave == null) {
274 				return;
275 			}
276 
277 			changesProvider.save(new FileOutputStream(changesSave));
278 
279 			getLog().info("Saved release information to file " + changesSave);
280 			
281 		} catch (Exception e) {
282 			getLog().error("Failed to save release information to file " + changesSave);
283 			throw new MojoExecutionException("Failed to save release information to file " + changesSave, e);
284 		}    
285     }    
286 
287 }