package net.sf.cotta;
import net.sf.cotta.io.*;
import net.sf.cotta.system.FileSystem;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;
/**
* The class that represents the file. Even though the constructor is public, the usual
* way is to create TFile through TFile, TDirectory, and TFileFactory
*
* @see TFileFactory#file(String)
* @see TFileFactory#fileFromJavaFile(java.io.File)
* @see TDirectory#file(String)
* @see TDirectory#file(TPath)
*/
public class TFile extends TEntry {
/**
* Create TFile instance backed up by the file system
*
* @param fileSystem file system backing the file
* @param path path for the file
* @see #TFile(TFileFactory, TPath)
* @see #TFile(TFileFactory, TPath)
* @deprecated use the other constructor for default encoding support provided by factory
*/
public TFile(FileSystem fileSystem, TPath path) {
this(new TFileFactory(fileSystem), path);
}
/**
* Create TFile instance backed up by the factory
*
* @param factory file factory as the file system
* @param path path for the file
*/
public TFile(TFileFactory factory, TPath path) {
super(factory, path);
}
public boolean exists() {
return filesystem().fileExists(path);
}
public TFile create() throws TIoException {
parent().ensureExists();
filesystem().createFile(path);
return this;
}
public String extname() {
String name = name();
int index = name.lastIndexOf('.');
return index == -1 ? "" : name.substring(index + 1);
}
public String basename() {
String name = name();
int index = name.lastIndexOf('.');
return index == -1 ? name : name.substring(0, index);
}
public void delete() throws TIoException {
filesystem().deleteFile(path);
}
private InputStreamFactory inputStreamFactory() {
return new InputStreamFactory() {
public InputStream inputStream() throws TIoException {
return TFile.this.inputStream();
}
public FileChannel inputChannel() throws TIoException {
return TFile.this.inputChannel();
}
public TPath path() {
return TFile.this.toPath();
}
};
}
private OutputStreamFactory outputStreamFactory(final OutputMode mode) {
return new OutputStreamFactory() {
public OutputStream outputStream() throws TIoException {
return TFile.this.outputStream(mode);
}
public TPath path() {
return TFile.this.toPath();
}
};
}
@SuppressWarnings({"deprecation"})
private StreamFactory streamFactory() {
return new StreamFactory() {
public InputStream inputStream() throws TIoException {
return TFile.this.inputStream();
}
public FileChannel inputChannel() throws TIoException {
return TFile.this.inputChannel();
}
public OutputStream outputStream(OutputMode mode) throws TIoException {
return TFile.this.outputStream(mode);
}
public TPath path() {
return path;
}
};
}
/**
* Creates the input channel for the file
*
* @return FileChannel for input
* @throws TIoException error in creating the input channel
*/
public FileChannel inputChannel() throws TIoException {
return filesystem().createInputChannel(path);
}
/**
* Create the output stream
*
* @param mode output mode
* @return output stream for the file
* @throws TIoException error in creating the output stream
*/
public OutputStream outputStream(OutputMode mode) throws TIoException {
parent().ensureExists();
return filesystem().createOutputStream(path, mode);
}
/**
* Create the input stream
*
* @return input stream for the file
* @throws TIoException error in creating the input stream
*/
public InputStream inputStream() throws TIoException {
return filesystem().createInputStream(path);
}
public void copyTo(final TFile target) throws TIoException {
target.write(new OutputProcessor() {
public void process(OutputManager manager) throws IOException {
copyTo(manager.outputStream());
}
});
}
public void copyTo(final OutputStream outputStream) throws TIoException {
read(new InputProcessor() {
public void process(InputManager inputManager) throws IOException {
copy(inputManager.inputStream(), outputStream);
}
});
}
private void copy(InputStream is, OutputStream os) throws IOException {
byte[] buffer = new byte[256];
int read = is.read(buffer, 0, buffer.length);
while (read > -1) {
os.write(buffer, 0, read);
read = is.read(buffer, 0, buffer.length);
}
}
public void moveTo(TFile destination) throws TIoException {
if (!exists()) {
throw new TFileNotFoundException(path);
}
if (destination.exists()) {
throw new TIoException(destination.path, "Destination exists");
}
if (filesystem() == destination.filesystem() || filesystem().equals(destination.filesystem())) {
filesystem().moveFile(this.path, destination.path);
} else {
this.copyTo(destination);
delete();
}
}
public long length() {
return filesystem().fileLength(path);
}
public long lastModified() {
return filesystem().fileLastModified(path);
}
public TFile ensureExists() throws TIoException {
if (!exists()) {
create();
}
return this;
}
/**
* Returns the IoFactory backed by the current TFile
*
* @return IoFactory
* @see #inputChannel()
* @see #inputStream()
* @see #outputStream(net.sf.cotta.io.OutputMode)
* @deprecated use TFile itself is more effective
*/
@SuppressWarnings({"deprecation"})
@Deprecated
public IoFactory io() {
return new IoFactory(streamFactory(), factory().defaultEncoding());
}
/**
* Open the file for I/O processing
*
* @param processor processor call back
* @throws TIoException error in the processing
* @see #read(net.sf.cotta.io.InputProcessor)
* @see #write(net.sf.cotta.io.OutputProcessor)
* @see #append(net.sf.cotta.io.OutputProcessor)
* @deprecated use read(), write(), and append() instead
*/
@SuppressWarnings({"deprecation"})
@Deprecated
public void open(IoProcessor processor) throws TIoException {
new IoManager(streamFactory(), factory().defaultEncoding()).open(processor);
}
/**
* Read the file with a input processor
*
* @param processor processor for the input stream
* @throws TIoException error in reading the file
*/
public void read(final InputProcessor processor) throws TIoException {
Input.with(inputStreamFactory()).read(processor);
}
/**
* Read the file with a line processor
*
* @param lineProcessor line processor for the lines
* @throws TIoException error in reading the file
*/
public void read(final LineProcessor lineProcessor) throws TIoException {
Input.with(inputStreamFactory()).readLines(lineProcessor);
}
public void append(final OutputProcessor processor) throws TIoException {
Output.with(outputStreamFactory(OutputMode.APPEND), null).write(processor);
}
public void write(final OutputProcessor processor) throws TIoException {
Output.with(outputStreamFactory(OutputMode.OVERWRITE), null).write(processor);
}
/**
* Read the file with a line processor
*
* @param lineProcessor line processor for the lines
* @throws TIoException error in reading the file
* @see #read(net.sf.cotta.io.LineProcessor)
* @deprecated use #read(LineProcessor)
*/
@Deprecated
public void open(final LineProcessor lineProcessor) throws TIoException {
read(lineProcessor);
}
/**
* Load the content of the file into string using system default encoding
*
* @return content of the file
* @throws TIoException error in reading the file
*/
public String load() throws TIoException {
return Input.with(streamFactory()).load();
}
/**
* Saves the content to the file
*
* @param content content to save
* @return the file instance
* @throws TIoException if there are any exception thrown during the operation
*/
public TFile save(final String content) throws TIoException {
write(new OutputProcessor() {
public void process(OutputManager io) throws IOException {
Writer writer = io.writer();
writer.write(content);
writer.flush();
}
});
return this;
}
/**
* Parse the file into an object
*
* @param parser parser to call after opening the file for read
* @param <T> the type of the object to return
* @return the parsed object
* @throws TIoException error in reading the file
*/
public <T> T parse(final Parser<T> parser) throws TIoException {
final List<T> result = new ArrayList<T>(1);
read(new InputProcessor() {
public void process(InputManager inputManager) throws IOException {
result.add(parser.parse(inputManager));
}
});
return result.get(0);
}
/**
* Converts to the instance with a cononical path
*
* @return the instance with a cononical path
*/
public TFile toCanonicalFile() {
return factory().file(toCanonicalPath());
}
public URI toUri() {
return filesystem().toUri(toPath());
}
public URL toUrl() throws MalformedURLException {
return toUri().toURL();
}
}