ZipFileSystem.java
package eu.javaexperience.file.fs.zip;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import eu.javaexperience.arrays.ArrayTools;
import eu.javaexperience.collection.iterator.IteratorTools;
import eu.javaexperience.collection.tree.TreeMerger;
import eu.javaexperience.collection.tree.TreeNode;
import eu.javaexperience.collection.tree.TreeNodeTools;
import eu.javaexperience.file.AbstractFile;
import eu.javaexperience.file.AbstractFileSystem;
import eu.javaexperience.file.FileSystemTools;
import eu.javaexperience.interfaces.simple.getBy.GetBy1;
import eu.javaexperience.interfaces.simple.publish.SimplePublish1;
public class ZipFileSystem implements AbstractFileSystem
{
protected String file;
protected ZipFile zip;
protected TreeNode root;
public ZipFileSystem(String file) throws IOException
{
this.file = file;
this.zip = new ZipFile(file);
this.root = processZipFiles(zip);
}
protected static final GetBy1<String, TreeNode> getNodeId = new GetBy1<String, TreeNode>()
{
@Override
public String getBy(TreeNode a)
{
return (String) a.getEtc("file");
}
};
protected static final GetBy1<TreeNode, String> createNode = new GetBy1<TreeNode, String>()
{
@Override
public TreeNode getBy(String a)
{
TreeNode ret = new TreeNode<>();
ret.putEtc("file", a);
return ret;
}
};
protected TreeNode getNodeByPath(String path)
{
return TreeNodeTools.getByPath(root, FileSystemTools.decomposePath(path), getNodeId);
}
protected String toPath(TreeNode node)
{
StringBuilder sb = new StringBuilder();
ArrayList<String> path = new ArrayList<>();
TreeNodeTools.getPathToRoot(path, node, getNodeId);
Collections.reverse(path);
for(String s:path)
{
if(sb.length() > 0)
{
sb.append("/");
}
if(null != s)
{
sb.append(s);
}
}
return sb.toString();
}
protected static final TreeMerger MERGER = new TreeMerger()
{
@Override
public Object getIdOf(TreeNode crnt)
{
return (String) crnt.getEtc("file");
}
@Override
public String getNameOf(TreeNode node)
{
return (String) node.getEtc("file");
}
};
protected static TreeNode processZipFiles(ZipFile zip)
{
TreeNode ret = new TreeNode();
for(ZipEntry e: IteratorTools.fromEnumeration(zip.entries()))
{
String[] path = FileSystemTools.decomposePath(e.getName());
TreeNodeTools.getOrCreatePath(ret, path, getNodeId, createNode).putEtc("ent", e);
}
ret.putEtc("file", "");
ret.putEtc("ent", new ZipEntry("/"));
//ensure directory entries also exists
ret.walkTree(new SimplePublish1<TreeNode>()
{
@Override
public void publish(TreeNode a)
{
ZipEntry e = (ZipEntry) a.getEtc("ent");
if(null == e)
{
String p = a.getPath(MERGER, "/");
a.putEtc("ent", new ZipEntry(p));
}
}
});
return ret;
}
@Override
public AbstractFile fromUri(String uri)
{
return new ZipFsFile(this, uri);
}
@Override
public String getFileSeparator()
{
return File.separator;
}
public static void main(String[] args) throws Throwable
{
ZipFileSystem zfs = new ZipFileSystem("/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar");
AbstractFile r = zfs.fromUri("java");
System.out.println(ArrayTools.toString(r.listFiles()));
}
}