001: package kawa.standard;
002:
003: import java.io.*;
004: import gnu.bytecode.ZipLoader;
005: import gnu.mapping.*;
006: import gnu.expr.*;
007: import gnu.text.SourceMessages;
008: import gnu.text.SyntaxException;
009: import gnu.lists.*;
010: import gnu.text.*;
011: import java.net.URL;
012:
013: public class load extends Procedure1 {
014: boolean relative;
015:
016: public load(String name, boolean relative) {
017: super (name);
018: this .relative = relative;
019: }
020:
021: public static final load load = new load("load", false);
022: public static final load loadRelative = new load("load-relative",
023: true);
024:
025: /** Load using the name of a compile .class file. */
026: /* This should probably be re-written to use a ClassLoader, unless '.'
027: * is in the CLASSPATH, since it a bit ugly that load of a source file
028: * or .zip file reads a file (using a relative or absolute file name),
029: * while load of a compiled .class uses the classpath. */
030: public final static void loadClassFile(String name, Environment env) {
031: Environment orig_env = Environment.getCurrent();
032: try {
033: if (env != orig_env)
034: Environment.setCurrent(env);
035: Class clas = Class.forName(name);
036: Object inst = clas.newInstance();
037: gnu.kawa.reflect.ClassMemberLocation.defineAll(inst, env);
038: if (inst instanceof Runnable)
039: ((Runnable) inst).run();
040: } catch (Throwable ex) {
041: throw new WrappedException("exception during load of \""
042: + name + '\"', ex);
043: } finally {
044: if (env != orig_env)
045: Environment.setCurrent(orig_env);
046: }
047: }
048:
049: public final static void loadCompiled(Path path, Environment env)
050: throws Throwable {
051: Environment orig_env = Environment.getCurrent();
052: String name = path.toString();
053: try {
054: if (env != orig_env)
055: Environment.setCurrent(env);
056: if (!(path instanceof FilePath))
057: throw new RuntimeException("load: " + name
058: + " - not a file path");
059: File zfile = ((FilePath) path).toFile();
060: if (!zfile.exists())
061: throw new RuntimeException("load: " + name
062: + " - not found");
063: if (!zfile.canRead())
064: throw new RuntimeException("load: " + name
065: + " - not readable");
066: ZipLoader loader = new ZipLoader(name);
067: Class clas = loader.loadAllClasses();
068: Object proc = clas == null ? null : clas.newInstance();
069: if (!(proc instanceof ModuleBody))
070: throw new RuntimeException("load: " + name
071: + " - no module in archive");
072: gnu.kawa.reflect.ClassMemberLocation.defineAll(proc, env);
073: ((ModuleBody) proc).run();
074: } catch (java.io.IOException ex) {
075: throw new WrappedException("load: " + name + " - "
076: + ex.toString(), ex);
077: } catch (InstantiationException ex) {
078: throw new WrappedException(
079: "class not instantiable: in load", ex);
080: } catch (IllegalAccessException ex) {
081: throw new WrappedException("class illegal access: in load",
082: ex);
083: } finally {
084: if (env != orig_env)
085: Environment.setCurrent(orig_env);
086: }
087: }
088:
089: public final static void loadSource(InPort port, Environment env,
090: URL url) throws SyntaxException, Throwable {
091: boolean print = ModuleBody.getMainPrintValues();
092: Language language = Language.getDefaultLanguage();
093: Consumer out = (print ? kawa.Shell.getOutputConsumer(OutPort
094: .outDefault()) : new VoidConsumer());
095: // Reading the entire file and evaluting it as a unit is more
096: // consistent with compiled code, and more efficient.
097: // Unfortunately, it is difficult to get macros to work properly.
098: // So instead, we read and evaluate each line individually.
099: if (true) {
100: kawa.Shell.run(language, env, port, out, OutPort
101: .errDefault(), url);
102: } else {
103: SourceMessages messages = new SourceMessages();
104: Compilation comp = language.parse(port, messages,
105: Language.PARSE_IMMEDIATE);
106: ModuleExp mexp = comp.getModule();
107: CallContext ctx = CallContext.getInstance();
108: Consumer save = ctx.consumer;
109: try {
110: ctx.consumer = out;
111: ctx.values = Values.noArgs;
112: ModuleExp.evalModule(env, ctx, comp, url, null);
113: if (messages.seenErrors())
114: throw new SyntaxException(messages);
115: } finally {
116: ctx.consumer = save;
117: }
118: }
119: }
120:
121: public final Object apply1(Object arg1) throws Throwable {
122: return apply2(arg1, Environment.getCurrent());
123: }
124:
125: public final Object apply2(Object name, Object arg2)
126: throws Throwable {
127: try {
128: Environment env = (Environment) arg2;
129: apply(Path.valueOf(name), env, relative, 0);
130: return Values.empty;
131: } catch (java.io.FileNotFoundException e) {
132: throw new RuntimeException("load: file not readable: "
133: + name);
134: } catch (SyntaxException ex) {
135: throw new RuntimeException("load: errors while compiling '"
136: + name + "':\n" + ex.getMessages().toString(20));
137: }
138: }
139:
140: public static final void apply(Path path, Environment env,
141: boolean relative, int skipLines) throws Throwable {
142: String name = path.toString();
143: if (name.endsWith(".zip") || name.endsWith(".jar")) {
144: loadCompiled(path, env);
145: return;
146: }
147: URL url = path.toURL();
148: char file_separator = System.getProperty("file.separator")
149: .charAt(0);
150:
151: if (name.endsWith(".class")) {
152: name = name.substring(0, name.length() - 6);
153: name = name.replace('/', '.');
154: if (file_separator != '/')
155: name = name.replace(file_separator, '.');
156: loadClassFile(name, env);
157: return;
158: }
159: InputStream fs = new BufferedInputStream(path.openInputStream());
160: fs.mark(5);
161: int char0 = fs.read();
162: if (char0 == -1)
163: return; // Sequence.eofValue;
164: if (char0 == 'P') {
165: int char1 = fs.read();
166: if (char1 == 'K') {
167: int char2 = fs.read();
168: if (char2 == '\003') {
169: int char3 = fs.read();
170: if (char3 == '\004') {
171: fs.close();
172: loadCompiled(path, env);
173: return;
174: }
175: }
176: }
177: }
178: fs.reset();
179: InPort src = InPort.openFile(fs, path);
180: while (--skipLines >= 0)
181: src.skipRestOfLine();
182: loadSource(src, env, url);
183: src.close();
184: }
185: }
|