legacy/experimental/java-libburnia/src/java/org/pykix/libburnia/libisofs/IsoVolume.java

291 lines
7.6 KiB
Java

/*
* IsoVolume.java
*
* Copyright (c) 2007 Vreixo Formoso
*
* This library 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.
* See COPYING file for details.
*/
package org.pykix.libburnia.libisofs;
import java.io.File;
import java.io.FileNotFoundException;
import org.pykix.libburnia.bindings.Proxy;
import org.pykix.libburnia.libburn.BurnSource;
/**
* ISO-9660 Data volume.
*
* <p>
* This is the primary object to keep track of files and directory to be
* recorded in an ISO-9660 image.
*
* <p>
* To create an ISO image, you have to create a <code>IsoVolume</code>
* object and add files and/or directories to it. After doing so, you will
* want to get a {@link BurnSource} to actually write the image to a file or
* disc. To do this, you have to create an {@link IsoVolSet} with this object.
*
* @see IsoVolSet
*
* TODO current implementation forces user to keep a reference to this
* object while still having a reference to an IsoTreeNode from this. This
* is because of automatic memory management. Underlying iso_volume is
* deleted when Java object gets out of scope, and this causes all iso_tree_node
* to be also deleted, thus <i>invalidating</i> java objects. Without
* modifying libburnia code, the only way to solve this (I think) is add a ref
* from each IsoTreeNode. Because of space efficience and normal library usage
* I think current solution is better.
* When added to IsoVolSet there is no problem if this
* goes out of scope (while keeping ref. to IsoVolSet), because ref count
* is incremented and underlying object is not deleted.
*
* @author Vreixo Formoso
* @since 0.1
*/
public class IsoVolume extends Proxy {
/**
* Create a new volume.
*
* @param volumeId
* Id for the volume, can be null if you wish to set it later.
* @param publisherId
* Id for the publish, can be null if you wish to set it later.
* @param dataPreparerId
* Id for the data prepared, can be null if you wish to set it later.
*/
public IsoVolume(String volumeId, String publisherId,
String dataPreparerId) {
super( iso_volume_new(volumeId, publisherId, dataPreparerId) );
}
/**
* Create a new volume.
*
* @param volumeId
* @param publisherId
* @param dataPreparerId
* @param root
*/
public IsoVolume(String volumeId, String publisherId,
String dataPreparerId, IsoTreeNode root) {
super( iso_volume_new_with_root(volumeId, publisherId, dataPreparerId,
pointerOf(root)) );
}
/**
* Get the root directory.
* @return
*/
public IsoTreeNode getRoot() {
long ptr = iso_volume_get_root( pointerOf(this) );
if (ptr == 0) {
return null;
}
IsoTreeNode node = (IsoTreeNode) proxyFor(ptr);
if (node == null) {
node = new IsoTreeNode(ptr);
}
/*
* FIXME a problem here is that if this IsoVolume gets out of
* scope, C iso_volume will be freed, thus deleting the
* iso_tree_node, and ptr is pointing to an invalid C object, which
* can lead to problems. This can also happen in C code if an user
* explicity free the iso_volume, but in Java is really a problem
* because the automatic memory management
*/
return node;
}
/**
* Fill in the volume identifier.
* @param volumeId
*/
public void setVolumeId(String volumeId) {
iso_volume_set_volume_id(pointerOf(this), volumeId);
}
/**
* Fill in the publisher.
* @param publisherId
*/
public void setPublisherId(String publisherId) {
iso_volume_set_publisher_id(pointerOf(this), publisherId);
}
/**
* Fill in the data preparer.
* @param dataPreparerId
*/
public void setDataPreparerId(String dataPreparerId) {
iso_volume_set_data_preparer_id(pointerOf(this), dataPreparerId);
}
/**
* Locate a node by its path on disc.
*
* @param path
* The path, in the image, of the file.
* @return
* The node found or <code>null</code>.
*/
/*
* Take care that this is really a wrapp for iso_tree_volume_path_to_node
*/
public IsoTreeNode getNode(String path) {
long ptr = iso_tree_volume_path_to_node(pointerOf(this), path);
if (ptr == 0) {
return null;
}
//FIXME same problems as in getRoot
return (ptr == 0) ? null : new IsoTreeNode(ptr);
}
/**
* Add a file or a directory (recursively) to the volume by specifying
* its path on the volume.
*
* @param discPath
* The path on the disc at which to add the file/directory.
* @param path
* The path, on the local filesystem, of the file.
* @return
* The node for the file or <code>null</code> if the parent doesn't
* exists on the disc.
*/
public IsoTreeNode addPath(String discPath, String path) {
long ptr = iso_tree_volume_add_path(pointerOf(this), discPath, path);
if (ptr == 0) {
return null;
}
IsoTreeNode node = (IsoTreeNode) proxyFor(ptr);
if (node == null) {
node = new IsoTreeNode(ptr);
}
//FIXME same problems as in getRoot
return node;
}
/**
* Like {@link #addPath(String, String) addPath}, but local path is
* passed as a {@link File}
*
* @param discPath
* The path on the disc at which to add the file/directory.
* @param path
* The path, on the local filesystem, of the file.
* @return
* The node for the file or <code>null</code> if the parent doesn't
* exists on the disc.
* @throws FileNotFoundException
* If passed local path does not exist
*/
public IsoTreeNode addPath(String discPath, File path)
throws FileNotFoundException {
if ( !path.exists() ) {
throw new FileNotFoundException(path.getPath());
}
long ptr = iso_tree_volume_add_path(pointerOf(this), discPath,
path.getPath());
if (ptr == 0) {
return null;
}
IsoTreeNode node = (IsoTreeNode) proxyFor(ptr);
if (node == null) {
node = new IsoTreeNode(ptr);
}
//FIXME same problems as in getRoot
return node;
}
/**
* Creates a new, empty directory on the volume.
*
* @param discPath
* The path on the volume at which to add the directory.
* @return
* The newly created directory or <code>null</code>.
*/
public IsoTreeNode addNewDir(String discPath) {
long ptr = iso_tree_volume_add_new_dir(pointerOf(this), discPath);
if (ptr == 0) {
return null;
}
IsoTreeNode node = (IsoTreeNode) proxyFor(ptr);
if (node == null) {
node = new IsoTreeNode(ptr);
}
//FIXME same problems as in getRoot
return node;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
/* free underlying C object */
iso_volume_free( pointerOf(this) );
}
private static native long iso_volume_new(String volumeId,
String publisherId, String dataPreparerId);
private static native long iso_volume_new_with_root(String volumeId,
String publisherId, String dataPreparerId, long root);
private static native void iso_volume_free(long volume);
private static native long iso_volume_get_root(long volume);
private static native void iso_volume_set_volume_id(long volume,
String volumeId);
private static native void iso_volume_set_publisher_id(long volume,
String publisherId);
private static native void iso_volume_set_data_preparer_id(long volume,
String data_preparer_id);
private static native long iso_tree_volume_path_to_node(long volume,
String path);
private static native long iso_tree_volume_add_path(long volume,
String discPath, String path);
private static native long iso_tree_volume_add_new_dir(long volume,
String discPath);
static {
System.loadLibrary("java-libburn-0.1");
}
}