/** scripts are allowed to make XMLRPC/SOAP calls to their origin address, even if it is firewalled */
public static java.net.InetAddress originAddr = null;
+ /** the URL where the initial xwar came from */
+ public static String origin = null;
+
/** see Template.numUnits() for a description */
public static int instantiatedUnits = 0;
if (args.length > startargs) {
if (args[startargs].startsWith("http://")) {
if (Log.on) Log.log(Main.class, "downloading xwar");
+ origin = args[startargs];
URL u = new URL(args[startargs]);
try {
originAddr = InetAddress.getByName(u.getHost());
Resources.loadArchive(new HTTP(args[startargs]).getInputStream());
} else {
-
if (Log.on) Log.log(Main.class, "loading xwar from local filesystem");
// HACK because MSIE turns \'s into /'s in URLs... argh!!
if (Platform.platform.getClass().getName().endsWith("Win32"))
args[startargs] = args[startargs].replace('/', '\\');
File f = new File(args[startargs]);
+ origin = "file://" + f.getAbsolutePath();
if (f.isDirectory()) Resources.loadDirectory(f);
else Resources.loadArchive(new FileInputStream(f));
}
/** Returns null if XWT should always use direct connection; otherwise returns a ProxyInfo object with proxy settings */
protected synchronized HTTP.ProxyInfo _detectProxy() { return null; }
- /** displays a platform-specific "open file" dialog and returns the chosen filename */
+ /** displays a platform-specific "open file" dialog and returns the chosen filename, or null if the user hit cancel */
protected String _fileDialog(String suggestedFileName, boolean write) { return null; }
/** returns true iff the platform has a case-sensitive filesystem */
/** returns true iff the platform has a case-sensitive filesystem */
public static boolean isCaseSensitive() { return platform._isCaseSensitive(); }
- /** displays a platform-specific "open file" dialog and returns the chosen filename */
+ /** displays a platform-specific "open file" dialog and returns the chosen filename, or null if the user hit cancel */
public static String fileDialog(String suggestedFileName, boolean write) {
- // put ourselves in the background
- Thread thread = Thread.currentThread();
- if (!(thread instanceof ThreadMessage)) {
- if (Log.on) Log.log(Platform.class, "xwt.openFile may only be called from background threads");
- return null;
- }
- ThreadMessage mythread = (ThreadMessage)thread;
- mythread.setPriority(Thread.MIN_PRIORITY);
- mythread.done.release();
-
+ if (!ThreadMessage.suspendThread()) return null;
try {
return platform._fileDialog(suggestedFileName, write);
} finally {
- // okay, let ourselves be brought to the foreground
- MessageQueue.add(mythread);
- mythread.setPriority(Thread.NORM_PRIORITY);
- mythread.go.block();
+ ThreadMessage.resumeThread();
}
}
try {
sb.append(" <" + name + " xsi:type=\"SOAP-ENC:base64\">");
InputStream is = ((ByteStream)o).getInputStream();
- byte[] buf = new byte[96];
+ byte[] buf = new byte[54];
while(true) {
- int numread = is.read(buf, 0, 96);
+ int numread = is.read(buf, 0, 54);
if (numread == -1) break;
byte[] writebuf = buf;
if (numread < buf.length) {
ret.f = f;
MessageQueue.add(ret);
}
+
+ /** attempts to put this thread into the background to perform a blocking operation; returns false if unable to do so */
+ public static boolean suspendThread() {
+ // put ourselves in the background
+ Thread thread = Thread.currentThread();
+ if (!(thread instanceof ThreadMessage)) {
+ Context cx = Context.enter();
+ if (Log.on) Log.log(ThreadMessage.class, "attempt to perform background-only operation in a foreground thread at " +
+ cx.interpreterSourceFile + ":" + cx.interpreterLine);
+ return false;
+ }
+ ThreadMessage mythread = (ThreadMessage)thread;
+ mythread.setPriority(Thread.MIN_PRIORITY);
+ mythread.done.release();
+ return true;
+ }
+
+ /** re-enqueues this thread */
+ public static void resumeThread() {
+ ThreadMessage mythread = (ThreadMessage)Thread.currentThread();
+ MessageQueue.add(mythread);
+ mythread.setPriority(Thread.NORM_PRIORITY);
+ mythread.go.block();
+ }
public void run() {
try {
try {
sb.append(" <value><base64>");
InputStream is = ((ByteStream)o).getInputStream();
- byte[] buf = new byte[96];
+ byte[] buf = new byte[54];
while(true) {
- int numread = is.read(buf, 0, 96);
+ int numread = is.read(buf, 0, 54);
if (numread == -1) break;
byte[] writebuf = buf;
if (numread < buf.length) {
public final Object call(Context cx, Scriptable scope, Scriptable thisObj, java.lang.Object[] args) throws JavaScriptException {
- // put ourselves in the background
- Thread thread = Thread.currentThread();
- if (!(thread instanceof ThreadMessage)) {
- if (Log.on) Log.log(this, "RPC calls may only be made from background threads");
- return null;
- }
- ThreadMessage mythread = (ThreadMessage)thread;
- mythread.setPriority(Thread.MIN_PRIORITY);
- mythread.done.release();
+ if (!ThreadMessage.suspendThread()) return null;
try {
return call(args);
-
} catch (IOException se) {
if (Log.on) Log.log(this, se);
if (Log.on) Log.log(this, " at " + cx.interpreterSourceFile + ":" + cx.interpreterLine);
if (Log.on) Log.log(this, " at " + cx.interpreterSourceFile + ":" + cx.interpreterLine);
}
throw jse;
-
} finally {
- // okay, let ourselves be brought to the foreground
- MessageQueue.add(mythread);
- mythread.setPriority(Thread.NORM_PRIORITY);
- mythread.go.block();
+ ThreadMessage.resumeThread();
}
}
else if (name.equals("newBox")) return newBox;
else if (name.equals("soap")) return soap;
else if (name.equals("xmlrpc")) return xmlrpc;
+ else if (name.equals("origin")) return Main.origin;
else if (name.equals("clipboard")) return Platform.getClipBoard();
else if (name.equals("altKeyName")) return Platform.altKeyName();
else if (name.equals("screenWidth")) return new Integer(Platform.getScreenWidth());
private static final JSFunction openFile = new JSFunction() {
public Object call(Context cx, Scriptable thisObj, Scriptable ctorObj, Object[] args) throws JavaScriptException {
- if (args == null || args.length != 1) return null;
+ if (args.length != 1) return null;
String file = Platform.fileDialog(args[0].toString(), false);
return file == null ? null : new ByteStream(file);
}
private static final JSFunction saveFile = new JSFunction() {
public Object call(Context cx, Scriptable thisObj, Scriptable ctorObj, Object[] args) throws JavaScriptException {
- if (args == null || args.length != 2) return null;
+ if (args.length != 2) return null;
if (!(args[1] instanceof ByteStream)) return null;
String file = args[0].toString();
if (safeFiles.get(Platform.isCaseSensitive() ? file : file.toLowerCase()) == null) {
file = Platform.fileDialog(file, true);
if (file == null) return null;
- System.out.println(">>" + file + "<<");
safeFiles.put(Platform.isCaseSensitive() ? file : file.toLowerCase(), new Object());
}
try {
- System.out.println("WRITING TO " + file);
((ByteStream)args[1]).writeTo(new FileOutputStream(file));
return null;
} catch (IOException e) {
private static final JSFunction saveFileAs = new JSFunction() {
public Object call(Context cx, Scriptable thisObj, Scriptable ctorObj, Object[] args) throws JavaScriptException {
- if (args == null || args.length != 2) return null;
+ if (args.length != 2) return null;
if (!(args[1] instanceof ByteStream)) return null;
String file = args[0].toString();
file = Platform.fileDialog(file, true);
return 0;
}
- static class Open extends FileDialog implements WindowListener, ComponentListener {
+ static class FileDialogHelper extends FileDialog implements WindowListener, ComponentListener {
Semaphore s;
- public Open(String suggestedFileName, Semaphore s, boolean write) {
+ public FileDialogHelper(String suggestedFileName, Semaphore s, boolean write) {
super(new Frame(), suggestedFileName, write ? FileDialog.SAVE : FileDialog.LOAD);
this.s = s;
+ addWindowListener(this);
+ addComponentListener(this);
+ show();
}
public void windowActivated(WindowEvent e) { }
public void windowClosed(WindowEvent e) { s.release(); }
};
protected String _fileDialog(String suggestedFileName, boolean write) {
- Semaphore s = new Semaphore();
- Open fd = new Open(suggestedFileName, s, write);
- fd.addWindowListener(fd);
- fd.addComponentListener(fd);
- fd.show();
+ final Semaphore s = new Semaphore();
+ FileDialogHelper fd = new FileDialogHelper(suggestedFileName, s, write);
s.block();
return fd.getDirectory() + File.separatorChar + fd.getFile();
}
- protected void _saveFile(String suggestedFileName, ByteStream data) throws IOException { }
// Inner Classes /////////////////////////////////////////////////////////////////////////////////////
ofn.nMaxFile = 1024;
if (write) ofn.Flags |= OFN_OVERWRITEPROMPT;
- ofn.Flags |= OFN_NOCHANGEDIR;
ofn.Flags |= OFN_HIDEREADONLY;
int ret = write ? GetSaveFileName(&ofn) : GetOpenFileName(&ofn);