package erjang.driver.efile;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import kilim.Pausable;
import erjang.EBinary;
import erjang.driver.IO;
public class ClassPathResource {
public static boolean isResource(String fileName) {
return fileName.startsWith(EFile.RESOURCE_PREFIX);
}
public static String getResourceName(String fileName) {
if (!isResource(fileName))
return fileName;
fileName = fileName.substring(EFile.RESOURCE_PREFIX.length());
if (fileName.startsWith(File.separator) || fileName.startsWith("/")) {
fileName = fileName.substring(1);
}
return fileName;
}
public static EBinary read_file(String name) {
if (!name.startsWith(EFile.RESOURCE_PREFIX))
return null;
String fileName = getResourceName(name);
ClassLoader loader = ClassPathResource.class.getClassLoader();
InputStream resource = loader.getResourceAsStream(fileName);
if (resource == null) {
// fallback: check context class loader
loader = Thread.currentThread().getContextClassLoader();
resource = loader.getResourceAsStream(fileName);
}
if (resource == null) {
return null;
} else {
EBinary bin = null;
try {
bin = IO.istream2binary(resource);
return bin;
} catch (IOException e) {
return null;
} finally {
try {
resource.close();
} catch (IOException e) {
}
}
}
}
public static void listdir(EFile eFile, String path) throws Pausable {
String[] dir;
try {
dir = list(path);
} catch (IOException e) {
eFile.reply_posix_error(IO.exception_to_posix_code(e));
return;
}
eFile.reply_list_directory(dir);
}
static String[] list(String path) throws IOException {
Enumeration<URL> out = ClassPathResource.class.getClassLoader()
.getResources(path);
Set<String> res = new HashSet<String>();
while (out.hasMoreElements()) {
URL u = out.nextElement();
list(res, u);
}
return res.toArray(new String[res.size()]);
}
static void list(Set<String> res, URL url) throws IOException {
if (url.getProtocol().equals("jar")) {
listJarURL(res, url);
}
if (url.getProtocol().equals("file")) {
File file = new File(url.getFile());
for (String elm : file.list()) {
res.add(elm);
}
} else {
return;
}
}
private static void listJarURL(Set<String> res, URL url) throws IOException {
String path = url.getPath();
int bang = path.indexOf('!');
String jar = path.substring("file:".length(), bang);
String elm = path.substring(bang + 2);
ZipFile z = new ZipFile(jar);
Enumeration<? extends ZipEntry> ents = z.entries();
while (ents.hasMoreElements()) {
ZipEntry ent = ents.nextElement();
if (ent.getName().startsWith(elm)) {
add(res, elm, ent.getName());
}
}
z.close();
}
private static void add(Set<String> res, String elm, String name) {
String rest = name.substring(elm.length() + 1);
int idx;
if ((idx = rest.indexOf('/')) != -1) {
res.add(rest.substring(0, idx));
} else if (rest.length() != 0) {
res.add(rest);
}
}
public static void fstat(EFile efile, String file_name) throws Pausable {
// System.err.println("trying entry for "+file_name);
try {
ZipEntry ent;
ent = get_entry(file_name + "/");
if (ent == null) {
ent = get_entry(file_name);
if (ent == null) {
efile.reply_posix_error(Posix.ENOENT);
return;
}
}
// System.err.println("got entry for "+file_name+" : "+ent.toString()+" isdir="+ent.isDirectory());
long file_size = ent.getSize();
int file_type = ent.isDirectory() ? EFile.FT_DIRECTORY
: EFile.FT_REGULAR;
final int RESULT_SIZE = (1 + (29 * 4));
ByteBuffer res = ByteBuffer.allocate(RESULT_SIZE);
res.order(ByteOrder.BIG_ENDIAN);
res.put(EFile.FILE_RESP_INFO);
res.putLong(file_size);
res.putInt(file_type);
put_time(res, ent.getTime());
put_time(res, ent.getTime());
put_time(res, ent.getTime());
res.putInt(0000400);
res.putInt(1 /* file_links */);
res.putInt(0 /* file_major_device */);
res.putInt(0 /* file_minor_device */);
res.putInt(file_name.hashCode() /* file_inode */);
res.putInt(0 /* file_uid */);
res.putInt(0 /* file_gid */);
res.putInt(EFile.FA_READ);
efile.driver_output2(res, null);
} catch (IOException e) {
efile.reply_posix_error(IO.exception_to_posix_code(e));
}
}
private static void put_time(ByteBuffer res, long time) {
Calendar c = GregorianCalendar.getInstance();
c.setTimeInMillis(time);
int year = c.get(Calendar.YEAR);
res.putInt(year);
int month = c.get(Calendar.MONTH) - Calendar.JANUARY + 1;
res.putInt(month);
int day_of_month = c.get(Calendar.DAY_OF_MONTH);
res.putInt(day_of_month);
int hour_of_day = c.get(Calendar.HOUR_OF_DAY);
res.putInt(hour_of_day);
int minute_of_hour = c.get(Calendar.MINUTE);
res.putInt(minute_of_hour);
int seconds = c.get(Calendar.SECOND);
res.putInt(seconds);
}
static ZipEntry get_entry(String path) throws IOException {
String fileName = getResourceName(path);
Enumeration<URL> out = ClassPathResource.class.getClassLoader().getResources(fileName);
while (out.hasMoreElements()) {
URL u = out.nextElement();
ZipEntry result = get_entry(u);
if (result != null)
return result;
}
return null;
}
static ZipEntry get_entry(URL url) throws IOException {
if (url.getProtocol().equals("jar")) {
return get_jar_entry(url);
} else {
return null;
}
}
private static ZipEntry get_jar_entry(URL url) throws IOException {
// System.err.println("looking at "+url);
String path = url.getPath();
int bang = path.indexOf('!');
String jar = path.substring("file:".length(), bang);
String elm = path.substring(bang + 2);
ZipFile z = new ZipFile(jar);
try {
ZipEntry ze = z.getEntry(elm);
if (ze != null)
return ze;
} finally {
z.close();
}
return null;
}
}