loadFont_cached_cache = new HashMap();
  static synchronized public 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 public Font loadFont_cached(String snippetID, float size) {
    try {
      return loadFont_cached(snippetID).deriveFont(size);
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }
  static public JTextArea jTextAreaWithUndo() {
    return jTextAreaWithUndo("");
  }
  static public JTextArea jTextAreaWithUndo(final String text) {
    return jenableUndoRedo(swingNu(JTextArea.class, text));
  }
  static public int iround(double d) {
    return (int) Math.round(d);
  }
  static public int iround(Number n) {
    return iround(toDouble(n));
  }
  static public float getSwingFontScale() {
    return or((Float) vm_generalMap_get("swingFontScale_value"), 1f);
  }
  static public void addActionListener(JTextField tf, final Runnable action) {
    onEnter(tf, action);
  }
  static public void addActionListener(final JComboBox cb, final Runnable action) {
    if (cb != null) {
      swing(new Runnable() {
        public void run() {
          try {
            cb.addActionListener(actionListener(action));
          } catch (Exception __e) {
            throw rethrow(__e);
          }
        }
        public String toString() {
          return "cb.addActionListener(actionListener(action));";
        }
      });
    }
  }
  static public void addActionListener(final AbstractButton b, final Runnable action) {
    if (b != null) {
      swing(new Runnable() {
        public void run() {
          try {
            b.addActionListener(actionListener(action));
          } catch (Exception __e) {
            throw rethrow(__e);
          }
        }
        public String toString() {
          return "b.addActionListener(actionListener(action));";
        }
      });
    }
  }
  static public String selectedItem(JList l) {
    return getSelectedItem(l);
  }
  static public String selectedItem(JComboBox cb) {
    return getSelectedItem(cb);
  }
  static public Map emptyMap() {
    return new HashMap();
  }
  static volatile public PersistableThrowable lastException_lastException;
  static public PersistableThrowable lastException() {
    return lastException_lastException;
  }
  static public void lastException(Throwable e) {
    lastException_lastException = persistableThrowable(e);
  }
  static public String hideCredentials(URL url) {
    return url == null ? null : hideCredentials(str(url));
  }
  static public 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)=[^&\\s\"]*", "$1$2=");
  }
  static public String hideCredentials(Object o) {
    return hideCredentials(str(o));
  }
  static public boolean swic(String a, String b) {
    return startsWithIgnoreCase(a, b);
  }
  static public 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 public boolean ewic(String a, String b) {
    return endsWithIgnoreCase(a, b);
  }
  static public boolean ewic(String a, String b, Matches m) {
    return endsWithIgnoreCase(a, b, m);
  }
  static public boolean containsNewLines(String s) {
    return containsNewLine(s);
  }
  static public String jlabel_textAsHTML_center(String text) {
    return "" + replace(htmlencode(text), "\n", "
") + "
";
  }
  static public 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 public String replacePrefix(String prefix, String replacement, String s) {
    if (!startsWith(s, prefix))
      return s;
    return replacement + substring(s, l(prefix));
  }
  static public Throwable innerException2(Throwable e) {
    if (e == null)
      return null;
    while (empty(e.getMessage()) && e.getCause() != null) e = e.getCause();
    return e;
  }
  static public Throwable getException(Runnable r) {
    try {
      callF(r);
      return null;
    } catch (Throwable e) {
      return e;
    }
  }
  static public String className(Object o) {
    return getClassName(o);
  }
  static public boolean eqOneOf(Object o, Object... l) {
    for (Object x : l) if (eq(o, x))
      return true;
    return false;
  }
  static public Font loadFont(String snippetID) {
    try {
      return loadFont(snippetID, 12f);
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }
  static public Font loadFont(InputStream in) {
    try {
      return Font.createFont(Font.TRUETYPE_FONT, in);
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }
  static public Font loadFont(String snippetID, float fontSize) {
    return loadFont(loadLibrary(snippetID), fontSize);
  }
  static public Font loadFont(File f, float fontSize) {
    try {
      return Font.createFont(Font.TRUETYPE_FONT, f).deriveFont(fontSize);
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }
  static public Font loadFont(InputStream in, float fontSize) {
    try {
      return Font.createFont(Font.TRUETYPE_FONT, in).deriveFont(fontSize);
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }
  static public  A jenableUndoRedo(final A textcomp) {
    {
      swing(new Runnable() {
        public void run() {
          try {
            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");
          } catch (Exception __e) {
            throw rethrow(__e);
          }
        }
        public String toString() {
          return "final new UndoManager undo;\r\n    vm_generalWeakSet(\"Undo Managers\").add(undo)...";
        }
      });
    }
    return textcomp;
  }
  static public double toDouble(Object o) {
    if (o instanceof Number)
      return ((Number) o).doubleValue();
    if (o instanceof BigInteger)
      return ((BigInteger) o).doubleValue();
    if (o == null)
      return 0.0;
    throw fail(o);
  }
  static public JTextField onEnter(final JTextField tf, final 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 public JButton onEnter(JButton btn, final Object action) {
    if (action == null || btn == null)
      return btn;
    btn.addActionListener(actionListener(action));
    return btn;
  }
  static public JList onEnter(JList list, Object action) {
    list.addKeyListener(enterKeyListener(rCallOnSelectedListItem(list, action)));
    return list;
  }
  static public JComboBox onEnter(final JComboBox cb, final Object action) {
    {
      swing(new Runnable() {
        public void run() {
          try {
            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);";
                }
              }));
            }
          } catch (Exception __e) {
            throw rethrow(__e);
          }
        }
        public String toString() {
          return "if (cb.isEditable()) {\r\n      JTextField text = (JTextField) cb.getEditor().g...";
        }
      });
    }
    return cb;
  }
  static public 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 public JTextField onEnter(Object action, JTextField tf) {
    return onEnter(tf, action);
  }
  static public ActionListener actionListener(final Object runnable) {
    return actionListener(runnable, null);
  }
  static public 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 __0 = holdInstance(instanceToHold);
          try {
            callF(runnable);
          } finally {
            _close(__0);
          }
        } catch (Throwable __e) {
          messageBox(__e);
        }
      }
    };
  }
  static public String getSelectedItem(JList l) {
    return (String) l.getSelectedValue();
  }
  static public String getSelectedItem(JComboBox cb) {
    return strOrNull(cb.getSelectedItem());
  }
  static public boolean startsWithOneOf(String s, String... l) {
    for (String x : l) if (startsWith(s, x))
      return true;
    return false;
  }
  static public boolean isAGIBlueDomain(String domain) {
    return domainIsUnder(domain, theAGIBlueDomain());
  }
  static public String hostNameFromURL(String url) {
    try {
      return new URL(url).getHost();
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }
  static public boolean startsWithIgnoreCase(String a, String b) {
    return regionMatchesIC(a, 0, b, 0, b.length());
  }
  static public boolean endsWithIgnoreCase(String a, String b) {
    int la = l(a), lb = l(b);
    return la >= lb && regionMatchesIC(a, la - lb, b, 0, lb);
  }
  static public boolean endsWithIgnoreCase(String a, String b, Matches m) {
    if (!endsWithIgnoreCase(a, b))
      return false;
    m.m = new String[] { substring(a, 0, l(a) - l(b)) };
    return true;
  }
  static public boolean containsNewLine(String s) {
    return contains(s, '\n');
  }
  static public  List replace(List 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 public  List replace(A a, A b, List l) {
    return replace(l, a, b);
  }
  static public String replace(String s, String a, String b) {
    return s == null ? null : a == null || b == null ? s : s.replace(a, b);
  }
  static public String replace(String s, char a, char b) {
    return s == null ? null : s.replace(a, b);
  }
  static public String htmlencode(Object o) {
    return htmlencode(str(o));
  }
  static public String htmlencode(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 == '&') {
        int cp = s.codePointAt(i);
        out.append("");
        out.append(intToHex_flexLength(cp));
        out.append(';');
        i += Character.charCount(cp) - 1;
      } else
        out.append(c);
    }
    return out.toString();
  }
  static public File loadLibrary(String snippetID) {
    return loadBinarySnippet(snippetID);
  }
  static public Set vm_generalWeakSet(Object name) {
    synchronized (get(javax(), "generalMap")) {
      Set set = (Set) (vm_generalMap_get(name));
      if (set == null)
        vm_generalMap_put(name, set = newWeakHashSet());
      return set;
    }
  }
  static public AbstractAction abstractAction(String name, final Object runnable) {
    return new AbstractAction(name) {
      public void actionPerformed(ActionEvent evt) {
        pcallF(runnable);
      }
    };
  }
  static public void messageBox(final String msg) {
    if (headless())
      print(msg);
    else {
      swing(new Runnable() {
        public void run() {
          try {
            JOptionPane.showMessageDialog(null, msg, "JavaX", JOptionPane.INFORMATION_MESSAGE);
          } catch (Exception __e) {
            throw rethrow(__e);
          }
        }
        public String toString() {
          return "JOptionPane.showMessageDialog(null, msg, \"JavaX\", JOptionPane.INFORMATION_MES...";
        }
      });
    }
  }
  static public void messageBox(Throwable e) {
    printStackTrace(e);
    messageBox(hideCredentials(innerException2(e)));
  }
  static public KeyListener enterKeyListener(final Object action) {
    return new KeyAdapter() {
      public void keyPressed(KeyEvent ke) {
        if (ke.getKeyCode() == KeyEvent.VK_ENTER)
          pcallF(action);
      }
    };
  }
  static public 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 public ThreadLocal> holdInstance_l = new ThreadLocal();
  static public AutoCloseable holdInstance(Object o) {
    if (o == null)
      return null;
    listThreadLocalAdd(holdInstance_l, o);
    return new AutoCloseable() {
      public void close() {
        listThreadLocalPopLast(holdInstance_l);
      }
    };
  }
  static public void _close(AutoCloseable c) {
    if (c != null)
      try {
        c.close();
      } catch (Throwable e) {
        if (c instanceof javax.imageio.stream.ImageOutputStream)
          return;
        else
          throw rethrow(e);
      }
  }
  static public boolean domainIsUnder(String domain, String mainDomain) {
    return eqic(domain, mainDomain) || ewic(domain, "." + mainDomain);
  }
  static public String theAGIBlueDomain() {
    return "agi.blue";
  }
  static public boolean regionMatchesIC(String a, int offsetA, String b, int offsetB, int len) {
    return a != null && a.regionMatches(true, offsetA, b, offsetB, len);
  }
  static public boolean contains(Collection c, Object o) {
    return c != null && c.contains(o);
  }
  static public boolean contains(Object[] x, Object o) {
    if (x != null)
      for (Object a : x) if (eq(a, o))
        return true;
    return false;
  }
  static public boolean contains(String s, char c) {
    return s != null && s.indexOf(c) >= 0;
  }
  static public boolean contains(String s, String b) {
    return s != null && s.indexOf(b) >= 0;
  }
  static public boolean contains(BitSet bs, int i) {
    return bs != null && bs.get(i);
  }
  static public String intToHex_flexLength(int i) {
    return Integer.toHexString(i);
  }
  static public File loadBinarySnippet(String snippetID) {
    try {
      IResourceLoader rl = vm_getResourceLoader();
      if (rl != null)
        return rl.loadLibrary(snippetID);
      long id = parseSnippetID(snippetID);
      if (isImageServerSnippet(id))
        return loadImageAsFile(snippetID);
      File f = DiskSnippetCache_getLibrary(id);
      if (fileSize(f) == 0)
        f = loadDataSnippetToFile(snippetID);
      return f;
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }
  static public Object vm_generalMap_put(Object key, Object value) {
    return mapPutOrRemove(vm_generalMap(), key, value);
  }
  static public  Set newWeakHashSet() {
    return synchroWeakHashSet();
  }
  static public boolean headless() {
    return isHeadless();
  }
  static public  void listThreadLocalAdd(ThreadLocal> tl, A a) {
    List l = tl.get();
    if (l == null)
      tl.set(l = new ArrayList());
    l.add(a);
  }
  static public  A listThreadLocalPopLast(ThreadLocal> tl) {
    List l = tl.get();
    if (l == null)
      return null;
    A a = popLast(l);
    if (empty(l))
      tl.set(null);
    return a;
  }
  static public IResourceLoader vm_getResourceLoader() {
    return proxy(IResourceLoader.class, vm_generalMap_get("_officialResourceLoader"));
  }
  static public boolean isImageServerSnippet(long id) {
    return id >= 1100000 && id < 1200000;
  }
  static public 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);
    }
  }
  static public File DiskSnippetCache_file(long snippetID) {
    return new File(getGlobalCache(), "data_" + snippetID + ".jar");
  }
  public static File DiskSnippetCache_getLibrary(long snippetID) throws IOException {
    File file = DiskSnippetCache_file(snippetID);
    return file.exists() ? file : null;
  }
  public static void DiskSnippetCache_putLibrary(long snippetID, byte[] data) throws IOException {
    saveBinaryFile(DiskSnippetCache_file(snippetID), data);
  }
  static public 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 public long fileSize(String path) {
    return getFileSize(path);
  }
  static public long fileSize(File f) {
    return getFileSize(f);
  }
  static public File loadDataSnippetToFile(String snippetID) {
    try {
      snippetID = fsI(snippetID);
      IResourceLoader rl = vm_getResourceLoader();
      if (rl != null)
        return rl.loadLibrary(snippetID);
      File f = DiskSnippetCache_file(parseSnippetID(snippetID));
      List urlsTried = new ArrayList();
      List 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));
        }
        if (fileSize(f) == 0)
          throw fail();
        System.err.println("Bytes loaded: " + fileSize(f));
      } catch (Throwable 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 public  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 public  Set synchroWeakHashSet() {
    return Collections.newSetFromMap((Map) newWeakHashMap());
  }
  static public  A popLast(List l) {
    return liftLast(l);
  }
  static public  List popLast(int n, List l) {
    return liftLast(n, l);
  }
  static public boolean loadBufferedImage_useImageCache = true;
  static public BufferedImage loadBufferedImage(String snippetIDOrURLOrFile) {
    try {
      ping();
      if (snippetIDOrURLOrFile == null)
        return null;
      if (isURL(snippetIDOrURLOrFile))
        return imageIO_readURL(snippetIDOrURLOrFile);
      if (isAbsolutePath(snippetIDOrURLOrFile))
        return loadBufferedImage(new File(snippetIDOrURLOrFile));
      if (!isSnippetID(snippetIDOrURLOrFile))
        throw fail("Not a URL or snippet ID or file: " + 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();
          }
      }
      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"));
      }
      return image;
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }
  static public BufferedImage loadBufferedImage(File file) {
    try {
      return file.isFile() ? ImageIO.read(file) : null;
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }
  static public  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 InvocationHandler() {
      public Object invoke(Object proxy, Method method, Object[] args) {
        return call(target, method.getName(), unnull(args));
      }
    });
  }
  static public  A proxy(Object target, Class intrface) {
    return proxy(intrface, target);
  }
  static public boolean isURL(String s) {
    return startsWithOneOf(s, "http://", "https://", "file:");
  }
  static public File imageSnippetCacheFile(String snippetID) {
    File dir = imageSnippetsCacheDir();
    if (!loadBufferedImage_useImageCache)
      return null;
    return new File(dir, parseSnippetID(snippetID) + ".png");
  }
  static public String snippetImageURL_noHttps(String snippetID) {
    return snippetImageURL_noHttps(snippetID, "png");
  }
  static public 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 public ThreadLocal