package net.sf.cotta.utils;
import net.sf.cotta.*;
import net.sf.cotta.zip.ZipFileSystem;
import java.io.File;
import java.io.IOException;
public class ClassPathEntry {
private ClassPathType type;
private TDirectory directory;
private TFile file;
private TResource resource = TResource.NULL;
private TDirectory cachedJarDirecotry;
public ClassPathEntry(TDirectory directory) {
this.directory = directory;
type = ClassPathType.DIRECTORY;
}
public ClassPathEntry(TFile file) {
this.file = file;
type = ClassPathType.FILE;
}
public ClassPathType type() {
return type;
}
/**
* Use the class path entry as a TDirectory.
* If the entry is a jar file, it will be opened and would require a close to be called. If you don't want to handle the
* resource management, you should use read method
*
* @return If the class path entry is a directory, the directory ponting to it, or if it is a zip file, to the root entry of it.
* @throws TIoException If the class path entry is pointing to a file that is not a zip format
* @see #read(ClassPathEntryProcessor)
*/
public TDirectory openAsDirectory() throws TIoException {
if (ClassPathType.DIRECTORY.equals(type)) {
return directory;
}
return convertToJarRoot();
}
private TDirectory convertToJarRoot() throws TIoException {
if (cachedJarDirecotry == null) {
ZipFileSystem fileSystem = convertToFileSystem();
cachedJarDirecotry = new TFileFactory(fileSystem).dir("/");
}
return cachedJarDirecotry;
}
private ZipFileSystem convertToFileSystem() throws TIoException {
File jarFile = new File(file.path());
ZipFileSystem fileSystem;
try {
fileSystem = new ZipFileSystem(jarFile);
} catch (IOException e) {
throw new TIoException(TPath.parse(file.path()), "Error opening zip file <" + jarFile.getAbsolutePath() + ">", e);
}
resource = fileSystem;
return fileSystem;
}
/**
* Close the resource. This is used to close the file if this class path entry is a zip file.
*
* @throws TIoException If close threw exception.
*/
public void closeResource() throws TIoException {
resource.close();
cachedJarDirecotry = null;
resource = TResource.NULL;
}
/**
* @return The path string of this class path entry
*/
public String path() {
return ClassPathType.DIRECTORY.equals(type) ? directory.path() : file.path();
}
/**
* Opens the class path entry, process its content, and close the resource
*
* @param processor The processor to call after openning the class path entry
* @throws TIoException for any read error
*/
public void read(ClassPathEntryProcessor processor) throws TIoException {
TResource resource = TResource.NULL;
TDirectory directory;
if (ClassPathType.DIRECTORY.equals(type)) {
directory = this.directory;
} else {
ZipFileSystem fileSystem = convertToFileSystem();
resource = fileSystem;
directory = new TFileFactory(fileSystem).dir("/");
}
callBack(processor, resource, directory);
}
private void callBack(ClassPathEntryProcessor processor, TResource resource, TDirectory directory) throws TIoException {
try {
processor.process(directory);
} finally {
resource.close();
}
}
}