diff --git a/docs/maven.md b/docs/maven.md
index 0b8eab1fc..b7a1b97a7 100644
--- a/docs/maven.md
+++ b/docs/maven.md
@@ -103,19 +103,19 @@ tarball archive, or a file. You can add as many data
elements to your dataSet as you'd like. The `data` element has the
following options:
-Element | Description | Required
----------------- | ---------------------------------------------------------------------------- | ------------------------------------
-src | The directory, tarball, file to include in the package | Yes
-dst | New filename at destination (type must be `file`) | No
-linkName | The path of the link (type must be `link`) | Yes for link
-linkTarget | The target of the link (type must be `link`) | Yes for link
-type | Type of the data source. (archive, directory, file, link or template) | No; but will be Yes in the future
-missingSrc | Fail if src file/folder is missing (ignore or fail) | No; defaults to `fail`
-includes | A comma seperated list of files to include from the directory or tarball | No; defaults to all files
-excludes | A comma seperated list of files to exclude from the directory or tarball | No; defaults to no exclutions
-conffile | A boolean value to define if the files should be included in the conffiles | No; defaults to `false`
-mapper | The files to exclude from the directory or tarball | No
-paths/(path..) | One or more string literal paths that will created in the package | No; Yes for type `template`
+Element | Description | Required
+---------------- | ------------------------------------------------------------------------------- | ------------------------------------
+src | The directory, tarball, file, man-page to include in the package | Yes
+dst | New filename at destination (type must be `file` or `man-page`) | No
+linkName | The path of the link (type must be `link`) | Yes for link
+linkTarget | The target of the link (type must be `link`) | Yes for link
+type | Type of the data source. (archive, directory, file, link, man-page or template) | No; but will be Yes in the future
+missingSrc | Fail if src file/folder is missing (ignore or fail) | No; defaults to `fail`
+includes | A comma seperated list of files to include from the directory or tarball | No; defaults to all files
+excludes | A comma seperated list of files to exclude from the directory or tarball | No; defaults to no exclutions
+conffile | A boolean value to define if the files should be included in the conffiles | No; defaults to `false`
+mapper | The files to exclude from the directory or tarball | No
+paths/(path..) | One or more string literal paths that will created in the package | No; Yes for type `template`
There are different kinds of mappers that can be selected via the `type` argument. The most common one is the 'perm' mapper.
@@ -218,6 +218,12 @@ include a directory, a tarball, and a file in your deb package and then sign it
true
+
+
+ man-page
+ /a/path/to/manpage.1
+
+
${project.build.directory}/data
@@ -241,6 +247,7 @@ include a directory, a tarball, and a file in your deb package and then sign it
```
If you don't want to store your key information in the POM you can store this is your settings.xml, here's an example settings.xml:
+```xml
@@ -256,5 +263,6 @@ If you don't want to store your key information in the POM you can store this is
jdeb-signing
+```
keyring, key and passphrase can then be omitted from the POM entirely.
diff --git a/src/main/java/org/vafer/jdeb/ant/Data.java b/src/main/java/org/vafer/jdeb/ant/Data.java
index 78756af2b..f80e2ab10 100644
--- a/src/main/java/org/vafer/jdeb/ant/Data.java
+++ b/src/main/java/org/vafer/jdeb/ant/Data.java
@@ -22,12 +22,11 @@
import java.util.Collection;
import java.util.Iterator;
+import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.PatternSet;
import org.vafer.jdeb.DataConsumer;
import org.vafer.jdeb.DataProducer;
-import org.vafer.jdeb.producers.DataProducerArchive;
-import org.vafer.jdeb.producers.DataProducerDirectory;
-import org.vafer.jdeb.producers.DataProducerFile;
+import org.vafer.jdeb.producers.*;
/**
* Ant "data" element acting as a factory for DataProducers.
@@ -82,36 +81,44 @@ public void produce( final DataConsumer pReceiver ) throws IOException {
throw new FileNotFoundException("Data source not found : " + src);
}
- org.vafer.jdeb.mapping.Mapper[] mappers = new org.vafer.jdeb.mapping.Mapper[mapperWrapper.size()];
+ final org.vafer.jdeb.mapping.Mapper[] mappers = new org.vafer.jdeb.mapping.Mapper[mapperWrapper.size()];
final Iterator it = mapperWrapper.iterator();
for (int i = 0; i < mappers.length; i++) {
mappers[i] = it.next().createMapper();
}
- if ("file".equalsIgnoreCase(type)) {
- new DataProducerFile(
- src,
- destinationName,
- getIncludePatterns(getProject()),
- getExcludePatterns(getProject()),
- mappers
- ).produce(pReceiver);
-
- } else if ("archive".equalsIgnoreCase(type)) {
- new DataProducerArchive(
- src,
- getIncludePatterns(getProject()),
- getExcludePatterns(getProject()),
- mappers
- ).produce(pReceiver);
-
- } else if ("directory".equalsIgnoreCase(type)) {
- new DataProducerDirectory(
- src,
- getIncludePatterns(getProject()),
- getExcludePatterns(getProject()),
- mappers
- ).produce(pReceiver);
+ final Project project = getProject();
+
+ ProducerFactory.KnownType knownType = ProducerFactory.KnownType.forString(type);
+
+ if (knownType == null) {
+ return;
}
+
+ final DataProducer p = ProducerFactory.create(knownType, new ProducerFactory.Params() {
+ @Override
+ public File getSource() {
+ return src;
+ }
+ @Override
+ public String getDestination() {
+ return destinationName;
+ }
+ @Override
+ public String[] getIncludePatterns() {
+ return Data.this.getIncludePatterns(project);
+ }
+
+ @Override
+ public String[] getExcludePatterns() {
+ return Data.this.getExcludePatterns(project);
+ }
+
+ @Override
+ public org.vafer.jdeb.mapping.Mapper[] getMappers() {
+ return mappers;
+ }
+ });
+ p.produce(pReceiver);
}
}
diff --git a/src/main/java/org/vafer/jdeb/maven/Data.java b/src/main/java/org/vafer/jdeb/maven/Data.java
index a8e13f191..7b3e8f92a 100644
--- a/src/main/java/org/vafer/jdeb/maven/Data.java
+++ b/src/main/java/org/vafer/jdeb/maven/Data.java
@@ -26,11 +26,7 @@
import org.apache.maven.plugins.annotations.Parameter;
import org.vafer.jdeb.DataConsumer;
import org.vafer.jdeb.DataProducer;
-import org.vafer.jdeb.producers.DataProducerArchive;
-import org.vafer.jdeb.producers.DataProducerDirectory;
-import org.vafer.jdeb.producers.DataProducerFile;
-import org.vafer.jdeb.producers.DataProducerLink;
-import org.vafer.jdeb.producers.DataProducerPathTemplate;
+import org.vafer.jdeb.producers.*;
import static org.vafer.jdeb.maven.MissingSourceBehavior.*;
@@ -148,62 +144,84 @@ public String[] splitPatterns( String patterns ) {
}
public void produce( final DataConsumer pReceiver ) throws IOException {
- org.vafer.jdeb.mapping.Mapper[] mappers = null;
- if (mapper != null) {
- mappers = new org.vafer.jdeb.mapping.Mapper[] { mapper.createMapper() };
- }
+ final org.vafer.jdeb.mapping.Mapper[] mappers =
+ mapper == null
+ ? null
+ : new org.vafer.jdeb.mapping.Mapper[] { mapper.createMapper() };
- // link type
+ ProducerFactory.KnownType knownType = ProducerFactory.KnownType.forString(type);
- if ("link".equalsIgnoreCase(type)) {
- if (linkName == null) {
- throw new RuntimeException("linkName is not set");
- }
- if (linkTarget == null) {
- throw new RuntimeException("linkTarget is not set");
- }
+ if (knownType == null) {
+ throw new IOException(buildUnknownTypeMessage(type, src));
+ }
- new DataProducerLink(linkName, linkTarget, symlink, includePatterns, excludePatterns, mappers).produce(pReceiver);
- return;
+ if (knownType.requiresSource() && (src == null || !src.exists())) {
+ if (IGNORE == missingSrc) {
+ return;
+ }
+ throw new FileNotFoundException("Data source not found : " + src);
}
- // template type
+ final DataProducer p = ProducerFactory.create(knownType, new ProducerFactory.Params() {
+ @Override
+ public File getSource() {
+ return src;
+ }
+ @Override
+ public String getDestination() {
+ return dst;
+ }
+ @Override
+ public String getLink() {
+ return linkName;
+ }
+ @Override
+ public String getLinkTarget() {
+ return linkTarget;
+ }
- if ("template".equalsIgnoreCase(type)) {
- if (paths == null || paths.length == 0) {
- throw new RuntimeException("paths is not set");
+ @Override
+ public boolean isSimlink() {
+ return symlink;
}
- new DataProducerPathTemplate(paths, includePatterns, excludePatterns, mappers).produce(pReceiver);
- return;
- }
+ @Override
+ public String[] getTemplatePaths() {
+ return paths;
+ }
- // Types that require src to exist
+ @Override
+ public String[] getIncludePatterns() {
+ return includePatterns;
+ }
- if (src == null || !src.exists()) {
- if (missingSrc == IGNORE) {
- return;
- } else {
- throw new FileNotFoundException("Data source not found : " + src);
+ @Override
+ public String[] getExcludePatterns() {
+ return excludePatterns;
}
- }
- if ("file".equalsIgnoreCase(type)) {
- new DataProducerFile(src, dst, includePatterns, excludePatterns, mappers).produce(pReceiver);
- return;
- }
+ @Override
+ public org.vafer.jdeb.mapping.Mapper[] getMappers() {
+ return mappers;
+ }
+ });
- if ("archive".equalsIgnoreCase(type)) {
- new DataProducerArchive(src, includePatterns, excludePatterns, mappers).produce(pReceiver);
- return;
- }
+ p.produce(pReceiver);
+ }
- if ("directory".equalsIgnoreCase(type)) {
- new DataProducerDirectory(src, includePatterns, excludePatterns, mappers).produce(pReceiver);
- return;
+ private static String buildUnknownTypeMessage( final String type,
+ final File src ) {
+ final StringBuilder b = new StringBuilder("Unknown type '");
+ b.append(type).append("' (");
+ for (ProducerFactory.KnownType t : ProducerFactory.KnownType.values()) {
+ if (t.ordinal() != 0) {
+ b.append("|");
+ }
+ b.append(t.shortName());
}
+ b.append(") for ").append(src);
+ return b.toString();
- throw new IOException("Unknown type '" + type + "' (file|directory|archive|template|link) for " + src);
}
}
diff --git a/src/main/java/org/vafer/jdeb/producers/AbstractDataProducer.java b/src/main/java/org/vafer/jdeb/producers/AbstractDataProducer.java
index 47d87646a..386972cd8 100644
--- a/src/main/java/org/vafer/jdeb/producers/AbstractDataProducer.java
+++ b/src/main/java/org/vafer/jdeb/producers/AbstractDataProducer.java
@@ -27,6 +27,9 @@
*/
public abstract class AbstractDataProducer implements DataProducer {
+ protected final static int ROOT_UID = 0;
+ protected final static String ROOT_NAME = "root";
+
private final String[] includes;
private final String[] excludes;
private final Mapper[] mappers;
diff --git a/src/main/java/org/vafer/jdeb/producers/DataProducerDirectory.java b/src/main/java/org/vafer/jdeb/producers/DataProducerDirectory.java
index 70eff71e2..2f82f5cd2 100644
--- a/src/main/java/org/vafer/jdeb/producers/DataProducerDirectory.java
+++ b/src/main/java/org/vafer/jdeb/producers/DataProducerDirectory.java
@@ -18,7 +18,6 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
-import java.io.InputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.tools.ant.DirectoryScanner;
@@ -72,12 +71,7 @@ public void produce( final DataConsumer pReceiver ) throws IOException {
dirname += "/";
}
- TarArchiveEntry entry = new TarArchiveEntry(dirname, true);
- entry.setUserId(0);
- entry.setUserName("root");
- entry.setGroupId(0);
- entry.setGroupName("root");
- entry.setMode(TarArchiveEntry.DEFAULT_DIR_MODE);
+ TarArchiveEntry entry = Producers.defaultDirEntryWithName(dirname);
entry = map(entry);
@@ -99,23 +93,13 @@ public void produce( final DataConsumer pReceiver ) throws IOException {
filename = filename.replace(File.separatorChar, '/');
}
- TarArchiveEntry entry = new TarArchiveEntry(filename, true);
- entry.setUserId(0);
- entry.setUserName("root");
- entry.setGroupId(0);
- entry.setGroupName("root");
- entry.setMode(TarArchiveEntry.DEFAULT_FILE_MODE);
+ TarArchiveEntry entry = Producers.defaultFileEntryWithName(filename);
entry = map(entry);
entry.setSize(file.length());
- final InputStream inputStream = new FileInputStream(file);
- try {
- pReceiver.onEachFile(inputStream, entry.getName(), entry.getLinkName(), entry.getUserName(), entry.getUserId(), entry.getGroupName(), entry.getGroupId(), entry.getMode(), entry.getSize());
- } finally {
- inputStream.close();
- }
+ Producers.produceInputStreamWithEntry(pReceiver, new FileInputStream(file), entry);
}
}
diff --git a/src/main/java/org/vafer/jdeb/producers/DataProducerFile.java b/src/main/java/org/vafer/jdeb/producers/DataProducerFile.java
index 455f81153..ee94a7227 100644
--- a/src/main/java/org/vafer/jdeb/producers/DataProducerFile.java
+++ b/src/main/java/org/vafer/jdeb/producers/DataProducerFile.java
@@ -18,7 +18,6 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
-import java.io.InputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.vafer.jdeb.DataConsumer;
@@ -51,23 +50,13 @@ public void produce( final DataConsumer pReceiver ) throws IOException {
fileName = file.getName();
}
- TarArchiveEntry entry = new TarArchiveEntry(fileName, true);
- entry.setUserId(0);
- entry.setUserName("root");
- entry.setGroupId(0);
- entry.setGroupName("root");
- entry.setMode(TarArchiveEntry.DEFAULT_FILE_MODE);
+ TarArchiveEntry entry = Producers.defaultFileEntryWithName(fileName);
entry = map(entry);
entry.setSize(file.length());
- final InputStream inputStream = new FileInputStream(file);
- try {
- pReceiver.onEachFile(inputStream, entry.getName(), entry.getLinkName(), entry.getUserName(), entry.getUserId(), entry.getGroupName(), entry.getGroupId(), entry.getMode(), entry.getSize());
- } finally {
- inputStream.close();
- }
+ Producers.produceInputStreamWithEntry(pReceiver, new FileInputStream(file), entry);
}
}
diff --git a/src/main/java/org/vafer/jdeb/producers/DataProducerFileSet.java b/src/main/java/org/vafer/jdeb/producers/DataProducerFileSet.java
index b4eaf4de7..3f3ecd47a 100644
--- a/src/main/java/org/vafer/jdeb/producers/DataProducerFileSet.java
+++ b/src/main/java/org/vafer/jdeb/producers/DataProducerFileSet.java
@@ -42,10 +42,10 @@ public DataProducerFileSet( final FileSet fileset ) {
}
public void produce( final DataConsumer pReceiver ) throws IOException {
- String user = "root";
- int uid = 0;
- String group = "root";
- int gid = 0;
+ String user = Producers.ROOT_NAME;
+ int uid = Producers.ROOT_UID;
+ String group = Producers.ROOT_NAME;
+ int gid = Producers.ROOT_UID;
int filemode = TarEntry.DEFAULT_FILE_MODE;
int dirmode = TarEntry.DEFAULT_DIR_MODE;
String prefix = "";
diff --git a/src/main/java/org/vafer/jdeb/producers/DataProducerLink.java b/src/main/java/org/vafer/jdeb/producers/DataProducerLink.java
index 69c851f8e..185df01d7 100644
--- a/src/main/java/org/vafer/jdeb/producers/DataProducerLink.java
+++ b/src/main/java/org/vafer/jdeb/producers/DataProducerLink.java
@@ -46,10 +46,10 @@ public void produce( final DataConsumer pReceiver ) throws IOException {
TarArchiveEntry entry = new TarArchiveEntry(path, symlink ? TarArchiveEntry.LF_SYMLINK : TarArchiveEntry.LF_LINK);
entry.setLinkName(linkName);
- entry.setUserId(0);
- entry.setUserName("root");
- entry.setGroupId(0);
- entry.setGroupName("root");
+ entry.setUserId(ROOT_UID);
+ entry.setUserName(ROOT_NAME);
+ entry.setGroupId(ROOT_UID);
+ entry.setGroupName(ROOT_NAME);
entry.setMode(TarArchiveEntry.DEFAULT_FILE_MODE);
entry = map(entry);
diff --git a/src/main/java/org/vafer/jdeb/producers/DataProducerManPage.java b/src/main/java/org/vafer/jdeb/producers/DataProducerManPage.java
new file mode 100644
index 000000000..d5b31df71
--- /dev/null
+++ b/src/main/java/org/vafer/jdeb/producers/DataProducerManPage.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2013 The jdeb developers.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.vafer.jdeb.producers;
+
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.compressors.CompressorException;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
+import org.vafer.jdeb.Compression;
+import org.vafer.jdeb.DataConsumer;
+import org.vafer.jdeb.mapping.Mapper;
+import org.vafer.jdeb.utils.Utils;
+
+import java.io.*;
+import java.util.zip.Deflater;
+import java.util.zip.GZIPOutputStream;
+
+/**
+ * DataProducer representing a man page entry.
+ *
+ * Ensures that man page is compressed with appropriate compression level
+ * and is placed to correct location.
+ *
+ * @author Roman Kashitsyn
+ */
+public class DataProducerManPage extends AbstractDataProducer {
+
+ private final static int DEFAULT_CATEGORY = 1;
+ private final static int BAD_CATEGORY = -1;
+ private final static Compression COMPRESSOR = Compression.GZIP;
+ private final static String MAN_PAGE_PREFIX = "/usr/share/man/man";
+
+ final File file;
+
+ final String destination;
+
+ public DataProducerManPage( final File pFile,
+ String pDestinationName,
+ String[] pIncludes,
+ String[] pExcludes,
+ Mapper[] pMapper ) {
+ super(pIncludes, pExcludes, pMapper);
+ file = pFile;
+ destination = makeDestination(pDestinationName, pFile);
+ }
+
+ @Override
+ public void produce( final DataConsumer receiver ) throws IOException {
+
+ TarArchiveEntry entry = Producers.defaultFileEntryWithName(destination);
+
+ entry = map(entry);
+
+ if (isCompressedFile(FilenameUtils.getExtension(file.getName()))) {
+ entry.setSize(file.length());
+ Producers.produceInputStreamWithEntry(receiver, new FileInputStream(file), entry);
+ } else {
+ produceCompressedPage(receiver, entry);
+ }
+ }
+
+ private static boolean isCompressedFile( final String extension ) {
+
+ return Compression.toEnum(extension) != null;
+ }
+
+ private void produceCompressedPage( final DataConsumer receiver,
+ final TarArchiveEntry entry ) throws IOException {
+ try {
+ final byte[] pageBytes = getCompressedPageBytes();
+ entry.setSize(pageBytes.length);
+ Producers.produceInputStreamWithEntry(receiver, new ByteArrayInputStream(pageBytes), entry);
+ } catch (CompressorException e) {
+ throw new IOException(e);
+ }
+ }
+
+ private byte[] getCompressedPageBytes() throws IOException, CompressorException {
+ InputStream inputStream = null;
+ final ByteArrayOutputStream inMemoryOut = new ByteArrayOutputStream();
+ final OutputStream compressedOut = new GZIPOutputStream(inMemoryOut) {
+ {
+ def.setLevel(Deflater.BEST_COMPRESSION);
+ }
+ };
+
+ try {
+ inputStream = new BufferedInputStream(new FileInputStream(file));
+ Utils.copy(inputStream, compressedOut);
+ } finally {
+ IOUtils.closeQuietly(compressedOut);
+ IOUtils.closeQuietly(inputStream);
+ }
+
+ // Updating compression level to avoid the lintian
+ // `manpage-not-compressed-with-max-compression` error
+ return setBestCompressionFlag(inMemoryOut.toByteArray());
+ }
+
+ /**
+ * Sets XFLAG header field to BEST COMPRESSION.
+ * See http://www.gzip.org/zlib/rfc-gzip.html for details.
+ *
+ * @param bytes compressed file bytes, must be a valid GZIP file
+ * @return augmented file bytes
+ */
+ private static byte[] setBestCompressionFlag( final byte[] bytes ) {
+
+ final int XFLAG_HEADER_INDEX = 8;
+ final byte BEST_COMPRESSION_FLAG = 2;
+
+ bytes[XFLAG_HEADER_INDEX] = BEST_COMPRESSION_FLAG;
+ return bytes;
+ }
+
+ static String makeDestination( final String dest, final File file ) {
+ if (dest != null && dest.length() > 0) {
+ return dest;
+ }
+
+ String fileName = file.getName();
+ final String extension = FilenameUtils.getExtension(fileName);
+
+ if (isCompressedFile(extension)) {
+ final String fileNameWithoutSuffix = FilenameUtils.removeExtension(fileName);
+ final int category = extractCategory(fileNameWithoutSuffix);
+ fileName = addCategory(fileNameWithoutSuffix, extension, category);
+ } else {
+ final int category = extractCategory(fileName);
+ final String newExtension = COMPRESSOR.getExtension().substring(1);
+ fileName = addCategory(fileName, newExtension, category);
+ }
+
+ return fileName;
+ }
+
+ private static String addCategory( final String base,
+ final String extension,
+ final int category ) {
+ if (category == BAD_CATEGORY) {
+ return MAN_PAGE_PREFIX + DEFAULT_CATEGORY + "/" +
+ base + "." + DEFAULT_CATEGORY + "." + extension;
+ }
+ return MAN_PAGE_PREFIX + category + "/" + base + "." + extension;
+ }
+
+ private static int extractCategory( final String fileName ) {
+ final String suffix = FilenameUtils.getExtension(fileName);
+ if (suffix.length() != 1 || !Character.isDigit(suffix.charAt(0))) {
+ return BAD_CATEGORY;
+ }
+ return suffix.charAt(0) - '0';
+ }
+}
diff --git a/src/main/java/org/vafer/jdeb/producers/DataProducerPathTemplate.java b/src/main/java/org/vafer/jdeb/producers/DataProducerPathTemplate.java
index bd6cfd079..821ec567f 100644
--- a/src/main/java/org/vafer/jdeb/producers/DataProducerPathTemplate.java
+++ b/src/main/java/org/vafer/jdeb/producers/DataProducerPathTemplate.java
@@ -33,12 +33,7 @@ public DataProducerPathTemplate( String[] pLiteralPaths, String[] pIncludes, Str
public void produce( DataConsumer pReceiver ) throws IOException {
for (String literalPath : literalPaths) {
- TarArchiveEntry entry = new TarArchiveEntry(literalPath, true);
- entry.setUserId(0);
- entry.setUserName("root");
- entry.setGroupId(0);
- entry.setGroupName("root");
- entry.setMode(TarArchiveEntry.DEFAULT_DIR_MODE);
+ TarArchiveEntry entry = Producers.defaultDirEntryWithName(literalPath);
entry = map(entry);
diff --git a/src/main/java/org/vafer/jdeb/producers/ProducerFactory.java b/src/main/java/org/vafer/jdeb/producers/ProducerFactory.java
new file mode 100644
index 000000000..3c52f604a
--- /dev/null
+++ b/src/main/java/org/vafer/jdeb/producers/ProducerFactory.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2013 The jdeb developers.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.vafer.jdeb.producers;
+
+import org.vafer.jdeb.DataProducer;
+import org.vafer.jdeb.mapping.Mapper;
+
+import java.io.File;
+
+/**
+ * Factory to create data producers at runtime.
+ *
+ * @author Roman Kashitsyn
+ */
+public class ProducerFactory {
+
+ private ProducerFactory() {
+ }
+
+ /**
+ * Enumeration of all known producer types.
+ */
+ public enum KnownType {
+ FILE("file", true),
+ ARCHIVE("archive", true),
+ DIRECTORY("directory", true),
+ MAN_PAGE("man-page", true),
+ LINK("link", false),
+ TEMPLATE("template", false);
+
+ private final String name;
+ private final boolean requiresSource;
+
+ private KnownType( final String name,
+ boolean requiresSource ) {
+ this.name = name;
+ this.requiresSource = requiresSource;
+ }
+
+ public boolean requiresSource() {
+ return requiresSource;
+ }
+
+ public String shortName() {
+ return name;
+ }
+
+ public static KnownType forString( final String typeName ) {
+ for (KnownType type : values()) {
+ if (type.shortName().equalsIgnoreCase(typeName)) {
+ return type;
+ }
+ }
+ return null;
+ }
+ }
+
+ public static abstract class Params {
+ public File getSource() {
+ return null;
+ }
+
+ public String getDestination() {
+ return null;
+ }
+
+ public String getLink() {
+ return null;
+ }
+
+ public String getLinkTarget() {
+ return null;
+ }
+
+ public String[] getIncludePatterns() {
+ return null;
+ }
+
+ public String[] getExcludePatterns() {
+ return null;
+ }
+
+ public String[] getTemplatePaths() {
+ return null;
+ }
+
+ public boolean isSimlink() {
+ return false;
+ }
+
+ public Mapper[] getMappers() {
+ return null;
+ }
+ }
+
+ /**
+ * Creates a data producer in runtime.
+ *
+ * @param type producer type
+ * @param params parameter provider
+ * @return producer or null if null type is given
+ * @throws java.lang.IllegalArgumentException if required parameters are missing
+ */
+ public static DataProducer create( final KnownType type,
+ final Params params ) {
+ switch (type) {
+ case FILE:
+ return new DataProducerFile(
+ params.getSource(),
+ params.getDestination(),
+ params.getIncludePatterns(),
+ params.getExcludePatterns(),
+ params.getMappers()
+ );
+
+ case ARCHIVE:
+ return new DataProducerArchive(
+ params.getSource(),
+ params.getIncludePatterns(),
+ params.getExcludePatterns(),
+ params.getMappers()
+ );
+
+ case DIRECTORY:
+ return new DataProducerDirectory(
+ params.getSource(),
+ params.getIncludePatterns(),
+ params.getExcludePatterns(),
+ params.getMappers()
+ );
+ case TEMPLATE:
+ final String[] paths = params.getTemplatePaths();
+ if (paths == null || paths.length == 0) {
+ throw new IllegalArgumentException("paths is not set");
+ }
+
+ return new DataProducerPathTemplate(
+ paths,
+ params.getIncludePatterns(),
+ params.getExcludePatterns(),
+ params.getMappers()
+ );
+ case LINK:
+ final String linkName = params.getLink();
+ final String linkTarget = params.getLinkTarget();
+
+ if (linkName == null) {
+ throw new IllegalArgumentException("linkName is not set");
+ }
+ if (linkTarget == null) {
+ throw new IllegalArgumentException("linkTarget is not set");
+ }
+
+ return new DataProducerLink(
+ linkName,
+ linkTarget,
+ params.isSimlink(),
+ params.getIncludePatterns(),
+ params.getExcludePatterns(),
+ params.getMappers()
+ );
+ case MAN_PAGE:
+ return new DataProducerManPage(
+ params.getSource(),
+ params.getDestination(),
+ params.getIncludePatterns(),
+ params.getExcludePatterns(),
+ params.getMappers()
+ );
+ default:
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/vafer/jdeb/producers/Producers.java b/src/main/java/org/vafer/jdeb/producers/Producers.java
new file mode 100644
index 000000000..e5d1d4496
--- /dev/null
+++ b/src/main/java/org/vafer/jdeb/producers/Producers.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2013 The jdeb developers.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.vafer.jdeb.producers;
+
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+
+import org.apache.commons.io.IOUtils;
+import org.vafer.jdeb.DataConsumer;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Package-private utility class with common producers functionality.
+ *
+ * @author Roman Kashitsyn
+ */
+class Producers {
+
+ final static int ROOT_UID = 0;
+ final static String ROOT_NAME = "root";
+
+ private Producers() {}
+
+
+ /**
+ * Creates a tar file entry with defaults parameters.
+ * @param entryName the entry name
+ * @return file entry with reasonable defaults
+ */
+ static TarArchiveEntry defaultFileEntryWithName( final String entryName ) {
+ TarArchiveEntry entry = new TarArchiveEntry(entryName, true);
+ entry.setUserId(ROOT_UID);
+ entry.setUserName(ROOT_NAME);
+ entry.setGroupId(ROOT_UID);
+ entry.setGroupName(ROOT_NAME);
+ entry.setMode(TarArchiveEntry.DEFAULT_FILE_MODE);
+ return entry;
+ }
+
+ /**
+ * Creates a tar directory entry with defaults parameters.
+ * @param dirName the directory name
+ * @return dir entry with reasonable defaults
+ */
+ static TarArchiveEntry defaultDirEntryWithName( final String dirName ) {
+ TarArchiveEntry entry = new TarArchiveEntry(dirName, true);
+ entry.setUserId(ROOT_UID);
+ entry.setUserName(ROOT_NAME);
+ entry.setGroupId(ROOT_UID);
+ entry.setGroupName(ROOT_NAME);
+ entry.setMode(TarArchiveEntry.DEFAULT_DIR_MODE);
+ return entry;
+ }
+
+
+ /**
+ * Feeds input stream to data consumer using metadata from tar entry.
+ * @param consumer the consumer
+ * @param inputStream the stream to feed
+ * @param entry the entry to use for metadata
+ * @throws IOException on consume error
+ */
+ static void produceInputStreamWithEntry( final DataConsumer consumer,
+ final InputStream inputStream,
+ final TarArchiveEntry entry ) throws IOException {
+ try {
+ consumer.onEachFile(inputStream, entry.getName(), entry.getLinkName(), entry.getUserName(), entry.getUserId(),
+ entry.getGroupName(), entry.getGroupId(), entry.getMode(), entry.getSize());
+ } finally {
+ IOUtils.closeQuietly(inputStream);
+ }
+ }
+
+}
diff --git a/src/test/java/org/vafer/jdeb/maven/DataTestCase.java b/src/test/java/org/vafer/jdeb/maven/DataTestCase.java
index fb894918b..b1f5d90c6 100644
--- a/src/test/java/org/vafer/jdeb/maven/DataTestCase.java
+++ b/src/test/java/org/vafer/jdeb/maven/DataTestCase.java
@@ -20,6 +20,7 @@
import java.io.IOException;
import junit.framework.TestCase;
+import org.vafer.jdeb.producers.ProducerFactory;
/*
* Admittedly not the nicest way to assert that failOnMissingSrc functions. However, the best that can be done without
@@ -27,6 +28,8 @@
*/
public class DataTestCase extends TestCase {
+ private static final ProducerFactory.KnownType fileType = ProducerFactory.KnownType.FILE;
+
private Data data;
private File missingFile;
private File file;
@@ -56,6 +59,7 @@ public void testFailOnUnknownValue() throws IOException {
public void testFailOnMissingSrcDefaultFileMissing() throws IOException {
try {
data.setSrc(missingFile);
+ data.setType(fileType.shortName());
data.produce(null);
fail();
} catch (FileNotFoundException expected) {
@@ -65,11 +69,13 @@ public void testFailOnMissingSrcDefaultFileMissing() throws IOException {
public void testFailOnMissingSrcIgnoreFileMissing() throws IOException {
data.setSrc(missingFile);
data.setMissingSrc("ignore");
+ data.setType(fileType.shortName());
data.produce(null);
}
public void testFailOnMissingSrcIgnoreFileMissingVaryInput() throws IOException {
data.setSrc(missingFile);
+ data.setType(fileType.shortName());
data.setMissingSrc(" IGNORE ");
data.produce(null);
}
@@ -77,6 +83,7 @@ public void testFailOnMissingSrcIgnoreFileMissingVaryInput() throws IOException
public void testFailOnMissingSrcFailFileMissing() throws IOException {
try {
data.setSrc(missingFile);
+ data.setType(fileType.shortName());
data.setMissingSrc("fail");
data.produce(null);
fail();
diff --git a/src/test/java/org/vafer/jdeb/producers/DataProducerManPageTest.java b/src/test/java/org/vafer/jdeb/producers/DataProducerManPageTest.java
new file mode 100644
index 000000000..1a2d1c2e2
--- /dev/null
+++ b/src/test/java/org/vafer/jdeb/producers/DataProducerManPageTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013 The jdeb developers.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.vafer.jdeb.producers;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+
+import static org.vafer.jdeb.producers.DataProducerManPage.makeDestination;
+
+/**
+ * @author Roman Kashitsyn
+ */
+public class DataProducerManPageTest extends TestCase {
+
+ private static final String[][] TEST_TABLE = {
+ /* given destination | file name | expected result */
+ {null, "page.1", "/usr/share/man/man1/page.1.gz"},
+ {"/some/fixed/location", "page.1", "/some/fixed/location"},
+ {"/some/fixed/location", "page.1.gz", "/some/fixed/location"},
+ {"", "/some/page.2.gz", "/usr/share/man/man2/page.2.gz"},
+ {"", "/some/page.7.bz2", "/usr/share/man/man7/page.7.bz2"},
+ {"", "page", "/usr/share/man/man1/page.1.gz"},
+ {"", "page.-1", "/usr/share/man/man1/page.-1.1.gz"},
+ {"", "page.txt", "/usr/share/man/man1/page.txt.1.gz"}
+ };
+
+ public void testMakeDestination() throws Exception {
+ for (final String[] tuple : TEST_TABLE) {
+ final String result = tuple[2];
+ assertEquals(result, makeDestination(tuple[0], new File(tuple[1])));
+ }
+ }
+}