Mercurial Hosting > luan
changeset 1842:22f73129eb4a
add load_jar
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sat, 01 Feb 2025 16:54:41 -0700 |
parents | 08d650b31a80 |
children | 833096ee8c89 |
files | src/goodjava/io/FileClassLoader.java src/luan/Luan.java src/luan/modules/IoLuan.java src/luan/modules/JavaLuan.java src/luan/modules/Package.luan src/luan/modules/PackageLuan.java |
diffstat | 6 files changed, 113 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
diff -r 08d650b31a80 -r 22f73129eb4a src/goodjava/io/FileClassLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/goodjava/io/FileClassLoader.java Sat Feb 01 16:54:41 2025 -0700 @@ -0,0 +1,73 @@ +package goodjava.io; + +import java.io.File; +import java.io.FileInputStream; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.MalformedURLException; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; + + +public class FileClassLoader extends URLClassLoader { + + public static final class FileInfo { + public final File file; + private final long checksum; + + public FileInfo(File file) throws IOException { + this.file = file; + this.checksum = IoUtils.checksum( new BufferedInputStream( new FileInputStream(file) ) ); + } + + public boolean equals(Object obj) { + if( !(obj instanceof FileInfo) ) + return false; + FileInfo fi = (FileInfo)obj; + return this.checksum==fi.checksum && this.file.getName().equals(fi.file.getName()); + } + + public int hashCode() { + return (int)checksum; + } + } + + private static URL[] toURLs(List<FileInfo> files) { + int n = files.size(); + URL[] urls = new URL[n]; + for( int i=0; i<n; i++ ) { + try { + urls[i] = files.get(i).file.toURI().toURL(); + } catch(MalformedURLException e) { + throw new RuntimeException(e); + } + } + return urls; + } + + private final List<FileInfo> files; + + private FileClassLoader(List<FileInfo> files) { + super(toURLs(files)); + this.files = new ArrayList<FileInfo>(files); + } + + public List<FileInfo> getFiles() { + return new ArrayList<FileInfo>(files); + } + + private static final Map<List<FileInfo>,FileClassLoader> map = new HashMap<List<FileInfo>,FileClassLoader>(); + + public static synchronized FileClassLoader getFileClassLoader(List<FileInfo> files) { + FileClassLoader fcl = map.get(files); + if( fcl == null ) { + fcl = new FileClassLoader(files); + map.put(fcl.files,fcl); + } + return fcl; + } +}
diff -r 08d650b31a80 -r 22f73129eb4a src/luan/Luan.java --- a/src/luan/Luan.java Thu Jan 30 20:55:05 2025 -0700 +++ b/src/luan/Luan.java Sat Feb 01 16:54:41 2025 -0700 @@ -1,6 +1,7 @@ package luan; import java.lang.reflect.Array; +import java.io.File; import java.io.IOException; import java.util.List; import java.util.ArrayList; @@ -11,7 +12,9 @@ import java.util.Arrays; import java.util.Set; import java.util.Collection; +import java.util.Collections; import javax.tools.ToolProvider; +import goodjava.io.FileClassLoader; import goodjava.logging.Logger; import goodjava.logging.LoggerFactory; import luan.modules.JavaLuan; @@ -23,18 +26,22 @@ public final class Luan { private static final Logger logger = LoggerFactory.getLogger(Luan.class); + private static final FileClassLoader emptyClassLoader = FileClassLoader.getFileClassLoader( Collections.emptyList() ); private final List<LuanClosure> stack = new ArrayList<LuanClosure>(); private final Map registry; private final Map localOnly = new HashMap(); + private FileClassLoader classLoader; public Luan() { - registry = new HashMap(); + this.registry = new HashMap(); + this.classLoader = emptyClassLoader; } public Luan(Luan luan) { LuanMutable.makeImmutable(luan.registry); this.registry = clone(luan.registry); + this.classLoader = luan.classLoader; } private static Object[] clone(Object[] obj) { @@ -475,4 +482,20 @@ return (Security)luan.registry().put(SECURITY_KEY,s); } + + // jars + + public ClassLoader getClassLoader() { + return classLoader; + } + + public void addJar(File jar) throws IOException { + FileClassLoader.FileInfo file = new FileClassLoader.FileInfo(jar); + List<FileClassLoader.FileInfo> files = classLoader.getFiles(); + if( files.contains(file) ) + return; + files.add(file); + classLoader = FileClassLoader.getFileClassLoader(files); + } + }
diff -r 08d650b31a80 -r 22f73129eb4a src/luan/modules/IoLuan.java --- a/src/luan/modules/IoLuan.java Thu Jan 30 20:55:05 2025 -0700 +++ b/src/luan/modules/IoLuan.java Sat Feb 01 16:54:41 2025 -0700 @@ -136,7 +136,7 @@ } - private static File objToFile(Luan luan,Object obj) throws LuanException { + static File objToFile(Luan luan,Object obj) throws LuanException { if( obj instanceof String ) { String fileName = (String)obj; check(luan,"file:"+fileName);
diff -r 08d650b31a80 -r 22f73129eb4a src/luan/modules/JavaLuan.java --- a/src/luan/modules/JavaLuan.java Thu Jan 30 20:55:05 2025 -0700 +++ b/src/luan/modules/JavaLuan.java Sat Feb 01 16:54:41 2025 -0700 @@ -347,7 +347,11 @@ try { cls = Thread.currentThread().getContextClassLoader().loadClass(name); } catch(ClassNotFoundException e2) { - return null; + try { + cls = luan.getClassLoader().loadClass(name); + } catch(ClassNotFoundException e3) { + return null; + } } } return new Static(cls);
diff -r 08d650b31a80 -r 22f73129eb4a src/luan/modules/Package.luan --- a/src/luan/modules/Package.luan Thu Jan 30 20:55:05 2025 -0700 +++ b/src/luan/modules/Package.luan Sat Feb 01 16:54:41 2025 -0700 @@ -6,6 +6,7 @@ local Package = {} Package.load = PackageLuan.load +Package.load_jar = PackageLuan.load_jar local loaded = PackageLuan.loaded -- returns java map local mt = {}
diff -r 08d650b31a80 -r 22f73129eb4a src/luan/modules/PackageLuan.java --- a/src/luan/modules/PackageLuan.java Thu Jan 30 20:55:05 2025 -0700 +++ b/src/luan/modules/PackageLuan.java Sat Feb 01 16:54:41 2025 -0700 @@ -2,6 +2,7 @@ import java.io.Reader; import java.io.InputStreamReader; +import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Collections; @@ -113,4 +114,12 @@ } } + public static void load_jar(Luan luan,Object jar) throws LuanException, IOException { + Luan.checkSecurity(luan,"java"); + File file = IoLuan.objToFile(luan,jar); + if( file==null ) + throw new LuanException( "bad argument #1 to 'load_jar' (string or file table expected)" ); + luan.addJar(file); + } + }