net.sourceforge.javadpkg.store.DataStoreImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dpkg Show documentation
Show all versions of dpkg Show documentation
The library for reading and writing Debian Packages.
/*
* 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.store;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.List;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import net.sourceforge.javadpkg.DebianPackageConstants;
import net.sourceforge.javadpkg.control.Size;
import net.sourceforge.javadpkg.io.DataSource;
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;
/**
*
* A {@link DataStore} implementation.
*
*
* @author Gerrit Hohl ([email protected])
* @version 1.0, 26.04.2016 by Gerrit Hohl
*/
public class DataStoreImpl implements DataStore, DebianPackageConstants {
/** The default owner. */
private static final FileOwner DEFAULT_OWNER = new FileOwnerImpl(ROOT_GROUP_ID, ROOT_GROUP_NAME, ROOT_USER_ID,
ROOT_USER_NAME);
/** The default mode for a directory. */
private static final FileMode DEFAULT_DIRECTORY_MODE = new FileModeImpl(DIRECTORY_MODE);
/** The default mode for a regular file. */
private static final FileMode DEFAULT_FILE_MODE = new FileModeImpl(FILE_MODE);
/** The root node. */
private DataStoreNode rootNode;
/**
*
* Creates a store.
*
*/
public DataStoreImpl() {
super();
this.rootNode = new DataStoreNode();
}
/**
*
* Splits the specified path into its parts.
*
*
* @param path
* The path.
* @return The path parts.
*/
private String[] getPathParts(String path) {
String line;
String[] pathParts;
line = path;
if (line.startsWith("./")) {
line = line.substring(2);
} else if (line.startsWith(".")) {
line = line.substring(1);
} else if (line.startsWith("/")) {
line = line.substring(1);
}
pathParts = line.split("/", 0);
return pathParts;
}
/**
*
* Returns the node with the specified path.
*
*
* @param pathParts
* The path parts.
* @param index
* The index of parent node in the path parts. Starts at
* 0
with the root node.
* @param level
* The level of the node which should be returned within the path
* parts. If level is pathParts.length - 1
the node
* referred by the complete path will be returned.
* @param parentNode
* The parent node.
* @return The node or null
, if no such node exists.
*/
private DataStoreNode getNode(String[] pathParts, int index, int level, DataStoreNode parentNode) {
String name;
DataStoreNode node;
if (index >= level)
return parentNode;
name = pathParts[index];
node = parentNode.getChildNodeByName(name);
if (node == null)
return null;
return this.getNode(pathParts, index + 1, level, node);
}
/**
*
* Adds a node.
*
*
* @param source
* The source (optional). Only needed if a file node is added.
* @param path
* The path.
* @param target
* The target (optional). Only needed if a symbolic link node is
* added.
* @param owner
* The owner.
* @param mode
* The mode.
* @throws IllegalArgumentException
* If the path is invalid, the parent node is not a directory,
* the parent directory doesn't exist or already contains an
* entry with the same name.
*/
private void addNode(DataSource source, String path, String target, FileOwner owner, FileMode mode) {
String type, name;
String[] pathParts;
DataStoreNode parentNode, node;
// --- Does the path point to the root node? ---
pathParts = this.getPathParts(path);
if ((pathParts.length == 0) || ((pathParts.length == 1) && pathParts[0].isEmpty()))
throw new IllegalArgumentException("Argument path doesn't contain a path: " + path);
// --- Prepare type for error messages ---
if (source != null) {
type = "file";
} else if (target != null) {
type = "symbolic link";
} else {
type = "directory";
}
// --- Get parent node ---
parentNode = this.getNode(pathParts, 0, pathParts.length - 1, this.rootNode);
if (parentNode == null)
throw new IllegalArgumentException(
"Can't add " + type + " |" + path + "| because the parent directory doesn't exist.");
if (!parentNode.isDirectory())
throw new IllegalArgumentException("Can't add " + type + " |" + path + "| because the entry |"
+ parentNode.getPath() + "| is not a directory.");
// --- Does the node already exist? ---
name = pathParts[pathParts.length - 1];
node = parentNode.getChildNodeByName(name);
if (node != null)
throw new IllegalArgumentException("Can't add " + type + " because a " + (node.isDirectory() ? "directory" : "file")
+ " with the path |" + path + "| already exists.");
// --- Create node for file, symbolic link or directory ---
if (source != null) {
node = new DataStoreNode(source, name, owner, mode);
} else if (target != null) {
node = new DataStoreNode(name, target, owner, mode);
} else {
node = new DataStoreNode(name, owner, mode);
}
parentNode.addChildNode(node);
}
@Override
public void addDirectory(String path) {
if (path == null)
throw new IllegalArgumentException("Argument path is null.");
this.addDirectory(path, DEFAULT_OWNER, DEFAULT_DIRECTORY_MODE);
}
@Override
public void addDirectory(String path, FileOwner owner, FileMode mode) {
if (path == null)
throw new IllegalArgumentException("Argument path is null.");
if (owner == null)
throw new IllegalArgumentException("Argument owner is null.");
if (mode == null)
throw new IllegalArgumentException("Argument mode is null.");
this.addNode(null, path, null, owner, mode);
}
@Override
public void addFile(DataSource source, String path) {
if (source == null)
throw new IllegalArgumentException("Argument source is null.");
if (path == null)
throw new IllegalArgumentException("Argument path is null.");
this.addFile(source, path, DEFAULT_OWNER, DEFAULT_FILE_MODE);
}
@Override
public void addFile(DataSource source, String path, FileOwner owner, FileMode mode) {
if (source == null)
throw new IllegalArgumentException("Argument source is null.");
if (path == null)
throw new IllegalArgumentException("Argument path is null.");
if (owner == null)
throw new IllegalArgumentException("Argument owner is null.");
if (mode == null)
throw new IllegalArgumentException("Argument mode is null.");
this.addNode(source, path, null, owner, mode);
}
@Override
public void addSymLink(String path, String target, FileOwner owner, FileMode mode) {
if (path == null)
throw new IllegalArgumentException("Argument path is null.");
if (target == null)
throw new IllegalArgumentException("Argument target is null.");
if (owner == null)
throw new IllegalArgumentException("Argument owner is null.");
if (mode == null)
throw new IllegalArgumentException("Argument mode is null.");
this.addNode(null, path, target, owner, mode);
}
@Override
public boolean exists(String path) {
String[] pathParts;
DataStoreNode node;
if (path == null)
throw new IllegalArgumentException("Argument path is null.");
// --- Does the path point to the root node? ---
pathParts = this.getPathParts(path);
if ((pathParts.length == 0) || ((pathParts.length == 1) && pathParts[0].isEmpty()))
throw new IllegalArgumentException("Argument path doesn't contain a path: " + path);
// --- Get node ---
node = this.getNode(pathParts, 0, pathParts.length, this.rootNode);
return (node != null);
}
@Override
public Size getSize() throws IOException {
Size size;
try {
size = new Size(this.rootNode.getSize());
} catch (IOException e) {
throw new IOException("Couldn't determine size of store: " + e.getMessage(), e);
}
return size;
}
@Override
public void write(TarArchiveOutputStream out) throws IOException {
if (out == null)
throw new IllegalArgumentException("Argument out is null.");
this.rootNode.write(out);
}
@Override
public List createFileHashes(MessageDigest digest) throws IOException {
List hashes;
if (digest == null)
throw new IllegalArgumentException("Argument digest is null.");
hashes = this.rootNode.createFileHashes(digest);
return hashes;
}
}