import java.util.*; import java.util.zip.*; import java.util.List; import java.util.regex.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.util.concurrent.locks.*; import java.util.function.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; import javax.swing.table.*; import java.io.*; import java.net.*; import java.lang.reflect.*; import java.lang.ref.*; import java.lang.management.*; import java.security.*; import java.security.spec.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; import java.awt.geom.*; import javax.imageio.*; import java.math.*; // uses its own transpiler so it can set options import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.nio.charset.Charset; import java.awt.geom.*; import static x30_pkg.x30_util.DynamicObject; import javax.swing.border.*; import java.awt.datatransfer.StringSelection; import javax.swing.event.AncestorListener; import javax.swing.event.AncestorEvent; import javax.swing.Timer; import javax.swing.undo.UndoManager; import javax.imageio.metadata.*; import javax.imageio.stream.*; import javax.swing.Icon; import java.nio.file.Files; import java.nio.file.Path; class main { static class SnippetTranspiler extends DynPrintLog { // API for Eleu void setEleu(Object eleu) { mainBot = eleu; } static boolean _switchableField_refreshDelay = true; int refreshDelay = 0; // seconds void start() { try { super.start(); dm_onSnippetTranspiled(new VF1() { public void get(String snippetID) { try { if (sameSnippetID(snippetID, defaultTranspilerID())) refresh(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (sameSnippetID(snippetID, defaultTranspilerID()))\r\n refresh();"; }}); } catch (Exception __e) { throw rethrow(__e); } } void refresh() { veryQuickJava_refresh(); vmBus_send("refreshedTranspiler"); print("Refreshed translator."); } Object html(IWebRequest req) { String realPW = realPW(); if (empty(realPW)) return "No password set by admin - please put password in: " + realPWFile().getAbsolutePath(); String pw = req.get("_pass"); if (empty(pw)) return "Need pw"; if (neq(pw, realPW)) { print("XXX - Alert, bad PW entered on web - XXX"); return "Bad PW, bugger"; } return dm_evalInQ(() -> snippetTranspileWebBot(req.uri(), req.params(), refreshDelay)); } File realPWFile() { return secretProgramFile("master-pw"); } String realPW() { return trim(loadTextFile(realPWFile())); } } static boolean _moduleClass_SnippetTranspiler = true; static Object mainBot; static Object getMainBot() { return mainBot; } // r : voidfunc(snippet ID), called in module queue static void dm_onSnippetTranspiled(VF1 r) { dm_requireSnippetUpdatesModule(); final DynModule m = dm_current_mandatory(); dm_vmBus_onMessage("snippetUpdate", new VF1() { public void get(final List l) { try { m.q().add(new Runnable() { public void run() { try { String uri = getString(l, 1); Matches m = new Matches(); if (swic(uri, "/transpileOK/", m)) { String snippetID = fsI(firstIntAsString(m.rest())); callF(r, snippetID); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "String uri = getString(l, 1);\r\n new Matches m;\r\n if (swic(uri, \"/transp..."; }}); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "switch to m.q();\r\n S uri = getString(l, 1);\r\n new Matches m;\r\n if (s..."; }}); } static void dm_onSnippetTranspiled(String snippetID, Runnable r) { if (empty(snippetID) || r == null) return; dm_onSnippetTranspiled(new VF1() { public void get(String snippetID2) { try { if (sameSnippetID(snippetID, snippetID2)) r.run(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (sameSnippetID(snippetID, snippetID2))\r\n r.run();"; }}); } static boolean sameSnippetID(String a, String b) { if (!isSnippetID(a) || !isSnippetID(b)) return false; return parseSnippetID(a) == parseSnippetID(b); } static String defaultTranspilerID() { return defaultJavaXTranslatorID(); } static RuntimeException rethrow(Throwable t) { if (t instanceof Error) _handleError((Error) t); throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t); } static RuntimeException rethrow(String msg, Throwable t) { throw new RuntimeException(msg, t); } // returns true if a translator had been loaded static synchronized boolean veryQuickJava_refresh() { boolean change = false; try { // TODO: Why are we dropping these? for (File f : listFiles(new File(javaxCodeDir(), "Transpilations"))) if (ewic(f.getName(), ".java")) { change = true; f.delete(); } } catch (Throwable __e) { printStackTrace(__e); } Lock lock = (Lock) (getOpt(mc(), "transpileRaw_lock")); if (lock != null) { Lock __0 = lock; lock(__0); try { Object trans = getOpt(mc(), "transpileRaw_trans"); if (trans != null) { cleanUp(trans); setOpt(mc(), "transpileRaw_trans", null); change = true; } } finally { unlock(__0); } } // Also clear standard functions callOpt(getOpt(mc(), "loadFunctions_cache"), "clear"); return change; } static void vmBus_send(String msg, Object... args) { Object arg = vmBus_wrapArgs(args); pcallFAll_minimalExceptionHandling(vm_busListeners_live(), msg, arg); pcallFAll_minimalExceptionHandling(vm_busListenersByMessage_live().get(msg), msg, arg); } static void vmBus_send(String msg) { vmBus_send(msg, (Object) null); } static volatile StringBuffer local_log = new StringBuffer(); // not redirected static boolean printAlsoToSystemOut = true; static volatile Appendable print_log = local_log; // might be redirected, e.g. to main bot // in bytes - will cut to half that static volatile int print_log_max = 1024*1024; static volatile int local_log_max = 100*1024; static boolean print_silent = false; // total mute if set static Object print_byThread_lock = new Object(); static volatile ThreadLocal print_byThread; // special handling by thread - prefers F1 static volatile Object print_allThreads; static volatile Object print_preprocess; static void print() { print(""); } static A print(String s, A o) { print(combinePrintParameters(s, o)); return o; } // slightly overblown signature to return original object... static A print(A o) { ping_okInCleanUp(); if (print_silent) return o; String s = o + "\n"; print_noNewLine(s); return o; } static void print_noNewLine(String s) { try { Object f = getThreadLocal(print_byThread_dontCreate()); if (f == null) f = print_allThreads; if (f != null) // We do need the general callF machinery here as print_byThread is sometimes shared between modules if (isFalse( f instanceof F1 ? ((F1) f).get(s) : callF(f, s))) return; } catch (Throwable e) { System.out.println(getStackTrace(e)); } print_raw(s); } static void print_raw(String s) { if (print_preprocess != null) s = (String) callF(print_preprocess, s); s = fixNewLines(s); Appendable loc = local_log; Appendable buf = print_log; int loc_max = print_log_max; if (buf != loc && buf != null) { print_append(buf, s, print_log_max); loc_max = local_log_max; } if (loc != null) print_append(loc, s, loc_max); if (printAlsoToSystemOut) System.out.print(s); vmBus_send("printed", mc(), s); } static void print_autoRotate() { } static boolean empty(Collection c) { return c == null || c.isEmpty(); } static boolean empty(Iterable c) { return c == null || !c.iterator().hasNext(); } static boolean empty(CharSequence s) { return s == null || s.length() == 0; } static boolean empty(Map map) { return map == null || map.isEmpty(); } static boolean empty(Object[] o) { return o == null || o.length == 0; } static boolean empty(BitSet bs) { return bs == null || bs.isEmpty(); } static boolean empty(Object o) { if (o instanceof Collection) return empty((Collection) o); if (o instanceof String) return empty((String) o); if (o instanceof Map) return empty((Map) o); if (o instanceof Object[]) return empty((Object[]) o); if (o instanceof byte[]) return empty((byte[]) o); if (o == null) return true; throw fail("unknown type for 'empty': " + getType(o)); } static boolean empty(Iterator i) { return i == null || !i.hasNext(); } static boolean empty(double[] a) { return a == null || a.length == 0; } static boolean empty(float[] a) { return a == null || a.length == 0; } static boolean empty(int[] a) { return a == null || a.length == 0; } static boolean empty(long[] a) { return a == null || a.length == 0; } static boolean empty(byte[] a) { return a == null || a.length == 0; } static boolean empty(short[] a) { return a == null || a.length == 0; } static boolean empty(MultiMap mm) { return mm == null || mm.isEmpty(); } static boolean empty(File f) { return getFileSize(f) == 0; } static boolean empty(Rect r) { return !(r != null && r.w != 0 && r.h != 0); } static boolean neq(Object a, Object b) { return !eq(a, b); } static A dm_evalInQ(F0 f) { return dm_evalInQ(dm_current_mandatory(), f); } static A dm_evalInQ(IF0 f) { return dm_evalInQ(dm_current_mandatory(), if0ToF0(f)); } static A dm_evalInQ(DynModule module, F0 f) { return evalInQ(module.q(), f); } static Object snippetTranspileWebBot(String uri, Map params, int refreshDelay) { if (eq("1", params.get("medium"))) { veryQuickJava_mediumRefresh(); print("Medium-refreshed transpiler."); } if (eq("1", params.get("fresh"))) { refreshTranspiler(); print("Refreshed transpiler."); } // use new TranspileForServer class (now default) //bool useNewTFS = eq("1", params.get("newTFS")); boolean useNewTFS = !eq("0", params.get("newTFS")); uri = dropPrefixSlash(uri); if (isSnippetID(uri)) params.put("snippetID" , uri); if (empty(params.get("snippetID"))) return "OK"; sendToSnippetUpdatesBot("/transpiling/" + psI(params.get("snippetID"))); final boolean compile = eq("1", params.get("compile")); final Flag ok = new Flag(); print_byThread = new InheritableThreadLocal(); String text = hijackPrint_tee(new Runnable() { public void run() { try { String snippetID = fsI(params.get("snippetID")); try { boolean isInclude = getSnippetType(snippetID) == snippetType_JavaXInclude(); transpileRaw_translator(); set(transpileRaw_trans, "print_byThread", print_byThread); print("Set print_byThread (" + print_byThread.get() + ") in " + systemHashCode(transpileRaw_trans)); AutoCloseable __1 = tempSetTL(transpileRaw_asInclude, isInclude); try { if (useNewTFS) new TranspileForServer(snippetID).run(); else { AutoCloseable __2 = tempSetTL(transpileForServer_compile, compile); try { transpileForServer(snippetID); } finally { _close(__2); }} ok.raise(); } finally { _close(__1); }} catch (Throwable __e) { printStackTrace(__e); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "String snippetID = fsI(params.get(\"snippetID\"));\r\n pcall {\r\n boolean ..."; }}); String redirect = params.get("redirect"); return hhtml(hhead(htitle((ok.isUp() ? "OK" : "Failed") + " Transpilation") + (ok.isUp() && nempty(redirect) ? hrefresh(refreshDelay, redirect) : "")) + hbody(hsourcecode(text))) + (ok.isUp() ? "" : hjs_scrollDownOnPageLoad()); } static File secretProgramFile(String progID, String fileName) { return new File(getSecretProgramDir(progID), fileName); } static File secretProgramFile(String fileName) { return secretProgramFile(getProgramID(), fileName); } static String trim(String s) { return s == null ? null : s.trim(); } static String trim(StringBuilder buf) { return buf.toString().trim(); } static String trim(StringBuffer buf) { return buf.toString().trim(); } static String loadTextFile(String fileName) { return loadTextFile(fileName, null); } static String loadTextFile(File f, String defaultContents) { return loadTextFile(f, defaultContents, "UTF-8"); } static String loadTextFile(File f, String defaultContents, String encoding) { try { checkFileNotTooBigToRead(f); if (f == null || !f.exists()) return defaultContents; FileInputStream fileInputStream = new FileInputStream(f); InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, encoding); return loadTextFile(inputStreamReader); } catch (Exception __e) { throw rethrow(__e); } } public static String loadTextFile(File fileName) { return loadTextFile(fileName, null); } static String loadTextFile(String fileName, String defaultContents) { return fileName == null ? defaultContents : loadTextFile(newFile(fileName), defaultContents); } static String loadTextFile(Reader reader) throws IOException { StringBuilder builder = new StringBuilder(); try { char[] buffer = new char[1024]; int n; while (-1 != (n = reader.read(buffer))) builder.append(buffer, 0, n); } finally { reader.close(); } return str(builder); } static AutoCloseable tempInterceptPrintIfNotIntercepted(F1 f) { return print_byThread().get() == null ? tempInterceptPrint(f) : null; } static void dm_requireSnippetUpdatesModule() { assertTrue("Update Stefan's OS", dm_subOSConnectorToChannel("snippetUpdates")); } static DynModule dm_current_mandatory() { return assertNotNull("No module set!", dm_currentModule()); } static AutoCloseable dm_vmBus_onMessage(final String msg, final VF1 onMessage) { return dm_ownResource(vmBus_onMessage(msg, onMessage)); } static AutoCloseable dm_vmBus_onMessage(final String msg, final IVF1 onMessage) { return dm_ownResource(vmBus_onMessage(msg, ivf1ToVF1(onMessage))); } static AutoCloseable dm_vmBus_onMessage(final String msg, final IVF2 onMessage) { return dm_ownResource(vmBus_onMessage(msg, ivf2ToVF2(onMessage))); } static AutoCloseable dm_vmBus_onMessage(String msg, final VF2 onMessage) { return dm_ownResource(vmBus_onMessage(msg, onMessage)); } static AutoCloseable dm_vmBus_onMessage(String msg, Runnable onMessage) { return dm_ownResource(vmBus_onMessage(msg, onMessage)); } static String getString(Map map, Object key) { return map == null ? null : (String) map.get(key); } static String getString(List l, int idx) { return (String) get(l, idx); } static String getString(Object o, Object key) { if (o instanceof Map) return getString((Map) o, key); if (key instanceof String) return (String) getOpt(o, (String) key); throw fail("Not a string key: " + getClassName(key)); } static String getString(String key, Object o) { return getString(o, (Object) key); } static boolean swic(String a, String b) { return startsWithIgnoreCase(a, b); } static boolean swic(String a, String b, Matches m) { if (!swic(a, b)) return false; m.m = new String[] {substring(a, l(b))}; return true; } static String fsI(String id) { return formatSnippetID(id); } static String fsI(long id) { return formatSnippetID(id); } static String firstIntAsString(String s) { return jextract("", s); } static Map> callF_cache = newDangerousWeakHashMap(); static A callF(F0 f) { return f == null ? null : f.get(); } static B callF(F1 f, A a) { return f == null ? null : f.get(a); } static A callF(IF0 f) { return f == null ? null : f.get(); } static B callF(IF1 f, A a) { return f == null ? null : f.get(a); } static B callF(A a, IF1 f) { return f == null ? null : f.get(a); } static C callF(F2 f, A a, B b) { return f == null ? null : f.get(a, b); } static C callF(IF2 f, A a, B b) { return f == null ? null : f.get(a, b); } static void callF(VF1 f, A a) { if (f != null) f.get(a); } static void callF(A a, IVF1 f) { if (f != null) f.get(a); } static void callF(IVF1 f, A a) { if (f != null) f.get(a); } static Object callF(Runnable r) { { if (r != null) r.run(); } return null; } static Object callF(Object f, Object... args) { return safeCallF(f, args); } static Object safeCallF(Object f, Object... args) { if (f instanceof Runnable) { ((Runnable) f).run(); return null; } if (f == null) return null; Class c = f.getClass(); ArrayList methods; synchronized(callF_cache) { methods = callF_cache.get(c); if (methods == null) methods = callF_makeCache(c); } int n = l(methods); if (n == 0) { if (f instanceof String) throw fail("Legacy call: " + f); throw fail("No get method in " + getClassName(c)); } if (n == 1) return invokeMethod(methods.get(0), f, args); for (int i = 0; i < n; i++) { Method m = methods.get(i); if (call_checkArgs(m, args, false)) return invokeMethod(m, f, args); } throw fail("No matching get method in " + getClassName(c)); } // used internally static ArrayList callF_makeCache(Class c) { ArrayList l = new ArrayList(); Class _c = c; do { for (Method m : _c.getDeclaredMethods()) if (m.getName().equals("get")) { makeAccessible(m); l.add(m); } if (!l.isEmpty()) break; _c = _c.getSuperclass(); } while (_c != null); callF_cache.put(c, l); return l; } public static boolean isSnippetID(String s) { try { parseSnippetID(s); return true; } catch (RuntimeException e) { return false; } } public static long parseSnippetID(String snippetID) { long id = Long.parseLong(shortenSnippetID(snippetID)); if (id == 0) throw fail("0 is not a snippet ID"); return id; } static String defaultJavaXTranslatorID_value = "#759"; static String defaultJavaXTranslatorID() { return defaultJavaXTranslatorID_value; } static void _handleError(Error e) { call(javax(), "_handleError", e); } static File[] listFiles(File dir) { File[] files = dir.listFiles(); return files == null ? new File[0] : files; } static File[] listFiles(String dir) { return listFiles(new File(dir)); } static File javaxCodeDir_dir; // can be set to work on different base dir static File javaxCodeDir() { return javaxCodeDir_dir != null ? javaxCodeDir_dir : new File(userHome(), "JavaX-Code"); } static File javaxCodeDir(String sub) { return newFile(javaxCodeDir(), sub); } static boolean ewic(String a, String b) { return endsWithIgnoreCase(a, b); } static boolean ewic(String a, String b, Matches m) { return endsWithIgnoreCase(a, b, m); } static A printStackTrace(A e) { // we go to system.out now - system.err is nonsense if (e != null) print(getStackTrace(e)); return e; } static void printStackTrace() { printStackTrace(new Throwable()); } static void printStackTrace(String msg) { printStackTrace(new Throwable(msg)); } static void printStackTrace(String msg, Throwable e) { printStackTrace(new Throwable(msg, e)); } static Object getOpt(Object o, String field) { return getOpt_cached(o, field); } static Object getOpt(String field, Object o) { return getOpt_cached(o, field); } static Object getOpt_raw(Object o, String field) { try { Field f = getOpt_findField(o.getClass(), field); if (f == null) return null; makeAccessible(f); return f.get(o); } catch (Exception __e) { throw rethrow(__e); } } // access of static fields is not yet optimized static Object getOpt(Class c, String field) { try { if (c == null) return null; Field f = getOpt_findStaticField(c, field); if (f == null) return null; makeAccessible(f); return f.get(null); } catch (Exception __e) { throw rethrow(__e); } } static Field getOpt_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static Class mc() { return main.class; } static void lock(Lock lock) { try { ping(); if (lock == null) return; try { vmBus_send("locking", lock, "thread" , currentThread()); lock.lockInterruptibly(); vmBus_send("locked", lock, "thread" , currentThread()); } catch (InterruptedException e) { Object reason = vm_threadInterruptionReasonsMap().get(currentThread()); print("Locking interrupted! Reason: " + strOr(reason, "Unknown")); printStackTrace(e); rethrow(e); } // NO call to ping here! Make sure lock is always released. } catch (Exception __e) { throw rethrow(__e); } } static void lock(Lock lock, String msg) { print("Locking: " + msg); lock(lock); } static void lock(Lock lock, String msg, long timeout) { print("Locking: " + msg); lockOrFail(lock, timeout); } static ReentrantLock lock() { return fairLock(); } static boolean cleanUp_interruptThreads = false; // experimental static void cleanUp(Object c) { if (c == null) return; if (c instanceof AutoCloseable) { close_pcall((AutoCloseable) c); return; } if (c instanceof java.util.Timer) { ((java.util.Timer) c).cancel(); return; } if (c instanceof Collection) { cleanUp((Collection) c); return; } if (c instanceof Map) { for (Object o : keys((Map) c)) cleanUp(o); for (Object o : values((Map) c)) cleanUp(o); ((Map) c).clear(); return; } //if (!(c instanceof Class)) ret; try { // revoke license preCleanUp(c); // unpause setOpt_raw(c, "ping_pauseAll", false); // call custom cleanMeUp() and cleanMeUp_*() functions innerCleanUp(c); // Java spec says finalize should only be called by GC, // but we care to differ. // Edit: Not anymore (illegal access warnings) /*if (isTrue(vmMap_get('callFinalize))) pcallOpt(c, "finalize");*/ // remove all virtual bots (hope this works) List androids = (List) getOpt(c, "record_list"); for (Object android : unnull(androids)) pcallOpt(android, "dispose"); // heck we'll dispose anything // sub-cleanup List classes = (List) (getOpt(c, "hotwire_classes")); if (classes != null) for (WeakReference cc : classes) { try { cleanUp(cc.get()); } catch (Throwable __e) { printStackTrace(__e); }} // interrupt all threads (experimental, they might be doing cleanup?) if (cleanUp_interruptThreads) { List threads = registeredThreads(c); if (nempty(threads)) { print("cleanUp: Interrupting " + n2(threads, "thread") + ": " + joinWithComma(allToString(threads))); interruptThreads(threads); } } } catch (Throwable __e) { printStackTrace(__e); } setOpt_raw(c, "cleaningUp_flag" , false); if (c instanceof Class && ((Class) c).getName().equals("main")) retireClassLoader(((Class) c).getClassLoader()); } static void cleanUp(Collection l) { if (l == null) return; for (Object c : l) cleanUp(c); l.clear(); } static Field setOpt_findField(Class c, String field) { HashMap map; synchronized(getOpt_cache) { map = getOpt_cache.get(c); if (map == null) map = getOpt_makeCache(c); } return map.get(field); } static void setOpt(Object o, String field, Object value) { try { if (o == null) return; Class c = o.getClass(); HashMap map; if (getOpt_cache == null) map = getOpt_makeCache(c); // in class init else synchronized(getOpt_cache) { map = getOpt_cache.get(c); if (map == null) map = getOpt_makeCache(c); } if (map == getOpt_special) { if (o instanceof Class) { setOpt((Class) o, field, value); return; } // It's probably a subclass of Map. Use raw method. TODO: huh? setOpt_raw(o, field, value); return; } Field f = map.get(field); if (f != null) { smartSet(f, o, value); return; } // possible improvement: skip setAccessible if (o instanceof DynamicObject) { setDyn(((DynamicObject) o), field, value); return; } if (o instanceof IMeta) setDyn(((IMeta) o), field, value); } catch (Exception __e) { throw rethrow(__e); } } static void setOpt(Class c, String field, Object value) { if (c == null) return; try { Field f = setOpt_findStaticField(c, field); // TODO: optimize if (f != null) smartSet(f, null, value); } catch (Exception e) { throw new RuntimeException(e); } } static Field setOpt_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) { makeAccessible(f); return f; } _c = _c.getSuperclass(); } while (_c != null); return null; } static void unlock(Lock lock, String msg) { if (lock == null) return; lock.unlock(); vmBus_send("unlocked", lock, "thread" , currentThread()); print("Unlocked: " + msg); // print afterwards to make sure the lock is always unlocked } static void unlock(Lock lock) { if (lock == null) return; lock.unlock(); vmBus_send("unlocked", lock, "thread" , currentThread()); } static Object callOpt(Object o) { return callF(o); } static Object callOpt(Object o, String method, Object... args) { return callOpt_withVarargs(o, method, args); } static Object vmBus_wrapArgs(Object... args) { return empty(args) ? null : l(args) == 1 ? args[0] : args; } static void pcallFAll_minimalExceptionHandling(Collection l, Object... args) { if (l != null) for (Object f : cloneList(l)) { ping(); pcallF_minimalExceptionHandling(f, args); } } static void pcallFAll_minimalExceptionHandling(Iterator it, Object... args) { while (it.hasNext()) { ping(); pcallF_minimalExceptionHandling(it.next(), args); } } static Set vm_busListeners_live_cache; static Set vm_busListeners_live() { if (vm_busListeners_live_cache == null) vm_busListeners_live_cache = vm_busListeners_live_load(); return vm_busListeners_live_cache;} static Set vm_busListeners_live_load() { return vm_generalIdentityHashSet("busListeners"); } static Map vm_busListenersByMessage_live_cache; static Map vm_busListenersByMessage_live() { if (vm_busListenersByMessage_live_cache == null) vm_busListenersByMessage_live_cache = vm_busListenersByMessage_live_load(); return vm_busListenersByMessage_live_cache;} static Map vm_busListenersByMessage_live_load() { return vm_generalHashMap("busListenersByMessage"); } static String combinePrintParameters(String s, Object o) { return (endsWithLetterOrDigit(s) ? s + ": " : s) + o; } static void ping_okInCleanUp() { if (ping_pauseAll || ping_anyActions) ping_impl(true); } // this syntax should be removed... static Object getThreadLocal(Object o, String name) { ThreadLocal t = (ThreadLocal) (getOpt(o, name)); return t != null ? t.get() : null; } static A getThreadLocal(ThreadLocal tl) { return tl == null ? null : tl.get(); } static A getThreadLocal(ThreadLocal tl, A defaultValue) { return or(getThreadLocal(tl), defaultValue); } static ThreadLocal print_byThread_dontCreate() { return print_byThread; } static boolean isFalse(Object o) { return eq(false, o); } static String getStackTrace(Throwable throwable) { lastException(throwable); return getStackTrace_noRecord(throwable); } static String getStackTrace_noRecord(Throwable throwable) { StringWriter writer = new StringWriter(); throwable.printStackTrace(new PrintWriter(writer)); return hideCredentials(writer.toString()); } static String getStackTrace() { return getStackTrace_noRecord(new Throwable()); } static String getStackTrace(String msg) { return getStackTrace_noRecord(new Throwable(msg)); } static String fixNewLines(String s) { int i = indexOf(s, '\r'); if (i < 0) return s; int l = s.length(); StringBuilder out = new StringBuilder(l); out.append(s, 0, i); for (; i < l; i++) { char c = s.charAt(i); if (c != '\r') out.append(c); else { out.append('\n'); if (i+1 < l && s.charAt(i+1) == '\n') ++i; } } return out.toString(); } static void print_append(Appendable buf, String s, int max) { try { synchronized(buf) { buf.append(s); if (buf instanceof StringBuffer) rotateStringBuffer(((StringBuffer) buf), max); else if (buf instanceof StringBuilder) rotateStringBuilder(((StringBuilder) buf), max); } } catch (Exception __e) { throw rethrow(__e); } } static RuntimeException fail() { throw new RuntimeException("fail"); } static RuntimeException fail(Throwable e) { throw asRuntimeException(e); } static RuntimeException fail(Object msg) { throw new RuntimeException(String.valueOf(msg)); } static RuntimeException fail(Object... objects) { throw new Fail(objects); } static RuntimeException fail(String msg) { throw new RuntimeException(msg == null ? "" : msg); } static RuntimeException fail(String msg, Throwable innerException) { throw new RuntimeException(msg, innerException); } static String getType(Object o) { return getClassName(o); } static long getFileSize(String path) { return path == null ? 0 : new File(path).length(); } static long getFileSize(File f) { return f == null ? 0 : f.length(); } static boolean eq(Object a, Object b) { return a == b || a != null && b != null && a.equals(b); } // a little kludge for stuff like eq(symbol, "$X") static boolean eq(Symbol a, String b) { return eq(str(a), b); } static F0 if0ToF0(IF0 f) { return f == null ? null : new F0() { public A get() { try { return f.get(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return f.get();"; }}; } static A evalInQ(Q q, final F0 f) { if (isInQ(q)) return callF(f); final Var> var = new Var(); q.add(new Runnable() { public void run() { try { try { var.set(eitherA(callF(f))); } catch (Throwable e) { var.set(eitherB(e)); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "try {\r\n var.set(eitherA(callF(f)));\r\n } catch (Throwable e) {\r\n ..."; }}); return returnOrThrow_either(waitForVarToBeNotNull(var)); } // returns true if a translator had been loaded static void veryQuickJava_mediumRefresh() { Object trans = getOpt(mc(), "transpileRaw_trans"); callOpt(trans, "mediumRefresh"); // Also clear our own standard functions callOpt(getOpt(mc(), "loadFunctions_cache"), "clear"); } // returns true if a translator had been loaded static boolean refreshTranspiler() { return veryQuickJava_refresh(); } static String dropPrefixSlash(String s) { return dropLeadingSlash(s); } static void sendToSnippetUpdatesBot(String uri, Object... params) { try { loadPageWithParams(butterBotURL("#1019175") + addSlashPrefix(uri), params); } catch (Throwable __e) { print(exceptionToStringShort(__e)); } } static long psI(String snippetID) { return parseSnippetID(snippetID); } static String hijackPrint_tee(Runnable r) { final StringBuilder buf = new StringBuilder(); Object old = interceptPrintInThisThread(new F1() { Boolean get(String s) { buf.append(s); return true; } }); try { callF(r); return str(buf); } finally { interceptPrintInThisThread(old); } } static int getSnippetType(String id) { if (!isSnippetID(id)) return 0; return getSnippetType(psI(id)); } static int getSnippetType(long id) { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.getSnippetType(fsI(id)); return getSnippetType_noResourceLoader(id); } static int getSnippetType_noResourceLoader(long id) { try { if (isLocalSnippetID(id)) return localSnippetType(id); if (isGeneralFileServerSnippet(id)) return snippetType_data(); if (isImageServerSnippet(id)) return snippetType_image(); return parseInt(trim(loadPageSilently(new URL(tb_mainServer() + "/tb-int/getfield.php?id=" + id + "&field=type" + standardCredentials())))); } catch (Exception __e) { throw rethrow(__e); } } static int snippetType_JavaXInclude() { return 42; } static A set(A o, String field, Object value) { if (o == null) return null; if (o instanceof Class) set((Class) o, field, value); else try { Field f = set_findField(o.getClass(), field); makeAccessible(f); smartSet(f, o, value); } catch (Exception e) { throw new RuntimeException(e); } return o; } static void set(Class c, String field, Object value) { if (c == null) return; try { Field f = set_findStaticField(c, field); makeAccessible(f); smartSet(f, null, value); } catch (Exception e) { throw new RuntimeException(e); } } static Field set_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Static field '" + field + "' not found in " + c.getName()); } static Field set_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Field '" + field + "' not found in " + c.getName()); } static void set(BitSet bs, int idx) { { if (bs != null) bs.set(idx); } } static int systemHashCode(Object o) { return identityHashCode(o); } static AutoCloseable tempSetTL(ThreadLocal tl, A a) { return tempSetThreadLocal(tl, a); } // can be false, it's compiled on the server anyway // defaults to true static ThreadLocal transpileForServer_compile = new ThreadLocal(); static long transpileForServer_localTime; static boolean transpileForServer_forceJavacOnServer = false; static boolean transpileForServer_forceJavacWhenLibs = false; static void transpileForServer(String progID) { new TranspileForServer(progID).run(); } static void _close(AutoCloseable c) { if (c != null) try { c.close(); } catch (Throwable e) { // Some classes stupidly throw an exception on double-closing if (c instanceof javax.imageio.stream.ImageOutputStream) return; else throw rethrow(e); } } static String hhtml(Object contents) { return containerTag("html", contents); } static String hhead(Object contents) { return tag("head", contents); } static String htitle(String title) { return hfulltag("title", htmlencode_noQuotes(title)); } static boolean nempty(Collection c) { return !empty(c); } static boolean nempty(CharSequence s) { return !empty(s); } static boolean nempty(Object[] o) { return !empty(o); } static boolean nempty(byte[] o) { return !empty(o); } static boolean nempty(int[] o) { return !empty(o); } static boolean nempty(BitSet bs) { return !empty(bs); } static boolean nempty(Map m) { return !empty(m); } static boolean nempty(Iterator i) { return i != null && i.hasNext(); } static boolean nempty(MultiMap mm) { return mm != null && !mm.isEmpty(); } static boolean nempty(Object o) { return !empty(o); } static boolean nempty(Rect r) { return r != null && r.w != 0 && r.h != 0; } static String hrefresh(String target) { return hrefresh(0, target); } static String hrefresh(double seconds) { return hrefresh(seconds, ""); } static String hrefresh(double seconds, String target) { return tag("meta", "", "http-equiv", "refresh", "content", iceil(seconds) + (nempty(target) ? "; url=" + target : "")); } static String hbody(Object contents, Object... params) { return tag("body", contents, params); } static String hsourcecode(Object o) { return sourceCodeToHTML(o); } static String hjs_scrollDownOnPageLoad() { return hjs("\r\n document.addEventListener(\"DOMContentLoaded\", function() {\r\n window.scrollTo(0, 100000);\r\n });\r\n "); } static File getSecretProgramDir() { return getSecretProgramDir(actualProgramID()); } static File getSecretProgramDir(String snippetID) { if (empty(snippetID)) return javaxSecretDir(); return newFile(javaxSecretDir(), formatSnippetID(snippetID)); } static String programID; static String getProgramID() { return nempty(programID) ? formatSnippetIDOpt(programID) : "?"; } // TODO: ask JavaX instead static String getProgramID(Class c) { String id = (String) getOpt(c, "programID"); if (nempty(id)) return formatSnippetID(id); return "?"; } static String getProgramID(Object o) { return getProgramID(getMainClass(o)); } static ThreadLocal> checkFileNotTooBigToRead_tl = new ThreadLocal(); static void checkFileNotTooBigToRead(File f) { callF(checkFileNotTooBigToRead_tl.get(), f); } static File newFile(File base, String... names) { for (String name : names) base = new File(base, name); return base; } static File newFile(String name) { return name == null ? null : new File(name); } static File newFile(String base, String... names) { return newFile(newFile(base), names); } static String str(Object o) { return o == null ? "null" : o.toString(); } static String str(char[] c) { return new String(c); } static String str(char[] c, int offset, int count) { return new String(c, offset, count); } //static final Map> getOpt_cache = newDangerousWeakHashMap(f getOpt_special_init); static class getOpt_Map extends WeakHashMap { getOpt_Map() { if (getOpt_special == null) getOpt_special = new HashMap(); clear(); } public void clear() { super.clear(); //print("getOpt clear"); put(Class.class, getOpt_special); put(String.class, getOpt_special); } } static final Map> getOpt_cache = _registerDangerousWeakMap(synchroMap(new getOpt_Map())); //static final Map> getOpt_cache = _registerWeakMap(synchroMap(new getOpt_Map)); static HashMap getOpt_special; // just a marker /*static void getOpt_special_init(Map map) { map.put(Class.class, getOpt_special); map.put(S.class, getOpt_special); }*/ static Map getOpt_getFieldMap(Object o) { Class c = _getClass(o); HashMap map = getOpt_cache.get(c); if (map == null) map = getOpt_makeCache(c); return map; } static Object getOpt_cached(Object o, String field) { try { if (o == null) return null; Map map = getOpt_getFieldMap(o); if (map == getOpt_special) { if (o instanceof Class) return getOpt((Class) o, field); /*if (o instanceof S) ret getOpt(getBot((S) o), field);*/ if (o instanceof Map) return ((Map) o).get(field); } Field f = map.get(field); if (f != null) return f.get(o); if (o instanceof DynamicObject) return syncMapGet2(((DynamicObject) o).fieldValues, field); return null; } catch (Exception __e) { throw rethrow(__e); } } // used internally - we are in synchronized block static HashMap getOpt_makeCache(Class c) { HashMap map; if (isSubtypeOf(c, Map.class)) map = getOpt_special; else { map = new HashMap(); if (!reflection_classesNotToScan().contains(c.getName())) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) { makeAccessible(f); String name = f.getName(); if (!map.containsKey(name)) map.put(name, f); } _c = _c.getSuperclass(); } while (_c != null); } } if (getOpt_cache != null) getOpt_cache.put(c, map); return map; } static ThreadLocal print_byThread() { synchronized(print_byThread_lock) { if (print_byThread == null) print_byThread = new ThreadLocal(); } return print_byThread; } // f can return false to suppress regular printing // call print_raw within f to actually print something static AutoCloseable tempInterceptPrint(F1 f) { return tempSetThreadLocal(print_byThread(), f); } static void assertTrue(Object o) { if (!(eq(o, true) /*|| isTrue(pcallF(o))*/)) throw fail(str(o)); } static boolean assertTrue(String msg, boolean b) { if (!b) throw fail(msg); return b; } static boolean assertTrue(boolean b) { if (!b) throw fail("oops"); return b; } static boolean dm_subOSConnectorToChannel(String channel) { if (!hasMethodNamed(dm_os(), "subConnectorToChannel")) return false; dm_osCall("subConnectorToChannel", channel); return true; } static A assertNotNull(A a) { assertTrue(a != null); return a; } static A assertNotNull(String msg, A a) { assertTrue(msg, a != null); return a; } static DynModule dm_currentModule() { return optCast(DynModule.class, dm_current_generic()); } static A dm_ownResource(A resource) { dm_currentModuleMandatory().ownResource(resource); return resource; } static AutoCloseable vmBus_onMessage(String msg, IVF1 onMessage) { return vmBus_onMessage(msg, ivf1ToVF1(onMessage)); } static AutoCloseable vmBus_onMessage(final String msg, final VF1 onMessage) { Map map = vm_busListenersByMessage_live(); synchronized(map) { Set listeners = map.get(msg); if (listeners == null) map.put(msg, listeners = syncIdentityHashSet()); // We're technically violating the one-synchronized-object-per-thread rule, // but it should be OK here. // TODO: remove empty sets from map return tempAdd(listeners, new VF2() { public void get(String _msg, Object arg) { try { callF(onMessage, arg) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(onMessage, arg)"; }}); } } static AutoCloseable vmBus_onMessage(String msg, final VF2 onMessage) { return vmBus_onMessage(msg, new VF1() { public void get(Object[] o) { try { callF(onMessage, first(o), second(o)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(onMessage, first(o), second(o));"; }}); } static AutoCloseable vmBus_onMessage(String msg, final IVF2 onMessage) { return vmBus_onMessage(msg, new VF1() { public void get(Object[] o) { try { callF(onMessage, first(o), second(o)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(onMessage, first(o), second(o));"; }}); } static AutoCloseable vmBus_onMessage(String msg, Runnable onMessage) { return vmBus_onMessage(msg, runnableToVF1(onMessage)); } static VF1 ivf1ToVF1(IVF1 f) { return f == null ? null : new VF1() { public void get(A a) { try { f.get(a) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "f.get(a)"; }}; } static VF2 ivf2ToVF2(IVF2 f) { return f == null ? null : new VF2() { public void get(A a, B b) { try { f.get(a, b) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "f.get(a, b)"; }}; } // get purpose 1: access a list/array/map (safer version of x.get(y)) static A get(List l, int idx) { return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null; } // seems to conflict with other signatures /*static B get(Map map, A key) { ret map != null ? map.get(key) : null; }*/ static A get(A[] l, int idx) { return idx >= 0 && idx < l(l) ? l[idx] : null; } // default to false static boolean get(boolean[] l, int idx) { return idx >= 0 && idx < l(l) ? l[idx] : false; } // get purpose 2: access a field by reflection or a map static Object get(Object o, String field) { try { if (o == null) return null; if (o instanceof Class) return get((Class) o, field); if (o instanceof Map) return ((Map) o).get(field); Field f = getOpt_findField(o.getClass(), field); if (f != null) { makeAccessible(f); return f.get(o); } if (o instanceof DynamicObject) return getOptDynOnly(((DynamicObject) o), field); } catch (Exception e) { throw asRuntimeException(e); } throw new RuntimeException("Field '" + field + "' not found in " + o.getClass().getName()); } static Object get_raw(String field, Object o) { return get_raw(o, field); } static Object get_raw(Object o, String field) { try { if (o == null) return null; Field f = get_findField(o.getClass(), field); makeAccessible(f); return f.get(o); } catch (Exception __e) { throw rethrow(__e); } } static Object get(Class c, String field) { try { Field f = get_findStaticField(c, field); makeAccessible(f); return f.get(null); } catch (Exception e) { throw new RuntimeException(e); } } static Field get_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Static field '" + field + "' not found in " + c.getName()); } static Field get_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Field '" + field + "' not found in " + c.getName()); } static Object get(String field, Object o) { return get(o, field); } static boolean get(BitSet bs, int idx) { return bs != null && bs.get(idx); } static String getClassName(Object o) { return o == null ? "null" : o instanceof Class ? ((Class) o).getName() : o.getClass().getName(); } static boolean startsWithIgnoreCase(String a, String b) { return regionMatchesIC(a, 0, b, 0, b.length()); } static String substring(String s, int x) { return substring(s, x, strL(s)); } static String substring(String s, int x, int y) { if (s == null) return null; if (x < 0) x = 0; int n = s.length(); if (y < x) y = x; if (y > n) y = n; if (x >= y) return ""; return s.substring(x, y); } // convenience method for quickly dropping a prefix static String substring(String s, CharSequence l) { return substring(s, lCharSequence(l)); } static int l(Object[] a) { return a == null ? 0 : a.length; } static int l(boolean[] a) { return a == null ? 0 : a.length; } static int l(byte[] a) { return a == null ? 0 : a.length; } static int l(short[] a) { return a == null ? 0 : a.length; } static int l(long[] a) { return a == null ? 0 : a.length; } static int l(int[] a) { return a == null ? 0 : a.length; } static int l(float[] a) { return a == null ? 0 : a.length; } static int l(double[] a) { return a == null ? 0 : a.length; } static int l(char[] a) { return a == null ? 0 : a.length; } static int l(Collection c) { return c == null ? 0 : c.size(); } static int l(Iterator i) { return iteratorCount_int_close(i); } // consumes the iterator && closes it if possible static int l(Map m) { return m == null ? 0 : m.size(); } static int l(CharSequence s) { return s == null ? 0 : s.length(); } static long l(File f) { return f == null ? 0 : f.length(); } static int l(Object o) { return o == null ? 0 : o instanceof String ? l((String) o) : o instanceof Map ? l((Map) o) : o instanceof Collection ? l((Collection) o) : o instanceof Object[] ? l((Object[]) o) : o instanceof boolean[] ? l((boolean[]) o) : o instanceof byte[] ? l((byte[]) o) : o instanceof char[] ? l((char[]) o) : o instanceof short[] ? l((short[]) o) : o instanceof int[] ? l((int[]) o) : o instanceof float[] ? l((float[]) o) : o instanceof double[] ? l((double[]) o) : o instanceof long[] ? l((long[]) o) : (Integer) call(o, "size"); } static String formatSnippetID(String id) { return "#" + parseSnippetID(id); } static String formatSnippetID(long id) { return "#" + id; } // returns from C to C static String jextract(String pat, String s) { return jextract(pat, javaTok(s)); } static String jextract(String pat, List tok) { List tokpat = javaTok(pat); jfind_preprocess(tokpat); int i = jfind(tok, tokpat); if (i < 0) return null; int j = i + l(tokpat) - 2; return joinSubList(tok, i, j); } static Map newDangerousWeakHashMap() { return _registerDangerousWeakMap(synchroMap(new WeakHashMap())); } // initFunction: voidfunc(Map) - is called initially, and after clearing the map static Map newDangerousWeakHashMap(Object initFunction) { return _registerDangerousWeakMap(synchroMap(new WeakHashMap()), initFunction); } static Object invokeMethod(Method m, Object o, Object... args) { try { try { return m.invoke(o, args); } catch (InvocationTargetException e) { throw rethrow(getExceptionCause(e)); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(e.getMessage() + " - was calling: " + m + ", args: " + joinWithSpace(classNames(args))); } } catch (Exception __e) { throw rethrow(__e); } } static boolean call_checkArgs(Method m, Object[] args, boolean debug) { Class[] types = m.getParameterTypes(); if (types.length != args.length) { if (debug) print("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) { Object arg = args[i]; if (!(arg == null ? !types[i].isPrimitive() : isInstanceX(types[i], arg))) { if (debug) print("Bad parameter " + i + ": " + arg + " vs " + types[i]); return false; } } return true; } static Field makeAccessible(Field f) { try { f.setAccessible(true); } catch (Throwable e) { // Note: The error reporting only works with Java VM option --illegal-access=deny vmBus_send("makeAccessible_error", e, f); } return f; } static Method makeAccessible(Method m) { try { m.setAccessible(true); } catch (Throwable e) { vmBus_send("makeAccessible_error", e, m); } return m; } static Constructor makeAccessible(Constructor c) { try { c.setAccessible(true); } catch (Throwable e) { vmBus_send("makeAccessible_error", e, c); } return c; } static String shortenSnippetID(String snippetID) { if (snippetID.startsWith("#")) snippetID = snippetID.substring(1); String httpBlaBla = "http://tinybrain.de/"; if (snippetID.startsWith(httpBlaBla)) snippetID = snippetID.substring(httpBlaBla.length()); return "" + parseLong(snippetID); } static Object call(Object o) { return callF(o); } // varargs assignment fixer for a single string array argument static Object call(Object o, String method, String[] arg) { return call(o, method, new Object[] {arg}); } static Object call(Object o, String method, Object... args) { //ret call_cached(o, method, args); return call_withVarargs(o, method, args); } static Class javax() { return getJavaX(); } static String _userHome; static String userHome() { if (_userHome == null) return actualUserHome(); return _userHome; } static File userHome(String path) { return new File(userDir(), path); } static boolean endsWithIgnoreCase(String a, String b) { int la = l(a), lb = l(b); return la >= lb && regionMatchesIC(a, la-lb, b, 0, lb); } static boolean endsWithIgnoreCase(String a, String b, Matches m) { if (!endsWithIgnoreCase(a, b)) return false; if (m != null) m.m = new String[] { substring(a, 0, l(a)-l(b)) }; return true; } static Field getOpt_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } //sbool ping_actions_shareable = true; static volatile boolean ping_pauseAll = false; static int ping_sleep = 100; // poll pauseAll flag every 100 static volatile boolean ping_anyActions = false; static Map ping_actions = newWeakHashMap(); static ThreadLocal ping_isCleanUpThread = new ThreadLocal(); // always returns true static boolean ping() { //ifdef useNewPing newPing(); //endifdef if (ping_pauseAll || ping_anyActions) ping_impl(true /* XXX */); //ifndef LeanMode ping_impl(); endifndef return true; } // returns true when it slept static boolean ping_impl(boolean okInCleanUp) { try { if (ping_pauseAll && !isAWTThread()) { do Thread.sleep(ping_sleep); while (ping_pauseAll); return true; } if (ping_anyActions) { // don't allow sharing ping_actions if (!okInCleanUp && !isTrue(ping_isCleanUpThread.get())) failIfUnlicensed(); Object action = null; synchronized(ping_actions) { if (!ping_actions.isEmpty()) { action = ping_actions.get(currentThread()); if (action instanceof Runnable) ping_actions.remove(currentThread()); if (ping_actions.isEmpty()) ping_anyActions = false; } } if (action instanceof Runnable) ((Runnable) action).run(); else if (eq(action, "cancelled")) throw fail("Thread cancelled."); } return false; } catch (Exception __e) { throw rethrow(__e); } } static Thread currentThread() { return Thread.currentThread(); } static Map vm_threadInterruptionReasonsMap() { return vm_generalWeakSubMap("Thread interruption reasons"); } static String strOr(Object o, String ifNull) { return o == null ? ifNull : str(o); } static void lockOrFail(Lock lock, long timeout) { try { ping(); vmBus_send("locking", lock, "thread" , currentThread()); if (!lock.tryLock(timeout, TimeUnit.MILLISECONDS)) { String s = "Couldn't acquire lock after " + timeout + " ms."; if (lock instanceof ReentrantLock) { ReentrantLock l = (ReentrantLock) lock; s += " Hold count: " + l.getHoldCount() + ", owner: " + call(l, "getOwner"); } throw fail(s); } vmBus_send("locked", lock, "thread" , currentThread()); ping(); } catch (Exception __e) { throw rethrow(__e); } } static ReentrantLock fairLock() { return new ReentrantLock(true); } static void close_pcall(AutoCloseable c) { if (c != null) { try { c.close(); } catch (Throwable __e) { printStackTrace(__e); }} } static Set keys(Map map) { return map == null ? new HashSet() : map.keySet(); } // convenience shortcut for keys_gen static Set keys(Object map) { return keys((Map) map); } static Set keys(MultiMap mm) { return mm.keySet(); } static Collection values(Map map) { return map == null ? emptyList() : map.values(); } // convenience shortcut for values_gen static Collection values(Object map) { return values((Map) map); } static Collection values(MultiMap mm) { return mm == null ? emptyList() : concatLists(values(mm.data)); } static void preCleanUp(Object c) { if (c instanceof Collection) { for (Object o : ((Collection) c)) preCleanUp(o); return; } callOpt(c, "licensed_off"); setOpt_raw(c, "ping_anyActions" , true); // so ping notices setOpt_raw(c, "cleaningUp_flag" , true); } // TODO: optimize (use getOpt_cache) static void setOpt_raw(Object o, String field, Object value) { try { if (o == null) return; if (o instanceof Class) setOpt_raw((Class) o, field, value); else { Field f = setOpt_raw_findField(o.getClass(), field); if (f != null) { makeAccessible(f); smartSet(f, o, value); } } } catch (Exception __e) { throw rethrow(__e); } } static void setOpt_raw(Class c, String field, Object value) { try { if (c == null) return; Field f = setOpt_raw_findStaticField(c, field); if (f != null) { makeAccessible(f); smartSet(f, null, value); } } catch (Exception __e) { throw rethrow(__e); } } static Field setOpt_raw_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static Field setOpt_raw_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static void innerCleanUp(Object c) { // call custom cleanMeUp() and cleanMeUp_*() functions if (!isFalse(pcallOpt(c, "cleanMeUp"))) for (String name : sorted(methodsStartingWith(c, "cleanMeUp_"))) try { callOpt(c, name); } catch (Throwable e) { print("Error cleaning up: " + programID(c)); _handleException(e); } } static void innerCleanUp() { innerCleanUp(mc()); } static String unnull(String s) { return s == null ? "" : s; } static Collection unnull(Collection l) { return l == null ? emptyList() : l; } static List unnull(List l) { return l == null ? emptyList() : l; } static int[] unnull(int[] l) { return l == null ? emptyIntArray() : l; } static char[] unnull(char[] l) { return l == null ? emptyCharArray() : l; } static double[] unnull(double[] l) { return l == null ? emptyDoubleArray() : l; } static Map unnull(Map l) { return l == null ? emptyMap() : l; } static Iterable unnull(Iterable i) { return i == null ? emptyList() : i; } static A[] unnull(A[] a) { return a == null ? (A[]) emptyObjectArray() : a; } static BitSet unnull(BitSet b) { return b == null ? new BitSet() : b; } static Pt unnull(Pt p) { return p == null ? new Pt() : p; } //ifclass Symbol static Symbol unnull(Symbol s) { return s == null ? emptySymbol() : s; } //endif static Pair unnull(Pair p) { return p != null ? p : new Pair(null, null); } static int unnull(Integer i) { return i == null ? 0 : i; } static long unnull(Long l) { return l == null ? 0L : l; } static double unnull(Double l) { return l == null ? 0.0 : l; } static Object pcallOpt(Object o, String method, Object... args) { try { return callOpt(o, method, args); } catch (Throwable __e) { printStackTrace(__e); } return null; } static List registeredThreads(Object o) { Map map = (Map) (getOpt(o, "_registerThread_threads")); if (map == null) return ll(); map.size(); // force clean-up synchronized(map) { return asList(keys(map)); } } static List registeredThreads() { _registerThread_threads.size(); // force clean-up return asList(keys(_registerThread_threads)); } static String n2(long l) { return formatWithThousands(l); } static String n2(AtomicLong l) { return n2(l.get()); } static String n2(Collection l) { return n2(l(l)); } static String n2(Map map) { return n2(l(map)); } static String n2(double l, String singular) { return empty(singular) ? str(l) : n2(l, singular, singular + "s"); } static String n2(double l, String singular, String plural) { if (fraction(l) == 0) return n2((long) l, singular, plural); else return l + " " + plural; } static String n2(long l, String singular, String plural) { return n_fancy2(l, singular, plural); } static String n2(long l, String singular) { return empty(singular) ? n2(l) : n_fancy2(l, singular, singular + "s"); } static String n2(Collection l, String singular) { return n2(l(l), singular); } static String n2(Collection l, String singular, String plural) { return n_fancy2(l, singular, plural); } static String n2(Map m, String singular, String plural) { return n_fancy2(m, singular, plural); } static String n2(Map m, String singular) { return n2(l(m), singular); } static String n2(long[] a, String singular) { return n2(l(a), singular); } static String n2(Object[] a, String singular) { return n2(l(a), singular); } static String n2(Object[] a, String singular, String plural) { return n_fancy2(a, singular, plural); } static String joinWithComma(Collection c) { return join(", ", c); } static String joinWithComma(Object... c) { return join(", ", c); } static String joinWithComma(String... c) { return join(", ", c); } static String joinWithComma(Pair p) { return p == null ? "" : joinWithComma(str(p.a), str(p.b)); } static List allToString(Iterable c) { List l = new ArrayList(); for (Object o : unnull(c)) l.add(str(o)); return l; } static List allToString(Object[] c) { List l = new ArrayList(); for (Object o : unnull(c)) l.add(str(o)); return l; } static void interruptThreads(Collection threads) { for (Thread t : unnull(threads)) interruptThread(t); } static void interruptThreads(Class mainClass) { interruptThreads(registeredThreads(mainClass)); } static void retireClassLoader(ClassLoader cl) { if (isJavaXClassLoader(cl)) setOptAll(cl, "retired" , true, "retiredMarker" , new DefunctClassLoader()); } static void smartSet(Field f, Object o, Object value) throws Exception { try { f.set(o, value); } catch (Exception e) { Class type = f.getType(); // take care of common case (long to int) if (type == int.class && value instanceof Long) { f.set(o, ((Long) value).intValue()); return; } if (type == boolean.class && value instanceof String) { f.set(o, isTrueOrYes(((String) value))); return; } if (type == LinkedHashMap.class && value instanceof Map) { f.set(o, asLinkedHashMap((Map) value)); return; } throw e; } } static A setDyn(A o, String key, Object value) { setDynObjectValue(o, key, value); return o; } static void setDyn(IMeta o, String key, Object value) { metaMapPut(o, key, value); } static Object callOpt_withVarargs(Object o, String method, Object... args) { try { if (o == null) return null; if (o instanceof Class) { Class c = (Class) o; _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(method, args); if (me == null) { // TODO: varargs return null; } if ((me.getModifiers() & Modifier.STATIC) == 0) return null; return invokeMethod(me, null, args); } else { Class c = o.getClass(); _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(method, args); if (me != null) return invokeMethod(me, o, args); // try varargs List methods = cache.cache.get(method); if (methods != null) methodSearch: for (Method m : methods) { { if (!(m.isVarArgs())) continue; } Object[] newArgs = massageArgsForVarArgsCall(m, args); if (newArgs != null) return invokeMethod(m, o, newArgs); } return null; } } catch (Exception __e) { throw rethrow(__e); } } static ArrayList cloneList(Iterable l) { return l instanceof Collection ? cloneList((Collection) l) : asList(l); } static ArrayList cloneList(Collection l) { if (l == null) return new ArrayList(); synchronized(collectionMutex(l)) { return new ArrayList(l); } } static Object pcallF_minimalExceptionHandling(Object f, Object... args) { try { return callFunction(f, args); } catch (Throwable e) { System.out.println(getStackTrace(e)); _storeException(e); } return null; } static Set vm_generalIdentityHashSet(Object name) { synchronized(vm_generalMap()) { Set set = (Set) (vm_generalMap_get(name)); if (set == null) vm_generalMap_put(name, set = syncIdentityHashSet()); return set; } } static Map vm_generalHashMap(Object name) { synchronized(vm_generalMap()) { Map m = (Map) (vm_generalMap_get(name)); if (m == null) vm_generalMap_put(name, m = syncHashMap()); return m; } } static boolean endsWithLetterOrDigit(String s) { return s != null && s.length() > 0 && Character.isLetterOrDigit(s.charAt(s.length()-1)); } static A or(A a, A b) { return a != null ? a : b; } // PersistableThrowable doesn't hold GC-disturbing class references in backtrace static volatile PersistableThrowable lastException_lastException; static PersistableThrowable lastException() { return lastException_lastException; } static void lastException(Throwable e) { lastException_lastException = persistableThrowable(e); } static String hideCredentials(URL url) { return url == null ? null : hideCredentials(str(url)); } static String hideCredentials(String url) { try { if (startsWithOneOf(url, "http://", "https://") && isAGIBlueDomain(hostNameFromURL(url))) return url; } catch (Throwable e) { print("HideCredentials", e); } return url.replaceAll("([&?])(_pass|key|cookie)=[^&\\s\"]*", "$1$2="); } static String hideCredentials(Object o) { return hideCredentials(str(o)); } static int indexOf(List l, A a, int startIndex) { if (l == null) return -1; int n = l(l); for (int i = startIndex; i < n; i++) if (eq(l.get(i), a)) return i; return -1; } static int indexOf(List l, int startIndex, A a) { return indexOf(l, a, startIndex); } static int indexOf(List l, A a) { if (l == null) return -1; return l.indexOf(a); } static int indexOf(String a, String b) { return a == null || b == null ? -1 : a.indexOf(b); } static int indexOf(String a, String b, int i) { return a == null || b == null ? -1 : a.indexOf(b, i); } static int indexOf(String a, char b) { return a == null ? -1 : a.indexOf(b); } static int indexOf(String a, int i, char b) { return indexOf(a, b, i); } static int indexOf(String a, char b, int i) { return a == null ? -1 : a.indexOf(b, i); } static int indexOf(String a, int i, String b) { return a == null || b == null ? -1 : a.indexOf(b, i); } static int indexOf(A[] x, A a) { int n = l(x); for (int i = 0; i < n; i++) if (eq(x[i], a)) return i; return -1; } static int indexOf(Iterable l, A a) { if (l == null) return -1; int i = 0; for (A x : l) { if (eq(x, a)) return i; i++; } return -1; } static void rotateStringBuffer(StringBuffer buf, int max) { try { if (buf == null) return; synchronized(buf) { if (buf.length() <= max) return; try { int newLength = max/2; int ofs = buf.length()-newLength; String newString = buf.substring(ofs); buf.setLength(0); buf.append("[...] ").append(newString); } catch (Exception e) { buf.setLength(0); } buf.trimToSize(); } } catch (Exception __e) { throw rethrow(__e); } } static void rotateStringBuilder(StringBuilder buf, int max) { try { if (buf == null) return; synchronized(buf) { if (buf.length() <= max) return; try { int newLength = max/2; int ofs = buf.length()-newLength; String newString = buf.substring(ofs); buf.setLength(0); buf.append("[...] ").append(newString); } catch (Exception e) { buf.setLength(0); } buf.trimToSize(); } } catch (Exception __e) { throw rethrow(__e); } } static RuntimeException asRuntimeException(Throwable t) { if (t instanceof Error) _handleError((Error) t); return t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t); } static boolean isInQ(Q q) { return q != null && isCurrentThread(q.rst.thread); } static Either eitherA(A a) { return new Either(1, a); } static Either eitherB(B b) { return new Either(2, b); } static A returnOrThrow_either(Either e) { if (isEitherB(e)) throw rethrow(e.b()); return eitherAOpt(e); } static A waitForVarToBeNotNull(Var v) { try { synchronized(v) { while (!v.has()) v.wait(); return v.get(); } } catch (Exception __e) { throw rethrow(__e); } } static String dropLeadingSlash(String s) { return dropPrefix("/", s); } static String loadPageWithParams(String url, Object... params) { return loadPage(appendQueryToURL(url, params)); } static String loadPageWithParams(String url, Map params) { return loadPage(appendQueryToURL(url, params)); } static String butterBotURL(String botID) { return "https://botcompany.de/" + psI(botID) + "/raw"; } static String addSlashPrefix(String s) { return addPrefix("/", s); } static String exceptionToStringShort(Throwable e) { lastException(e); e = getInnerException(e); String msg = hideCredentials(unnull(e.getMessage())); if (msg.indexOf("Error") < 0 && msg.indexOf("Exception") < 0) return baseClassName(e) + prependIfNempty(": ", msg); else return msg; } // f can return false to suppress regular printing // call print_raw within f to actually print something // f preferrably is F1 static Object interceptPrintInThisThread(Object f) { Object old = print_byThread().get(); print_byThread().set(f); return old; } static IResourceLoader vm_getResourceLoader() { return proxy(IResourceLoader.class, vm_generalMap_get("_officialResourceLoader")); } static boolean isLocalSnippetID(String snippetID) { return isSnippetID(snippetID) && isLocalSnippetID(psI(snippetID)); } static boolean isLocalSnippetID(long snippetID) { return snippetID >= 1000 && snippetID <= 9999; } static int localSnippetType(String snippetID) { return localSnippetType(psI(snippetID)); } static int localSnippetType(long snippetID) { return parseIntOpt(getFileInfoField(localSnippetFile(snippetID), "Type")); } static boolean isGeneralFileServerSnippet(long id) { return id >= 1400000 && id < 1500000; } static int snippetType_data() { return 37; } static boolean isImageServerSnippet(long id) { return id >= 1100000 && id < 1200000; } static int snippetType_image() { return 23; } static int parseInt(String s) { return emptyString(s) ? 0 : Integer.parseInt(s); } static int parseInt(char c) { return Integer.parseInt(str(c)); } static int loadPage_defaultTimeout = 60000; static ThreadLocal loadPage_charset = new ThreadLocal(); static boolean loadPage_allowGzip = true, loadPage_debug; static boolean loadPage_anonymous = false; // don't send computer ID static int loadPage_verboseness = 100000; static int loadPage_retries = 1; //60; // seconds static ThreadLocal loadPage_silent = new ThreadLocal(); static volatile int loadPage_forcedTimeout; // ms static ThreadLocal loadPage_forcedTimeout_byThread = new ThreadLocal(); // ms static ThreadLocal>> loadPage_responseHeaders = new ThreadLocal(); static ThreadLocal> loadPage_extraHeaders = new ThreadLocal(); static ThreadLocal loadPage_sizeLimit = new ThreadLocal(); public static String loadPageSilently(String url) { try { return loadPageSilently(new URL(loadPage_preprocess(url))); } catch (Exception __e) { throw rethrow(__e); } } public static String loadPageSilently(URL url) { try { if (!networkAllowanceTest(str(url))) throw fail("Not allowed: " + url); IOException e = null; for (int tries = 0; tries < loadPage_retries; tries++) try { URLConnection con = loadPage_openConnection(url); return loadPage(con, url); } catch (IOException _e) { e = _e; if (loadPage_debug) print(exceptionToStringShort(e)); if (tries < loadPage_retries-1) sleepSeconds(1); } throw e; } catch (Exception __e) { throw rethrow(__e); } } static String loadPage_preprocess(String url) { if (url.startsWith("tb/")) // don't think we use this anymore url = tb_mainServer() + "/" + url; if (url.indexOf("://") < 0) url = "http://" + url; return url; } static String loadPage(String url) { try { url = loadPage_preprocess(url); if (!isTrue(loadPage_silent.get())) printWithTime("Loading: " + hideCredentials(url)); return loadPageSilently(new URL(url)); } catch (Exception __e) { throw rethrow(__e); } } static String loadPage(URL url) { return loadPage(url.toExternalForm()); } static String loadPage(URLConnection con, URL url) throws IOException { return loadPage(con, url, true); } static String loadPage(URLConnection con, URL url, boolean addHeaders) throws IOException { Map extraHeaders = getAndClearThreadLocal(loadPage_extraHeaders); Long limit = optPar(loadPage_sizeLimit); if (addHeaders) try { if (!loadPage_anonymous) setHeaders(con); if (loadPage_allowGzip) con.setRequestProperty("Accept-Encoding", "gzip"); con.setRequestProperty("X-No-Cookies", "1"); for (String key : keys(extraHeaders)) con.setRequestProperty(key, extraHeaders.get(key)); } catch (Throwable e) {} // fails if within doPost vm_generalSubMap("URLConnection per thread").put(currentThread(), con); loadPage_responseHeaders.set(con.getHeaderFields()); InputStream in = null; try { in = urlConnection_getInputStream(con); //vm_generalSubMap("InputStream per thread").put(currentThread(), in); if (loadPage_debug) print("Put stream in map: " + currentThread()); String contentType = con.getContentType(); if (contentType == null) { //printStruct("Headers: ", con.getHeaderFields()); throw new IOException("Page could not be read: " + hideCredentials(url)); } //print("Content-Type: " + contentType); String charset = loadPage_charset == null ? null : loadPage_charset.get(); if (charset == null) charset = loadPage_guessCharset(contentType); if ("gzip".equals(con.getContentEncoding())) { if (loadPage_debug) print("loadPage: Using gzip."); in = newGZIPInputStream(in); } Reader r; try { r = new InputStreamReader(in, unquote(charset)); } catch (UnsupportedEncodingException e) { print(toHex(utf8(charset))); throw e; } boolean silent = isTrue(loadPage_silent.get()); StringBuilder buf = new StringBuilder(); int n = 0; while (limit == null || n < limit) { ping(); int ch = r.read(); if (ch < 0) break; buf.append((char) ch); ++n; if (!silent && (n % loadPage_verboseness) == 0) print(" " + n + " chars read"); } return buf.toString(); } finally { if (loadPage_debug) print("loadPage done"); //vm_generalSubMap("InputStream per thread").remove(currentThread()); vm_generalSubMap("URLConnection per thread").remove(currentThread()); if (in != null) in.close(); } } static String loadPage_guessCharset(String contentType) { Matcher m = regexpMatcher("text/[a-z]+;\\s*charset=([^\\s]+)\\s*", contentType); String match = m.matches() ? m.group(1) : null; if (loadPage_debug) print("loadPage: contentType=" + contentType + ", match: " + match); /* If Content-Type doesn't match this pre-conception, choose default and hope for the best. */ //return or(match, "ISO-8859-1"); return or(match, "UTF-8"); } static URLConnection loadPage_openConnection(URL url) { URLConnection con = openConnection(url); int timeout = toInt(loadPage_forcedTimeout_byThread.get()); if (timeout == 0) timeout = loadPage_forcedTimeout; if (timeout != 0) setURLConnectionTimeouts(con, loadPage_forcedTimeout); else setURLConnectionDefaultTimeouts(con, loadPage_defaultTimeout); return con; } static String tb_mainServer_default = "https://code.botcompany.de:9898"; static Object tb_mainServer_override; // func -> S static String tb_mainServer() { if (tb_mainServer_override != null) return (String) callF(tb_mainServer_override); return trim(loadTextFile(tb_mainServer_file(), tb_mainServer_default)); } static File tb_mainServer_file() { return getProgramFile("#1001638", "mainserver.txt"); } static boolean tb_mainServer_isDefault() { return eq(tb_mainServer(), tb_mainServer_default); } static String standardCredentials() { String user = standardCredentialsUser(); String pass = standardCredentialsPass(); if (nempty(user) && nempty(pass)) return "&_user=" + urlencode(user) + "&_pass=" + urlencode(pass); return ""; } static int identityHashCode(Object o) { return System.identityHashCode(o); } static AutoCloseable tempSetThreadLocal(final ThreadLocal tl, A a) { if (tl == null) return null; final A prev = setThreadLocal(tl, a); return new AutoCloseable() { public String toString() { return "tl.set(prev);"; } public void close() throws Exception { tl.set(prev); }}; } static AutoCloseable tempSetThreadLocalIfNecessary(ThreadLocal tl, A a) { if (tl == null) return null; A prev = tl.get(); if (eq(prev, a)) return null; tl.set(a); return new AutoCloseable() { public String toString() { return "tl.set(prev);"; } public void close() throws Exception { tl.set(prev); }}; } static String containerTag(String tag) { return containerTag(tag, ""); } static String containerTag(String tag, Object contents, Object... params) { String openingTag = hopeningTag(tag, params); String s = str(contents); return openingTag + s + ""; } static String tag(String tag) { return htag(tag); } static String tag(String tag, Object contents, Object... params) { return htag(tag, str(contents), params); } static String tag(String tag, StringBuilder contents, Object... params) { return htag(tag, contents, params); } static String tag(String tag, StringBuffer contents, Object... params) { return htag(tag, contents, params); } static String hfulltag(String tag) { return hfulltag(tag, ""); } static String hfulltag(String tag, Object contents, Object... params) { return hopeningTag(tag, params) + str(contents) + ""; } static String htmlencode_noQuotes(String s) { if (s == null) return ""; int n = s.length(); StringBuilder out = null; for (int i = 0; i < n; i++) { char c = s.charAt(i); if (c == '<') { if (out == null) out = new StringBuilder(Math.max(16, n)).append(takeFirst(i, s)); out .append("<"); } else if (c == '>') { if (out == null) out = new StringBuilder(Math.max(16, n)).append(takeFirst(i, s)); out .append(">"); } else if (c > 127 || c == '&') { int cp = s.codePointAt(i); if (out == null) out = new StringBuilder(Math.max(16, n)).append(takeFirst(i, s)); out .append("&#x"); out.append(intToHex_flexLength(cp)); out.append(';'); i += Character.charCount(cp)-1; } else { if (out != null) out.append(c); } } return out == null ? s : out.toString(); } static int iceil(double d) { return (int) Math.ceil(d); } static String sourceCodeToHTML(String src) { return sourceCodeToHTML_noEncode(htmlencode2(src)); } // works for String, StringBuffer, StringBuilder static String sourceCodeToHTML(Object o) { return sourceCodeToHTML(str(o)); } static String hjs(String script) { return hjs(script, (Object[]) null); } static String hjs(String script, Object... __) { return hjavascript(script, __); } static String hjs(JS script) { return hjs(script, (Object[]) null); } static String hjs(JS script, Object... __) { return hjavascript(script == null ? null : script.get(), __); } static String actualProgramID() { //try answer getProgramIDOrNull(realMC()); return programID(); } static File javaxSecretDir_dir; // can be set to work on different base dir static File javaxSecretDir() { return javaxSecretDir_dir != null ? javaxSecretDir_dir : new File(userHome(), "JavaX-Secret"); } static File javaxSecretDir(String sub) { return newFile(javaxSecretDir(), sub); } static String formatSnippetIDOpt(String s) { return isSnippetID(s) ? formatSnippetID(s) : s; } static Class getMainClass() { return mc(); } static Class getMainClass(Object o) { try { if (o == null) return null; if (o instanceof Class && eq(((Class) o).getName(), "x30")) return (Class) o; ClassLoader cl = (o instanceof Class ? (Class) o : o.getClass()).getClassLoader(); if (cl == null) return null; String name = mainClassNameForClassLoader(cl); return loadClassFromClassLoader_orNull(cl, name); } catch (Exception __e) { throw rethrow(__e); } } static Map _registerThread_threads; static Object _onRegisterThread; // voidfunc(Thread) static Thread _registerThread(Thread t) { if (_registerThread_threads == null) _registerThread_threads = newWeakHashMap(); _registerThread_threads.put(t, true); vm_generalWeakSubMap("thread2mc").put(t, weakRef(mc())); callF(_onRegisterThread, t); return t; } static void _registerThread() { _registerThread(Thread.currentThread()); } static void clear(Collection c) { if (c != null) c.clear(); } static void clear(Map map) { if (map != null) map.clear(); } static void put(Map map, A a, B b) { if (map != null) map.put(a, b); } static void put(List l, int i, A a) { if (l != null && i >= 0 && i < l(l)) l.set(i, a); } static List _registerDangerousWeakMap_preList; static A _registerDangerousWeakMap(A map) { return _registerDangerousWeakMap(map, null); } static A _registerDangerousWeakMap(A map, Object init) { callF(init, map); if (init instanceof String) { final String f = (String) init; init = new VF1() { public void get(Map map) { try { callMC(f, map) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callMC(f, map)"; }}; } if (javax() == null) { // We're in class init if (_registerDangerousWeakMap_preList == null) _registerDangerousWeakMap_preList = synchroList(); _registerDangerousWeakMap_preList.add(pair(map, init)); return map; } call(javax(), "_registerDangerousWeakMap", map, init); return map; } static void _onLoad_registerDangerousWeakMap() { assertNotNull(javax()); if (_registerDangerousWeakMap_preList == null) return; for (Pair p : _registerDangerousWeakMap_preList) _registerDangerousWeakMap(p.a, p.b); _registerDangerousWeakMap_preList = null; } static Map synchroMap() { return synchroHashMap(); } static Map synchroMap(Map map) { return Collections.synchronizedMap(map); } static Class _getClass(String name) { try { return Class.forName(name); } catch (ClassNotFoundException e) { return null; // could optimize this } } static Class _getClass(Object o) { return o == null ? null : o instanceof Class ? (Class) o : o.getClass(); } static Class _getClass(Object realm, String name) { try { return classLoaderForObject(realm).loadClass(classNameToVM(name)); } catch (ClassNotFoundException e) { return null; // could optimize this } } static B syncMapGet2(Map map, A a) { if (map == null) return null; synchronized(collectionMutex(map)) { return map.get(a); } } static B syncMapGet2(A a, Map map) { return syncMapGet2(map, a); } static boolean isSubtypeOf(Class a, Class b) { return a != null && b != null && b.isAssignableFrom(a); // << always hated that method, let's replace it! } static Set reflection_classesNotToScan_value = litset( "jdk.internal.loader.URLClassPath" ); static Set reflection_classesNotToScan() { return reflection_classesNotToScan_value; } // This is a bit rough... finds static and non-static methods. // It's usually just for error messages though, so no worries. static boolean hasMethodNamed(Object obj, String method) { if (obj == null) return false; if (obj instanceof Class) return hasMethodNamed((Class) obj, method); return hasMethodNamed(obj.getClass(), method); } static boolean hasMethodNamed(Class c, String method) { while (c != null) { for (Method m : c.getDeclaredMethods()) if (m.getName().equals(method)) return true; c = c.getSuperclass(); } return false; } static Object dm_os() { { var __1= vm_generalMap_get("stefansOS"); if (__1 != null) return __1; } return creator(); } static Object dm_osCall(String functionName, Object... args) { return dm_callOS(functionName, args); } static A optCast(Class c, Object o) { return isInstance(c, o) ? (A) o : null; } static Object dm_current_generic() { return getWeakRef(dm_current_generic_tl().get()); } static DynModule dm_currentModuleMandatory() { return dm_current_mandatory(); } static Set syncIdentityHashSet() { return (Set) synchronizedSet(identityHashSet()); } static AutoCloseable tempAdd(Collection l, A a) { if (l == null || l.contains(a)) return null; l.add(a); return new AutoCloseable() { public String toString() { return "l.remove(a);"; } public void close() throws Exception { l.remove(a); }}; } static Object first(Object list) { return first((Iterable) list); } static A first(List list) { return empty(list) ? null : list.get(0); } static A first(A[] bla) { return bla == null || bla.length == 0 ? null : bla[0]; } static Pair first(Map map) { return mapEntryToPair(first(entrySet(map))); } static Pair first(MultiMap mm) { if (mm == null) return null; var e = first(mm.data.entrySet()); if (e == null) return null; return pair(e.getKey(), first(e.getValue())); } static A first(IterableIterator i) { return first((Iterator) i); } static A first(Iterator i) { return i == null || !i.hasNext() ? null : i.next(); } static A first(Iterable i) { if (i == null) return null; Iterator it = i.iterator(); return it.hasNext() ? it.next() : null; } static Character first(String s) { return empty(s) ? null : s.charAt(0); } static Character first(CharSequence s) { return empty(s) ? null : s.charAt(0); } static A first(Pair p) { return p == null ? null : p.a; } static Byte first(byte[] l) { return empty(l) ? null : l[0]; } static A first(A[] l, IF1 pred) { return firstThat(l, pred); } static A first(Iterable l, IF1 pred) { return firstThat(l, pred); } static A first(IF1 pred, Iterable l) { return firstThat(pred, l); } static A second(List l) { return get(l, 1); } static A second(Iterable l) { if (l == null) return null; Iterator it = iterator(l); if (!it.hasNext()) return null; it.next(); return it.hasNext() ? it.next() : null; } static A second(A[] bla) { return bla == null || bla.length <= 1 ? null : bla[1]; } static B second(Pair p) { return p == null ? null : p.b; } static A second(Producer p) { if (p == null) return null; if (p.next() == null) return null; return p.next(); } static char second(String s) { return charAt(s, 1); } static B second(Either e) { return e == null ? null : e.bOpt(); } static A third(List l) { return _get(l, 2); } static A third(Iterable l) { if (l == null) return null; Iterator it = iterator(l); for (int _repeat_0 = 0; _repeat_0 < 2; _repeat_0++) { if (!it.hasNext()) return null; it.next(); } return it.hasNext() ? it.next() : null; } static A third(Producer p) { if (p == null) return null; for (int _repeat_1 = 0; _repeat_1 < 2; _repeat_1++) { if (p.next() == null) return null; } return p.next(); } static A third(A[] bla) { return bla == null || bla.length <= 2 ? null : bla[2]; } static A last(List l) { return empty(l) ? null : l.get(l.size()-1); } static char last(String s) { return empty(s) ? '#' : s.charAt(l(s)-1); } static byte last(byte[] a) { return l(a) != 0 ? a[l(a)-1] : 0; } static int last(int[] a) { return l(a) != 0 ? a[l(a)-1] : 0; } static double last(double[] a) { return l(a) != 0 ? a[l(a)-1] : 0; } static A last(A[] a) { return l(a) != 0 ? a[l(a)-1] : null; } static A last(Iterator it) { A a = null; while (it.hasNext()) { ping(); a = it.next(); } return a; } static A last(Collection l) { if (l == null) return null; if (l instanceof List) return (A) last((List) l); if (l instanceof SortedSet) return (A) last((SortedSet) l); Iterator it = iterator(l); A a = null; while (it.hasNext()) { ping(); a = it.next(); } return a; } static A last(SortedSet l) { return l == null ? null : l.last(); } static A last(CompactLinkedHashSet set) { return set == null ? null : set.last(); } static VF1 runnableToVF1(final Runnable r) { return r == null ? null : new VF1() { public void get(A a) { try { r.run() ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "r.run()"; }}; } static Object getOptDynOnly(DynamicObject o, String field) { if (o == null || o.fieldValues == null) return null; return o.fieldValues.get(field); } static boolean regionMatchesIC(String a, int offsetA, String b, int offsetB, int len) { return a != null && a.regionMatches(true, offsetA, b, offsetB, len); } static int strL(String s) { return s == null ? 0 : s.length(); } static int lCharSequence(CharSequence s) { return s == null ? 0 : s.length(); } static int iteratorCount_int_close(Iterator i) { try { int n = 0; if (i != null) while (i.hasNext()) { i.next(); ++n; } if (i instanceof AutoCloseable) ((AutoCloseable) i).close(); return n; } catch (Exception __e) { throw rethrow(__e); } } // TODO: extended multi-line strings static int javaTok_n, javaTok_elements; static boolean javaTok_opt = false; static List javaTok(String s) { ++javaTok_n; ArrayList tok = new ArrayList(); int l = s == null ? 0 : s.length(); int i = 0; while (i < l) { int j = i; char c, d; // scan for whitespace while (j < l) { c = s.charAt(j); d = j+1 >= l ? '\0' : s.charAt(j+1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !regionMatches(s, j, "*/")); j = Math.min(j+2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } tok.add(javaTok_substringN(s, i, j)); i = j; if (i >= l) break; c = s.charAt(i); d = i+1 >= l ? '\0' : s.charAt(i+1); // scan for non-whitespace // Special JavaX syntax: 'identifier if (c == '\'' && Character.isJavaIdentifierStart(d) && i+2 < l && "'\\".indexOf(s.charAt(i+2)) < 0) { j += 2; while (j < l && Character.isJavaIdentifierPart(s.charAt(j))) ++j; } else if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { int c2 = s.charAt(j); if (c2 == opener || c2 == '\n' && opener == '\'') { // allow multi-line strings, but not for ' ++j; break; } else if (c2 == '\\' && j+1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || s.charAt(j) == '\'')); // for stuff like "don't" else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; // Long constants like 1L } else if (c == '[' && d == '[') { do ++j; while (j < l && !regionMatches(s, j, "]]")); j = Math.min(j+2, l); } else if (c == '[' && d == '=' && i+2 < l && s.charAt(i+2) == '[') { do ++j; while (j+2 < l && !regionMatches(s, j, "]=]")); j = Math.min(j+3, l); } else ++j; tok.add(javaTok_substringC(s, i, j)); i = j; } if ((tok.size() % 2) == 0) tok.add(""); javaTok_elements += tok.size(); return tok; } static List javaTok(List tok) { return javaTokWithExisting(join(tok), tok); } static int jfind(String s, String in) { return jfind(javaTok(s), in); } static int jfind(List tok, String in) { return jfind(tok, 1, in); } static int jfind(List tok, int startIdx, String in) { return jfind(tok, startIdx, in, (ITokCondition) null); } static int jfind(List tok, String in, Object condition) { return jfind(tok, 1, in, condition); } static int jfind(List tok, String in, IIntPred condition) { return jfind(tok, 1, in, condition); } static int jfind(List tok, int startIndex, String in, IIntPred condition) { return jfind(tok, startIndex, in, tokCondition(condition)); } static int jfind(List tok, String in, ITokCondition condition) { return jfind(tok, 1, in, condition); } static int jfind(List tok, int startIndex, String in, ITokCondition condition) { return jfind(tok, startIndex, in, (Object) condition); } static int jfind(List tok, int startIdx, String in, Object condition) { //LS tokin = jfind_preprocess(javaTok(in)); return jfind(tok, startIdx, javaTokForJFind_array(in), condition); } // assumes you preprocessed tokin static int jfind(List tok, List tokin) { return jfind(tok, 1, tokin); } static int jfind(List tok, int startIdx, List tokin) { return jfind(tok, startIdx, tokin, null); } static int jfind(List tok, int startIdx, String[] tokinC, Object condition) { return findCodeTokens(tok, startIdx, false, tokinC, condition); } static int jfind(List tok, int startIdx, List tokin, Object condition) { return jfind(tok, startIdx, codeTokensAsStringArray(tokin), condition); } static List jfind_preprocess(List tok) { for (String type : litlist("quoted", "id", "int")) replaceSublist(tok, ll("<", "", type, "", ">"), ll("<" + type + ">")); replaceSublist(tok, ll("\\", "", "*"), ll("\\*")); return tok; } static String joinSubList(List l, int i, int j) { return join(subList(l, i, j)); } static String joinSubList(List l, int i) { return join(subList(l, i)); } static Throwable getExceptionCause(Throwable e) { Throwable c = e.getCause(); return c != null ? c : e; } static String joinWithSpace(Iterable c) { return join(" ", c); } static String joinWithSpace(String... c) { return join(" ", c); } static List classNames(Collection l) { return getClassNames(l); } static List classNames(Object[] l) { return getClassNames(Arrays.asList(l)); } static boolean isInstanceX(Class type, Object arg) { if (type == boolean.class) return arg instanceof Boolean; if (type == int.class) return arg instanceof Integer; if (type == long.class) return arg instanceof Long; if (type == float.class) return arg instanceof Float; if (type == short.class) return arg instanceof Short; if (type == char.class) return arg instanceof Character; if (type == byte.class) return arg instanceof Byte; if (type == double.class) return arg instanceof Double; return type.isInstance(arg); } static long parseLong(String s) { if (empty(s)) return 0; return Long.parseLong(dropSuffix("L", s)); } static long parseLong(Object s) { return Long.parseLong((String) s); } static Object call_withVarargs(Object o, String method, Object... args) { try { if (o == null) return null; if (o instanceof Class) { Class c = (Class) o; _MethodCache cache = callOpt_getCache(c); Method me = cache.findStaticMethod(method, args); if (me != null) return invokeMethod(me, null, args); // try varargs List methods = cache.cache.get(method); if (methods != null) methodSearch: for (Method m : methods) { { if (!(m.isVarArgs())) continue; } { if (!(isStaticMethod(m))) continue; } Object[] newArgs = massageArgsForVarArgsCall(m, args); if (newArgs != null) return invokeMethod(m, null, newArgs); } throw fail("Method " + c.getName() + "." + method + "(" + joinWithComma(classNames(args)) + ") not found"); } else { Class c = o.getClass(); _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(method, args); if (me != null) return invokeMethod(me, o, args); // try varargs List methods = cache.cache.get(method); if (methods != null) methodSearch: for (Method m : methods) { { if (!(m.isVarArgs())) continue; } Object[] newArgs = massageArgsForVarArgsCall(m, args); if (newArgs != null) return invokeMethod(m, o, newArgs); } throw fail("Method " + c.getName() + "." + method + "(" + joinWithComma(classNames(args)) + ") not found"); } } catch (Exception __e) { throw rethrow(__e); } } static Class __javax; static Class getJavaX() { try { return __javax; } catch (Exception __e) { throw rethrow(__e); } } static void __setJavaX(Class j) { __javax = j; _onJavaXSet(); } static String actualUserHome_value; static String actualUserHome() { if (actualUserHome_value == null) { if (isAndroid()) actualUserHome_value = "/storage/emulated/0/"; else actualUserHome_value = System.getProperty("user.home"); } return actualUserHome_value; } static File actualUserHome(String sub) { return newFile(new File(actualUserHome()), sub); } static File userDir() { return new File(userHome()); } static File userDir(String path) { return new File(userHome(), path); } static Map newWeakHashMap() { return _registerWeakMap(synchroMap(new WeakHashMap())); } static void newPing() { var tl = newPing_actionTL(); Runnable action = tl == null ? null : tl.get(); { if (action != null) action.run(); } } // TODO: test if android complains about this static boolean isAWTThread() { if (isAndroid()) return false; if (isHeadless()) return false; return isAWTThread_awt(); } static boolean isAWTThread_awt() { return SwingUtilities.isEventDispatchThread(); } static boolean isTrue(Object o) { if (o instanceof Boolean) return ((Boolean) o).booleanValue(); if (o == null) return false; if (o instanceof ThreadLocal) // TODO: remove this return isTrue(((ThreadLocal) o).get()); throw fail(getClassName(o)); } static boolean isTrue(Boolean b) { return b != null && b.booleanValue(); } static void failIfUnlicensed() { assertTrue("license off", licensed()); } static Map vm_generalWeakSubMap(Object name) { synchronized(vm_generalMap()) { Map map = (Map) (vm_generalMap_get(name)); if (map == null) vm_generalMap_put(name, map = newWeakMap()); return map; } } static ArrayList emptyList() { return new ArrayList(); //ret Collections.emptyList(); } static ArrayList emptyList(int capacity) { return new ArrayList(max(0, capacity)); } // Try to match capacity static ArrayList emptyList(Iterable l) { return l instanceof Collection ? emptyList(((Collection) l).size()) : emptyList(); } static ArrayList emptyList(Object[] l) { return emptyList(l(l)); } // get correct type at once static ArrayList emptyList(Class c) { return new ArrayList(); } static List concatLists(Iterable... lists) { List l = new ArrayList(); if (lists != null) for (Iterable list : lists) addAll(l, list); return l; } static List concatLists(Collection> lists) { List l = new ArrayList(); if (lists != null) for (Iterable list : lists) addAll(l, list); return l; } static List sorted(Collection c, Object comparator) { List l = cloneList(c); sort(l, makeComparator(comparator)); return l; } static List sorted(Collection c) { List l = cloneList(c); sort(l); return l; } static List sorted(Comparator comparator, Collection c) { List l = cloneList(c); sort(l, comparator); return l; } static List methodsStartingWith(Object o, final String prefix) { return filter(allMethodNames(o), new F1() { public Object get(String s) { try { return startsWith(s, prefix); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "startsWith(s, prefix)"; }}); } static String programID() { return getProgramID(); } static String programID(Object o) { return getProgramID(o); } static volatile PersistableThrowable _handleException_lastException; static List _handleException_onException = synchroList(ll((IVF1) (__1 -> printStackTrace2(__1)))); static boolean _handleException_showThreadCancellations = false; static void _handleException(Throwable e) { _handleException_lastException = persistableThrowable(e); Throwable e2 = innerException(e); if (e2.getClass() == RuntimeException.class && eq(e2.getMessage(), "Thread cancelled.") || e2 instanceof InterruptedException) { if (_handleException_showThreadCancellations) System.out.println(getStackTrace_noRecord(e2)); return; } for (Object f : cloneList(_handleException_onException)) try { callF(f, e); } catch (Throwable e3) { try { printStackTrace2(e3); // not using pcall here - it could lead to endless loops } catch (Throwable e4) { System.out.println(getStackTrace(e3)); System.out.println(getStackTrace(e4)); } } } static int[] emptyIntArray_a = new int[0]; static int[] emptyIntArray() { return emptyIntArray_a; } static char[] emptyCharArray = new char[0]; static char[] emptyCharArray() { return emptyCharArray; } static double[] emptyDoubleArray = new double[0]; static double[] emptyDoubleArray() { return emptyDoubleArray; } static Map emptyMap() { return new HashMap(); } static Object[] emptyObjectArray_a = new Object[0]; static Object[] emptyObjectArray() { return emptyObjectArray_a; } static Symbol emptySymbol_value; static Symbol emptySymbol() { if (emptySymbol_value == null) emptySymbol_value = symbol(""); return emptySymbol_value; } static List ll(A... a) { ArrayList l = new ArrayList(a.length); if (a != null) for (A x : a) l.add(x); return l; } // unclear semantics as to whether return null on null static ArrayList asList(A[] a) { return a == null ? new ArrayList() : new ArrayList(Arrays.asList(a)); } static ArrayList asList(int[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (int i : a) l.add(i); return l; } static ArrayList asList(long[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (long i : a) l.add(i); return l; } static ArrayList asList(float[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (float i : a) l.add(i); return l; } static ArrayList asList(double[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (double i : a) l.add(i); return l; } static ArrayList asList(short[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (short i : a) l.add(i); return l; } static ArrayList asList(Iterator it) { ArrayList l = new ArrayList(); if (it != null) while (it.hasNext()) l.add(it.next()); return l; } // disambiguation static ArrayList asList(IterableIterator s) { return asList((Iterator) s); } static ArrayList asList(Iterable s) { if (s instanceof ArrayList) return (ArrayList) s; ArrayList l = new ArrayList(); if (s != null) for (A a : s) l.add(a); return l; } static ArrayList asList(Producer p) { ArrayList l = new ArrayList(); A a; if (p != null) while ((a = p.next()) != null) l.add(a); return l; } static ArrayList asList(Enumeration e) { ArrayList l = new ArrayList(); if (e != null) while (e.hasMoreElements()) l.add(e.nextElement()); return l; } static List asList(Pair p) { return p == null ? null : ll(p.a, p.b); } static String formatWithThousands(long l) { return formatWithThousandsSeparator(l); } static double fraction(double d) { return d % 1; } static String n_fancy2(long l, String singular, String plural) { return formatWithThousandsSeparator(l) + " " + trim(l == 1 ? singular : plural); } static String n_fancy2(Collection l, String singular, String plural) { return n_fancy2(l(l), singular, plural); } static String n_fancy2(Map m, String singular, String plural) { return n_fancy2(l(m), singular, plural); } static String n_fancy2(Object[] a, String singular, String plural) { return n_fancy2(l(a), singular, plural); } public static String join(String glue, Iterable strings) { if (strings == null) return ""; if (strings instanceof Collection) { if (((Collection) strings).size() == 1) return str(first((Collection) strings)); } StringBuilder buf = new StringBuilder(); Iterator i = strings.iterator(); if (i.hasNext()) { buf.append(i.next()); while (i.hasNext()) buf.append(glue).append(i.next()); } return buf.toString(); } public static String join(String glue, String... strings) { return join(glue, Arrays.asList(strings)); } public static String join(String glue, Object... strings) { return join(glue, Arrays.asList(strings)); } static String join(Iterable strings) { return join("", strings); } static String join(Iterable strings, String glue) { return join(glue, strings); } public static String join(String[] strings) { return join("", strings); } static String join(String glue, Pair p) { return p == null ? "" : str(p.a) + glue + str(p.b); } static boolean interruptThread_verbose = false; static void interruptThread(Thread t) { if (t == null) return; if (interruptThread_verbose) print("Interrupting thread " + t); // note reason in global map vm_threadInterruptionReasonsMap().put(t, getStackTrace()); t.interrupt(); URLConnection c = (URLConnection) (vm_generalSubMap("URLConnection per thread").get(t)); if (c != null) { try { print("Closing URLConnection of interrupted thread."); call(c, "disconnect"); } catch (Throwable __e) { printStackTrace(__e); }} } static boolean isJavaXClassLoader(ClassLoader cl) { return startsWithOneOf(className(cl), "main$JavaXClassLoader", "x30$JavaXClassLoader"); } static void setOptAll(Object o, Map fields) { if (fields == null) return; for (String field : keys(fields)) setOpt/*_flex*/(o, field, fields.get(field)); } static void setOptAll(Object o, Object... values) { //values = expandParams(c.getClass(), values); warnIfOddCount(values); for (int i = 0; i+1 < l(values); i += 2) { String field = (String) values[i]; Object value = values[i+1]; setOpt(o, field, value); } } static boolean isTrueOrYes(Object o) { return isTrueOpt(o) || o instanceof String && (eqicOneOf(((String) o), "1", "t", "true") || isYes(((String) o))); } static LinkedHashMap asLinkedHashMap(Map map) { if (map instanceof LinkedHashMap) return (LinkedHashMap) map; LinkedHashMap m = new LinkedHashMap(); if (map != null) synchronized(collectionMutex(map)) { m.putAll(map); } return m; } static void setDynObjectValue(DynamicObject o, String field, Object value) { dynamicObject_setRawFieldValue(o, field, value); } static void metaMapPut(IMeta o, Object key, Object value) { { if (o != null) o.metaPut(key, value); } } static void metaMapPut(Object o, Object key, Object value) { var meta = initIMeta(o); { if (meta != null) meta.metaPut(key, value); } } static final Map callOpt_cache = newDangerousWeakHashMap(); static Object callOpt_cached(Object o, String methodName, Object... args) { try { if (o == null) return null; if (o instanceof Class) { Class c = (Class) o; _MethodCache cache = callOpt_getCache(c); // TODO: (super-rare) case where method exists static and non-static // with different args Method me = cache.findMethod(methodName, args); if (me == null || (me.getModifiers() & Modifier.STATIC) == 0) return null; return invokeMethod(me, null, args); } else { Class c = o.getClass(); _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(methodName, args); if (me == null) return null; return invokeMethod(me, o, args); } } catch (Exception __e) { throw rethrow(__e); } } // no longer synchronizes! (see #1102990) static _MethodCache callOpt_getCache(Class c) { _MethodCache cache = callOpt_cache.get(c); if (cache == null) callOpt_cache.put(c, cache = new _MethodCache(c)); return cache; } static Object[] massageArgsForVarArgsCall(Method m, Object[] args) { Class[] types = m.getParameterTypes(); int n = types.length-1, nArgs = args.length; if (nArgs < n) return null; for (int i = 0; i < n; i++) if (!argumentCompatibleWithType(args[i], types[i])) return null; Class varArgType = types[n].getComponentType(); for (int i = n; i < nArgs; i++) if (!argumentCompatibleWithType(args[i], varArgType)) return null; Object[] newArgs = new Object[n+1]; arraycopy(args, 0, newArgs, 0, n); Object[] varArgs = arrayOfType(varArgType, nArgs-n); arraycopy(args, n, varArgs, 0, nArgs-n); newArgs[n] = varArgs; return newArgs; } // TODO: JDK 17!! ?? No! Yes? Yes!! static Object collectionMutex(List l) { return l; } static Object collectionMutex(Object o) { if (o instanceof List) return o; // TODO: actually use our own maps so we can get the mutex properly String c = className(o); return o; } static Object callFunction(Object f, Object... args) { return callF(f, args); } static Throwable _storeException_value; static void _storeException(Throwable e) { _storeException_value = e; } static Map vm_generalMap_map; static Map vm_generalMap() { if (vm_generalMap_map == null) vm_generalMap_map = (Map) get(javax(), "generalMap"); return vm_generalMap_map; } static Object vm_generalMap_get(Object key) { return vm_generalMap().get(key); } static Object vm_generalMap_put(Object key, Object value) { return mapPutOrRemove(vm_generalMap(), key, value); } static Map syncHashMap() { return synchroHashMap(); } static PersistableThrowable persistableThrowable(Throwable e) { return e == null ? null : new PersistableThrowable(e); } static boolean startsWithOneOf(String s, String... l) { for (String x : l) if (startsWith(s, x)) return true; return false; } static boolean startsWithOneOf(String s, Matches m, String... l) { for (String x : l) if (startsWith(s, x, m)) return true; return false; } static boolean isAGIBlueDomain(String domain) { return domainIsUnder(domain, theAGIBlueDomain()); } static String hostNameFromURL(String url) { try { return empty(url) ? null : new URL(url).getHost(); } catch (Exception __e) { throw rethrow(__e); } } static boolean isCurrentThread(Thread t) { return t != null && t == currentThread(); } static boolean isEitherB(Either e) { return eitherIsB(e); } static A eitherAOpt(Either e) { return e != null && e.isA() ? e.a() : null; } static String dropPrefix(String prefix, String s) { return s == null ? null : s.startsWith(prefix) ? s.substring(l(prefix)) : s; } static String appendQueryToURL(String url, Map params) { if (url == null) return null; String data = makePostData(params); if (empty(data)) return url; int idx = smartIndexOf(url, '#'); String url2 = takeFirst(url, idx); return url2 + (url2.contains("?") ? "&" : "?") + data + substring(url, idx); } static String appendQueryToURL(String url, Object... data) { return appendQueryToURL(url, paramsToMap(data)); } static String addPrefix(String prefix, String s) { return s.startsWith(prefix) ? s : prefix + s; } static Throwable getInnerException(Throwable e) { if (e == null) return null; while (e.getCause() != null) e = e.getCause(); return e; } static Throwable getInnerException(Runnable r) { return getInnerException(getException(r)); } static String baseClassName(String className) { return substring(className, className.lastIndexOf('.')+1); } static String baseClassName(Object o) { return baseClassName(getClassName(o)); } static String prependIfNempty(String prefix, String s) { return empty(s) ? unnull(s) : prefix + s; } static A proxy(Class intrface, final Object target) { if (target == null) return null; if (isInstance(intrface, target)) return (A) target; return (A) java.lang.reflect.Proxy.newProxyInstance(intrface.getClassLoader(), new Class[] { intrface }, new proxy_InvocationHandler(target)); } static A proxy(Object target, Class intrface) { return proxy(intrface, target); } static int parseIntOpt(String s) { return parseIntOpt(s, 0); } static int parseIntOpt(String s, int defValue) { return isInteger(s) ? parseInt(s) : defValue; } static String getFileInfoField(File f, String field) { return getOneLineFileInfoField(f, field); } static File localSnippetFile(long snippetID) { return localSnippetsDir(snippetID + ".text"); } static File localSnippetFile(String snippetID) { return localSnippetFile(parseSnippetID(snippetID)); } static boolean emptyString(String s) { return s == null || s.length() == 0; } static boolean networkAllowanceTest(String url) { return isAllowed("networkAllowanceTest", url); } static void sleepSeconds(double s) { if (s > 0) sleep(round(s*1000)); } static A printWithTime(A a) { return printWithTime("", a); } static A printWithTime(String s, A a) { print(hmsWithColons() + ": " + s, a); return a; } static A getAndClearThreadLocal(ThreadLocal tl) { A a = tl.get(); tl.set(null); return a; } static A optPar(ThreadLocal tl, A defaultValue) { A a = tl.get(); if (a != null) { tl.set(null); return a; } return defaultValue; } static A optPar(ThreadLocal tl) { return optPar(tl, null); } static Object optPar(Object[] params, String name) { return optParam(params, name); } static Object optPar(String name, Object[] params) { return optParam(params, name); } static Object optPar(String name, Map params) { return optParam(name, params); } static A optPar(Object[] params, String name, A defaultValue) { return optParam(params, name, defaultValue); } static A optPar(String name, Object[] params, A defaultValue) { return optParam(params, name, defaultValue); } static void setHeaders(URLConnection con) throws IOException { String computerID = getComputerID_quick(); if (computerID != null) try { con.setRequestProperty("X-ComputerID", computerID); con.setRequestProperty("X-OS", System.getProperty("os.name") + " " + System.getProperty("os.version")); } catch (Throwable e) { //printShortException(e); } } static Map vm_generalSubMap(Object name) { synchronized(vm_generalMap()) { Map map = (Map) (vm_generalMap_get(name)); if (map == null) vm_generalMap_put(name, map = synchroMap()); return map; } } static InputStream urlConnection_getInputStream(URLConnection con) throws IOException { return con.getInputStream(); } static GZIPInputStream newGZIPInputStream(File f) { return gzInputStream(f); } static GZIPInputStream newGZIPInputStream(InputStream in) { return gzInputStream(in); } static String unquote(String s) { if (s == null) return null; if (startsWith(s, '[')) { int i = 1; while (i < s.length() && s.charAt(i) == '=') ++i; if (i < s.length() && s.charAt(i) == '[') { String m = s.substring(1, i); if (s.endsWith("]" + m + "]")) return s.substring(i+1, s.length()-i-1); } } if (s.length() > 1) { char c = s.charAt(0); if (c == '\"' || c == '\'') { int l = endsWith(s, c) ? s.length()-1 : s.length(); StringBuilder sb = new StringBuilder(l-1); for (int i = 1; i < l; i++) { char ch = s.charAt(i); if (ch == '\\') { char nextChar = (i == l - 1) ? '\\' : s.charAt(i + 1); // Octal escape? if (nextChar >= '0' && nextChar <= '7') { String code = "" + nextChar; i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; } } sb.append((char) Integer.parseInt(code, 8)); continue; } switch (nextChar) { case '\"': ch = '\"'; break; case '\\': ch = '\\'; break; case 'b': ch = '\b'; break; case 'f': ch = '\f'; break; case 'n': ch = '\n'; break; case 'r': ch = '\r'; break; case 't': ch = '\t'; break; case '\'': ch = '\''; break; // Hex Unicode: u???? case 'u': if (i >= l - 5) { ch = 'u'; break; } int code = Integer.parseInt( "" + s.charAt(i + 2) + s.charAt(i + 3) + s.charAt(i + 4) + s.charAt(i + 5), 16); sb.append(Character.toChars(code)); i += 5; continue; default: ch = nextChar; // added by Stefan } i++; } sb.append(ch); } return sb.toString(); } } return s; // not quoted - return original } static String toHex(byte[] bytes) { return bytesToHex(bytes); } static String toHex(byte[] bytes, int ofs, int len) { return bytesToHex(bytes, ofs, len); } static byte[] utf8(String s) { return toUtf8(s); } static Matcher regexpMatcher(String pat, String s) { return compileRegexp(pat).matcher(unnull(s)); } static Matcher regexpMatcher(java.util.regex.Pattern pat, String s) { return pat.matcher(unnull(s)); } static URLConnection openConnection(String url) { try { return openConnection(new URL(url)); } catch (Exception __e) { throw rethrow(__e); } } static URLConnection openConnection(URL url) { try { ping(); callOpt(javax(), "recordOpenURLConnection", str(url)); return url.openConnection(); } catch (Exception __e) { throw rethrow(__e); } } static int toInt(Object o) { if (o == null) return 0; if (o instanceof Number) return ((Number) o).intValue(); if (o instanceof String) return parseInt((String) o); if (o instanceof Boolean) return boolToInt((Boolean) o); throw fail("woot not int: " + getClassName(o)); } static int toInt(long l) { if (l != (int) l) throw fail("Too large for int: " + l); return (int) l; } static URLConnection setURLConnectionTimeouts(URLConnection con, long timeout) { con.setConnectTimeout(toInt(timeout)); con.setReadTimeout(toInt(timeout)); if (con.getConnectTimeout() != timeout || con.getReadTimeout() != timeout) print("Warning: Timeouts not set by JDK."); return con; } static URLConnection setURLConnectionDefaultTimeouts(URLConnection con, long timeout) { if (con.getConnectTimeout() == 0) { con.setConnectTimeout(toInt(timeout)); if (con.getConnectTimeout() != timeout) print("Warning: URL connect timeout not set by JDK."); } if (con.getReadTimeout() == 0) { con.setReadTimeout(toInt(timeout)); if (con.getReadTimeout() != timeout) print("Warning: URL read timeout not set by JDK."); } return con; } static File getProgramFile(String progID, String fileName) { if (new File(fileName).isAbsolute()) return new File(fileName); return new File(getProgramDir(progID), fileName); } static File getProgramFile(String fileName) { return getProgramFile(getProgramID(), fileName); } static String standardCredentialsUser() { return trim(loadTextFile( oneOfTheFiles( javaxSecretDir("tinybrain-username"), userDir(".tinybrain/username")))); } static String standardCredentialsPass() { return trim(loadTextFile( oneOfTheFiles( javaxSecretDir("tinybrain-userpass"), userDir(".tinybrain/userpass")))); } static String urlencode(String x) { try { return URLEncoder.encode(unnull(x), "UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } static A setThreadLocal(ThreadLocal tl, A value) { if (tl == null) return null; A old = tl.get(); tl.set(value); return old; } static String hopeningTag(String tag, Map params) { return hopeningTag(tag, mapToParams(params)); } static String hopeningTag(String tag, Object... params) { StringBuilder buf = new StringBuilder(); buf.append("<" + tag); params = unrollParams(params); for (int i = 0; i < l(params); i += 2) { String name = (String) get(params, i); Object val = get(params, i+1); if (nempty(name) && val != null) { if (eqOneOf(val, html_valueLessParam(), true)) buf.append(" " + name); else { String s = str(val); if (!empty(s)) buf.append(" " + name + "=" + htmlQuote(s)); } } } buf.append(">"); return str(buf); } static String htag(String tag) { return htag(tag, ""); } static String htag(String tag, Object contents, Object... params) { String openingTag = hopeningTag(tag, params); String s = str(contents); if (empty(s) && neqic(tag, "script")) return dropLast(openingTag) + "/>"; return openingTag + s + ""; } static List takeFirst(List l, int n) { return l(l) <= n ? l : newSubListOrSame(l, 0, n); } static List takeFirst(int n, List l) { return takeFirst(l, n); } static String takeFirst(int n, String s) { return substring(s, 0, n); } static String takeFirst(String s, int n) { return substring(s, 0, n); } static CharSequence takeFirst(int n, CharSequence s) { return subCharSequence(s, 0, n); } static List takeFirst(int n, Iterator it) { if (it == null) return null; List l = new ArrayList(); for (int _repeat_0 = 0; _repeat_0 < n; _repeat_0++) { if (it.hasNext()) l.add(it.next()); else break; } return l; } static List takeFirst(int n, Iterable i) { if (i == null) return null; return i == null ? null : takeFirst(n, i.iterator()); } static List takeFirst(int n, IterableIterator i) { return takeFirst(n, (Iterator) i); } static int[] takeFirst(int n, int[] a) { return takeFirstOfIntArray(n, a); } static short[] takeFirst(int n, short[] a) { return takeFirstOfShortArray(n, a); } static byte[] takeFirst(int n, byte[] a) { return takeFirstOfByteArray(n, a); } static byte[] takeFirst(byte[] a, int n) { return takeFirstOfByteArray(n, a); } static double[] takeFirst(int n, double[] a) { return takeFirstOfDoubleArray(n, a); } static double[] takeFirst(double[] a, int n) { return takeFirstOfDoubleArray(n, a); } static String intToHex_flexLength(int i) { return Integer.toHexString(i); } static String sourceCodeToHTML_noEncode(String html) { return "
" + html + "
"; } static String htmlencode2(String s) { return htmlencode_noQuotes(s); } static String hjavascript(String scriptOrURL, Object... __) { if (isRelativeOrAbsoluteURL(scriptOrURL) && !startsWithOneOf(scriptOrURL, "//", "/*")) return hjavascript_src(scriptOrURL, __); else return tag("script", scriptOrURL, paramsPlus(__, "type" , "text/javascript")); } static String mainClassNameForClassLoader(ClassLoader cl) { return or((String) callOpt(cl, "mainClassName"), "main"); } static Class loadClassFromClassLoader_orNull(ClassLoader cl, String name) { try { return cl == null ? null : cl.loadClass(name); } catch (ClassNotFoundException e) { return null; } } static
WeakReference weakRef(A a) { return newWeakReference(a); } static HashMap> callMC_cache = new HashMap(); static String callMC_key; static Method callMC_value; // varargs assignment fixer for a single string array argument static Object callMC(String method, String[] arg) { return callMC(method, new Object[] {arg}); } static Object callMC(String method, Object... args) { try { Method me; if (callMC_cache == null) callMC_cache = new HashMap(); // initializer time workaround synchronized(callMC_cache) { me = method == callMC_key ? callMC_value : null; } if (me != null) try { return invokeMethod(me, null, args); } catch (IllegalArgumentException e) { throw new RuntimeException("Can't call " + me + " with arguments " + classNames(args), e); } List m; synchronized(callMC_cache) { m = callMC_cache.get(method); } if (m == null) { if (callMC_cache.isEmpty()) { callMC_makeCache(); m = callMC_cache.get(method); } if (m == null) throw fail("Method named " + method + " not found in main"); } int n = m.size(); if (n == 1) { me = m.get(0); synchronized(callMC_cache) { callMC_key = method; callMC_value = me; } try { return invokeMethod(me, null, args); } catch (IllegalArgumentException e) { throw new RuntimeException("Can't call " + me + " with arguments " + classNames(args), e); } } for (int i = 0; i < n; i++) { me = m.get(i); if (call_checkArgs(me, args, false)) return invokeMethod(me, null, args); } throw fail("No method called " + method + " with arguments (" + joinWithComma(getClasses(args)) + ") found in main"); } catch (Exception __e) { throw rethrow(__e); } } static void callMC_makeCache() { synchronized(callMC_cache) { callMC_cache.clear(); Class _c = (Class) mc(), c = _c; while (c != null) { for (Method m : c.getDeclaredMethods()) if ((m.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) { makeAccessible(m); multiMapPut(callMC_cache, m.getName(), m); } c = c.getSuperclass(); } } } static List synchroList() { return synchroList(new ArrayList()); } static List synchroList(List l) { return Collections.synchronizedList(l); } static Pair pair(A a, B b) { return new Pair(a, b); } static Pair pair(A a) { return new Pair(a, a); } static Map synchroHashMap() { return synchronizedMap(new HashMap()); } static ClassLoader classLoaderForObject(Object o) { if (o instanceof ClassLoader) return ((ClassLoader) o); if (o == null) return null; return _getClass(o).getClassLoader(); } // Note: This is actually broken. Inner classes must stay with a $ separator static String classNameToVM(String name) { return name.replace(".", "$"); } static HashSet litset(A... items) { return lithashset(items); } static WeakReference creator_class; static Object creator() { return creator_class == null ? null : creator_class.get(); } static Object dm_callOS(String functionName, Object... args) { return call(dm_os(), functionName, args); } static boolean isInstance(Class type, Object arg) { return type.isInstance(arg); } static A getWeakRef(Reference ref) { return ref == null ? null : ref.get(); } static x30_pkg.x30_util.BetterThreadLocal dm_current_generic_tl; static x30_pkg.x30_util.BetterThreadLocal dm_current_generic_tl() { if (dm_current_generic_tl == null) dm_current_generic_tl = vm_generalMap_getOrCreate("currentModule", () -> new x30_pkg.x30_util.BetterThreadLocal()); return dm_current_generic_tl; } static Set synchronizedSet() { return synchroHashSet(); } static Set synchronizedSet(Set set) { return Collections.synchronizedSet(set); } static Set identityHashSet() { return Collections.newSetFromMap(new IdentityHashMap()); } static Pair mapEntryToPair(Map.Entry e) { return e == null ? null : pair(e.getKey(), e.getValue()); } static Set> entrySet(Map map) { return _entrySet(map); } static A firstThat(Iterable l, IF1 pred) { for (A a : unnullForIteration(l)) if (pred.get(a)) return a; return null; } static A firstThat(A[] l, IF1 pred) { for (A a : unnullForIteration(l)) if (pred.get(a)) return a; return null; } static A firstThat(IF1 pred, Iterable l) { return firstThat(l, pred); } static A firstThat(IF1 pred, A[] l) { return firstThat(l, pred); } static Iterator iterator(Iterable c) { return c == null ? emptyIterator() : c.iterator(); } static char charAt(String s, int i) { return s != null && i >= 0 && i < s.length() ? s.charAt(i) : '\0'; } static A _get(List l, int idx) { return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null; } static Object _get(Object o, String field) { return get(o, field); } static Object _get(String field, Object o) { return get(o, field); } static A _get(A[] l, int idx) { return idx >= 0 && idx < l(l) ? l[idx] : null; } static boolean regionMatches(String a, int offsetA, String b, int offsetB, int len) { return a != null && b != null && a.regionMatches(offsetA, b, offsetB, len); } static boolean regionMatches(String a, int offsetA, String b) { return regionMatches(a, offsetA, b, 0, l(b)); } static String javaTok_substringN(String s, int i, int j) { if (i == j) return ""; if (j == i+1 && s.charAt(i) == ' ') return " "; return s.substring(i, j); } static String javaTok_substringC(String s, int i, int j) { return s.substring(i, j); } static List javaTokWithExisting(String s, List existing) { ++javaTok_n; int nExisting = javaTok_opt && existing != null ? existing.size() : 0; ArrayList tok = existing != null ? new ArrayList(nExisting) : new ArrayList(); int l = s.length(); int i = 0, n = 0; while (i < l) { int j = i; char c, d; // scan for whitespace while (j < l) { c = s.charAt(j); d = j+1 >= l ? '\0' : s.charAt(j+1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j+2, l)).equals("*/")); j = Math.min(j+2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } if (n < nExisting && javaTokWithExisting_isCopyable(existing.get(n), s, i, j)) tok.add(existing.get(n)); else tok.add(javaTok_substringN(s, i, j)); ++n; i = j; if (i >= l) break; c = s.charAt(i); d = i+1 >= l ? '\0' : s.charAt(i+1); // scan for non-whitespace // Special JavaX syntax: 'identifier if (c == '\'' && Character.isJavaIdentifierStart(d) && i+2 < l && "'\\".indexOf(s.charAt(i+2)) < 0) { j += 2; while (j < l && Character.isJavaIdentifierPart(s.charAt(j))) ++j; } else if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener /*|| s.charAt(j) == '\n'*/) { // allow multi-line strings ++j; break; } else if (s.charAt(j) == '\\' && j+1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || "'".indexOf(s.charAt(j)) >= 0)); // for stuff like "don't" else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; // Long constants like 1L } else if (c == '[' && d == '[') { do ++j; while (j+1 < l && !s.substring(j, j+2).equals("]]")); j = Math.min(j+2, l); } else if (c == '[' && d == '=' && i+2 < l && s.charAt(i+2) == '[') { do ++j; while (j+2 < l && !s.substring(j, j+3).equals("]=]")); j = Math.min(j+3, l); } else ++j; if (n < nExisting && javaTokWithExisting_isCopyable(existing.get(n), s, i, j)) tok.add(existing.get(n)); else tok.add(javaTok_substringC(s, i, j)); ++n; i = j; } if ((tok.size() % 2) == 0) tok.add(""); javaTok_elements += tok.size(); return tok; } static boolean javaTokWithExisting_isCopyable(String t, String s, int i, int j) { return t.length() == j-i && s.regionMatches(i, t, 0, j-i); // << could be left out, but that's brave } static ITokCondition tokCondition(IIntPred condition) { return condition == null ? null : (tok, nIdx) -> condition.get(nIdx); } static Map javaTokForJFind_array_cache = synchronizedMRUCache(1000); static String[] javaTokForJFind_array(String s) { String[] tok = javaTokForJFind_array_cache.get(s); if (tok == null) javaTokForJFind_array_cache.put(s, tok = codeTokensAsStringArray(jfind_preprocess(javaTok(s)))); return tok; } // Note: In the transpiler, this version is used: #1025802 static int findCodeTokens(List tok, String... tokens) { return findCodeTokens(tok, 1, false, tokens); } static int findCodeTokens(List tok, boolean ignoreCase, String... tokens) { return findCodeTokens(tok, 1, ignoreCase, tokens); } static int findCodeTokens(List tok, int startIdx, boolean ignoreCase, String... tokens) { return findCodeTokens(tok, startIdx, ignoreCase, tokens, null); } static HashSet findCodeTokens_specials = lithashset("*", "", "", "", "\\*"); static int findCodeTokens_bails, findCodeTokens_nonbails; static interface findCodeTokens_Matcher { boolean get(String token); } static int findCodeTokens(List tok, int startIdx, boolean ignoreCase, String[] tokens, Object condition) { int end = tok.size()-tokens.length*2+2, nTokens = tokens.length; int i = startIdx | 1; if (i >= end) return -1; // bail out early if first token not found (works great with IndexedList) String firstToken = tokens[0]; if (!ignoreCase && !findCodeTokens_specials.contains(firstToken)) { // quickly scan for first token while (i < end && !firstToken.equals(tok.get(i))) i += 2; } findCodeTokens_Matcher[] matchers = new findCodeTokens_Matcher[nTokens]; for (int j = 0; j < nTokens; j++) { String p = tokens[j]; findCodeTokens_Matcher matcher; if (p.equals("*")) matcher = t -> true; else if (p.equals("")) matcher = t -> isQuoted(t); else if (p.equals("")) matcher = t -> isIdentifier(t); else if (p.equals("")) matcher = t -> isInteger(t); else if (p.equals("\\*")) matcher = t -> t.equals("*"); else if (ignoreCase) matcher = t -> eqic(p, t); else matcher = t -> t.equals(p); matchers[j] = matcher; } outer: for (; i < end; i += 2) { for (int j = 0; j < nTokens; j++) if (!matchers[j].get(tok.get(i+j*2))) continue outer; if (condition == null || checkTokCondition(condition, tok, i-1)) // pass N index return i; } return -1; } static String[] codeTokensAsStringArray(List tok) { int n = max(0, (l(tok)-1)/2); String[] out = new String[n]; for (int i = 0; i < n; i++) out[i] = tok.get(i*2+1); return out; } static ArrayList litlist(A... a) { ArrayList l = new ArrayList(a.length); for (A x : a) l.add(x); return l; } // syntax 1: replace all occurrences of x in l with y static List replaceSublist(List l, List x, List y) { if (x == null) return l; int i = 0; while (true) { i = indexOfSubList(l, x, i); if (i < 0) break; replaceSublist(l, i, i+l(x), y); i += l(y); } return l; } // syntax 2: splice l at fromIndex-toIndex and replace middle part with y static List replaceSublist(List l, int fromIndex, int toIndex, List y) { int n = y.size(), toIndex_new = fromIndex+n; if (toIndex_new < toIndex) { removeSubList(l, toIndex_new, toIndex); copyListPart(y, 0, l, fromIndex, n); } else { copyListPart(y, 0, l, fromIndex, toIndex-fromIndex); if (toIndex_new > toIndex) l.addAll(toIndex, subList(y, toIndex-fromIndex)); } return l; } static List subList(List l, int startIndex) { return subList(l, startIndex, l(l)); } static List subList(int startIndex, List l) { return subList(l, startIndex); } static List subList(int startIndex, int endIndex, List l) { return subList(l, startIndex, endIndex); } static List subList(List l, int startIndex, int endIndex) { if (l == null) return null; int n = l(l); startIndex = Math.max(0, startIndex); endIndex = Math.min(n, endIndex); if (startIndex > endIndex) return ll(); if (startIndex == 0 && endIndex == n) return l; return l.subList(startIndex, endIndex); } static List getClassNames(Collection l) { List out = new ArrayList(); if (l != null) for (Object o : l) out.add(o == null ? null : getClassName(o)); return out; } static String dropSuffix(String suffix, String s) { return nempty(suffix) && endsWith(s, suffix) ? s.substring(0, l(s)-l(suffix)) : s; } static boolean isStaticMethod(Method m) { return methodIsStatic(m); } static void _onJavaXSet() {} static int isAndroid_flag; static boolean isAndroid() { if (isAndroid_flag == 0) isAndroid_flag = System.getProperty("java.vendor").toLowerCase().indexOf("android") >= 0 ? 1 : -1; return isAndroid_flag > 0; } static List _registerWeakMap_preList; static A _registerWeakMap(A map) { if (javax() == null) { // We're in class init if (_registerWeakMap_preList == null) _registerWeakMap_preList = synchroList(); _registerWeakMap_preList.add(map); return map; } try { call(javax(), "_registerWeakMap", map); } catch (Throwable e) { printException(e); print("Upgrade JavaX!!"); } return map; } static void _onLoad_registerWeakMap() { assertNotNull(javax()); if (_registerWeakMap_preList == null) return; for (Object o : _registerWeakMap_preList) _registerWeakMap(o); _registerWeakMap_preList = null; } static x30_pkg.x30_util.BetterThreadLocal newPing_actionTL; static x30_pkg.x30_util.BetterThreadLocal newPing_actionTL() { if (newPing_actionTL == null) newPing_actionTL = vm_generalMap_getOrCreate("newPing_actionTL", () -> { Runnable value = (Runnable) (callF_gen(vm_generalMap_get("newPing_valueForNewThread"))); var tl = new x30_pkg.x30_util.BetterThreadLocal(); tl.set(value); return tl; }); return newPing_actionTL; } static Boolean isHeadless_cache; static boolean isHeadless() { if (isHeadless_cache != null) return isHeadless_cache; if (isAndroid()) return isHeadless_cache = true; if (GraphicsEnvironment.isHeadless()) return isHeadless_cache = true; // Also check if AWT actually works. // If DISPLAY variable is set but no X server up, this will notice. try { SwingUtilities.isEventDispatchThread(); return isHeadless_cache = false; } catch (Throwable e) { return isHeadless_cache = true; } } static volatile boolean licensed_yes = true; static boolean licensed() { if (!licensed_yes) return false; ping_okInCleanUp(); return true; } static void licensed_off() { licensed_yes = false; } static Map newWeakMap() { return newWeakHashMap(); } static int max(int a, int b) { return Math.max(a, b); } static int max(int a, int b, int c) { return max(max(a, b), c); } static long max(int a, long b) { return Math.max((long) a, b); } static long max(long a, long b) { return Math.max(a, b); } static double max(int a, double b) { return Math.max((double) a, b); } static float max(float a, float b) { return Math.max(a, b); } static double max(double a, double b) { return Math.max(a, b); } static int max(Collection c) { int x = Integer.MIN_VALUE; for (int i : c) x = max(x, i); return x; } static double max(double[] c) { if (c.length == 0) return Double.MIN_VALUE; double x = c[0]; for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]); return x; } static float max(float[] c) { if (c.length == 0) return Float.MAX_VALUE; float x = c[0]; for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]); return x; } static byte max(byte[] c) { byte x = -128; for (byte d : c) if (d > x) x = d; return x; } static short max(short[] c) { short x = -0x8000; for (short d : c) if (d > x) x = d; return x; } static int max(int[] c) { int x = Integer.MIN_VALUE; for (int d : c) if (d > x) x = d; return x; } static > A max(A a, A b) { return cmp(a, b) >= 0 ? a : b; } static void addAll(Collection c, Iterable b) { if (c != null && b != null) for (A a : b) c.add(a); } static boolean addAll(Collection c, Collection b) { return c != null && b != null && c.addAll(b); } static boolean addAll(Collection c, B... b) { return c != null && b != null && c.addAll(Arrays.asList(b)); } static Map addAll(Map a, Map b) { if (a != null && b != null) a.putAll(b); return a; } static void sort(T[] a, Comparator c) { if (a != null) Arrays.sort(a, c); } static void sort(T[] a) { if (a != null) Arrays.sort(a); } static void sort(int[] a) { if (a != null) Arrays.sort(a); } static void sort(List a, Comparator c) { if (a != null) Collections.sort(a, c); } static void sort(List a) { if (a != null) Collections.sort(a); } static Comparator makeComparator(final Object f) { if (f instanceof Comparator) return (Comparator) f; return new Comparator() { public int compare(Object a, Object b) { return (Integer) callF(f, a, b); } }; } static List filter(Iterable c, Object pred) { if (pred instanceof F1) return filter(c, (F1) pred); List x = new ArrayList(); if (c != null) for (Object o : c) if (isTrue(callF(pred, o))) x.add(o); return x; } static List filter(Object pred, Iterable c) { return filter(c, pred); } static List filter(Iterable c, F1 pred) { List x = new ArrayList(); if (c != null) for (B o : c) if (pred.get(o)) x.add(o); return x; } static List filter(F1 pred, Iterable c) { return filter(c, pred); } //ifclass IF1 static List filter(Iterable c, IF1 pred) { List x = new ArrayList(); if (c != null) for (B o : c) if (pred.get(o)) x.add(o); return x; } static List filter(B[] c, IF1 pred) { List x = new ArrayList(); if (c != null) for (B o : c) if (pred.get(o)) x.add(o); return x; } static List filter(IF1 pred, Iterable c) { return filter(c, pred); } //endif static List allMethodNames(Object o) { Class c = _getClass(o); TreeSet names = new TreeSet(); while (c != null) { for (Method m : c.getDeclaredMethods()) names.add(m.getName()); c = c.getSuperclass(); } return asList(names); } static boolean startsWith(String a, String b) { return a != null && a.startsWith(unnull(b)); } static boolean startsWith(String a, char c) { return nemptyString(a) && a.charAt(0) == c; } static boolean startsWith(String a, String b, Matches m) { if (!startsWith(a, b)) return false; if (m != null) m.m = new String[] {substring(a, strL(b))}; return true; } static boolean startsWith(List a, List b) { if (a == null || listL(b) > listL(a)) return false; for (int i = 0; i < listL(b); i++) if (neq(a.get(i), b.get(i))) return false; return true; } static Throwable printStackTrace2(Throwable e) { // we go to system.out now - system.err is nonsense print(getStackTrace2(e)); return e; } static void printStackTrace2() { printStackTrace2(new Throwable()); } static void printStackTrace2(String msg) { printStackTrace2(new Throwable(msg)); } static Throwable innerException(Throwable e) { return getInnerException(e); } static WeakHasherMap symbol_map = new WeakHasherMap(new Hasher() { public int hashCode(Symbol symbol) { return symbol.text.hashCode(); } public boolean equals(Symbol a, Symbol b) { if (a == null) return b == null; return b != null && eq(a.text, b.text); } }); static Symbol symbol(String s) { if (s == null) return null; synchronized(symbol_map) { // TODO: avoid object creation by passing the string to findKey Symbol symbol = new Symbol(s, true); Symbol existingSymbol = symbol_map.findKey(symbol); if (existingSymbol == null) symbol_map.put(existingSymbol = symbol, true); return existingSymbol; } } static Symbol symbol(CharSequence s) { if (s == null) return null; if (s instanceof Symbol) return (Symbol) s; if (s instanceof String) return symbol((String) s); return symbol(str(s)); } static Symbol symbol(Object o) { return symbol((CharSequence) o); } static String formatWithThousandsSeparator(long l) { return NumberFormat.getInstance(new Locale("en_US")).format(l); } static String className(Object o) { return getClassName(o); } static void warnIfOddCount(Object... list) { if (odd(l(list))) printStackTrace("Odd list size: " + list); } static boolean isTrueOpt(Object o) { if (o instanceof Boolean) return ((Boolean) o).booleanValue(); return false; } static boolean isTrueOpt(String field, Object o) { return isTrueOpt(getOpt(field, o)); } static boolean eqicOneOf(String s, String... l) { for (String x : l) if (eqic(s, x)) return true; return false; } static List isYes_yesses = litlist("y", "yes", "yeah", "y", "yup", "yo", "corect", "sure", "ok", "afirmative"); // << collapsed words, so "corect" means "correct" static boolean isYes(String s) { return isYes_yesses.contains(collapseWord(toLowerCase(firstWord2(s)))); } static void dynamicObject_setRawFieldValue(DynamicObject o, Object key, Object value) { if (o == null) return; // double sync, but should be OK here because of locking order o > o.fieldValues synchronized(o) { o.fieldValues = syncMapPut2_createLinkedHashMap((LinkedHashMap) o.fieldValues, key, value); } } static IMeta initIMeta(Object o) { if (o == null) return null; if (o instanceof IMeta) return ((IMeta) o); if (o instanceof JComponent) return initMetaOfJComponent((JComponent) o); if (o instanceof BufferedImage) return optCast(IMeta.class, ((BufferedImage) o).getProperty("meta")); return null; } static boolean argumentCompatibleWithType(Object arg, Class type) { return arg == null ? !type.isPrimitive() : isInstanceX(type, arg); } static void arraycopy(Object[] a, Object[] b) { if (a != null && b != null) arraycopy(a, 0, b, 0, Math.min(a.length, b.length)); } static void arraycopy(Object src, int srcPos, int destPos, int n) { arraycopy(src, srcPos, src, destPos, n); } static void arraycopy(Object src, int srcPos, Object dest, int destPos, int n) { if (n != 0) System.arraycopy(src, srcPos, dest, destPos, n); } static A[] arrayOfType(Class type, int n) { return makeArray(type, n); } static A[] arrayOfType(int n, Class type) { return arrayOfType(type, n); } static B mapPutOrRemove(Map map, A key, B value) { if (map != null && key != null) if (value != null) return map.put(key, value); else return map.remove(key); return null; } static boolean domainIsUnder(String domain, String mainDomain) { return eqic(domain, mainDomain) || ewic(domain, "." + mainDomain); } static String theAGIBlueDomain() { return "agi.blue"; } static boolean eitherIsB(Either e) { return e != null && e.isB(); } static String makePostData(Map map) { StringBuilder buf = new StringBuilder(); for (Map.Entry e : castMapToMapO(map).entrySet()) { String key = (String) (e.getKey()); Object val = e.getValue(); if (val != null) { String value = str(val); if (nempty(buf)) buf.append("&"); buf.append(urlencode(key)).append("=").append(urlencode(/*escapeMultichars*/(value))); } } return str(buf); } static String makePostData(Object... params) { StringBuilder buf = new StringBuilder(); int n = l(params); for (int i = 0; i+1 < n; i += 2) { String key = (String) (params[i]); Object val = params[i+1]; if (val != null) { String value = str(val); if (nempty(buf)) buf.append("&"); buf.append(urlencode(key)).append("=").append(urlencode(/*escapeMultichars*/(value))); } } return str(buf); } // returns l(s) if not found static int smartIndexOf(String s, String sub, int i) { if (s == null) return 0; i = s.indexOf(sub, min(i, l(s))); return i >= 0 ? i : l(s); } static int smartIndexOf(String s, int i, char c) { return smartIndexOf(s, c, i); } static int smartIndexOf(String s, char c, int i) { if (s == null) return 0; i = s.indexOf(c, min(i, l(s))); return i >= 0 ? i : l(s); } static int smartIndexOf(String s, String sub) { return smartIndexOf(s, sub, 0); } static int smartIndexOf(String s, char c) { return smartIndexOf(s, c, 0); } static int smartIndexOf(List l, A sub) { return smartIndexOf(l, sub, 0); } static int smartIndexOf(List l, int start, A sub) { return smartIndexOf(l, sub, start); } static int smartIndexOf(List l, A sub, int start) { int i = indexOf(l, sub, start); return i < 0 ? l(l) : i; } static Map paramsToMap(Object... params) { int n = l(params); if (l(params) == 1 && params[0] instanceof Map) return (Map) params[0]; LinkedHashMap map = new LinkedHashMap(); for (int i = 0; i+1 < n; i += 2) mapPut(map, params[i], params[i+1]); return map; } static Throwable getException(Runnable r) { try { callF(r); return null; } catch (Throwable e) { return e; } } static boolean isInteger(String s) { int n = l(s); if (n == 0) return false; int i = 0; if (s.charAt(0) == '-') if (++i >= n) return false; while (i < n) { char c = s.charAt(i); if (c < '0' || c > '9') return false; ++i; } return true; } static String getOneLineFileInfoField(File f, String field) { File infoFile = associatedInfosFile(f); List lines = lines(loadTextFile(infoFile)); return firstStartingWithIC_drop(lines, field + ": "); } static File localSnippetsDir() { return javaxDataDir("Personal Programs"); } static File localSnippetsDir(String sub) { return newFile(localSnippetsDir(), sub); } static volatile Object isAllowed_function; // func(S, O[]) -> bool static volatile boolean isAllowed_all = true; static boolean isAllowed(String askingMethod, Object... args) { // check on VM level Object f = vm_generalMap_get("isAllowed_function"); if (f != null && !isTrue(callF(f, askingMethod, args))) return false; // check locally return isAllowed_all || isTrue(callF(isAllowed_function, askingMethod, args)); } static volatile boolean sleep_noSleep = false; static void sleep(long ms) { ping(); if (ms < 0) return; // allow spin locks if (isAWTThread() && ms > 100) throw fail("Should not sleep on AWT thread"); try { Thread.sleep(ms); } catch (Exception e) { throw new RuntimeException(e); } } static void sleep() { try { if (sleep_noSleep) throw fail("nosleep"); print("Sleeping."); sleepQuietly(); } catch (Exception __e) { throw rethrow(__e); } } static long round(double d) { return Math.round(d); } static String round(String s) { return roundBracket(s); } static Complex round(Complex c) { return new Complex(round(c.re), round(c.im)); } static String hmsWithColons() { return hmsWithColons(now()); } static String hmsWithColons(long time) { return new SimpleDateFormat("HH:mm:ss").format(time); } static A optParam(ThreadLocal tl, A defaultValue) { return optPar(tl, defaultValue); } static A optParam(ThreadLocal tl) { return optPar(tl); } static Object optParam(String name, Map params) { return mapGet(params, name); } // now also takes a map as single array entry static A optParam(Object[] opt, String name, A defaultValue) { int n = l(opt); if (n == 1 && opt[0] instanceof Map) { Map map = (Map) (opt[0]); return map.containsKey(name) ? (A) map.get(name) : defaultValue; } if (!even(l(opt))) throw fail("Odd parameter length"); for (int i = 0; i < l(opt); i += 2) if (eq(opt[i], name)) return (A) opt[i+1]; return defaultValue; } static Object optParam(Object[] opt, String name) { return optParam(opt, name, null); } static Object optParam(String name, Object[] params) { return optParam(params, name); } static String getComputerID_quick() { return computerID(); } static int gzInputStream_defaultBufferSize = 65536; static GZIPInputStream gzInputStream(File f) { try { return gzInputStream(new FileInputStream(f)); } catch (Exception __e) { throw rethrow(__e); } } static GZIPInputStream gzInputStream(File f, int bufferSize) { try { return gzInputStream(new FileInputStream(f), bufferSize); } catch (Exception __e) { throw rethrow(__e); } } static GZIPInputStream gzInputStream(InputStream in) { return gzInputStream(in, gzInputStream_defaultBufferSize); } static GZIPInputStream gzInputStream(InputStream in, int bufferSize) { try { return _registerIOWrap(new GZIPInputStream(in, gzInputStream_defaultBufferSize), in); } catch (Exception __e) { throw rethrow(__e); } } static boolean endsWith(String a, String b) { return a != null && a.endsWith(b); } static boolean endsWith(String a, char c) { return nempty(a) && lastChar(a) == c; } static boolean endsWith(String a, String b, Matches m) { if (!endsWith(a, b)) return false; m.m = new String[] {dropLast(l(b), a)}; return true; } public static String bytesToHex(byte[] bytes) { return bytesToHex(bytes, 0, bytes.length); } public static String bytesToHex(byte[] bytes, int ofs, int len) { StringBuilder stringBuilder = new StringBuilder(len*2); for (int i = 0; i < len; i++) { String s = "0" + Integer.toHexString(bytes[ofs+i]); stringBuilder.append(s.substring(s.length()-2, s.length())); } return stringBuilder.toString(); } static byte[] toUtf8(String s) { try { return s.getBytes(utf8charset()); } catch (Exception __e) { throw rethrow(__e); } } static Map compileRegexp_cache = syncMRUCache(10); static java.util.regex.Pattern compileRegexp(String pat) { java.util.regex.Pattern p = compileRegexp_cache.get(pat); if (p == null) { compileRegexp_cache.put(pat, p = java.util.regex.Pattern.compile(pat)); } return p; } static int boolToInt(boolean b) { return b ? 1 : 0; } static File getProgramDir() { return programDir(); } static File getProgramDir(String snippetID) { return programDir(snippetID); } static File oneOfTheFiles(String... paths) { if (paths != null) for (String path : paths) if (fileExists(path)) return newFile(path); return null; } static File oneOfTheFiles(File... files) { return oneOfTheFiles(asList(files)); } static File oneOfTheFiles(Iterable files) { if (files != null) for (File f : files) if (fileExists(f)) return f; return null; } static Object[] mapToParams(Map map) { return mapToObjectArray(map); } static Object[] unrollParams(Object[] params) { if (l(params) == 1 && params[0] instanceof Map) return mapToParams((Map) params[0]); return params; } static boolean eqOneOf(Object o, Object... l) { for (Object x : l) if (eq(o, x)) return true; return false; } static Object html_valueLessParam_cache; static Object html_valueLessParam() { if (html_valueLessParam_cache == null) html_valueLessParam_cache = html_valueLessParam_load(); return html_valueLessParam_cache;} static Object html_valueLessParam_load() { return new Object(); } static String htmlQuote(String s) { return "\"" + htmlencode_forParams(s) + "\""; } static boolean neqic(String a, String b) { return !eqic(a, b); } static boolean neqic(char a, char b) { return !eqic(a, b); } static A[] dropLast(A[] a) { return dropLast(a, 1); } static A[] dropLast(A[] a, int n) { if (a == null) return null; n = Math.min(n, a.length); A[] b = arrayOfSameType(a, a.length-n); System.arraycopy(a, 0, b, 0, b.length); return b; } static List dropLast(List l) { return subList(l, 0, l(l)-1); } static List dropLast(int n, List l) { return subList(l, 0, l(l)-n); } static List dropLast(Iterable l) { return dropLast(asList(l)); } static String dropLast(String s) { return substring(s, 0, l(s)-1); } static String dropLast(String s, int n) { return substring(s, 0, l(s)-n); } static String dropLast(int n, String s) { return dropLast(s, n); } static List newSubListOrSame(List l, int startIndex) { return newSubListOrSame(l, startIndex, l(l)); } static List newSubListOrSame(List l, int startIndex, int endIndex) { if (l == null) return null; int n = l(l); startIndex = max(0, startIndex); endIndex = min(n, endIndex); if (startIndex >= endIndex) return ll(); if (startIndex == 0 && endIndex == n) return l; return cloneList(l.subList(startIndex, endIndex)); } static CharSequence subCharSequence(CharSequence s, int x) { return subCharSequence(s, x, s == null ? 0 : s.length()); } static CharSequence subCharSequence(CharSequence s, int x, int y) { if (s == null) return null; if (x < 0) x = 0; if (x >= s.length()) return ""; if (y < x) y = x; if (y > s.length()) y = s.length(); return s.subSequence(x, y); } static int[] takeFirstOfIntArray(int[] b, int n) { return subIntArray(b, 0, n); } static int[] takeFirstOfIntArray(int n, int[] b) { return takeFirstOfIntArray(b, n); } static short[] takeFirstOfShortArray(short[] b, int n) { return subShortArray(b, 0, n); } static short[] takeFirstOfShortArray(int n, short[] b) { return takeFirstOfShortArray(b, n); } static byte[] takeFirstOfByteArray(byte[] b, int n) { return subByteArray(b, 0, n); } static byte[] takeFirstOfByteArray(int n, byte[] b) { return takeFirstOfByteArray(b, n); } static double[] takeFirstOfDoubleArray(double[] b, int n) { return subDoubleArray(b, 0, n); } static double[] takeFirstOfDoubleArray(int n, double[] b) { return takeFirstOfDoubleArray(b, n); } static boolean isRelativeOrAbsoluteURL(String s) { return isAbsoluteURL(s) || isRelativeURL(s); } static String hjavascript_src(String src, Object... __) { return hfulltag("script", "", paramsPlus(__, "src", src)); } static Object[] paramsPlus(Object[] a1, Object... a2) { if (a2 == null) return a1; if (a1 == null) return a2; if (l(a1) == 1 && a1[0] instanceof Map) return new Object[] { mapPlus((Map) a1[0], a2) }; assertEvenLength(a1); assertEvenLength(a2); Map map = paramsToOrderedMap(a1); int n = l(a2); for (int i = 0; i < n; i += 2) { Object key = a2[i]; if (key != null) map.put(key, a2[i+1]); } return mapToParams(map); } static Object[] paramsPlus(Map a1, Object... a2) { return paramsPlus(new Object[] {a1}, a2); } static WeakReference newWeakReference(A a) { return a == null ? null : new WeakReference(a); } static List getClasses(Object[] array) { List l = emptyList(l(array)); for (Object o : array) l.add(_getClass(o)); return l; } static void multiMapPut(Map> map, A a, B b) { List l = map.get(a); if (l == null) map.put(a, l = new ArrayList()); l.add(b); } static void multiMapPut(MultiMap mm, A key, B value) { if (mm != null && key != null && value != null) mm.put(key, value); } static Map synchronizedMap() { return synchroMap(); } static Map synchronizedMap(Map map) { return synchroMap(map); } static HashSet lithashset(A... items) { HashSet set = new HashSet(); for (A a : items) set.add(a); return set; } static A vm_generalMap_getOrCreate(Object key, F0 create) { return vm_generalMap_getOrCreate(key, f0ToIF0(create)); } static A vm_generalMap_getOrCreate(Object key, IF0 create) { Map generalMap = vm_generalMap(); if (generalMap == null) return null; // must be x30 init synchronized(generalMap) { // should switch to locks here A a = (A) (vm_generalMap_get(key)); if (a == null) vm_generalMap_put(key, a = create == null ? null : create.get()); return a; } } static Set synchroHashSet() { return synchronizedSet(new HashSet()); } static Set> _entrySet(Map map) { return map == null ? Collections.EMPTY_SET : map.entrySet(); } static String unnullForIteration(String s) { return s == null ? "" : s; } static Collection unnullForIteration(Collection l) { return l == null ? immutableEmptyList() : l; } static List unnullForIteration(List l) { return l == null ? immutableEmptyList() : l; } static int[] unnullForIteration(int[] l) { return l == null ? emptyIntArray() : l; } static char[] unnullForIteration(char[] l) { return l == null ? emptyCharArray() : l; } static double[] unnullForIteration(double[] l) { return l == null ? emptyDoubleArray() : l; } static short[] unnullForIteration(short[] l) { return l == null ? emptyShortArray() : l; } static Map unnullForIteration(Map l) { return l == null ? immutableEmptyMap() : l; } static Iterable unnullForIteration(Iterable i) { return i == null ? immutableEmptyList() : i; } static A[] unnullForIteration(A[] a) { return a == null ? (A[]) emptyObjectArray() : a; } static BitSet unnullForIteration(BitSet b) { return b == null ? new BitSet() : b; } static Pt unnullForIteration(Pt p) { return p == null ? new Pt() : p; } //ifclass Symbol static Symbol unnullForIteration(Symbol s) { return s == null ? emptySymbol() : s; } //endif static Pair unnullForIteration(Pair p) { return p != null ? p : new Pair(null, null); } static long unnullForIteration(Long l) { return l == null ? 0L : l; } static Iterator emptyIterator() { return Collections.emptyIterator(); } static Map synchronizedMRUCache(int maxSize) { return synchroMap(new MRUCache(maxSize)); } // supports the usual quotings (", variable length double brackets) except ' quoting static boolean isQuoted(String s) { if (isNormalQuoted(s)) return true; // use the exact version return isMultilineQuoted(s); } static boolean isIdentifier(String s) { return isJavaIdentifier(s); } static boolean eqic(String a, String b) { if ((a == null) != (b == null)) return false; if (a == null) return true; return a.equalsIgnoreCase(b); } static boolean eqic(Symbol a, Symbol b) { return eq(a, b); } static boolean eqic(Symbol a, String b) { return eqic(asString(a), b); } static boolean eqic(char a, char b) { if (a == b) return true; char u1 = Character.toUpperCase(a); char u2 = Character.toUpperCase(b); if (u1 == u2) return true; return Character.toLowerCase(u1) == Character.toLowerCase(u2); } static boolean checkTokCondition(Object condition, List tok, int i) { if (condition instanceof TokCondition) return ((TokCondition) condition).get(tok, i); return checkCondition(condition, tok, i); } static int indexOfSubList(List x, List y) { return indexOfSubList(x, y, 0); } static int indexOfSubList(List x, List y, int i) { outer: for (; i+l(y) <= l(x); i++) { for (int j = 0; j < l(y); j++) if (neq(x.get(i+j), y.get(j))) continue outer; return i; } return -1; } static int indexOfSubList(List x, A[] y, int i) { outer: for (; i+l(y) <= l(x); i++) { for (int j = 0; j < l(y); j++) if (neq(x.get(i+j), y[j])) continue outer; return i; } return -1; } static void removeSubList(List l, int from, int to) { if (l != null) subList(l, from, to).clear(); } static void removeSubList(List l, int from) { if (l != null) subList(l, from).clear(); } static void copyListPart(List a, int i1, List b, int i2, int n) { if (a == null || b == null) return; for (int i = 0; i < n; i++) b.set(i2+i, a.get(i1+i)); } static boolean methodIsStatic(Method m) { return (m.getModifiers() & Modifier.STATIC) != 0; } static A printException(A e) { printStackTrace(e); return e; } static A callF_gen(F0 f) { return f == null ? null : f.get(); } static B callF_gen(F1 f, A a) { return f == null ? null : f.get(a); } static A callF_gen(IF0 f) { return f == null ? null : f.get(); } static B callF_gen(IF1 f, A a) { return f == null ? null : f.get(a); } static B callF_gen(A a, IF1 f) { return f == null ? null : f.get(a); } static C callF_gen(F2 f, A a, B b) { return f == null ? null : f.get(a, b); } static C callF_gen(IF2 f, A a, B b) { return f == null ? null : f.get(a, b); } static void callF_gen(VF1 f, A a) { { if (f != null) f.get(a); } } static void callF_gen(A a, IVF1 f) { { if (f != null) f.get(a); } } static void callF_gen(IVF1 f, A a) { { if (f != null) f.get(a); } } static Object callF_gen(Runnable r) { { if (r != null) r.run(); } return null; } static Object callF_gen(Object f, Object... args) { return callF(f, args); } static int cmp(Number a, Number b) { return a == null ? b == null ? 0 : -1 : cmp(a.doubleValue(), b.doubleValue()); } static int cmp(double a, double b) { return a < b ? -1 : a == b ? 0 : 1; } static int cmp(int a, int b) { return a < b ? -1 : a == b ? 0 : 1; } static int cmp(long a, long b) { return a < b ? -1 : a == b ? 0 : 1; } static int cmp(Object a, Object b) { if (a == null) return b == null ? 0 : -1; if (b == null) return 1; return ((Comparable) a).compareTo(b); } static boolean nemptyString(String s) { return s != null && s.length() > 0; } static int listL(Collection l) { return l == null ? 0 : l.size(); } static String getStackTrace2(Throwable e) { return hideCredentials(getStackTrace(unwrapTrivialExceptionWraps(e)) + replacePrefix("java.lang.RuntimeException: ", "FAIL: ", hideCredentials(str(innerException2(e)))) + "\n"); } static boolean odd(int i) { return (i & 1) != 0; } static boolean odd(long i) { return (i & 1) != 0; } static boolean odd(BigInteger i) { return odd(toInt(i)); } static String collapseWord(String s) { if (s == null) return ""; StringBuilder buf = new StringBuilder(); for (int i = 0; i < l(s); i++) if (i == 0 || !charactersEqualIC(s.charAt(i), s.charAt(i-1))) buf.append(s.charAt(i)); return buf.toString(); } static List toLowerCase(List strings) { List x = new ArrayList(); for (String s : strings) x.add(s.toLowerCase()); return x; } static String[] toLowerCase(String[] strings) { String[] x = new String[l(strings)]; for (int i = 0; i < l(strings); i++) x[i] = strings[i].toLowerCase(); return x; } static String toLowerCase(String s) { return s == null ? "" : s.toLowerCase(); } static String firstWord2(String s) { s = xltrim(s); if (empty(s)) return ""; if (isLetterOrDigit(first(s))) return takeCharsWhile(__22 -> isLetterOrDigit(__22), s); else return "" + first(s); } static LinkedHashMap syncMapPut2_createLinkedHashMap(LinkedHashMap map, A key, B value) { if (key != null) if (value != null) { if (map == null) map = new LinkedHashMap(); synchronized(collectionMutex(map)) { map.put(key, value); } } else if (map != null) synchronized(collectionMutex(map)) { map.remove(key); } return map; } static IMeta initMetaOfJComponent(JComponent c) { if (c == null) return null; IMeta meta = (IMeta) (c.getClientProperty(IMeta.class)); if (meta == null) c.putClientProperty(IMeta.class, meta = new Meta()); return meta; } static A[] makeArray(Class type, int n) { return (A[]) Array.newInstance(type, n); } static Map castMapToMapO(Map map) { return map; } static int min(int a, int b) { return Math.min(a, b); } static long min(long a, long b) { return Math.min(a, b); } static float min(float a, float b) { return Math.min(a, b); } static float min(float a, float b, float c) { return min(min(a, b), c); } static double min(double a, double b) { return Math.min(a, b); } static double min(double[] c) { double x = Double.MAX_VALUE; for (double d : c) x = Math.min(x, d); return x; } static float min(float[] c) { float x = Float.MAX_VALUE; for (float d : c) x = Math.min(x, d); return x; } static byte min(byte[] c) { byte x = 127; for (byte d : c) if (d < x) x = d; return x; } static short min(short[] c) { short x = 0x7FFF; for (short d : c) if (d < x) x = d; return x; } static int min(int[] c) { int x = Integer.MAX_VALUE; for (int d : c) if (d < x) x = d; return x; } static void mapPut(Map map, A key, B value) { if (map != null && key != null && value != null) map.put(key, value); } static void mapPut(Map map, Pair p) { if (map != null && p != null) map.put(p.a, p.b); } static File associatedInfosFile(File f) { return replaceExtension(f, ".infos"); } static String lines(Iterable lines) { return fromLines(lines); } static String lines(Object[] lines) { return fromLines(asList(lines)); } static List lines(String s) { return toLines(s); } // convenience map call static String lines(Iterable l, IF1 f) { return mapToLines(l, f); } static String firstStartingWithIC_drop(Collection l, final String prefix) { for (String s : unnull(l)) if (swic(s, prefix)) return substring(s, l(prefix)); return null; } static String firstStartingWithIC_drop(String prefix, Collection l) { return firstStartingWithIC_drop(l, prefix); } static File javaxDataDir_dir; // can be set to work on different base dir static File javaxDataDir() { return javaxDataDir_dir != null ? javaxDataDir_dir : new File(userHome(), "JavaX-Data"); } static File javaxDataDir(String... subs) { return newFile(javaxDataDir(), subs); } static Object sleepQuietly_monitor = new Object(); static void sleepQuietly() { try { assertFalse(isAWTThread()); synchronized(sleepQuietly_monitor) { sleepQuietly_monitor.wait(); } } catch (Exception __e) { throw rethrow(__e); } } static String roundBracket(String s) { return "(" + s + ")"; } static String roundBracket(Object s) { return roundBracket(str(s)); } static long now_virtualTime; static long now() { return now_virtualTime != 0 ? now_virtualTime : System.currentTimeMillis(); } static B mapGet(Map map, A a) { return map == null || a == null ? null : map.get(a); } static B mapGet(A a, Map map) { return map == null || a == null ? null : map.get(a); } static boolean even(int i) { return (i & 1) == 0; } static boolean even(long i) { return (i & 1) == 0; } static boolean even(BigInteger n) { return even(n.intValue()); } static String _computerID; static Lock computerID_lock = lock(); public static String computerID() { if (_computerID == null) { Lock __0 = computerID_lock; lock(__0); try { if (_computerID != null) return _computerID; File file = computerIDFile(); _computerID = loadTextFile(file.getPath()); if (_computerID == null) { // legacy load _computerID = loadTextFile(userDir(".tinybrain/computer-id")); if (_computerID == null) _computerID = makeRandomID(12, new SecureRandom()); saveTextFile(file, _computerID); } } finally { unlock(__0); } } return _computerID; } static A _registerIOWrap(A wrapper, Object wrapped) { return wrapper; } static char lastChar(String s) { return empty(s) ? '\0' : s.charAt(l(s)-1); } static Charset utf8charset_cache; static Charset utf8charset() { if (utf8charset_cache == null) utf8charset_cache = utf8charset_load(); return utf8charset_cache;} static Charset utf8charset_load() { return Charset.forName("UTF-8"); } static Map syncMRUCache(int size) { return synchroMap(new MRUCache(size)); } static File programDir_mine; // set this to relocate program's data static File programDir() { return programDir(getProgramID()); } static File programDir(String snippetID) { boolean me = sameSnippetID(snippetID, programID()); if (programDir_mine != null && me) return programDir_mine; File dir = new File(javaxDataDir(), formatSnippetIDOpt(snippetID)); if (me) { String c = caseID(); if (nempty(c)) dir = newFile(dir, c); } return dir; } static File programDir(String snippetID, String subPath) { return new File(programDir(snippetID), subPath); } static boolean fileExists(String path) { return path != null && new File(path).exists(); } static boolean fileExists(File f) { return f != null && f.exists(); } static Object[] mapToObjectArray(Map map) { List l = new ArrayList(); for (Object o : keys(map)) { l.add(o); l.add(map.get(o)); } return toObjectArray(l); } static Object[] mapToObjectArray(Object f, Collection l) { int n = l(l); Object[] array = new Object[n]; if (n != 0) { Iterator it = iterator(l); for (int i = 0; i < n; i++) array[i] = callF(f, it.next()); } return array; } static Object[] mapToObjectArray(Object f, Object[] l) { int n = l(l); Object[] array = new Object[n]; for (int i = 0; i < n; i++) array[i] = callF(f, l[i]); return array; } static Object[] mapToObjectArray(Collection l, IF1 f) { return mapToObjectArray(f, l); } static Object[] mapToObjectArray(A[] l, IF1 f) { return mapToObjectArray(f, l); } static Object[] mapToObjectArray(IF1 f, A[] l) { int n = l(l); Object[] array = new Object[n]; for (int i = 0; i < n; i++) array[i] = f.get(l[i]); return array; } static Object[] mapToObjectArray(IF1 f, Collection l) { int n = l(l); Object[] array = new Object[n]; if (n != 0) { Iterator it = iterator(l); for (int i = 0; i < n; i++) array[i] = callF(f, it.next()); } return array; } // this should be on by default now I think, but it may break // legacy code... static ThreadLocal htmlencode_forParams_useV2 = new ThreadLocal(); static String htmlencode_forParams(String s) { if (s == null) return ""; if (isTrue(htmlencode_forParams_useV2.get())) return htmlencode_forParams_v2(s); StringBuilder out = new StringBuilder(Math.max(16, s.length())); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c > 127 || c == '"' || c == '<' || c == '>') { out.append("&#"); out.append((int) c); out.append(';'); } else out.append(c); } return out.toString(); } static A[] arrayOfSameType(A[] a, int n) { return newObjectArrayOfSameType(a, n); } static int[] subIntArray(int[] b, int start) { return subIntArray(b, start, l(b)); } static int[] subIntArray(int[] b, int start, int end) { start = max(start, 0); end = min(end, l(b)); if (start == 0 && end == l(b)) return b; if (start >= end) return new int[0]; int[] x = new int[end-start]; System.arraycopy(b, start, x, 0, end-start); return x; } static short[] subShortArray(short[] b, int start, int end) { start = max(start, 0); end = min(end, l(b)); if (start == 0 && end == l(b)) return b; if (start >= end) return new short[0]; short[] x = new short[end-start]; System.arraycopy(b, start, x, 0, end-start); return x; } static byte[] subByteArray(byte[] b, int start) { return subByteArray(b, start, l(b)); } static byte[] subByteArray(byte[] b, int start, int end) { start = max(start, 0); end = min(end, l(b)); if (start == 0 && end == l(b)) return b; if (start >= end) return new byte[0]; byte[] x = new byte[end-start]; System.arraycopy(b, start, x, 0, end-start); return x; } static double[] subDoubleArray(double[] b, int start) { return subDoubleArray(b, start, l(b)); } static double[] subDoubleArray(double[] b, int start, int end) { start = max(start, 0); end = min(end, l(b)); if (start == 0 && end == l(b)) return b; if (start >= end) return new double[0]; double[] x = new double[end-start]; System.arraycopy(b, start, x, 0, end-start); return x; } static boolean isAbsoluteURL(String s) { return isURL(s); } // does not detect relative urls starting with a letter static boolean isRelativeURL(String s) { return startsWithOneOf(s, "/", "./", "../"); } static Map mapPlus(Map m, Object... data) { m = cloneMap(m); litmap_impl(m, data); return m; } static Object[] assertEvenLength(Object[] a) { assertTrue(even(l(a))); return a; } static LinkedHashMap paramsToOrderedMap(Object... params) { return asLinkedHashMap(paramsToMap(params)); } static IF0 f0ToIF0(F0 f) { return f == null ? null : () -> f.get(); } static List immutableEmptyList() { return Collections.emptyList(); } static short[] emptyShortArray = new short[0]; static short[] emptyShortArray() { return emptyShortArray; } static Map immutableEmptyMap() { return Collections.emptyMap(); } static boolean isNormalQuoted(String s) { int l = l(s); if (!(l >= 2 && s.charAt(0) == '"' && lastChar(s) == '"')) return false; int j = 1; while (j < l) if (s.charAt(j) == '"') return j == l-1; else if (s.charAt(j) == '\\' && j+1 < l) j += 2; else ++j; return false; } static boolean isMultilineQuoted(String s) { if (!startsWith(s, "[")) return false; int i = 1; while (i < s.length() && s.charAt(i) == '=') ++i; return i < s.length() && s.charAt(i) == '['; } static boolean isJavaIdentifier(String s) { if (empty(s) || !Character.isJavaIdentifierStart(s.charAt(0))) return false; for (int i = 1; i < s.length(); i++) if (!Character.isJavaIdentifierPart(s.charAt(i))) return false; return true; } static String asString(Object o) { return o == null ? null : o.toString(); } static boolean checkCondition(Object condition, Object... args) { return isTrue(callF(condition, args)); } static boolean checkCondition(IF1 condition, A arg) { return isTrue(callF(condition, arg)); } static Throwable unwrapTrivialExceptionWraps(Throwable e) { if (e == null) return e; while (e.getClass() == RuntimeException.class && e.getCause() != null && eq(e.getMessage(), str(e.getCause()))) e = e.getCause(); return e; } static String replacePrefix(String prefix, String replacement, String s) { if (!startsWith(s, prefix)) return s; return replacement + substring(s, l(prefix)); } static Throwable innerException2(Throwable e) { if (e == null) return null; while (empty(e.getMessage()) && e.getCause() != null) e = e.getCause(); return e; } static boolean charactersEqualIC(char c1, char c2) { if (c1 == c2) return true; char u1 = Character.toUpperCase(c1); char u2 = Character.toUpperCase(c2); if (u1 == u2) return true; return Character.toLowerCase(u1) == Character.toLowerCase(u2); } static String xltrim(String s) { int i = 0, n = l(s); while (i < n && contains(" \t\r\n", s.charAt(i))) ++i; return substr(s, i); } static boolean isLetterOrDigit(char c) { return Character.isLetterOrDigit(c); } // pred: char -> bool static String takeCharsWhile(String s, Object pred) { int i = 0; while (i < l(s) && isTrue(callF(pred, s.charAt(i)))) ++i; return substring(s, 0, i); } static String takeCharsWhile(IF1 f, String s) { return takeCharsWhile(s, f); } static File replaceExtension(File f, String extOld, String extNew) { return newFile(replaceExtension(f2s(f), extOld, extNew)); } static File replaceExtension(File f, String extNew) { return replaceExtension(f, fileExtension(f), extNew); } static String replaceExtension(String s, String extOld, String extNew) { s = dropSuffixIC(addPrefixOptIfNempty(".", extOld), s); return s + addPrefixOptIfNempty(".", extNew); } static String replaceExtension(String name, String extNew) { return replaceExtension(name, fileExtension(name), extNew); } // usually L static String fromLines(Iterable lines) { StringBuilder buf = new StringBuilder(); if (lines != null) for (Object line : lines) buf.append(str(line)).append('\n'); return buf.toString(); } static String fromLines(String... lines) { return fromLines(asList(lines)); } static IterableIterator toLines(File f) { return linesFromFile(f); } static List toLines(String s) { List lines = new ArrayList(); if (s == null) return lines; int start = 0; while (true) { int i = toLines_nextLineBreak(s, start); if (i < 0) { if (s.length() > start) lines.add(s.substring(start)); break; } lines.add(s.substring(start, i)); if (s.charAt(i) == '\r' && i+1 < s.length() && s.charAt(i+1) == '\n') i += 2; else ++i; start = i; } return lines; } static int toLines_nextLineBreak(String s, int start) { int n = s.length(); for (int i = start; i < n; i++) { char c = s.charAt(i); if (c == '\r' || c == '\n') return i; } return -1; } static List mapToLines(Map map) { List l = new ArrayList(); for (Object key : keys(map)) l.add(str(key) + " = " + str(map.get(key))); return l; } static String mapToLines(Map map, Object f) { return lines(map(map, f)); } static String mapToLines(Object f, Map map) { return lines(map(map, f)); } static String mapToLines(Object f, Iterable l) { return lines(map(f, l)); } static String mapToLines(Iterable l, IF1 f) { return mapToLines((Object) f, l); } static String mapToLines(IF1 f, Iterable l) { return mapToLines((Object) f, l); } static String mapToLines(Map map, IF2 f) { return lines(map(map, f)); } static String mapToLines(IF1 f, A data1, A... moreData) { return lines(map(f, data1, moreData)); } static void assertFalse(Object o) { if (!(eq(o, false) /*|| isFalse(pcallF(o))*/)) throw fail(str(o)); } static boolean assertFalse(boolean b) { if (b) throw fail("oops"); return b; } static boolean assertFalse(String msg, boolean b) { if (b) throw fail(msg); return b; } static File computerIDFile() { return javaxDataDir("Basic Info/computer-id.txt"); } static String makeRandomID(int length) { return makeRandomID(length, defaultRandomGenerator()); } static String makeRandomID(int length, Random random) { char[] id = new char[length]; for (int i = 0; i < id.length; i++) id[i] = (char) ((int) 'a' + random.nextInt(26)); return new String(id); } static String makeRandomID(Random r, int length) { return makeRandomID(length, r); } /** writes safely (to temp file, then rename) */ static File saveTextFile(String fileName, String contents) throws IOException { /*ifdef CriticalActions temp beginCriticalAction("Saving file " + fileName + " (" + l(contents) + " chars)"); endifdef*/ File file = new File(fileName); mkdirsForFile(file); String tempFileName = fileName + "_temp"; File tempFile = new File(tempFileName); if (contents != null) { if (tempFile.exists()) try { String saveName = tempFileName + ".saved." + now(); copyFile(tempFile, new File(saveName)); } catch (Throwable e) { printStackTrace(e); } FileOutputStream fileOutputStream = newFileOutputStream(tempFile.getPath()); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8"); PrintWriter printWriter = new PrintWriter(outputStreamWriter); printWriter.print(contents); printWriter.close(); } if (file.exists() && !file.delete()) throw new IOException("Can't delete " + fileName); if (contents != null) if (!tempFile.renameTo(file)) throw new IOException("Can't rename " + tempFile + " to " + file); vmBus_send("wroteFile", file); return file; } static File saveTextFile(File fileName, String contents) { try { saveTextFile(fileName.getPath(), contents); return fileName; } catch (Exception __e) { throw rethrow(__e); } } static volatile String caseID_caseID; static String caseID() { return caseID_caseID; } static void caseID(String id) { caseID_caseID = id; } // binary legacy signature static Object[] toObjectArray(Collection c) { return toObjectArray((Iterable) c); } static Object[] toObjectArray(Iterable c) { List l = asList(c); return l.toArray(new Object[l.size()]); } static String htmlencode_forParams_v2(String s) { if (s == null) return ""; StringBuilder out = new StringBuilder(Math.max(16, s.length())); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c > 127 || c == '"' || c == '<' || c == '>' || c == '&') { out.append("&#"); out.append((int) c); out.append(';'); } else out.append(c); } return out.toString(); } static A[] newObjectArrayOfSameType(A[] a) { return newObjectArrayOfSameType(a, a.length); } static A[] newObjectArrayOfSameType(A[] a, int n) { return (A[]) Array.newInstance(a.getClass().getComponentType(), n); } static boolean isURL(String s) { return startsWithOneOf(s, "http://", "https://", "file:"); } static Map cloneMap(Map map) { if (map == null) return new HashMap(); // assume mutex is equal to map synchronized(map) { return map instanceof TreeMap ? new TreeMap((TreeMap) map) // copies comparator : map instanceof LinkedHashMap ? new LinkedHashMap(map) : new HashMap(map); } } static List cloneMap(Iterable l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : cloneList(l)) x.add(f.get(o)); return x; } static HashMap litmap(Object... x) { HashMap map = new HashMap(); litmap_impl(map, x); return map; } static void litmap_impl(Map map, Object... x) { if (x != null) for (int i = 0; i < x.length-1; i += 2) if (x[i+1] != null) map.put(x[i], x[i+1]); } static boolean contains(Collection c, Object o) { return c != null && c.contains(o); } static boolean contains(Iterable it, Object a) { if (it != null) for (Object o : it) if (eq(a, o)) return true; return false; } static boolean contains(Object[] x, Object o) { if (x != null) for (Object a : x) if (eq(a, o)) return true; return false; } static boolean contains(String s, char c) { return s != null && s.indexOf(c) >= 0; } static boolean contains(String s, String b) { return s != null && s.indexOf(b) >= 0; } static boolean contains(BitSet bs, int i) { return bs != null && bs.get(i); } static boolean contains(Producer p, A a) { if (p != null && a != null) while (true) { A x = p.next(); if (x == null) break; if (eq(x, a)) return true; } return false; } static boolean contains(Rect r, Pt p) { return rectContains(r, p); } static String substr(String s, int x) { return substring(s, x); } static String substr(String s, int x, int y) { return substring(s, x, y); } static String f2s(File f) { return f == null ? null : f.getAbsolutePath(); } static String f2s(String s) { return f2s(newFile(s)); } static String f2s(java.nio.file.Path p) { return p == null ? null : f2s(p.toFile()); } static String fileExtension(File f) { if (f == null) return null; return fileExtension(f.getName()); } static String fileExtension(String s) { return substring(s, smartLastIndexOf(s, '.')); } static String dropSuffixIC(String suffix, String s) { return s == null ? null : ewic(s, suffix) ? s.substring(0, l(s)-l(suffix)) : s; } static String addPrefixOptIfNempty(String prefix, String s) { return addPrefixIfNotEmpty2(prefix, s); } static CloseableIterableIterator linesFromFile(File f) { return linesFromFile(f, null); } static CloseableIterableIterator linesFromFile(File f, IResourceHolder resourceHolder) { try { if (!f.exists()) return emptyCloseableIterableIterator(); if (ewic(f.getName(), ".gz")) return linesFromReader(utf8bufferedReader(newGZIPInputStream(f)), resourceHolder); return linesFromReader(utf8bufferedReader(f), resourceHolder); } catch (Exception __e) { throw rethrow(__e); } } static CloseableIterableIterator linesFromFile(String path) { return linesFromFile(path, null); } static CloseableIterableIterator linesFromFile(String path, IResourceHolder resourceHolder) { return linesFromFile(newFile(path), resourceHolder); } static List map(Iterable l, Object f) { return map(f, l); } static List map(Object f, Iterable l) { List x = emptyList(l); if (l != null) for (Object o : l) { ping(); x.add(callF(f, o)); } return x; } static List map(Iterable l, F1 f) { return map(f, l); } static List map(F1 f, Iterable l) { List x = emptyList(l); if (l != null) for (A o : l) { ping(); x.add(callF(f, o)); } return x; } static List map(IF1 f, Iterable l) { return map(l, f); } static List map(Iterable l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : l) { ping(); x.add(f.get(o)); } return x; } static List map(IF1 f, A[] l) { return map(l, f); } static List map(A[] l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : l) { ping(); x.add(f.get(o)); } return x; } static List map(Object f, Object[] l) { return map(f, asList(l)); } static List map(Object[] l, Object f) { return map(f, l); } static List map(Object f, Map map) { return map(map, f); } // map: func(key, value) -> list element static List map(Map map, Object f) { List x = new ArrayList(); if (map != null) for (Object _e : map.entrySet()) { ping(); Map.Entry e = (Map.Entry) _e; x.add(callF(f, e.getKey(), e.getValue())); } return x; } static List map(Map map, IF2 f) { return map(map, (Object) f); } // new magic alias for mapLL - does it conflict? static List map(IF1 f, A data1, A... moreData) { List x = emptyList(l(moreData)+1); x.add(f.get(data1)); if (moreData != null) for (A o : moreData) { ping(); x.add(f.get(o)); } return x; } static Random defaultRandomGenerator() { { Random r = customRandomizerForThisThread(); if (r != null) return r; } return ThreadLocalRandom.current(); } public static File mkdirsForFile(File file) { File dir = file.getParentFile(); if (dir != null) { // is null if file is in current dir dir.mkdirs(); if (!dir.isDirectory()) if (dir.isFile()) throw fail("Please delete the file " + f2s(dir) + " - it is supposed to be a directory!"); else throw fail("Unknown IO exception during mkdirs of " + f2s(file)); } return file; } public static String mkdirsForFile(String path) { mkdirsForFile(new File(path)); return path; } static File copyFile(File src, File dest) { try { FileInputStream inputStream = new FileInputStream(src.getPath()); FileOutputStream outputStream = newFileOutputStream(dest.getPath()); try { copyStream(inputStream, outputStream); inputStream.close(); } finally { outputStream.close(); } return dest; } catch (Exception __e) { throw rethrow(__e); } } static FileOutputStream newFileOutputStream(File path) throws IOException { return newFileOutputStream(path.getPath()); } static FileOutputStream newFileOutputStream(String path) throws IOException { return newFileOutputStream(path, false); } static FileOutputStream newFileOutputStream(File path, boolean append) throws IOException { return newFileOutputStream(path.getPath(), append); } static FileOutputStream newFileOutputStream(String path, boolean append) throws IOException { mkdirsForFile(path); FileOutputStream f = new FileOutputStream(path, append); _registerIO(f, path, true); return f; } static boolean rectContains(int x1, int y1, int w, int h, Pt p) { return p.x >= x1 && p.y >= y1 && p.x < x1+w && p.y < y1+h; } static boolean rectContains(Rect a, Rect b) { return b.x >= a.x && b.y >= a.y && b.x2() <= a.x2() && b.y2() <= a.y2(); } static boolean rectContains(Rect a, Rectangle b) { return rectContains(a, toRect(b)); } static boolean rectContains(Rect a, int x, int y) { return a != null && a.contains(x, y); } static boolean rectContains(Rect a, Pt p) { return a != null && p != null && a.contains(p); } static int smartLastIndexOf(String s, char c) { if (s == null) return 0; int i = s.lastIndexOf(c); return i >= 0 ? i : l(s); } static int smartLastIndexOf(List l, A sub) { int i = lastIndexOf(l, sub); return i < 0 ? l(l) : i; } static String addPrefixIfNotEmpty2(String prefix, String s) { return empty(s) ? "" : addPrefix(prefix, s); } static CloseableIterableIterator emptyCloseableIterableIterator_instance = new CloseableIterableIterator() { public Object next() { throw fail(); } public boolean hasNext() { return false; } }; static CloseableIterableIterator emptyCloseableIterableIterator() { return emptyCloseableIterableIterator_instance; } static CloseableIterableIterator linesFromReader(Reader r) { return linesFromReader(r, null); } static CloseableIterableIterator linesFromReader(Reader r, IResourceHolder resourceHolder) { final BufferedReader br = bufferedReader(r); return holdResource(resourceHolder, iteratorFromFunction_f0_autoCloseable(new F0() { public String get() { try { return readLineFromReaderWithClose(br); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return readLineFromReaderWithClose(br);"; }}, _wrapIOCloseable(r))); } static BufferedReader utf8bufferedReader(InputStream in) { try { return in == null ? null : bufferedReader(_registerIOWrap(new InputStreamReader(in, "UTF-8"), in)); } catch (Exception __e) { throw rethrow(__e); } } static BufferedReader utf8bufferedReader(File f) { try { return utf8bufferedReader(newFileInputStream(f)); } catch (Exception __e) { throw rethrow(__e); } } static Random customRandomizerForThisThread() { return customRandomizerForThisThread_tl().get(); } static void copyStream(InputStream in, OutputStream out) { try { byte[] buf = new byte[65536]; while (true) { int n = in.read(buf); if (n <= 0) return; out.write(buf, 0, n); } } catch (Exception __e) { throw rethrow(__e); } } static void _registerIO(Object object, String path, boolean opened) { } static Rect toRect(Rectangle r) { return r == null ? null : new Rect(r); } static Rect toRect(RectangularShape r) { return r == null ? null : toRect(r.getBounds()); } static Rect toRect(Rect r) { return r; } static int lastIndexOf(String a, String b) { return a == null || b == null ? -1 : a.lastIndexOf(b); } static int lastIndexOf(String a, char b) { return a == null ? -1 : a.lastIndexOf(b); } // starts searching from i-1 static int lastIndexOf(List l, int i, A a) { if (l == null) return -1; for (i = min(l(l), i)-1; i >= 0; i--) if (eq(l.get(i), a)) return i; return -1; } static int lastIndexOf(List l, A a) { if (l == null) return -1; for (int i = l(l)-1; i >= 0; i--) if (eq(l.get(i), a)) return i; return -1; } static BufferedReader bufferedReader(Reader r) { return bufferedReader(r, 8192); } static BufferedReader bufferedReader(Reader r, int bufSize) { if (r == null) return null; return r instanceof BufferedReader ? (BufferedReader) r : _registerIOWrap(new BufferedReader(r, bufSize), r); } static A holdResource(IResourceHolder holder, A a) { { if (holder != null) holder.add(a); } return a; } static CloseableIterableIterator iteratorFromFunction_f0_autoCloseable(final F0 f, final AutoCloseable closeable) { class IFF2 extends CloseableIterableIterator { A a; boolean done = false; public boolean hasNext() { getNext(); return !done; } public A next() { getNext(); if (done) throw fail(); A _a = a; a = null; return _a; } void getNext() { if (done || a != null) return; a = f.get(); done = a == null; } public void close() throws Exception { if (closeable != null) closeable.close(); } }; return new IFF2(); } static String readLineFromReaderWithClose(BufferedReader r) { try { String s = r.readLine(); if (s == null) r.close(); return s; } catch (Exception __e) { throw rethrow(__e); } } static AutoCloseable _wrapIOCloseable(final AutoCloseable c) { return c == null ? null : new AutoCloseable() { public String toString() { return "c.close();\r\n _registerIO(c, null, false);"; } public void close() throws Exception { c.close(); _registerIO(c, null, false); }}; } static FileInputStream newFileInputStream(File path) throws IOException { return newFileInputStream(path.getPath()); } static FileInputStream newFileInputStream(String path) throws IOException { FileInputStream f = new FileInputStream(path); _registerIO(f, path, true); return f; } static ThreadLocal customRandomizerForThisThread_tl = new ThreadLocal(); static ThreadLocal customRandomizerForThisThread_tl() { return customRandomizerForThisThread_tl; } static int iround(double d) { return (int) Math.round(d); } static int iround(Number n) { return iround(toDouble(n)); } static double toDouble(Object o) { if (o instanceof Number) return ((Number) o).doubleValue(); if (o instanceof BigInteger) return ((BigInteger) o).doubleValue(); if (o instanceof String) return parseDouble((String) o); if (o == null) return 0.0; throw fail(o); } static double parseDouble(String s) { return empty(s) ? 0.0 : Double.parseDouble(s); } // immutable, has strong refs // Do not run in a synchronized block - it goes wrong in the presence // of elaborate classloaders (like in Gazelle BEA) // see #1102990 and #1102991 final static class _MethodCache { final Class c; final HashMap> cache = new HashMap(); _MethodCache(Class c) { this.c = c; _init(); } void _init() { Class _c = c; java.lang.Module myModule = getClass().getModule(); boolean anyHiddenClasses = false; while (_c != null) { boolean exported = classIsExportedTo(_c, myModule); if (!exported) anyHiddenClasses = true; else for (Method m : _c.getDeclaredMethods()) if ((anyHiddenClasses || !isAbstract(m)) && !reflection_isForbiddenMethod(m)) multiMapPut(cache, m.getName(), makeAccessible(m)); _c = _c.getSuperclass(); } // add default methods - this might lead to a duplication // because the overridden method is also added, but it's not // a problem except for minimal performance loss. // If any classes in the hierarchy were inaccessible, we add // all interface methods (see test_callForbiddenMethodByReflection for a test) for (Class intf : allInterfacesImplementedBy(c)) for (Method m : intf.getDeclaredMethods()) if ((anyHiddenClasses || m.isDefault()) && !reflection_isForbiddenMethod(m)) multiMapPut(cache, m.getName(), makeAccessible(m)); } // Returns only matching methods Method findMethod(String method, Object[] args) { try { List m = cache.get(method); if (m == null) return null; int n = m.size(); for (int i = 0; i < n; i++) { Method me = m.get(i); if (call_checkArgs(me, args, false)) return me; } return null; } catch (Exception __e) { throw rethrow(__e); } } Method findStaticMethod(String method, Object[] args) { try { List m = cache.get(method); if (m == null) return null; int n = m.size(); for (int i = 0; i < n; i++) { Method me = m.get(i); if (isStaticMethod(me) && call_checkArgs(me, args, false)) return me; } return null; } catch (Exception __e) { throw rethrow(__e); } } } static abstract class VF1 implements IVF1 { public abstract void get(A a); } // Meta - a "minimal" approach to adding meta-level to Java objects static class Meta implements IMeta { // Meta - a "minimal" approach to adding meta-level to Java objects // (implementing the interface IMeta) // We allocate one extra field for each Java object to make it // reasoning-compatible (reasoning-compatible = extensible with // fields of any name at runtime). // // We couldn't go for 0 extra fields (meta values must be linked // directly from the object) and there are no half fields in // Java... so there you go. // // Also, if you don't use any meta data, you are probably not // reasoning about anything. The point of reasoning in JavaX is // to attach information to objects directly used in the program. // Possible information contained in the meta field: // Origin, destination, security level, sender, cost center, // purpose, list of reifications, ... // So here it is. THE FIELD YOU HAVE BEEN WAITING FOR! // [We also have IMeta to retrofit foreign classes (rare but // probably useful).] ////////////////////// // The "meta" field // ////////////////////// // Generic meta value of any kind, but the typical case is it's a // Map with extra field values for the object etc. // "meta" is volatile to avoid synchronization; but you can also synchronize on // _tempMetaMutex() which is usually the object itself. Collections // and maps are exempt from using the collections's monitor as the meta // mutex because their monitor tends to be held for long operations // (e.g. cloneList). For those we use a substantially more complex // algorithm using a weakMap. Probably overkill. I may reconsider. volatile Object meta; // The meta field is not transient, thus by default it will be // persisted like anything else unless you customize your object // to suppress or modulate this. // ...and the interface methods public void _setMeta(Object meta) { this.meta = meta; } public Object _getMeta() { return meta; } // MOST functions are implemented in IMeta (default implementations) // Scaffolding convenience functions final boolean scaffolding(){ return scaffoldingEnabled(); } boolean scaffoldingEnabled() { return main.scaffoldingEnabled(this); } boolean scaffoldingEnabled(Object o) { return main.scaffoldingEnabled(o); } } static abstract class VF2 { abstract void get(A a, B b); } static class Matches { String[] m; Matches() {} Matches(String... m) { this.m = m;} String get(int i) { return i < m.length ? m[i] : null; } String unq(int i) { return unquote(get(i)); } String tlc(int i) { return unq(i).toLowerCase(); } boolean bool(int i) { return "true".equals(unq(i)); } String rest() { return m[m.length-1]; } // for matchStart int psi(int i) { return Integer.parseInt(unq(i)); } public String toString() { return "Matches(" + joinWithComma(quoteAll(asList(m))) + ")"; } public int hashCode() { return _hashCode(toList(m)); } public boolean equals(Object o) { return o instanceof Matches && arraysEqual(m, ((Matches) o).m); } } // for the version with MasterSymbol (used WAY back in "Smart Bot"!) see #1010608 static class Symbol implements CharSequence { String text; Symbol() {} Symbol(String text, boolean dummy) { this.text = text;} // weird signature to prevent accidental calling public int hashCode() { return _hashCode(text); } public String toString() { return text; } public boolean equals(Object o) { return this == o; } // implementation of CharSequence methods public int length() { return text.length(); } public char charAt(int index) { return text.charAt(index); } public CharSequence subSequence(int start, int end) { return text.substring(start, end); } } static class Var implements IVar, ISetter { Var() {} Var(A v) { this.v = v;} A v; // you can access this directly if you use one thread public synchronized void set(A a) { if (v != a) { v = a; notifyAll(); } } public synchronized A get() { return v; } public synchronized boolean has() { return v != null; } public void clear() { set(null); } public String toString() { return str(this.get()); } } static interface IMeta { // see class "Meta" for the bla bla public void _setMeta(Object meta); public Object _getMeta(); default public IAutoCloseableF0 _tempMetaMutex() { return new IAutoCloseableF0() { public Object get() { return IMeta.this; } public void close() {} }; } // actually query another object default public Object getMeta(Object obj, Object key){ return metaGet(obj, key); } default public Object metaGet(Object obj, Object key) { // call global function return metaMapGet(obj, key); } default public Object metaGet(String key, Object obj) { // call global function return metaMapGet(obj, key); } default public Object getMeta(Object key){ return metaGet(key); } default public Object metaGet(Object key) { if (key == null) return null; Object meta = _getMeta(); if (meta instanceof Map) return ((Map) meta).get(key); return null; } default public void metaSet(IMeta obj, Object key, Object value){ metaPut(obj, key, value); } default public void metaPut(IMeta obj, Object key, Object value) { // call global function metaMapPut(obj, key, value); } default public void metaSet(Object key, Object value){ metaPut(key, value); } default public void metaPut(Object key, Object value) { if (key == null) return; Map map = convertObjectMetaToMap(this); syncMapPutOrRemove(map, key, value); } } static class DefunctClassLoader {} static class JS implements IF0, Htmlable { JS() {} String code; Set requiredLibraries; Set requiredLibraries() { return requiredLibraries; } JS(String code, Object... dollarVars) { this.code = jsDollarVars(code, dollarVars); } public String get() { return code; } public String toString() { return unnull(code); } void requireJQuery() { require("jquery"); } void require(Object library) { requiredLibraries = addToSet_create(requiredLibraries, library); } public String html() { return hjs(code); } } static interface ITokCondition { boolean get(List tok, int i); // i = N Index } static abstract class TokCondition implements ITokCondition { public abstract boolean get(List tok, int i); // i = N Index } // doesn't compile locally, just uploads and compiles on server static class TranspileForServer implements IFieldsToList{ String progID; TranspileForServer() {} TranspileForServer(String progID) { this.progID = progID;} public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + progID + ")"; }public Object[] _fieldsToList() { return new Object[] {progID}; } String server = tb_mainServer(); String javax; Pair uploadResults; public void run() { try { javax = loadSnippet(progID); print("Source: " + l(javax)); long time = sysNow(); long _startTime_0 = sysNow(); transpileRaw_silent = false; String java; try { AutoCloseable __2 = tempSetTL(transpileRaw_progID, progID); try { java = transpileRaw(javax); } finally { _close(__2); }} catch (Throwable e) { printLineContextAfterJavaCompilerError(e, loadProgramTextFile("error.java")); throw rethrow(e); } print("Transpiled: " + l(java)); done2_always("Transpile", _startTime_0); List libs = new ArrayList(); java = findTranslators2(java, libs); print("Libs: " + or2(joinWithComma(libs), "-")); uploadResults = uploadTranspilation(progID, java, libs); print("Transpiled & uploaded " + fsI(progID) + "!"); } catch (Exception __e) { throw rethrow(__e); } } } static class Q implements AutoCloseable { String name = "Unnamed Queue"; List q = synchroLinkedList(); ReliableSingleThread rst = new ReliableSingleThread(new Runnable() { public void run() { try { _run() ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "_run()"; }}); final public boolean getRetired(){ return retired(); } public boolean retired() { return retired; } volatile boolean retired = false; final public Runnable getCurrentJob(){ return currentJob(); } public Runnable currentJob() { return currentJob; } volatile Runnable currentJob; AtomicLong jobsDone = new AtomicLong(); Q() {} Q(String name) { this.name = name;} void add(Runnable r) { assertNotRetired(); q.add(r); _trigger(); } void addInFront(Runnable r) { assertNotRetired(); q.add(0, r); _trigger(); } void _trigger() { rst.name = name; rst.go(); } void add(Object r) { add(toRunnable(r)); } void _run() { Runnable r; while (licensed() && !retired && (r = syncPopFirst(q)) != null) { currentJob = r; inc(jobsDone); try { r.run(); } catch (Throwable __e) { printStackTrace(__e); } currentJob = null; } onIdle(); } public void close() { retired = true; } // TODO: interrupt thread void done() {} // legacy function boolean isEmpty() { return q.isEmpty(); } int size() { return q.size(); } Object mutex() { return q; } // clients can synchronize on this List snapshot() { return cloneList(q); } // override this void onIdle() {} boolean busy() { return currentJob != null; } void assertNotRetired() { assertFalse("Queue is retired", retired()); } boolean hasThread() { return rst.hasThread(); } long nJobsDone() { return jobsDone.get(); } public String toString() { return (retired ? "Retired " : "") + "Q " + systemHashCodeHex(this) + " (" + (isEmpty() ? "empty" : nEntries(size()) + ", current job: " + currentJob) + ")"; } } static class MultiMap { Map> data = new HashMap>(); int fullSize; MultiMap() {} MultiMap(boolean useTreeMap) { if (useTreeMap) data = new TreeMap(); } MultiMap(MultiMap map) { putAll(map); } MultiMap(Map> data) { this.data = data;} void put(A key, B value) { synchronized(data) { List list = data.get(key); if (list == null) data.put(key, list = _makeEmptyList()); list.add(value); ++fullSize; }} void add(A key, B value) { put(key, value); } void addAll(A key, Collection values) { putAll(key, values); } void addAllIfNotThere(A key, Collection values) { synchronized(data) { for (B value : values) setPut(key, value); }} void setPut(A key, B value) { synchronized(data) { if (!containsPair(key, value)) put(key, value); }} boolean containsPair(A key, B value) { synchronized(data) { return get(key).contains(value); }} void putAll(Collection keys, B value) { synchronized(data) { for (A key : unnullForIteration(keys)) put(key, value); }} void putAll(A key, Collection values) { synchronized(data) { if (nempty(values)) getActual(key).addAll(values); }} void putAll(Iterable> pairs) { synchronized(data) { for (Pair p : unnullForIteration(pairs)) put(p.a, p.b); }} void removeAll(A key, Collection values) { synchronized(data) { for (B value : values) remove(key, value); }} List get(A key) { synchronized(data) { List list = data.get(key); return list == null ? Collections. emptyList() : list; }} List getOpt(A key) { synchronized(data) { return data.get(key); }} List getAndClear(A key) { synchronized(data) { List l = cloneList(data.get(key)); remove(key); return l; }} // returns actual mutable live list // creates the list if not there List getActual(A key) { synchronized(data) { List list = data.get(key); if (list == null) data.put(key, list = _makeEmptyList()); return list; }} void clean(A key) { synchronized(data) { List list = data.get(key); if (list != null && list.isEmpty()) { fullSize -= l(list); data.remove(key); } }} Set keySet() { synchronized(data) { return data.keySet(); }} Set keys() { synchronized(data) { return data.keySet(); }} void remove(A key) { synchronized(data) { fullSize -= l(this.getOpt(key)); data.remove(key); }} final void remove(Pair p){ removePair(p); } void removePair(Pair p) { if (p != null) remove(p.a, p.b); } void remove(A key, B value) { synchronized(data) { List list = data.get(key); if (list != null) { if (list.remove(value)) fullSize--; if (list.isEmpty()) data.remove(key); } }} void clear() { synchronized(data) { data.clear(); }} boolean containsKey(A key) { synchronized(data) { return data.containsKey(key); }} B getFirst(A key) { synchronized(data) { List list = get(key); return list.isEmpty() ? null : list.get(0); }} void addAll(MultiMap map) { putAll(map); } void putAll(MultiMap map) { synchronized(data) { for (A key : map.keySet()) putAll(key, map.get(key)); }} void putAll(Map map) { synchronized(data) { if (map != null) for (Map.Entry e : map.entrySet()) put(e.getKey(), e.getValue()); }} final int keyCount(){ return keysSize(); } int keysSize() { synchronized(data) { return l(data); }} // full size - note: expensive operation final int fullSize(){ return size(); } int size() { synchronized(data) { return fullSize; }} // expensive operation List reverseGet(B b) { synchronized(data) { List l = new ArrayList(); for (A key : data.keySet()) if (data.get(key).contains(b)) l.add(key); return l; }} Map> asMap() { synchronized(data) { return cloneMap(data); }} boolean isEmpty() { synchronized(data) { return data.isEmpty(); }} // override in subclasses List _makeEmptyList() { return new ArrayList(); } // returns live lists Collection> allLists() { synchronized(data) { return new ArrayList(data.values()); } } Collection> values() { return allLists(); } List allValues() { return concatLists(data.values()); } Object mutex() { return data; } public String toString() { return "mm" + str(data); } } static interface IResourceLoader { String loadSnippet(String snippetID); String getTranspiled(String snippetID); // with libs int getSnippetType(String snippetID); String getSnippetTitle(String snippetID); File loadLibrary(String snippetID); //ifndef NoJavaXJar default File pathToJavaXJar() { return pathToJavaxJar_noResourceLoader(); } //endifndef // may return null, then caller compiles themselves default File getSnippetJar(String snippetID, String transpiledSrc) { return null; } } /* * @(#)WeakHashMap.java 1.5 98/09/30 * * Copyright 1998 by Sun Microsystems, Inc., * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A. * All rights reserved. * * This software is the confidential and proprietary information * of Sun Microsystems, Inc. ("Confidential Information"). You * shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with Sun. */ // From https://github.com/mernst/plume-lib/blob/df0bfafc3c16848d88f4ea0ef3c8bf3367ae085e/java/src/plume/WeakHasherMap.java static final class WeakHasherMap extends AbstractMap implements Map { private Hasher hasher = null; /*@Pure*/ private boolean keyEquals(Object k1, Object k2) { return (hasher==null ? k1.equals(k2) : hasher.equals(k1, k2)); } /*@Pure*/ private int keyHashCode(Object k1) { return (hasher==null ? k1.hashCode() : hasher.hashCode(k1)); } // The WeakKey class can't be static because it depends on the hasher. // That in turn means that its methods can't be static. // However, I need to be able to call the methods such as create() that // were static in the original version of this code. // This finesses that. private /*@Nullable*/ WeakKey WeakKeyCreate(K k) { if (k == null) return null; else return new WeakKey(k); } private /*@Nullable*/ WeakKey WeakKeyCreate(K k, ReferenceQueue q) { if (k == null) return null; else return new WeakKey(k, q); } // Cannot be a static class: uses keyHashCode() and keyEquals() private final class WeakKey extends WeakReference { private int hash; /* Hashcode of key, stored here since the key may be tossed by the GC */ private WeakKey(K k) { super(k); hash = keyHashCode(k); } private /*@Nullable*/ WeakKey create(K k) { if (k == null) return null; else return new WeakKey(k); } private WeakKey(K k, ReferenceQueue q) { super(k, q); hash = keyHashCode(k); } private /*@Nullable*/ WeakKey create(K k, ReferenceQueue q) { if (k == null) return null; else return new WeakKey(k, q); } /* A WeakKey is equal to another WeakKey iff they both refer to objects that are, in turn, equal according to their own equals methods */ /*@Pure*/ @Override public boolean equals(/*@Nullable*/ Object o) { if (o == null) return false; // never happens if (this == o) return true; // This test is illegal because WeakKey is a generic type, // so use the getClass hack below instead. // if (!(o instanceof WeakKey)) return false; if (!(o.getClass().equals(WeakKey.class))) return false; Object t = this.get(); @SuppressWarnings("unchecked") Object u = ((WeakKey)o).get(); if ((t == null) || (u == null)) return false; if (t == u) return true; return keyEquals(t, u); } /*@Pure*/ @Override public int hashCode() { return hash; } } /* Hash table mapping WeakKeys to values */ private HashMap hash; /* Reference queue for cleared WeakKeys */ private ReferenceQueue queue = new ReferenceQueue(); /* Remove all invalidated entries from the map, that is, remove all entries whose keys have been discarded. This method should be invoked once by each public mutator in this class. We don't invoke this method in public accessors because that can lead to surprising ConcurrentModificationExceptions. */ @SuppressWarnings("unchecked") private void processQueue() { WeakKey wk; while ((wk = (WeakKey)queue.poll()) != null) { // unchecked cast hash.remove(wk); } } /* -- Constructors -- */ /** * Constructs a new, empty WeakHashMap with the given * initial capacity and the given load factor. * * @param initialCapacity the initial capacity of the * WeakHashMap * * @param loadFactor the load factor of the WeakHashMap * * @throws IllegalArgumentException If the initial capacity is less than * zero, or if the load factor is * nonpositive */ public WeakHasherMap(int initialCapacity, float loadFactor) { hash = new HashMap(initialCapacity, loadFactor); } /** * Constructs a new, empty WeakHashMap with the given * initial capacity and the default load factor, which is * 0.75. * * @param initialCapacity the initial capacity of the * WeakHashMap * * @throws IllegalArgumentException If the initial capacity is less than * zero */ public WeakHasherMap(int initialCapacity) { hash = new HashMap(initialCapacity); } /** * Constructs a new, empty WeakHashMap with the default * capacity and the default load factor, which is 0.75. */ public WeakHasherMap() { hash = new HashMap(); } /** * Constructs a new, empty WeakHashMap with the default * capacity and the default load factor, which is 0.75. * The WeakHashMap uses the specified hasher for hashing * keys and comparing them for equality. * @param h the Hasher to use when hashing values for this map */ public WeakHasherMap(Hasher h) { hash = new HashMap(); hasher = h; } /* -- Simple queries -- */ /** * Returns the number of key-value mappings in this map. * Note: In contrast to most implementations of the * Map interface, the time required by this operation is * linear in the size of the map. */ /*@Pure*/ @Override public int size() { return entrySet().size(); } /** * Returns true if this map contains no key-value mappings. */ /*@Pure*/ @Override public boolean isEmpty() { return entrySet().isEmpty(); } /** * Returns true if this map contains a mapping for the * specified key. * * @param key the key whose presence in this map is to be tested */ /*@Pure*/ @Override public boolean containsKey(Object key) { @SuppressWarnings("unchecked") K kkey = (K) key; return hash.containsKey(WeakKeyCreate(kkey)); } /* -- Lookup and modification operations -- */ /** * Returns the value to which this map maps the specified key. * If this map does not contain a value for this key, then return * null. * * @param key the key whose associated value, if any, is to be returned */ /*@Pure*/ @Override public /*@Nullable*/ V get(Object key) { // type of argument is Object, not K @SuppressWarnings("unchecked") K kkey = (K) key; return hash.get(WeakKeyCreate(kkey)); } /** * Updates this map so that the given key maps to the given * value. If the map previously contained a mapping for * key then that mapping is replaced and the previous value is * returned. * * @param key the key that is to be mapped to the given * value * @param value the value to which the given key is to be * mapped * * @return the previous value to which this key was mapped, or * null if if there was no mapping for the key */ @Override public V put(K key, V value) { processQueue(); return hash.put(WeakKeyCreate(key, queue), value); } /** * Removes the mapping for the given key from this map, if * present. * * @param key the key whose mapping is to be removed * * @return the value to which this key was mapped, or null if * there was no mapping for the key */ @Override public V remove(Object key) { // type of argument is Object, not K processQueue(); @SuppressWarnings("unchecked") K kkey = (K) key; return hash.remove(WeakKeyCreate(kkey)); } /** * Removes all mappings from this map. */ @Override public void clear() { processQueue(); hash.clear(); } /* -- Views -- */ /* Internal class for entries */ // This can't be static, again because of dependence on hasher. @SuppressWarnings("TypeParameterShadowing") private final class Entry implements Map.Entry { private Map.Entry ent; private K key; /* Strong reference to key, so that the GC will leave it alone as long as this Entry exists */ Entry(Map.Entry ent, K key) { this.ent = ent; this.key = key; } /*@Pure*/ @Override public K getKey() { return key; } /*@Pure*/ @Override public V getValue() { return ent.getValue(); } @Override public V setValue(V value) { return ent.setValue(value); } /*@Pure*/ private boolean keyvalEquals(K o1, K o2) { return (o1 == null) ? (o2 == null) : keyEquals(o1, o2); } /*@Pure*/ private boolean valEquals(V o1, V o2) { return (o1 == null) ? (o2 == null) : o1.equals(o2); } /*@Pure*/ @SuppressWarnings("NonOverridingEquals") public boolean equals(Map.Entry e /* Object o*/) { // if (! (o instanceof Map.Entry)) return false; // Map.Entry e = (Map.Entry)o; return (keyvalEquals(key, e.getKey()) && valEquals(getValue(), e.getValue())); } /*@Pure*/ @Override public int hashCode() { V v; return (((key == null) ? 0 : keyHashCode(key)) ^ (((v = getValue()) == null) ? 0 : v.hashCode())); } } /* Internal class for entry sets */ private final class EntrySet extends AbstractSet> { Set> hashEntrySet = hash.entrySet(); @Override public Iterator> iterator() { return new Iterator>() { Iterator> hashIterator = hashEntrySet.iterator(); Map.Entry next = null; @Override public boolean hasNext() { while (hashIterator.hasNext()) { Map.Entry ent = hashIterator.next(); WeakKey wk = ent.getKey(); K k = null; if ((wk != null) && ((k = wk.get()) == null)) { /* Weak key has been cleared by GC */ continue; } next = new Entry(ent, k); return true; } return false; } @Override public Map.Entry next() { if ((next == null) && !hasNext()) throw new NoSuchElementException(); Map.Entry e = next; next = null; return e; } @Override public void remove() { hashIterator.remove(); } }; } /*@Pure*/ @Override public boolean isEmpty() { return !(iterator().hasNext()); } /*@Pure*/ @Override public int size() { int j = 0; for (Iterator> i = iterator(); i.hasNext(); i.next()) j++; return j; } @Override public boolean remove(Object o) { processQueue(); if (!(o instanceof Map.Entry)) return false; @SuppressWarnings("unchecked") Map.Entry e = (Map.Entry)o; // unchecked cast Object ev = e.getValue(); WeakKey wk = WeakKeyCreate(e.getKey()); Object hv = hash.get(wk); if ((hv == null) ? ((ev == null) && hash.containsKey(wk)) : hv.equals(ev)) { hash.remove(wk); return true; } return false; } /*@Pure*/ @Override public int hashCode() { int h = 0; for (Iterator> i = hashEntrySet.iterator(); i.hasNext(); ) { Map.Entry ent = i.next(); WeakKey wk = ent.getKey(); Object v; if (wk == null) continue; h += (wk.hashCode() ^ (((v = ent.getValue()) == null) ? 0 : v.hashCode())); } return h; } } private /*@Nullable*/ Set> entrySet = null; /** * Returns a Set view of the mappings in this map. */ /*@SideEffectFree*/ @Override public Set> entrySet() { if (entrySet == null) entrySet = new EntrySet(); return entrySet; } // find matching key K findKey(Object key) { processQueue(); K kkey = (K) key; // TODO: use replacement for HashMap to avoid reflection WeakKey wkey = WeakKeyCreate(kkey); WeakKey found = hashMap_findKey(hash, wkey); return found == null ? null : found.get(); } } static class Either { byte which; Object value; Either() {} Either(int which, Object value) { this.which = (byte) which; this.value = value; } boolean isA() { return which == 1; } boolean isB() { return which == 2; } A a() { if (which != 1) _failMe(); return (A) value; } B b() { if (which != 2) _failMe(); return (B) value; } A aOpt() { return which != 1 ? null : (A) value; } B bOpt() { return which != 2 ? null : (B) value; } void _failMe() { throw fail("Either object is of wrong type: " + shortClassName(value)); } public String toString() { return "Either" + (isA() ? "A" : "B") + "(" + value + ")"; } } static class proxy_InvocationHandler implements InvocationHandler { Object target; proxy_InvocationHandler() {} proxy_InvocationHandler(Object target) { this.target = target;} public Object invoke(Object proxy, Method method, Object[] args) { return call(target, method.getName(), unnull(args)); } } static abstract class DynModule extends DynamicObject implements Enterable, ChangeTriggerable { // we really shouldn't have used up these variable names // (subclasses can't overload them due to how the persistence works) String name, toolTip; // module name, module tool tip in task bar PersistableThrowable _error; Map> mechLists; Map _persistenceInfo; transient Object _host; // pointer to this module's stem transient Map timers = newWeakHashMap(); // all kinds of resources actually; value is closer helper transient Set _resources = synchroHashSet(); transient Lock lock; // set by stem transient boolean persistOnChangedField = true; transient int changeCount; transient Object changeCountSync = new Object(); transient List onChange; transient List onTransientChange; transient boolean verboseTimers = false; transient ReliableSingleThread rstUpdate; transient Set componentFieldsToKeep; // TODO: use DynamicObject for this transient Map transientGeneralMap = synchroHashMap(); transient Q q; // module command queue transient List onFieldChange; // also for non-persistent fields. L transient boolean _hasPreviousBounds = false; transient StringBuffer _printLog = new StringBuffer(); transient boolean deleted = false; DynModule() { if (useErrorHandling()) dm_initErrorHandling(); // TODO: DynModule is now shared between modules, so not good setMainDesktopPane((JDesktopPane) getCreatorOpt("desktop")); } boolean useErrorHandling() { return true; } boolean isVisible() { return isTrue(getOpt(_host, "visible")); } String moduleName() { return name; } void setModuleName(String name) { String oldName = this.name; if (!eq(name, oldName)) { setField("name", name); possiblyInternalFrameTitle(vis(), name); vmBus_send("moduleNameChange", this, oldName, name); } } void setModuleToolTip(String toolTip) { this.toolTip = toolTip; } JComponent vis() { return (JComponent) getOpt(_host, "vis"); } A ownResource(A a) { if (a != null) _resources.add(a); return a; } A ownTimer(A timer) { if (timer instanceof AutoCloseable) ownResource((AutoCloseable) timer); else ownTimer(timer, __10 -> cancelTimerOrInterruptThread(__10)); return timer; } void ownTimer(Object timer, IVF1 closerHelper) { timers.put(timer, closerHelper); } void singleTimer(java.util.Timer timer) { stopAllTimers(); ownTimer(timer); } void stopAllTimers() { for (AutoCloseable resource : getAndClearList(_resources)) { if (verboseTimers) print("Releasing resource: " + resource); try { resource.close(); } catch (Throwable __e) { printStackTrace(__e); } } for (Map.Entry __0 : _entrySet( getAndClearMap(timers))) { Object timer = __0.getKey(); IVF1 closerHelper = __0.getValue(); if (verboseTimers) print("Stopping timer: " + closerHelper + " / " + timer); pcallF(closerHelper, timer); } } boolean isDeleted() { return deleted; } boolean deleted() { return deleted; } void cleanMeUp_dynModule() { deleted = true; { cleanUp(q); q = null; } stopAllTimers(); } void persistMe() { synchronized(changeCountSync) { ++changeCount; } pcallFAll(onChange); callOpt(_host, "_change"); updateMe(); } void fireChangeWithoutPersisting() { pcallFAll(onChange); } void fireTransientChange() { pcallFAll(onTransientChange); } final void _change() { persistMe(); } final public void change() { persistMe(); } void updateMe() { rstUpdate().trigger(); } void changeAndUpdate() { _change(); updateMe(); } boolean setField_noPersist(String name, Object value) { return setField(name, value, true); } boolean _setField(String name, Object value) { return setField(name, value); } boolean setField(String name, Object value) { return setField(name, value, false); } boolean setField(String name, Object value, boolean noPersist) { AutoCloseable __6 = enter(); try { try { // some really weird classes fail on equals() (BCEL JavaClass, I'm looking at you) if (eq(get(this, name), value)) return false; } catch (Throwable __e) { printStackTrace(__e); } return setField_noCheck(name, value, noPersist); } finally { _close(__6); }} // always set even if equal boolean setField_noCheck(String name, Object value) { return setField_noCheck(name, value, false); } boolean setField_noCheck(String name, Object value, boolean noPersist) { AutoCloseable __7 = enter(); try { //set(this, name, value); setOpt(this, name, value); // XXX allow virtual fields pcallFAll(onFieldChange, name); // XXX - new check for transient field if (!noPersist && dm_isPersistentField(me(), name)) _change(); return true; } finally { _close(__7); }} A setFieldAndReturn(String name, A value) { setField(name, value); return value; } boolean setFields(Object... params) { boolean change = false; for (int i = 0; i < l(params); i += 2) if (setField((String) params[i], params[i+1])) change = true; return change; } void start() { _hasPreviousBounds = dm_getBounds() != null; if (hasMethod_onTypes(this, "onTopInput", String.class)) dm_onTopInput_q(new VF1() { public void get(String s) { try { call(module(), "onTopInput", s) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "call(module(), 'onTopInput, s)"; }}); } void revisualize() { call(dm_os(), "revisualizeModule", _host); } boolean useEnterShortcut() { return false; } public AutoCloseable enter() { AutoCloseable c = tempSetBetterThreadLocalIfNecessary_weakRef(dm_current_generic_tl(), this); /// XXX shortcut, testing now (doesn't seem to work yet) if (c == null && useEnterShortcut()) return null; // assume we are entered (so the rest of what we do in this function is also done) Object realMC = getMainClass(this); if (printToModule()) c = combineAutoCloseables(c, tempInterceptPrintIfNotIntercepted(_printToModuleInterceptor())); if (realMC != mc()) { if (printToModule()) c = combineAutoCloseables(c, (AutoCloseable) callOpt(realMC, "tempInterceptPrintIfNotIntercepted", _printToModuleInterceptor())); else c = combineAutoCloseables(c, tempInterceptPrintIfNotIntercepted(new F1() { public Boolean get(String s) { try { { call(realMC, "print", s); return false; } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret false with call(realMC, 'print, s);"; }})); c = combineAutoCloseables(c, tempSetTL(realMC_tl(), realMC)); } return c; } F1 _printToModuleInterceptor() { return new F1() { public Boolean get(String s) { try { if (print_preprocess != null) s = (String) callF(print_preprocess, s); s = fixNewLines(s); Appendable loc = _printLog; Appendable buf = print_log; int loc_max = print_log_max; if (buf != loc && buf != null) { print_append(buf, s, print_log_max); loc_max = local_log_max; } if (loc != null) print_append(loc, s, loc_max); if (printAlsoToSystemOut) System.out.print(s); return false; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (print_preprocess != null) s = (S) callF(print_preprocess, s);\r\n s = ..."; }}; } boolean printToModule() { return true; } // on by default now AutoCloseable enterAndLock() { return combineAutoCloseables(enter(), tempLock(lock)); } boolean setError(Throwable e) { setField("_error" , persistableThrowable(e)); return true; } void clearError() { setField("_error" , null); } void onChange(Runnable r) { Lock __2 = lock; lock(__2); try { if (onChange == null) onChange = synchroList(); addIfNotThere(onChange, r); } finally { unlock(__2); } } public void removeChangeListener(Runnable r) { remove(onChange, r); } void onFieldChange(VF1 r) { Lock __3 = lock; lock(__3); try { if (onFieldChange == null) onFieldChange = synchroList(); addIfNotThere(onFieldChange, r); } finally { unlock(__3); } } void removeFieldChangeListener(VF1 r) { remove(onFieldChange, r); } void onChangeAndNow(Runnable r) { onChange(r); callF(r); } // forward to main class void onChangeAndNow(JComponent c, Object r) { onUpdateAndNow(c, r); } /*static*/ A onChange(A tc, Object r) { onUpdate(tc, r); return tc; } void update() {} void unvisualize() { zeroAllFieldsOfTypeExcept(this, Component.class, componentFieldsToKeep); } // return L (legacy) // or litobjectarray(text, Runnable, text, Runnable, ...) Object menuItems() { return null; } void enhanceFrame(Container f) { Object items = menuItems(); if (items instanceof Object[]) items = paramsToAbstractActions((Object[]) items); internalFramePopupMenuFromActions_threaded(f, (List) items); String switchableFields = (String) (callOpt(this, "switchableFields")); Set set = asLinkedHashSet(splitAtSpace(switchableFields)); Matches m = new Matches(); for (String field : allFields(getClass())) if (startsWith(field, "_switchableField_", m)) set.add(m.rest()); for (String field : set) { Class type = fieldType(this, field); if (eq(boolean.class, type)) dm_boolFieldMenuItem(f, field); else if (eq(int.class, type)) dm_intFieldMenuItem(f, field); else if (eq(long.class, type)) dm_longFieldMenuItem(f, field); else if (eq(double.class, type)) dm_doubleFieldMenuItem(f, field); else if (eq(float.class, type)) dm_floatFieldMenuItem(f, field); else if (eq(String.class, type)) dm_stringFieldMenuItem(f, field); else if (eq(File.class, type)) dm_fileFieldMenuItem(f, field); } } // assume this is called in start(), so no locking ReliableSingleThread rstUpdate() { if (rstUpdate == null) rstUpdate = dm_rst(this, new Runnable() { public void run() { try { AutoCloseable __8 = enter(); try { update(); } finally { _close(__8); }} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp enter(); update();"; }}); return rstUpdate; } Q q() { AutoCloseable __9 = enter(); try { if (q == null) { Lock __4 = lock; lock(__4); try { if (q == null) q = dm_startQ(); } finally { unlock(__4); } } return q; } finally { _close(__9); }} A withUpdate(A a) { rstUpdate().trigger(); return a; } DynModule module() { return this; } DynModule me() { return this; } JComponent visualize() { return dm_noVisualisation(); } String programTitle_cache; String programTitle() { if (programTitle_cache == null) programTitle_cache = snippetTitle(programID(mainClass(this))); return programTitle_cache; } // field must be non-transient void doPersist(String field) { _persistenceInfo = mapMinus(_persistenceInfo, field); } void dontPersist(String field) { _persistenceInfo = mapPlus(_persistenceInfo, "field" , false); } Appendable _actualPrintLog() { return printToModule() ? _printLog : print_log; } Object getHost() { return _host; } boolean addAndChange(Collection cl, A a) { if (cl == null || !cl.add(a)) return false; change(); return true; } void clearAndChange(Collection cl) { if (cl == null) return; cl.clear(); change(); } } // end of DynModule static void _registerTimer(java.util.Timer timer) { _registerTimer_original(timer); var mod = dm_currentModule(); { if (mod != null) mod.ownTimer(timer); } } /* TODO: thread {} should enter the module svoid _onLoad_moduleThreadInfo { _threadInfo_addMakerAndRetriever( voidfunc(Map map) { mapPut(map, dm_current := dm_currentModule()) }, voidfunc(Map map) { dm_enter((S) map.get('dm_current)) }); } */ static class Fail extends RuntimeException implements IFieldsToList{ Object[] objects; Fail() {} Fail(Object... objects) { this.objects = objects;}public Object[] _fieldsToList() { return new Object[] {objects}; } Fail(Throwable cause, Object... objects) { super(cause); this.objects = objects; } public String toString() { return joinNemptiesWithColon("Fail", commaCombine(getCause(), objects)); } } static class Pair implements Comparable> { A a; B b; Pair() {} Pair(A a, B b) { this.b = b; this.a = a;} public int hashCode() { return hashCodeFor(a) + 2*hashCodeFor(b); } public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof Pair)) return false; Pair t = (Pair) o; return eq(a, t.a) && eq(b, t.b); } public String toString() { return "<" + a + ", " + b + ">"; } public int compareTo(Pair p) { if (p == null) return 1; int i = ((Comparable) a).compareTo(p.a); if (i != 0) return i; return ((Comparable) b).compareTo(p.b); } } static interface IResourceHolder { A add(A a); Collection takeAll(); } static interface IWebRequest { public String uri(); public Map params(); public Map headers(); public Map files(); default public String clientIP() { return unnull(getClientIPFromHeaders(headers())); } default public String getHeader(String name) { return mapGet(headers(), name); } default public String domain() { return getHeader("host"); } public String cookie(); public boolean isHttps(); public boolean isPost(); default String protocol() { return isHttps() ? "https://" : "http://"; } // mark this request as no-spam (don't count towards spam limit) default void noSpam() {} default String get(String param) { return mapGet(params(), param); } default String userAgent() { return getHeader("user-agent"); } // proxy another page default Object proxy(String url, boolean rewriteHost, boolean rewritePort) { throw unimplemented(); } default boolean uriIs(String uri) { return eq(uri(), uri); } } abstract static class DynPrintLog extends DynModule { transient JFastLogView_noWrap printLogView; transient Lock updatePrintLog_lock = lock(); transient StringBuffer actualPrintLog; transient int printLogUpdateInterval = 500; transient JComponent printLogPanel; public JComponent visualize() { return makePrintLogPanel(); } JComponent makePrintLogPanel() { JComponent section = printLogPanel = jSection("Log", jscroll_copyBackground(printLogView = jFastLogView_noWrap(getPrintLog()))); componentPopupMenuItem(section, "Clear", new Runnable() { public void run() { try { AutoCloseable __3 = enter(); try { dm_clearModulePrintLog(); } finally { _close(__3); }} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp enter(); dm_clearModulePrintLog();"; }}); return awtEvery(section, printLogUpdateInterval, new Runnable() { public void run() { try { updatePrintLog(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "updatePrintLog();"; }}); } void updatePrintLog() { swing(() -> { // TODO: optimize Lock __0 = updatePrintLog_lock; lock(__0); try { JFastLogView_noWrap _view = printLogView; if (_view == null) return; if (_view.setText(getPrintLog())) { // Still trying to reliably scroll down scrollAllTheWayDown(_view); awtLater(100, new Runnable() { public void run() { try { scrollAllTheWayDown(_view) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "scrollAllTheWayDown(_view)"; }}); } } finally { unlock(__0); } }); } JFastLogView_noWrap myPrintLogComponent() { return printLogView; } void enableWordWrap() { // TODO } String getPrintLog() { if (actualPrintLog == null) { if (printToModule()) actualPrintLog = _printLog; else actualPrintLog = liveLocalPrintLog_realMC(this); } return str(actualPrintLog); } } final static class Rect implements IFieldsToList{ static final String _fieldOrder = "x y w h"; int x; int y; int w; int h; Rect() {} Rect(int x, int y, int w, int h) { this.h = h; this.w = w; this.y = y; this.x = x;} public boolean equals(Object o) { if (!(o instanceof Rect)) return false; Rect __1 = (Rect) o; return x == __1.x && y == __1.y && w == __1.w && h == __1.h; } public int hashCode() { int h = 2543108; h = boostHashCombine(h, _hashCode(x)); h = boostHashCombine(h, _hashCode(y)); h = boostHashCombine(h, _hashCode(w)); h = boostHashCombine(h, _hashCode(h)); return h; } public Object[] _fieldsToList() { return new Object[] {x, y, w, h}; } Rect(Rectangle r) { x = r.x; y = r.y; w = r.width; h = r.height; } Rect(Pt p, int w, int h) { this.h = h; this.w = w; x = p.x; y = p.y; } Rect(Rect r) { x = r.x; y = r.y; w = r.w; h = r.h; } Rectangle getRectangle() { return new Rectangle(x, y, w, h); } public String toString() { return x + "," + y + " / " + w + "," + h; } int x1() { return x; } int y1() { return y; } int x2() { return x + w; } int y2() { return y + h; } boolean contains(Pt p) { return contains(p.x, p.y); } boolean contains(int _x, int _y) { return _x >= x && _y >= y && _x < x+w && _y < y+h; } boolean contains(Rectangle r) { return rectContains(this, r); } boolean empty() { return w <= 0 || h <= 0; } int getWidth() { return w; } int getHeight() { return h; } } static class Pt implements Comparable, IDoublePt { int x, y; Pt() {} Pt(Point p) { x = p.x; y = p.y; } Pt(int x, int y) { this.y = y; this.x = x;} Point getPoint() { return new Point(x, y); } public boolean equals(Object o) { return o instanceof Pt && x == ((Pt) o).x && y == ((Pt) o).y; } public int hashCode() { return boostHashCombine(x, y); } // compare in scan order public int compareTo(Pt p) { if (y != p.y) return cmp(y, p.y); return cmp(x, p.x); } public String toString() { return x + ", " + y; } double length() { return sqrt(x*x+y*y); } Pt minus(Pt p) { return ptMinus(this, p); } public double x_double() { return x; } public double y_double() { return y; } } static abstract class F0 { abstract A get(); } static abstract class F1 { abstract B get(A a); } // you still need to implement hasNext() and next() static abstract class IterableIterator implements Iterator, Iterable { public Iterator iterator() { return this; } public void remove() { unsupportedOperation(); } } /** this class is fully thread-safe */ static class Flag implements Runnable { private boolean up = false; /** returns true if flag was down before (i.e. flag was actually raised right now) */ public synchronized boolean raise() { if (!up) { up = true; notifyAll(); return true; } else return false; } public synchronized void waitUntilUp() { while (!up) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public boolean waitUntilUp(double timeout) { return waitUntilUp(toMS(timeout)); } public synchronized boolean waitUntilUp(long timeout) { if (!up) { try { wait(timeout); } catch (InterruptedException e) { e.printStackTrace(); } } return isUp(); } public synchronized boolean isUp() { return up; } boolean get() { return isUp(); } public String toString() { return isUp() ? "up" : "down"; } // currently does a semi-active wait with latency = 50 ms public void waitForThisOr(Flag otherFlag) { try { while (!isUp() && !otherFlag.isUp()) Thread.sleep(50); } catch (Exception __e) { throw rethrow(__e); } } public void run() { raise(); } } // elements are put to front when added (not when accessed) static class MRUCache extends LinkedHashMap { int maxSize = 10; MRUCache() {} MRUCache(int maxSize) { this.maxSize = maxSize;} protected boolean removeEldestEntry(Map.Entry eldest) { return size() > maxSize; } Object _serialize() { return ll(maxSize, cloneLinkedHashMap(this)); } static MRUCache _deserialize(List l) { MRUCache m = new MRUCache(); m.maxSize = (int) first(l); m.putAll((LinkedHashMap) second(l)); return m; } } public static interface IF0 { A get(); } static interface Hasher { int hashCode(A a); boolean equals(A a, A b); } static abstract class CloseableIterableIterator extends IterableIterator implements AutoCloseable { public void close() throws Exception {} } static interface IF2 { C get(A a, B b); } static interface IF1 { B get(A a); } static class PersistableThrowable extends DynamicObject { String className; String msg; String stacktrace; PersistableThrowable() {} PersistableThrowable(Throwable e) { if (e == null) className = "Crazy Null Error"; else { className = getClassName(e).replace('/', '.'); msg = e.getMessage(); stacktrace = getStackTrace_noRecord(e); } } public String toString() { return nempty(msg) ? className + ": " + msg : className; } RuntimeException asRuntimeException() { return new Fail(this); } } static interface IVF1 { void get(A a); } static interface IVF2 { void get(A a, B b); } static interface IIntPred { boolean get(int a); } interface Enterable { AutoCloseable enter(); } static interface Htmlable { default String headStuff() { return ""; } String html(); } interface IHasChangeListeners { IHasChangeListeners onChange(Runnable r); IHasChangeListeners removeChangeListener(Runnable r); default IHasChangeListeners onChangeAndNow(Runnable l) { onChange(l); callF(l); return this; } } static interface IFieldsToList { Object[] _fieldsToList(); } static interface ISetter { void set(A a); } static class ReliableSingleThread implements Runnable { boolean _isTransient() { return true; } Object runnable; // usually a Runnable. is allowed to call trigger() itself String name = "Single Thread"; boolean cancelBeforeTrigger = false; // always cancel running thread and wait for it to end before starting new operation boolean waitBetweenCancelAndTrigger = false; // make sure the old thread is actually ended F0 enter; // optional ownership marker, e.g. for DynModules int cancelTimeOut = 10000; boolean trigger = false; Thread thread; WeakReference threadBeingCancelled; List inserts = syncL(); ReliableSingleThread(Object runnable) { this.runnable = runnable;} void trigger() { go(); } synchronized void go() { if (cancelBeforeTrigger) cancelAndPossiblyWait(); trigger = true; if (!running()) { AutoCloseable __1 = callF(enter); try { thread = startThread(name, new Runnable() { public void run() { try { AutoCloseable __2 = callF(enter); try { _run(); } finally { _close(__2); }} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp callF(enter);\r\n _run();"; }}); } finally { _close(__1); }} } public void run() { go(); } void get() { go(); } // so you can use the ! syntax synchronized boolean running() { return thread != null; } // use only if this is the last time you trigger this void triggerAndWait() { trigger(); waitUntilDone(); } void waitUntilDone() { while (running()) sleep(1); } void _run() { try { while (licensed()) { Thread oldThread; synchronized(this) { var currentInserts = syncGetAndClear(inserts); pcallFAll(currentInserts); if (!trigger) { thread = null; break; } oldThread = getWeakRef(threadBeingCancelled); trigger = false; } if (oldThread != null && oldThread != currentThread()) oldThread.join(cancelTimeOut); pcallF(runnable); } } catch (Exception __e) { throw rethrow(__e); } } synchronized void cancel() { if (thread == null) return; threadBeingCancelled = new WeakReference(thread); cancelAndInterruptThread(thread); thread = null; } void cancelAndWait() { Thread _thread; synchronized(this) { if (thread == null) return; _thread = thread; threadBeingCancelled = new WeakReference(thread); thread = null; } cancelAndInterruptThread(_thread); } void cancelAndTrigger() { cancelAndPossiblyWait(); trigger(); } synchronized boolean triggered() { return trigger; } void cleanMeUp() { cancel(); } ReliableSingleThread cancelBeforeTrigger() { cancelBeforeTrigger = true; return this; } void cancelAndPossiblyWait() { if (waitBetweenCancelAndTrigger) cancel(); } // TODO: trigger technically not necessary, just notify (I guess) void insert(Runnable r) { inserts.add(r); trigger(); } synchronized boolean hasThread() { return thread != null; } } static interface IAutoCloseableF0 extends IF0, AutoCloseable {} static class JFastLogView_noWrap extends JComponent implements Scrollable { List lines = syncList(); boolean endsWithNewLine, verbose; public Dimension getPreferredScrollableViewportSize() { return getPreferredSize(); } public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { return 20; } public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { return (direction == SwingConstants.HORIZONTAL ? visibleRect.width : visibleRect.height)*5/6; } public boolean getScrollableTracksViewportWidth() { return false; } public boolean getScrollableTracksViewportHeight() { return false; } public void paint(Graphics g) { //if (verbose) _print("JFastLogView_noWrap painting"); int w = getWidth(), h = getHeight(); g.setColor(getBackground()); g.fillRect(0, 0, w, h); g.setColor(getForeground()); FontMetrics fm = componentFontMetrics(this); int fh = fm.getHeight(); Rectangle clip = g.getClipBounds(); int start, end; if (clip == null) { start = 0; end = l(lines); } else { start = max(0, clip.y/fh); end = min(l(lines), idiv_ceil(clip.y+clip.height, fh)); } //printVars(+start, +end); int y = fm.getAscent()+start*fh; for (int i = start; i < end; i++) { String s = get(lines, i); if (s != null) g.drawString(s, 0, y); y += fh; } //if (verbose) _print("JFastLogView_noWrap painted"); } public Dimension getPreferredSize() { FontMetrics fm = componentFontMetrics(this); if (fm == null) return new Dimension(50, 50); // not renderable yet int fh = fm.getHeight(); int w = 0; for (int i = 0; i < l(lines); i++) { String s = get(lines, i); w = max(w, fm.stringWidth(unnull(s))); // TODO: just count chars } return new Dimension(w, fh*l(lines)); } JFastLogView_noWrap() {} JFastLogView_noWrap(String text) { setText(text); } { componentPopupMenuItem(this, "Copy full text", new Runnable() { public void run() { try { copyFullText(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "copyFullText();"; }}); } // API // returns true if changed boolean setLines(Collection lines) { List newList = asSyncList(lines); if (eq(this.lines, newList)) return false; this.lines = newList; _revalidate(this); return true; } // returns true if changed boolean setText(String text) { endsWithNewLine = endsWithNewLine(text); return setLines(lines(text)); } void append(String text) { if (nempty(text)) setText(getText() + text); } String getText() { return lines_rtrimIf(!endsWithNewLine, cloneList(lines)); } void copyFullText() { copyTextToClipboard(getText()); } } interface IDoublePt { public double x_double(); public double y_double(); } static interface IVar extends IF0 { void set(A a); A get(); // reified type of value (if available) default Class getType() { return null; } default boolean has() { return get() != null; } default void clear() { set(null); } } interface ChangeTriggerable { public void change(); } static List myInnerClasses_list=litlist( "VF1", "Meta", "VF2", "JSection", "Var", "DefunctClassLoader", "SnippetTranspiler", "ITokCondition", "TokCondition", "IntVar", "PopupMenuMaker", "findCodeTokens_Matcher", "ReliableSingleThread", "JFastLogView_noWrap", "CompactAbstractMap", "SingleComponentPanel", "CompactLinkedHashSet", "DynModule", "Fail", "IWebRequest", "Rect", "PtInComponent", "Pt", "ISetter", "F0", "F1", "IterableIterator", "F2", "Flag", "IF0", "Hasher", "CloseableIterableIterator", "IContentsIndexedList2", "getOpt_Map", "IF2", "IFieldsToList", "Producer", "IF1", "Value", "IVF1", "IVF2", "IVar", "IIntPred", "Cache", "_MethodCache", "Enterable", "Matches", "Symbol", "IGetterWithNotify", "IMeta", "CompactHashMap", "JS", "BetterThread", "LiveValue", "TranspileForServer", "Complex", "Q", "MultiMap", "IHasChangeListeners", "Lowest", "IResourceLoader", "WeakHasherMap", "Either", "proxy_InvocationHandler", "Pair", "ChangeTrigger", "CompilerBot", "IResourceHolder", "Swingable", "DynPrintLog", "Htmlable", "JMenuScroller", "JavaXClassLoader", "JavaXClassLoaderWithParent", "IAutoCloseableF0", "jLiveValueSection_class", "UnsynchronizedCompactHashSet", "ChangeTriggerable", "BetterLabel", "MRUCache", "componentPopupMenu_Adapter", "JavaXClassLoaderWithParent2", "PersistableThrowable", "IDoublePt", "HasIndex"); static List myInnerClasses() { return myInnerClasses_list; } static Class getClass(String name) { return _getClass(name); } static Class getClass(Object o) { return _getClass(o); } static Class getClass(Object realm, String name) { return _getClass(realm, name); } static boolean classIsExportedTo(Class c, java.lang.Module destModule) { if (c == null || destModule == null) return false; java.lang.Module srcModule = c.getModule(); String packageName = c.getPackageName(); return srcModule.isExported(packageName, destModule); } static boolean isAbstract(Class c) { return (c.getModifiers() & Modifier.ABSTRACT) != 0; } static boolean isAbstract(Method m) { return (m.getModifiers() & Modifier.ABSTRACT) != 0; } static boolean reflection_isForbiddenMethod(Method m) { return m.getDeclaringClass() == Object.class && eqOneOf(m.getName(), "finalize", "clone", "registerNatives"); } static Set allInterfacesImplementedBy(Class c) { if (c == null) return null; HashSet set = new HashSet(); allInterfacesImplementedBy_find(c, set); return set; } static void allInterfacesImplementedBy_find(Class c, Set set) { if (c.isInterface() && !set.add(c)) return; do { for (Class intf : c.getInterfaces()) allInterfacesImplementedBy_find(intf, set); } while ((c = c.getSuperclass()) != null); } static Method findMethod(Object o, String method, Object... args) { return findMethod_cached(o, method, args); } static boolean findMethod_checkArgs(Method m, Object[] args, boolean debug) { Class[] types = m.getParameterTypes(); if (types.length != args.length) { if (debug) System.out.println("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) { if (debug) System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]); return false; } return true; } static Method findStaticMethod(Class c, String method, Object... args) { Class _c = c; while (c != null) { for (Method m : c.getDeclaredMethods()) { if (!m.getName().equals(method)) continue; if ((m.getModifiers() & Modifier.STATIC) == 0 || !findStaticMethod_checkArgs(m, args)) continue; return m; } c = c.getSuperclass(); } return null; } static boolean findStaticMethod_checkArgs(Method m, Object[] args) { Class[] types = m.getParameterTypes(); if (types.length != args.length) return false; for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) return false; return true; } static List quoteAll(String[] l) { return quoteAll(asList(l)); } static List quoteAll(Collection l) { List x = new ArrayList(); for (String s : l) x.add(quote(s)); return x; } static int _hashCode(Object a) { return a == null ? 0 : a.hashCode(); } static ArrayList toList(A[] a) { return asList(a); } static ArrayList toList(int[] a) { return asList(a); } static ArrayList toList(Set s) { return asList(s); } static ArrayList toList(Iterable s) { return asList(s); } static boolean arraysEqual(Object[] a, Object[] b) { if (a.length != b.length) return false; for (int i = 0; i < a.length; i++) if (neq(a[i], b[i])) return false; return true; } static Object metaGet(IMeta o, Object key) { return metaMapGet(o, key); } static Object metaGet(Object o, Object key) { return metaMapGet(o, key); } static Object metaGet(String key, IMeta o) { return metaMapGet(o, key); } static Object metaGet(String key, Object o) { return metaMapGet(o, key); } static Object metaMapGet(IMeta o, Object key) { return o == null ? null : o.metaGet(key); // We now let the object itself do it (overridable!) } static Object metaMapGet(Object o, Object key) { return metaMapGet(toIMeta(o), key); } static void metaPut(IMeta o, Object key, Object value) { metaMapPut(o, key, value); } static void metaPut(Object o, Object key, Object value) { metaMapPut(o, key, value); } static Map convertObjectMetaToMap(IMeta o) { return convertObjectMetaToMap(o, () -> makeObjectMetaMap()); } static Map convertObjectMetaToMap(IMeta o, IF0 createEmptyMap) { if (o == null) return null; // The following shortcut depends on the assumption that a meta field never reverts // to null when it was a map Object meta = o._getMeta(); if (meta instanceof Map) return ((Map) meta); // non-shortcut path (create meta) var mutex = tempMetaMutex(o); try { var actualMutex = mutex.get(); synchronized(actualMutex) { meta = o._getMeta(); if (meta instanceof Map) return ((Map) meta); Map map = createEmptyMap.get(); if (meta != null) map.put("previousMeta" , meta); o._setMeta(map); return map; } } finally { _close(mutex); }} static void syncMapPutOrRemove(Map map, A key, B value) { syncMapPut2(map, key, value); } static String jsDollarVars(String s, Object... __) { return replaceDollarVars_js(s, __); } static Set addToSet_create(Set set, A a) { return createOrAddToSet(set, a); } static String shortClassName_dropNumberPrefix(Object o) { return dropNumberPrefix(shortClassName(o)); } static boolean preferCached = false; static boolean loadSnippet_debug = false; static ThreadLocal loadSnippet_silent = new ThreadLocal(); static ThreadLocal loadSnippet_publicOnly = new ThreadLocal(); static int loadSnippet_timeout = 30000; static String loadSnippet(String snippetID) { try { if (snippetID == null) return null; return loadSnippet(parseSnippetID(snippetID), preferCached); } catch (Exception __e) { throw rethrow(__e); } } static String loadSnippet(String snippetID, boolean preferCached) throws IOException { return loadSnippet(parseSnippetID(snippetID), preferCached); } static IF1 loadSnippet; static String loadSnippet(long snippetID) { return loadSnippet != null ? loadSnippet.get(snippetID) : loadSnippet_base(snippetID); } final static String loadSnippet_fallback(IF1 _f, long snippetID) { return _f != null ? _f.get(snippetID) : loadSnippet_base(snippetID); } static String loadSnippet_base(long snippetID) { try { return loadSnippet(snippetID, preferCached); } catch (Exception __e) { throw rethrow(__e); } } static String loadSnippet(long snippetID, boolean preferCached) throws IOException { if (isLocalSnippetID(snippetID)) return loadLocalSnippet(snippetID); IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.loadSnippet(fsI(snippetID)); return loadSnippet_noResourceLoader(snippetID, preferCached); } static String loadSnippet_noResourceLoader(long snippetID, boolean preferCached) throws IOException { String text; // boss bot (old concept) /*text = getSnippetFromBossBot(snippetID); if (text != null) return text;*/ initSnippetCache(); text = DiskSnippetCache_get(snippetID); if (preferCached && text != null) return text; try { if (loadSnippet_debug && text != null) System.err.println("md5: " + md5(text)); String url = tb_mainServer() + "/getraw.php?id=" + snippetID + "&utf8=1"; if (nempty(text)) url += "&md5=" + md5(text); if (!isTrue(loadSnippet_publicOnly.get())) url += standardCredentials(); String text2 = loadSnippet_loadFromServer(url); boolean same = eq(text2, "==*#*=="); if (loadSnippet_debug) print("loadSnippet: same=" + same); if (!same) text = text2; } catch (RuntimeException e) { e.printStackTrace(); throw new IOException("Snippet #" + snippetID + " not found or not public"); } try { initSnippetCache(); DiskSnippetCache_put(snippetID, text); } catch (IOException e) { System.err.println("Minor warning: Couldn't save snippet to cache (" + DiskSnippetCache_getDir() + ")"); } return text; } static File DiskSnippetCache_dir; public static void initDiskSnippetCache(File dir) { DiskSnippetCache_dir = dir; dir.mkdirs(); } public static synchronized String DiskSnippetCache_get(long snippetID) throws IOException { return loadTextFile(DiskSnippetCache_getFile(snippetID).getPath(), null); } private static File DiskSnippetCache_getFile(long snippetID) { return new File(DiskSnippetCache_dir, "" + snippetID); } public static synchronized void DiskSnippetCache_put(long snippetID, String snippet) throws IOException { saveTextFile(DiskSnippetCache_getFile(snippetID).getPath(), snippet); } public static File DiskSnippetCache_getDir() { return DiskSnippetCache_dir; } public static void initSnippetCache() { if (DiskSnippetCache_dir == null) initDiskSnippetCache(getGlobalCache()); } static String loadSnippet_loadFromServer(String url) { Integer oldTimeout = setThreadLocal(loadPage_forcedTimeout_byThread, loadSnippet_timeout); try { return isTrue(loadSnippet_silent.get()) ? loadPageSilently(url) : loadPage(url); } finally { loadPage_forcedTimeout_byThread.set(oldTimeout); } } static long sysNow() { ping(); return System.nanoTime()/1000000; } static boolean transpileRaw_silent = true; static boolean transpileRaw_useDiskCache = false; static Class transpileRaw_trans; static boolean transpileRaw_mine = true; static boolean transpileRaw_verySilent = false; static boolean transpileRaw_dontCopyFromCreator = false; static Lock transpileRaw_lock = lock(); static ThreadLocal transpileRaw_asInclude = new ThreadLocal(); static ThreadLocal transpileRaw_progID = new ThreadLocal(); static String transpileRaw(String mainJava) { return transpileRaw(mainJava, false, transpileRaw_useDiskCache); } static String transpileRaw(String mainJava, boolean fragment) { return transpileRaw(mainJava, fragment, transpileRaw_useDiskCache); } static String transpileRaw(String mainJava, boolean fragment, boolean useDiskCache) { mainJava = dropTranslators(mainJava); if (!transpileRaw_dontCopyFromCreator) transpileRaw_copyFromCreator(); Lock __0 = transpileRaw_lock; lock(__0); try { File cacheFile = null; if (useDiskCache) { cacheFile = new File(javaxCodeDir(), "Transpilations/" + uniqueFileNameUsingMD5_80_v2(mainJava) + ".java"); { String __3 = loadTextFile(cacheFile); if (!empty(__3)) return __3; } } AutoCloseable __4 = transpileRaw_verySilent ? null : tempLoadingAnim("Transpiling..."); try { transpileRaw_translator(); //setOpt(transpileRaw_trans, dontPrintSource := true); setOpt(transpileRaw_trans, "localStuffOnly" , fragment); setOpt(transpileRaw_trans, "asInclude" , isTrue(transpileRaw_asInclude.get())); setOpt(transpileRaw_trans, "mainSnippetID" , transpileRaw_progID.get()); set(transpileRaw_trans, "mainJava", mainJava); // TODO: setOpt(transpileRaw_trans, transpilingSnippetID := ); set(transpileRaw_trans, "print_byThread", print_byThread); if (!transpileRaw_verySilent) print("Running translator " + getOpt(transpileRaw_trans, "programID")); callMain(transpileRaw_trans); //print("Ran translator " + identityHashCode(transpileRaw_trans)); String main = (String) (get(transpileRaw_trans, "mainJava")); if (useDiskCache) { saveTextFile(new File(cacheFile.getPath() + "x"), mainJava); saveTextFile(cacheFile, main); } return main; } finally { _close(__4); }} finally { unlock(__0); } } static IF0 transpileRaw_translator; static Class transpileRaw_translator() { return transpileRaw_translator != null ? transpileRaw_translator.get() : transpileRaw_translator_base(); } final static Class transpileRaw_translator_fallback(IF0 _f) { return _f != null ? _f.get() : transpileRaw_translator_base(); } static Class transpileRaw_translator_base() { if (transpileRaw_trans == null) { //print("Loading translator."); transpileRaw_trans = transpileRaw_makeTranslator(); transpileRaw_mine = true; makeDependent(transpileRaw_trans); //print("Loaded translator: " + identityHashCode(transpileRaw_trans)); } setOpt(transpileRaw_trans, "print_silent", transpileRaw_silent); return transpileRaw_trans; } static IF0 transpileRaw_makeTranslator; static Class transpileRaw_makeTranslator() { return transpileRaw_makeTranslator != null ? transpileRaw_makeTranslator.get() : transpileRaw_makeTranslator_base(); } final static Class transpileRaw_makeTranslator_fallback(IF0 _f) { return _f != null ? _f.get() : transpileRaw_makeTranslator_base(); } static Class transpileRaw_makeTranslator_base() { return hotwireSharingLibraries_silently(defaultJavaXTranslatorID()); } static void transpileRaw_copyFromCreator() { Lock __1 = transpileRaw_lock; lock(__1); try { if (transpileRaw_trans != null) return; Object c = creator(); if (c == null) return; Class trans = (Class) (getOpt(c, "transpileRaw_trans")); Lock lock = (Lock) (getOpt(c, "transpileRaw_lock")); if (trans != null && lock != null) { print("Using creator's transpiler: " + getProgramID(c) + " => " + programID()); transpileRaw_lock = lock; transpileRaw_trans = trans; transpileRaw_mine = false; } } finally { unlock(__1); } } static void cleanMeUp_transpileRaw() { if (transpileRaw_mine) cleanUp(transpileRaw_trans); transpileRaw_trans = null; // release proactively (it's big) } static void printLineContextAfterJavaCompilerError(Throwable error, String src) { // (line 980,col 1) int line = parseIntOpt(jextract("(line ,", str(error))); if (line != 0) printLineWithContext(src, line); } static String loadProgramTextFile(String name) { return loadTextFile(getProgramFile(name)); } static String loadProgramTextFile(String progID, String name) { return loadTextFile(getProgramFile(progID, name)); } static String loadProgramTextFile(String progID, String name, String defaultText) { return loadTextFile(getProgramFile(progID, name), defaultText); } static long done2_always(long startTime, String desc) { long time = sysNow()-startTime; // BREAKING CHANGE: Now stores result for lastTiming() saveTiming_noPrint(time); print(desc + " [" + time + " ms]"); return time; } static long done2_always(String desc, long startTime) { return done2_always(startTime, desc); } static long done2_always(long startTime) { return done2_always(startTime, ""); } // probably better than findTranslators (uses tokens) // removes invocations from src static String findTranslators2(String src, List libsOut) { return join(findTranslators2(javaTok(src), libsOut)); } // modifies original tok static List findTranslators2(List tok, List libsOut) { int i; while ((i = jfind(tok, "!")) >= 0) { setAdd(libsOut, tok.get(i+2)); clearTokens(tok, i, i+3); } return tok; } static String or2(String a, String b) { return nempty(a) ? a : b; } static String or2(String a, String b, String c) { return or2(or2(a, b), c); } static Pair uploadTranspilation(String progID, String transpilation, List libs) { String server = tb_mainServer(); String transpilationResult = postPageWithCredentials(server + "/tb/upload-transpilation.php", "id" , psI(progID), "transpilation", transpilation, "libs" , lines(map(__46 -> parseSnippetID(__46), libs)), "computer" , computerID()); Matcher m = regexp("URL=/(dexcompile\\.php.*?)'", transpilationResult); if (!m.find()) throw fail("Server said: " + transpilationResult); String url = addParamToURL(server + "/" + m.group(1), "useJarBot" , 1); String compilationResult = postPageWithCredentials(url); print(compilationResult); boolean ok = compilationResult.contains("" + "SUCCESS"); // XXX sendToSnippetUpdatesBot((ok ? "/transpileOK" : "transpileFail") + "/" + psI(progID)); if (!ok) throw fail("Server said: " + compilationResult); print("Transpiled & uploaded " + fsI(progID) + "!"); return pair(transpilationResult, compilationResult); } static <A> List<A> synchroLinkedList() { return synchroList(new LinkedList<A>()); } static Class _run(String progID, String... args) { Class main = hotwire(progID); callMain(main, args); return main; } static void add(BitSet bs, int i) { bs.set(i); } static <A> boolean add(Collection<A> c, A a) { return c != null && c.add(a); } static void add(Container c, Component x) { addToContainer(c, x); } static long add(AtomicLong l, long b) { return l.addAndGet(b); } static Runnable toRunnable(final Object o) { if (o instanceof Runnable) return (Runnable) o; if (o instanceof String) throw fail("callF_legacy"); return new Runnable() { public void run() { try { callF(o) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(o)"; }}; } static <A> A syncPopFirst(List<A> l) { if (empty(l)) return null; synchronized(l) { A a = first(l); l.remove(0); return a; } } static int inc(AtomicInteger i) { return incAtomicInt(i); } static int inc(AtomicInteger i, int delta) { return incAtomicInt(i, delta); } static long inc(AtomicLong l) { return incAtomicLong(l); } static long inc(AtomicLong l, long b) { return l.addAndGet(b); } static int inc(IntVar v) { synchronized(v) { int val = v.get() + 1; v.set(val); return val; } } static String systemHashCodeHex(Object o) { return intToHex(identityHashCode(o)); } static boolean isEmpty(Collection c) { return c == null || c.isEmpty(); } static boolean isEmpty(CharSequence s) { return s == null || s.length() == 0; } static boolean isEmpty(Object[] a) { return a == null || a.length == 0; } static boolean isEmpty(byte[] a) { return a == null || a.length == 0; } static boolean isEmpty(Map map) { return map == null || map.isEmpty(); } static String nEntries(long n) { return n2(n, "entry", "entries"); } static String nEntries(Collection l) { return nEntries(l(l)); } static String nEntries(Map map) { return nEntries(l(map)); } static <A, B> Map<A, B> putAll(Map<A, B> a, Map<? extends A,? extends B> b) { if (a != null && b != null) a.putAll(b); return a; } static <A, B> MultiMap<A, B> putAll(MultiMap<A, B> a, Map<? extends A,? extends B> b) { if (a != null) a.putAll((Map) b); return a; } static <A, B> Map<A, B> putAll(Map<A, B> a, Object... b) { if (a != null) litmap_impl(a, b); return a; } static <A> void remove(List<A> l, int i) { if (l != null && i >= 0 && i < l(l)) l.remove(i); } static <A> void remove(Collection<A> l, A a) { if (l != null) l.remove(a); } static <A, B> B remove(Map<A, B> map, Object a) { return map == null ? null : map.remove(a); } static void remove(BitSet bs, int i) { bs.clear(i); } static <A> A getAndClear(IVar<A> v) { A a = v.get(); v.set(null); return a; } static <A, B> Set<A> keySet(Map<A, B> map) { return map == null ? new HashSet() : map.keySet(); } static Set keySet(Object map) { return keys((Map) map); } static <A, B> Set<A> keySet(MultiMap<A, B> mm) { return mm.keySet(); } static <A, B> int keysSize(MultiMap<A, B> mm) { return lKeys(mm); } static <A> A reverseGet(List<A> l, int idx) { if (l == null || idx < 0) return null; int n = l(l); return idx < n ? l.get(n-1-idx) : null; } static File loadLibrary(String snippetID) { return loadBinarySnippet(snippetID); } // TODO: use actualUserHome()? // (there was a problem with onLocallyInferiorJavaX() always triggering inside #1013896) static File pathToJavaxJar() { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.pathToJavaXJar(); return pathToJavaxJar_noResourceLoader(); } static File pathToJavaxJar_noResourceLoader() { try { int x = latestInstalledJavaX(); File xfile = new File(userHome(), ".javax/x" + Math.max(x, 30) + ".jar"); if (!xfile.isFile()) { print("Saving " + f2s(xfile)); String url = x30JarServerURL(); byte[] data = loadBinaryPage(url); if (data.length < 1000000) throw fail("Could not load " + url); saveBinaryFile(xfile.getPath(), data); } return xfile; } catch (Exception __e) { throw rethrow(__e); } } static Method hashMap_findKey_method; static <A, B> A hashMap_findKey(HashMap<A, B> map, Object key) { try { if (hashMap_findKey_method == null) hashMap_findKey_method = findMethodNamed(HashMap.class, "getNode"); Map.Entry<A, B> entry = (Map.Entry) hashMap_findKey_method.invoke(map, hashMap_internalHash(key), key); // java.util.Map.Entry<A, B> entry = (java.util.Map.Entry) call(hash, 'getNode, hashMap_internalHash(key), wkey); return entry == null ? null : entry.getKey(); } catch (Exception __e) { throw rethrow(__e); } } static String b(Object contents, Object... params) { return tag("b", contents, params); } static String shortClassName(Object o) { if (o == null) return null; Class c = o instanceof Class ? (Class) o : o.getClass(); String name = c.getName(); return shortenClassName(name); } static <A, B> boolean isA(Either<A, B> e) { return eitherIsA(e); } static Flag dm_initErrorHandling_flag = new Flag(); static void dm_initErrorHandling() { raiseFlagAndDo(dm_initErrorHandling_flag, new Runnable() { public void run() { try { _handleException_addHandler(__1 -> dm_initErrorHandling_handler(__1)); assertNull(_onRegisterThread); _onRegisterThread = new VF1<Thread>() { public void get(Thread t) { try { Object m = dm_current_generic(); if (m == null) printStackTrace("New thread made outside of a module"); else if (m instanceof DynModule) ((DynModule) m).ownTimer(t); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "O m = dm_current_generic();\r\n if (m == null) printStackTrace(\"New thread..."; }}; _threadInfo_makers.add(new VF1<Map>() { public void get(Map map) { try { mapPut(map, "currentModule", dm_currentModule()) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "mapPut(map, \"currentModule\", dm_currentModule())"; }}); _threadInheritInfo_retrievers.add(new VF1<Map>() { public void get(Map map) { try { Object mod = map.get("currentModule"); if (mod instanceof DynModule) dm_current_generic_tl().set(new WeakReference((DynModule) mod)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "O mod = map.get(\"currentModule\");\r\n if (mod cast DynModule)\r\n dm_..."; }}); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "_handleException_addHandler(lambda1 dm_initErrorHandling_handler);\r\n \r\n ..."; }}); } static void dm_initErrorHandling_handler(Throwable e) { DynModule m = dm_currentModule(); if (m == null) print("Weird: Error outside of module"); else m.setField("_error" , persistableThrowable(e)); } static void setMainDesktopPane(JDesktopPane desktop) { mainDesktopPane_value = desktop; } static <A> A getCreatorOpt(String field) { return (A) getOpt(creator(), field); } static <A extends Component> A possiblyInternalFrameTitle(A c, String title) { JInternalFrame f = getInternalFrame(c); if (f != null) internalFrameTitle(f, title); else frameTitle(getFrame(c), title); return c; } static String possiblyInternalFrameTitle(Component c) { JInternalFrame f = getInternalFrame(c); return f != null ? internalFrameTitle(f) : frameTitle(getFrame(c)); } static void ownResource(AutoCloseable c) { _registerAutoCloseable(c); } static void cancelTimerOrInterruptThread(Object timer) { if (timer instanceof Thread && !(timer instanceof AutoCloseable)) // AutoCloseable takes precedence interruptThread((Thread) timer); else cancelTimer(timer); } static <A> List<A> getAndClearList(Collection<A> l) { if (l == null) return emptyList(); synchronized(collectionMutex(l)) { List<A> out = cloneList(l); l.clear(); return out; } } static <A, B> Map<A, B> getAndClearMap(Map<A, B> map) { if (map == null) return emptyMap(); synchronized(collectionMutex(map)) { Map<A, B> out = cloneMap(map); map.clear(); return out; } } static Object pcallF(Object f, Object... args) { return pcallFunction(f, args); } static <A> A pcallF(F0<A> f) { try { return f == null ? null : f.get(); } catch (Throwable __e) { printStackTrace(__e); } return null; } static <A, B> B pcallF(F1<A, B> f, A a) { try { return f == null ? null : f.get(a); } catch (Throwable __e) { printStackTrace(__e); } return null; } static <A> void pcallF(VF1<A> f, A a) { try { { if (f != null) f.get(a); } } catch (Throwable __e) { printStackTrace(__e); } } static Object pcallF(Runnable r) { try { { if (r != null) r.run(); } } catch (Throwable __e) { printStackTrace(__e); } return null; } static <A> A pcallF(IF0<A> f) { try { return f == null ? null : f.get(); } catch (Throwable __e) { printStackTrace(__e); } return null; } static <A, B> B pcallF(IF1<A, B> f, A a) { try { return f == null ? null : f.get(a); } catch (Throwable __e) { printStackTrace(__e); } return null; } static void pcallFAll(Collection l, Object... args) { if (l != null) for (Object f : cloneList(l)) pcallF(f, args); } static void pcallFAll(Iterator it, Object... args) { while (it.hasNext()) pcallF(it.next(), args); } static boolean dm_isPersistentField(String field) { return dm_isPersistentField(dm_current_mandatory(), field); } static boolean dm_isPersistentField(DynModule m, String field) { return m.persistOnChangedField && !isTransientField(m, field) && !isFalse(mapGet(m._persistenceInfo, field)); } static Rect dm_getBounds(Object module) { return shallowCloneToClass(Rect.class, call(dm_getStem(module), "getFrameRect")); } static Rect dm_getBounds() { return dm_getBounds(dm_current_generic()); } static boolean hasMethod_onTypes(Object o, String method, Class... argTypes) { return findMethod_precise_onTypes(o, method, argTypes) != null; } static void dm_onTopInput_q(final VF1<String> r) { final DynModule m = dm_current_mandatory(); dm_onTopInput(new VF1<String>() { public void get(final String s) { try { m.q().add(new Runnable() { public void run() { try { callF(r, s); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(r, s);"; }}); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "switch to m.q();\r\n callF(r, s);"; }}); } static <A> AutoCloseable tempSetBetterThreadLocalIfNecessary_weakRef(x30_pkg.x30_util.BetterThreadLocal<WeakReference> tl, A a) { if (tl == null) return null; WeakReference prev = tl.get(); if (eq(getWeakRef(prev), a)) return null; tl.set(weakRef(a)); return new AutoCloseable() { public String toString() { return "tl.set(prev);"; } public void close() throws Exception { tl.set(prev); }}; } static AutoCloseable combineAutoCloseables(final AutoCloseable a, final AutoCloseable b) { return a == null ? b : b == null ? a : new AutoCloseable() { public String toString() { return "pClose(a); pClose(b);"; } public void close() throws Exception { pClose(a); pClose(b); }}; } static AutoCloseable combineAutoCloseables(AutoCloseable a, AutoCloseable b, AutoCloseable c, AutoCloseable... more) { return combineAutoCloseables(concatLists(ll(a, b, c), asList(more))); } static AutoCloseable combineAutoCloseables(Iterable<AutoCloseable> l) { return foldl(new F2<AutoCloseable, AutoCloseable, AutoCloseable>() { public AutoCloseable get(AutoCloseable a, AutoCloseable b) { try { return combineAutoCloseables(a,b); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "combineAutoCloseables(a,b)"; }}, null, l); } static ThreadLocal realMC_tl_tl = new ThreadLocal(); static ThreadLocal realMC_tl() { return realMC_tl_tl; } // accept purpose argument so we are a drop-in for tempVerboseLock static AutoCloseable tempLock(Lock lock) { return tempLock("", lock); } static AutoCloseable tempLock(String purpose, Lock lock) { if (lock == null) return null; lock(lock); return new AutoCloseable() { public String toString() { return "unlock(lock);"; } public void close() throws Exception { unlock(lock); }}; } static <A> boolean addIfNotThere(Collection<A> c, A a) { return setAdd(c, a); } static <A extends JSpinner> A onChange(A spinner, Object r) { return onChange(spinner, toRunnable(r)); } static <A extends JSpinner> A onChange(A spinner, Runnable r) { if (r != null) { swing(() -> { spinner.addChangeListener(changeListener(r)); }); } return spinner; } static <A extends AbstractButton> A onChange(A b, Object r) { { swing(() -> { b.addItemListener(itemListener(r)); }); } return b; } static void onChange(JTextComponent tc, Object r) { onUpdate(tc, r); } static void onChange(JTextComponent tc, Runnable r) { onUpdate(tc, r); } static <A extends JSlider> A onChange(A slider, final Object r) { { swing(() -> { slider.addChangeListener(changeListener(r)); }); } return slider; } static <A> JComboBox<A> onChange(JComboBox<A> cb, Runnable r) { addActionListener(cb, r); return cb; } static <A> JComboBox<A> onChange(JComboBox<A> cb, IVF1<A> f) { if (f != null) addActionListener(cb, () -> f.get(getSelectedItem_typed(cb))); return cb; } static JComboBox onChange(Object r, JComboBox cb) { return onChange(cb, r); } static JComboBox onChange(JComboBox cb, final Object r) { if (isEditableComboBox(cb)) onChange(textFieldFromComboBox(cb), r); else onSelectedItem(cb, new VF1<String>() { public void get(String s) { try { callF(r) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(r)"; }}); return cb; } static <A extends JTabbedPane> A onChange(A tabs, Runnable r) { { swing(() -> { tabs.addChangeListener(changeListener(r)); }); } return tabs; } static <A extends JColorChooser> A onChange(Runnable r, A cc) { if (cc != null && r != null) { swing(() -> { cc.getSelectionModel().addChangeListener(changeListener(r)); }); } return cc; } static void onChange(IHasChangeListeners a, ChangeTriggerable b) { if (a != null && b != null) a.onChange(new ChangeTrigger(b)); } // action = runnable or method name static void onUpdateAndNow(JComponent c, final Object r) { onUpdate(c, r); callF(r); } static void onUpdateAndNow(List<? extends JComponent> l, Object r) { for (JComponent c : l) onUpdate(c, r); callF(r); } static void onUpdate(JComponent c, Runnable r) { onUpdate(c, (Object) r); } // legacy signature static void onUpdate(JComponent c, Object r) { if (c instanceof JTextComponent) ((JTextComponent) c).getDocument().addDocumentListener(new DocumentListener() { public void insertUpdate(DocumentEvent e) { call(r); } public void removeUpdate(DocumentEvent e) { call(r); } public void changedUpdate(DocumentEvent e) { call(r); } }); else if (c instanceof ItemSelectable) // JCheckBox and others ((ItemSelectable) c).addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { call(r); } }); else print("Warning: onUpdate doesn't know " + getClassName(c)); } static void onUpdate(List<? extends JComponent> l, Object r) { for (JComponent c : l) onUpdate(c, r); } static void zeroAllFieldsOfTypeExcept(Object o, Class type, String... exceptions) { zeroAllFieldsOfTypeExcept(o, type, asSet(exceptions)); } static void zeroAllFieldsOfTypeExcept(Object o, Class type, Collection<String> exceptions) { Set<String> set = asSet(exceptions); for (String field : allFields(o)) if (!set.contains(field) && instanceOf(getOpt(o, field), type)) set(o, field, null); } static List<AbstractAction> paramsToAbstractActions(Object... params) { List<AbstractAction> l = new ArrayList(); for (int i = 0; i+1 < l(params); i += 2) { String text = (String) (params[i]); Runnable action = (Runnable) (params[i+1]); if (nempty(text)) l.add(abstractAction(text, action)); } return l; } static void internalFramePopupMenuFromActions_threaded(Container f, List<AbstractAction> actions) { if (!(f instanceof JInternalFrame)) return; for (final AbstractAction a : unnull(actions)) if (a != null) internalFramePopupMenuItem(((JInternalFrame) f), str(a.getValue(Action.NAME)), runnableThread(new Runnable() { public void run() { try { callAction(a) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callAction(a)"; }})); } static <A> LinkedHashSet<A> asLinkedHashSet(A[] array) { LinkedHashSet<A> set = new LinkedHashSet(); for (A o : array) if (o != null) set.add(o); return set; } static <A> LinkedHashSet<A> asLinkedHashSet(Collection<A> l) { if (l instanceof LinkedHashSet) return (LinkedHashSet) l; LinkedHashSet<A> set = new LinkedHashSet(); for (A o : l) if (o != null) set.add(o); return set; } static List<String> splitAtSpace(String s) { return empty(s) ? emptyList() : asList(s.split("\\s+")); } static Map<Class, Set<String>> allFields_cache = weakHashMap(); static Set<String> allFields(Object o) { if (o == null) return emptySet(); Class _c = _getClass(o); Set<String> fields = allFields_cache.get(_c); if (fields == null) allFields_cache.put(_c, fields = asTreeSet(keys(getOpt_getFieldMap(o)))); return fields; } static Class fieldType(Object o, String field) { Field f = getField(o, field); return f == null ? null : f.getType(); } static void dm_boolFieldMenuItem(Container frame, final String field, final Object... __) { final DynModule m = dm_current_mandatory(); final String humanized = humanizeFormLabel(field); internalFrameTitlePopupMenu(((JInternalFrame) frame), new VF1<JPopupMenu>() { public void get(JPopupMenu menu) { try { menu.add(jCheckBoxMenuItem(humanized, (boolean) _get(m, field), new VF1<Boolean>() { public void get(Boolean b) { try { m.setField(field, b); callF(optPar(__, "onSet")); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "m.setField(field, b);\r\n callF(optPar(_, 'onSet));"; }})); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "menu.add(jCheckBoxMenuItem(humanized, (bool) _get(m, field), voidfunc(bool b)..."; }}); } static void dm_intFieldMenuItem(Container frame, final String field, final Object... __) { final DynModule m = dm_current_mandatory(); final String humanized = humanizeFormLabel(field); internalFramePopupMenuItem(((JInternalFrame) frame), humanizeFormLabel(field) + "...", new Runnable() { public void run() { try { final JTextField tf = jtextfield(get(m, field)); showFormTitled(or2(stringOptPar(__, "formTitle"), "Set " + humanized), humanized + ":", tf, new Runnable() { public void run() { try { m.setField(field, parseInt(gtt(tf))); callF(optPar(__, "onSet")); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "m.setField(field, parseInt(gtt(tf)));\r\n callF(optPar(__, \"onSet\"));"; }}); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final JTextField tf = jtextfield(get(m, field));\r\n showFormTitled(or2(stri..."; }}); } static void dm_longFieldMenuItem(Container frame, final String field, final Object... __) { final DynModule m = dm_current_mandatory(); final String humanized = humanizeFormLabel(field); internalFramePopupMenuItem(((JInternalFrame) frame), humanizeFormLabel(field) + "...", new Runnable() { public void run() { try { final JTextField tf = jtextfield(get(m, field)); showFormTitled(or2(stringOptPar(__, "formTitle"), "Set " + humanized), humanized + ":", tf, new Runnable() { public void run() { try { m.setField(field, parseLong(gtt(tf))); callF(optPar(__, "onSet")); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "m.setField(field, parseLong(gtt(tf)));\r\n callF(optPar(__, \"onSet\"));"; }}); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final JTextField tf = jtextfield(get(m, field));\r\n showFormTitled(or2(stri..."; }}); } static void dm_doubleFieldMenuItem(Container frame, final String field, final Object... __) { final DynModule m = dm_current_mandatory(); internalFramePopupMenuItem(((JInternalFrame) frame), humanizeFormLabel(field) + "...", new Runnable() { public void run() { try { AutoCloseable __1 = m.enter(); try { dm_doubleFieldSetterDialog(field, __); } finally { _close(__1); }} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp m.enter();\r\n dm_doubleFieldSetterDialog(field, __);"; }}); } static void dm_floatFieldMenuItem(Container frame, String field, Object... __) { DynModule m = dm_current_mandatory(); internalFramePopupMenuItem(((JInternalFrame) frame), humanizeFormLabel(field) + "...", new Runnable() { public void run() { try { AutoCloseable __1 = m.enter(); try { dm_floatFieldSetterDialog(field, __); } finally { _close(__1); }} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp m.enter();\r\n dm_floatFieldSetterDialog(field, __);"; }}); } static void dm_stringFieldMenuItem(Container frame, final String field, final Object... __) { final DynModule m = dm_current_mandatory(); internalFramePopupMenuItem(((JInternalFrame) frame), humanizeFormLabel(field) + "...", new Runnable() { public void run() { try { AutoCloseable __1 = m.enter(); try { dm_stringFieldDialog(field, __); } finally { _close(__1); }} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp m.enter();\r\n dm_stringFieldDialog(field, __);"; }}); } static void dm_fileFieldMenuItem(Container frame, String field, Object... __) { DynModule m = dm_current_mandatory(); internalFramePopupMenuItem(((JInternalFrame) frame), humanizeFormLabel(field) + "...", new Runnable() { public void run() { try { AutoCloseable __1 = m.enter(); try { dm_fileFieldDialog(field, __); } finally { _close(__1); }} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp m.enter();\r\n dm_fileFieldDialog(field, __);"; }}); } static ReliableSingleThread dm_rst(Runnable r) { return dm_rst(dm_current_mandatory(), r); } static ReliableSingleThread dm_rst(DynModule mod, Runnable r) { return dm_rst(mod, new ReliableSingleThread(r)); } static ReliableSingleThread dm_rst(DynModule mod, ReliableSingleThread rst) { rst.enter = dm_rEnter(mod); return rst; } static Q dm_startQ() { return dm_ownQ(startQ()); } static Q dm_startQ(String name) { return dm_ownQ(startQ(name)); } static JComponent dm_noVisualisation() { return setToolTip("Module has no visualization", jimage("#1101480")); } static String snippetTitle(String id) { return getSnippetTitle(id); } static String snippetTitle(long id) { return getSnippetTitle(id); } static Class mainClass() { return getMainClass(); } static Class mainClass(Object o) { return getMainClass(o); } static <A, B> Map<A, B> mapMinus(Map<A, B> map, Object... keys) { if (empty(keys)) return map; Map<A, B> m2 = cloneMap(map); for (Object key : keys) m2.remove(key); return m2; } static Set<java.util.Timer> _registerTimer_list = newWeakHashSet(); static void _registerTimer_original(java.util.Timer timer) { _registerTimer_list.add(timer); } static void cleanMeUp__registerTimer() { cancelTimers(getAndClearList(_registerTimer_list)); } static String joinNemptiesWithColon(String... strings) { return joinNempties(": ", strings); } static String joinNemptiesWithColon(Collection<String> strings) { return joinNempties(": ", strings); } static String commaCombine(Object... l) { return joinNemptiesWithComma(flattenCollectionsAndArrays(ll(l))); } static int hashCodeFor(Object a) { return a == null ? 0 : a.hashCode(); } static String getClientIPFromHeaders(Map<String, String> headers) { //print("All headers: " + sfu(headers)); if (headers == null) return null; String remoteAddr = (String) (headers.get("remote-addr")); String client = (String) (headers.get("x-forwarded-for")); if (nempty(client)) remoteAddr += "," + client; return remoteAddr; } static RuntimeException unimplemented() { throw fail("TODO"); } static RuntimeException unimplemented(String msg) { throw fail("TODO: " + msg); } static RuntimeException unimplemented(Object obj) { throw fail("TODO: implement method in " + className(obj)); } static URI uri(String uri) { try { return new URI(uri); } catch (Exception __e) { throw rethrow(__e); } } static JPanel jSection(Component c) { return jSection("", c); } static JPanel jSection(final String title, final Component c) { return swing(new F0<JPanel>() { public JPanel get() { try { Border border = BorderFactory.createBevelBorder(BevelBorder.LOWERED); border = BorderFactory.createTitledBorder(border, title); JSection panel = new JSection(c); panel.setBorder(border); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Border border = BorderFactory.createBevelBorder(BevelBorder.LOWERED);\r\n bo..."; }}); } static JPanel jSection(String title) { return jSection(title, jpanel()); } static JPanel jSection(LiveValue<?> lv, Component c) { return jLiveValueSection(lv, c); } static JScrollPane jscroll_copyBackground(Component c) { return setScrollPaneBackground(getBackground(c), jscroll(c)); } static JFastLogView_noWrap jFastLogView_noWrap() { return jFastLogView_noWrap(""); } static JFastLogView_noWrap jFastLogView_noWrap(String text) { return withTypeWriterFont(swingNu(JFastLogView_noWrap.class, text)); } static String getPrintLog() { return str(print_log); } static <A extends JComponent> A componentPopupMenuItem(A c, final String name, final Object action) { componentPopupMenu(c, new VF1<JPopupMenu>() { public void get(JPopupMenu menu) { try { addMenuItem(menu, name, action); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addMenuItem(menu, name, action);"; }}); return c; } static void componentPopupMenuItem(JComponent c, final JMenuItem menuItem) { componentPopupMenu(c, new VF1<JPopupMenu>() { public void get(JPopupMenu menu) { try { addMenuItem(menu, menuItem); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addMenuItem(menu, menuItem);"; }}); } static void dm_clearModulePrintLog() { clearStringBuffer_gen(dm_current_mandatory()._actualPrintLog()); } static <A extends JComponent> A awtEvery(A component, long delay, Object r) { swingEvery(component, delay, r); return component; } static <A extends JComponent> A awtEvery(A component, long delay, long firstDelay, Object r) { swingEvery(component, delay, firstDelay, r); return component; } static void awtEvery(RootPaneContainer frame, long delay, Object r) { swingEvery(frame, delay, r); } static <A extends JComponent> A awtEvery(A component, double delaySeconds, Object r) { return awtEvery(component, toMS(delaySeconds), r); } static Object swing(Object f) { return swingAndWait(f); } static void swing(Runnable f) { swingAndWait(f); } static <A> A swing(F0<A> f) { return (A) swingAndWait(f); } static <A> A swing(IF0<A> f) { return (A) swingAndWait(f); } static boolean scrollAllTheWayDown_bruteForce = true; static <A extends JComponent> A scrollAllTheWayDown(A c) { if (c != null) { swing(() -> { int h = c.getHeight()-1; if (scrollAllTheWayDown_bruteForce) h = max(h, 100000); c.scrollRectToVisible(new Rectangle(0, h, 1, 1)); }); } return c; } // independent timer static void awtLater(int delay, final Object r) { swingLater(delay, r); } static void awtLater(int delay, Runnable r) { swingLater(delay, r); } static void awtLater(Object r) { swingLater(r); } static void awtLater(double delaySeconds, Runnable r) { swingLater(toMS(delaySeconds), r); } // dependent timer (runs only when component is visible) static void awtLater(JComponent component, int delay, Object r) { installTimer(component, r, delay, delay, false); } static void awtLater(JFrame frame, int delay, Object r) { awtLater(frame.getRootPane(), delay, r); } static StringBuffer liveLocalPrintLog_realMC(Object o) { Object realMC = getMainClass(o); if (realMC != mc()) return (StringBuffer) getOpt(realMC, "local_log"); return liveLocalPrintLog(); } static int boostHashCombine(int a, int b) { return a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2)); } static double sqrt(double x) { return Math.sqrt(x); } static <A> List<A> minus(Collection<A> a, Object... b) { Set set = asSet(b); List l = new ArrayList(); for (Object s : unnull(a)) if (!set.contains(s)) l.add(s); return l; } static BigInteger minus(BigInteger a, BigInteger b) { return a.subtract(b); } static Complex minus(Complex c) { return c == null ? null : complex(-c.re(), -c.im()); } static int minus(int a, int b) { return a-b; } static double minus(double a, double b) { return a-b; } static Pt ptMinus(Pt a, Pt b) { if (b == null) return a; return new Pt(a.x-b.x, a.y-b.y); } static UnsupportedOperationException unsupportedOperation() { throw new UnsupportedOperationException(); } static long toMS(double seconds) { return (long) (seconds*1000); } static <A, B> LinkedHashMap<A, B> cloneLinkedHashMap(Map<A, B> map) { return map == null ? new LinkedHashMap() : new LinkedHashMap(map); } // action = runnable or method name static void onChangeAndNow(JComponent c, Object r) { onUpdateAndNow(c, r); } static void onChangeAndNow(List<? extends JComponent> l, Object r) { onUpdateAndNow(l, r); } static <A> JComboBox<A> onChangeAndNow(JComboBox<A> cb, IVF1<A> f) { onChange(cb, f); { if (f != null) f.get(getSelectedItem_typed(cb)); } return cb; } static <A extends JTabbedPane> A onChangeAndNow(A tabs, Runnable r) { if (r != null) { onChange(tabs, r); r.run(); } return tabs; } static int syncL(Collection l) { if (l == null) return 0; synchronized(collectionMutex(l)) { return l.size(); } } static int syncL(Map map) { if (map == null) return 0; synchronized(collectionMutex(map)) { return map.size(); } } static <A> List<A> syncL() { return syncList(); } static Thread startThread(Object runnable) { return startThread(defaultThreadName(), runnable); } static Thread startThread(String name, Runnable runnable) { runnable = wrapAsActivity(runnable); return startThread(newThread(runnable, name)); } static Thread startThread(String name, Object runnable) { runnable = wrapAsActivity(runnable); return startThread(newThread(toRunnable(runnable), name)); } static Thread startThread(Thread t) { _registerThread(t); t.start(); return t; } static <A> List<A> syncGetAndClear(Collection<A> l) { return syncCloneAndClearList(l); } static void cancelAndInterruptThread(Thread t) { if (t == null) return; cancelThread(t); t.interrupt(); } static <A> List<A> syncList() { return synchroList(); } static <A> List<A> syncList(List<A> l) { return synchroList(l); } static Dimension getPreferredSize(final Component c) { return c == null ? null : swing(new F0<Dimension>() { public Dimension get() { try { return c.getPreferredSize(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return c.getPreferredSize();"; }}); } static int getWidth(Component c) { return c == null ? 0 : (int) swingCall(c, "getWidth"); } static int getHeight(Component c) { return c == null ? 0 : (int) swingCall(c, "getHeight"); } static Color getBackground(final Component c) { return c == null ? null : swing(new F0<Color>() { public Color get() { try { return c.getBackground(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return c.getBackground();"; }}); } static FontMetrics componentFontMetrics(JComponent c) { Font font = getFont(c); return font == null ? null : swing(new F0<FontMetrics>() { public FontMetrics get() { try { return c.getFontMetrics(font); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return c.getFontMetrics(font);"; }}); } static int idiv_ceil(int a, int b) { return (a+b-1)/b; } static int idiv_ceil(long a, long b) { return toInt_checked((a+b-1)/b); } static boolean setText_opt = true; // optimize by calling getText first static <A extends JTextComponent> A setText(A c, Object text) { setText((JComponent) c, text); return c; } static <A extends JComboBox> A setText(final A c, Object text) { // only for editable combo boxes at this point final String s = strUnnull(text); { swing(() -> { c.getEditor().setItem(s); }); } return c; } static void setText(JLabel c, Object text) { setText((JComponent) c, text); } static JButton setText(JButton c, Object text) { setText((JComponent) c, jlabel_textAsHTML_center_ifNeeded(strUnnull(text))); return c; } static <A extends JComponent> A setText(final A c, Object text) { if (c == null) return null; final String s = strUnnull(text); { swing(() -> { if (!setText_opt || neq(callOpt(c, "getText"), s)) call(c, "setText", s); }); } return c; } static <A> List<A> asSyncList(Iterable<A> l) { return asSynchroList(l); } static <A extends Component> A _revalidate(A c) { return revalidate(c); } static void _revalidate(JFrame f) { revalidate(f); } static void _revalidate(JInternalFrame f) { revalidate(f); } static boolean endsWithNewLine(String s) { return endsWith(s, "\n"); } static String getText(final AbstractButton c) { return c == null ? "" : (String) swingAndWait(new F0<Object>() { public Object get() { try { return c.getText(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return c.getText();"; }}); } static String getText(final JTextComponent c) { return c == null ? "" : (String) swingAndWait(new F0<Object>() { public Object get() { try { return c.getText(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return c.getText();"; }}); } static String getText(final JLabel l) { return l == null ? "" : (String) swingAndWait(new F0<Object>() { public Object get() { try { return l.getText(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return l.getText();"; }}); } // returns the contents of text field for editable combo box static String getText(final JComboBox cb) { if (cb == null) return null; if (isEditableComboBox(cb)) return unnull((String) cb.getEditor().getItem()); else return str(cb.getSelectedItem()); } static String lines_rtrimIf(boolean rtrim, List<String> lines) { return rtrim ? lines_rtrim(lines) : lines(lines); } static String copyTextToClipboard(Object _text) { String text = str(_text); StringSelection selection = new StringSelection(text); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); vmBus_send("newClipboardContents", text); return text; } static List<VF1<Map>> _threadInheritInfo_retrievers = synchroList(); static void _threadInheritInfo(Object info) { if (info == null) return; pcallFAll(_threadInheritInfo_retrievers, (Map) info); } static List<VF1<Map>> _threadInfo_makers = synchroList(); static Object _threadInfo() { if (empty(_threadInfo_makers)) return null; HashMap map = new HashMap(); pcallFAll(_threadInfo_makers, map); return map; } static Object _onAWTEnter_f; static AutoCloseable _onAWTEnter() { return (AutoCloseable) callF(_onAWTEnter_f); } static JDesktopPane mainDesktopPane_value; static JDesktopPane mainDesktopPane() { return mainDesktopPane_value; } static Method findMethod_cached(Object o, String method, Object... args) { try { if (o == null) return null; if (o instanceof Class) { _MethodCache cache = callOpt_getCache((Class) o); List<Method> methods = cache.cache.get(method); if (methods != null) for (Method m : methods) if (isStaticMethod(m) && findMethod_checkArgs(m, args, false)) return m; return null; } else { _MethodCache cache = callOpt_getCache(o.getClass()); List<Method> methods = cache.cache.get(method); if (methods != null) for (Method m : methods) if (findMethod_checkArgs(m, args, false)) return m; return null; } } catch (Exception __e) { throw rethrow(__e); } } static String quote(Object o) { if (o == null) return "null"; return quote(str(o)); } static String quote(String s) { if (s == null) return "null"; StringBuilder out = new StringBuilder((int) (l(s)*1.5+2)); quote_impl(s, out); return out.toString(); } static void quote_impl(String s, StringBuilder out) { out.append('"'); int l = s.length(); for (int i = 0; i < l; i++) { char c = s.charAt(i); if (c == '\\' || c == '"') out.append('\\').append(c); else if (c == '\r') out.append("\\r"); else if (c == '\n') out.append("\\n"); else if (c == '\t') out.append("\\t"); else if (c == '\0') out.append("\\0"); else out.append(c); } out.append('"'); } static IMeta toIMeta(Object o) { if (o == null) return null; if (o instanceof IMeta) return ((IMeta) o); if (o instanceof JComponent) return initMetaOfJComponent((JComponent) o); if (o instanceof BufferedImage) return optCast(IMeta.class, ((BufferedImage) o).getProperty("meta")); return null; } static Map makeObjectMetaMap() { //ret synchroLinkedHashMap(); return new CompactHashMap(); } static IAutoCloseableF0 tempMetaMutex(IMeta o) { return o == null ? null : o._tempMetaMutex(); } static <A, B> void syncMapPut2(Map<A, B> map, A key, B value) { if (map != null && key != null) synchronized(collectionMutex(map)) { if (value != null) map.put(key, value); else map.remove(key); } } // TODO: handle null values static String replaceDollarVars_js(String s, Object... __) { //ret replaceDollarVars_withCustomToString(s, o -> jsonEncode_extended(o), _); Map<String, Object> vars = paramsToMap_withNulls(__); if (empty(vars)) return s; var vars2 = mapKeys(__47 -> dropDollarPrefix(__47), vars); return replaceDollarVars_dyn(s, var -> { if (!vars2.containsKey(var)) return null; Object value = vars2.get(var); return jsonEncode_extended(value); }); } static <A> Set<A> createOrAddToSet(Set<A> set, A a) { if (set == null) set = new HashSet(); set.add(a); return set; } static <A> Set<A> createOrAddToSet(Set<A> set, A... l) { for (A a : unnullForIteration(l)) set = createOrAddToSet(set, a); return set; } static String dropNumberPrefix(String s) { return dropFirst(s, indexOfNonDigit(s)); } static String loadLocalSnippet(String snippetID) { return loadLocalSnippet(psI(snippetID)); } static String loadLocalSnippet(long snippetID) { return loadTextFile(localSnippetFile(snippetID)); } static String md5(String text) { try { if (text == null) return "-"; return bytesToHex(md5_impl(toUtf8(text))); // maybe different than the way PHP does it... } catch (Exception __e) { throw rethrow(__e); } } static String md5(byte[] data) { if (data == null) return "-"; return bytesToHex(md5_impl(data)); } static byte[] md5_impl(byte[] data) { try { return MessageDigest.getInstance("MD5").digest(data); } catch (Exception __e) { throw rethrow(__e); } } static String md5(File file) { return md5OfFile(file); } static File getGlobalCache() { File file = new File(javaxCachesDir(), "Binary Snippets"); file.mkdirs(); return file; } static String dropTranslators(String src) { return findTranslators2(src, null); } // modifies original tok static List<String> dropTranslators(List<String> tok) { return findTranslators2(tok, null); } static String uniqueFileNameUsingMD5_80_v2(String fullName) { return uniqueFileNameUsingMD5_80_v2(fullName, md5(fullName)); } static String uniqueFileNameUsingMD5_80_v2(String fullName, String md5) { return takeFirst(80-33, fileNameEncode(fullName)) + " - " + md5; } static <A> AutoCloseable tempLoadingAnim(String msg) { return tempDisposeWindow(loadingAnim(msg)); } static <A> A callMain(A c, String... args) { callOpt(c, "main", new Object[] {args}); return c; } static void callMain() { callMain(mc()); } static Object makeDependent_postProcess; static void makeDependent(Object c) { if (c == null) return; assertTrue("Not a class", c instanceof Class); dependentClasses(); // cleans up the list hotwire_classes.add(new WeakReference(c)); Object local_log = getOpt(mc(), "local_log"); if (local_log != null) setOpt(c, "local_log", local_log); /*if (isTrue(getOpt(c, 'ping_actions_shareable))) setOpt(c, +ping_actions);*/ Object print_byThread = getOpt(mc(), "print_byThread"); if (print_byThread != null) setOpt(c, "print_byThread", print_byThread); callF(makeDependent_postProcess, c); } static Class<?> hotwireSharingLibraries_silently(String progID) { AutoCloseable __1 = temp_loadPage_silent(); try { return hotwireSharingLibraries(progID); } finally { _close(__1); }} // line starts at 1 static void printLineWithContext(String text, int line) { print(); List<String> lines = lines(text); for (int i = max(1, line-5); i <= min(l(lines), line+5); i++) print((i == line ? "* " : " ") + "LINE " + i + ": " + lines.get(i-1)); print(); } static ThreadLocal<Long> saveTiming_last = new ThreadLocal(); static void saveTiming(long ms) { print(ms + " ms"); saveTiming_noPrint(ms); } static void saveTiming_noPrint(long ms) { saveTiming_last.set(ms); } static ThreadLocal<Long> saveTiming_tl() { return saveTiming_last; } static <A> boolean setAdd(Collection<A> c, A a) { if (c == null || c.contains(a)) return false; c.add(a); return true; } static void clearTokens(List<String> tok) { clearAllTokens(tok); } static void clearTokens(List<String> tok, int i, int j) { clearAllTokens(tok, i, j); } static String postPageWithCredentials(String url, Object... params) { return doPost(mapPlus(standardCredentialsMap(), params), url); } static Matcher regexp(String pat, String s) { return regexp(compileRegexp(pat), unnull(s)); } static Matcher regexp(java.util.regex.Pattern pat, String s) { return pat.matcher(unnull(s)); } static java.util.regex.Pattern regexp(String pat) { return compileRegexp(pat); } static String addParamToURL(String url, Map params) { return appendQueryToURL(url, params); } static String addParamToURL(String url, Object... data) { return appendQueryToURL(url, data); } // custom mainClass only works with hotwire_here static Class<?> hotwire(String src) { return hotwire(src, __1 -> mainClassNameForClassLoader(__1)); } static Class<?> hotwire(String src, IF1<ClassLoader, String> calculateMainClass) { assertFalse(_inCore()); Class j = getJavaX(); if (isAndroid()) { synchronized(j) { // hopefully this goes well... List<File> libraries = new ArrayList<File>(); File srcDir = (File) call(j, "transpileMain", src, libraries); if (srcDir == null) throw fail("transpileMain returned null (src=" + quote(src) + ")"); Object androidContext = get(j, "androidContext"); return (Class) call(j, "loadx2android", srcDir, src); } } else { Class c = (Class) (call(j, "hotwire", src)); hotwire_copyOver(c); return c; } } static void addToContainer(Container a, Component... b) { if (a == null) return; { swing(() -> { for (Component c : unnullForIteration(b)) if (c != null) a.add(c); }); } } static int incAtomicInt(AtomicInteger i) { return i.incrementAndGet(); } static int incAtomicInt(AtomicInteger i, int delta) { return i.addAndGet(delta); } static long incAtomicLong(AtomicLong l) { return l.incrementAndGet(); } static String intToHex(int i) { return bytesToHex(intToBytes(i)); } static <A, B> int lKeys(MultiMap<A, B> mm) { return mm == null ? 0 : mm.keysSize(); } static File loadBinarySnippet(String snippetID) { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.loadLibrary(snippetID); return loadBinarySnippet_noResourceLoader(snippetID); } static File loadBinarySnippet_noResourceLoader(String snippetID) { try { long id = parseSnippetID(snippetID); if (isImageServerSnippet(id)) return loadImageAsFile(snippetID); File f = DiskSnippetCache_getLibrary(id); if (fileSize(f) == 0) f = loadDataSnippetToFile_noResourceLoader(snippetID); return f; } catch (Exception __e) { throw rethrow(__e); } } static int latestInstalledJavaX() { File[] files = new File(userHome(), ".javax").listFiles(); int v = 0; if (files != null) for (File f : files) { Matcher m = regexpMatcher("x(\\d\\d\\d?)\\.jar", f.getName()); if (m.matches()) v = Math.max(v, Integer.parseInt(m.group(1))); } return v; } static String x30JarServerURL() { return "http://botcompany.de:8081/x30.jar"; } static ThreadLocal<Map<String, List<String>>> loadBinaryPage_responseHeaders = new ThreadLocal(); static ThreadLocal<Map<String, String>> loadBinaryPage_extraHeaders = new ThreadLocal(); static byte[] loadBinaryPage(String url) { try { print("Loading " + url); return loadBinaryPage(loadPage_openConnection(new URL(url))); } catch (Exception __e) { throw rethrow(__e); } } static byte[] loadBinaryPage(URLConnection con) { try { Map<String, String> extraHeaders = getAndClearThreadLocal(loadBinaryPage_extraHeaders); setHeaders(con); for (String key : keys(extraHeaders)) con.setRequestProperty(key, extraHeaders.get(key)); return loadBinaryPage_noHeaders(con); } catch (Exception __e) { throw rethrow(__e); } } static byte[] loadBinaryPage_noHeaders(URLConnection con) { try { ByteArrayOutputStream buf = new ByteArrayOutputStream(); InputStream inputStream = con.getInputStream(); loadBinaryPage_responseHeaders.set(con.getHeaderFields()); long len = 0; try { len = con.getContentLength/*Long*/(); } catch (Throwable e) { printStackTrace(e); } int n = 0; while (true) { int ch = inputStream.read(); if (ch < 0) break; buf.write(ch); if (++n % 100000 == 0) println(" " + n + (len != 0 ? "/" + len : "") + " bytes loaded."); } inputStream.close(); return buf.toByteArray(); } catch (Exception __e) { throw rethrow(__e); } } /** writes safely (to temp file, then rename) */ public static byte[] saveBinaryFile(String fileName, byte[] contents) { try { File file = new File(fileName); File parentFile = file.getParentFile(); if (parentFile != null) parentFile.mkdirs(); String tempFileName = fileName + "_temp"; FileOutputStream fileOutputStream = newFileOutputStream(tempFileName); fileOutputStream.write(contents); fileOutputStream.close(); if (file.exists() && !file.delete()) throw new IOException("Can't delete " + fileName); if (!new File(tempFileName).renameTo(file)) throw new IOException("Can't rename " + tempFileName + " to " + fileName); vmBus_send("wroteFile", file); return contents; } catch (Exception __e) { throw rethrow(__e); } } static byte[] saveBinaryFile(File fileName, byte[] contents) { return saveBinaryFile(fileName.getPath(), contents); } // This is a bit rough... finds static and non-static methods. static Method findMethodNamed(Object obj, String method) { if (obj == null) return null; if (obj instanceof Class) return findMethodNamed((Class) obj, method); return findMethodNamed(obj.getClass(), method); } static Method findMethodNamed(Class c, String method) { while (c != null) { for (Method m : c.getDeclaredMethods()) if (m.getName().equals(method)) { makeAccessible(m); return m; } c = c.getSuperclass(); } return null; } static int hashMap_internalHash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } static String shortenClassName(String name) { if (name == null) return null; int i = lastIndexOf(name, "$"); if (i < 0) i = lastIndexOf(name, "."); return i < 0 ? name : substring(name, i+1); } static <A, B> boolean eitherIsA(Either<A, B> e) { return e != null && e.isA(); } static void raiseFlagAndDo(Flag flag, Runnable r) { if (flag.raise()) callF(r); } static void _handleException_addHandler(Object handler) { addIfNotThere(_handleException_onException, handler); } static void _handleException_addHandler(IVF1<Throwable> handler) { _handleException_addHandler((Object) handler); } static <A> A assertNull(A a) { assertTrue(a == null); return a; } static <A> A assertNull(String msg, A a) { assertTrue(msg, a == null); return a; } static JInternalFrame getInternalFrame(final Object _o) { return _o == null ? null : swing(new F0<JInternalFrame>() { public JInternalFrame get() { try { Object o = _o; if (o instanceof ButtonGroup) o = first(buttonsInGroup((ButtonGroup) o)); if (!(o instanceof Component)) return null; Component c = (Component) o; while (c != null) { if (c instanceof JInternalFrame) return (JInternalFrame) c; c = c.getParent(); } return null; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "O o = _o;\r\n if (o instanceof ButtonGroup) o = first(buttonsInGroup((Button..."; }}); } static <A extends Component> A internalFrameTitle(A c, final String title) { final JInternalFrame f = getInternalFrame(c); if (f != null) { swing(() -> { f.setTitle(unnull(title)); toolTip(getInternalFrameTitlePaneComponent(f), title); }); } return c; } static <A extends Component> A internalFrameTitle(String title, A c) { return internalFrameTitle(c, title); } static String internalFrameTitle(Component c) { final JInternalFrame f = getInternalFrame(c); return f == null ? null : swing(new F0<String>() { public String get() { try { return f.getTitle(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return f.getTitle();"; }}); } static <A extends Component> A frameTitle(A c, String title) { return setFrameTitle(c, title); } static <A extends Component> A frameTitle(String title, A c) { return setFrameTitle(c, title); } static String frameTitle(Component c) { return getFrameTitle(c); } static JFrame getFrame(final Object _o) { return swing(new F0<JFrame>() { public JFrame get() { try { Object o = _o; if (o instanceof ButtonGroup) o = first(buttonsInGroup((ButtonGroup) o)); if (!(o instanceof Component)) return null; Component c = (Component) o; while (c != null) { if (c instanceof JFrame) return (JFrame) c; c = c.getParent(); } return null; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "O o = _o;\r\n if (o instanceof ButtonGroup) o = first(buttonsInGroup((Button..."; }}); } static Set<AutoCloseable> _registerAutoCloseable_set = synchroHashSet(); static void _registerAutoCloseable(AutoCloseable c) { addIfNotNull(_registerAutoCloseable_set, c); } static void cleanMeUp__registerAutoCloseable() { closeAutoCloseables(getAndClearList(_registerAutoCloseable_set)); } static void cancelTimer(javax.swing.Timer timer) { if (timer != null) timer.stop(); } static void cancelTimer(java.util.Timer timer) { if (timer != null) timer.cancel(); } static void cancelTimer(Object o) { if (o instanceof java.util.Timer) cancelTimer((java.util.Timer) o); else if (o instanceof javax.swing.Timer) cancelTimer((javax.swing.Timer) o); else if (o instanceof AutoCloseable) { try { ((AutoCloseable) o).close(); } catch (Throwable __e) { printStackTrace(__e); }} } static Object pcallFunction(Object f, Object... args) { try { return callFunction(f, args); } catch (Throwable __e) { printStackTrace(__e); } return null; } static boolean isTransientField(Object object, String name) { Field f = getField(object, name); return f != null && (f.getModifiers() & Modifier.TRANSIENT) != 0; } static <A> A shallowCloneToClass(Class<A> c, Object o) { if (o == null) return null; A a = nuInstance(c); copyFields(o, a); return a; } static Object dm_getStem(Object moduleOrID) { if (isString(moduleOrID) && isIdentifier(((String) moduleOrID))) moduleOrID = dm_getService(((String) moduleOrID)); if (isStringOrIntOrLong(moduleOrID)) return dm_getStemByID(moduleOrID); return or(getOpt(dm_getModule(moduleOrID), "_host"), moduleOrID); } static Method findMethod_precise_onTypes(Object o, String method, Class... argTypes) { try { if (o instanceof Class) { _MethodCache cache = callOpt_getCache((Class) o); List<Method> methods = cache.cache.get(method); Lowest<Method> best = new Lowest(); if (methods != null) for (Method m : methods) { { if (!(isStaticMethod(m))) continue; } int score = methodApplicabilityScore_onTypes(m, argTypes); if (score < Integer.MAX_VALUE) best.put(m, score); } return best.get(); } if (o == null) return null; _MethodCache cache = callOpt_getCache(o.getClass()); List<Method> methods = cache.cache.get(method); Lowest<Method> best = new Lowest(); if (methods != null) for (Method m : methods) { int score = methodApplicabilityScore_onTypes(m, argTypes); if (score < Integer.MAX_VALUE) best.put(m, score); } return best.get(); } catch (Exception __e) { throw rethrow(__e); } } static void dm_onTopInput(final VF1<String> r) { final DynModule m = dm_current_mandatory(); dm_ownResource(vmBus_onMessage("topInput", new VF1<String>() { public void get(final String s) { try { m.enter(); callF(r, s) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "m.enter();\r\n callF(r, s)"; }})); } static void dm_onTopInput(final Runnable r) { final DynModule m = dm_current_mandatory(); dm_ownResource(vmBus_onMessage("topInput", new VF1<String>() { public void get(final String s) { try { m.enter(); callF(r) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "m.enter();\r\n callF(r)"; }})); } static void pClose(AutoCloseable c) { close_pcall(c); } static <A, B> A foldl(F2<A, B, A> f, A seed, Iterable<B> l) { A a = seed; if (l != null) for(B b : l) a = callF(f, a, b); return a; } static <A, B> A foldl(F2<A, B, A> f, A seed, B[] l) { A a = seed; if (l != null) for(B b : l) a = callF(f, a, b); return a; } static <A, B> A foldl(Object f, A seed, B[] l) { A a = seed; if (l != null) for(B b : l) a = (A) callF(f, a, b); return a; } static ChangeListener changeListener(final Object r) { return new ChangeListener() { public void stateChanged(ChangeEvent e) { pcallF(r); } }; } static ItemListener itemListener(final Object r) { return new ItemListener() { public void itemStateChanged(ItemEvent e) { pcallF(r); } }; } static void addActionListener(JTextField tf, final Runnable action) { onEnter(tf, action); } static void addActionListener(final JComboBox cb, final Runnable action) { if (cb != null) { swing(() -> { cb.addActionListener(actionListener(action)); }); } } static void addActionListener(final AbstractButton b, final Runnable action) { if (b != null) { swing(() -> { b.addActionListener(actionListener(action)); }); } } static <A> A getSelectedItem_typed(JList<A> l) { return swing(() -> l.getSelectedValue()); } static <A> A getSelectedItem_typed(JComboBox<A> cb) { return swing(() -> (A) cb.getSelectedItem()); } static boolean isEditableComboBox(final JComboBox cb) { return cb != null && swing(new F0<Boolean>() { public Boolean get() { try { return cb.isEditable(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return cb.isEditable();"; }}); } static JTextField textFieldFromComboBox(JComboBox cb) { return (JTextField) cb.getEditor().getEditorComponent(); } static JComboBox onSelectedItem(final JComboBox cb, final VF1<String> f) { addActionListener(cb, new Runnable() { public void run() { try { pcallF(f, selectedItem(cb)) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pcallF(f, selectedItem(cb))"; }}); return cb; } static JComboBox onSelectedItem(final JComboBox cb, IVF1<String> f) { addActionListener(cb, new Runnable() { public void run() { try { pcallF(f, selectedItem(cb)) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pcallF(f, selectedItem(cb))"; }}); return cb; } static Set asSet(Object[] array) { HashSet set = new HashSet(); for (Object o : array) if (o != null) set.add(o); return set; } static Set<String> asSet(String[] array) { TreeSet<String> set = new TreeSet(); for (String o : array) if (o != null) set.add(o); return set; } static <A> Set<A> asSet(Iterable<A> l) { if (l instanceof Set) return (Set) l; HashSet<A> set = new HashSet(); for (A o : unnull(l)) if (o != null) set.add(o); return set; } // not a very good one static boolean instanceOf(Object o, String className) { if (o == null) return false; String c = o.getClass().getName(); return eq(c, className) || eq(c, "main$" + className); } // better static boolean instanceOf(Object o, Class c) { if (c == null) return false; return c.isInstance(o); } static boolean instanceOf(Class c, Object o) { return instanceOf(o, c); } static AbstractAction abstractAction(String name, final Object runnable) { return new AbstractAction(name) { public void actionPerformed(ActionEvent evt) { pcallF(runnable); } }; } static void internalFramePopupMenuItem(Container f, final String name, final Object action) { internalFrameTitlePopupMenuItem(((JInternalFrame) f), name, action); } static Runnable runnableThread(final Runnable r) { return new Runnable() { public void run() { try { startThread(r) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "startThread(r)"; }}; } static void callAction(Action a) { if (a != null) a.actionPerformed(null); } static <A, B> Map<A, B> weakHashMap() { return newWeakHashMap(); } static Set emptySet() { return new HashSet(); } static <A> TreeSet<A> asTreeSet(Collection<A> set) { return set == null ? null : set instanceof TreeSet ? (TreeSet) set : new TreeSet(set); } static Field getField(Object o, String field) { if (o == null) return null; return setOpt_findField(_getClass(o), field); } static Object getField(Field field, Object o) { return fieldGet(field, o); } static Map<String, String> humanizeFormLabel_replacements = litmap("id" , "ID", "md5" , "MD5"); static String humanizeFormLabel(String s) { if (containsSpace(s)) return s; return firstToUpper( joinWithSpace(replaceElementsUsingMap(splitCamelCase(s), humanizeFormLabel_replacements)).replace("I D", "ID") ); } // menuMaker = voidfunc(JPopupMenu) static void internalFrameTitlePopupMenu(final JInternalFrame f, final Object... params) { { swing(() -> { Object menuMaker; if (l(params) == 1 && !(params[0] instanceof JMenu)) menuMaker = params[0]; else menuMaker = new VF1<JPopupMenu>() { public void get(JPopupMenu menu) { try { addMenuItems(menu, params) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addMenuItems(menu, params)"; }}; Component titleComponent = getInternalFrameTitlePaneComponent(f); if (!(titleComponent instanceof JComponent)) print("Can't add internal frame title popup menu!"); else { componentPopupMenu((JComponent) titleComponent, menuMaker); setOpt(componentPopupMenu_initForComponent((JComponent) titleComponent), "internalFrameLeftButtonMagic" , isTrue(vm_generalMap_get("internalFramePopupOnLeftButton"))); } // Also add to the frame so we can show the items e.g. in a JFrame menu componentPopupMenu(f, menuMaker); }); } } // r : runnable or voidfunc(bool) static JCheckBoxMenuItem jCheckBoxMenuItem(String text, boolean checked, final Object r) { final JCheckBoxMenuItem mi = swing(() -> new JCheckBoxMenuItem(text, checked)); addActionListener(mi, new Runnable() { public void run() { try { callF(r, isChecked(mi)) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(r, isChecked(mi))"; }}); return mi; } static JCheckBoxMenuItem jCheckBoxMenuItem(String text, boolean checked, IVF1<Boolean> r) { return jCheckBoxMenuItem(text, checked, (Object) r); } static JTextField jtextfield() { return jTextField(); } static JTextField jtextfield(String text) { return jTextField(text); } static JTextField jtextfield(Object o) { return jTextField(o); } static int showForm_defaultGap = 4; static int showForm_gapBetweenColumns = 10; static JPanel showFormTitled(final String title, final Object... _parts) { JDesktopPane desktop = mainDesktopPane(); if (desktop != null) return showInternalFrameFormTitled(desktop, title, _parts); return swing(new F0<JPanel>() { public JPanel get() { try { final Var<JFrame> frame = new Var(); JPanel panel = showForm_makePanel(false, _parts); showForm_makeFrame(title, panel); frame.set(getFrame(panel)); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final new Var<JFrame> frame;\r\n JPanel panel = showForm_makePanel(false, _p..."; }}); } static JPanel showForm_makePanel(Boolean internalFrame, Object... _parts) { List<JComponent> out = showForm_arrange1(showForm_makeComponents(internalFrame, _parts)); return vstackWithSpacing(out, showForm_defaultGap); } static String stringOptPar(Object[] params, String name) { return (String) optPar(params, name); } static String gtt(JTextComponent c) { return getTextTrim(c); } static String gtt(JComboBox cb) { return getTextTrim(cb); } static void dm_doubleFieldSetterDialog(String field, Object... __) { final DynModule m = dm_current_mandatory(); final String humanized = humanizeFormLabel(field); final JTextField tf = jtextfield(get(m, field)); showFormTitled(or2(stringOptPar(__, "formTitle"), "Set " + humanized), humanized + ":", tf, new Runnable() { public void run() { try { m.setField(field, parseDouble(gtt(tf))); callF(optPar(__, "onSet")); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "m.setField(field, parseDouble(gtt(tf)));\r\n callF(optPar(__, \"onSet\"));"; }}); } static void dm_floatFieldSetterDialog(String field, Object... __) { DynModule m = dm_current_mandatory(); String humanized = humanizeFormLabel(field); JTextField tf = jtextfield(get(m, field)); showFormTitled(or2(stringOptPar(__, "formTitle"), "Set " + humanized), humanized + ":", tf, new Runnable() { public void run() { try { m.setField(field, parseFloat(gtt(tf))); callF(optPar(__, "onSet")); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "m.setField(field, parseFloat(gtt(tf)));\r\n callF(optPar(__, \"onSet\"));"; }}); } static void dm_stringFieldDialog(final String field, final Object... __) { final DynModule m = dm_current_mandatory(); final String humanized = humanizeFormLabel(field); final JTextField tf = jtextfield(get(m, field)); showFormTitled(or2(stringOptPar(__, "formTitle"), "Set " + humanized), humanized + ":", tf, new Runnable() { public void run() { try { m.setField(field, gtt(tf)); callF(optPar(__, "onSet")); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "m.setField(field, gtt(tf));\r\n callF(optPar(__, \"onSet\"));"; }}); } static void dm_fileFieldDialog(final String field, final Object... __) { DynModule m = dm_current_mandatory(); String humanized = humanizeFormLabel(field); JTextField tf = jtextfield(strOrNull(get(m, field))); showFormTitled(or2(stringOptPar(__, "formTitle"), "Set " + humanized), humanized + ":", tf, new Runnable() { public void run() { try { m.setField(field, toFile_nullOnEmpty(gtt(tf))); callF(optPar(__, "onSet")); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "m.setField(field, toFile_nullOnEmpty(gtt(tf)));\r\n callF(optPar(__, \"onSe..."; }}); } static F0<AutoCloseable> dm_rEnter() { return dm_rEnter(dm_current()); } static F0<AutoCloseable> dm_rEnter(DynModule mod) { return mod == null ? null : new F0<AutoCloseable>() { public AutoCloseable get() { try { return mod.enter(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return mod.enter();"; }}; } static Runnable dm_rEnter(Runnable r) { return dm_rEnter(dm_current(), r); } static Runnable dm_rEnter(DynModule mod, Runnable r) { return mod == null || r == null ? r : new Runnable() { public void run() { try { AutoCloseable __1 = mod.enter(); try { r.run(); } finally { _close(__1); }} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp mod.enter(); r.run();"; }}; } static Q dm_ownQ(Q q) { q.rst.enter = dm_rEnter(dm_current_mandatory()); dm_ownResource(q); return q; } static Q startQ() { return new Q(); } static Q startQ(String name) { return new Q(name); } static <A extends JComponent> A setToolTip(A c, Object toolTip) { return setToolTipText(c, toolTip); } static <A extends JComponent> A setToolTip(Object toolTip, A c) { return setToolTipText(c, toolTip); } static void setToolTip(TrayIcon trayIcon, String toolTip) { setTrayIconToolTip(trayIcon, toolTip); } static JLabel jimage(Image img) { return jImageLabel(img); } static JLabel jimage(String imageID) { return jImageLabel(imageID); } static String getSnippetTitle(String id) { if (id == null) return null; if (!isSnippetID(id)) return "?"; IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.getSnippetTitle(id); return getSnippetTitle_noResourceLoader(id); } static String getSnippetTitle_noResourceLoader(String id) { try { if (isLocalSnippetID(id)) return localSnippetTitle(id); long parsedID = parseSnippetID(id); String url; if (isImageServerSnippet(parsedID)) url = imageServerURL() + "title/" + parsedID + muricaCredentialsQuery(); else if (isGeneralFileServerSnippet(parsedID)) url = "http://butter.botcompany.de:8080/files/name/" + parsedID; else url = tb_mainServer() + "/tb-int/getfield.php?id=" + parsedID + "&field=title" + standardCredentials_noCookies(); String title = trim(loadPageSilently(url)); if (title != null) try { saveTextFileIfChanged(snippetTitle_cacheFile(id), title); } catch (Throwable __e) { print(exceptionToStringShort(__e)); } return or(title, "?"); } catch (Exception __e) { throw rethrow(__e); } } static String getSnippetTitle(long id) { return getSnippetTitle(fsI(id)); } static <A> Set<A> newWeakHashSet() { return synchroWeakHashSet(); } static void cancelTimers(Collection timers) { for (Object timer : timers) cancelTimer(timer); } static String joinNempties(String sep, Object... strings) { return joinStrings(sep, strings); } static String joinNempties(String sep, Iterable strings) { return joinStrings(sep, strings); } static String joinNemptiesWithComma(Object... strings) { return joinNempties(", ", strings); } static String joinNemptiesWithComma(Iterable strings) { return joinNempties(", ", strings); } static List flattenCollectionsAndArrays(Iterable a) { List l = new ArrayList(); for (Object x : a) if (x instanceof Collection) l.addAll(flattenCollectionsAndArrays((Collection) x)); else if (x instanceof Object[]) l.addAll(flattenCollectionsAndArrays(asList((Object[]) x))); else l.add(x); return l; } static JPanel jpanel(LayoutManager layout) { return swingNu(JPanel.class, layout); } static JPanel jpanel() { return swingNu(JPanel.class); } static class jLiveValueSection_class extends SingleComponentPanel { LiveValue<?> liveValue; String getTitle() { return strOrEmpty(liveValue.get()); } jLiveValueSection_class(LiveValue<?> lv, Component c) { super(c); bindLiveValueListenerToComponent(this, liveValue = lv, new Runnable() { public void run() { try { swingLater(new Runnable() { public void run() { try { setBorder(BorderFactory.createTitledBorder( BorderFactory.createBevelBorder(BevelBorder.LOWERED), getTitle())); revalidate(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "setBorder(BorderFactory.createTitledBorder(\r\n BorderFactory.createBeve..."; }}); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "swingLater(r {\r\n setBorder(BorderFactory.createTitledBorder(\r\n Bo..."; }}); } } static JPanel jLiveValueSection(LiveValue<?> lv, Component c) { return swingNu(jLiveValueSection_class.class, lv, c); } static JScrollPane setScrollPaneBackground(Color c, JScrollPane sp) { if (sp != null && c != null) { swing(() -> { sp.getViewport().setBackground(c); }); } return sp; } static JScrollPane jscroll(final Component c) { return swing(new F0<JScrollPane>() { public JScrollPane get() { try { return new JScrollPane(c); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return new JScrollPane(c);"; }}); } static <A extends JComponent> A withTypeWriterFont(A c) { return setFont(c, typeWriterFont()); } static <A> A swingNu(final Class<A> c, final Object... args) { return swingConstruct(c, args); } static ThreadLocal<MouseEvent> componentPopupMenu_mouseEvent; static void componentPopupMenu_init() { { swing(() -> { if (componentPopupMenu_mouseEvent == null) componentPopupMenu_mouseEvent = (ThreadLocal<MouseEvent>) vm_generalMap_get("mouseEvent"); if (componentPopupMenu_mouseEvent == null) vm_generalMap_put("componentPopupMenu_mouseEvent" , componentPopupMenu_mouseEvent = new ThreadLocal()); }); } } // menuMaker = voidfunc(JPopupMenu) static void componentPopupMenu(final JComponent component, final Object menuMaker) { if (component == null || menuMaker == null) return; { swing(() -> { Object adapter = componentPopupMenu_initForComponent(component); ((List) _get(adapter, "maker")).add(menuMaker); }); } } static Object componentPopupMenu_initForComponent(final JComponent component) { return component == null ? null : swing(new F0<Object>() { public Object get() { try { componentPopupMenu_init(); Object adapter = findComponentPopupMenuListener_gen(component); if (adapter == null) { componentPopupMenu_Adapter a = new componentPopupMenu_Adapter(); //addMouseListener_inFront(component, a); component.addMouseListener(a); adapter = a; } return adapter; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "componentPopupMenu_init();\r\n O adapter = findComponentPopupMenuListener_ge..."; }}); } static class componentPopupMenu_Adapter extends MouseAdapter { List maker = new ArrayList(); boolean internalFrameLeftButtonMagic = false; boolean allowScrolling = true; Point pressedAt; public void mousePressed(MouseEvent e) { displayMenu(e); pressedAt = internalFrameLeftButtonMagic && e.getClickCount() == 1 && internalFrameActive(e.getComponent()) ? e.getLocationOnScreen() : null; } public void mouseReleased(MouseEvent e) { // TODO: show a little less often on left mouse click if (internalFrameLeftButtonMagic && eq(pressedAt, e.getLocationOnScreen())) displayMenu2(e); else displayMenu(e); } void displayMenu(MouseEvent e) { if (e.getSource() instanceof JInternalFrame) return; if (e.isPopupTrigger()) displayMenu2(e); } void populate(JPopupMenu menu, MouseEvent e) { AutoCloseable __1 = tempSetTL(componentPopupMenu_mouseEvent, e); try { for (Object menuMaker : maker) pcallF(menuMaker, menu); vmBus_send("showingPopupMenu", e.getComponent(), menu); } finally { _close(__1); }} void displayMenu2(MouseEvent e) { new PopupMenuMaker(e, menu -> populate(menu, e)) .allowScrolling(allowScrolling).run(); } } static void addMenuItem(JPopupMenu menu, String text, Object action) { menu.add(jmenuItem(text, action)); } static void addMenuItem(JPopupMenu menu, JMenuItem menuItem) { if (menu != null && menuItem != null) menu.add(menuItem); } static void addMenuItem(JMenu menu, String text, Object action) { menu.add(jmenuItem(text, action)); } static void addMenuItem(Menu menu, String text, Object action) { menu.add(menuItem(text, action)); } static void addMenuItem(JMenu menu, JMenuItem menuItem) { menu.add(menuItem); } static void addMenuItem(JMenuBar menuBar, String text, Runnable action) { addMenuItem(menuBar, jmenuItem(text, action)); } static void addMenuItem(JMenuBar menuBar, JMenuItem menuItem) { addDirectMenuItem(menuBar, menuItem); } static void clearStringBuffer_gen(Object buf) { if (buf != null) { call(buf, "setLength", 0); call(buf, "trimToSize"); } } static void swingEvery(JComponent component, long delay, Object r) { installTimer(component, delay, r); } static void swingEvery(JComponent component, long delay, long firstDelay, Object r) { installTimer(component, r, delay, firstDelay); } static void swingEvery(RootPaneContainer frame, long delay, Object r) { installTimer(frame, delay, r); } static void swingEvery(RootPaneContainer frame, long delay, long firstDelay, Object r) { installTimer(frame, delay, firstDelay, r); } static void swingAndWait(Runnable r) { try { if (isAWTThread()) r.run(); else EventQueue.invokeAndWait(addThreadInfoToRunnable(r)); } catch (Exception __e) { throw rethrow(__e); } } static Object swingAndWait(final Object f) { if (isAWTThread()) return callF(f); else { final Var result = new Var(); swingAndWait(new Runnable() { public void run() { try { result.set(callF(f)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "result.set(callF(f));"; }}); return result.get(); } } static void swingLater(long delay, final Object r) { javax.swing.Timer timer = new javax.swing.Timer(toInt(delay), actionListener(wrapAsActivity(r))); timer.setRepeats(false); timer.start(); } static void swingLater(Object r) { SwingUtilities.invokeLater(toRunnable(r)); } // first delay = delay static Timer installTimer(JComponent component, Object r, long delay) { return installTimer(component, r, delay, delay); } // first delay = delay static Timer installTimer(RootPaneContainer frame, long delay, Object r) { return installTimer(frame.getRootPane(), r, delay, delay); } // first delay = delay static Timer installTimer(JComponent component, long delay, Object r) { return installTimer(component, r, delay, delay); } static Timer installTimer(JComponent component, long delay, long firstDelay, Object r) { return installTimer(component, r, delay, firstDelay); } static Timer installTimer(final JComponent component, final Object r, final long delay, final long firstDelay) { return installTimer(component, r, delay, firstDelay, true); } static Timer installTimer(final JComponent component, final Object r, final long delay, final long firstDelay, final boolean repeats) { if (component == null) return null; return (Timer) swingAndWait(new F0<Object>() { public Object get() { try { final Var<Timer> timer = new Var(); timer.set(new Timer(toInt(delay), new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent _evt) { try { AutoCloseable __1 = tempActivity(r); try { try { if (!allPaused()) if (isFalse(callF(r))) cancelTimer(timer.get()); } catch (Throwable __e) { printStackTrace(__e); } } finally { _close(__1); }} catch (Throwable __e) { messageBox(__e); }}})); timer.get().setInitialDelay(toInt(firstDelay)); timer.get().setRepeats(repeats); bindTimerToComponent(timer.get(), component); return timer.get(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final new Var<Timer> timer;\r\n timer.set(new Timer(toInt(delay), actionList..."; }}); } static Timer installTimer(RootPaneContainer frame, long delay, long firstDelay, Object r) { return installTimer(frame.getRootPane(), delay, firstDelay, r); } static StringBuffer liveLocalPrintLog() { return local_log; } static Complex complex(double re, double im) { return new Complex(re, im); } static Complex complex(double re) { return new Complex(re, 0.0); } static Complex complex(double[] reIm) { if (empty(reIm)) return null; if (l(reIm) != 2) throw fail("Need 2 doubles to make complex number"); return complex(reIm[0], reIm[1]); } static String defaultThreadName_name; static String defaultThreadName() { if (defaultThreadName_name == null) defaultThreadName_name = "A thread by " + programID(); return defaultThreadName_name; } static Runnable wrapAsActivity(Object r) { if (r == null) return null; Runnable r2 = toRunnable(r); Object mod = dm_current_generic(); if (mod == null) return r2; return new Runnable() { public void run() { try { AutoCloseable c = (AutoCloseable) (rcall("enter", mod)); AutoCloseable __1 = c; try { r2.run(); } finally { _close(__1); }} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "AutoCloseable c = (AutoCloseable) (rcall enter(mod));\r\n temp c;\r\n r2.r..."; }}; } // runnable = Runnable or String (method name) static Thread newThread(Object runnable) { return new BetterThread(_topLevelErrorHandling(toRunnable(runnable))); } static Thread newThread(Object runnable, String name) { if (name == null) name = defaultThreadName(); return new BetterThread(_topLevelErrorHandling(toRunnable(runnable)), name); } static Thread newThread(String name, Object runnable) { return newThread(runnable, name); } static <A> List<A> syncCloneAndClearList(Collection<A> l) { if (l == null) return emptyList(); synchronized(collectionMutex(l)) { List<A> l2 = cloneList(l); l.clear(); return l2; } } static void cancelThread(Thread t) { if (t == null) return; ping(); synchronized(ping_actions) { ping_actions.put(t, "cancelled"); ping_anyActions = true; } } static Object swingCall(final Object o, final String method, final Object... args) { return swing(new F0<Object>() { public Object get() { try { return call(o, method, args); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return call(o, method, args);"; }}); } static Font getFont(JComponent c) { return c == null ? null : swing(new F0<Font>() { public Font get() { try { return c.getFont(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return c.getFont();"; }}); } static int toInt_checked(long l) { if (l != (int) l) throw fail("Too large for int: " + l); return (int) l; } static String strUnnull(Object o) { return o == null ? "" : str(o); } static String jlabel_textAsHTML_center_ifNeeded(String text) { if (swic(text, "<html>") && ewic(text, "</html>")) return text; if (!containsNewLines(text)) return text; return jlabel_textAsHTML_center(text); } static <A> List<A> asSynchroList(Iterable<A> l) { return syncList(cloneList(l)); } static <A extends Component> A revalidate(final A c) { if (c == null || !c.isShowing()) return c; { swing(() -> { // magic combo to actually relayout and repaint c.revalidate(); c.repaint(); }); } return c; } static void revalidate(JFrame f) { revalidate((Component) f); } static void revalidate(JInternalFrame f) { revalidate((Component) f); } static String lines_rtrim(Collection lines) { return rtrim_fromLines(lines); } static Map paramsToMap_withNulls(Object... params) { int n = l(params); if (l(params) == 1 && params[0] instanceof Map) return (Map) params[0]; LinkedHashMap map = new LinkedHashMap(); for (int i = 0; i+1 < n; i += 2) map.put(params[i], params[i+1]); return map; } static Map mapKeys(Object func, Map map) { Map m = similarEmptyMap(map); // TODO: this might break when key type changes through func for (Object key : keys(map)) m.put(callF(func, key), map.get(key)); return m; } static Map mapKeys(Map map, Object func) { return mapKeys(func, map); } static <A, B, C> Map<B, C> mapKeys(Map<A, C> map, IF1<A, B> func) { return mapKeys(map, (Object) func); } static <A, B, C> Map<B, C> mapKeys(IF1<A, B> func, Map<A, C> map) { return mapKeys(map, func); } static String dropDollarPrefix(String s) { return dropPrefix("$", s); } // f takes variable without $ sign. if it returns null, variable is kept static String replaceDollarVars_dyn(String s, IF1<String, String> f) { if (f == null) return s; return regexpReplaceIC(s, "\\$(\\w+)", matcher -> { String var = matcher.group(1); String val = f.get(var); return val == null ? matcher.group() : str(val); }); } static String jsonEncode_extended(Object o) { StringBuilder buf = new StringBuilder(); jsonEncode_extended(o, buf); return str(buf); } static void jsonEncode_extended(Object o, StringBuilder buf) { if (o == null) buf.append("null"); else if (o instanceof JS) buf.append(((JS) o).get()); else if (o instanceof String) buf.append(quote((String) o)); else if (o instanceof Number || o instanceof Boolean) buf.append(o); else if (o instanceof Map) { Map map = (Map) o; buf.append("{"); boolean first = true; for (Object key : keys(map)) { if (first) first = false; else buf.append(","); buf.append(quote((String) key)); buf.append(":"); jsonEncode_extended(map.get(key), buf); } buf.append("}"); } else if (o instanceof Collection) { Collection l = (Collection) o; buf.append("["); boolean first = true; for (Object element : l) { if (first) first = false; else buf.append(","); jsonEncode_extended(element, buf); } buf.append("]"); } else throw fail("Unknown object for JSON encoding: " + className(o)); } static String[] dropFirst(int n, String[] a) { return drop(n, a); } static String[] dropFirst(String[] a) { return drop(1, a); } static Object[] dropFirst(Object[] a) { return drop(1, a); } static <A> List<A> dropFirst(List<A> l) { return dropFirst(1, l); } static <A> List<A> dropFirst(int n, Iterable<A> i) { return dropFirst(n, toList(i)); } static <A> List<A> dropFirst(Iterable<A> i) { return dropFirst(toList(i)); } static <A> List<A> dropFirst(int n, List<A> l) { return n <= 0 ? l : new ArrayList(l.subList(Math.min(n, l.size()), l.size())); } static <A> List<A> dropFirst(List<A> l, int n) { return dropFirst(n, l); } static String dropFirst(int n, String s) { return substring(s, n); } static String dropFirst(String s, int n) { return substring(s, n); } static String dropFirst(String s) { return substring(s, 1); } static int indexOfNonDigit(String s) { int n = l(s); for (int i = 0; i < n; i++) if (!isDigit(s.charAt(i))) return i; return -1; } static boolean md5OfFile_verbose = false; static String md5OfFile(String path) { return md5OfFile(newFile(path)); } static String md5OfFile(File f) { try { if (!f.exists()) return "-"; if (md5OfFile_verbose) print("Getting MD5 of " + f); MessageDigest md5 = MessageDigest.getInstance("MD5"); FileInputStream in = new FileInputStream(f); try { byte buf[] = new byte[65536]; int l; while (true) { l = in.read(buf); if (l <= 0) break; md5.update(buf, 0, l); } return bytesToHex(md5.digest()); } finally { _close(in); }} catch (Exception __e) { throw rethrow(__e); } } static File javaxCachesDir_dir; // can be set to work on different base dir static File javaxCachesDir() { return javaxCachesDir_dir != null ? javaxCachesDir_dir : new File(userHome(), "JavaX-Caches"); } static File javaxCachesDir(String sub) { return newFile(javaxCachesDir(), sub); } static String fileNameEncode_safeChars = " "; //" ()[]#"; static String fileNameEncode(String s) { s = dropLeadingDots(s); // don't produce file names starting with a dot! StringBuilder buf = new StringBuilder(); int n = l(s); for (int i = 0; i < n; i++) { char c = s.charAt(i); if (contains(fileNameEncode_safeChars, c)) buf.append(c); else buf.append(urlencode(str(c))); } return str(buf); } static <A> AutoCloseable tempDisposeWindow(final Window w) { return new AutoCloseable() { public void close() { disposeWindow(w); } }; } static JWindow loadingAnim() { return showLoadingAnimation(); } static JWindow loadingAnim(String text) { return showLoadingAnimation(text); } static List<Class> dependentClasses() { return cleanUpAndGetWeakReferencesList(hotwire_classes); } static AutoCloseable temp_loadPage_silent() { return tempSetThreadLocal(loadPage_silent, true); } static Class<?> hotwireSharingLibraries(String progID) { try { Pair<File, String> p = CompilerBot.compileSnippet2(progID); File jar = p.a; assertTrue(f2s(jar), jar.isFile()); // collect files (program + libraries) List<File> files = ll(jar); String dehlibs = unnull(loadTextFileFromZip(jar, "libraries")); List<File> myLibraries = myLibraryFiles(); //print("My libraries: " + myLibraries); Matcher matcher = Pattern.compile("\\d+").matcher(dehlibs); while (matcher.find()) { String libID = matcher.group(); File lib = loadLibrary(libID); if (myLibraries.contains(lib)) { //print("Skipping lib " + lib); } else { //print("Adding lib " + lib); files.add(lib); } } // make class loader JavaXClassLoaderWithParent classLoader = new JavaXClassLoaderWithParent(progID, files, myClassLoader()); return hotwire_finish(classLoader, progID, p.b); } catch (Exception __e) { throw rethrow(__e); } } static void clearAllTokens(List<String> tok) { for (int i = 0; i < tok.size(); i++) tok.set(i, ""); } static void clearAllTokens(List<String> tok, int i, int j) { for (; i < j; i++) tok.set(i, ""); } static ThreadLocal<Boolean> doPost_silently = new ThreadLocal(); static ThreadLocal<Long> doPost_timeout = new ThreadLocal(); static ThreadLocal<Map<String, String>> doPost_extraHeaders = new ThreadLocal(); static String doPost(String url, Map urlParameters) { return doPost(urlParameters, url); } static String doPost(Map urlParameters, String url) { return doPost(makePostData(urlParameters), url); } static String doPost(String urlParameters, String url) { try { URL _url = new URL(url); ping(); return doPost(urlParameters, _url.openConnection(), _url); } catch (Exception __e) { throw rethrow(__e); } } static String doPost(String urlParameters, URLConnection conn, URL url) { try { boolean silently = isTrue(optParam(doPost_silently)); Long timeout = optParam(doPost_timeout); Map<String, String> extraHeaders = optPar(doPost_extraHeaders); setHeaders(conn); for (String key : keys(extraHeaders)) { conn.setRequestProperty(key, extraHeaders.get(key)); } int l = lUtf8(urlParameters); if (!silently) print("Sending POST request: " + hideCredentials(url) + " (" + l + " bytes)"); // connect and do POST if (timeout != null) setURLConnectionTimeouts(conn, timeout); ((HttpURLConnection) conn).setRequestMethod("POST"); conn.setDoOutput(true); conn.setRequestProperty("Content-Length", str(l)); OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), "UTF-8"); writer.write(urlParameters); writer.flush(); String contents = loadPage_utf8(conn, url, false); writer.close(); return contents; } catch (Exception __e) { throw rethrow(__e); } } static Map<String, String> standardCredentialsMap() { String user = standardCredentialsUser(); String pass = standardCredentialsPass(); if (nempty(user) && nempty(pass)) return litmap("_user" , user, "_pass" , pass); return litmap(); } static boolean _inCore() { return false; } static List hotwire_copyOver_after = synchroList(); static void hotwire_copyOver(Class c) { // TODO: make a mechanism for making such "inheritable" fields for (String field : ll("print_log", "print_silent", "androidContext", "_userHome")) setOptIfNotNull(c, field, getOpt(mc(), field)); setOptIfNotNull(c, "mainBot" , getMainBot()); setOpt(c, "creator_class" , new WeakReference(mc())); pcallFAll(hotwire_copyOver_after, c); } static byte[] intToBytes(int i) { return new byte[] { (byte) (i >>> 24), (byte) (i >>> 16), (byte) (i >>> 8), (byte) i}; } static File loadImageAsFile(String snippetIDOrURL) { try { if (isURL(snippetIDOrURL)) throw fail("not implemented"); if (!isSnippetID(snippetIDOrURL)) throw fail("Not a URL or snippet ID: " + snippetIDOrURL); String snippetID = "" + parseSnippetID(snippetIDOrURL); File file = imageSnippetCacheFile(snippetID); if (fileSize(file) > 0) return file; String imageURL = snippetImageURL_noHttps(snippetID); System.err.println("Loading image: " + imageURL); byte[] data = loadBinaryPage(imageURL); saveBinaryFile(file, data); return file; } catch (Exception __e) { throw rethrow(__e); } } // If you change this, also change DiskSnippetCache_fileToLibID static File DiskSnippetCache_file(long snippetID) { return new File(getGlobalCache(), "data_" + snippetID + ".jar"); } // Data files are immutable, use centralized cache public static File DiskSnippetCache_getLibrary(long snippetID) throws IOException { File file = DiskSnippetCache_file(snippetID); return file.exists() ? file : null; } public static File DiskSnippetCache_getLibrary(String snippetID) { try { return DiskSnippetCache_getLibrary(psI(snippetID)); } catch (Exception __e) { throw rethrow(__e); } } public static void DiskSnippetCache_putLibrary(long snippetID, byte[] data) throws IOException { saveBinaryFile(DiskSnippetCache_file(snippetID), data); } static byte[] loadDataSnippetImpl(String snippetID) throws IOException { byte[] data; try { URL url = new URL(dataSnippetLink(snippetID)); print("Loading library: " + hideCredentials(url)); try { data = loadBinaryPage(url.openConnection()); } catch (RuntimeException e) { data = null; } if (data == null || data.length == 0) { url = new URL(tb_mainServer() + "/blobs/" + parseSnippetID(snippetID)); print("Loading library: " + hideCredentials(url)); data = loadBinaryPage(url.openConnection()); } print("Bytes loaded: " + data.length); } catch (FileNotFoundException e) { throw new IOException("Binary snippet #" + snippetID + " not found or not public"); } return data; } static long fileSize(String path) { return getFileSize(path); } static long fileSize(File f) { return getFileSize(f); } static File loadDataSnippetToFile(String snippetID) { try { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.loadLibrary(snippetID); return loadDataSnippetToFile_noResourceLoader(snippetID); } catch (Exception __e) { throw rethrow(__e); } } static File loadDataSnippetToFile_noResourceLoader(String snippetID) { try { snippetID = fsI(snippetID); File f = DiskSnippetCache_file(parseSnippetID(snippetID)); List<URL> urlsTried = new ArrayList(); List<Throwable> errors = new ArrayList(); try { URL url = addAndReturn(urlsTried, new URL(dataSnippetLink(snippetID))); print("Loading library: " + hideCredentials(url)); try { loadBinaryPageToFile(openConnection(url), f); if (fileSize(f) == 0) throw fail(); } catch (Throwable e) { errors.add(e); url = addAndReturn(urlsTried, new URL(tb_mainServer() + "/blobs/" + psI(snippetID))); print(e); print("Trying other server: " + hideCredentials(url)); loadBinaryPageToFile(openConnection(url), f); print("Got bytes: " + fileSize(f)); } // TODO: check if we hit the "LOADING" message if (fileSize(f) == 0) throw fail(); System.err.println("Bytes loaded: " + fileSize(f)); } catch (Throwable e) { //printStackTrace(e); errors.add(e); throw fail("Binary snippet " + snippetID + " not found or not public. URLs tried: " + allToString(urlsTried) + ", errors: " + allToString(errors)); } return f; } catch (Exception __e) { throw rethrow(__e); } } static <A> A println(A a) { return print(a); } static List<AbstractButton> buttonsInGroup(ButtonGroup g) { if (g == null) return ll(); return asList(g.getElements()); } static <A extends JComponent> A toolTip(A c, final Object toolTip) { return setToolTipText(c, toolTip); } static <A extends JComponent> A toolTip(Object toolTip, A c) { return setToolTipText(toolTip, c); } static JComponent getInternalFrameTitlePaneComponent(JInternalFrame f) { return (JComponent) childWithClassNameEndingWith(f, "InternalFrameTitlePane"); } static <A> A setFrameTitle(A c, final String title) { final Frame f = getAWTFrame(c); if (f != null) { swing(() -> { f.setTitle(title); }); } return c; } static <A extends Component> A setFrameTitle(String title, A c) { return setFrameTitle(c, title); } // magically find a field called "frame" in main class :-) static JFrame setFrameTitle(String title) { Object f = getOpt(mc(), "frame"); if (f instanceof JFrame) return setFrameTitle((JFrame) f, title); return null; } static String getFrameTitle(Component c) { JFrame f = getFrame(c); return f == null ? null : f.getTitle(); } static <A> boolean addIfNotNull(Collection<A> l, A a) { return a != null && l != null & l.add(a); } static void closeAutoCloseables(Collection<AutoCloseable> l) { if (l != null) for (AutoCloseable c : l) { try { c.close(); } catch (Throwable __e) { printStackTrace(__e); }} } static <A> A nuInstance(Class<A> c) { return nuEmptyObject(c); } static <A> A copyFields(Object x, A y, String... fields) { if (empty(fields)) { // assume we should copy all fields Map<String, Object> map = objectToMap(x); for (String field : map.keySet()) setOpt(y, field, map.get(field)); } else for (String field : fields) { Object o = getOpt(x, field); if (o != null) setOpt(y, field, o); } return y; } static <A> A copyFields(Object x, A y, Collection<String> fields) { return copyFields(x, y, asStringArray(fields)); } static boolean isString(Object o) { return o instanceof String; } static Object dm_getService(String serviceName) { return empty(serviceName) ? null : dm_getModule(vmBus_query(assertIdentifier(serviceName))); } static boolean isStringOrIntOrLong(Object o) { return o instanceof String || o instanceof Integer || o instanceof Long; } static Object dm_getStemByID(Object id) { return dm_callOS("getModuleByID", str(id)); } static Object dm_getModule(Object moduleOrID) { if (moduleOrID == null || eq(moduleOrID, "")) return null; if (isString(moduleOrID) && isIdentifier(((String) moduleOrID))) return dm_getService(((String) moduleOrID)); if (isStringOrIntOrLong(moduleOrID)) return dm_callOS("getDynModuleByID", str(moduleOrID)); return dm_resolveModule(moduleOrID); } // return Int.MAX_VALUE if not applicable // Lower score is better static int methodApplicabilityScore_onTypes(Method m, Class[] argTypes) { return methodApplicabilityScore_onTypes((Executable) m, argTypes); } static int methodApplicabilityScore_onTypes(Executable m, Class[] argTypes) { Class<?>[] types = m.getParameterTypes(); if (types.length != argTypes.length) return Integer.MAX_VALUE; int score = 0; for (int i = 0; i < types.length; i++) { Class a = argTypes[i]; Class c = types[i]; if (c == a) {} // perfect match else if (isSubclassOf(a, c)) ++score; else return Integer.MAX_VALUE; } return score; } static JTextField onEnter(JTextField tf, JButton btn) { if (btn != null) onEnter(tf, new Runnable() { public void run() { try { clickButton(btn) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "clickButton(btn)"; }}); return tf; } static JTextField onEnter(JTextField tf, Object action) { if (action == null || tf == null) return tf; tf.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent _evt) { try { tf.selectAll(); callF(action); } catch (Throwable __e) { messageBox(__e); }}}); return tf; } static JButton onEnter(JButton btn, final Object action) { if (action == null || btn == null) return btn; btn.addActionListener(actionListener(action)); return btn; } static JList onEnter(JList list, Object action) { list.addKeyListener(enterKeyListener(rCallOnSelectedListItem(list, action))); return list; } static JComboBox onEnter(final JComboBox cb, Runnable action) { { swing(() -> { if (cb.isEditable()) { JTextField text = (JTextField) cb.getEditor().getEditorComponent(); onEnter(text, action); } else { cb.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "enter"); cb.getActionMap().put("enter", abstractAction("", new Runnable() { public void run() { try { cb.hidePopup(); callF(action); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cb.hidePopup(); callF(action);"; }})); } }); } return cb; } static JTable onEnter(final JTable table, final Object action) { table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) .put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "Enter"); table.getActionMap().put("Enter", new AbstractAction() { public void actionPerformed(ActionEvent e) { callF(action, table.getSelectedRow()); } }); return table; } /*static JTextArea onEnter(final JTextArea ta, fO action) { addKeyListener(ta, enterKeyListener(action)); ret ta; }*/ static JTextField onEnter(Runnable action, JTextField tf) { return onEnter(tf, action); } static ActionListener actionListener(final Object runnable) { return actionListener(runnable, null); } static ActionListener actionListener(final Object runnable, final Object instanceToHold) { if (runnable instanceof ActionListener) return (ActionListener) runnable; final Object info = _threadInfo(); return new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent _evt) { try { _threadInheritInfo(info); AutoCloseable __1 = holdInstance(instanceToHold); try { pcallF(runnable); } finally { _close(__1); }} catch (Throwable __e) { messageBox(__e); }}}; } static String selectedItem(JList l) { return getSelectedItem(l); } static String selectedItem(JComboBox cb) { return getSelectedItem(cb); } static void internalFrameTitlePopupMenuItem(JInternalFrame f, final String name, final Object action) { internalFrameTitlePopupMenu(f, new VF1<JPopupMenu>() { public void get(JPopupMenu menu) { try { addMenuItem(menu, name, action) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addMenuItem(menu, name, action)"; }}); } static Object fieldGet(Field f, Object o) { try { return f == null ? null : f.get(o); } catch (Exception __e) { throw rethrow(__e); } } static boolean containsSpace(String s) { return containsSpaces(s); } static String firstToUpper(String s) { if (empty(s)) return s; return Character.toUpperCase(s.charAt(0)) + s.substring(1); } static <A> List<A> replaceElementsUsingMap(Iterable<A> l, final Map<A, A> map) { return map(l, new F1<A, A>() { public A get(A a) { try { return getOrKeep(map, a); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "getOrKeep(map, a)"; }}); } static List<String> splitCamelCase(String s) { return ai_splitCamelCase(s); } static void addMenuItems(JMenu m, Object... x) { fillJMenu(m, x); } static void addMenuItems(JPopupMenu m, Object... x) { fillJPopupMenu(m, x); } static boolean isChecked(JCheckBox checkBox) { return checkBox != null && (boolean) swing(new F0<Boolean>() { public Boolean get() { try { return checkBox.isSelected(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return checkBox.isSelected();"; }}); } static boolean isChecked(JCheckBoxMenuItem mi) { return mi != null && (boolean) swing(new F0<Boolean>() { public Boolean get() { try { return mi.isSelected(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return mi.isSelected();"; }}); } static boolean isChecked(JRadioButton rb) { return rb != null && (boolean) swing(() -> rb.isSelected()); } static JTextField jTextField() { return jTextField(""); } static JTextField jTextField(final String text) { return swing(new F0<JTextField>() { public JTextField get() { try { JTextField tf = new JTextField(unnull(text)); standardTextFieldPopupMenu(tf); jenableUndoRedo(tf); tf.selectAll(); return tf; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JTextField tf = new JTextField(unnull(text));\r\n standardTextFieldPopupMenu..."; }}); } static JTextField jTextField(Object o) { return jTextField(strOrEmpty(o)); } static JPanel showInternalFrameFormTitled(final JDesktopPane desktop, final String title, final Object... _parts) { JPanel panel = showForm_makePanel(true, _parts); showForm_makeInternalFrame(desktop, title, panel); return panel; } static IVF2<String, JPanel> showForm_makeFrame; static void showForm_makeFrame(String title, JPanel panel) { if (showForm_makeFrame != null) showForm_makeFrame.get(title, panel); else showForm_makeFrame_base(title, panel); } final static void showForm_makeFrame_fallback(IVF2<String, JPanel> _f, String title, JPanel panel) { if (_f != null) _f.get(title, panel); else showForm_makeFrame_base(title, panel); } static void showForm_makeFrame_base(String title, JPanel panel) { handleEscapeKey(minFrameWidth(showPackedFrame(title, withMargin(panel)), 400)); } static List<JComponent> showForm_arrange1(List<List<JComponent>> l) { int minW = showForm_leftWidth(l); List<JComponent> out = new ArrayList(); for (List<JComponent> row : l) out.add(westAndCenter(withRightMargin(showForm_gapBetweenColumns, jMinWidthAtLeast(minW, first(row))), second(row))); return out; } static List<List<JComponent>> showForm_makeComponents(final Boolean internalFrame, Object... _parts) { List<List<JComponent>> l = new ArrayList(); List parts = asList(_parts); JButton submitButton = null; for (int i = 0; i < l(parts); i++) { final Object o = parts.get(i), next = get(parts, i+1); if (o instanceof String && next instanceof Component) setComponentID((Component) next, (String) o); if (o instanceof Component || o instanceof String || next instanceof Component) { // smartAdd accepts strings l.add(mapLL(__48 -> wrapForSmartAdd_jComponent(__48), o == null ? new JPanel() : o instanceof String ? humanizeFormLabel((String) o) : o, next)); if (next instanceof JButton && submitButton == null) submitButton = (JButton) next; i++; } else if (isRunnable(o)) l.add(mapLL(__49 -> wrapForSmartAdd_jComponent(__49), null, submitButton = jbutton(showFormSubmitButtonName(), new Runnable() { public void run() { try { Object result = call(o); print("Result of form runnable: " + result + ". Button: " + heldInstance(JButton.class)); if (neq(Boolean.FALSE, result)) { if (isTrue(internalFrame)) disposeInternalFrame(heldInstance(JButton.class)); else if (isFalse(internalFrame)) disposeFrame(heldInstance(JButton.class)); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Object result = call(o);\r\n print(\"Result of form runnable: \" + result ..."; }}))); else print("showForm: Unknown element type: " + getClassName(o)); } if (submitButton != null) { final JButton _submitButton = submitButton; onEnterInAllTextFields(concatLists(l), new Runnable() { public void run() { try { clickButton(_submitButton) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "clickButton(_submitButton)"; }}); } // massage labels for (List<JComponent> row : l) { JComponent left = first(row); if (left instanceof JLabel) makeBold((JLabel) left).setVerticalAlignment(JLabel.TOP); } return l; } static int vstackWithSpacing_default = 10; static JPanel vstackWithSpacing(final List parts) { return vstackWithSpacing(parts, vstackWithSpacing_default); } static JPanel vstackWithSpacing(final List parts, final int spacing) { return swing(new F0<JPanel>() { public JPanel get() { try { JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.weightx = 1; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.insets = new Insets(spacing/2, 0, (spacing+1)/2, 0); // well... smartAddWithLayout(panel, gbc, toObjectArray(nonNulls(parts))); //gbc = (GridBagConstraints) gbc.clone(); //gbc.fill = GridBagConstraints.BOTH; gbc.weighty = 1; gbc.insets = new Insets(0, 0, 0, 0); panel.add(jrigid(), gbc); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel panel = new JPanel(new GridBagLayout);\r\n new GridBagConstraints gbc..."; }}); } static JPanel vstackWithSpacing(Component... parts) { return vstackWithSpacing(asList(parts), vstackWithSpacing_default); } static JPanel vstackWithSpacing(int spacing, Component... parts) { return vstackWithSpacing(asList(parts), spacing); } static String getTextTrim(JTextComponent c) { return trim(getText(c)); } // tested for editable combo box - returns the contents of text field static String getTextTrim(JComboBox cb) { return trim(getText(cb)); } static String getTextTrim(JComponent c) { if (c instanceof JLabel) return trim(((JLabel) c).getText()); if (c instanceof JComboBox) return getTextTrim((JComboBox) c); return getTextTrim((JTextComponent) c); } static float parseFloat(String s) { return Float.parseFloat(s); } static String strOrNull(Object o) { return o == null ? null : str(o); } static File toFile_nullOnEmpty(String s) { return empty(s) ? null : new File(s); } static DynModule dm_current() { return dm_currentModule(); } static <A extends JComponent> A setToolTipText(final A c, final Object toolTip) { if (c == null) return null; { swing(() -> { String s = nullIfEmpty(str(toolTip)); if (neq(s, c.getToolTipText())) c.setToolTipText(s); }); } return c; } static <A extends JComponent> A setToolTipText(Object toolTip, A c) { return setToolTipText(c, toolTip); } static void setTrayIconToolTip(TrayIcon trayIcon, String toolTip) { if (trayIcon != null) trayIcon.setToolTip(toolTip); } static JLabel jImageLabel(Image img) { return swingNu(JLabel.class, imageIcon(img)); } static JLabel jImageLabel(javax.swing.Icon icon) { return swingNu(JLabel.class, icon); } static JLabel jImageLabel(String imageID) { return jImageLabel(imageIcon(imageID)); } static JLabel jImageLabel(String text, String imageID) { final JLabel l = swingNu(JLabel.class, text, imageIcon(imageID), JLabel.CENTER); { swing(() -> { l.setVerticalTextPosition(SwingConstants.BOTTOM); l.setHorizontalTextPosition(SwingConstants.CENTER); }); } return l; } static String localSnippetTitle(String snippetID) { if (!isLocalSnippetID(snippetID)) return null; File f = localSnippetFile(snippetID); if (!f.exists()) return null; return or2(getFileInfoField(dropExtension(f), "Title"), "Unnamed"); } static String imageServerURL() { return or2(trim(loadTextFile(javaxDataDir("image-server-url.txt"))), "http://botcompany.de/images/raw/"); } static String muricaCredentialsQuery() { return htmlQuery(muricaCredentials()); } static String standardCredentials_noCookies() { return standardCredentials() + "&noCookies=1"; } static boolean saveTextFileIfChanged(File f, String contents) { return saveTextFileIfDifferent(f, contents); } static File snippetTitle_cacheFile(String snippetID) { return javaxCachesDir("Snippet Titles/" + psI(snippetID)); } static <A> Set<A> synchroWeakHashSet() { return Collections.newSetFromMap((Map) newWeakHashMap()); } static String joinStrings(String sep, Object... strings) { return joinStrings(sep, Arrays.asList(strings)); } static String joinStrings(String sep, Iterable strings) { StringBuilder buf = new StringBuilder(); for (Object o : unnull(strings)) { String s = strOrNull(o); if (nempty(s)) { if (nempty(buf)) buf.append(sep); buf.append(s); } } return str(buf); } static String strOrEmpty(Object o) { return o == null ? "" : str(o); } static <A extends JComponent> A bindLiveValueListenerToComponent(A component, final LiveValue lv, final Runnable listener) { if (lv != null) bindToComponent(component, new Runnable() { public void run() { try { lv.onChangeAndNow(listener); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ifdef bindLiveValueListenerToComponent_debug\r\n print(\"bindLiveValueL..."; }}, new Runnable() { public void run() { try { lv.removeChangeListener(listener) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "lv.removeChangeListener(listener)"; }}); return component; } static <A extends JComponent> A setBorder(Border border, A c) { if (c != null) { swing(() -> { c.setBorder(border); }); } return c; } static <A extends JComponent> A setBorder(A c, Border border) { return setBorder(border, c); } static <A extends JComponent> A setFont(final Font font, final A a) { if (a != null) { swing(() -> { a.setFont(font); }); } return a; } static <A extends JComponent> A setFont(A a, Font font) { return setFont(font, a); } static <A extends JComponent> A setFont(final String fontID, float fontSize, final A a) { return setFont(loadFont_cached(fontID, fontSize), a); } static Font typeWriterFont() { return typeWriterFont(iround(14*getSwingFontScale())); } static Font typeWriterFont(int size) { return new Font("Courier", Font.PLAIN, size); } static <A> A swingConstruct(final Class<A> c, final Object... args) { return swing(new F0<A>() { public A get() { try { return nuObject(c, args); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return nuObject(c, args);"; }}); } static MouseListener findComponentPopupMenuListener_gen(final JComponent c) { return c == null ? null : swing(() -> firstWithClassShortNamed("componentPopupMenu_Adapter", c.getMouseListeners()) ); } static boolean internalFrameActive(Component c) { final JInternalFrame f = getInternalFrame(c); return f != null && swing(new F0<Boolean>() { public Boolean get() { try { return f.isSelected(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return f.isSelected();"; }}); } static boolean jmenuItem_newThreads = false; static JMenuItem jmenuItem(final String text) { return jMenuItem(text, null); } static JMenuItem jmenuItem(final String text, final Object r) { return swing(new F0<JMenuItem>() { public JMenuItem get() { try { Pair<String, Integer> p = jmenu_autoMnemonic(dropPrefix("[disabled] ", text)); JMenuItem mi = new JMenuItem(p.a); if (startsWith(text, "[disabled] ")) disableMenuItem(mi); if (p.b != 0) mi.setMnemonic(p.b); mi.addActionListener(jmenuItem_newThreads ? actionListenerInNewThread(r) : actionListener(r)); return mi; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Pair<S, Int> p = jmenu_autoMnemonic(dropPrefix(\"[disabled] \", text));\r\n JM..."; }}); } static MenuItem menuItem(String text, final Object r) { MenuItem mi = new MenuItem(text); mi.addActionListener(actionListener(r)); return mi; } static void addDirectMenuItem(JMenuBar mb, String text, Object action) { if (mb != null) { swing(() -> { addDirectMenuItem(mb, directJMenuItem(text, action)); }); } } static void addDirectMenuItem(Component c, String text, Object action) { addDirectMenuItem(addMenuBar(c), text, action); } static void addDirectMenuItem(JMenuBar mb, JMenuItem menuItem) { if (mb != null) { swing(() -> { mb.add(menuItem); revalidate(mb); }); } } static Runnable addThreadInfoToRunnable(final Object r) { final Object info = _threadInfo(); return info == null ? asRunnable(r) : new Runnable() { public void run() { try { _inheritThreadInfo(info); callF(r); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "_inheritThreadInfo(info); callF(r);"; }}; } static AutoCloseable tempActivity(Object r) { return null; } static boolean allPaused() { return ping_pauseAll; } static void messageBox(final String msg) { if (headless()) print(msg); else { swing(() -> { JOptionPane.showMessageDialog(null, msg, "JavaX", JOptionPane.INFORMATION_MESSAGE); }); } } static void messageBox(Throwable e) { //showConsole(); printStackTrace(e); messageBox(hideCredentials(innerException2(e))); } static void bindTimerToComponent(final Timer timer, JFrame f) { bindTimerToComponent(timer, f.getRootPane()); } static void bindTimerToComponent(final Timer timer, JComponent c) { if (c.isShowing()) timer.start(); c.addAncestorListener(new AncestorListener() { public void ancestorAdded(AncestorEvent event) { timer.start(); } public void ancestorRemoved(AncestorEvent event) { timer.stop(); } public void ancestorMoved(AncestorEvent event) { } }); } static Object rcall(String method, Object o, Object... args) { return call_withVarargs(o, method, args); } static Runnable _topLevelErrorHandling(Runnable r) { if (r == null) return null; // maybe we don't want this anymore. just dm_current_generic() Object info = _threadInfo(); Object mod = dm_current_generic(); if (info == null && mod == null) return r; return new Runnable() { public void run() { try { AutoCloseable __1 = (AutoCloseable) (rcall("enter", mod)); try { _threadInheritInfo(info); r.run(); } finally { _close(__1); }} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp (AutoCloseable) rcall enter(mod);\r\n _threadInheritInfo(info);\r\n r...."; }}; } static boolean containsNewLines(String s) { return containsNewLine(s); } static String jlabel_textAsHTML_center(String text) { return "<html><div style=\"text-align: center;\">" + replace(htmlencode2(text), "\n", "<br>") + "</div></html>"; } static String rtrim_fromLines(Collection lines) { StringBuilder buf = new StringBuilder(); if (lines != null) { boolean first = true; for (Object line : lines) { if (first) first = false; else buf.append('\n'); buf.append(str(line)); } } return buf.toString(); } static List<WeakReference<Class>> hotwire_classes = synchroList(); static Class<?> hotwireDependent(String src) { Class c = hotwire(src); makeDependent(c); return c; } static boolean loadBufferedImage_useImageCache = true; static BufferedImage loadBufferedImage(String snippetIDOrURLOrFile) { try { ping(); if (snippetIDOrURLOrFile == null) return null; if (isURL(snippetIDOrURLOrFile)) return imageIO_readURL(snippetIDOrURLOrFile); if (isSnippetID(snippetIDOrURLOrFile)) { String snippetID = "" + parseSnippetID(snippetIDOrURLOrFile); IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return loadBufferedImage(rl.loadLibrary(snippetID)); File dir = imageSnippetsCacheDir(); if (loadBufferedImage_useImageCache) { dir.mkdirs(); File file = new File(dir, snippetID + ".png"); if (file.exists() && file.length() != 0) try { return ImageIO.read(file); } catch (Throwable e) { e.printStackTrace(); // fall back to loading from sourceforge } } String imageURL = snippetImageURL_http(snippetID); print("Loading image: " + imageURL); BufferedImage image = imageIO_readURL(imageURL); if (loadBufferedImage_useImageCache) { File tempFile = new File(dir, snippetID + ".tmp." + System.currentTimeMillis()); ImageIO.write(image, "png", tempFile); tempFile.renameTo(new File(dir, snippetID + ".png")); //Log.info("Cached image."); } //Log.info("Loaded image."); return image; } else return loadBufferedImage(new File(snippetIDOrURLOrFile)); } catch (Exception __e) { throw rethrow(__e); } } static BufferedImage loadBufferedImage(File file) { return loadBufferedImageFile(file); } static Map similarEmptyMap(Map m) { if (m instanceof TreeMap) return new TreeMap(((TreeMap) m).comparator()); if (m instanceof LinkedHashMap) return new LinkedHashMap(); // default to a hash map return new HashMap(); } static Map similarEmptyMap(Iterable m) { if (m instanceof TreeSet) return new TreeMap(((TreeSet) m).comparator()); if (m instanceof LinkedHashSet) return new LinkedHashMap(); return new HashMap(); } // f : Matcher -> S static String regexpReplaceIC(String s, String pat, Object f) { return regexReplaceIC(s, pat, f); } static String regexpReplaceIC(String s, String pat, String replacement) { return regexReplaceIC(s, pat, replacement); } static String regexpReplaceIC(String s, String pat, IF1<Matcher, String> f) { return regexReplaceIC(s, pat, f); } static String[] drop(int n, String[] a) { n = Math.min(n, a.length); String[] b = new String[a.length-n]; System.arraycopy(a, n, b, 0, b.length); return b; } static Object[] drop(int n, Object[] a) { n = Math.min(n, a.length); Object[] b = new Object[a.length-n]; System.arraycopy(a, n, b, 0, b.length); return b; } static boolean isDigit(char c) { return Character.isDigit(c); } static String dropLeadingDots(String s) { int i = 0; while (charAt(s, i) == '.') ++i; return dropFirst(s, i); } static void disposeWindow(final Window window) { if (window != null) { swing(() -> { window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); // call listeners myFrames_list.remove(window); window.dispose(); }); } } static void disposeWindow(final Component c) { disposeWindow(getWindow(c)); } static void disposeWindow(Object o) { if (o != null) disposeWindow(((Component) o)); } static void disposeWindow() { disposeWindow(heldInstance(Component.class)); } static JWindow showLoadingAnimation() { return showLoadingAnimation("Hold on user..."); } static JWindow showLoadingAnimation(String text) { try { return showAnimationInTopRightCorner("#1003543", text); } catch (Throwable __e) { return null; } } static <A> List<A> cleanUpAndGetWeakReferencesList(List<WeakReference<A>> l) { if (l == null) return null; synchronized(l) { List<A> out = new ArrayList(); for (int i = 0; i < l(l); i++) { A a = l.get(i).get(); if (a == null) l.remove(i--); else out.add(a); } return out; } } static String loadTextFileFromZip(File inZip, String fileName) { return loadTextFileFromZipFile(inZip, fileName); } static List<File> myLibraryFiles() { Collection<File> files = (Collection<File>) (getOpt(myClassLoader(), "files")); if (files != null) return asList(files); return ll(getBytecodePathForClass(mc())); } static ClassLoader myClassLoader() { return _getClass(mc()).getClassLoader(); } static Class hotwire_finish(ClassLoader classLoader, String progID, String javaSource) { return hotwire_finish(classLoader, progID, javaSource, "main"); } static Class hotwire_finish(ClassLoader classLoader, String progID, String javaSource, String mainClass) { try { // load & return main class Class<?> theClass = classLoader.loadClass(mainClass); Class j = getJavaX(); setOpt(theClass, "myJavaSource_code", javaSource); synchronized(j) { // hopefully this goes well... call(j, "setVars", theClass, progID); callOpt(j, "addInstance", progID, theClass); } hotwire_copyOver(theClass); vmBus_send("hotwireFinished", theClass, mc()); return theClass; } catch (Exception __e) { throw rethrow(__e); } } static int lUtf8(String s) { return l(utf8(s)); } static String loadPage_utf8(URL url) { return loadPage_utf8(url.toString()); } static String loadPage_utf8(String url) { AutoCloseable __1 = tempSetTL(loadPage_charset, "UTF-8"); try { return loadPage(url); } finally { _close(__1); }} static String loadPage_utf8(URLConnection con, URL url, boolean addHeaders) throws IOException { AutoCloseable __2 = tempSetTL(loadPage_charset, "UTF-8"); try { return loadPage(con, url, addHeaders); } finally { _close(__2); }} static void setOptIfNotNull(Object o, String field, Object value) { if (value != null) setOpt(o, field, value); } static File imageSnippetCacheFile(String snippetID) { File dir = imageSnippetsCacheDir(); if (!loadBufferedImage_useImageCache) return null; return new File(dir, parseSnippetID(snippetID) + ".png"); } static String snippetImageURL_noHttps(String snippetID) { return snippetImageURL_noHttps(snippetID, "png"); } static String snippetImageURL_noHttps(String snippetID, String contentType) { return snippetImageURL(snippetID, contentType) .replace("https://www.botcompany.de:8443/", "http://www.botcompany.de:8080/") .replace("https://botcompany.de/", "http://botcompany.de/"); } static String dataSnippetLink(String snippetID) { long id = parseSnippetID(snippetID); if (id >= 1100000 && id < 1200000) return imageServerURL() + id; if (id >= 1200000 && id < 1300000) { // Woody files, actually String pw = muricaPassword(); if (empty(pw)) throw fail("Please set 'murica password by running #1008829"); return "https://botcompany.de/files/" + id + "?_pass=" + pw; // XXX, although it typically gets hidden when printing } return fileServerURL() + "/" + id /*+ "?_pass=" + muricaPassword()*/; } static <B, A extends B> A addAndReturn(Collection<B> c, A a) { if (c != null) c.add(a); return a; } static void loadBinaryPageToFile(String url, File file) { try { print("Loading " + url); loadBinaryPageToFile(openConnection(new URL(url)), file); } catch (Exception __e) { throw rethrow(__e); } } static void loadBinaryPageToFile(URLConnection con, File file) { try { setHeaders(con); loadBinaryPageToFile_noHeaders(con, file); } catch (Exception __e) { throw rethrow(__e); } } static void loadBinaryPageToFile_noHeaders(URLConnection con, File file) { try { File ftemp = new File(f2s(file) + "_temp"); FileOutputStream buf = newFileOutputStream(mkdirsFor(ftemp)); try { InputStream inputStream = con.getInputStream(); long len = 0; try { len = con.getContentLength/*Long*/(); } catch (Throwable e) { printStackTrace(e); } String pat = " {*}" + (len != 0 ? "/" + len : "") + " bytes loaded."; copyStreamWithPrints(inputStream, buf, pat); inputStream.close(); buf.close(); file.delete(); renameFile_assertTrue(ftemp, file); } finally { if (buf != null) buf.close(); } } catch (Exception __e) { throw rethrow(__e); } } static Component childWithClassNameEndingWith(Component c, String suffix) { if (endsWith(className(c), suffix)) return c; Component x; for (Component comp : getComponents(c)) if ((x = childWithClassNameEndingWith(comp, suffix)) != null) return x; return null; } static Frame getAWTFrame(final Object _o) { return swing(new F0<Frame>() { public Frame get() { try { Object o = _o; /* ifdef HaveProcessing if (o instanceof PApplet) o = ((PApplet) o).getSurface(); endifdef */ if (o instanceof ButtonGroup) o = first(buttonsInGroup((ButtonGroup) o)); if (!(o instanceof Component)) return null; Component c = (Component) o; while (c != null) { if (c instanceof Frame) return (Frame) c; c = c.getParent(); } return null; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "O o = _o;\r\n /*\r\n ifdef HaveProcessing\r\n if (o instanceof PApplet) ..."; }}); } static Map<Class, Constructor> nuEmptyObject_cache = newDangerousWeakHashMap(); static <A> A nuEmptyObject(Class<A> c) { try { Constructor ctr; synchronized(nuEmptyObject_cache) { ctr = nuEmptyObject_cache.get(c); if (ctr == null) { nuEmptyObject_cache.put(c, ctr = nuEmptyObject_findConstructor(c)); makeAccessible(ctr); } } try { return (A) ctr.newInstance(); } catch (InstantiationException e) { if (empty(e.getMessage())) if ((c.getModifiers() & Modifier.ABSTRACT) != 0) throw fail("Can't instantiate abstract class " + className(c), e); else throw fail("Can't instantiate " + className(c), e); else throw rethrow(e); } } catch (Exception __e) { throw rethrow(__e); } } static Constructor nuEmptyObject_findConstructor(Class c) { for (Constructor m : c.getDeclaredConstructors()) if (m.getParameterTypes().length == 0) return m; throw fail("No default constructor declared in " + c.getName()); } // o is either a map already (string->object) or an arbitrary object, // in which case its fields are converted into a map. static Map<String, Object> objectToMap(Object o) { try { if (o instanceof Map) return (Map) o; TreeMap<String, Object> map = new TreeMap(); Class c = o.getClass(); while (c != Object.class) { Field[] fields = c.getDeclaredFields(); for (final Field field : fields) { if ((field.getModifiers() & Modifier.STATIC) != 0) continue; field.setAccessible(true); final Object value = field.get(o); if (value != null) map.put(field.getName(), value); } c = c.getSuperclass(); } // XXX NEW - hopefully this doesn't break anything if (o instanceof DynamicObject) putAll(map, ((DynamicObject) o).fieldValues); return map; } catch (Exception __e) { throw rethrow(__e); } } // same for a collection (convert each element) static List<Map<String, Object>> objectToMap(Iterable l) { if (l == null) return null; List x = new ArrayList(); for (Object o : l) x.add(objectToMap(o)); return x; } static String[] asStringArray(Collection<String> c) { return toStringArray(c); } static String[] asStringArray(Object o) { return toStringArray(o); } static Object vmBus_query(String msg, Object... args) { Object arg = vmBus_wrapArgs(args); { var __1= pcallFAll_returnFirstNotNull(vm_busListeners_live(), msg, arg); if (__1 != null) return __1; } return pcallFAll_returnFirstNotNull(vm_busListenersByMessage_live().get(msg), msg, arg); } static Object vmBus_query(String msg) { return vmBus_query(msg, (Object) null); } static String assertIdentifier(String s) { return assertIsIdentifier(s); } static String assertIdentifier(String msg, String s) { return assertIsIdentifier(msg, s); } static Object dm_resolveModule(Object moduleOrStem) { return dm_callOS("resolveModule", moduleOrStem); } static boolean isSubclassOf(Class a, Class b) { return isSubclass(a, b); } static void clickButton(final JButton b) { if (b != null) { swing(() -> { if (b.isEnabled()) b.doClick(); }); } } static KeyListener enterKeyListener(final Object action) { return new KeyAdapter() { public void keyPressed(KeyEvent ke) { if (ke.getKeyCode() == KeyEvent.VK_ENTER) pcallF(action); } }; } static Runnable rCallOnSelectedListItem(final JList list, final Object action) { return new Runnable() { public void run() { try { pcallF(action, getSelectedItem(list)) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pcallF(action, getSelectedItem(list))"; }}; } static ThreadLocal<List<Object>> holdInstance_l = new ThreadLocal(); static AutoCloseable holdInstance(Object o) { if (o == null) return null; listThreadLocalAdd(holdInstance_l, o); return new AutoCloseable() { public void close() { listThreadLocalPopLast(holdInstance_l); } }; } static String getSelectedItem(JList l) { return (String) l.getSelectedValue(); } static String getSelectedItem(JComboBox cb) { return strOrNull(cb.getSelectedItem()); } static boolean containsSpaces(String s) { return indexOf(s, ' ') >= 0; } static <A> A getOrKeep(Map<A, ? extends A> map, A a) { if (map == null) return a; A v = map.get(a); return v != null ? v : a; } static List<String> ai_splitCamelCase(String s) { int j = 0; List<String> l = new ArrayList(); // new addition if (isAllUpperCase(s)) { l.add(s); return l; } for (int i = 0; i < l(s); i++) if (i > j && isUpperCaseLetter(s.charAt(i))) { l.add(substring(s, j, i)); j = i; } if (j < l(s)) l.add(substring(s, j)); return l; } static void fillJMenu(final JMenu m, Object... x) { //ifdef fillJMenu_debug //print("fillJMenu " + m); //endifdef if (x == null) return; for (int i = 0; i < l(x); i++) { Object o = x[i], y = get(x, i+1); if (o instanceof List) fillJMenu(m, asArray((List) o)); else if (isMenuSeparatorIndicator(o)) { if (menuItemCount(m) != 0) // auto-skip separator if at top m.addSeparator(); } else if (o instanceof LiveValue && ((LiveValue) o).getType() == String.class && isRunnableX(y)) { final LiveValue<String> lv = (LiveValue<String>) o; final JMenuItem mi = jmenuItem(or2(unCurlyBracket(lv.get()), "..."), y); bindLiveValueListenerToComponent(mi, lv, new Runnable() { public void run() { try { String s = lv.get(); if (isCurlyBracketed(s)) { setEnabled(mi, false); s = unCurlyBracket(s); } else setEnabled(mi, true); setText(mi, s); revalidate(m); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "String s = lv!;\r\n if (isCurlyBracketed(s)) {\r\n setEnabled(mi,..."; }}); print("bound live value " + lv + " to menu item " + mi); m.add(mi); ++i; } else if (o instanceof String && isRunnableX(y)) { m.add(jmenuItem((String) o, y)); ++i; } else if (o instanceof JMenuItem) m.add((JMenuItem) o); // "call" might use wrong method else if (o instanceof String || o instanceof Action || o instanceof Component) call(m, "add", o); else if (o == null && y instanceof Runnable) ++i; // text == null => disabled item else if (o != null) print("Unknown menu item: " + o); } } static void fillJPopupMenu(JPopupMenu m, Object... x) { if (x == null) return; for (int i = 0; i < l(x); i++) { Object o = x[i], y = get(x, i+1); if (o instanceof IVF1) callF(o, m); else if (o instanceof List) fillJPopupMenu(m, asArray((List) o)); else if (isMenuSeparatorIndicator(o)) m.addSeparator(); else if (o instanceof LiveValue && ((LiveValue) o).getType() == String.class && isRunnableX(y)) { final LiveValue<String> lv = (LiveValue<String>) o; final JMenuItem mi = jmenuItem("", y); bindLiveValueListenerToComponent(mi, lv, new Runnable() { public void run() { try { String s = lv.get(); if (isCurlyBracketed(s)) { setEnabled(mi, false); s = unCurlyBracket(s); } else setEnabled(mi, true); setText(mi, s); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "String s = lv!;\r\n if (isCurlyBracketed(s)) {\r\n setEnabled(mi,..."; }}); m.add(mi); } else if (o instanceof String && isRunnableX(y)) { m.add(jmenuItem((String) o, y)); ++i; } else if (o instanceof JMenuItem) m.add((JMenuItem) o); // "call" might use wrong method else if (o instanceof String || o instanceof Action || o instanceof Component) call(m, "add", o); else if (o != null) print("Unknown menu item: " + o); } } static JTextField standardTextFieldPopupMenu(final JTextField tf) { final WeakReference<JTextField> ref = weakRef(tf); componentPopupMenuItem(tf, "Copy text to clipboard", new Runnable() { public void run() { try { copyTextToClipboard(ref.get().getText()) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "copyTextToClipboard(ref.get().getText())"; }}); componentPopupMenuItem(tf, "Paste", new Runnable() { public void run() { try { ref.get().paste() ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ref.get().paste()"; }}); return tf; } static <A extends JTextComponent> A jenableUndoRedo(final A textcomp) { { swing(() -> { final UndoManager undo = new UndoManager(); vm_generalWeakSet("Undo Managers").add(undo); textcomp.getDocument().addUndoableEditListener(new UndoableEditListener() { public void undoableEditHappened(UndoableEditEvent evt) { undo.addEdit(evt.getEdit()); } }); textcomp.getActionMap().put("Undo", abstractAction("Undo", new Runnable() { public void run() { try { if (undo.canUndo()) undo.undo() ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (undo.canUndo()) undo.undo()"; }})); textcomp.getActionMap().put("Redo", abstractAction("Redo", new Runnable() { public void run() { try { if (undo.canRedo()) undo.redo() ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (undo.canRedo()) undo.redo()"; }})); textcomp.getInputMap().put(KeyStroke.getKeyStroke("control Z"), "Undo"); textcomp.getInputMap().put(KeyStroke.getKeyStroke("control Y"), "Redo"); }); } return textcomp; } static JInternalFrame showForm_makeInternalFrame(JDesktopPane desktop, String title, JPanel panel) { JInternalFrame f = addInternalFrame(desktop, title, withMargin(panel)); minInternalFrameWidth(f, 400); packInternalFrameVertically(f); centerInternalFrame(f); // TODO: handleEscapeKey(f); return f; } static JFrame handleEscapeKey(final JFrame frame) { KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); frame.getRootPane().registerKeyboardAction(new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { frame.dispose(); } }, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); return frame; } static JFrame minFrameWidth(JFrame frame, int w) { if (frame != null && frame.getWidth() < w) frame.setSize(w, frame.getHeight()); return frame; } static JFrame minFrameWidth(int w, JFrame frame) { return minFrameWidth(frame, w); } static JFrame showPackedFrame(String title, Component contents) { return packFrame(showFrame(title, contents)); } static JFrame showPackedFrame(Component contents) { return packFrame(showFrame(contents)); } static int withMargin_defaultWidth = 6; static JPanel withMargin(Component c) { return withMargin(withMargin_defaultWidth, c); } static JPanel withMargin(int w, Component c) { return withMargin(w, w, c); } static JPanel withMargin(int w, int h, Component c) { return withMargin(w, h, w, h, c); } static JPanel withMargin(final int top, final int left, final int bottom, final int right, final Component c) { return swing(new F0<JPanel>() { public JPanel get() { try { JPanel p = marginPanel(); p.setBorder(BorderFactory.createEmptyBorder(top, left, bottom, right)); p.add(c); return p; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel p = marginPanel();\r\n p.setBorder(BorderFactory.createEmptyBorder(to..."; }}); } static int showForm_leftWidth_safetyMargin = 10; static int showForm_leftWidth(List<List<JComponent>> l) { forEachLevel2(l, x -> vmBus_send("updateLayoutNow", x)); int minW = 0; for (List<JComponent> row : l) minW = max(minW, getMinimumSize(first(row)).width); return minW + or((Integer) vmBus_query("formSafetyMargin"), showForm_leftWidth_safetyMargin); } static JPanel westAndCenter(final Component w, final Component c) { return swing(new F0<JPanel>() { public JPanel get() { try { JPanel panel = new JPanel(new BorderLayout()); panel.add(BorderLayout.WEST, wrap(w)); panel.add(BorderLayout.CENTER, wrap(c)); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel panel = new JPanel(new BorderLayout);\r\n panel.add(BorderLayout.WEST..."; }}); } static int withRightMargin_defaultWidth = 6; static JPanel withRightMargin(Component c) { return withRightMargin(withRightMargin_defaultWidth, c); } static JPanel withRightMargin(final int w, final Component c) { return swing(new F0<JPanel>() { public JPanel get() { try { JPanel p = marginPanel(); p.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, w)); p.add(c); return p; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel p = marginPanel();\r\n p.setBorder(BorderFactory.createEmptyBorder(0,..."; }}); } static <A extends Component> A jMinWidthAtLeast(int w, final A c) { if (c == null) return null; return swing(new F0<A>() { public A get() { try { Dimension size = c.getMinimumSize(); Dimension d = new Dimension(max(w, size.width), size.height); c.setMinimumSize(d); return jPreferWidth(d.width, c); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Dimension size = c.getMinimumSize();\r\n Dimension d = new Dimension(max(w, ..."; }}); } static void setComponentID(Component c, String id) { if (c != null) componentID_map.put(c, id); } static List mapLL(Object f, Object... data) { return map(f, ll(data)); } static <A, B> List<B> mapLL(IF1<A, B> f, A... data) { return map(f, ll(data)); } static JComponent wrapForSmartAdd_jComponent(Object o) { return componentToJComponent(wrapForSmartAdd(o)); } static boolean isRunnable(Object o) { return o instanceof Runnable || hasMethod(o, "get"); } static JButton jbutton(String text, Runnable action) { return newButton(text, action); } static JButton jbutton(String text, Object action) { return newButton(text, action); } // button without action static JButton jbutton(String text) { return newButton(text, null); } /*static JButton jbutton(BufferedImage img, O action) { ret setButtonImage(img, jbutton("", action)); }*/ static JButton jbutton(Action action) { return swingNu(JButton.class, action); } static String showFormSubmitButtonName() { return "Submit"; } static <A> A heldInstance(Class<A> c) { List<Object> l = holdInstance_l.get(); for (int i = l(l)-1; i >= 0; i--) { Object o = l.get(i); if (isInstanceOf(o, c)) return (A) o; } throw fail("No instance of " + className(c) + " held"); } static void disposeInternalFrame(Component c) { final JInternalFrame f = getInternalFrame(c); if (f != null) { swing(() -> { vmBus_send("disposingInternalFrame", f); f.dispose(); // now illegal... setOpt(f, lastFocusOwner := null); // Help GC }); } } static void disposeFrame(final Component c) { disposeWindow(c); } static void onEnterInAllTextFields(JComponent c, Runnable action) { if (action == null) return; for (Component tf : allChildren(c)) onEnterIfTextField(tf, action); } static void onEnterInAllTextFields(List c, Runnable action) { for (Object o : unnull(c)) if (o instanceof JComponent) onEnterInAllTextFields(((JComponent) o), action); } static <A extends JComponent> A makeBold(final A c) { if (c != null) { swing(() -> { c.setFont(c.getFont().deriveFont(java.awt.Font.BOLD)); }); } return c; } static JPanel smartAddWithLayout(JPanel panel, Object layout, List parts) { for (Object o : parts) panel.add(wrapForSmartAdd(o), layout); return panel; } static JPanel smartAddWithLayout(JPanel panel, Object layout, Object... parts) { return smartAddWithLayout(panel, layout, asList(flattenArray2(parts))); } static <A> List<A> nonNulls(Iterable<A> l) { return withoutNulls(l); } static <A> List<A> nonNulls(A[] l) { return withoutNulls(l); } static <A, B> Map<A, B> nonNulls(Map<A, B> map) { return withoutNulls(map); } static Component jrigid() { return javax.swing.Box.createRigidArea(new Dimension(0, 0)); } static String nullIfEmpty(String s) { return isEmpty(s) ? null : s; } static <A, B> Map<A, B> nullIfEmpty(Map<A, B> map) { return isEmpty(map) ? null : map; } static <A> List<A> nullIfEmpty(List<A> l) { return isEmpty(l) ? null : l; } static int imageIcon_cacheSize = 10; static boolean imageIcon_verbose = false; static Map<String, ImageIcon> imageIcon_cache; static Lock imageIcon_lock = lock(); static ThreadLocal<Boolean> imageIcon_fixGIF = new ThreadLocal(); // not going through BufferedImage preserves animations static ImageIcon imageIcon(String imageID) { try { if (imageID == null) return null; Lock __0 = imageIcon_lock; lock(__0); try { if (imageIcon_cache == null) imageIcon_cache = new MRUCache(imageIcon_cacheSize); imageID = fsI(imageID); ImageIcon ii = imageIcon_cache.get(imageID); if (ii == null) { if (imageIcon_verbose) print("Loading image icon: " + imageID); File f = loadBinarySnippet(imageID); Boolean b = imageIcon_fixGIF.get(); if (!isFalse(b)) ii = new ImageIcon(loadBufferedImageFixingGIFs(f)); else ii = new ImageIcon(f.toURI().toURL()); } else imageIcon_cache.remove(imageID); // move to front of cache on access imageIcon_cache.put(imageID, ii); return ii; } finally { unlock(__0); } } catch (Exception __e) { throw rethrow(__e); } } // doesn't fix GIFs static ImageIcon imageIcon(File f) { try { return new ImageIcon(f.toURI().toURL()); } catch (Exception __e) { throw rethrow(__e); } } static ImageIcon imageIcon(Image img) { return img == null ? null : new ImageIcon(img); } static File dropExtension(File f) { return f == null ? null : fileInSameDir(f, dropExtension(f.getName())); } static String dropExtension(String s) { return takeFirst(s, smartLastIndexOf(s, '.')); } static String htmlQuery(Map params) { return empty(params) ? "" : "?" + makePostData(params); } static String htmlQuery(Object... data) { return empty(data) ? "" : "?" + makePostData(data); } static Object[] muricaCredentials() { String pass = muricaPassword(); return nempty(pass) ? new Object[] {"_pass", pass } : new Object[0]; } static boolean saveTextFileIfDifferent(File f, String contents) { if (eq(loadTextFile(f), contents)) return false; // TODO: optimize { saveTextFile(f, contents); return true; } } static <A extends JComponent> A bindToComponent(final A component, final Runnable onShow, final Runnable onUnShow) { { swing(() -> { final Var < Boolean > flag = new Var<>(false); component.addAncestorListener(new AncestorListener() { public void ancestorAdded(AncestorEvent event) { if (flag.get()) print("Warning: bindToComponent logic failure"); flag.set(true); pcallF(onShow); } public void ancestorRemoved(AncestorEvent event) { if (!flag.get()) print("Warning: bindToComponent logic failure"); flag.set(false); pcallF(onUnShow); } public void ancestorMoved(AncestorEvent event) { } }); if (component.isShowing()) { // Hopefully this matches the AncestorListener logic flag.set(true); pcallF(onShow); } }); } return component; } static <A extends JComponent> A bindToComponent(A component, Runnable onShow) { return bindToComponent(component, onShow, null); } static Map<String, Font> loadFont_cached_cache = new HashMap(); static synchronized Font loadFont_cached(String snippetID) { try { snippetID = formatSnippetID(snippetID); Font f = loadFont_cached_cache.get(snippetID); if (f == null) loadFont_cached_cache.put(snippetID, f = loadFont(snippetID, 12f)); return f; } catch (Exception __e) { throw rethrow(__e); } } static synchronized Font loadFont_cached(String snippetID, float size) { try { return loadFont_cached(snippetID).deriveFont(size); } catch (Exception __e) { throw rethrow(__e); } } static float getSwingFontScale() { return or((Float) vm_generalMap_get("swingFontScale_value"), 1f); } static Object nuObject(String className, Object... args) { try { return nuObject(classForName(className), args); } catch (Exception __e) { throw rethrow(__e); } } // too ambiguous - maybe need to fix some callers /*static O nuObject(O realm, S className, O... args) { ret nuObject(_getClass(realm, className), args); }*/ static <A> A nuObject(Class<A> c, Object... args) { try { if (args.length == 0) return nuObjectWithoutArguments(c); // cached! Constructor m = nuObject_findConstructor(c, args); makeAccessible(m); return (A) m.newInstance(args); } catch (Exception __e) { throw rethrow(__e); } } static Constructor nuObject_findConstructor(Class c, Object... args) { for (Constructor m : c.getDeclaredConstructors()) { if (!nuObject_checkArgs(m.getParameterTypes(), args, false)) continue; return m; } throw fail("Constructor " + c.getName() + getClasses(args) + " not found" + (args.length == 0 && (c.getModifiers() & java.lang.reflect.Modifier.STATIC) == 0 ? " - hint: it's a non-static class!" : "")); } static boolean nuObject_checkArgs(Class[] types, Object[] args, boolean debug) { if (types.length != args.length) { if (debug) System.out.println("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) { if (debug) System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]); return false; } return true; } static <A> A firstWithClassShortNamed(String shortName, Iterable<A> l) { if (l != null) for (A o : l) if (eq(shortClassName(o), shortName)) return o; return null; } static <A> A firstWithClassShortNamed(String shortName, A[] l) { if (l != null) for (A o : l) if (eq(shortClassName(o), shortName)) return o; return null; } static JMenuItem jMenuItem(final String text) { return jmenuItem(text); } static JMenuItem jMenuItem(String text, Object r) { return jmenuItem(text, r); } static Pair<String, Integer> jmenu_autoMnemonic(String s) { int i = indexOf(s, '&'); if (i >= 0 && i < l(s) && isLetterOrDigit(s.charAt(i+1))) return pair(substring(s, 0, i) + substring(s, i+1), (int) s.charAt(i+1)); return pair(s, 0); } static JMenuItem disableMenuItem(final JMenuItem mi) { if (mi != null) { swing(() -> { mi.setEnabled(false); }); } return mi; } static ActionListener actionListenerInNewThread(final Object runnable) { return actionListenerInNewThread(runnable, null); } static ActionListener actionListenerInNewThread(final Object runnable, final Object instanceToHold) { if (runnable instanceof ActionListener) return (ActionListener) runnable; return new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent _evt) { try { startThread("Action Listener", new Runnable() { public void run() { try { AutoCloseable __1 = holdInstance(instanceToHold); try { callF(runnable); } finally { _close(__1); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "AutoCloseable __1 = holdInstance(instanceToHold); try {\r\n callF(runnable..."; }}); } catch (Throwable __e) { messageBox(__e); }}}; } static JMenuItem directJMenuItem(Action a) { return new JMenuItem(a) { public Dimension getMaximumSize() { return new Dimension(super.getPreferredSize().width, super.getMaximumSize().height); } }; } static JMenuItem directJMenuItem(String text, Object action) { return directJMenuItem(abstractAction(text, action)); } static JMenuBar addMenuBar(final Component c) { return swing(new F0<JMenuBar>() { public JMenuBar get() { try { RootPaneContainer f = getPossiblyInternalFrame(c); if (f == null) return null; JMenuBar bar = (JMenuBar) (call(f, "getJMenuBar")); if (bar == null) { setMenuBar(f, bar = new JMenuBar()); revalidate((Component) f); } return bar; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "RootPaneContainer f = getPossiblyInternalFrame(c);\r\n if (f == null) null;\r..."; }}); } static Runnable asRunnable(Object o) { return toRunnable(o); } static void _inheritThreadInfo(Object info) { _threadInheritInfo(info); } static boolean headless() { return isHeadless(); } static boolean containsNewLine(String s) { return contains(s, '\n'); // screw \r, nobody needs it } static <A> List<A> replace(List<A> l, A a, A b) { for (int i = 0; i < l(l); i++) if (eq(l.get(i), a)) l.set(i, b); return l; } static <A> List<A> replace(A a, A b, List<A> l) { return replace(l, a, b); } // replace all occurrences of a in s with b static String replace(String s, String a, String b) { return s == null ? null : a == null || b == null ? s : s.replace(a, b); } static String replace(String s, char a, char b) { return s == null ? null : s.replace(a, b); } static Map<JFrame, Boolean> myFrames_list = weakHashMap(); static List<JFrame> myFrames() { return swing(new F0<List<JFrame>>() { public List<JFrame> get() { try { return keysList(myFrames_list); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return keysList(myFrames_list);"; }}); } static Map<Component, String> componentID_map = weakHashMap(); static String componentID(Component c) { return c == null ? null : componentID_map.get(c); } static BufferedImage imageIO_readURL(String url) { try { return ImageIO.read(new URL(url)); } catch (Exception __e) { throw rethrow(__e); } } static File imageSnippetsCacheDir() { return javaxCachesDir("Image-Snippets"); } static String snippetImageURL_http(String snippetID) { return snippetImageURL_http(snippetID, "png"); } static String snippetImageURL_http(String snippetID, String contentType) { return replacePrefix("https://", "http://", snippetImageURL(snippetID, contentType)).replace(":8443", ":8080"); } static BufferedImage loadBufferedImageFile(File file) { try { return isFile(file) ? ImageIO.read(file) : null; } catch (Exception __e) { throw rethrow(__e); } } // f : Matcher -> S static String regexReplaceIC(String s, String pat, Object f) { return regexReplace(regexpMatcherIC(pat, s), f); } static String regexReplaceIC(String s, String pat, String replacement) { return regexpReplaceIC_direct(s, pat, replacement); } static Window getWindow(Object o) { if (!(o instanceof Component)) return null; return swing(() -> { Component c = (Component) o; while (c != null) { if (c instanceof Window) return ((Window) c); c = c.getParent(); } return null; }); } static boolean showAnimationInTopRightCorner_alwaysOnTop = true; static boolean showAnimationInTopRightCorner_on = true; // automatically switches to AWT thread for you // text is optional text below image static JWindow showAnimationInTopRightCorner(String imageID, String text) { if (isHeadless() || !showAnimationInTopRightCorner_on) return null; return showAnimationInTopRightCorner(imageIcon(imageID), text); } static JWindow showAnimationInTopRightCorner(final Image image, final String text) { if (image == null || isHeadless() || !showAnimationInTopRightCorner_on) return null; return showAnimationInTopRightCorner(imageIcon(image), text); } static JWindow showAnimationInTopRightCorner(final ImageIcon imageIcon, final String text) { if (isHeadless() || !showAnimationInTopRightCorner_on) return null; return (JWindow) swingAndWait(new F0<Object>() { public Object get() { try { JLabel label = new JLabel(imageIcon); if (nempty(text)) { label.setText(text); label.setVerticalTextPosition(SwingConstants.BOTTOM); label.setHorizontalTextPosition(SwingConstants.CENTER); } final JWindow window = showInTopRightCorner(label); onClick(label, new Runnable() { public void run() { try { window.dispose() ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "window.dispose()"; }}); if (showAnimationInTopRightCorner_alwaysOnTop) window.setAlwaysOnTop(true); return window; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JLabel label = new JLabel(imageIcon);\r\n if (nempty(text)) {\r\n label.s..."; }}); } static JWindow showAnimationInTopRightCorner(final String imageID) { return showAnimationInTopRightCorner(imageID, ""); } static JWindow showAnimationInTopRightCorner(String imageID, double seconds) { return showAnimationInTopRightCorner(imageID, "", seconds); } static JWindow showAnimationInTopRightCorner(String imageID, String text, double seconds) { if (isHeadless()) return null; return disposeWindowAfter(iround(seconds*1000), showAnimationInTopRightCorner(imageID, text)); } static JWindow showAnimationInTopRightCorner(BufferedImage img, String text, double seconds) { return disposeWindowAfter(iround(seconds*1000), showAnimationInTopRightCorner(img, text)); } static String loadTextFileFromZipFile(File inZip, String fileName) { try { if (!fileExists(inZip)) return null; try { ZipFile zip = new ZipFile(inZip); try { return loadTextFileFromZipFile(zip, fileName); } finally { _close(zip); }} catch (Throwable e) { throw fail(f2s(inZip), e); } } catch (Exception __e) { throw rethrow(__e); } } static String loadTextFileFromZipFile(ZipFile zip, String fileName) { try { ZipEntry entry = zip.getEntry(fileName); if (entry == null) return null; InputStream fin = zip.getInputStream(entry); try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); copyStream(fin, baos); return fromUTF8(baos.toByteArray()); } finally { _close(fin); }} catch (Exception __e) { throw rethrow(__e); } } static File getBytecodePathForClass(Object o) { return getBytecodePathForClass(_getClass(o)); } static File getBytecodePathForClass(Class c) { try { return c == null ? null : new File(c.getProtectionDomain().getCodeSource().getLocation().toURI()); } catch (Exception __e) { throw rethrow(__e); } } static String snippetImageURL(long snippetID) { return snippetImageURL(fsI(snippetID)); } static String snippetImageURL(String snippetID) { return snippetImageURL(snippetID, "png"); } static String snippetImageURL(String snippetID, String contentType) { if (snippetID == null || isURL(snippetID)) return snippetID; long id = parseSnippetID(snippetID); String url; if (isImageServerSnippet(id)) url = imageServerLink(id); else //url = "http://eyeocr.sourceforge.net/filestore/filestore.php?cmd=serve&file=blob_" + id + "&contentType=image/" + contentType; url = "https://botcompany.de/img/" + id; return url; } static volatile boolean muricaPassword_pretendNotAuthed = false; static String muricaPassword() { if (muricaPassword_pretendNotAuthed) return null; return trim(loadTextFile(muricaPasswordFile())); } static String fileServerURL() { return "https://botcompany.de/files"; } public static File mkdirsFor(File file) { return mkdirsForFile(file); } static void copyStreamWithPrints(InputStream in, OutputStream out, String pat) { try { byte[] buf = new byte[65536]; int total = 0; while (true) { int n = in.read(buf); if (n <= 0) return; out.write(buf, 0, n); if ((total+n)/100000 > total/100000) print(pat.replace("{*}", str(roundDownTo(100000, total)))); total += n; } } catch (Exception __e) { throw rethrow(__e); } } static File renameFile_assertTrue(File a, File b) { try { if (a.equals(b)) return b; // no rename necessary if (!a.exists()) throw fail("Source file not found: " + f2s(a)); if (b.exists()) throw fail("Target file exists: " + f2s(b)); mkdirsForFile(b); if (!a.renameTo(b)) throw fail("Can't rename " + f2s(a) + " to " + f2s(b)); return b; } catch (Exception __e) { throw rethrow(__e); } } static List<Component> getComponents(final Component c) { return !(c instanceof Container) ? emptyList() : asList(swing(new F0<Component[]>() { public Component[] get() { try { return ((Container) c).getComponents(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return ((Container) c).getComponents();"; }})); } static String[] toStringArray(Collection<String> c) { String[] a = new String[l(c)]; Iterator<String> it = c.iterator(); for (int i = 0; i < l(a); i++) a[i] = it.next(); return a; } static String[] toStringArray(Object o) { if (o instanceof String[]) return (String[]) o; else if (o instanceof Collection) return toStringArray((Collection<String>) o); else throw fail("Not a collection or array: " + getClassName(o)); } static Object pcallFAll_returnFirstNotNull(Collection l, Object... args) { if (l != null) for (Object f : cloneList(l)) { var __1= pcallF(f, args); if (__1 != null) return __1; } return null; } static Object pcallFAll_returnFirstNotNull(Iterator it, Object... args) { while (it.hasNext()) { var __2= pcallF(it.next(), args); if (__2 != null) return __2; } return null; } static String assertIsIdentifier(String s) { if (!isIdentifier(s)) throw fail("Not an identifier: " + quote(s)); return s; } static String assertIsIdentifier(String msg, String s) { if (!isIdentifier(s)) throw fail(msg + " - Not an identifier: " + quote(s)); return s; } static boolean isSubclass(Class a, Class b) { return a != null && b != null && b.isAssignableFrom(a); } static <A> void listThreadLocalAdd(ThreadLocal<List<A>> tl, A a) { List<A> l = tl.get(); if (l == null) tl.set(l = new ArrayList()); l.add(a); } static <A> A listThreadLocalPopLast(ThreadLocal<List<A>> tl) { List<A> l = tl.get(); if (l == null) return null; A a = popLast(l); if (empty(l)) tl.set(null); return a; } static boolean isAllUpperCase(String s) { return hasLettersAllUpperCase(s); } static boolean isUpperCaseLetter(char c) { return Character.isUpperCase(c); } static Object[] asArray(List l) { return toObjectArray(l); } static <A> A[] asArray(Class<A> type, List l) { return (A[]) l.toArray((Object[]) Array.newInstance(type, l.size())); } static boolean isMenuSeparatorIndicator(Object o) { return eqOneOf(o, "***", "---", "===", ""); } static int menuItemCount(JMenu menu) { return menu == null ? 0 : swing(() -> menu.getItemCount()); } static boolean isRunnableX(Object o) { if (o == null) return false; if (o instanceof String) return hasMethod(mc(), (String) o); return o instanceof Runnable || hasMethod(o, "get"); } static String unCurlyBracket(String s) { return tok_unCurlyBracket(s); } static boolean isCurlyBracketed(String s) { return isCurlyBraced(s); } static <A extends JComponent> A setEnabled(A c, boolean enable) { if (c != null) { swing(() -> { c.setEnabled(enable); }); } return c; } static <A extends JComponent> A setEnabled(boolean enable, A c) { return setEnabled(c, enable); } static void setEnabled(boolean enable, JComponent... l) { for (var c : unnullForIteration(l)) setEnabled(c, enable); } static Set vm_generalWeakSet(Object name) { synchronized(vm_generalMap()) { Set set = (Set) (vm_generalMap_get(name)); if (set == null) vm_generalMap_put(name, set = newWeakHashSet()); return set; } } static ThreadLocal<Boolean> addInternalFrame_dontSelect = new ThreadLocal(); static ThreadLocal<Integer> addInternalFrame_layer = new ThreadLocal(); static ThreadLocal<Boolean> addInternalFrame_toBack = new ThreadLocal(); static JInternalFrame addInternalFrame(final JDesktopPane desktop, final String title, final int x, final int y, final int w, final int h) { return addInternalFrame(desktop, title, x, y, w, h, null); } static JInternalFrame addInternalFrame(final JDesktopPane desktop, final String title, final int x, final int y, final int w, final int h, final Component contents) { return addInternalFrame(desktop, title, rect(x, y, w, h), contents); } static JInternalFrame addInternalFrame(final JDesktopPane desktop, final String title, final Component contents) { return addInternalFrame(desktop, title, null, contents); } static JInternalFrame addInternalFrame(final JDesktopPane desktop, final String title, final Rect r, final Component contents) { final boolean dontSelect = isTrue(optParam(addInternalFrame_dontSelect)); final boolean toBack = isTrue(optParam(addInternalFrame_toBack)); final Integer layer = optParam(addInternalFrame_layer); return swing(new F0<JInternalFrame>() { public JInternalFrame get() { try { JInternalFrame frame; if (contents instanceof JInternalFrame) frame = (JInternalFrame) contents; else { frame = jInternalFrame(title); setInternalFrameContents(frame, contents); } frame.setVisible(true); desktop.add(frame, layer); if (r != null) setBounds(frame, r); else internalFrameDefaultPosition(frame); if (dontSelect) if (toBack) frame.toBack(); else frame.toFront(); else frame.setSelected(true); return fixInternalFrame(frame); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JInternalFrame frame;\r\n if (contents instanceof JInternalFrame)\r\n fra..."; }}); } static JInternalFrame addInternalFrame(JDesktopPane desktop, String title) { return addInternalFrame(desktop, title, jpanel()); } static JInternalFrame minInternalFrameWidth(final JInternalFrame frame, final int w) { { swing(() -> { if (frame != null && frame.getWidth() < w) frame.setSize(w, frame.getHeight()); }); } return frame; } static JInternalFrame minInternalFrameWidth(int w, JInternalFrame frame) { return minInternalFrameWidth(frame, w); } static <A extends Component> A packInternalFrameVertically(A c) { return packInternalFrameVertically(-1, c); } static <A extends Component> A packInternalFrameVertically(int width, A c) { final JInternalFrame win = getInternalFrame(c); if (win == null) return c; final int w = width < 0 ? win.getWidth() : width; { swing(() -> { win.pack(); win.setSize(w, win.getHeight()); fixInternalFrame(win); }); } return c; } static JInternalFrame centerInternalFrame(final JInternalFrame f) { { swing(() -> { Container c = f.getParent(); if (c != null) { //print("Container type: " + className(c) + ", bounds: " + c.getBounds()); f.setLocation((c.getWidth()-f.getWidth())/2, (c.getHeight()-f.getHeight())/2); } }); } return f; } static JInternalFrame centerInternalFrame(final int w, final int h, final JInternalFrame f) { { swing(() -> { f.setSize(w, h); }); } return centerInternalFrame(f); } static int packFrame_minw = 150, packFrame_minh = 50; static <A extends Component> A packFrame(final A c) { { swing(() -> { Window w = getWindow(c); if (w != null) { w.pack(); int maxW = getScreenWidth()-50, maxH = getScreenHeight()-50; w.setSize( min(maxW, max(w.getWidth(), packFrame_minw)), min(maxH, max(w.getHeight(), packFrame_minh))); } }); } return c; } static JFrame packFrame(ButtonGroup g) { return packFrame(getFrame(g)); } static JFrame showFrame() { return makeFrame(); } static JFrame showFrame(Object content) { return makeFrame(content); } static JFrame showFrame(String title) { return makeFrame(title); } static JFrame showFrame(String title, Object content) { return makeFrame(title, content); } static JFrame showFrame(final JFrame f) { if (f != null) { swing(() -> { if (frameTooSmall(f)) frameStandardSize(f); if (!f.isVisible()) f.setVisible(true); // XXX if (f.getState() == Frame.ICONIFIED) f.setState(Frame.NORMAL); }); } return f; } // make or update frame static JFrame showFrame(String title, Object content, JFrame frame) { if (frame == null) return showFrame(title, content); else { frame.setTitle(title); setFrameContents(frame, content); return frame; } } static JPanel marginPanel() { return jtransparent(borderLayoutPanel()); } static <A, B extends Collection<A>> void forEachLevel2(Iterable<B> l, IVF1<A> f) { if (l != null) for (B b : l) forEach(b, f); } static <A, B extends Collection<A>> void forEachLevel2(IVF1<A> f, Iterable<B> l) { forEachLevel2(f, l); } static Dimension getMinimumSize(final Component c) { return c == null ? null : swing(new F0<Dimension>() { public Dimension get() { try { return c.getMinimumSize(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return c.getMinimumSize();"; }}); } // c = Component or something implementing swing() static JComponent wrap(Object swingable) { return _recordNewSwingComponent(wrap_2(swingable)); } static JComponent wrap_2(Object swingable) { if (swingable == null) return null; JComponent c; if (swingable instanceof Component) c = componentToJComponent((Component) swingable); else if (swingable instanceof Swingable) c = componentToJComponent(((Swingable) swingable).visualize()); else c = componentToJComponent((Component) callOpt(swingable, "swing")); if (c instanceof JTable || c instanceof JList || c instanceof JTextArea || c instanceof JEditorPane || c instanceof JTextPane || c instanceof JTree) return jscroll(c); return c == null ? jlabel(str(swingable)) : c; } static <A extends Component> A jPreferWidth(int w, A c) { { swing(() -> { Dimension size = c.getPreferredSize(); c.setPreferredSize(new Dimension(/*max(w, size.width) ??? */w, size.height)); }); } return c; } static JComponent componentToJComponent(Component c) { if (c instanceof JComponent) return (JComponent) c; if (c instanceof JFrame) return ((JFrame) c).getRootPane(); if (c == null) return null; throw fail("boohoo " + getClassName(c)); } static Component wrapForSmartAdd(Object o) { if (o == null) return jpanel(); if (o instanceof String) return jlabel((String) o); return wrap(o); } static boolean hasMethod(Object o, String method, Object... args) { return findMethod_cached(o, method, args) != null; } static boolean newButton_autoToolTip = true; // action can be Runnable or a function name static JButton newButton(final String text, final Object action) { return swing(new F0<JButton>() { public JButton get() { try { String text2 = dropPrefix("[disabled] ", text); JButton btn = basicJButton(text2); if (l(text2) < l(text)) btn.setEnabled(false); if (newButton_autoToolTip) { btn.setToolTipText(btn.getText()); //onChangeAndNow(btn, r { btn.setToolTipText(btn.getText()) }); } // submitButtonOnEnter(btn); // test this first if (action != null) btn.addActionListener(actionListener(action, btn)); return btn; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "S text2 = dropPrefix(\"[disabled] \", text);\r\n JButton btn = basicJButton(te..."; }}); } static boolean isInstanceOf(Object o, Class type) { return type.isInstance(o); } static List<Component> allChildren(Component c) { return childrenOfType(c, Component.class); } static void onEnterIfTextField(Component c, Runnable action) { if (action == null) return; if (c instanceof JTextField) onEnter(((JTextField) c), action); else if (c instanceof JComboBox) onEnter(((JComboBox) c), action); } static Object[] flattenArray2(Object... a) { List l = new ArrayList(); if (a != null) for (Object x : a) if (x instanceof Object[]) l.addAll(asList((Object[]) x)); else if (x instanceof Collection) l.addAll((Collection) x); else l.add(x); return asObjectArray(l); } static <A> List<A> withoutNulls(Iterable<A> l) { if (l instanceof List) if (!containsNulls((List) l)) return ((List) l); List<A> l2 = new ArrayList(); for (A a : l) if (a != null) l2.add(a); return l2; } static <A, B> Map<A, B> withoutNulls(Map<A, B> map) { Map<A, B> map2 = similarEmptyMap(map); for (A a : keys(map)) if (a != null) { B b = map.get(a); if (b != null) map2.put(a, b); } return map2; } static <A> List<A> withoutNulls(A[] l) { List<A> l2 = new ArrayList(); if (l != null) for (A a : l) if (a != null) l2.add(a); return l2; } static boolean loadBufferedImageFixingGIFs_debug = false; static ThreadLocal<Var<byte[]>> loadBufferedImageFixingGIFs_output = new ThreadLocal(); static Image loadBufferedImageFixingGIFs(File file) { try { if (!file.exists()) return null; // Load anything but GIF the normal way if (!isGIF(file)) return ImageIO.read(file); if (loadBufferedImageFixingGIFs_debug) print("loadBufferedImageFixingGIFs" + ": checking gif"); // Get GIF reader ImageReader reader = ImageIO.getImageReadersByFormatName("gif").next(); // Give it the stream to decode from reader.setInput(ImageIO.createImageInputStream(file)); int numImages = reader.getNumImages(true); // Get 'metaFormatName'. Need first frame for that. IIOMetadata imageMetaData = reader.getImageMetadata(0); String metaFormatName = imageMetaData.getNativeMetadataFormatName(); // Find out if GIF is bugged boolean foundBug = false; for (int i = 0; i < numImages && !foundBug; i++) { // Get metadata IIOMetadataNode root = (IIOMetadataNode)reader.getImageMetadata(i).getAsTree(metaFormatName); // Find GraphicControlExtension node int nNodes = root.getLength(); for (int j = 0; j < nNodes; j++) { org.w3c.dom.Node node = root.item(j); if (node.getNodeName().equalsIgnoreCase("GraphicControlExtension")) { // Get delay value String delay = ((IIOMetadataNode)node).getAttribute("delayTime"); // Check if delay is bugged if (Integer.parseInt(delay) == 0) { foundBug = true; } break; } } } if (loadBufferedImageFixingGIFs_debug) print("loadBufferedImageFixingGIFs" + ": " + f2s(file) + " foundBug=" + foundBug); // Load non-bugged GIF the normal way Image image; if (!foundBug) { image = Toolkit.getDefaultToolkit().createImage(f2s(file)); } else { // Prepare streams for image encoding ByteArrayOutputStream baoStream = new ByteArrayOutputStream(); { ImageOutputStream ios = ImageIO.createImageOutputStream(baoStream); try { // Get GIF writer that's compatible with reader ImageWriter writer = ImageIO.getImageWriter(reader); // Give it the stream to encode to writer.setOutput(ios); writer.prepareWriteSequence(null); for (int i = 0; i < numImages; i++) { // Get input image BufferedImage frameIn = reader.read(i); // Get input metadata IIOMetadataNode root = (IIOMetadataNode)reader.getImageMetadata(i).getAsTree(metaFormatName); // Find GraphicControlExtension node int nNodes = root.getLength(); for (int j = 0; j < nNodes; j++) { org.w3c.dom.Node node = root.item(j); if (node.getNodeName().equalsIgnoreCase("GraphicControlExtension")) { // Get delay value String delay = ((IIOMetadataNode)node).getAttribute("delayTime"); // Check if delay is bugged if (Integer.parseInt(delay) == 0) { // Overwrite with a valid delay value ((IIOMetadataNode)node).setAttribute("delayTime", "10"); } break; } } // Create output metadata IIOMetadata metadata = writer.getDefaultImageMetadata(new ImageTypeSpecifier(frameIn), null); // Copy metadata to output metadata metadata.setFromTree(metadata.getNativeMetadataFormatName(), root); // Create output image IIOImage frameOut = new IIOImage(frameIn, null, metadata); // Encode output image writer.writeToSequence(frameOut, writer.getDefaultWriteParam()); } writer.endWriteSequence(); } finally { _close(ios); }} // Create image using encoded data byte[] data = baoStream.toByteArray(); setVar(loadBufferedImageFixingGIFs_output.get(), data); if (loadBufferedImageFixingGIFs_debug) print("Data size: " + l(data)); image = Toolkit.getDefaultToolkit().createImage(data); } return image; } catch (Exception __e) { throw rethrow(__e); } } static File fileInSameDir(File f, String newName) { return newFile(parentFile(f), newName); } static Font loadFont(String snippetID) { try { return loadFont(snippetID, 12f); } catch (Exception __e) { throw rethrow(__e); } } static Font loadFont(InputStream in) { try { return Font.createFont(Font.TRUETYPE_FONT, in); } catch (Exception __e) { throw rethrow(__e); } } static Font loadFont(String snippetID, float fontSize) { return loadFont(loadLibrary(snippetID), fontSize); } static Font loadFont(File f, float fontSize) { try { return Font.createFont(Font.TRUETYPE_FONT, f).deriveFont(fontSize); } catch (Exception __e) { throw rethrow(__e); } } static Font loadFont(InputStream in, float fontSize) { try { return Font.createFont(Font.TRUETYPE_FONT, in).deriveFont(fontSize); } catch (Exception __e) { throw rethrow(__e); } } static Map<String, Class> classForName_cache = synchroHashMap(); static Class classForName(String name) { return classForName(name, null); } static Class classForName(String name, Object classFinder) { // first clause is when we're in class init if (classForName_cache == null || classFinder != null) return classForName_uncached(name, classFinder); Class c = classForName_cache.get(name); if (c == null) classForName_cache.put(name, c = classForName_uncached(name, null)); return c; } static Class classForName_uncached(String name, Object classFinder) { try { if (classFinder != null) return (Class) callF(classFinder, name); return Class.forName(name); } catch (Exception __e) { throw rethrow(__e); } } static Map<Class, Constructor> nuObjectWithoutArguments_cache = newDangerousWeakHashMap(); static Object nuObjectWithoutArguments(String className) { try { return nuObjectWithoutArguments(classForName(className)); } catch (Exception __e) { throw rethrow(__e); } } static <A> A nuObjectWithoutArguments(Class<A> c) { try { if (nuObjectWithoutArguments_cache == null) // in class init return (A) nuObjectWithoutArguments_findConstructor(c).newInstance(); Constructor m = nuObjectWithoutArguments_cache.get(c); if (m == null) nuObjectWithoutArguments_cache.put(c, m = nuObjectWithoutArguments_findConstructor(c)); return (A) m.newInstance(); } catch (Exception __e) { throw rethrow(__e); } } static Constructor nuObjectWithoutArguments_findConstructor(Class c) { for (Constructor m : c.getDeclaredConstructors()) if (empty(m.getParameterTypes())) { makeAccessible(m); return m; } throw fail("No default constructor found in " + c.getName()); } static RootPaneContainer getPossiblyInternalFrame(Component c) { JInternalFrame f = getInternalFrame(c); if (f != null) return f; return optCast(RootPaneContainer.class, getWindow(c)); } static void setMenuBar(final JMenuBar mb, final RootPaneContainer f) { { swing(() -> { call(f, "setJMenuBar", mb); revalidate((Component) f); }); } } static void setMenuBar(RootPaneContainer f, JMenuBar mb) { setMenuBar(mb, f); } static <A, B> List<A> keysList(Map<A, B> map) { return cloneListSynchronizingOn(keys(map), map); } static boolean isFile(File f) { return f != null && f.isFile(); } static boolean isFile(String path) { return isFile(newFile(path)); } // f : Matcher -> S static String regexReplace(String s, String pat, Object f) { Matcher m = Pattern.compile(pat).matcher(s); return regexReplace(m, f); } static String regexReplace(String s, String pat, String replacement) { return regexpReplace_direct(s, pat, replacement); } static String regexReplace(Matcher m, Object f) { StringBuffer buf = new StringBuffer(); while (m.find()) m.appendReplacement(buf, m.quoteReplacement(str(callF(f, m)))); m.appendTail(buf); return str(buf); } static String regexReplace(String s, String pat, IF1<Matcher, String> f) { return regexReplace(s, pat, (Object) f); } static Matcher regexpMatcherIC(String pat, String s) { return compileRegexpIC(pat).matcher(unnull(s)); } static String regexpReplaceIC_direct(String s, String pat, String replacement) { Matcher m = regexpIC(pat, s); StringBuffer buf = new StringBuffer(); while (m.find()) m.appendReplacement(buf, replacement); m.appendTail(buf); return str(buf); } static JWindow showInTopRightCorner(Component c) { return swing(() -> { JWindow w = new JWindow(); w.add(c); w.pack(); moveToTopRightCorner(w); w.setVisible(true); return w; }); } static <A extends JComponent> A onClick(final A c, final Object runnable) { if (c != null) { swing(() -> { c.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { callF(runnable, e); } }); }); } return c; } // re-interpreted for buttons static void onClick(JButton btn, final Object runnable) { onEnter(btn, runnable); } static <A extends Window> A disposeWindowAfter(int delay, final A w) { if (w != null) swingLater(delay, new Runnable() { public void run() { try { w.dispose(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "w.dispose();"; }}); return w; } static <A extends Window> A disposeWindowAfter(A w, double seconds) { return disposeWindowAfter(toMS_int(seconds), w); } static <A extends Window> A disposeWindowAfter(double seconds, A w) { return disposeWindowAfter(w, seconds); } static String fromUTF8(byte[] bytes) { return fromUtf8(bytes); } static String imageServerLink(String md5OrID) { if (possibleMD5(md5OrID)) return "https://botcompany.de/images/md5/" + md5OrID; return imageServerLink(parseSnippetID(md5OrID)); } static String imageServerLink(long id) { return "https://botcompany.de/images/" + id; } static File muricaPasswordFile() { return new File(javaxSecretDir(), "murica/muricaPasswordFile"); } // TODO: optimize to x-(x%n) in case that's the same thing // (or x-mod(x,n)?) static int roundDownTo(int n, int x) { return x/n*n; } static long roundDownTo(long n, long x) { return x/n*n; } static <A> A popLast(List<A> l) { return liftLast(l); } static <A> List<A> popLast(int n, List<A> l) { return liftLast(n, l); } static boolean hasLettersAllUpperCase(String s) { return hasLetters(s) && !containsLowerCase(s); } static String tok_unCurlyBracket(String s) { return isCurlyBraced(s) ? join(dropFirstThreeAndLastThree(javaTok(s))) : s; } static boolean isCurlyBraced(String s) { List<String> tok = tok_combineCurlyBrackets_keep(javaTok(s)); return l(tok) == 3 && startsWithAndEndsWith(tok.get(1), "{", "}"); } static Rect rect(int x, int y, int w, int h) { return new Rect(x, y, w, h); } static Rect rect(Pt p, int w, int h) { return new Rect(p.x, p.y, w, h); } static Rect rect(int w, int h) { return new Rect(0, 0, w, h); } static boolean jInternalFrame_iconifiable = true; static JInternalFrame jInternalFrame() { return jInternalFrame(""); } static JInternalFrame jInternalFrame(final String title) { return swing(new F0<JInternalFrame>() { public JInternalFrame get() { try { JInternalFrame f = new JInternalFrame(title, true, true, true, jInternalFrame_iconifiable); f.setVisible(true); return f; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JInternalFrame f = new JInternalFrame(title, true, true, true, jInternalFrame..."; }}); } static void setInternalFrameContents(final Component c, final Object contents) { { swing(() -> { JInternalFrame frame = getInternalFrame(c); if (frame == null) return; frame.getContentPane().removeAll(); frame.getContentPane().setLayout(new BorderLayout()); if (contents != null) frame.getContentPane().add(wrap(contents)); revalidate(frame); }); } } static <A extends Component> A setBounds(final int x, final int y, final int w, final int h, final A a) { if (a != null) { swing(() -> { a.setBounds(x, y, w, h); }); } return a; } static <A extends Component> A setBounds(A a, Rect r) { if (a != null && r != null) { swing(() -> { a.setBounds(toRectangle(r)); }); } return a; } static <A extends Component> A setBounds(A a, Rectangle r) { if (a != null && r != null) { swing(() -> { a.setBounds(r); }); } return a; } static <A extends Component> A setBounds(Rect r, A a) { return setBounds(a, r); } static <A extends Component> A setBounds(A a, int x, int y, int w, int h) { return setBounds(x, y, w, h, a); } static void internalFrameDefaultPosition(JInternalFrame f) { f.setSize(500, 300); centerInternalFrame(f); } static int fixInternalFrame_borderTopLeft = 0; static int fixInternalFrame_borderBottomRight = 40; // for title bar static JInternalFrame fixInternalFrame(final JInternalFrame f) { return swing(new F0<JInternalFrame>() { public JInternalFrame get() { try { Container c = f.getParent(); if (c == null) return f; Rect r = toRect(f.getBounds()); int a = fixInternalFrame_borderTopLeft, b = fixInternalFrame_borderBottomRight; Rect outer = new Rect(a, a, c.getWidth()-b, c.getHeight()-b); if (!rectContains(outer, r)) f.setLocation( max(a, min(r.x, outer.x2())), max(a, min(r.y, outer.y2()))); if (r.w > c.getWidth() || r.h > c.getHeight()) f.setSize(c.getWidth()-a, c.getHeight()-a); return f; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Container c = f.getParent();\r\n if (c == null) ret f;\r\n Rect r = toRect(..."; }}); } static int getScreenWidth() { return getScreenSize().width; } static int getScreenHeight() { return getScreenSize().height; } static String makeFrame_defaultIcon; static boolean makeFrame_hideConsole = false; static ThreadLocal<VF1<JFrame>> makeFrame_post = new ThreadLocal(); static JFrame makeFrame() { return makeFrame((Component) null); } static JFrame makeFrame(Object content) { return makeFrame(programTitle(), content); } static JFrame makeFrame(String title) { return makeFrame(title, null); } static JFrame makeFrame(String title, Object content) { return makeFrame(title, content, true); } static JFrame makeFrame(final String title, final Object content, final boolean showIt) { final VF1<JFrame> post = optParam(makeFrame_post); return swing(new F0<JFrame>() { public JFrame get() { try { if (getFrame(content) != null) return getFrame(setFrameTitle((Component) content, title)); final JFrame frame = new JFrame(title); if (makeFrame_defaultIcon != null) setFrameIconLater(frame, makeFrame_defaultIcon); _initFrame(frame); Component wrapped = wrap(content); if (wrapped != null) frame.getContentPane().add(wrapped); frame.setBounds(defaultNewFrameBounds()); callF(post, frame); if (showIt) frame.setVisible(true); //callOpt(content, "requestFocus"); //exitOnFrameClose(frame); if (showIt && makeFrame_hideConsole) { hideConsole(); makeFrame_hideConsole = false; } return frame; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (getFrame(content) != null)\r\n ret getFrame(setFrameTitle((Component) ..."; }}); } static boolean frameTooSmall(JFrame frame) { return frame.getWidth() < 100 || frame.getHeight() < 50; } static void frameStandardSize(JFrame frame) { frame.setBounds(300, 100, 500, 400); } static void setFrameContents(final Component c, final Object contents) { swing(() -> { JFrame frame = getFrame(c); if (frame == null) return; frame.getContentPane().removeAll(); frame.getContentPane().setLayout(new BorderLayout()); frame.getContentPane().add(wrap(contents)); revalidate(frame); }); } static <A extends JComponent> A jtransparent(final A a) { { swing(() -> { a.setOpaque(false); }); } return a; } static JPanel borderLayoutPanel() { return jpanel(new BorderLayout()); } static <A> void forEach(Iterable<A> l, IVF1<A> f) { if (f != null && l != null) for (A a : l) callF(f, a); } static <A> void forEach(IVF1<A> f, Iterable<A> l) { forEach(l, f); } static <A> void forEach(A[] l, IVF1<A> f) { if (f != null && l != null) for (A a : l) callF(f, a); } static <A> void forEach(IVF1<A> f, A[] l) { forEach(l, f); } static <A, B> void forEach(Map<A, B> map, IVF2<A, B> f) { for (Map.Entry<? extends A, ? extends B> __0 : _entrySet( map)) { A a = __0.getKey(); B b = __0.getValue(); f.get(a, b); } } static <A extends Component> A _recordNewSwingComponent(A c) { if (c != null) callF((Object) vm_generalMap_get("newSwingComponentRegistry"), (Object) c); return c; } static JLabel jlabel(final String text) { return swingConstruct(BetterLabel.class, text); } static JLabel jlabel() { return jlabel(" "); } static JButton basicJButton(String text) { return swing(() -> new JButton(text)); } static <A> List<A> childrenOfType(Component c, Class<A> theClass) { List<A> l = new ArrayList(); scanForComponents(c, theClass, l); return l; } static <A> List<A> childrenOfType(Class<A> theClass, Component c) { return childrenOfType(c, theClass); } static Object[] asObjectArray(Collection l) { return toObjectArray(l); } static boolean containsNulls(Collection c) { return contains(c, null); } static byte[] isGIF_magic = bytesFromHex("47494638"); // Actual signature is longer, but we're lazy static boolean isGIF(byte[] data) { return byteArrayStartsWith(data, isGIF_magic); } static boolean isGIF(File f) { return isGIF(loadBeginningOfBinaryFile(f, l(isGIF_magic))); } static <A> void setVar(IVar<A> v, A value) { if (v != null) v.set(value); } static <A> IVF1<A> setVar(IVar<A> v) { return a -> { if (v != null) v.set(a); }; } static File parentFile(File f) { return dirOfFile(f); } static <A> ArrayList<A> cloneListSynchronizingOn(Collection<A> l, Object mutex) { if (l == null) return new ArrayList(); synchronized(mutex) { return new ArrayList<A>(l); } } static String regexpReplace_direct(String s, String pat, String replacement) { Matcher m = regexp(pat, s); return regexpReplace_direct(m, replacement); } static String regexpReplace_direct(Matcher m, String replacement) { StringBuffer buf = new StringBuffer(); while (m.find()) m.appendReplacement(buf, replacement); m.appendTail(buf); return str(buf); } static Map<String, java.util.regex.Pattern> compileRegexpIC_cache = syncMRUCache(10); static java.util.regex.Pattern compileRegexpIC(String pat) { java.util.regex.Pattern p = compileRegexpIC_cache.get(pat); if (p == null) { try { compileRegexpIC_cache.put(pat, p = java.util.regex.Pattern.compile(pat, Pattern.CASE_INSENSITIVE)); } catch (PatternSyntaxException e) { throw rethrow(wrapPatternSyntaxException(e)); } } return p; } static Matcher regexpIC(Pattern pat, String s) { return pat.matcher(unnull(s)); } static Matcher regexpIC(String pat, String s) { return compileRegexpIC(pat).matcher(unnull(s)); } static Pattern regexpIC(String pat) { return compileRegexpIC(pat); } static int moveToTopRightCorner_inset = 20; static <A extends Component> A moveToTopRightCorner(A a) { return moveToTopRightCorner(moveToTopRightCorner_inset, moveToTopRightCorner_inset, a); } static <A extends Component> A moveToTopRightCorner(int insetX, int insetY, A a) { { swing(() -> { Window w = getWindow(a); if (w != null) { var bounds = preferredScreenBounds(); w.setLocation(bounds.x2()-w.getWidth()-insetX, bounds.y1()+insetY); } }); } return a; } static int toMS_int(double seconds) { return toInt_checked((long) (seconds*1000)); } static String fromUtf8(byte[] bytes) { try { return bytes == null ? null : new String(bytes, utf8charset()); } catch (Exception __e) { throw rethrow(__e); } } static boolean possibleMD5(String s) { return isMD5(s); } static <A> A liftLast(List<A> l) { if (empty(l)) return null; int i = l(l)-1; A a = l.get(i); l.remove(i); return a; } static <A> List<A> liftLast(int n, List<A> l) { int i = l(l)-n; List<A> part = cloneSubList(l, i); removeSubList(l, i); return part; } static boolean hasLetters(String s) { for (int i = 0; i < s.length(); i++) if (Character.isLetter(s.charAt(i))) return true; return false; } static boolean containsLowerCase(String s) { for (int i = 0; i < l(s); i++) if (isLowerCase(s.charAt(i))) return true; return false; } static <A> List<A> dropFirstThreeAndLastThree(List<A> l) { return dropFirstAndLast(3, l); } static List<String> tok_combineCurlyBrackets_keep(List<String> tok) { List<String> l = new ArrayList(); for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (odd(i) && eq(t, "{")) { int j = findEndOfCurlyBracketPart(tok, i); l.add(joinSubList(tok, i, j)); i = j-1; } else l.add(t); } return l; } static boolean startsWithAndEndsWith(String s, String prefix, String suffix) { return startsWith(s, prefix) && endsWith(s, suffix); } static Rectangle toRectangle(Rect r) { return r == null ? null : r.getRectangle(); } static Dimension getScreenSize() { return Toolkit.getDefaultToolkit().getScreenSize(); } static String programTitle() { return getProgramName(); } static JFrame setFrameIconLater(Component c, final String imageID) { final JFrame frame = getFrame(c); if (frame != null) startThread("Loading Icon", new Runnable() { public void run() { try { final Image i = imageIcon(or2(imageID, "#1005557")).getImage(); swingLater(new Runnable() { public void run() { try { frame.setIconImage(i); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "frame.setIconImage(i);"; }}); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final Image i = imageIcon(or2(imageID, \"#1005557\")).getImage();\r\n swingL..."; }}); return frame; } static void _initFrame(JFrame f) { myFrames_list.put(f, Boolean.TRUE); standardTitlePopupMenu(f); } static Rectangle defaultNewFrameBounds_r = new Rectangle(300, 100, 500, 400); static Rectangle defaultNewFrameBounds() { return swing(new F0<Rectangle>() { public Rectangle get() { try { defaultNewFrameBounds_r.translate(60, 20); var bounds = preferredScreenBounds(); if (!bounds.contains(defaultNewFrameBounds_r)) //defaultNewFrameBounds_r.setLocation(bounds.x+30+random(30), bounds.y+20+random(20)); defaultNewFrameBounds_r.setLocation(centerX(bounds)+random_incl(-30, 30), centerY(bounds)+random_incl(-20, 20)); return new Rectangle(defaultNewFrameBounds_r); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "defaultNewFrameBounds_r.translate(60, 20);\r\n var bounds = preferredScreenB..."; }}); } static void hideConsole() { final JFrame frame = consoleFrame(); if (frame != null) { autoVMExit(); swingLater(new Runnable() { public void run() { try { frame.setVisible(false); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "frame.setVisible(false);"; }}); } } static <A> void scanForComponents(final Component c, final Class<A> theClass, final List<A> l) { if (theClass.isInstance(c)) l.add((A) c); if (c instanceof Container) { swing(() -> { for (Component comp : ((Container) c).getComponents()) scanForComponents(comp, theClass, l); }); } } static byte[] bytesFromHex(String s) { return hexToBytes(s); } static boolean byteArrayStartsWith(byte[] a, byte[] b) { if (a == null || b == null) return false; if (a.length < b.length) return false; for (int i = 0; i < b.length; i++) if (a[i] != b[i]) return false; return true; } static byte[] loadBeginningOfBinaryFile(File file, int maxBytes) { return loadBinaryFilePart(file, 0, maxBytes); } static File dirOfFile(File f) { return f == null ? null : f.getParentFile(); } static RuntimeException wrapPatternSyntaxException(PatternSyntaxException e) { if (e == null) return null; String pat = e.getPattern(); int i = e.getIndex(); return new RuntimeException("Regular expression error between " + multiLineQuoteWithSpaces(substring(pat, 0, i)) + " and " + multiLineQuoteWithSpaces(substring(pat, i)) + " - " + e.getMessage()); } static Rect preferredScreenBounds() { return screenBounds_safe(preferredScreen()); } static boolean isMD5(String s) { return l(s) == 32 && isLowerHexString(s); } static <A> List<A> cloneSubList(List<A> l, int startIndex, int endIndex) { return newSubList(l, startIndex, endIndex); } static <A> List<A> cloneSubList(List<A> l, int startIndex) { return newSubList(l, startIndex); } static boolean isLowerCase(char c) { return Character.isLowerCase(c); } static <A> List<A> dropFirstAndLast(int n, List<A> l) { return cloneSubList(l, n, l(l)-n); } static <A> List<A> dropFirstAndLast(int m, int n, List<A> l) { return cloneSubList(l, m, l(l)-n); } static <A> List<A> dropFirstAndLast(List<A> l) { return dropFirstAndLast(1, l); } static String dropFirstAndLast(String s) { return substring(s, 1, l(s)-1); } // i must point at the (possibly imaginary) opening bracket // index returned is index of closing bracket + 1 static int findEndOfCurlyBracketPart(List<String> cnc, int i) { int j = i+2, level = 1; while (j < cnc.size()) { if (eq(cnc.get(j), "{")) ++level; else if (eq(cnc.get(j), "}")) --level; if (level == 0) return j+1; ++j; } return cnc.size(); } static String getProgramName_cache; static String getProgramName() { Lock __0 = downloadLock(); lock(__0); try { if (getProgramName_cache == null) getProgramName_cache = getSnippetTitleOpt(programID()); return getProgramName_cache; } finally { unlock(__0); } } static void _onLoad_getProgramName() { { startThread(new Runnable() { public void run() { try { getProgramName(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "getProgramName();"; }}); } } static void standardTitlePopupMenu(final JFrame frame) { // standard right-click behavior on titles if (!isSubstanceLAF()) return; titlePopupMenu(frame, new VF1<JPopupMenu>() { public void get(JPopupMenu menu) { try { boolean alwaysOnTop = frame.isAlwaysOnTop(); menu.add(jmenuItem("Restart Program", new Runnable() { public void run() { try { restart(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "restart();"; }})); menu.add(jmenuItem("Duplicate Program", new Runnable() { public void run() { try { duplicateThisProgram(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "duplicateThisProgram();"; }})); menu.add(jmenuItem("Show Console", new Runnable() { public void run() { try { showConsole(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showConsole();"; }})); menu.add(jCheckBoxMenuItem("Always On Top", alwaysOnTop, new Runnable() { public void run() { try { toggleAlwaysOnTop(frame) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "toggleAlwaysOnTop(frame)"; }})); /*ifndef standardTitlePopupMenu_noShootWindow { menu.add(jMenuItem("Shoot Window", r { shootWindowGUI_external(frame, 500) })); } endifndef*/ //addMenuItem(menu, "Bigger fonts", r swingBiggerFonts); //addMenuItem(menu, "Smaller fonts", r swingSmallerFonts); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "bool alwaysOnTop = frame.isAlwaysOnTop();\r\n ifndef standardTitlePopupMenu_..."; }}); } static Integer centerX(Rect r) { return rectCenterX(r); } static int random_incl(int min, int max) { return random_incl(min, max, defaultRandomizer()); } static int random_incl(int min, int max, Random random) { return random(min, max+1, random); } static int random_incl(int max) { return random(0, max+1); } static Integer centerY(Rect r) { return rectCenterY(r); } static JFrame consoleFrame() { return (JFrame) getOpt(get(getJavaX(), "console"), "frame"); } static void autoVMExit() { call(getJavaX(), "autoVMExit"); } static byte[] hexToBytes(String s) { if (odd(l(s))) throw fail("Hex string has odd length: " + quote(shorten(10, s))); int n = l(s) / 2; byte[] bytes = new byte[n]; for (int i = 0; i < n; i++) { int a = parseHexChar(s.charAt(i*2)); int b = parseHexChar(s.charAt(i*2+1)); if (a < 0 || b < 0) throw fail("Bad hex byte: " + quote(substring(s, i*2, i*2+2)) + " at " + i*2 + "/" + l(s)); bytes[i] = (byte) ((a << 4) | b); } return bytes; } static byte[] loadBinaryFilePart(File file, long start, long end) { try { RandomAccessFile raf = new RandomAccessFile(file, "r"); int n = toInt(min(raf.length(), end-start)); byte[] buffer = new byte[n]; try { raf.seek(start); raf.readFully(buffer, 0, n); return buffer; } finally { raf.close(); } } catch (Exception __e) { throw rethrow(__e); } } static String multiLineQuoteWithSpaces(String s) { return multiLineQuote(" " + s + " "); } static Rect screenBounds_safe(int iScreen) { return screenBounds(min(iScreen, screenCount()-1)); } static IF0<Integer> preferredScreen; static int preferredScreen() { return preferredScreen != null ? preferredScreen.get() : preferredScreen_base(); } final static int preferredScreen_fallback(IF0<Integer> _f) { return _f != null ? _f.get() : preferredScreen_base(); } static int preferredScreen_base() { return 0; } static boolean isLowerHexString(String s) { for (int i = 0; i < l(s); i++) { char c = s.charAt(i); if (c >= '0' && c <= '9' || c >= 'a' && c <= 'f') { // ok } else return false; } return true; } static <A> List<A> newSubList(List<A> l, int startIndex, int endIndex) { return cloneList(subList(l, startIndex, endIndex)); } static <A> List<A> newSubList(List<A> l, int startIndex) { return cloneList(subList(l, startIndex)); } static Lock downloadLock_lock = fairLock(); static Lock downloadLock() { return downloadLock_lock; } static String getSnippetTitleOpt(String s) { try { return isSnippetID(s) ? getSnippetTitle(s) : s; } catch (Throwable __e) { printStackTrace(__e); } return s; } static boolean isSubstanceLAF() { return substanceLookAndFeelEnabled(); } // menuMaker = voidfunc(JPopupMenu) // return true if menu could be added static boolean titlePopupMenu(final Component c, final Object menuMaker) { JComponent titleBar = getTitlePaneComponent(getPossiblyInternalFrame(c)); if (titleBar == null) { print("Can't add title right click!"); return false; } else { componentPopupMenu(titleBar, menuMaker); return true; } } static void restart() { Object j = getJavaX(); call(j, "cleanRestart", get(j, "fullArgs")); } static void duplicateThisProgram() { nohupJavax(trim(programID() + " " + smartJoin((String[]) get(getJavaX(), "fullArgs")))); } static void showConsole() { callOpt(get(javax(), "console"), "showConsole"); } static void toggleAlwaysOnTop(Window frame) { if (frame == null) return; { swing(() -> { frame.setAlwaysOnTop(!frame.isAlwaysOnTop()); }); } } static Integer rectCenterX(Rect r) { return r == null ? null : r.x+r.w/2; } static Random defaultRandomizer() { return defaultRandomGenerator(); } static int random(int n) { return random(n, defaultRandomGenerator()); } static int random(int n, Random r) { return random(r, n); } static int random(Random r, int n) { return n <= 0 ? 0 : getRandomizer(r).nextInt(n); } static double random(double max) { return random()*max; } static double random() { return defaultRandomGenerator().nextInt(100001)/100000.0; } static double random(double min, double max) { return min+random()*(max-min); } // min <= value < max static int random(int min, int max) { return min+random(max-min); } static int random(int min, int max, Random r) { return random(r, min, max); } static int random(Random r, int min, int max) { return min+random(r, max-min); } static <A> A random(List<A> l) { return oneOf(l); } static <A> A random(Collection<A> c) { if (c instanceof List) return random((List<A>) c); int i = random(l(c)); return collectionGet(c, i); } static <A, B> Pair<A, B> random(Map<A, B> map) { return entryToPair(random(entries(map))); } static Integer rectCenterY(Rect r) { return r == null ? null : r.y+r.h/2; } static int shorten_default = 100; static String shorten(CharSequence s) { return shorten(s, shorten_default); } static String shorten(CharSequence s, int max) { return shorten(s, max, "..."); } static String shorten(CharSequence s, int max, String shortener) { if (s == null) return ""; if (max < 0) return str(s); return s.length() <= max ? str(s) : subCharSequence(s, 0, min(s.length(), max-l(shortener))) + shortener; } static String shorten(int max, CharSequence s) { return shorten(s, max); } static int parseHexChar(char c) { if (c >= '0' && c <= '9') return charDiff(c, '0'); if (c >= 'a' && c <= 'f') return charDiff(c, 'a')+10; if (c >= 'A' && c <= 'F') return charDiff(c, 'A')+10; return -1; } static String multiLineQuote(String s) { for (int i = 0; ; i++) { String closer = "]" + rep('=', i) + "]"; if (!contains(s, closer)) return "[" + rep('=', i) + "[" + s + closer; } } static Rect screenBounds(GraphicsDevice screen) { return screen == null ? null : toRect(screen.getDefaultConfiguration().getBounds()); } static Rect screenBounds(int iScreen) { return screenBounds(get(screenDevices(), iScreen)); } static int screenCount() { return l(GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()); } static boolean substanceLookAndFeelEnabled() { return startsWith(getLookAndFeel(), "org.pushingpixels."); } static JComponent getTitlePaneComponent(RootPaneContainer window) { if (window instanceof JInternalFrame) return getInternalFrameTitlePaneComponent((JInternalFrame) window); if (!substanceLookAndFeelEnabled() || window == null) return null; JRootPane rootPane = window.getRootPane(); if (rootPane != null) { Object /*SubstanceRootPaneUI*/ ui = rootPane.getUI(); return (JComponent) call(ui, "getTitlePane"); } return null; } static void nohupJavax(final String javaxargs) { { startThread(new Runnable() { public void run() { try { call(hotwireOnce("#1008562"), "nohupJavax", javaxargs); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "call(hotwireOnce(\"#1008562\"), \"nohupJavax\", javaxargs);"; }}); } } static void nohupJavax(final String javaxargs, final String vmArgs) { { startThread(new Runnable() { public void run() { try { call(hotwireOnce("#1008562"), "nohupJavax", javaxargs, vmArgs); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "call(hotwireOnce(\"#1008562\"), \"nohupJavax\", javaxargs, vmArgs);"; }}); } } // Try to get the quoting right... static String smartJoin(String[] args) { if (empty(args)) return ""; if (args.length == 1) return args[0]; String[] a = new String[args.length]; for (int i = 0; i < a.length; i++) a[i] = !isJavaIdentifier(args[i]) && !isQuoted(args[i]) ? quote(args[i]) : args[i]; return join(" ", a); } static String smartJoin(List<String> args) { return smartJoin(toStringArray(args)); } static Random getRandomizer(Random r) { return r != null ? r : defaultRandomGenerator(); } static <A> A oneOf(List<A> l) { if (empty(l)) return null; int n = l.size(); return n == 1 ? first(l) : l.get(defaultRandomizer().nextInt(n)); } static char oneOf(String s) { return empty(s) ? '?' : s.charAt(random(l(s))); } static String oneOf(String... l) { return oneOf(asList(l)); } static <A> A collectionGet(Collection<A> c, int idx) { if (c == null || idx < 0 || idx >= l(c)) return null; if (c instanceof List) return listGet((List<A>) c, idx); Iterator<A> it = c.iterator(); for (int i = 0; i < idx; i++) if (it.hasNext()) it.next(); else return null; return it.hasNext() ? it.next() : null; } static <A, B> Pair<A, B> entryToPair(Map.Entry<A, B> e) { return mapEntryToPair(e); } static <A, B> Set<Map.Entry<A,B>> entries(Map<A, B> map) { return _entrySet(map); } static int charDiff(char a, char b) { return (int) a-(int) b; } static int charDiff(String a, char b) { return charDiff(stringToChar(a), b); } static String rep(int n, char c) { return repeat(c, n); } static String rep(char c, int n) { return repeat(c, n); } static <A> List<A> rep(A a, int n) { return repeat(a, n); } static <A> List<A> rep(int n, A a) { return repeat(n, a); } static List<GraphicsDevice> screenDevices() { return asList(GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()); } static String getLookAndFeel() { return getClassName(UIManager.getLookAndFeel()); } static Class hotwireOnce(String programID) { return hotwireCached(programID, false); } static <A> A listGet(List<A> l, int idx) { return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null; } static char stringToChar(String s) { if (l(s) != 1) throw fail("bad stringToChar: " + s); return firstChar(s); } static String repeat(char c, int n) { n = Math.max(n, 0); char[] chars = new char[n]; for (int i = 0; i < n; i++) chars[i] = c; return new String(chars); } static <A> List<A> repeat(A a, int n) { n = Math.max(n, 0); List<A> l = new ArrayList(n); for (int i = 0; i < n; i++) l.add(a); return l; } static <A> List<A> repeat(int n, A a) { return repeat(a, n); } static TreeMap<String, Class> hotwireCached_cache = new TreeMap(); static Lock hotwireCached_lock = lock(); static Class hotwireCached(String programID) { return hotwireCached(programID, true); } static Class hotwireCached(String programID, boolean runMain) { return hotwireCached(programID, runMain, false); } static Class hotwireCached(String programID, boolean runMain, boolean dependent) { Lock __0 = hotwireCached_lock; lock(__0); try { programID = formatSnippetID(programID); Class c = hotwireCached_cache.get(programID); if (c == null) { c = hotwire(programID); if (dependent) makeDependent(c); if (runMain) callMain(c); hotwireCached_cache.put(programID, c); } return c; } finally { unlock(__0); } } static char firstChar(String s) { return s.charAt(0); } static class JSection extends SingleComponentPanel { JSection(Component c) { super(c); } String getTitle() { Border border = getBorder(); if (border instanceof TitledBorder) return ((TitledBorder) border).getTitle(); return null; } } // size: // 64 bytes for 0 to 1 elements // 96 bytes for 2 to 4 elements /* * #! * Ontopia Engine * #- * Copyright (C) 2001 - 2013 The Ontopia Project * #- * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * !# */ static class CompactHashMap<K, V> extends CompactAbstractMap<K, V> { final static int INITIAL_SIZE = 3; final static double LOAD_FACTOR = 0.6; // This object is used to represent null, should clients use that as final static Object nullObject = new Object(); /** * When a key is deleted this object is put into the hashtable in * its place, so that other entries with the same key (collisions) * further down the hashtable are not lost after we delete an object * in the collision chain. */ final static Object deletedObject = new Object(); int elements; int freecells; Object[] table; // key, value, key, value, ... //int modCount; CompactHashMap() { this(INITIAL_SIZE); } CompactHashMap(int size) { table = new Object[(size==0 ? 1 : size)*2]; elements = 0; freecells = tableSize(); //modCount = 0; } // TODO: allocate smarter CompactHashMap(Map<K, V> map) { this(0); if (map != null) putAll(map); } // ===== MAP IMPLEMENTATION ============================================= /** * Returns the number of key/value mappings in this map. */ public synchronized int size() { return elements; } /** * Returns <tt>true</tt> if this map contains no mappings. */ public synchronized boolean isEmpty() { return elements == 0; } /** * Removes all key/value mappings in the map. */ public synchronized void clear() { elements = 0; for (int ix = 0; ix < tableSize(); ix++) { key(ix, null); value(ix, null); } freecells = tableSize(); //modCount++; } /** * Returns <tt>true</tt> if this map contains the specified key. */ public synchronized boolean containsKey(Object k) { return key(findKeyIndex(k)) != null; } /** * Returns <tt>true</tt> if this map contains the specified value. */ public synchronized boolean containsValue(Object v) { if (v == null) v = (V)nullObject; for (int ix = 0; ix < tableSize(); ix++) if (value(ix) != null && value(ix).equals(v)) return true; return false; } /** * Returns a read-only set view of the map's keys. */ public synchronized Set<Entry<K, V>> entrySet() { throw new UnsupportedOperationException(); } /** * Removes the mapping with key k, if there is one, and returns its * value, if there is one, and null if there is none. */ public synchronized V remove(Object k) { int index = findKeyIndex(k); // we found the right position, now do the removal if (key(index) != null) { // we found the object // same problem here as with put V v = value(index); key(index, deletedObject); value(index, deletedObject); //modCount++; elements--; return v; } else // we did not find the key return null; } /** * Adds the specified mapping to this map, returning the old value for * the mapping, if there was one. */ public synchronized V put(K k, V v) { if (k == null) k = (K)nullObject; int hash = k.hashCode(); int index = (hash & 0x7FFFFFFF) % tableSize(); int offset = 1; int deletedix = -1; // search for the key (continue while !null and !this key) while(key(index) != null && !(key(index).hashCode() == hash && key(index).equals(k))) { // if there's a deleted mapping here we can put this mapping here, // provided it's not in here somewhere else already if (key(index) == deletedObject) deletedix = index; index = ((index + offset) & 0x7FFFFFFF) % tableSize(); offset = offset*2 + 1; if (offset == -1) offset = 2; } if (key(index) == null) { // wasn't present already if (deletedix != -1) // reusing a deleted cell index = deletedix; else freecells--; //modCount++; elements++; key(index, k); value(index, v); // rehash with increased capacity if (1 - (freecells / (double) tableSize()) > LOAD_FACTOR) rehash(tableSize()*2 + 1); return null; } else { // was there already //modCount++; V oldv = value(index); value(index, v); return oldv; } } /** * INTERNAL: Rehashes the hashmap to a bigger size. */ void rehash(int newCapacity) { int oldCapacity = tableSize(); Object[] newTable = new Object[newCapacity*2]; for (int ix = 0; ix < oldCapacity; ix++) { Object k = key(ix); if (k == null || k == deletedObject) continue; int hash = k.hashCode(); int index = (hash & 0x7FFFFFFF) % newCapacity; int offset = 1; // search for the key while(newTable[index*2] != null) { // no need to test for duplicates index = ((index + offset) & 0x7FFFFFFF) % newCapacity; offset = offset*2 + 1; if (offset == -1) offset = 2; } newTable[index*2] = k; newTable[index*2+1] = value(ix); } table = newTable; freecells = tableSize() - elements; } /** * Returns the value for the key k, if there is one, and null if * there is none. */ public synchronized V get(Object k) { return value(findKeyIndex(k)); } /** * Returns a virtual read-only collection containing all the values * in the map. */ public synchronized Collection<V> values() { return new ValueCollection(); } /** * Returns a virtual read-only set of all the keys in the map. */ public synchronized Set<K> keySet() { return new KeySet(); } // --- Internal utilities final int findKeyIndex(Object k) { if (k == null) k = nullObject; int hash = k.hashCode(); int index = (hash & 0x7FFFFFFF) % tableSize(); int offset = 1; // search for the key (continue while !null and !this key) while(key(index) != null && !(key(index).hashCode() == hash && key(index).equals(k))) { index = ((index + offset) & 0x7FFFFFFF) % tableSize(); offset = offset*2 + 1; if (offset == -1) offset = 2; } return index; } // --- Key set class KeySet<K> extends AbstractSet<K> { public synchronized int size() { return elements; } public synchronized boolean contains(Object k) { return containsKey(k); } public synchronized Iterator<K> iterator() { return new KeyIterator(); } } class KeyIterator<K> implements Iterator<K> { private int ix; private KeyIterator() { // walk up to first value, so that hasNext() and next() return // correct results for (; ix < tableSize(); ix++) if (value(ix) != null && key(ix) != deletedObject) break; } public synchronized boolean hasNext() { return ix < tableSize(); } public synchronized void remove() { throw new UnsupportedOperationException("Collection is read-only"); } public synchronized K next() { if (ix >= tableSize()) throw new NoSuchElementException(); K key = (K) key(ix++); // walk up to next value for (; ix < tableSize(); ix++) if (key(ix) != null && key(ix) != deletedObject) break; // ix now either points to next key, or outside array (if no next) return key; } } // --- Value collection class ValueCollection<V> extends AbstractCollection<V> { public synchronized int size() { return elements; } public synchronized Iterator<V> iterator() { return new ValueIterator(); } public synchronized boolean contains(Object v) { return containsValue(v); } } class ValueIterator<V> implements Iterator<V> { private int ix; private ValueIterator() { // walk up to first value, so that hasNext() and next() return // correct results for (; ix < table.length/2; ix++) if (value(ix) != null && value(ix) != deletedObject) break; } public synchronized boolean hasNext() { return ix < tableSize(); } public synchronized void remove() { throw new UnsupportedOperationException("Collection is read-only"); } public synchronized V next() { if (ix >= tableSize()) throw new NoSuchElementException(); V value = (V) value(ix++); // walk up to next value for (; ix < tableSize(); ix++) if (value(ix) != null && value(ix) != deletedObject) break; // ix now either points to next value, or outside array (if no next) return value; } } K key(int i) { return (K) table[i*2]; } void key(int i, Object key) { table[i*2] = key; } V value(int i) { return (V) table[i*2+1]; } void value(int i, Object value) { table[i*2+1] = value; } int tableSize() { return table.length/2; } } static class JavaXClassLoaderWithParent extends JavaXClassLoader { ClassLoader virtualParent; JavaXClassLoaderWithParent(String progID, List<File> files, ClassLoader virtualParent) { super(progID, files); this.virtualParent = virtualParent; } protected Class<?> findClass(String name) throws ClassNotFoundException { if (virtualParent != null && !eq(name, "main") && !name.startsWith("main$")) { try { return virtualParent.loadClass(name); } catch (ClassNotFoundException e) {} } return super.findClass(name); } public URL findResource(String name) { if (virtualParent != null) { URL url = virtualParent.getResource(name); if (url != null) return url; } return super.findResource(name); } ClassLoader getVirtualParent() { return virtualParent; } } // a variant of thread where you can get the Runnable target later. // Also notes its existence on the VM bus. // We should use this exclusively instead of Thread. static class BetterThread extends Thread { Runnable target; BetterThread(Runnable target) { this.target = target; _created(); } BetterThread(Runnable target, String name) { super(name); this.target = target; _created(); } void _created() { vmBus_send("threadCreated", this); } public void run() { try { try { vmBus_send("threadStarted", this); if (target != null) target.run(); } finally { vmBus_send("threadEnded", this); } } catch (Exception __e) { throw rethrow(__e); } } Runnable getTarget() { return target; } } static abstract class LiveValue<A> implements IGetterWithNotify<A> { abstract Class<A> getType(); public abstract A get(); } static abstract class F2<A, B, C> { abstract C get(A a, B b); } static class IntVar { int a; // you can access this directly if you use one thread public synchronized void set(int v) { if (v != a) { a = v; notifyAll(); } } public synchronized int get() { return a; } synchronized int waitForValue(int x) { try { while (a != x) wait(); return a; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return str(this.get()); } } static class Complex implements IFieldsToList{ static final String _fieldOrder = "re im"; double re; double im; Complex() {} Complex(double re, double im) { this.im = im; this.re = re;} public boolean equals(Object o) { if (!(o instanceof Complex)) return false; Complex __1 = (Complex) o; return re == __1.re && im == __1.im; } public int hashCode() { int h = -1679819632; h = boostHashCombine(h, _hashCode(re)); h = boostHashCombine(h, _hashCode(im)); return h; } public Object[] _fieldsToList() { return new Object[] {re, im}; } double abs() { return sqrt(re*re+im*im); } double re() { return re; } double im() { return im; } final double angle(){ return phase(); } double phase() { return Math.atan2(im, re); } double fracAngle() { return fracNonNeg(angle()/twoPi()); } // angle as 0 to 1 public String toString() { if (im != 0) return re == 0 ? im + "i" : re + plusPrefixUnlessMinus(str(im)) + "i"; else return str(re); } } static class PopupMenuMaker { final public PopupMenuMaker setAllowScrolling(boolean allowScrolling){ return allowScrolling(allowScrolling); } public PopupMenuMaker allowScrolling(boolean allowScrolling) { this.allowScrolling = allowScrolling; return this; } final public boolean getAllowScrolling(){ return allowScrolling(); } public boolean allowScrolling() { return allowScrolling; } boolean allowScrolling = true; // ignored when using existingMenu final public PopupMenuMaker setEvent(MouseEvent event){ return event(event); } public PopupMenuMaker event(MouseEvent event) { this.event = event; return this; } final public MouseEvent getEvent(){ return event(); } public MouseEvent event() { return event; } MouseEvent event; final public PopupMenuMaker setPtInComponent(PtInComponent ptInComponent){ return ptInComponent(ptInComponent); } public PopupMenuMaker ptInComponent(PtInComponent ptInComponent) { this.ptInComponent = ptInComponent; return this; } final public PtInComponent getPtInComponent(){ return ptInComponent(); } public PtInComponent ptInComponent() { return ptInComponent; } PtInComponent ptInComponent; // if different from event final public PopupMenuMaker setFillMenu(IVF1<JPopupMenu> fillMenu){ return fillMenu(fillMenu); } public PopupMenuMaker fillMenu(IVF1<JPopupMenu> fillMenu) { this.fillMenu = fillMenu; return this; } final public IVF1<JPopupMenu> getFillMenu(){ return fillMenu(); } public IVF1<JPopupMenu> fillMenu() { return fillMenu; } IVF1<JPopupMenu> fillMenu; final public PopupMenuMaker setExistingMenu(JPopupMenu existingMenu){ return existingMenu(existingMenu); } public PopupMenuMaker existingMenu(JPopupMenu existingMenu) { this.existingMenu = existingMenu; return this; } final public JPopupMenu getExistingMenu(){ return existingMenu(); } public JPopupMenu existingMenu() { return existingMenu; } JPopupMenu existingMenu; final public PopupMenuMaker setAddSeparator(boolean addSeparator){ return addSeparator(addSeparator); } public PopupMenuMaker addSeparator(boolean addSeparator) { this.addSeparator = addSeparator; return this; } final public boolean getAddSeparator(){ return addSeparator(); } public boolean addSeparator() { return addSeparator; } boolean addSeparator = true; // add separator if existing meun JPopupMenu menu; PopupMenuMaker() {} PopupMenuMaker(MouseEvent event, IVF1<JPopupMenu> fillMenu) { this.fillMenu = fillMenu; this.event = event;} public void run() { swing(() -> { if (existingMenu != null) { var menu = existingMenu; int emptyCount = menu.getComponentCount(); if (addSeparator) menu.addSeparator(); int emptyCount2 = menu.getComponentCount(); { if (fillMenu != null) fillMenu.get(menu); } if (menu.getComponentCount() == emptyCount2) truncateContainer(menu, emptyCount); //printVars("Extended popup menu", +emptyCount, +emptyCount2, n := menu.getComponentCount()); packWindow(menu); //revalidate(menu); } else { JPopupMenu menu = new JPopupMenu(); int emptyCount = menu.getComponentCount(); { if (fillMenu != null) fillMenu.get(menu); } if (menu.getComponentCount() == emptyCount) return; if (allowScrolling) { menu = new JPopupMenu(); JMenuScroller scroller = JMenuScroller.setScrollerFor(menu); scroller.fillMenu = toVF1(fillMenu); } if (ptInComponent == null) ptInComponent = ptInComponentFromEvent(event); if (hasParentOfType(JPopupMenu.class, ptInComponent.component)) { // component is in a menu itself. TODO: better positioning // Also this doesn't actually seem to work... menu.setInvoker(ptInComponent.component); menu.setVisible(true); } else menu.show(ptInComponent.component, ptInComponent.p.x, ptInComponent.p.y); } }); } } static class BetterLabel extends JLabel { boolean autoToolTip = true; BetterLabel() { // Listeners given out to componentPopupMenu must not directly // reference the outer object (-> weak map problem). final WeakReference < BetterLabel > me = new WeakReference<>(this); componentPopupMenu(this, BetterLabel_menuItems(me)); } BetterLabel(String text) { this(); this.setText(text); } public void setText(String text) { super.setText(text); if (autoToolTip) if (!swic(text, "<html>")) // HTML labels make super-huge, confusing tool tips setToolTipText(nullIfEmpty(text)); } } // moved outside of class for GC reasons (see above) static VF1<JPopupMenu> BetterLabel_menuItems(final WeakReference<BetterLabel> me) { return new VF1<JPopupMenu>() { public void get(JPopupMenu menu) { try { addMenuItem(menu, "Copy text to clipboard", new Runnable() { public void run() { try { copyTextToClipboard(me.get().getText()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "copyTextToClipboard(me.get().getText());"; }}); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addMenuItem(menu, \"Copy text to clipboard\", r {\r\n copyTextToClipboard(me..."; }}; } static class Lowest<A> { A best; double score; transient Object onChange; synchronized boolean isNewBest(double score) { return best == null || score < this.score; } synchronized double bestScore() { return best == null ? Double.NaN : score; } double score() { return bestScore(); } synchronized float floatScore() { return best == null ? Float.NaN : (float) score; } synchronized float floatScoreOr(float defaultValue) { return best == null ? defaultValue : (float) score; } boolean put(A a, double score) { boolean change = false; synchronized(this) { if (a != null && isNewBest(score)) { best = a; this.score = score; change = true; } } if (change) pcallF(onChange); return change; } synchronized void clear() { best = null; score = 0; } synchronized A get() { return best; } synchronized boolean has() { return best != null; } synchronized Pair<A, Double> pair() { return best == null ? null : new Pair(best, bestScore()); } public String toString() { return "Score " + formatDouble_significant2(score, 4) + ": " + best; } } static class SingleComponentPanel extends JPanel { SingleComponentPanel() { super(new BorderLayout()); } SingleComponentPanel(Component component) { this(); if (component != null) setComponent(component); } void set(Swingable component) { set(wrap(component)); } final void set(Component component){ setComponent(component); } void setComponent(Component component) { { swing(() -> { if (getComponent() == component) return; removeAll(); if (component != null) add(BorderLayout.CENTER, wrap(component)); _revalidate(SingleComponentPanel.this); }); } } // Sometimes we need this? void setComponentAndRevalidateParent(Component component) { setComponent(component); _revalidate(_getParent(this)); } final void clear(){ noComponent(); } void noComponent() { setComponent(null); } Component getComponent() { return swing( () -> getComponentCount() == 0 ? null : getComponent(0)); } boolean isEmpty() { return getComponent() == null; } } // has equals semantics so passing it to onChange() etc is idempotent static class ChangeTrigger implements Runnable , IFieldsToList{ ChangeTriggerable target; ChangeTrigger() {} ChangeTrigger(ChangeTriggerable target) { this.target = target;} public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + target + ")"; } public boolean equals(Object o) { if (!(o instanceof ChangeTrigger)) return false; ChangeTrigger __1 = (ChangeTrigger) o; return eq(target, __1.target); } public int hashCode() { int h = -1239972920; h = boostHashCombine(h, _hashCode(target)); return h; } public Object[] _fieldsToList() { return new Object[] {target}; } public void run() { try { { if (target != null) target.change(); } } catch (Exception __e) { throw rethrow(__e); } } } static class CompilerBot { static boolean verbose = false; static File compileSnippet(String snippetID) { return compileSnippet(snippetID, ""); } static Pair<File, String> compileSnippet2(String snippetID) { return compileSnippet2(snippetID, ""); } // returns jar path static File compileSnippet(String snippetID, String javaTarget) { return compileSnippet2(snippetID, javaTarget).a; } // returns jar path, Java source static Pair<File, String> compileSnippet2(String snippetID, String javaTarget) { String transpiledSrc = getServerTranspiled2(snippetID); if (transpiledSrc == null) throw fail("Snippet not found or not public: " + snippetID); int i = transpiledSrc.indexOf('\n'); String libs = transpiledSrc.substring(0, Math.max(0, i)); if (verbose) print("Compiling snippet: " + snippetID + ". Libs: " + libs); transpiledSrc = transpiledSrc.substring(i+1); return pair(compile(transpiledSrc, libs, javaTarget, snippetID), transpiledSrc); } static File compile(String src) { return compile(src, ""); } static File compile(String src, String libs) { return compile(src, libs, null); } static File compile(String src, String dehlibs, String javaTarget) { return compile(src, dehlibs, javaTarget, null); } static File compile(String src, String dehlibs, String javaTarget, String progID) { if (verbose) print("Compiling " + l(src) + " chars"); // Note: This is different from the calculation in x30 // (might lead to programs being compiled twice) String md5 = md5(dehlibs + "\n" + src + "\n" + fsIOpt(progID)); File jar = getJarFile(md5); if (jar == null || jar.length() <= 22) { // have to compile //print("Have to compile: " + progID + " / " + md5); List<String> tok = javaTok(src); List<String> mainClass = findMainClass(tok); boolean canRename = mainClass != null && useDummyMainClasses() && isSnippetID(progID) && !tok_classHasModifier(mainClass, "public"); if (verbose) print("useRenaming: " + useDummyMainClasses() + ", canRename: " + canRename + ", progID: " + progID); String mainClassName = joinNemptiesWithDot(tok_packageName(tok), or(getClassDeclarationName(mainClass), "main")); AutoCloseable __1 = tempSetTL(javaCompileToJar_addMoreFiles, dir -> { if (!eq(mainClassName, "main")) saveTextFile(newFile(dir, "main-class"), mainClassName); saveTextFile(newFile(dir, manifestPathInJar()), manifestTextForMainClass(mainClassName)); }); try { javaCompileToJar_optionalRename(src, dehlibs, jar, canRename ? progID : null, progID); } finally { _close(__1); }} else { if (verbose) print("Getting classes from cache (" + jar.getAbsolutePath() + ", " + jar.length() + " bytes)"); touchFile(jar); // so we can find the unused ones easier } return jar; } // look in non-virtual JavaX-Caches first (important for packaged programs) // Edit: Huh? This is strange. static File getJarFile(String md5) { assertTrue(isMD5(md5)); String fileName = md5 + ".jar"; File f = newFile(destDir(), fileName); return fileExists(f) ? f : userDir(appendSlash(compilerBotDestDirSubName()) + fileName); } /*swappable*/ static File destDir() { return compilerBotDestDir(); } } static interface Swingable { JComponent visualize(); } static class PtInComponent<A extends Component> implements IFieldsToList{ A component; Pt p; PtInComponent() {} PtInComponent(A component, Pt p) { this.p = p; this.component = component;} public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + component + ", " + p + ")"; } public boolean equals(Object o) { if (!(o instanceof PtInComponent)) return false; PtInComponent __1 = (PtInComponent) o; return eq(component, __1.component) && eq(p, __1.p); } public int hashCode() { int h = -1774729068; h = boostHashCombine(h, _hashCode(component)); h = boostHashCombine(h, _hashCode(p)); return h; } public Object[] _fieldsToList() { return new Object[] {component, p}; } PtInComponent(Pt p, A component) { this.component = component; this.p = p;} } /** * A class that provides scrolling capabilities to a long menu dropdown or * popup menu. A number of items can optionally be frozen at the top and/or * bottom of the menu. * <P> * <B>Implementation note:</B> The default number of items to display * at a time is 15, and the default scrolling interval is 125 milliseconds. * <P> * * @version 1.5.0 04/05/12 * @author Darryl * https://tips4java.wordpress.com/2009/02/01/menu-scroller/ */ static class JMenuScroller { VF1<JPopupMenu> fillMenu; private JPopupMenu menu; private Component[] menuItems; private MenuScrollItem upItem; private MenuScrollItem downItem; private final MenuScrollListener menuListener = new MenuScrollListener(); private int scrollCount; private int interval; private int topFixedCount; private int bottomFixedCount; private int firstIndex = 0; private int keepVisibleIndex = -1; /** * Registers a menu to be scrolled with the default number of items to * display at a time and the default scrolling interval. * * @param menu the menu * @return the JMenuScroller */ public static JMenuScroller setScrollerFor(JMenu menu) { return new JMenuScroller(menu); } /** * Registers a popup menu to be scrolled with the default number of items to * display at a time and the default scrolling interval. * * @param menu the popup menu * @return the JMenuScroller */ public static JMenuScroller setScrollerFor(JPopupMenu menu) { return new JMenuScroller(menu); } /** * Registers a menu to be scrolled with the default number of items to * display at a time and the specified scrolling interval. * * @param menu the menu * @param scrollCount the number of items to display at a time * @return the JMenuScroller * @throws IllegalArgumentException if scrollCount is 0 or negative */ public static JMenuScroller setScrollerFor(JMenu menu, int scrollCount) { return new JMenuScroller(menu, scrollCount); } /** * Registers a popup menu to be scrolled with the default number of items to * display at a time and the specified scrolling interval. * * @param menu the popup menu * @param scrollCount the number of items to display at a time * @return the JMenuScroller * @throws IllegalArgumentException if scrollCount is 0 or negative */ public static JMenuScroller setScrollerFor(JPopupMenu menu, int scrollCount) { return new JMenuScroller(menu, scrollCount); } /** * Registers a menu to be scrolled, with the specified number of items to * display at a time and the specified scrolling interval. * * @param menu the menu * @param scrollCount the number of items to be displayed at a time * @param interval the scroll interval, in milliseconds * @return the JMenuScroller * @throws IllegalArgumentException if scrollCount or interval is 0 or negative */ public static JMenuScroller setScrollerFor(JMenu menu, int scrollCount, int interval) { return new JMenuScroller(menu, scrollCount, interval); } /** * Registers a popup menu to be scrolled, with the specified number of items to * display at a time and the specified scrolling interval. * * @param menu the popup menu * @param scrollCount the number of items to be displayed at a time * @param interval the scroll interval, in milliseconds * @return the JMenuScroller * @throws IllegalArgumentException if scrollCount or interval is 0 or negative */ public static JMenuScroller setScrollerFor(JPopupMenu menu, int scrollCount, int interval) { return new JMenuScroller(menu, scrollCount, interval); } /** * Registers a menu to be scrolled, with the specified number of items * to display in the scrolling region, the specified scrolling interval, * and the specified numbers of items fixed at the top and bottom of the * menu. * * @param menu the menu * @param scrollCount the number of items to display in the scrolling portion * @param interval the scroll interval, in milliseconds * @param topFixedCount the number of items to fix at the top. May be 0. * @param bottomFixedCount the number of items to fix at the bottom. May be 0 * @throws IllegalArgumentException if scrollCount or interval is 0 or * negative or if topFixedCount or bottomFixedCount is negative * @return the JMenuScroller */ public static JMenuScroller setScrollerFor(JMenu menu, int scrollCount, int interval, int topFixedCount, int bottomFixedCount) { return new JMenuScroller(menu, scrollCount, interval, topFixedCount, bottomFixedCount); } /** * Registers a popup menu to be scrolled, with the specified number of items * to display in the scrolling region, the specified scrolling interval, * and the specified numbers of items fixed at the top and bottom of the * popup menu. * * @param menu the popup menu * @param scrollCount the number of items to display in the scrolling portion * @param interval the scroll interval, in milliseconds * @param topFixedCount the number of items to fix at the top. May be 0 * @param bottomFixedCount the number of items to fix at the bottom. May be 0 * @throws IllegalArgumentException if scrollCount or interval is 0 or * negative or if topFixedCount or bottomFixedCount is negative * @return the JMenuScroller */ public static JMenuScroller setScrollerFor(JPopupMenu menu, int scrollCount, int interval, int topFixedCount, int bottomFixedCount) { return new JMenuScroller(menu, scrollCount, interval, topFixedCount, bottomFixedCount); } /** * Constructs a <code>JMenuScroller</code> that scrolls a menu with the * default number of items to display at a time, and default scrolling * interval. * * @param menu the menu */ public JMenuScroller(JMenu menu) { this(menu, 15); } /** * Constructs a <code>JMenuScroller</code> that scrolls a popup menu with the * default number of items to display at a time, and default scrolling * interval. * * @param menu the popup menu */ public JMenuScroller(JPopupMenu menu) { this(menu, 15); } /** * Constructs a <code>JMenuScroller</code> that scrolls a menu with the * specified number of items to display at a time, and default scrolling * interval. * * @param menu the menu * @param scrollCount the number of items to display at a time * @throws IllegalArgumentException if scrollCount is 0 or negative */ public JMenuScroller(JMenu menu, int scrollCount) { this(menu, scrollCount, 150); } /** * Constructs a <code>JMenuScroller</code> that scrolls a popup menu with the * specified number of items to display at a time, and default scrolling * interval. * * @param menu the popup menu * @param scrollCount the number of items to display at a time * @throws IllegalArgumentException if scrollCount is 0 or negative */ public JMenuScroller(JPopupMenu menu, int scrollCount) { this(menu, scrollCount, 150); } /** * Constructs a <code>JMenuScroller</code> that scrolls a menu with the * specified number of items to display at a time, and specified scrolling * interval. * * @param menu the menu * @param scrollCount the number of items to display at a time * @param interval the scroll interval, in milliseconds * @throws IllegalArgumentException if scrollCount or interval is 0 or negative */ public JMenuScroller(JMenu menu, int scrollCount, int interval) { this(menu, scrollCount, interval, 0, 0); } /** * Constructs a <code>JMenuScroller</code> that scrolls a popup menu with the * specified number of items to display at a time, and specified scrolling * interval. * * @param menu the popup menu * @param scrollCount the number of items to display at a time * @param interval the scroll interval, in milliseconds * @throws IllegalArgumentException if scrollCount or interval is 0 or negative */ public JMenuScroller(JPopupMenu menu, int scrollCount, int interval) { this(menu, scrollCount, interval, 0, 0); } /** * Constructs a <code>JMenuScroller</code> that scrolls a menu with the * specified number of items to display in the scrolling region, the * specified scrolling interval, and the specified numbers of items fixed at * the top and bottom of the menu. * * @param menu the menu * @param scrollCount the number of items to display in the scrolling portion * @param interval the scroll interval, in milliseconds * @param topFixedCount the number of items to fix at the top. May be 0 * @param bottomFixedCount the number of items to fix at the bottom. May be 0 * @throws IllegalArgumentException if scrollCount or interval is 0 or * negative or if topFixedCount or bottomFixedCount is negative */ public JMenuScroller(JMenu menu, int scrollCount, int interval, int topFixedCount, int bottomFixedCount) { this(menu.getPopupMenu(), scrollCount, interval, topFixedCount, bottomFixedCount); } /** * Constructs a <code>JMenuScroller</code> that scrolls a popup menu with the * specified number of items to display in the scrolling region, the * specified scrolling interval, and the specified numbers of items fixed at * the top and bottom of the popup menu. * * @param menu the popup menu * @param scrollCount the number of items to display in the scrolling portion * @param interval the scroll interval, in milliseconds * @param topFixedCount the number of items to fix at the top. May be 0 * @param bottomFixedCount the number of items to fix at the bottom. May be 0 * @throws IllegalArgumentException if scrollCount or interval is 0 or * negative or if topFixedCount or bottomFixedCount is negative */ public JMenuScroller(JPopupMenu menu, int scrollCount, int interval, int topFixedCount, int bottomFixedCount) { if (scrollCount <= 0 || interval <= 0) { throw new IllegalArgumentException("scrollCount and interval must be greater than 0"); } if (topFixedCount < 0 || bottomFixedCount < 0) { throw new IllegalArgumentException("topFixedCount and bottomFixedCount cannot be negative"); } upItem = new MenuScrollItem(UP, -1); downItem = new MenuScrollItem(DOWN, +1); setScrollCount(scrollCount); setInterval(interval); setTopFixedCount(topFixedCount); setBottomFixedCount(bottomFixedCount); this.menu = menu; menu.addPopupMenuListener(menuListener); } /** * Returns the scroll interval in milliseconds * * @return the scroll interval in milliseconds */ public int getInterval() { return interval; } /** * Sets the scroll interval in milliseconds * * @param interval the scroll interval in milliseconds * @throws IllegalArgumentException if interval is 0 or negative */ public void setInterval(int interval) { if (interval <= 0) { throw new IllegalArgumentException("interval must be greater than 0"); } upItem.setInterval(interval); downItem.setInterval(interval); this.interval = interval; } /** * Returns the number of items in the scrolling portion of the menu. * * @return the number of items to display at a time */ public int getscrollCount() { return scrollCount; } /** * Sets the number of items in the scrolling portion of the menu. * * @param scrollCount the number of items to display at a time * @throws IllegalArgumentException if scrollCount is 0 or negative */ public void setScrollCount(int scrollCount) { if (scrollCount <= 0) { throw new IllegalArgumentException("scrollCount must be greater than 0"); } this.scrollCount = scrollCount; // XXX the following line closes all menus then this menu is made. // That doesn't seem right. // MenuSelectionManager.defaultManager().clearSelectedPath(); } /** * Returns the number of items fixed at the top of the menu or popup menu. * * @return the number of items */ public int getTopFixedCount() { return topFixedCount; } /** * Sets the number of items to fix at the top of the menu or popup menu. * * @param topFixedCount the number of items */ public void setTopFixedCount(int topFixedCount) { if (firstIndex <= topFixedCount) { firstIndex = topFixedCount; } else { firstIndex += (topFixedCount - this.topFixedCount); } this.topFixedCount = topFixedCount; } /** * Returns the number of items fixed at the bottom of the menu or popup menu. * * @return the number of items */ public int getBottomFixedCount() { return bottomFixedCount; } /** * Sets the number of items to fix at the bottom of the menu or popup menu. * * @param bottomFixedCount the number of items */ public void setBottomFixedCount(int bottomFixedCount) { this.bottomFixedCount = bottomFixedCount; } /** * Scrolls the specified item into view each time the menu is opened. Call this method with * <code>null</code> to restore the default behavior, which is to show the menu as it last * appeared. * * @param item the item to keep visible * @see #keepVisible(int) */ public void keepVisible(JMenuItem item) { if (item == null) { keepVisibleIndex = -1; } else { int index = menu.getComponentIndex(item); keepVisibleIndex = index; } } /** * Scrolls the item at the specified index into view each time the menu is opened. Call this * method with <code>-1</code> to restore the default behavior, which is to show the menu as * it last appeared. * * @param index the index of the item to keep visible * @see #keepVisible(javax.swing.JMenuItem) */ public void keepVisible(int index) { keepVisibleIndex = index; } /** * Removes this JMenuScroller from the associated menu and restores the * default behavior of the menu. */ public void dispose() { if (menu != null) { menu.removePopupMenuListener(menuListener); menu = null; } } /** * Ensures that the <code>dispose</code> method of this JMenuScroller is * called when there are no more refrences to it. * * @exception Throwable if an error occurs. * @see JMenuScroller#dispose() */ @Override public void finalize() throws Throwable { dispose(); } private void refreshMenu() { if (menuItems != null && menuItems.length > 0) { firstIndex = Math.max(topFixedCount, firstIndex); firstIndex = Math.min(menuItems.length - bottomFixedCount - scrollCount, firstIndex); upItem.setEnabled(firstIndex > topFixedCount); downItem.setEnabled(firstIndex + scrollCount < menuItems.length - bottomFixedCount); menu.removeAll(); for (int i = 0; i < topFixedCount; i++) { menu.add(menuItems[i]); } if (topFixedCount > 0) { menu.addSeparator(); } menu.add(upItem); for (int i = firstIndex; i < scrollCount + firstIndex; i++) { menu.add(menuItems[i]); } menu.add(downItem); if (bottomFixedCount > 0) { menu.addSeparator(); } for (int i = menuItems.length - bottomFixedCount; i < menuItems.length; i++) { menu.add(menuItems[i]); } JComponent parent = (JComponent) upItem.getParent(); parent.revalidate(); parent.repaint(); } } private class MenuScrollListener implements PopupMenuListener { @Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) { if (fillMenu != null) { clearPopupMenu(menu); callF(fillMenu, menu); } setMenuItems(); } @Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { if (fillMenu != null) clearPopupMenu(menu); else restoreMenuItems(); } @Override public void popupMenuCanceled(PopupMenuEvent e) { if (fillMenu != null) clearPopupMenu(menu); else restoreMenuItems(); } private void setMenuItems() { menuItems = menu.getComponents(); if (keepVisibleIndex >= topFixedCount && keepVisibleIndex <= menuItems.length - bottomFixedCount && (keepVisibleIndex > firstIndex + scrollCount || keepVisibleIndex < firstIndex)) { firstIndex = Math.min(firstIndex, keepVisibleIndex); firstIndex = Math.max(firstIndex, keepVisibleIndex - scrollCount + 1); } if (menuItems.length > topFixedCount + scrollCount + bottomFixedCount) { refreshMenu(); } } private void restoreMenuItems() { menu.removeAll(); for (Component component : menuItems) { menu.add(component); } } } private class MenuScrollTimer extends javax.swing.Timer { public MenuScrollTimer(final int increment, int interval) { super(interval, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { firstIndex += increment; refreshMenu(); } }); } } private class MenuScrollItem extends JMenuItem implements ChangeListener { private MenuScrollTimer timer; public MenuScrollItem(MenuIcon icon, int increment) { setIcon(icon); setDisabledIcon(icon); timer = new MenuScrollTimer(increment, interval); addChangeListener(this); } public void setInterval(int interval) { timer.setDelay(interval); } @Override public void stateChanged(ChangeEvent e) { if (isArmed() && !timer.isRunning()) { timer.start(); } if (!isArmed() && timer.isRunning()) { timer.stop(); } } } static MenuIcon UP = new MenuIcon(9, 1, 9); static MenuIcon DOWN = new MenuIcon(1, 9, 1); private static class MenuIcon implements Icon { final int[] xPoints = {1, 5, 9}; final int[] yPoints; MenuIcon(int... yPoints) { this.yPoints = yPoints; } @Override public void paintIcon(Component c, Graphics g, int x, int y) { Dimension size = c.getSize(); Graphics g2 = g.create(size.width / 2 - 5, size.height / 2 - 5, 10, 10); g2.setColor(Color.GRAY); g2.drawPolygon(xPoints, yPoints, 3); if (c.isEnabled()) { g2.setColor(Color.BLACK); g2.fillPolygon(xPoints, yPoints, 3); } g2.dispose(); } @Override public int getIconWidth() { return 0; } @Override public int getIconHeight() { return 10; } } } // progID is just for information static class JavaXClassLoader extends URLClassLoader { String progID; Set<File> files = syncLinkedHashSet(); Set<String> libraryIDs = syncLinkedHashSet(); Set<String> triedToLoad = synchroSet(); Set<Class> loadedClasses = synchroSet(); boolean retired = false; Object retiredMarker; IF1<String, Class> findClass_extension; String mainClassName; boolean verbose = false; JavaXClassLoader(String progID, List<File> files) { this(progID, files, getSystemClassLoader()); } JavaXClassLoader(String progID, List<File> files, ClassLoader parent) { // sadly can't see this constructor //super(progID, new URL[0], parent, vm_globalACC()); super(new URL[0], parent); this.progID = progID; for (File f : unnullForIteration(files)) addFile(f); // TODO: how to get around this fixACCInClassLoader(this); } Class<?> super_findClass(String name) throws ClassNotFoundException { return super.findClass(name); } protected Class<?> findClass(String name) throws ClassNotFoundException { if (verbose) System.out.println(this + " findClass: " + name); if (findClass_extension != null) { Class<?> c = findClass_extension.get(name); if (verbose) System.out.println("extension returned: " + c); if (c != null) return c; } boolean triedBefore = !triedToLoad.add(name); try { Class<?> c = super.findClass(name); if (verbose) System.out.println("super.findClass returned: " + c); loadedClasses.add(c); if (eq(name, mainClassName())) callOpt(javax(), "registerAMainClass", c); return c; } catch (ClassNotFoundException e) { if (verbose) System.out.println(getStackTrace(e)); throw new ClassNotFoundException("Class " + name + " not found in " + joinWithComma(map(__50 -> f2s(__50), files)) + " (progID=" + progID + ")" + (triedBefore ? ", tried to load before" : ""), e); } } public String toString() { return shortClassName(this) + "[" + systemHashCodeHex(this) + "] - " + progID; } String mainClassName() { if (mainClassName == null) { mainClassName = "main"; try { mainClassName = or2(trim(loadTextFileResource(this, "main-class")), mainClassName); } catch (Throwable __e) { printStackTrace(__e); } } return mainClassName; } boolean addFile(File f, String libraryID) { if (nempty(libraryID)) if (!libraryIDs.add(libraryID)) return false; return addFile(f); } boolean addFile(File f) { try { if (!files.add(f)) return false; addURL(f.toURI().toURL()); mainClassName(); // calculate early. no good loading text files later return true; } catch (Exception __e) { throw rethrow(__e); } } Set<String> libraryIDs() { return libraryIDs; } boolean hasLibraryID(String libraryID) { return libraryIDs.contains(libraryID); } protected transient IF1<String, String> findLibrary; protected String findLibrary(String libname) { return findLibrary != null ? findLibrary.get(libname) : findLibrary_base(libname); } final protected String findLibrary_fallback(IF1<String, String> _f, String libname) { return _f != null ? _f.get(libname) : findLibrary_base(libname); } protected String findLibrary_base(String libname) { return super.findLibrary(libname); } // make public public void addURL(URL url) { super.addURL(url); } } interface IGetterWithNotify<A> extends IF0<A>, IHasChangeListeners { } abstract static class CompactAbstractMap<K, V> implements Map<K, V> { public int size() { return entrySet().size(); } public boolean isEmpty() { return size() == 0; } public boolean containsValue(Object value) { Iterator<Entry<K, V>> i = entrySet().iterator(); if (value == null) { while (i.hasNext()) { Entry<K, V> e = i.next(); if (e.getValue() == null) return true; } } else { while (i.hasNext()) { Entry<K, V> e = i.next(); if (value.equals(e.getValue())) return true; } } return false; } public boolean containsKey(Object key) { Iterator<Entry<K, V>> i = entrySet().iterator(); if (key == null) { while (i.hasNext()) { Entry<K, V> e = i.next(); if (e.getKey() == null) return true; } } else { while (i.hasNext()) { Entry<K, V> e = i.next(); if (key.equals(e.getKey())) return true; } } return false; } public V get(Object key) { Iterator<Entry<K, V>> i = entrySet().iterator(); if (key == null) { while (i.hasNext()) { Entry<K, V> e = i.next(); if (e.getKey() == null) return e.getValue(); } } else { while (i.hasNext()) { Entry<K, V> e = i.next(); if (key.equals(e.getKey())) return e.getValue(); } } return null; } public V put(K key, V value) { throw new UnsupportedOperationException(); } public V remove(Object key) { Iterator<Entry<K, V>> i = entrySet().iterator(); Entry<K, V> correctEntry = null; if (key == null) { while (correctEntry == null && i.hasNext()) { Entry<K, V> e = i.next(); if (e.getKey() == null) correctEntry = e; } } else { while (correctEntry == null && i.hasNext()) { Entry<K, V> e = i.next(); if (key.equals(e.getKey())) correctEntry = e; } } V oldValue = null; if (correctEntry != null) { oldValue = correctEntry.getValue(); i.remove(); } return oldValue; } public void putAll(Map<? extends K, ? extends V> m) { for (Entry<? extends K, ? extends V> e : m.entrySet()) put(e.getKey(), e.getValue()); } public void clear() { entrySet().clear(); } public Set<K> keySet() { return new AbstractSet<K>() { public Iterator<K> iterator() { return new Iterator<K>() { private Iterator<Entry<K, V>> i = entrySet().iterator(); public boolean hasNext() { return i.hasNext(); } public K next() { return i.next().getKey(); } public void remove() { i.remove(); } }; } public int size() { return CompactAbstractMap.this.size(); } public boolean isEmpty() { return CompactAbstractMap.this.isEmpty(); } public void clear() { CompactAbstractMap.this.clear(); } public boolean contains(Object k) { return CompactAbstractMap.this.containsKey(k); } }; } public Collection<V> values() { return new AbstractCollection<V>() { public Iterator<V> iterator() { return new Iterator<V>() { private Iterator<Entry<K, V>> i = entrySet().iterator(); public boolean hasNext() { return i.hasNext(); } public V next() { return i.next().getValue(); } public void remove() { i.remove(); } }; } public int size() { return CompactAbstractMap.this.size(); } public boolean isEmpty() { return CompactAbstractMap.this.isEmpty(); } public void clear() { CompactAbstractMap.this.clear(); } public boolean contains(Object v) { return CompactAbstractMap.this.containsValue(v); } }; } public abstract Set<Entry<K, V>> entrySet(); public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof Map)) return false; Map<?, ?> m = (Map<?, ?>) o; if (m.size() != size()) return false; try { for (Entry<K, V> e : entrySet()) { K key = e.getKey(); V value = e.getValue(); if (value == null) { if (!(m.get(key) == null && m.containsKey(key))) return false; } else { if (!value.equals(m.get(key))) return false; } } } catch (ClassCastException unused) { return false; } catch (NullPointerException unused) { return false; } return true; } public int hashCode() { int h = 0; for (Entry<K, V> entry : entrySet()) h += entry.hashCode(); return h; } public String toString() { Iterator<Entry<K, V>> i = entrySet().iterator(); if (!i.hasNext()) return "{}"; StringBuilder sb = new StringBuilder(); sb.append('{'); for (; ; ) { Entry<K, V> e = i.next(); K key = e.getKey(); V value = e.getValue(); sb.append(key == this ? "(this Map)" : key); sb.append('='); sb.append(value == this ? "(this Map)" : value); if (!i.hasNext()) return sb.append('}').toString(); sb.append(',').append(' '); } } protected Object clone() throws CloneNotSupportedException { CompactAbstractMap<?, ?> result = (CompactAbstractMap<?, ?>) super.clone(); return result; } public static class SimpleEntry<K, V> implements Entry<K, V>, java.io.Serializable { @java.io.Serial private static final long serialVersionUID = -8499721149061103585L; @SuppressWarnings("serial") private final K key; @SuppressWarnings("serial") private V value; public SimpleEntry(K key, V value) { this.key = key; this.value = value; } public SimpleEntry(Entry<? extends K, ? extends V> entry) { this.key = entry.getKey(); this.value = entry.getValue(); } public K getKey() { return key; } public V getValue() { return value; } public V setValue(V value) { V oldValue = this.value; this.value = value; return oldValue; } public boolean equals(Object o) { if (!(o instanceof Map.Entry)) return false; Entry<?, ?> e = (Entry<?, ?>) o; return eq(key, e.getKey()) && eq(value, e.getValue()); } public int hashCode() { return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode()); } public String toString() { return key + "=" + value; } } public static class SimpleImmutableEntry<K, V> implements Entry<K, V>, java.io.Serializable { @java.io.Serial private static final long serialVersionUID = 7138329143949025153L; @SuppressWarnings("serial") private final K key; @SuppressWarnings("serial") private final V value; public SimpleImmutableEntry(K key, V value) { this.key = key; this.value = value; } public SimpleImmutableEntry(Entry<? extends K, ? extends V> entry) { this.key = entry.getKey(); this.value = entry.getValue(); } public K getKey() { return key; } public V getValue() { return value; } public V setValue(V value) { throw new UnsupportedOperationException(); } public boolean equals(Object o) { if (!(o instanceof Map.Entry)) return false; Entry<?, ?> e = (Entry<?, ?>) o; return eq(key, e.getKey()) && eq(value, e.getValue()); } public int hashCode() { return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode()); } public String toString() { return key + "=" + value; } } } static boolean scaffoldingEnabled(Object o) { return metaGet(o, "scaffolding") != null; } static void change() { //mainConcepts.allChanged(); // safe version for now cause function is sometimes included unnecessarily (e.g. by EGDiff) callOpt(getOptMC("mainConcepts"), "allChanged"); } static Border getBorder(final JComponent c) { return c == null ? null : swing(new F0<Border>() { public Border get() { try { return c.getBorder(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return c.getBorder();"; }}); } static <A> Value<A> value(A a) { return new Value<A>(a); } static <A, B> boolean containsKey(Map<A, B> map, A key) { return map != null && map.containsKey(key); } static HashMap<String, Class> findClass_cache = new HashMap(); // currently finds only inner classes of class "main" // returns null on not found // this is the simple version that is not case-tolerant static Class findClass(String name) { synchronized(findClass_cache) { if (findClass_cache.containsKey(name)) return findClass_cache.get(name); if (!isJavaIdentifier(name)) return null; Class c; try { c = Class.forName("main$" + name); } catch (ClassNotFoundException e) { c = null; } findClass_cache.put(name, c); return c; } } static ClassLoader getVirtualParent(ClassLoader cl) { return (ClassLoader) rcallOpt("getVirtualParent", cl); } static double fracNonNeg(double d) { return frac_nonNeg(d); } static double twoPi() { return Math.PI*2; } static String plusPrefixUnlessMinus(String s) { return startsWith(s, "-") ? s : "+" + s; } static void addSeparator(JMenu menu) { menu.addSeparator(); } static void addSeparator(JPopupMenu menu) { menu.addSeparator(); } static void truncateContainer(Container c, int n) { swing(() -> { if (c != null) while (c.getComponentCount() > n) c.remove(c.getComponentCount()-1); }); } static <A extends Component> A packWindow(final A c) { { swing(() -> { Window w = getWindow(c); if (w != null) w.pack(); }); } return c; } static <A> VF1<A> toVF1(IVF1<A> f) { return ivf1ToVF1(f); } static PtInComponent ptInComponentFromEvent(MouseEvent evt) { return new PtInComponent(evt.getComponent(), pt(evt.getX(), evt.getY())); } static boolean hasParentOfType(Class<?> type, Component c) { return parentOfType(c, type) != null; } static String formatDouble_significant2(double d, int digits) { try { digits -= max(0, Math.floor(Math.log10(abs(d))+1)); return formatDouble(d, digits); } catch (Throwable _e) { print("Had number: " + d + ", digits: " + digits); throw rethrow(_e); } } static void setComponent(SingleComponentPanel scp, Component c) { setSCPComponent(scp, c); } static void setComponent(SingleComponentPanel scp, IF0<Component> c) { if (scp != null) setComponent(scp, callF(c)); } static <A> void removeAll(Collection<A> a, Collection<A> b) { if (a != null && b != null) a.removeAll(b); } static <A, B> void removeAll(Map<A, B> a, Collection<A> b) { if (a != null && b != null) for (A x : b) a.remove(x); } static <A, B extends A> boolean removeAll(Collection<A> c, B... b) { return c != null && b != null && c.removeAll(Arrays.asList(b)); } static <A, B> void removeAll(Map<A, B> a, A... b) { if (a != null && b != null) for (A x : b) a.remove(x); } static Container _getParent(Component c) { return getParent(c); } static boolean getServerTranspiled2_allowLocalFallback = true, getServerTranspiled2_localFallbackVerbose = true; // to avoid checking server for transpilations too often when booting OS static Map<String, String> getServerTranspiled2_tempCache; static String getServerTranspiled2(String id) { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.getTranspiled(id); return getServerTranspiled2_noResourceLoader(id); } static String getServerTranspiled2_noResourceLoader(String id) { id = fsIOpt(id); String transpiled = mapGet(getServerTranspiled2_tempCache, id); if (transpiled != null) return transpiled; //if (getServerTranspiled2_tempCache != null) print("CACHE FAIL on " + id); transpiled = loadCachedTranspilation(id); String md5 = null; if (machineIsOffline() || isOfflineMode() || isLocalSnippet(id)) return transpiled; if (transpiled != null) md5 = md5(transpiled); String transpiledSrc; try { transpiledSrc = getServerTranspiled(formatSnippetID(id), md5); } catch (Throwable e) { if (!getServerTranspiled2_allowLocalFallback) rethrow(e); printExceptionShort(e); if (getServerTranspiled2_localFallbackVerbose) print("Fallback to local code"); return transpiled; } if (eq(transpiledSrc, "SAME")) { if (!isTrue(loadPage_silent.get())) print("SAME"); return mapPut_returnValue(getServerTranspiled2_tempCache, id, transpiled); } return mapPut_returnValue(getServerTranspiled2_tempCache, id, transpiledSrc); } static String fsIOpt(String s) { return formatSnippetIDOpt(s); } // assumes main class is last declared class // returns actual CNC static List<String> findMainClass(List<String> tok) { for (List<String> c : reversedList(allClasses(tok))) { String name = getClassDeclarationName(c); if (eq(name, "main") || name.startsWith("x")) return c; } return findBlock("m {", tok); } static boolean useDummyMainClasses() { return true; //ret eq("1", trim(loadTextFile(getProgramFile(#1008755, "use-dummy-main-classes")))); } static boolean tok_classHasModifier(List<String> classDecl, String modifier) { if (classDecl == null) return false; int i = classDecl.indexOf("class"); return subList(classDecl, 0, i).contains(modifier); } static String joinNemptiesWithDot(Object... strings) { return joinNempties(".", strings); } static String joinNemptiesWithDot(Iterable strings) { return joinNempties(".", strings); } static String tok_packageName(List<String> tok) { int i = jfind(tok, "package"); if (i < 0) return ""; i += 2; int j = jfind(tok, i, ";"); if (j < 0) return ""; return join(codeTokensOnly(subList(tok, i-1, j))); } static String tok_packageName(String src) { Producer<String> p = javaTokC_producer(src); String t = p.next(); if (!eq(t, "package")) return ""; StringBuilder buf = new StringBuilder(); while (!eqOneOf(t = p.next(), null, ";")) buf.append(t); return str(buf); } static String getClassDeclarationName(List<String> tok) { if (tok != null) for (int i = 1; i+2 < tok.size(); i += 2) if (allClasses_keywords.contains(tok.get(i)) && isIdentifier(tok.get(i+2))) { while (contains(getClassDeclarationName_skippables(), get(tok, i+2))) i += 2; return tok.get(i+2); } return null; } static String manifestPathInJar() { return "META-INF/MANIFEST.MF"; } static String manifestTextForMainClass(String mainClass) { return "Manifest-Version: 1.0\n" + "Main-Class: " + mainClass + "\n\n"; } // before you use this, add a RAM disk cleaner static boolean javaCompileToJar_useRAMDisk = false; static ThreadLocal<List<File>> javaCompileToJar_localLibraries = new ThreadLocal(); static ThreadLocal<IVF1<File>> javaCompileToJar_addMoreFiles = new ThreadLocal(); static File javaCompileToJar_optionalRename(String src, File destJar, String progIDForRename) { return javaCompileToJar_optionalRename(src, "", destJar, progIDForRename); } static synchronized File javaCompileToJar_optionalRename(String src, String dehlibs, File destJar, String progIDForRename) { return javaCompileToJar_optionalRename(src, dehlibs, destJar, progIDForRename, null); } // returns path to jar static synchronized File javaCompileToJar_optionalRename(String src, String dehlibs, File destJar, String progIDForRename, String progID) { String javaTarget = null; // use default target //print("Compiling " + l(src) + " chars"); String dummyClass = "main"; if (progIDForRename != null) { dummyClass = dummyMainClassName(progIDForRename); src += "\nclass " + dummyClass + "{}"; } String md5 = md5(src); File jar = destJar; Class j = getJavaX(); if (javaTarget != null) setOpt(j, "javaTarget", javaTarget); //setOpt(j, "verbose", true); File srcDir = tempDir(); String fileName = dummyClass + ".java"; // deriver name of main Java file from source List<String> tok = javaTok(src); String packageName = tok_packageName(tok); if (packageName != null) fileName = packageName.replace(".", "/") + "/" + tok_firstClassName(tok) + ".java"; File mainJava = new File(srcDir, fileName); //print("main java: " + mainJava.getAbsolutePath()); saveTextFile(mainJava, src); File classesDir = javaCompileToJar_useRAMDisk ? tempDirPossiblyInRAMDisk() : tempDir(); //print("Compiling to " + f2s(classesDir)); try { List<File> libraries = cloneList(getAndClearTL(javaCompileToJar_localLibraries)); Matcher m = Pattern.compile("\\d+").matcher(dehlibs); while (m.find()) { String libID = m.group(); //print("libID=" + quote(libID)); assertTrue(isSnippetID(libID)); print("Adding library " + libID); libraries.add(loadLibraryOrSrcLib(libID)); } libraries.add(pathToJavaxJar()); String compilerOutput; try { compilerOutput = (String) call(j, "compileJava", srcDir, libraries, classesDir); } catch (Throwable e) { compilerOutput = (String) get(getJavaX(), "javaCompilerOutput"); //fail("Compile Error. " + cleanJavaCompilerOutput(compilerOutput) + " " + e); //compilerOutput = indentx("> ", cleanJavaCompilerOutput(compilerOutput)); //throw JavaCompilerException(compilerOutput, e); if (!swic(e.getMessage(), "Java compiler returned errors.")) compilerOutput = appendWithNewLine(compilerOutput, str(e)); //printStackTrace(e); throw fail(compilerOutput, e); } compilerOutput = cleanJavaCompilerOutput("Annotation processing got disabled, since it requires a 1.6 compliant JVM"); if (nempty(compilerOutput)) { print("Compiler said: " + compilerOutput); //fail("Compile Error. " + compilerOutput); } // sanity test if (!anyFileWithExtensionInDir(classesDir, ".class")) { printWithIndent("SRC> ", src); throw fail("No classes generated (was compiling " + nChars(src) + ")"); } // add sources to .jar saveTextFile(new File(classesDir, "main.java"), src); // add information about libraries to jar if (nempty(dehlibs)) saveTextFile(new File(classesDir, "libraries"), dehlibs); // add prog id to jar saveTextFile(new File(classesDir, "progID"), progID); // save pointer to main Java source //saveTextFile(new File(classesDir, "main-src"), fileName); callF(javaCompileToJar_addMoreFiles.get(), classesDir); print("Zipping: " + classesDir.getAbsolutePath() + " to " + jar.getAbsolutePath()); dir2zip_recurse_verbose = false; int n = dir2zip_recurse(classesDir, jar); // cache on success only print("Files zipped: " + n); return jar; } finally { if (isInRAMDisk(classesDir)) deleteDirectory(classesDir); } } // will create the file or update its last modified timestamp static File touchFile(File file) { try { closeRandomAccessFile(newRandomAccessFile(mkdirsForFile(file), "rw")); return file; } catch (Exception __e) { throw rethrow(__e); } } static String appendSlash(String s) { return addSlash(s); } static String compilerBotDestDirSubName() { return "JavaX-Caches/Compilations"; } static File compilerBotDestDir() { return actualUserDir(compilerBotDestDirSubName()); } static File compilerBotDestDir(String sub) { return newFile(compilerBotDestDir(), sub); } static void clearPopupMenu(final JPopupMenu menu) { if (menu != null) { swing(() -> { menu.removeAll(); }); } } static <A> Set<A> syncLinkedHashSet() { return synchroLinkedHashSet(); } static <A> Set<A> synchroSet() { return synchroHashSet(); } static <A> Set<A> synchroSet(Set<A> set) { return Collections.synchronizedSet(set); } // I believe this was meant to mitigate memory leaks. // Disabled now because JDK 17 doesn't allow it anyways. static void fixACCInClassLoader(Object o) { /*pcall { AccessControlContext acc = vm_globalACC(); if (acc != null) replaceACCInClassLoader(o, acc); }*/ } static String loadTextFileResource(ClassLoader cl, String name) { return inputStreamToString(cl.getResourceAsStream(name)); } static HashSet<String> allClasses_keywords = lithashset("class", "interface", "enum", "sclass", "sinterface", "record", "srecord", "strecord", "asclass", "concept"); // lists returned are actual CNC (N/C/N/.../C/N) - and connected to // original list // only returns the top level classes static List<List<String>> allClasses(List<String> tok) { List<List<String>> l = new ArrayList(); int n = tok.size(); HashSet<String> _allClasses_keywords = allClasses_keywords; for (int i = 1; i < n; i += 2) { String t = tok.get(i); if ("{".equals(t)) // skip functions i = findEndOfBlock(tok, i)-1; else if (_allClasses_keywords.contains(t) && (tok_isJavaxMetaCommandLeftOf(tok, i) || !(eqGetOneOf(tok, i-2, ".", "include") && !containsNewLine(tok.get(i-1))))) { int j = i; while (j < n && !tok.get(j).equals("{")) j += 2; j = findEndOfBlock(tok, j)+1; i = leftScanModifiers(tok, i); l.add(subList(tok, i-1, Math.min(n, j))); i = j-2; } } return l; } static List<List<String>> allClasses(String text) { return allClasses(javaTok(text)); } static Object getOptMC(String field) { return getOpt(mc(), field); } static Object rcallOpt(String method, Object o, Object... args) { return callOpt_withVarargs(o, method, args); } static double frac_nonNeg(double d) { return mod(d, 1); } static Pt pt(int x, int y) { return new Pt(x, y); } static Pt pt(int x) { return new Pt(x, x); } static <A> A parentOfType(Component _c, Class<A> theClass) { return swing(() -> { Component c = _c; while (c != null) { if (isInstance(theClass, c)) return (A) c; c = c.getParent(); } return null; }); } static float abs(float f) { return Math.abs(f); } static int abs(int i) { return Math.abs(i); } static double abs(double d) { return Math.abs(d); } static double abs(Complex c) { return c.abs(); } static String formatDouble(double d, int digits) { String format = digits <= 0 ? "0" : "0." + rep(digits, '#'); return decimalFormatEnglish(format, d); } static String formatDouble(double d) { return str(d); } static void setSCPComponent(SingleComponentPanel scp, Component c) { if (scp != null) scp.setComponent(c); } static Container getParent(final Component c) { return c == null ? null : swing(new F0<Container>() { public Container get() { try { return c.getParent(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return c.getParent();"; }}); } static String loadCachedTranspilation(String id) { try { return loadTextFilePossiblyGZipped(getCachedTranspilationFile(id)); } catch (Throwable __e) { return null; } } static boolean machineIsOffline() { return isFalse(callF(vmGeneralMap_get("areWeOnline"))); } static boolean isOfflineMode() { return eq("1", trim(loadProgramTextFile("#1005806", "offline-mode"))); } static boolean isLocalSnippet(String snippetID) { return isLocalSnippetID(snippetID); } static boolean isLocalSnippet(long snippetID) { return isLocalSnippetID(snippetID); } static String getServerTranspiled(String snippetID) { return getServerTranspiled(snippetID, null); } static boolean getServerTranspiled_printStackTrace = false; // returns "SAME" if md5 matches static String getServerTranspiled(String snippetID, String expectedMD5) { try { if (getServerTranspiled_printStackTrace) printStackTrace(); long id = parseSnippetID(snippetID); /*S t = getTranspilationFromBossBot(id); if (t != null) return t;*/ String text = loadPage_utf8(tb_mainServer() + "/tb-int/get-transpiled.php?raw=1&withlibs=1&id=" + id + "&utf8=1" + (l(expectedMD5) > 1 ? "&md5=" + urlencode(expectedMD5) : "") + standardCredentials()); if (nempty(text) && neq(text, "SAME")) saveTranspiledCode(snippetID, text); return text; } catch (Exception __e) { throw rethrow(__e); } } static void printExceptionShort(Throwable e) { printExceptionShort("", e); } static void printExceptionShort(String prefix, Throwable e) { print(prefix, exceptionToStringShort(e)); } static <A, B> B mapPut_returnValue(Map<A, B> map, A key, B value) { mapPut(map, key, value); return value; } static <A> List<A> reversedList(Iterable<A> l) { List<A> x = cloneList(l); Collections.reverse(x); return x; } static List<String> findBlock(String pat, List<String> tok) { List<String> tokpat = javaTok(pat); int i = findCodeTokens(tok, toStringArray(codeTokensOnly(tokpat))); //print("index of block " + quote(pat) + ": " + i); if (i < 0) return null; int bracketIdx = i+tokpat.size()-3; assertEquals("{", tok.get(bracketIdx)); int endIdx = findEndOfBlock(tok, bracketIdx); return subList(tok, i-1, endIdx+1); // make it actual CNC } static List<String> codeTokensOnly(List<String> tok) { int n = l(tok); List<String> l = emptyList(n/2); for (int i = 1; i < n; i += 2) l.add(tok.get(i)); return l; } static Producer<String> javaTokC_producer(String s) { return javaTokC_iterator(s); } static Set<String> getClassDeclarationName_skippables_cache; static Set<String> getClassDeclarationName_skippables() { if (getClassDeclarationName_skippables_cache == null) getClassDeclarationName_skippables_cache = getClassDeclarationName_skippables_load(); return getClassDeclarationName_skippables_cache;} static Set<String> getClassDeclarationName_skippables_load() { return litset("noeq", "mapMethodLike"); } static String dummyMainClassName(String progID) { return "m" + psI(progID); } static File tempDir() { return makeTempDir(); } static String tok_firstClassName(List<String> tok) { int i = jfind(tok, "class <id>"); return i < 0 ? null : tok.get(i+2); } static File tempDirPossiblyInRAMDisk() { File f = linux_fileInRamDisk(aGlobalID()); if (f != null) { f.mkdirs(); return f; } return makeTempDir(); } static <A> A getAndClearTL(ThreadLocal<A> tl) { return getAndClearThreadLocal(tl); } static boolean loadLibraryOrSrcLib_srcLibsEnabled = true; // to avoid checking src libs too often when booting OS static ThreadLocal<Map<Long, File>> loadLibraryOrSrcLib_tempCache = new ThreadLocal(); static ThreadLocal<IF1<String, File>> loadLibraryOrSrcLib_compiler = new ThreadLocal(); static File loadLibraryOrSrcLib(String snippetID) { return loadLibraryOrSrcLib(snippetID, loadLibraryOrSrcLib_compiler.get()); } static File loadLibraryOrSrcLib(String snippetID, IF1<String, File> compiler) { try { vmBus_send("loadLibraryOrSrcLib", snippetID); long id = parseSnippetID(snippetID); if (loadLibraryOrSrcLib_tempCache.get() != null) { File f = loadLibraryOrSrcLib_tempCache.get().get(id); if (f != null) { print(snippetID + " from tempCache: " + f); return f; } } boolean srcLib = loadLibraryOrSrcLib_srcLibsEnabled && isMarkedAsSrcLib(snippetID); if (srcLib) { print(snippetID + " marked as src lib, compiling"); File f; if (compiler != null) f = compiler.get(snippetID); else f = pairA(hotwire_compile(snippetID)); print("Src lib: " + f); mapPut(loadLibraryOrSrcLib_tempCache.get(), id, f); return f; } File f = DiskSnippetCache_getLibrary(id); if (fileSize(f) != 0) { print(snippetID + " from disk cache: " + f); return f; } try { print("Trying " + snippetID + " as binary library"); return loadDataSnippetToFile(snippetID); } catch (Throwable e) { if (loadLibraryOrSrcLib_srcLibsEnabled) { print("Trying " + snippetID + " as src lib"); if (nempty(loadSnippet(snippetID))) { print("Is src lib."); markAsSrcLib(snippetID); return pairA(hotwire_compile(snippetID)); } } throw rethrow(e); } } catch (Exception __e) { throw rethrow(__e); } } static String appendWithNewLine(String a, String b) { if (empty(b)) return a; if (empty(a)) return b; return addSuffix(a, "\n") + b; } static String cleanJavaCompilerOutput(String s) { return dropPrefixTrim("Annotation processing got disabled, since it requires a 1.6 compliant JVM", s); } static boolean anyFileWithExtensionInDir(File dir, String ext) { return nempty(filesWithExtension(ext, findAllFiles_noDirs(dir))); } static <A> A printWithIndent(A o) { return printIndent(o); } static <A> A printWithIndent(String indent, A o) { return printIndent(indent, o); } static void printWithIndent(int indent, Object o) { printIndent(indent, o); } static String nChars(long n) { return n2(n, "char"); } static String nChars(String s) { return nChars(l(s)); } static boolean dir2zip_recurse_verbose = false; static int dir2zip_recurse(File inDir, File zip) { return dir2zip_recurse(inDir, zip, ""); } // TODO: the zero files case? static int dir2zip_recurse(File inDir, File zip, String outPrefix) { try { mkdirsForFile(zip); FileOutputStream fout = newFileOutputStream(zip); ZipOutputStream outZip = new ZipOutputStream(fout); try { return dir2zip_recurse(inDir, outZip, outPrefix, 0); } finally { outZip.close(); } } catch (Exception __e) { throw rethrow(__e); } } static int dir2zip_recurse(File inDir, ZipOutputStream outZip) { return dir2zip_recurse(inDir, outZip, "", 0); } static int dir2zip_recurse(File inDir, ZipOutputStream outZip, String outPrefix, int level) { try { if (++level >= 20) throw fail("woot? 20 levels in zip?"); List<File> files = new ArrayList(); for (File f : listFiles(inDir)) files.add(f); int n = 0; sortFilesByName(files); for (File f : files) { if (f.isDirectory()) { if (dir2zip_recurse_verbose) print("dir2zip_recurse: Scanning " + f.getAbsolutePath()); n += dir2zip_recurse(f, outZip, outPrefix + f.getName() + "/", level); } else { if (dir2zip_recurse_verbose) print("Copying " + f.getName()); outZip.putNextEntry(new ZipEntry(outPrefix + f.getName())); InputStream fin = new FileInputStream(f); copyStream(fin, outZip); fin.close(); ++n; } } return n; } catch (Exception __e) { throw rethrow(__e); } } static boolean isInRAMDisk(File f) { return startsWithOneOf(f2s(f), "/dev/shm/", "/run/shm/"); } static void deleteDirectory(File dir) { deleteDirectory(dir, false, false); } static void deleteDirectory(File dir, boolean verbose, boolean testRun) { deleteAllFilesInDirectory(dir, verbose, testRun); if (verbose) print((testRun ? "Would delete " : "Deleting ") + dir.getAbsolutePath()); if (!testRun) dir.delete(); } static void closeRandomAccessFile(RandomAccessFile f) { if (f != null) try { f.close(); callJavaX("dropIO", f); } catch (Throwable e) { printStackTrace(e); } } static RandomAccessFile newRandomAccessFile(File path, String mode) { try { boolean forWrite = mode.indexOf('w') >= 0; if (forWrite) mkdirsForFile(path); RandomAccessFile f = new RandomAccessFile(path, mode); callJavaX("registerIO", f, path, forWrite); return f; } catch (Exception __e) { throw rethrow(__e); } } static String addSlash(String s) { return empty(s) || s.endsWith("/") ? s : s + "/"; } static File actualUserDir() { return new File(actualUserHome()); } static File actualUserDir(String path) { return new File(actualUserHome(), path); } // BREAKING CHANGE! // Also NOTE: Iterators of these sync-wrapped collections // after generally NOT thread-safe! // TODO: change that? static <A> Set<A> synchroLinkedHashSet() { return Collections.synchronizedSet(new CompactLinkedHashSet()); } static String inputStreamToString(InputStream in) { return utf8streamToString(in); } // i must point at the (possibly imaginary) opening bracket ("{") // index returned is index of closing bracket + 1 (or l(tok)) static int findEndOfBlock(List<String> tok, int i) { return tok_findEndOfBlock(tok, i); } // i points at C token after suspected meta command static boolean tok_isJavaxMetaCommandLeftOf(List<String> tok, int i) { int j = i-2*4-1; if (j >= 0 && jfind(subList(tok, j, i), "set flag <id> .") == 1) return true; return false; } static <A> boolean eqGetOneOf(List<A> l, int i, A... options) { return eqOneOf(get(l, i), options); } static int leftScanModifiers(List<String> tok, int i) { return leftScanModifiers(tok, i, getJavaModifiers()); } static int leftScanModifiers(List<String> tok, int i, Collection<String> modifiers) { while (i > 1 && contains(modifiers, tok.get(i-2))) i -= 2; return i; } // better modulo that gives positive numbers always static int mod(int n, int m) { return (n % m + m) % m; } static long mod(long n, long m) { return (n % m + m) % m; } static BigInteger mod(BigInteger n, int m) { return n.mod(bigint(m)); } static double mod(double n, double m) { return (n % m + m) % m; } static String decimalFormatEnglish(String format, double d) { return decimalFormatEnglish(format).format(d); } static java.text.DecimalFormat decimalFormatEnglish(String format) { return new java.text.DecimalFormat(format, new java.text.DecimalFormatSymbols(Locale.ENGLISH)); } static String loadTextFilePossiblyGZipped(String fileName) { return loadTextFilePossiblyGZipped(fileName, null); } static String loadTextFilePossiblyGZipped(String fileName, String defaultContents) { File gz = new File(fileName + ".gz"); return gz.exists() ? loadGZTextFile(gz) : loadTextFile(fileName, defaultContents); } static String loadTextFilePossiblyGZipped(File fileName) { return loadTextFilePossiblyGZipped(fileName, null); } static String loadTextFilePossiblyGZipped(File fileName, String defaultContents) { return loadTextFilePossiblyGZipped(fileName.getPath(), defaultContents); } static File getCachedTranspilationFile(String id) { return newFile(getCodeProgramDir(id), "Transpilation"); } static Object vmGeneralMap_get(Object key) { return vm_generalMap_get(key); } static void saveTranspiledCode(String progID, String code) { File dir = getCodeProgramDir(progID); new File(dir, "Transpilation").delete(); saveGZTextFile(new File(dir, "Transpilation.gz"), code); } static <A> A assertEquals(Object x, A y) { return assertEquals("", x, y); } static <A> A assertEquals(String msg, Object x, A y) { if (assertVerbose()) return assertEqualsVerbose(msg, x, y); if (!(x == null ? y == null : x.equals(y))) throw fail((msg != null ? msg + ": " : "") + y + " != " + x); return y; } static Producer<String> javaTokC_iterator(String s) { return new Producer<String>() { final int l = strL(s); int i = 0; public String next() { if (i >= l) return null; int j = i; char c, d; // scan for whitespace while (j < l) { c = s.charAt(j); d = j+1 >= l ? '\0' : s.charAt(j+1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j+2, l)).equals("*/")); j = Math.min(j+2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } i = j; if (i >= l) return null; c = s.charAt(i); d = i+1 >= l ? '\0' : s.charAt(i+1); // scan for non-whitespace if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener || s.charAt(j) == '\n') { // end at \n to not propagate unclosed string literal errors ++j; break; } else if (s.charAt(j) == '\\' && j+1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || "'".indexOf(s.charAt(j)) >= 0)); // for stuff like "don't" else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; // Long constants like 1L } else if (c == '[' && d == '[') { do ++j; while (j+1 < l && !s.substring(j, j+2).equals("]]")); j = Math.min(j+2, l); } else if (c == '[' && d == '=' && i+2 < l && s.charAt(i+2) == '[') { do ++j; while (j+2 < l && !s.substring(j, j+3).equals("]=]")); j = Math.min(j+3, l); } else ++j; String t = quickSubstring(s, i, j); i = j; return t; } }; } static File makeTempDir() { return (File) call(getJavaX(), "TempDirMaker_make"); } static File linux_fileInRamDisk(String name) { if (!isLinux()) return null; File dir = newFile("/dev/shm"); if (dir.isDirectory()) return newFile(dir, name); return null; } static String aGlobalID() { return randomID(globalIDLength()); } static String aGlobalID(Random random) { return randomID(random, globalIDLength()); } static boolean isMarkedAsSrcLib(String snippetID) { if (snippetID == null) return false; IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return isJavaxCompilableSnippetType(rl.getSnippetType(snippetID)); return fileExists(javaxCodeDir("srclibs/" + psI(snippetID))); } static <A, B> A pairA(Pair<A, B> p) { return p == null ? null : p.a; } static Object hotwire_onCompile; // voidfunc(Pair<jarFile, transpiledSource>) static boolean hotwire_serially = false; static Lock hotwire_overInternalBot_lock = lock(); static boolean hotwire_compileOnServer = false; static Class<?> hotwire_overInternalBot(String progID) { return hotwire_overInternalBot(progID, "main"); } static Class<?> hotwire_overInternalBot(String progID, String mainClass) { return hotwire_overInternalBot(progID, __ -> mainClass); } static Class<?> hotwire_overInternalBot(String progID, IF1<ClassLoader, String> calculateMainClass) { try { Pair<File, String> p; try { p = hotwire_compile(progID); } catch (Throwable e) { throw rethrow("Error hotwiring " + progID, e); } File jar = p.a; assertTrue(jar.getAbsolutePath(), jar.isFile()); List<File> files = hotwire_collectJars(jar); // make class loader JavaXClassLoader classLoader = hotwire_makeClassLoader(files); classLoader.progID = progID; String mainClass = calculateMainClass == null ? "main" : calculateMainClass.get(classLoader); return hotwire_finish(classLoader, progID, p.b, mainClass); } catch (Exception __e) { throw rethrow(__e); } } // returns pair(jar, transpiled src) static Pair<File, String> hotwire_compile(String progID) { Pair<File, String> p = hotwire_compileOnServer && !isLocalSnippetID(progID) ? compileSnippetThroughServer(progID) : CompilerBot.compileSnippet2(progID); Lock __0 = hotwire_serially ? hotwire_overInternalBot_lock : null; lock(__0); try { callF(hotwire_onCompile, p); return p; } finally { unlock(__0); } } static void markAsSrcLib(String snippetID) { saveTextFile(javaxCodeDir("srclibs/" + psI(snippetID)), ""); } static String addSuffix(String s, String suffix) { return s == null || s.endsWith(suffix) ? s : s + suffix; } static String dropPrefixTrim(String prefix, String s) { return trim(dropPrefix(prefix, s)); } static List<File> filesWithExtension(String ext, List<File> files) { return filesEndingWith(files, addPrefixIfNotEmpty2(".", ext)); } static List<File> findAllFiles_noDirs(List dirs) { return findAllFiles_noDirs(asObjectArray(dirs)); } // dirs are String's or File's static List<File> findAllFiles_noDirs(Object... dirs) { List<File> l = new ArrayList(); for (Object dir : dirs) { ping(); if (dir instanceof String && ((String) dir).endsWith("/.")) { // "/." means non-recurse for (File f : listFiles(dropSuffix("/.", ((String) dir)))) { ping(); if (f.isFile()) l.add(f); } } else findAllFiles_noDirs_impl(toFile(dir), l); } return l; } static void findAllFiles_noDirs_impl(File dir, List<File> l) { for (File f : listFiles(dir)) { ping(); if (f.isDirectory()) findAllFiles_noDirs_impl(f, l); else l.add(f); } } static <A> A printIndent(A o) { print(indentx(str(o))); return o; } static <A> A printIndent(String indent, A o) { print(indentx(indent, str(o))); return o; } static void printIndent(int indent, Object o) { print(indentx(indent, str(o))); } static List<File> sortFilesByName(List<File> l) { sort(l, (a, b) -> stdcompare(a.getName(), b.getName())); return l; } static int deleteAllFilesInDirectory_minPathLength = 10; static void deleteAllFilesInDirectory(File dir) { deleteAllFilesInDirectory(dir, false, false); } static void deleteAllFilesInDirectory(File dir, boolean verbose, boolean testRun) { dir = getCanonicalFile(dir); assertTrue(f2s(dir), l(f2s(dir)) >= deleteAllFilesInDirectory_minPathLength); File[] files = dir.listFiles(); if (files == null) return; for (File f : files) { if (!isSymLink(f) && f.isDirectory()) // just delete the symlink, don't follow it deleteDirectory(f, verbose, testRun); else { if (verbose) print((testRun ? "Would delete " : "Deleting ") + f.getAbsolutePath()); if (!testRun) f.delete(); } } } static Object callJavaX(String method, Object... args) { return callOpt(getJavaX(), method, args); } static String utf8streamToString(InputStream in) { return readerToString(utf8bufferedReader(in)); } // i must point at the (possibly imaginary) opening bracket ("{") // index returned is index of closing bracket + 1 (or l(tok)) static int tok_findEndOfBlock(List<String> tok, int i) { if (tok instanceof IContentsIndexedList2) return tok_findEndOfBlock_IContentsIndexedList2_v2(((IContentsIndexedList2) tok), i); int j = i+2, level = 1, n = l(tok); while (j < n) { String t = tok.get(j); if ("{".equals(t)) ++level; else if ("}".equals(t)) --level; if (level == 0) return j+1; j += 2; } return n; } static List<String> getJavaModifiers_list = litlist("static", "abstract", "public", "private", "protected", "final", "native", "volatile", "synchronized", "transient", "default"); static List<String> getJavaModifiers() { return getJavaModifiers_list; } static BigInteger bigint(String s) { return new BigInteger(s); } static BigInteger bigint(long l) { return BigInteger.valueOf(l); } static String loadGZTextFile(File file) { try { if (!file.isFile()) return null; ping(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); InputStream fis = new FileInputStream(file); try { GZIPInputStream gis = newGZIPInputStream(fis); byte[] buffer = new byte[1024]; int len; while ((len = gis.read(buffer)) != -1) baos.write(buffer, 0, len); baos.close(); return fromUtf8(baos.toByteArray()); // TODO: use a Reader } finally { _close(fis); }} catch (Exception __e) { throw rethrow(__e); } } static File getCodeProgramDir() { return getCodeProgramDir(getProgramID()); } static File getCodeProgramDir(String snippetID) { return new File(javaxCodeDir(), formatSnippetID(snippetID)); } static File getCodeProgramDir(long snippetID) { return getCodeProgramDir(formatSnippetID(snippetID)); } static void saveGZTextFile(File file, String contents) { saveGZTextFile(file, contents, "UTF-8"); } static void saveGZTextFile(File file, String contents, String encoding) { try { File parentFile = file.getParentFile(); if (parentFile != null) parentFile.mkdirs(); String tempFileName = file.getPath() + "_temp"; File tempFile = new File(tempFileName); if (contents != null) { if (tempFile.exists()) try { String saveName = tempFileName + ".saved." + now(); copyFile(tempFile, new File(saveName)); } catch (Throwable e) { printStackTrace(e); } FileOutputStream fileOutputStream = newFileOutputStream(tempFile.getPath()); GZIPOutputStream gos = new GZIPOutputStream(fileOutputStream); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(gos, encoding); PrintWriter printWriter = new PrintWriter(outputStreamWriter); printWriter.print(contents); printWriter.close(); gos.close(); fileOutputStream.close(); } if (file.exists() && !file.delete()) throw new IOException("Can't delete " + file.getPath()); if (contents != null) if (!tempFile.renameTo(file)) throw new IOException("Can't rename " + tempFile + " to " + file); } catch (Exception __e) { throw rethrow(__e); } } static ThreadLocal<Boolean> assertVerbose_value = new ThreadLocal(); static void assertVerbose(boolean b) { assertVerbose_value.set(b); } static boolean assertVerbose() { return isTrue(assertVerbose_value.get()); } static <A> A assertEqualsVerbose(Object x, A y) { assertEqualsVerbose((String) null, x, y); return y; } // x = expected, y = actual static <A> A assertEqualsVerbose(String msg, Object x, A y) { if (!eq(x, y)) { throw fail((nempty(msg) ? msg + ": " : "") + "expected: "+ x + ", got: " + y); } else print("OK" + (empty(msg) ? "" : " " + msg) + ": " + /*sfu*/(x)); return y; } static String quickSubstring(String s, int i, int j) { if (i >= j) return ""; return s.substring(i, j); } static Cache<Boolean> isLinux_cache = new Cache<>(() -> isLinux_load()); static boolean isLinux() { return isLinux_cache.get(); } static Boolean isLinux_load() { return !isWindows() && !isMac() && !isAndroid(); } static int randomID_defaultLength = 12; static String randomID(int length) { return makeRandomID(length); } static String randomID(Random r, int length) { return makeRandomID(r, length); } static String randomID() { return randomID(randomID_defaultLength); } static String randomID(Random r) { return randomID(r, randomID_defaultLength); } static int globalIDLength() { return 16; } static boolean isJavaxCompilableSnippetType(int type) { return isJavaxCompilableSnippetTypeExceptInclude(type) || type == javaxIncludeSnippetType(); } static List<File> hotwire_collectJars(File jar) { List<String> libIDs = hotwire_libraryIDsFromJar_deleteJarOnFail(jar); List<File> files = ll(jar); // main program has to be first entry! (e.g. for hotwire_makeClassLoader_stickyAndSrcLibs) for (String libID : libIDs) files.add(loadLibraryOrSrcLib(libID)); return files; } static JavaXClassLoader hotwire_makeClassLoader(List<File> files) { Collection<String> toShare = hotwire_classesToShare(); return nempty(toShare) ? new JavaXClassLoaderWithParent2(null, files, myClassLoader(), cloneList(toShare)) : new JavaXClassLoader(null, files); } // returns (jar, transpiled src) static Pair<File, String> compileSnippetThroughServer(String progID) { String transpiledSrc = getServerTranspiled2(progID); String md5 = md5(transpiledSrc + "\n" + progID); File jar = CompilerBot.getJarFile(md5); if (jar == null || jar.length() <= 22) { byte[] jarData = null; boolean dontLoad = false; IResourceLoader rl = vm_getResourceLoader(); if (rl != null) { dontLoad = true; File jar2 = rl.getSnippetJar(progID, transpiledSrc); if (jar2 != null) return pair(jar2, transpiledSrc); } if (!dontLoad) { try { jarData = loadBinaryPage("https://botcompany.de/jar/" + psI(progID) + "?md5=" + md5(transpiledSrc)); } catch (Throwable __e) { printStackTrace(__e); }} if (!isJAR(jarData)) { if (jarData != null) { print(bytesToHex(takeFirstOfByteArray(8, jarData))); print("fallback to CompilerBot: " + fromUtf8(takeFirstOfByteArray(80, jarData))); } return CompilerBot.compileSnippet2(progID); } saveBinaryFile(jar, jarData); } return pair(jar, transpiledSrc); } static List<File> filesEndingWith(File dir, String suffix) { return listFilesWithSuffix(dir, suffix); } static List<File> filesEndingWith(List<File> l, String suffix) { List<File> out = new ArrayList(); for (File f : unnull(l)) if (!f.isDirectory() && (empty(suffix) || endsWithIgnoreCase(f.getName(), suffix))) out.add(f); return out; } static List<File> filesEndingWith(String suffix, File dir) { return filesEndingWith(dir, suffix); } static File toFile(Object o) { if (o instanceof File) return (File) o; if (o instanceof String) return new File((String) o); throw fail("Not a file: " + o); } static String indentx(String s) { return indentx(indent_default, s); } static String indentx(int n, String s) { return dropSuffix(repeat(' ', n), indent(n, s)); } static String indentx(String indent, String s) { return dropSuffix(indent, indent(indent, s)); } static int stdcompare(Number a, Number b) { return cmp(a, b); } static int stdcompare(String a, String b) { return cmp(a, b); } static int stdcompare(long a, long b) { return a < b ? -1 : a > b ? 1 : 0; } static int stdcompare(Object a, Object b) { return cmp(a, b); } static File getCanonicalFile(File f) { try { return f == null ? null : f.getCanonicalFile(); } catch (Exception __e) { throw rethrow(__e); } } static boolean isSymLink(File f) { return f != null && Files.isSymbolicLink(toPath(f)); } static String readerToString(Reader r) { try { if (r == null) return null; try { StringBuilder buf = new StringBuilder(); int n = 0; while (true) { int ch = r.read(); if (ch < 0) break; buf.append((char) ch); ++n; //if ((n % loadPage_verboseness) == 0) print(" " + n + " chars read"); } return buf.toString(); } finally { r.close(); } } catch (Exception __e) { throw rethrow(__e); } } // i must point at the (possibly imaginary) opening bracket ("{") // index returned is index of closing bracket + 1 (or l(tok)) // version using iterator (much faster than v1!) static int tok_findEndOfBlock_IContentsIndexedList2_v2(IContentsIndexedList2<String> tok, int i) { int n = l(tok); // find opening & closing brackets after start index HasIndex start = new HasIndex(i); TreeSet<HasIndex> openers = tok.indicesOf_treeSetOfHasIndex("{"); Iterator<HasIndex> iOpener = openers == null ? null : openers.tailSet(start, false).iterator(); TreeSet<HasIndex> closers = tok.indicesOf_treeSetOfHasIndex("}"); Iterator<HasIndex> iCloser = closers == null ? null : closers.tailSet(start, false).iterator(); // now step through both sets int level = 1; HasIndex nextOpener = iOpener != null && iOpener.hasNext() ? iOpener.next() : null; HasIndex nextCloser = iCloser != null && iCloser.hasNext() ? iCloser.next() : null; while (true) { if (nextCloser == null) return n; // block isn't closed if (nextOpener != null && nextOpener.idx < nextCloser.idx) { // process opener ++level; nextOpener = iOpener.hasNext() ? iOpener.next() : null; } else { // process closer if (--level == 0) return nextCloser.idx+1; nextCloser = iCloser.hasNext() ? iCloser.next() : null; } } } static String appendColonIfNempty(String s) { return empty(s) ? "" : s + ": "; } public static boolean isWindows() { return System.getProperty("os.name").contains("Windows"); } static boolean isMac() { return System.getProperty("os.name").toLowerCase().contains("mac"); } static boolean isJavaxCompilableSnippetTypeExceptInclude(int type) { return isJavaxApplicationSnippetType(type) || isJavaxModuleSnippetType(type) || type == snippetType_dynModule(); } static int javaxIncludeSnippetType() { return 42; } static List<String> hotwire_libraryIDsFromJar_deleteJarOnFail(File jar) { try { return hotwire_libraryIDsFromJar(jar); } catch (Throwable _e) { jar.delete(); throw rethrow(_e); } } static Set<String> hotwire_classesToShare = synchroSet(); static Set<String> hotwire_classesToShare() { return hotwire_classesToShare; } static byte[] isJAR_magic = bytesFromHex("504B0304"); static boolean isJAR(byte[] data) { return byteArrayStartsWith(data, isJAR_magic); } static boolean isJAR(File f) { return isJAR(loadBeginningOfBinaryFile(f, l(isJAR_magic))); } static List<File> listFilesWithSuffix(File dir, String suffix) { List<File> l = new ArrayList(); for (File f : listFiles(dir)) if (!f.isDirectory() && (empty(suffix) || endsWithIgnoreCase(f.getName(), suffix))) l.add(f); return l; } static List<File> listFilesWithSuffix(String suffix, File dir) { return listFilesWithSuffix(dir, suffix); } static int indent_default = 2; static String indent(int indent) { return repeat(' ', indent); } static String indent(int indent, String s) { return indent(repeat(' ', indent), s); } static String indent(String indent, String s) { return indent + replace(unnull(s), "\n", "\n" + indent); } static String indent(String s) { return indent(indent_default, s); } static List<String> indent(String indent, List<String> lines) { List<String> l = new ArrayList(); if (lines != null) for (String s : lines) l.add(indent + s); return l; } static Path toPath(File f) { return f == null ? null : f.toPath(); } static boolean isJavaxApplicationSnippetType(int type) { return type == snippetType_javaxSource() || type == snippetType_JavaXDesktop(); } static boolean isJavaxModuleSnippetType(int type) { return type == snippetType_javaxModule() || type == snippetType_javaxDesktopModule(); } static int snippetType_dynModule() { return 57; } static List<String> hotwire_libraryIDsFromJar(File jar) { String dehlibs = unnull(loadTextFileFromZip(jar, "libraries")); return regexpExtractAll("\\d+", dehlibs); } static int snippetType_javaxSource() { return 34; } static int snippetType_JavaXDesktop() { return 55; } static int snippetType_javaxModule() { return 54; } static int snippetType_javaxDesktopModule() { return 58; } static List<String> regexpExtractAll(String pat, String s) { if (s == null) return null; Matcher m = regexpMatcher(pat, s); List<String> out = new ArrayList(); while (m.find()) out.add(m.group()); return out; } static interface IContentsIndexedList2<A> extends List<A> { TreeSet<HasIndex> indicesOf_treeSetOfHasIndex(A o); } static class JavaXClassLoaderWithParent2 extends JavaXClassLoader { ClassLoader virtualParent; List<String> classesToSkip; // classes that should be taken from parent JavaXClassLoaderWithParent2(String progID, List<File> files, ClassLoader virtualParent, List<String> classesToSkip) { super(progID, files); this.virtualParent = virtualParent; this.classesToSkip = classesToSkip; } protected Class<?> findClass(String name) throws ClassNotFoundException { if (shouldDelegate(name)) { Class<?> c = virtualParent.loadClass(name); if (c != null) return c; } return super.findClass(name); } boolean shouldDelegate(String name) { for (String s : classesToSkip) if (eq(name, s) || startsWith(name, s + "$")) return true; return false; } } static interface Producer<A> { public A next(); // null when end } static class Value<A> implements IF0<A> , IFieldsToList{ A value; Value() {} Value(A value) { this.value = value;} public boolean equals(Object o) { if (!(o instanceof Value)) return false; Value __1 = (Value) o; return eq(value, __1.value); } public int hashCode() { int h = 82420049; h = boostHashCombine(h, _hashCode(value)); return h; } public Object[] _fieldsToList() { return new Object[] {value}; } public A get() { return value; } public String toString() { return str(get()); } } // -has fast nextElement() and prevElement() // -design allows for more functions like reordering the list // -Saves up to 34% in space over LinkedHashSet // (e.g. 22% for a set of 1,000 Ints) static class CompactLinkedHashSet<A> extends AbstractSet<A> { UnsynchronizedCompactHashSet<Entry<A>> entries = new UnsynchronizedCompactHashSet(); Entry<A> head, tail; static class Entry<A> { A value; Entry<A> prev, next; public int hashCode() { return _hashCode(value); } // "magic" equals function for CompactHashSet lookup without temp object public boolean equals(Object o) { return o == this || eq(value, o); } } public boolean add(A a) { if (entries.contains(a)) return false; Entry<A> n = new Entry(); n.value = a; n.prev = tail; if (tail != null) tail.next = n; tail = n; if (head == null) head = n; entries.add(n); return true; } public boolean remove(Object a) { return remove(entries.find(a)); } public boolean remove(Entry<A> node) { if (node == null) return false; if (node.next != null) node.next.prev = node.prev; else tail = node.prev; if (node.prev != null) node.prev.next = node.next; else head = node.next; entries.remove(node); return true; } public int size() { return entries.size(); } public IterableIterator<A> iterator() { return new IterableIterator<A>() { Entry<A> entry = head, prev = null; public boolean hasNext() { return entry != null; } public A next() { A a = entry.value; prev = entry; entry = entry.next; return a; } // untested public void remove() { if (prev == null) throw new IllegalStateException(); CompactLinkedHashSet.this.remove(prev); prev = null; } }; } public void clear() { entries.clear(); head = tail = null; } public boolean contains(Object a) { return entries.contains(a); } public A find(Object o) { Entry<A> e = entries.find(o); return e == null ? null : e.value; } public A prevElement(A a) { Entry<A> e = entries.find(a); if (e == null || e.prev == null) return null; return e.prev.value; } public A nextElement(A a) { Entry<A> e = entries.find(a); if (e == null || e.next == null) return null; return e.next.value; } public A first() { return head == null ? null : head.value; } public A last() { return tail == null ? null : tail.value; } boolean removeIfSame(Object o) { A value = find(o); if (value == o) { remove(value); return true; } return false; } } static class HasIndex implements Comparable<HasIndex> { int idx; HasIndex() {} HasIndex(int idx) { this.idx = idx;} public int compareTo(HasIndex h) { return idx-h.idx; } final int get() { return idx; } } static class Cache<A> { Object maker; // func -> A A value; long loaded; static boolean debug = false; long changeCount; Lock lock = lock(); Cache() {} Cache(Object maker) { this.maker = maker;} Cache(IF0<A> maker) { this.maker = maker;} A get() { if (hasLock(lock)) return value; // Must be called from within maker Lock __0 = lock; lock(__0); try { if (loaded == 0) { value = make(); changeCount++; loaded = sysNow(); } return value; } finally { unlock(__0); } } void clear() { Lock __1 = lock; lock(__1); try { if (debug && loaded != 0) print("Clearing cache"); value = null; changeCount++; loaded = 0; } finally { unlock(__1); } } // clear if older than x seconds // 0 does not do anything void clear(double seconds) { Lock __2 = lock; lock(__2); try { if (seconds != 0 && loaded != 0 && sysNow() >= loaded+seconds*1000) clear(); } finally { unlock(__2); } } // override void set(A a) { Lock __3 = lock; lock(__3); try { value = a; ++changeCount; loaded = sysNow(); } finally { unlock(__3); } } A make() { return (A) callF(maker); } } /* * #! * Ontopia Engine * #- * Copyright (C) 2001 - 2013 The Ontopia Project * #- * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * !# */ // modified by Stefan Reich // Implements the Set interface more compactly than // java.util.HashSet by using a closed hashtable. // Note: equals is always called on the _stored_ object, not the one // passed as an argument to find(), contains() etc. // (In case you want to put special magic in your equals() function) static class UnsynchronizedCompactHashSet<A> extends java.util.AbstractSet<A> { protected final static int INITIAL_SIZE = 3; public final static double LOAD_FACTOR = 0.75; protected final static Object nullObject = new Object(); protected final static Object deletedObject = new Object(); protected int elements; protected int freecells; protected A[] objects; protected int modCount; UnsynchronizedCompactHashSet() { this(INITIAL_SIZE); } UnsynchronizedCompactHashSet(int size) { // NOTE: If array size is 0, we get a // "java.lang.ArithmeticException: / by zero" in add(Object). objects = (A[]) new Object[(size==0 ? 1 : size)]; elements = 0; freecells = objects.length; modCount = 0; } UnsynchronizedCompactHashSet(Collection<A> c) { this(c.size()); addAll(c); } @Override public Iterator<A> iterator() { return new CompactHashIterator<A>(); } @Override public int size() { return elements; } @Override public boolean isEmpty() { return elements == 0; } @Override public boolean contains(Object o) { return find(o) != null; } A find(Object o) { if (o == null) o = nullObject; int hash = o.hashCode(); int index = (hash & 0x7FFFFFFF) % objects.length; int offset = 1; // search for the object (continue while !null and !this object) while(objects[index] != null && !(objects[index].hashCode() == hash && objects[index].equals(o))) { index = ((index + offset) & 0x7FFFFFFF) % objects.length; offset = offset*2 + 1; if (offset == -1) offset = 2; } return objects[index]; } boolean removeIfSame(Object o) { A value = find(o); if (value == o) { remove(value); return true; } return false; } @Override public boolean add(Object o) { if (o == null) o = nullObject; int hash = o.hashCode(); int index = (hash & 0x7FFFFFFF) % objects.length; int offset = 1; int deletedix = -1; // search for the object (continue while !null and !this object) while(objects[index] != null && !(objects[index].hashCode() == hash && objects[index].equals(o))) { // if there's a deleted object here we can put this object here, // provided it's not in here somewhere else already if (objects[index] == deletedObject) deletedix = index; index = ((index + offset) & 0x7FFFFFFF) % objects.length; offset = offset*2 + 1; if (offset == -1) offset = 2; } if (objects[index] == null) { // wasn't present already if (deletedix != -1) // reusing a deleted cell index = deletedix; else freecells--; modCount++; elements++; // here we face a problem regarding generics: // add(A o) is not possible because of the null Object. We cant do 'new A()' or '(A) new Object()' // so adding an empty object is a problem here // If (! o instanceof A) : This will cause a class cast exception // If (o instanceof A) : This will work fine objects[index] = (A) o; // do we need to rehash? if (1 - (freecells / (double) objects.length) > LOAD_FACTOR) rehash(); return true; } else // was there already return false; } @Override public boolean remove(Object o) { if (o == null) o = nullObject; int hash = o.hashCode(); int index = (hash & 0x7FFFFFFF) % objects.length; int offset = 1; // search for the object (continue while !null and !this object) while(objects[index] != null && !(objects[index].hashCode() == hash && objects[index].equals(o))) { index = ((index + offset) & 0x7FFFFFFF) % objects.length; offset = offset*2 + 1; if (offset == -1) offset = 2; } // we found the right position, now do the removal if (objects[index] != null) { // we found the object // same problem here as with add objects[index] = (A) deletedObject; modCount++; elements--; return true; } else // we did not find the object return false; } @Override public void clear() { elements = 0; for (int ix = 0; ix < objects.length; ix++) objects[ix] = null; freecells = objects.length; modCount++; } @Override public Object[] toArray() { Object[] result = new Object[elements]; Object[] objects = this.objects; int pos = 0; for (int i = 0; i < objects.length; i++) if (objects[i] != null && objects[i] != deletedObject) { if (objects[i] == nullObject) result[pos++] = null; else result[pos++] = objects[i]; } // unchecked because it should only contain A return result; } // not sure if this needs to have generics @Override public <T> T[] toArray(T[] a) { int size = elements; if (a.length < size) a = (T[])java.lang.reflect.Array.newInstance( a.getClass().getComponentType(), size); A[] objects = this.objects; int pos = 0; for (int i = 0; i < objects.length; i++) if (objects[i] != null && objects[i] != deletedObject) { if (objects[i] == nullObject) a[pos++] = null; else a[pos++] = (T) objects[i]; } return a; } protected void rehash() { int garbagecells = objects.length - (elements + freecells); if (garbagecells / (double) objects.length > 0.05) // rehash with same size rehash(objects.length); else // rehash with increased capacity rehash(objects.length*2 + 1); } protected void rehash(int newCapacity) { int oldCapacity = objects.length; @SuppressWarnings("unchecked") A[] newObjects = (A[]) new Object[newCapacity]; for (int ix = 0; ix < oldCapacity; ix++) { Object o = objects[ix]; if (o == null || o == deletedObject) continue; int hash = o.hashCode(); int index = (hash & 0x7FFFFFFF) % newCapacity; int offset = 1; // search for the object while(newObjects[index] != null) { // no need to test for duplicates index = ((index + offset) & 0x7FFFFFFF) % newCapacity; offset = offset*2 + 1; if (offset == -1) offset = 2; } newObjects[index] = (A) o; } objects = newObjects; freecells = objects.length - elements; } private class CompactHashIterator<T> implements Iterator<T> { private int index; private int lastReturned = -1; private int expectedModCount; @SuppressWarnings("empty-statement") public CompactHashIterator() { for (index = 0; index < objects.length && (objects[index] == null || objects[index] == deletedObject); index++) ; expectedModCount = modCount; } @Override public boolean hasNext() { return index < objects.length; } @SuppressWarnings("empty-statement") @Override public T next() { /*if (modCount != expectedModCount) throw new ConcurrentModificationException();*/ int length = objects.length; if (index >= length) { lastReturned = -2; throw new NoSuchElementException(); } lastReturned = index; for (index += 1; index < length && (objects[index] == null || objects[index] == deletedObject); index++) ; if (objects[lastReturned] == nullObject) return null; else return (T) objects[lastReturned]; } @Override public void remove() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); if (lastReturned == -1 || lastReturned == -2) throw new IllegalStateException(); // delete object if (objects[lastReturned] != null && objects[lastReturned] != deletedObject) { objects[lastReturned] = (A) deletedObject; elements--; modCount++; expectedModCount = modCount; // this is expected; we made the change } } } int capacity() { return objects.length; } // returns true if there was a shrink boolean shrinkToFactor(double factor) { if (factor > LOAD_FACTOR) throw fail("Shrink factor must be equal to or smaller than load factor: " + factor + " / " + LOAD_FACTOR); int newCapacity = max(INITIAL_SIZE, iround(size()/factor)); if (newCapacity >= capacity()) return false; rehash(newCapacity); return true; } } static String find(String pattern, String text) { Matcher matcher = Pattern.compile(pattern).matcher(text); if (matcher.find()) return matcher.group(1); return null; } static <A> A find(Collection<A> c, Object... data) { for (A x : c) if (checkFields(x, data)) return x; return null; } static boolean hasLock(Lock lock) { return ((ReentrantLock) lock).isHeldByCurrentThread(); } static boolean checkFields(Object x, Object... data) { for (int i = 0; i < l(data); i += 2) if (neq(getOpt(x, (String) data[i]), data[i+1])) return false; return true; } }