Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'master' of git@github.com:trifork/erjang

  • Loading branch information...
commit d94730ed6e29e284a6b75681be61c4a4a80f7c0a 2 parents ad79c21 + 4d194ef
@eriksoe eriksoe authored
View
23 build.xml
@@ -1,6 +1,8 @@
<?xml version="1.0"?>
<project name="erjang" default="all">
<property name="erjang.version" value="0.1" />
+ <property file="erjang_cfg.properties" />
+
<path id="erjang.classpath">
<pathelement location="target/classes/" />
<pathelement location="lib/js.jar" />
@@ -178,6 +180,27 @@
</jar>
</target>
+ <target name="otpjar">
+ <jar jarfile="otp-${erjang.otp.version}.jar" basedir="${erjang.otp.root}">
+ <exclude name="**/*.so" />
+ <exclude name="**/*.dll" />
+ <exclude name="**/*.a" />
+ <exclude name="**/*.erl" />
+ <exclude name="**/bin/beam" />
+ <exclude name="**/bin/beam.smp" />
+ <exclude name="lib/megaco-*/**" />
+ <exclude name="lib/wx-*/**" />
+ <exclude name="lib/hipe-*/**" />
+ <exclude name="lib/jinterface-*/**" />
+
+ <!-- include all of erjang -->
+ <zipgroupfileset dir="." includes="erjang-${erjang.version}.jar" />
+
+ <manifest>
+ <attribute name="Main-Class" value="erjang.Main" />
+ </manifest>
+ </jar>
+ </target>
<target name="javadoc" description="generate Javadoc documentation">
<javadoc destdir="target/doc">
View
4 src/main/java/erjang/EModuleLoader.java
@@ -24,6 +24,8 @@
import erjang.beam.EUtil;
import erjang.beam.loader.ErjangBeamDisLoader;
+import erjang.driver.efile.ClassPathResource;
+import erjang.driver.efile.EFile;
import erjang.util.Progress;
@@ -112,6 +114,8 @@ private static File findBeamFile(String module) {
File beam = new File(e, n + ".beam");
if (beam.exists())
return beam;
+ if (ClassPathResource.read_file(beam.getPath()) != null)
+ return beam;
}
return null;
View
8 src/main/java/erjang/Main.java
@@ -22,6 +22,8 @@
import java.io.IOException;
import java.util.ArrayList;
+import erjang.driver.efile.EFile;
+
public class Main {
public static final String SYSTEM_ARCHITECTURE = "java";
public static final String OTP_VERSION = ErjangConfig.getString("erjang.otp.version", "R13B04");
@@ -56,6 +58,10 @@ static String setup(String cmd_line_root) {
private static String guess_erl_root() {
+ if (Main.class.getClassLoader().getResource("bin/start.boot") != null) {
+ return EFile.RESOURCE_PREFIX.substring(0, EFile.RESOURCE_PREFIX.length()-1);
+ }
+
// this logic works on Unixes ... what about windows?
String path = System.getenv("PATH");
for (String elem : path.split(File.pathSeparator)) {
@@ -154,7 +160,7 @@ public static void main(String[] args) throws Exception {
System.setProperty("erjang.path", erl_bootstrap_ebindir);
- if (!(new File(erl_bootstrap_ebindir)).exists()) {
+ if (!(new File(erl_bootstrap_ebindir)).exists() && !erl_bootstrap_ebindir.startsWith(EFile.RESOURCE_PREFIX)) {
System.err.println("No bootstrap classes at: "+erl_bootstrap_ebindir);
System.exit(1);
}
View
24 src/main/java/erjang/OTPMain.java
@@ -18,6 +18,7 @@
package erjang;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -27,6 +28,8 @@
import java.util.logging.Logger;
import erjang.driver.EDriver;
+import erjang.driver.efile.ClassPathResource;
+import erjang.driver.efile.EFile;
/**
* This will eventually be the main entrypoint for an OTP node.
@@ -49,9 +52,24 @@
};
public static void load_modules_and_drivers() throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {
- for (String m : MODULES) {
- ERT.load_module(EAtom.intern(m));
- }
+
+ if (Main.erl_bootstrap_ebindir.startsWith(EFile.RESOURCE_PREFIX)) {
+
+ for (String m : MODULES) {
+ String beam_path = Main.erl_bootstrap_ebindir + "/" + m + ".beam";
+ EBinary bin = ClassPathResource.read_file(beam_path);
+ if (bin == null) {
+ throw new FileNotFoundException(beam_path);
+ }
+ EModuleLoader.load_module(m, bin);
+ }
+
+ } else {
+ for (String m : MODULES) {
+ ERT.load_module(EAtom.intern(m));
+ }
+ }
+
for (EDriver d : DRIVERS) {
erjang.driver.Drivers.register(d);
}
View
2  src/main/java/erjang/driver/EDriverInstance.java
@@ -136,7 +136,7 @@ protected void driver_outputv(ByteBuffer hdr, ByteBuffer[] ev) throws Pausable {
task.output_from_driver(res);
}
- protected void driver_output2(ByteBuffer header, ByteBuffer buf) throws Pausable {
+ public void driver_output2(ByteBuffer header, ByteBuffer buf) throws Pausable {
int status = task.status;
View
28 src/main/java/erjang/driver/IO.java
@@ -20,6 +20,7 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.net.BindException;
import java.net.ConnectException;
@@ -29,6 +30,7 @@
import java.nio.charset.Charset;
import java.util.zip.GZIPOutputStream;
+import erjang.EBinary;
import erjang.ERT;
import erjang.driver.efile.Posix;
@@ -218,4 +220,30 @@ public static String getstr(ByteBuffer buf, boolean term) {
}
}
+ static private class BARR2 extends ByteArrayOutputStream {
+ EBinary asBinary() {
+ return new EBinary(super.buf, 0, super.count);
+ }
+ }
+
+ public static EBinary istream2binary(InputStream in) throws IOException {
+ BARR2 out = new BARR2();
+ byte[] buf = new byte[4 * 1024];
+ int read;
+ while ((read = in.read(buf)) > 0) {
+ out.write(buf, 0, read);
+ }
+ return out.asBinary();
+ }
+
+ public static byte[] istream2bytearray(InputStream in) throws IOException {
+ BARR2 out = new BARR2();
+ byte[] buf = new byte[4 * 1024];
+ int read;
+ while ((read = in.read(buf)) > 0) {
+ out.write(buf, 0, read);
+ }
+ return out.toByteArray();
+ }
+
}
View
246 src/main/java/erjang/driver/efile/ClassPathResource.java
@@ -0,0 +1,246 @@
+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.EBinList;
+import erjang.EBinary;
+import erjang.driver.IO;
+
+public class ClassPathResource {
+
+ public static EBinary read_file(String name) {
+
+ if (!name.startsWith(EFile.RESOURCE_PREFIX))
+ return null;
+
+ InputStream resource = ClassPathResource.class.getClassLoader()
+ .getResourceAsStream(
+ name.substring(EFile.RESOURCE_PREFIX.length()));
+
+ 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 {
+ Enumeration<URL> out = ClassPathResource.class.getClassLoader()
+ .getResources(path.substring(EFile.RESOURCE_PREFIX.length()));
+
+ 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;
+ }
+
+}
View
60 src/main/java/erjang/driver/efile/EFile.java
@@ -18,6 +18,7 @@
package erjang.driver.efile;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -25,6 +26,7 @@
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
+import java.io.InputStream;
import java.io.RandomAccessFile;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
@@ -39,6 +41,7 @@
import java.util.concurrent.locks.Lock;
import kilim.Pausable;
+import erjang.EBinList;
import erjang.EBinary;
import erjang.EHandle;
import erjang.EPort;
@@ -56,6 +59,7 @@
*/
public class EFile extends EDriverInstance {
+ public static final String RESOURCE_PREFIX = "/~resource/";
private static Field FileDescriptor_FD;
static {
@@ -775,6 +779,18 @@ public void ready() throws Pausable {
reply_posix_error(Posix.ENOENT);
return;
}
+
+ if (name.startsWith(RESOURCE_PREFIX)) {
+
+ EBinary data = ClassPathResource.read_file(name);
+ if (data == null) {
+ reply_posix_error(Posix.ENOENT);
+ } else {
+ task.output_from_driver(new EBinList(FILE_RESP_OK_HEADER, data));
+ }
+
+ return;
+ }
FileAsync d = new FileAsync() {
private ByteBuffer binp = null;
@@ -1475,6 +1491,11 @@ public void ready() throws Pausable {
final String file_name = IO.strcpy(buf);
final File file = ERT.newFile(file_name);
+ if (file_name.startsWith(RESOURCE_PREFIX)) {
+ ClassPathResource.fstat(this, file_name);
+ return;
+ }
+
d = new FileAsync() {
long file_size;
@@ -1576,6 +1597,12 @@ private void put_time(ByteBuffer res, long time) {
case FILE_READDIR: {
final String dir_name = IO.strcpy(buf);
+
+ if (dir_name.startsWith(RESOURCE_PREFIX)) {
+ ClassPathResource.listdir(this, dir_name.substring(RESOURCE_PREFIX.length()));
+ return;
+ }
+
//final File cwd = new File(System.getProperty("user.dir")).getAbsoluteFile();
final File dir = ERT.newFile(/*cwd, */dir_name);
@@ -1618,21 +1645,7 @@ public void ready() throws Pausable {
return;
}
- for (int i = 0; i < files.length; i++) {
- ByteBuffer resbuf = ByteBuffer.allocate(files[i].length()+1);
- resbuf.put(FILE_RESP_OK);
- resbuf.limit(resbuf.capacity());
- resbuf.position(1);
-
- IO.putstr(resbuf, files[i], false);
-
- driver_output2(resbuf, null);
- }
-
- ByteBuffer resbuf = ByteBuffer.allocate(1);
- resbuf.put(FILE_RESP_OK);
- driver_output2(resbuf, null);
-
+ reply_list_directory(files);
}
};
break;
@@ -1882,5 +1895,22 @@ public String toString() {
return "EFile[name=\""+name+"\";pos="+pos+"]";
}
+
+ void reply_list_directory(String[] files) throws Pausable {
+ for (int i = 0; i < files.length; i++) {
+ ByteBuffer resbuf = ByteBuffer.allocate(files[i].length()+1);
+ resbuf.put(FILE_RESP_OK);
+ resbuf.limit(resbuf.capacity());
+ resbuf.position(1);
+
+ IO.putstr(resbuf, files[i], false);
+
+ driver_output2(resbuf, null);
+ }
+
+ ByteBuffer resbuf = ByteBuffer.allocate(1);
+ resbuf.put(FILE_RESP_OK);
+ driver_output2(resbuf, null);
+ }
}
Please sign in to comment.
Something went wrong with that request. Please try again.