1 /*
  2  * ilib-rhino.js - glue code for rhino apps to load local ilib code and
  3  * data in a plain rhino environment. If you are using ringojs, use the
  4  * ilib-ringo.js loader instead.
  5  *
  6  * Copyright © 2015, JEDLSoft
  7  *
  8  * Licensed under the Apache License, Version 2.0 (the "License");
  9  * you may not use this file except in compliance with the License.
 10  * You may obtain a copy of the License at
 11  *
 12  *     http://www.apache.org/licenses/LICENSE-2.0
 13  *
 14  * Unless required by applicable law or agreed to in writing, software
 15  * distributed under the License is distributed on an "AS IS" BASIS,
 16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 17  *
 18  * See the License for the specific language governing permissions and
 19  * limitations under the License.
 20  */
 21 
 22 var module = {
 23     exports: {},
 24     filename:null
 25 };
 26 
 27 var console = {
 28     log: function() {
 29         print.apply(undefined, arguments);
 30     }
 31 };
 32 
 33 console.log("root environment is " + JSON.stringify(environment, undefined, 4));
 34 
 35 var requireClass = function() {
 36     this.cache = {};
 37     this.loading = {};
 38     this.updateRequire = /require\(("[^/][^"+]*")\)/g;
 39 
 40     this.root = environment["user.dir"];
 41     if (this.root[this.root.length-1] === '/') {
 42         this.root = this.normalize(this.root.substring(0,this.root.length-1));
 43     }
 44 };
 45 
 46 requireClass.prototype.dirname = function(pathname) {
 47     pathname = pathname.replace("\\", "/");
 48     var i = pathname.lastIndexOf("/");
 49     return i !== -1 ? pathname.substring(0,i) : pathname;
 50 };
 51 
 52 requireClass.prototype.normalize = function(pathname) {
 53     if (pathname) {
 54         var previousLen;
 55         pathname = pathname.replace(/\\/g, "/");
 56         do {
 57             previousLen = pathname.length;
 58             pathname = pathname.replace(/\/\//g, "/");
 59             pathname = pathname.replace(/\/[^/]*[^\./]\/\.\./g, "/.");
 60             pathname = pathname.replace(/\/\.\//g, "/");
 61             pathname = pathname.replace(/^\.\//, "");
 62             pathname = pathname.replace(/\/\.$/, "/");
 63             if (pathname.length > 1) pathname = pathname.replace(/\/$/, "");
 64             if (pathname.length === 0) pathname = '.';
 65         } while (pathname.length < previousLen);
 66     }
 67     return pathname;
 68 };
 69 
 70 requireClass.prototype._loadFile = function (pathname) {
 71     console.log("requireClass._loadFile: attempting to load " + pathname);
 72     var text = "";
 73     var reader;
 74     try {
 75         reader = new BufferedReader(new InputStreamReader(new FileInputStream(pathname), "utf-8"));
 76         var tmp;
 77         while ((tmp = reader.readLine()) !== null) {
 78             text += tmp + '\n';
 79         }
 80     } catch (e) {
 81         // ignore
 82         text = undefined;
 83     } finally {
 84         if (reader) {
 85             try {
 86                 reader.close();
 87             } catch (e2) {}
 88         }
 89         cb && typeof(cb) === 'function' && cb(text);
 90     }
 91     return text;
 92 };
 93 
 94 requireClass.prototype.require = function(parent, pathname) {
 95     console.log("------------------------\nrequire: called with " + pathname);
 96 
 97     console.log("this.root is " + this.root + " and pathname before was " + pathname);
 98     console.log("require: module.filename is " + module.filename);
 99     console.log("require: parent is " + parent);
100 
101     var base = parent || (module.filename && this.dirname(module.filename)) || this.root;
102 
103     console.log("require: base is " + base);
104 
105     if (pathname.charAt(0) !== '/') {
106         pathname = base + "/" + pathname;
107     }
108 
109     pathname = this.normalize(pathname);
110     console.log("require: pathname after is " + pathname);
111 
112     if (this.cache[pathname]) {
113         console.log("require: cache hit");
114         return this.cache[pathname];
115     }
116 
117     // don't try to load things that are currently in the process of loading
118     if (this.loading[pathname]) {
119         console.log("require: already loading...");
120         return {};
121     }
122     console.log("require: loading the file");
123 
124     try {
125         var text = this._loadFile(pathname);
126         var dirname = path.dirname(pathname);
127         var match, replacement;
128 
129         if (text) {
130             var tmp = module.filename;
131             module.filename = pathname;
132             module.exports = null;
133             this.loading[pathname] = true;
134             module.require = requireClass.prototype.require.bind(r, this.dirname(pathname));
135 
136             while ((match = this.updateRequire.exec(text)) !== null) {
137                 replacement = path.normalize(path.join(dirname, match[1]));
138                 text = text.replace(new RegExp('"' + match[1] + '"', "g"), '"' + replacement + '"');
139                 this.updateRequire.lastIndex = match.index + replacement.length + 2;
140             }
141 
142             // console.log("text is " + text);
143             try {
144                 eval(text);
145 
146                 this.cache[pathname] = module.exports;
147                 module.exports.module = {
148                     filename: pathname,
149                     require: requireClass.prototype.require.bind(r, this.dirname(pathname))
150                 };
151             } finally {
152                 this.loading[pathname] = undefined;
153                 module.filename = tmp;
154             }
155 
156             return module.exports;
157         }
158     } catch (e) {
159         console.log("Failed loading " + pathname);
160         console.log("exception was " + e);
161     }
162 
163     return undefined;
164 };
165 
166 var r = new requireClass();
167 var require = requireClass.prototype.require.bind(r, undefined);
168 
169 var RhinoLoader = require("../lib/RhinoLoader.js");
170 var ilib = require("../lib/ilib.js");
171 ilib._dyncode = true; // indicate that we are using dynamically loaded code
172 ilib._dyndata = true;
173 
174 ilib.setLoaderCallback(new RhinoLoader());