Files
cappuccino/Tools/Utilities/bridge.js
T

677 lines
17 KiB
JavaScript

if (typeof debug == "undefined")
debug = false;
//window
if (!this.window)
this.window = this;
// DOMParser
/*function DOMParser() {};
DOMParser.prototype.parseFromString = function(text, contentType) {
return new DOMDocument(
new Packages.org.xml.sax.InputSource(
new Packages.java.io.StringReader(text)));
};*/
// Image
function Image() { }
// print, alert, prompt, confirm
if (!this.print)
{
if (this.Packages)
{
this.print = function(object)
{
Packages.java.lang.System.out.println(String(object));
}
}
}
window.alert = function(obj)
{
if (this.print)
print(String(obj));
}
// FIXME: prompt user for response?
window.confirm = function(obj)
{
window.alert(obj);
return true;
}
window.prompt = function(obj)
{
window.alert(obj);
return "";
}
// setTimeout, setInterval, clearTimeout, clearInterval
// This implementation is single-threaded (like browsers) but requires a call to serviceTimeouts()
// Also includes beginning of a multithreaded implementation (commented out)
window.setNativeTimeout = function(callback, delay)
{
return _scheduleTimeout(callback, delay, false);
}
window.setTimeout = window.setNativeTimeout;
window.setNativeInterval = function(callback, delay)
{
return _scheduleTimeout(callback, delay, true);
}
window.setInterval = window.setInterval;
window.clearTimeout = function(id)
{
if (_timeouts[id])
_timeouts[id] = null;
}
window.clearInterval = window.clearTimeout;
var _nextId = 0,
_timeouts = {},
_pendingTimeouts = [];
var _scheduleTimeout = function(callback, delay, repeat)
{
var date = new Date(new Date().getTime() + delay);
if (typeof callback == "function")
var func = callback;
else if (typeof callback == "string")
var func = new Function(callback);
else
return;
var timeout = {
callback: func,
date: date,
repeat: repeat,
interval: delay,
id : _nextId++
}
_timeouts[timeout.id] = timeout;
_pendingTimeouts.push(timeout);
// if (!_timersBlock)
// serviceTimeouts();
return timeout.id;
}
var _sortTimeouts = function()
{
}
//var _timersBlock = false,
// _timerThread = null,
// _nextTimeout = null;
function serviceTimeouts()
{
while (_pendingTimeouts.length > 0)
{
_pendingTimeouts = _pendingTimeouts.sort(function (a,b) { return a.date - b.date; });
var timeout = _pendingTimeouts.shift();
if (_timeouts[timeout.id])
{
var wait = timeout.date - new Date();
if (wait > 0)
{
//if (_timersBlock)
//{
Packages.java.lang.Thread.sleep(wait);
//}
//else
//{
// _pendingTimeouts.splice(0, 0, timeout);
//
// if (!_nextTimeout || _nextTimeout > timeout.date)
// {
// _nextTimeout = timeout.date;
//
//
// _timerThread = new java.lang.Thread(new java.lang.Runnable({
// run: function() {
// Packages.java.lang.Thread.sleep(wait);
// _nextTimeout = null;
// serviceTimeouts();
// }
// }));
//
// _timerThread.start();
// }
//
// return;
//}
}
// perform the callback
timeout.callback();
// if its an interval, reschedule it, otherwise clear it
if (timeout.repeat)
{
var now = new Date(),
proposed = new Date(timeout.date.getTime() + timeout.interval);
timeout.date = (proposed < now) ? now : proposed;
_pendingTimeouts.push(timeout);
}
else
_timeouts[timeout.id] = null;
}
}
}
// load
if (!this.load)
{
if (debug)
alert("Setting up 'load()'");
this.load = function(path)
{
var contents = readFile(path);
if (typeof Packages !== "undefined")
return Packages.org.mozilla.javascript.Context.getCurrentContext().evaluateString(window, contents, path, 0, null);
else
return eval(contents);
}
}
// readFile
if (!this.readFile)
{
if (this.File)
{
if (debug)
alert("Setting up 'readFile()' for SpiderMonkey");
this.readFile = function(path)
{
var f = new File(path);
if (!f.canRead)
{
if (debug)
alert("can't read: " + f.path);
return "";
}
if (debug)
alert("reading: " + f.path);
f.open("read", "text");
var result = f.readAll().join("\n");
f.close();
return result;
}
}
else if (this.Packages)
{
if (debug)
alert("Setting up 'readFile()' for Rhino");
this.readFile = function(path, characterCoding)
{
var f = new Packages.java.io.File(path);
if (!f.canRead())
{
if (debug)
alert("can't read: " + f.path);
return "";
}
if (debug)
alert("reading: " + f.getAbsolutePath());
var fis = new Packages.java.io.FileInputStream(f),
b = Packages.java.lang.reflect.Array.newInstance(Packages.java.lang.Byte.TYPE, fis.available());
fis.read(b);
fis.close();
if (characterCoding)
return String(new Packages.java.lang.String(b, characterCoding));
else
return String(new Packages.java.lang.String(b));
}
}
else
{
alert("Warning: No 'readFile' implementation available.")
}
}
var hex_lookup = "0123456789abcdef";
function bytesToHexString(buf)
{
var buffer = "";
for (var i = 0 ; i < buf.length; i++)
buffer += hex_lookup[(buf[i] >> 4) & 0x0F] + hex_lookup[buf[i] & 0x0F];
return buffer;
}
// Rhino utilities
if (this.Packages) {
if (debug)
alert("Setting up Rhino utilties");
jsArrayToJavaArray = function(js_array, type)
{
var java_class = null;
var java_converter = null;
switch (type || ((js_array && js_array.length > 0) && typeof js_array[0]))
{
case "string":
case "String":
java_class = Packages.java.lang.String;
java_converter = Packages.java.lang.String.valueOf;
break;
case "Boolean":
java_class = Packages.java.lang.Boolean;
java_converter = Packages.java.lang.Boolean.valueOf;
break;
case "boolean":
java_class = Packages.java.lang.Boolean.TYPE;
java_converter = function(input) { return Packages.java.lang.Boolean.valueOf(input).booleanValue(); };
break;
default:
return null;
}
if (js_array && js_array.length > 0)
{
var java_array = Packages.java.lang.reflect.Array.newInstance(java_class, js_array.length);
for (var i = 0; i < js_array.length; i++)
java_array[i] = java_converter ? java_converter(js_array[i]) : js_array[i];
return java_array;
}
return Packages.java.lang.reflect.Array.newInstance(java_class, 0);
}
jsObjectToJavaHashMap = function(js_object)
{
var map = Packages.java.util.HashMap();
for (var i in js_object)
map.put(i, js_object[i]);
return map;
}
objj_console = function()
{
var br = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(Packages.java.lang.System["in"], "UTF-8"));
keepgoing = true;
while (keepgoing)
{
try {
Packages.java.lang.System.out.print("objj> ");
var input = String(br.readLine()),
fragments = objj_preprocess(input, new objj_bundle(), new objj_file(), OBJJ_PREPROCESSOR_DEBUG_SYMBOLS),
count = fragments.length,
ctx = (new objj_context);
if (count == 1 && (fragments[0].type & FRAGMENT_CODE))
{
var fragment = fragments[0];
var result = eval(fragment.info);
if (result != undefined)
print(result);
}
else if (count > 0)
{
while (count--)
{
var fragment = fragments[count];
if (fragment.type & FRAGMENT_FILE)
objj_request_file(fragment.info, (fragment.type & FRAGMENT_LOCAL), NULL);
ctx.pushFragment(fragment);
}
ctx.schedule();
}
serviceTimeouts();
} catch (e) {
print(e);
}
}
};
var _documentBuilderFactory = Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance();
// setValidating to false doesn't seem to prevent it from downloading the DTD, but lets do it anyway
_documentBuilderFactory.setValidating(false);
_documentBuilder = _documentBuilderFactory.newDocumentBuilder();
// prevent the Java XML parser from downloading the plist DTD from Apple every time we parse a plist
_documentBuilder.setEntityResolver(new Packages.org.xml.sax.EntityResolver({
resolveEntity: function(publicId, systemId) {
//Packages.java.lang.System.out.println("publicId=" + publicId + " systemId=" + systemId);
// TODO: return a local copy of the DTD?
if (String(systemId) == "http://www.apple.com/DTDs/PropertyList-1.0.dtd")
return new Packages.org.xml.sax.InputSource(new Packages.java.io.StringReader(""));
return null;
}
}));
// throw an exception on error
_documentBuilder.setErrorHandler(function(exception, methodName) {
throw exception;
});
copyInputStreamToOutputStream = function(is, os)
{
var buf = Packages.java.lang.reflect.Array.newInstance(Packages.java.lang.Byte.TYPE, 1024*10);
var len = 0;
while ((len = is.read(buf)) != -1)
{
os.write(buf, 0, len);
}
}
var lineEnd = "\r\n";
var twoHyphens = "--";
var boundary = "----------------------------b453b5d52446";
//var boundary = "----CappuccinoBoundary" + (new Date().getTime());
multipartRequest = function(method, url, headers, parts)
{
var bufferSize = 1024*10,
buffer = Packages.java.lang.reflect.Array.newInstance(Packages.java.lang.Byte.TYPE, bufferSize);
var url = new Packages.java.net.URL(url),
connection = url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod(method);
for (var i in headers)
{
print(i+":"+headers[i]);
connection.setRequestProperty(i, headers[i]);
}
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary="+ boundary);
var output = new Packages.java.io.DataOutputStream(connection.getOutputStream());
for (var i = 0; parts && i < parts.length; i++)
{
var part = parts[i];
output.writeBytes(twoHyphens + boundary + lineEnd);
if (part.headers)
{
for (var header in part.headers)
{
output.writeBytes(header +": " + part.headers[header] + lineEnd);
}
}
output.writeBytes(lineEnd);
if (part.data)
{
output.writeBytes(part.data);
}
else if (part.stream)
{
var n;
while ((n = part.stream.read(buffer, 0, bufferSize)) > 0)
{
output.write(buffer, 0, n)
}
}
output.writeBytes(lineEnd);
}
output.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
output.flush();
output.close();
var buffer,
input = new Packages.java.io.DataInputStream(connection.getInputStream()),
result = new Packages.java.lang.StringBuffer();
while (null != (buffer = input.readLine()))
result.append(buffer);
input.close();
return String(result.toString());
}
parseXMLString = function(string) {
return (_documentBuilder.parse(
new Packages.org.xml.sax.InputSource(
new Packages.java.io.StringReader(string))).getDocumentElement());
}
}
// Environment variables
function getenv(variable)
{
if (this.Packages)
return String(Packages.java.lang.System.getenv().get(variable) || "") || null;
else if (this.environment)
return environment[variable] || null;
return null;
}
// XMLHttpRequest
function XMLHttpRequest()
{
this.readyState = 0;
this.responseText = "";
this.responseXML = null;
this.status = null;
this.statusText = null;
this.onreadystatechange = null;
this.method = null;
this.url = null;
this.async = null;
this.username = null;
this.password = null;
}
XMLHttpRequest.prototype.abort = function()
{
this.readyState = 0;
}
XMLHttpRequest.prototype.open = function(method, url, async, username, password)
{
this.readyState = 1;
this.method = method;
this.url = url;
this.async = async;
this.username = username;
this.password = password;
}
XMLHttpRequest.prototype.send = function(body)
{
this.readyState = 3;
this.responseText = "";
this.responseXML = null;
try
{
this.responseText = readFile(this.url, "UTF-8"); // FIXME: should we really assume this is UTF-8?
if (debug)
alert("xhr response: " + this.url + " (length="+this.responseText.length+")");
}
catch (e)
{
if (debug)
alert("xhr exception: " + this.url);
this.responseText = "";
this.responseXML = null;
}
if (this.responseText.length > 0)
{
try
{
this.responseXML = _documentBuilder.parse(new Packages.org.xml.sax.InputSource(new Packages.java.io.StringReader(this.responseText)));
}
catch (e)
{
this.responseXML = null;
}
this.status = 200;
}
else {
if (debug)
alert("xhr empty: " + this.url);
this.status = 404;
}
this.readyState = 4;
if (this.onreadystatechange)
{
if (this.async)
setNativeTimeout(this.onreadystatechange, 0);
else
this.onreadystatechange();
}
}
XMLHttpRequest.prototype.getResponseHeader = function(header)
{
return (this.readyState < 3) ? "" : "";
}
XMLHttpRequest.prototype.getAllResponseHeaders = function()
{
return (this.readyState < 3) ? null : "";
}
XMLHttpRequest.prototype.setRequestHeader = function(name, value)
{
}
objj_request_xmlhttp = function()
{
return new XMLHttpRequest();
}
OBJJ_HOME = getenv("OBJJ_HOME");
if (!OBJJ_HOME)
{
OBJJ_HOME = "/usr/local/share/objj";
alert("OBJJ_HOME environment variable not set, defaulting to " + OBJJ_HOME);
}
function exec(/*Array*/ command, /*Boolean*/ showOutput)
{
var line = "",
output = "",
process = Packages.java.lang.Runtime.getRuntime().exec(command),//jsArrayToJavaArray(command));
reader = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(process.getInputStream()));
while (line = reader.readLine())
{
if (showOutput)
Packages.java.lang.System.out.println(line);
output += line + '\n';
}
reader = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(process.getErrorStream()));
while (line = reader.readLine())
Packages.java.lang.System.out.println(line);
try
{
if (process.waitFor() != 0)
Packages.java.lang.System.err.println("exit value = " + process.exitValue());
}
catch (anException)
{
Packages.java.lang.System.err.println(anException);
}
return output;
}
function getFiles(/*File*/ sourceDirectory, /*nil|String|Array<String>*/ extensions, /*Array*/ exclusions)
{
var matches = [],
files = sourceDirectory.listFiles(),
hasMultipleExtensions = typeof extensions !== "string";
if (files)
{
var index = 0,
count = files.length;
for (; index < count; ++index)
{
var file = files[index].getCanonicalFile(),
name = String(file.getName()),
isValidExtension = !extensions;
if (exclusions && fileArrayContainsFile(exclusions, file))
continue;
if (!isValidExtension)
if (hasMultipleExtensions)
{
var extensionCount = extensions.length;
while (extensionCount-- && !isValidExtension)
{
var extension = extensions[extensionCount];
if (name.substring(name.length - extension.length - 1) === ("." + extension))
isValidExtension = true;
}
}
else if (name.substring(name.length - extensions.length - 1) === ("." + extensions))
isValidExtension = true;
if (isValidExtension)
matches.push(file);
if (file.isDirectory())
matches = matches.concat(getFiles(file, extensions, exclusions));
}
}
return matches;
}