package yalp.vfs;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.Channel;
import java.nio.channels.FileChannel;
import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import yalp.Yalp;
import yalp.exceptions.UnexpectedException;
import yalp.libs.IO;
/**
* The VFS used by Yalp
*/
public class VirtualFile {
File realFile;
VirtualFile(File file) {
this.realFile = file;
}
public String getName() {
return realFile.getName();
}
public boolean isDirectory() {
return realFile.isDirectory();
}
public String relativePath() {
List<String> path = new ArrayList<String>();
File f = realFile;
String prefix = "{?}";
while (true) {
path.add(f.getName());
f = f.getParentFile();
if (f == null) {
break; // ??
}
if (f.equals(Yalp.frameworkPath)) {
prefix = "{yalp}";
break;
}
if (f.equals(Yalp.applicationPath)) {
prefix = "";
break;
}
String module = isRoot(f);
if (module != null) {
prefix = module;
break;
}
}
Collections.reverse(path);
StringBuilder builder = new StringBuilder();
for (String p : path) {
builder.append("/" + p);
}
return prefix + builder.toString();
}
String isRoot(File f) {
for (VirtualFile vf : Yalp.roots) {
if (vf.realFile.getAbsolutePath().equals(f.getAbsolutePath())) {
return "{module:" + vf.getName() + "}";
}
}
return null;
}
public List<VirtualFile> list() {
List<VirtualFile> res = new ArrayList<VirtualFile>();
if (exists()) {
File[] children = realFile.listFiles();
for (int i = 0; i < children.length; i++) {
res.add(new VirtualFile(children[i]));
}
}
return res;
}
public boolean exists() {
try {
if (realFile != null) {
return realFile.exists();
}
return false;
} catch (AccessControlException e) {
return false;
}
}
public InputStream inputstream() {
try {
return new FileInputStream(realFile);
} catch (Exception e) {
throw new UnexpectedException(e);
}
}
public OutputStream outputstream() {
try {
return new FileOutputStream(realFile);
} catch (Exception e) {
throw new UnexpectedException(e);
}
}
public Long lastModified() {
if (realFile != null) {
return realFile.lastModified();
}
return 0L;
}
@Override
public boolean equals(Object other) {
if (other instanceof VirtualFile) {
VirtualFile vf = (VirtualFile) other;
if (realFile != null && vf.realFile != null) {
return realFile.equals(vf.realFile);
}
}
return super.equals(other);
}
@Override
public int hashCode() {
if (realFile != null) {
return realFile.hashCode();
}
return super.hashCode();
}
public long length() {
return realFile.length();
}
public VirtualFile child(String name) {
return new VirtualFile(new File(realFile, name));
}
public Channel channel() {
try {
FileInputStream fis = new FileInputStream(realFile);
FileChannel ch = fis.getChannel();
return ch;
} catch (FileNotFoundException e) {
return null;
}
}
public static VirtualFile open(String file) {
return open(new File(file));
}
public static VirtualFile open(File file) {
return new VirtualFile(file);
}
public String contentAsString() {
try {
return IO.readContentAsString(inputstream());
} catch (Exception e) {
throw new UnexpectedException(e);
}
}
public File getRealFile() {
return realFile;
}
public void write(CharSequence string) {
try {
IO.writeContent(string, outputstream());
} catch (Exception e) {
throw new UnexpectedException(e);
}
}
public byte[] content() {
byte[] buffer = new byte[(int) length()];
try {
InputStream is = inputstream();
is.read(buffer);
is.close();
return buffer;
} catch (Exception e) {
throw new UnexpectedException(e);
}
}
@Override
public String toString() {
return getName();
}
public static VirtualFile search(Collection<VirtualFile> roots, String path) {
for (VirtualFile file : roots) {
if (file.child(path).exists()) {
return file.child(path);
}
}
return null;
}
public static VirtualFile fromRelativePath(String relativePath) {
Pattern pattern = Pattern.compile("^(\\{(.+?)\\})?(.*)$");
Matcher matcher = pattern.matcher(relativePath);
if (matcher.matches()) {
String path = matcher.group(3);
String module = matcher.group(2);
if (module == null || module.equals("?") || module.equals("")) {
return new VirtualFile(Yalp.applicationPath).child(path);
} else {
if (module.equals("yalp")) {
return new VirtualFile(Yalp.frameworkPath).child(path);
}
if (module.startsWith("module:")) {
module = module.substring("module:".length());
for (Entry<String, VirtualFile> entry : Yalp.modules.entrySet()) {
if (entry.getKey().equals(module))
return entry.getValue().child(path);
}
}
}
}
return null;
}
}