001 /*
002 * Copyright 2005 The Apache Software Foundation.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.vafer.jdeb.maven;
017
018 import java.io.File;
019 import java.io.FileInputStream;
020 import java.io.FileOutputStream;
021 import java.text.ParseException;
022 import java.util.HashMap;
023 import java.util.Map;
024
025 import org.apache.maven.plugin.MojoExecutionException;
026 import org.apache.maven.project.MavenProjectHelper;
027 import org.apache.tools.tar.TarEntry;
028 import org.vafer.jdeb.Console;
029 import org.vafer.jdeb.DataConsumer;
030 import org.vafer.jdeb.DataProducer;
031 import org.vafer.jdeb.Processor;
032 import org.vafer.jdeb.changes.TextfileChangesProvider;
033 import org.vafer.jdeb.descriptors.PackageDescriptor;
034 import org.vafer.jdeb.utils.MapVariableResolver;
035 import org.vafer.jdeb.utils.Utils;
036 import org.vafer.jdeb.utils.VariableResolver;
037
038 /**
039 * Creates deb archive
040 *
041 * @goal deb
042 * @requiresDependencyResolution compile
043 * @execute phase="package"
044 */
045 public final class DebMojo extends AbstractPluginMojo {
046
047 /**
048 * @component
049 */
050 private MavenProjectHelper projectHelper;
051
052 /**
053 * Defines the pattern of the name of final artifacts.
054 * Possible substitutions are [[artifactId]] [[version]] [[extension]] and [[groupId]].
055 *
056 * @parameter expression="${namePattern}" default-value="[[artifactId]]_[[version]].[[extension]]"
057 */
058 private String namePattern;
059
060 /**
061 * Explicitly defines the final artifact name (without using the pattern)
062 *
063 * @parameter expression="${deb}"
064 */
065 private File deb;
066
067 /**
068 * Explicitly defines the path to the control directory. At least the control file is mandatory.
069 *
070 * @parameter expression="${controlDir}"
071 */
072 private File controlDir;
073
074 /**
075 * Explicitly define the file to read the changes from.
076 *
077 * @parameter expression="${changesIn}"
078 */
079 private File changesIn = null;
080
081 /**
082 * Explicitly define the file where to write the changes to.
083 *
084 * @parameter expression="${changesIn}"
085 */
086 private File changesOut = null;
087
088 /**
089 * Explicitly define the file where to write the changes of the changes input to.
090 *
091 * @parameter expression="${changesSave}"
092 */
093 private File changesSave = null;
094
095 /**
096 * The keyring file. Usually some/path/secring.gpg
097 *
098 * @parameter expression="${keyring}"
099 */
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 }