net.sourceforge.javadpkg.plugin.impl.DataConfigurationParserImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dpkg-maven-plugin Show documentation
Show all versions of dpkg-maven-plugin Show documentation
The plugin for creating Debian Packages during a Maven build process.
The newest version!
/*
* dpkg - Debian Package library and the Debian Package Maven plugin
* (c) Copyright 2016 Gerrit Hohl
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package net.sourceforge.javadpkg.plugin.impl;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.util.List;
import org.apache.maven.plugin.logging.Log;
import net.sourceforge.javadpkg.Context;
import net.sourceforge.javadpkg.DebianPackageBuilder;
import net.sourceforge.javadpkg.DebianPackageConstants;
import net.sourceforge.javadpkg.ParseException;
import net.sourceforge.javadpkg.control.Size;
import net.sourceforge.javadpkg.io.FileMode;
import net.sourceforge.javadpkg.io.FileOwner;
import net.sourceforge.javadpkg.io.impl.FileModeImpl;
import net.sourceforge.javadpkg.io.impl.FileOwnerImpl;
import net.sourceforge.javadpkg.plugin.DataConfigurationParser;
import net.sourceforge.javadpkg.plugin.cfg.DataConfiguration;
import net.sourceforge.javadpkg.plugin.io.FileSystemNode;
import net.sourceforge.javadpkg.plugin.io.Path;
import net.sourceforge.javadpkg.plugin.io.impl.FileSystemNodeImpl;
import net.sourceforge.javadpkg.plugin.io.impl.PathImpl;
import net.sourceforge.javadpkg.replace.Replacements;
/**
*
* A {@link DataConfigurationParser} implementation.
*
*
* @author Gerrit Hohl ([email protected])
* @version 1.0, 09.05.2016 by Gerrit Hohl
*/
public class DataConfigurationParserImpl implements DataConfigurationParser, DebianPackageConstants {
/** The number format for the metrics in the log. */
private static final DecimalFormat FORMAT = new DecimalFormat("###,###,###,##0");
/** The default encoding. */
private Charset defaultEncoding;
/** The replacements. */
private Replacements replacements;
/** The transformer. */
private DataEntryNodeTransformer transformer;
/**
*
* Creates a parser.
*
*
* @param defaultEncoding
* The default encoding.
* @param replacements
* The replacements.
* @throws IllegalArgumentException
* If any of the parameters are null
.
*/
public DataConfigurationParserImpl(Charset defaultEncoding, Replacements replacements) {
super();
if (defaultEncoding == null)
throw new IllegalArgumentException("Argument defaultEncoding is null.");
if (replacements == null)
throw new IllegalArgumentException("Argument replacements is null.");
this.defaultEncoding = defaultEncoding;
this.replacements = replacements;
this.transformer = new DataEntryNodeTransformer();
}
@Override
public Size parseDataConfiguration(Log log, DataConfiguration configuration, DebianPackageBuilder builder, Context context)
throws IOException, ParseException {
Size installedSize;
FileSystemNode root;
DataFileSystemNodeVisitor visitor;
if (configuration == null)
throw new IllegalArgumentException("Argument configuration is null.");
if (builder == null)
throw new IllegalArgumentException("Argument builder is null.");
if (context == null)
throw new IllegalArgumentException("Argument context is null.");
// --- Let's create a structure for all defined files ---
root = this.parseDataConfiguration(log, configuration);
/*
* --- Remove unnecessary nodes, count the file sizes
* and add the directories and files to the builder. ---
*/
if (log.isInfoEnabled()) {
log.info("Add files...");
}
visitor = new DataFileSystemNodeVisitor(log, builder, this.defaultEncoding, this.replacements, context);
root.walkNodeTree(visitor);
if (log.isInfoEnabled()) {
log.info("Size : " + FORMAT.format(visitor.getSize()) + " byte(s)");
if (visitor.isProcess()) {
log.info(" Attention: Size can differ from real size as at least one file is marked for being processed.");
}
log.info("Files : " + FORMAT.format(visitor.getFiles()));
log.info("Directories : " + FORMAT.format(visitor.getDirectories()));
}
installedSize = Size.getSizeInBytes(visitor.getSize());
return installedSize;
}
/**
*
* Parses the data configuration and returns the node tree.
*
*
* @param log
* The log.
* @param configuration
* The data configuration.
* @return The root node of the node tree.
* @throws IOException
* If an I/O error occurs.
* @throws ParseException
* If an error occurs during the parsing.
*/
private FileSystemNode parseDataConfiguration(Log log, DataConfiguration configuration)
throws IOException, ParseException {
FileSystemNode root, parentNode;
List nodes;
File source;
String name = null, symLink, groupName, userName;
Path parent, target;
long groupId, userId;
int modeValue;
FileOwner owner;
FileMode mode;
FileSystemNodeInfo info;
// --- Create the root node ---
root = this.createDefaultFileSystem();
// --- Get all directory and files from the configuration ---
nodes = this.transformer.transform(log, configuration.getEntries());
for (DataEntryNode node : nodes) {
// --- Source --
source = node.getSource();
// --- Name ---
name = node.getName();
// --- Parent ---
parent = node.getParent();
try {
parentNode = root.createDirectories(parent);
} catch (IllegalStateException e) {
throw new ParseException(
"Couldn't ensure existence of parent path |" + parent.getAbsolutePath() + "|: " + e.getMessage(), e);
}
// --- Symbolic link ---
symLink = node.getSymLink();
if (symLink != null) {
target = PathImpl.parsePath(symLink);
} else {
target = null;
}
// --- Group ID ---
if (node.getGroupId() == null) {
groupId = ROOT_GROUP_ID;
} else {
groupId = node.getGroupId().longValue();
}
// --- Group name ---
if (node.getGroupName() == null) {
groupName = ROOT_GROUP_NAME;
} else {
groupName = node.getGroupName();
}
// --- User ID ---
if (node.getUserId() == null) {
userId = ROOT_USER_ID;
} else {
userId = node.getUserId().longValue();
}
// --- User name ---
if (node.getUserName() == null) {
userName = ROOT_USER_NAME;
} else {
userName = node.getUserName();
}
// --- Mode ---
if (node.getMode() == null) {
// --- Do we have a file? ---
if (source == null) {
modeValue = DIRECTORY_MODE;
}
// --- Otherwise it's a directory ---
else {
modeValue = FILE_MODE;
}
} else {
modeValue = node.getMode().intValue();
}
// --- Create the node ---
owner = new FileOwnerImpl(groupId, groupName, userId, userName);
mode = new FileModeImpl(modeValue);
try {
// --- Do we have a regular file? ---
if (source != null) {
// --- Take of an already existing node ---
this.removeExistingNode(log, parentNode, name, false);
// --- Create and add new node ---
info = new FileSystemNodeInfo(new FileInfoImpl(source), node.isProcess(), node.getEncoding());
parentNode.createChildFile(name, owner, mode, info);
}
// --- Do we have a symbolic link? ---
else if (symLink != null) {
// --- Take of an already existing node ---
this.removeExistingNode(log, parentNode, name, false);
// --- Create and add new node ---
parentNode.createChildSymLink(name, target, owner, mode, null);
}
// --- Otherwise it is a directory ---
else {
// --- Take of an already existing node ---
this.removeExistingNode(log, parentNode, name, true);
// --- Create and add new node ---
parentNode.createChildDirectory(name, owner, mode, null);
}
} catch (IllegalStateException e) {
throw new ParseException("Couldn't create node |" + name + "| in path |"
+ parentNode.getPath().getAbsolutePath() + "|: " + e.getMessage(), e);
}
}
return root;
}
/**
*
* Creates a default file system based on the FHS.
*
*
* For more information see:
*
* Filesystem Hierarchy Standard.
*
*
* A few directories are not created as they should be used by any Debian
* package (like /dev
, /home
, etc.).
*
*
* @return The root.
*/
private FileSystemNode createDefaultFileSystem() {
FileSystemNode root;
root = new FileSystemNodeImpl<>("");
root.createDirectories(PathImpl.parsePath("/bin"));
root.createDirectories(PathImpl.parsePath("/boot"));
root.createDirectories(PathImpl.parsePath("/etc"));
root.createDirectories(PathImpl.parsePath("/lib"));
root.createDirectories(PathImpl.parsePath("/opt"));
root.createDirectories(PathImpl.parsePath("/run"));
root.createDirectories(PathImpl.parsePath("/sbin"));
root.createDirectories(PathImpl.parsePath("/srv"));
root.createDirectories(PathImpl.parsePath("/usr"));
root.createDirectories(PathImpl.parsePath("/usr/bin"));
root.createDirectories(PathImpl.parsePath("/usr/include"));
root.createDirectories(PathImpl.parsePath("/usr/lib"));
root.createDirectories(PathImpl.parsePath("/usr/local"));
root.createDirectories(PathImpl.parsePath("/usr/sbin"));
root.createDirectories(PathImpl.parsePath("/usr/share"));
root.createDirectories(PathImpl.parsePath("/usr/src"));
root.createDirectories(PathImpl.parsePath("/usr/X11R6"));
root.createDirectories(PathImpl.parsePath("/var"));
root.createDirectories(PathImpl.parsePath("/var/cache"));
root.createDirectories(PathImpl.parsePath("/var/lib"));
root.createDirectories(PathImpl.parsePath("/var/lock"));
root.createDirectories(PathImpl.parsePath("/var/log"));
root.createDirectories(PathImpl.parsePath("/var/mail"));
root.createDirectories(PathImpl.parsePath("/var/opt"));
root.createDirectories(PathImpl.parsePath("/var/run"));
root.createDirectories(PathImpl.parsePath("/var/spool"));
root.createDirectories(PathImpl.parsePath("/var/spool/mail"));
return root;
}
/**
*
* Removes an existing node with the specified name if the type is the same.
*
*
* @param log
* The log.
* @param parentNode
* The parent node.
* @param name
* The name of the node.
* @param directory
* The type: true
, if the new node is a directory,
* false
otherwise.
* @throws ParseException
* If the type of the existing node and the new node are not the
* same.
*/
private void removeExistingNode(Log log, FileSystemNode parentNode, String name, boolean directory)
throws ParseException {
FileSystemNode previousNode;
previousNode = parentNode.getChild(name);
if (previousNode != null) {
if (previousNode.isDirectory() != directory)
throw new ParseException("The existing node |" + previousNode.getPath().getAbsolutePath()
+ "| should be replaced, but the existing node is a " + (directory ? "directory" : "file")
+ " node while the replacement is not.");
parentNode.removeChild(previousNode);
if (log.isInfoEnabled()) {
log.info("Existing node |" + previousNode.getPath().getAbsolutePath() + "| is replaced.");
}
}
}
}