Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

2480
LINES

< > BotCompany Repo | #1001370 // x28.java (JavaX)

JavaX source code [tags: use-pretranspiled] - run with: x30.jar

Libraryless. Click here for Pure Java version (4321L/30K/96K).

1  
!747
2  
!awt {
3  
!actionListener {
4  
!named thread
5  
6  
/**
7  
 JavaX runner version 28
8  
9  
 Changes to v26:
10  
 -ask Boot Bot for snippets if it's online (seems to work)
11  
 -make every VM injectable (almost done)
12  
13  
 TODO when making x29: change program ID in source
14  
 */
15  
16  
m { p { throw new RuntimeException("placebo"); } }
17  
18  
interface StringFunc {
19  
  String get(String s);
20  
}
21  
22  
class x28 implements Runnable {
23  
  static final String version = "JavaX 28";
24  
  static final int subversion = 2;
25  
26  
  // If programs run longer than this, they might have their class files
27  
  // deleted.
28  
  static int tempFileRetentionTime = 24; // hours
29  
  
30  
  static boolean verbose = false, translate = false, list = false, virtualizeTranslators = true;
31  
  static String translateTo = null;
32  
  static boolean preferCached = false, noID = false, noPrefetch = false, noAWT = false;
33  
  static boolean safeOnly = false, safeTranslate = false, javacOnly = false, logOn = true;
34  
  static boolean runMainInProcess = true, consoleOn = true, hasHelloMessage = false;
35  
  static List<String[]> mainTranslators = new ArrayList<String[]>();
36  
  private static Map<Long, String> memSnippetCache = new HashMap<Long, String>();
37  
  private static int processesStarted, compilations;
38  
39  
  // snippet ID -> md5
40  
  private static HashMap<Long, String> prefetched = new HashMap<Long, String>();
41  
  private static File virtCache;
42  
43  
  // doesn't work yet
44  
  private static Map<String, Class<?>> programCache = new HashMap<String, Class<?>>();
45  
  static boolean cacheTranslators = false;
46  
47  
  // this should work (caches transpiled translators)
48  
  private static HashMap<Long, Object[]> translationCache = new HashMap<Long, Object[]>();
49  
  static boolean cacheTranspiledTranslators = true;
50  
51  
  // which snippets are available pre-transpiled server-side?
52  
  private static Set<Long> hasTranspiledSet = new HashSet<Long>();
53  
  static boolean useServerTranspiled = true;
54  
55  
  static Object androidContext;
56  
  static boolean android = isAndroid();
57  
  
58  
  // We stick to 1.7 for now to support android.
59  
  // Scripts like #1001155 might change to 1.6
60  
  static S javaTarget = System.getProperty("java.version").startsWith("1.6.") ? "1.6" : "1.7";
61  
62  
  // Translators currently being translated (to detect recursions)
63  
  private static Set<Long> translating = new HashSet<Long>();
64  
65  
  static String lastOutput;
66  
  static String[] fullArgs;
67  
  private static Console console;
68  
  
69  
  static String javaCompilerOutput;
70  
71  
  public static void main(String[] args) {
72  
    try {
73  
      goMain(args);
74  
    } catch (Throwable e) {
75  
      e.printStackTrace();
76  
    }
77  
  }
78  
  
79  
  static void goMain(String[] args) throws Exception {
80  
    __javax = x28.class; // for hotwire
81  
    
82  
    if (args.length != 0 && args[0].equals("-v")) verbose = true;
83  
    redirectSystemOutAndErr();
84  
85  
    for (S arg : args)
86  
      if (arg.equals("-noawt"))
87  
        noAWT = true;
88  
        
89  
    if (consoleOn && console == null && !noAWT)
90  
      tryToOpenConsole(args);
91  
    
92  
    String autoReport = loadTextFile(new File(userHome(), ".javax/auto-report-to-chat").getPath(), "").trim();
93  
    //print("autoReport=" + autoReport);
94  
    if (!isChatServer(args) && autoReport.equals("1"))
95  
      autoReportToChat();
96  
97  
    if (!hasHelloMessage) {
98  
      hasHelloMessage = true;
99  
      //installHelloMessage(args.length == 0 ? "JavaX Start-Up VM" : "JavaX VM (" + smartJoin(args) + ")");
100  
      makeVMAndroid();
101  
    }
102  
    
103  
    File ioBaseDir = new File("."), inputDir = null, outputDir = null;
104  
    String src = null;
105  
    List<String> programArgs = new ArrayList<String>();
106  
    fullArgs = args;
107  
108  
    for (int i = 0; i < args.length; i++) {
109  
      String arg = args[i];
110  
111  
      if (arg.equals("-version")) {
112  
        showVersion();
113  
        System.exit(0);
114  
      }
115  
116  
      if (arg.equals("-sysprop")) {
117  
        showSystemProperties();
118  
        return;
119  
      }
120  
121  
      if (arg.equals("-v") || arg.equals("-verbose"))
122  
        verbose = true;
123  
      else if (arg.equals("-finderror"))
124  
        verbose = true;
125  
      else if (arg.equals("-offline") || arg.equalsIgnoreCase("-prefercached"))
126  
        preferCached = true;
127  
      else if (arg.equals("-novirt"))
128  
        virtualizeTranslators = false;
129  
      else if (arg.equals("-safeonly"))
130  
        safeOnly = true;
131  
      else if (arg.equals("-safetranslate"))
132  
        safeTranslate = true;
133  
      else if (arg.equals("-noawt"))
134  
        noAWT = true;
135  
      else if (arg.equals("-noid"))
136  
        noID = true;
137  
      else if (arg.equals("-nocachetranspiled"))
138  
        cacheTranspiledTranslators = false;
139  
      else if (arg.equals("-javac"))
140  
        javacOnly = true;
141  
      else if (arg.equals("-localtranspile"))
142  
        useServerTranspiled = false;
143  
      else if (arg.equals("translate") && src == null)
144  
        translate = true;
145  
      else if (arg.equals("list") && src == null) {
146  
        list = true;
147  
        virtualizeTranslators = false; // so they are silenced
148  
      } else if (arg.equals("run") && src == null) {
149  
        // it's the default command anyway
150  
      } else if (arg.startsWith("input="))
151  
        inputDir = new File(arg.substring(6));
152  
      else if (arg.startsWith("output="))
153  
        outputDir = new File(arg.substring(7));
154  
      else if (arg.equals("with"))
155  
        mainTranslators.add(new String[] {args[++i], null});
156  
      else if (translate && arg.equals("to"))
157  
        translateTo = args[++i];
158  
      else if (src == null) {
159  
        //System.out.println("src=" + arg);
160  
        src = arg;
161  
      } else
162  
        programArgs.add(arg);
163  
    }
164  
165  
    cleanCache();
166  
167  
    if (useServerTranspiled)
168  
      noPrefetch = true;
169  
170  
    if (src == null) src = ".";
171  
172  
    // Might actually want to write to 2 disk caches (global/per program).
173  
    if (virtualizeTranslators && !preferCached)
174  
      virtCache = TempDirMaker_make();
175  
176  
    if (inputDir != null) {
177  
      ioBaseDir = TempDirMaker_make();
178  
      System.out.println("Taking input from: " + inputDir.getAbsolutePath());
179  
      System.out.println("Output is in: " + new File(ioBaseDir, "output").getAbsolutePath());
180  
      copyInput(inputDir, new File(ioBaseDir, "input"));
181  
    }
182  
    
183  
    if (logOn)
184  
      logStart(args);
185  
186  
    javaxmain(src, ioBaseDir, translate, list, programArgs.toArray(new String[programArgs.size()]));
187  
188  
    if (outputDir != null) {
189  
      copyInput(new File(ioBaseDir, "output"), outputDir);
190  
      System.out.println("Output copied to: " + outputDir.getAbsolutePath());
191  
    }
192  
193  
    if (verbose) {
194  
      // print stats
195  
      System.out.println("Processes started: " + processesStarted + ", compilations: " + compilations);
196  
    }
197  
  }
198  
199  
  public static void javaxmain(String src, File ioDir, boolean translate, boolean list,
200  
                               String[] args) throws Exception {
201  
    String programID = isSnippetID(src) ? "" + parseSnippetID(src) : null;
202  
    
203  
    if (programID != null)
204  
      System.err.println("JavaX TRANSLATE " + programID + " " + smartJoin(args));
205  
    
206  
    List<File> libraries = new ArrayList<File>();
207  
    File X = transpileMain(src, libraries);
208  
    if (verbose)
209  
      print("After transpileMain: " + X);
210  
      
211  
    if (X == null) {
212  
      showVersion();
213  
      
214  
      if (fullArgs != null) {
215  
        String[] nargs;
216  
        if (fullArgs.length == 0)
217  
          nargs = new String[] {"1000825"}; // swing-start
218  
        else {
219  
          // forward to search
220  
          nargs = new String[fullArgs.length+1];
221  
          nargs[0] = "636";
222  
          // nargs[1] = "search-runnables";
223  
          System.arraycopy(fullArgs, 0, nargs, 1, fullArgs.length);
224  
        }
225  
        main(nargs); // Hopefully we get no infinite recursion :)
226  
        return;
227  
      }
228  
      
229  
      System.out.println("No main.java found, exiting");
230  
      return;
231  
    }
232  
    
233  
    info.transpiledSrc = X;
234  
235  
    // list or run
236  
237  
    if (translate) {
238  
      File to = X;
239  
      if (translateTo != null) {
240  
        StringBuilder buf = new StringBuilder();
241  
        for (File f : libraries) buf.append(f.getName()+"\n");
242  
        if (new File(translateTo).isDirectory()) {
243  
          to = new File(translateTo, "main.java");
244  
          saveTextFile(new File(translateTo, "libraries.txt").getPath(), buf.toString());
245  
        } else {
246  
          to = new File(translateTo);
247  
          saveTextFile(new File(translateTo + "_libraries").getPath(), buf.toString());
248  
        }
249  
      }
250  
      if (to != X)
251  
        copy(new File(X, "main.java"), to);
252  
      System.out.println("Program translated to: " + to.getAbsolutePath());
253  
    } else if (list)
254  
      System.out.println(loadTextFile(new File(X, "main.java").getPath(), null));
255  
    else {
256  
      if (programID != null)
257  
        System.err.println("JavaX RUN " + programID + " " + smartJoin(args));
258  
      System.err.println(); // Make empty line before actual program starts
259  
      
260  
      javax2(X, ioDir, false, runMainInProcess, libraries, args, null, programID, info);
261  
      
262  
      System.out.println("[main done]");
263  
      
264  
      // cleanup reportToChat thread
265  
      if (reportToChat_q != null) {
266  
        if (customSystemOut != null)
267  
          Thread.sleep(1000); // delay to finish autoReportToChat. Yes it's hacky.
268  
        if (verbose) System.out.println("Closing reportToChat queue");
269  
        reportToChat_q.done();
270  
      }
271  
    }
272  
  }
273  
274  
  static File transpileMain(String src, List<File> libraries) throws Exception {
275  
    File srcDir = null;
276  
    boolean isTranspiled = false;
277  
    if (isSnippetID(src)) {
278  
      S transpiledSrc = getTranspilationFromBossBot(parseSnippetID(src));
279  
      if (transpiledSrc != null) {
280  
        int i = transpiledSrc.indexOf('\n');
281  
        String libs = transpiledSrc.substring(0, Math.max(0, i));
282  
        transpiledSrc = transpiledSrc.substring(i+1);
283  
        if (!transpiledSrc.isEmpty()) {
284  
          srcDir = TempDirMaker_make();
285  
          saveTextFile(new File(srcDir, "main.java").getPath(), transpiledSrc);
286  
          isTranspiled = true;
287  
288  
          Matcher m = Pattern.compile("\\d+").matcher(libs);
289  
          while (m.find()) {
290  
            String libid = m.group();
291  
            File libraryFile = DiskSnippetCache_getLibrary(parseSnippetID(libid));
292  
            loadLibrary(libid, libraries, libraryFile);
293  
          }
294  
        }
295  
      }
296  
     
297  
      if (srcDir == null) {
298  
        prefetch(src);
299  
        long id = parseSnippetID(src);
300  
        prefetched.remove(id); // hackfix to ensure transpiled main program is found.
301  
        srcDir = loadSnippetAsMainJava(src);
302  
        if (verbose)
303  
          System.err.println("hasTranspiledSet: " + hasTranspiledSet);
304  
        if (hasTranspiledSet.contains(id) && useServerTranspiled) {
305  
          //System.err.println("Trying pretranspiled main program: #" + id);
306  
          transpiledSrc = getServerTranspiled("#" + id);
307  
          int i = transpiledSrc.indexOf('\n');
308  
          String libs = transpiledSrc.substring(0, Math.max(0, i));
309  
          transpiledSrc = transpiledSrc.substring(i+1);
310  
          if (!transpiledSrc.isEmpty()) {
311  
            srcDir = TempDirMaker_make();
312  
            saveTextFile(new File(srcDir, "main.java").getPath(), transpiledSrc);
313  
            isTranspiled = true;
314  
            //translationCache.put(id, new Object[] {srcDir, libraries});
315  
  
316  
            Matcher m = Pattern.compile("\\d+").matcher(libs);
317  
            while (m.find()) {
318  
              String libid = m.group();
319  
              File libraryFile = DiskSnippetCache_getLibrary(parseSnippetID(libid));
320  
              loadLibrary(libid, libraries, libraryFile);
321  
            }
322  
          }
323  
        }
324  
      }
325  
    } else {
326  
      srcDir = new File(src);
327  
328  
      // if the argument is a file, it is assumed to be main.java
329  
      if (srcDir.isFile()) {
330  
        srcDir = TempDirMaker_make();
331  
        copy(new File(src), new File(srcDir, "main.java"));
332  
      }
333  
334  
      if (!new File(srcDir, "main.java").exists())
335  
        return null;
336  
    }
337  
338  
    // translate
339  
340  
    File X = srcDir;
341  
342  
    if (!isTranspiled) {
343  
      X = topLevelTranslate(X, libraries);
344  
      System.err.println("Translated " + src);
345  
346  
      // save prefetch data
347  
      if (isSnippetID(src))
348  
        savePrefetchData(src);
349  
    }
350  
    return X;
351  
  }
352  
353  
  private static void prefetch(String mainSnippetID) throws IOException {
354  
    if (noPrefetch) return;
355  
356  
    long mainID = parseSnippetID(mainSnippetID);
357  
    String s = mainID + " " + loadTextFile(new File(userHome(), ".tinybrain/prefetch/" + mainID + ".txt").getPath(), "");
358  
    String[] ids = s.trim().split(" ");
359  
    if (ids.length > 1) {
360  
      String url = "http://tinybrain.de:8080/tb-int/prefetch.php?ids=" + URLEncoder.encode(s, "UTF-8");
361  
      String data = loadPage(new URL(url));
362  
      String[] split = data.split(" ");
363  
      if (split.length == ids.length)
364  
        for (int i = 0; i < ids.length; i++)
365  
          prefetched.put(parseSnippetID(ids[i]), split[i]);
366  
    }
367  
  }
368  
369  
  static String userHome() {
370  
    if (android)
371  
      return ((File) call(androidContext, "getFilesDir")).getAbsolutePath();
372  
    else
373  
      return System.getProperty("user.home");
374  
  }
375  
376  
  private static void savePrefetchData(String mainSnippetID) throws IOException {
377  
    List<String> ids = new ArrayList<String>();
378  
    long mainID = parseSnippetID(mainSnippetID);
379  
380  
    for (long id : memSnippetCache.keySet())
381  
      if (id != mainID)
382  
        ids.add(String.valueOf(id));
383  
384  
    saveTextFile(new File(userHome(),".tinybrain/prefetch/" + mainID + ".txt").getPath(), join(" ", ids));
385  
  }
386  
387  
  static File topLevelTranslate(File srcDir, List<File> libraries_out) throws Exception {
388  
    File X = srcDir;
389  
    X = applyTranslators(X, mainTranslators, libraries_out); // translators supplied on command line (unusual)
390  
391  
    // actual inner translation of the JavaX source
392  
    X = defaultTranslate(X, libraries_out);
393  
    return X;
394  
  }
395  
396  
  private static File defaultTranslate(File x, List<File> libraries_out) throws Exception {
397  
    x = luaPrintToJavaPrint(x);
398  
    x = repeatAutoTranslate(x, libraries_out);
399  
    return x;
400  
  }
401  
402  
  private static File repeatAutoTranslate(File x, List<File> libraries_out) throws Exception {
403  
    new List<String[]> postTranslators;
404  
    
405  
    while (true) {
406  
      String main = loadTextFile(new File(x, "main.java").getPath(), null);
407  
      List<String> lines = toLines(main);
408  
      List<String[]> t = findPostTranslators(lines);
409  
      postTranslators.addAll(t);
410  
      
411  
      if (!t.isEmpty()) {
412  
        main = fromLines(lines);
413  
        x = TempDirMaker_make();
414  
        saveTextFile(new File(x, "main.java").getPath(), main);
415  
      }
416  
417  
      File y = autoTranslate(x, libraries_out);
418  
      if (y == x)
419  
        break;
420  
      x = y;
421  
    }
422  
    
423  
    x = applyTranslators(x, postTranslators, libraries_out);
424  
    
425  
    return x;
426  
  }
427  
428  
  private static File autoTranslate(File x, List<File> libraries_out) throws Exception {
429  
    String main = loadTextFile(new File(x, "main.java").getPath(), null);
430  
    List<String> lines = toLines(main);
431  
    List<String[]> translators = findTranslators(lines);
432  
    if (translators.isEmpty())
433  
      return x;
434  
435  
    main = fromLines(lines);
436  
    File newDir = TempDirMaker_make();
437  
    saveTextFile(new File(newDir, "main.java").getPath(), main);
438  
    return applyTranslators(newDir, translators, libraries_out);
439  
  }
440  
441  
  static List<String[]> findTranslators(List<String> lines) {
442  
    List<String[]> translators = new ArrayList<String[]>();
443  
    Pattern pattern = Pattern.compile("^!([0-9# \t]+)");
444  
    Pattern pArgs = Pattern.compile("^\\s*\\((.*)\\)");
445  
    for (ListIterator<String> iterator = lines.listIterator(); iterator.hasNext(); ) {
446  
      String line = iterator.next();
447  
      line = line.trim();
448  
      Matcher matcher = pattern.matcher(line);
449  
      if (matcher.find()) {
450  
        String[] t = matcher.group(1).split("[ \t]+");
451  
        String rest = line.substring(matcher.end());
452  
        String arg = null;
453  
        if (t.length == 1) {
454  
          Matcher mArgs = pArgs.matcher(rest);
455  
          if (mArgs.find())
456  
            arg = mArgs.group(1);
457  
        }
458  
        for (String transi : t)
459  
          translators.add(new String[]{transi, arg});
460  
        iterator.remove();
461  
      }
462  
    }
463  
    return translators;
464  
  }
465  
466  
  static List<String[]> findPostTranslators(List<String> lines) {
467  
    List<String[]> translators = new ArrayList<String[]>();
468  
    Pattern pattern = Pattern.compile("^!post\\s*([0-9# \t]+)");
469  
    Pattern pArgs = Pattern.compile("^\\s*\\((.*)\\)");
470  
    for (ListIterator<String> iterator = lines.listIterator(); iterator.hasNext(); ) {
471  
      String line = iterator.next();
472  
      line = line.trim();
473  
      Matcher matcher = pattern.matcher(line);
474  
      if (matcher.find()) {
475  
        String[] t = matcher.group(1).split("[ \t]+");
476  
        String rest = line.substring(matcher.end());
477  
        String arg = null;
478  
        if (t.length == 1) {
479  
          Matcher mArgs = pArgs.matcher(rest);
480  
          if (mArgs.find())
481  
            arg = mArgs.group(1);
482  
        }
483  
        for (String transi : t)
484  
          translators.add(new String[]{transi, arg});
485  
        iterator.remove();
486  
      }
487  
    }
488  
    return translators;
489  
  }
490  
491  
  public static List<String> toLines(String s) {
492  
    List<String> lines = new ArrayList<String>();
493  
    int start = 0;
494  
    while (true) {
495  
      int i = toLines_nextLineBreak(s, start);
496  
      if (i < 0) {
497  
        if (s.length() > start) lines.add(s.substring(start));
498  
        break;
499  
      }
500  
501  
      lines.add(s.substring(start, i));
502  
      if (s.charAt(i) == '\r' && i+1 < s.length() && s.charAt(i+1) == '\n')
503  
        i += 2;
504  
      else
505  
        ++i;
506  
507  
      start = i;
508  
    }
509  
    return lines;
510  
  }
511  
512  
  private static int toLines_nextLineBreak(String s, int start) {
513  
    for (int i = start; i < s.length(); i++) {
514  
      char c = s.charAt(i);
515  
      if (c == '\r' || c == '\n')
516  
        return i;
517  
    }
518  
    return -1;
519  
  }
520  
521  
  public static String fromLines(List<String> lines) {
522  
    StringBuilder buf = new StringBuilder();
523  
    for (String line : lines) {
524  
      buf.append(line).append('\n');
525  
    }
526  
    return buf.toString();
527  
  }
528  
529  
  private static File applyTranslators(File x, List<String[]> translators, List<File> libraries_out) throws Exception {
530  
    for (String[] translator : translators)
531  
      x = applyTranslator(x, translator[0], translator[1], libraries_out);
532  
    return x;
533  
  }
534  
535  
  // also takes a library
536  
  private static File applyTranslator(File x, String translator, String arg, List<File> libraries_out) throws Exception {
537  
    if (verbose)
538  
      System.out.println("Using translator " + translator + " on sources in " + x.getPath());
539  
540  
    File newDir = runTranslatorOnInput(translator, null, arg, x, !verbose, libraries_out);
541  
542  
    if (!new File(newDir, "main.java").exists()) {
543  
      throw new Exception("Translator " + translator + " did not generate main.java");
544  
      // TODO: show translator output
545  
    }
546  
    if (verbose)
547  
      System.out.println("Translated with " + translator + " from " + x.getPath() + " to " + newDir.getPath());
548  
    x = newDir;
549  
    return x;
550  
  }
551  
552  
  private static File luaPrintToJavaPrint(File x) throws IOException {
553  
    File newDir = TempDirMaker_make();
554  
    String code = loadTextFile(new File(x, "main.java").getPath(), null);
555  
    code = luaPrintToJavaPrint(code);
556  
    saveTextFile(new File(newDir, "main.java").getPath(), code);
557  
    return newDir;
558  
  }
559  
560  
  public static String luaPrintToJavaPrint(String code) {
561  
    return ("\n" + code).replaceAll(
562  
      "(\n\\s*)print (\".*\")",
563  
      "$1System.out.println($2);").substring(1);
564  
  }
565  
566  
  public static File loadSnippetAsMainJava(String snippetID) throws IOException {
567  
    checkProgramSafety(snippetID);
568  
    File srcDir = TempDirMaker_make();
569  
    saveTextFile(new File(srcDir, "main.java").getPath(), loadSnippet(snippetID));
570  
    return srcDir;
571  
  }
572  
573  
  public static File loadSnippetAsMainJavaVerified(String snippetID, String hash) throws IOException {
574  
    checkProgramSafety(snippetID);
575  
    File srcDir = TempDirMaker_make();
576  
    saveTextFile(new File(srcDir, "main.java").getPath(), loadSnippetVerified(snippetID, hash));
577  
    return srcDir;
578  
  }
579  
580  
  @SuppressWarnings( "unchecked" )
581  
  /** returns output dir */
582  
  private static File runTranslatorOnInput(String snippetID, String hash, String arg, File input,
583  
                                           boolean silent,
584  
                                           List<File> libraries_out) throws Exception {
585  
    if (safeTranslate)
586  
      checkProgramSafetyImpl(snippetID);
587  
    long id = parseSnippetID(snippetID);
588  
589  
    // It's a library, not a translator.
590  
    File libraryFile = DiskSnippetCache_getLibrary(id);
591  
    if (verbose)
592  
      System.out.println("Library file for " + id + ": " + libraryFile);
593  
    if (libraryFile != null) {
594  
      loadLibrary(snippetID, libraries_out, libraryFile);
595  
      return input;
596  
    }
597  
598  
    String[] args = arg != null ? new String[]{arg} : new String[0];
599  
600  
    File srcDir = hash == null ? loadSnippetAsMainJava(snippetID)
601  
      : loadSnippetAsMainJavaVerified(snippetID, hash);
602  
    long mainJavaSize = new File(srcDir, "main.java").length();
603  
604  
    if (verbose)
605  
      System.out.println(snippetID + ": length = " + mainJavaSize);
606  
    if (mainJavaSize == 0) { // no text in snippet? assume it's a library
607  
      loadLibrary(snippetID, libraries_out, libraryFile);
608  
      return input;
609  
    }
610  
611  
    List<File> libraries = new ArrayList<File>();
612  
    Object[] cached = translationCache.get(id);
613  
    if (cached != null) {
614  
      //System.err.println("Taking translator " + snippetID + " from cache!");
615  
      srcDir = (File) cached[0];
616  
      libraries = (List<File>) cached[1];
617  
    } else if (hasTranspiledSet.contains(id) && useServerTranspiled) {
618  
      System.err.println("Trying pretranspiled translator: #" + snippetID);
619  
      String transpiledSrc = getServerTranspiled(snippetID);
620  
      transpiledSrc = transpiledSrc.substring(transpiledSrc.indexOf('\n')+1);
621  
      // TODO: check for libraries
622  
      if (!transpiledSrc.isEmpty()) {
623  
        srcDir = TempDirMaker_make();
624  
        saveTextFile(new File(srcDir, "main.java").getPath(), transpiledSrc);
625  
        translationCache.put(id, cached = new Object[] {srcDir, libraries});
626  
      }
627  
    }
628  
629  
    File ioBaseDir = TempDirMaker_make();
630  
631  
    /*Class<?> mainClass = programCache.get("" + parseSnippetID(snippetID));
632  
    if (mainClass != null)
633  
      return runCached(ioBaseDir, input, args);*/
634  
    // Doesn't work yet because virtualized directories are hardcoded in translator...
635  
636  
    if (cached == null) {
637  
      System.err.println("Translating translator #" + id);
638  
      if (translating.contains(id))
639  
        throw new RuntimeException("Recursive translator reference chain: " + structure(translating));
640  
      translating.add(id);
641  
      try {
642  
        srcDir = defaultTranslate(srcDir, libraries);
643  
      } finally {
644  
        translating.remove(id);
645  
      }
646  
      System.err.println("Translated translator #" + id);
647  
      translationCache.put(id, new Object[]{srcDir, libraries});
648  
    }
649  
650  
    boolean runInProcess = false;
651  
652  
    if (virtualizeTranslators) {
653  
      if (verbose) System.out.println("Virtualizing translator");
654  
655  
      // TODO: don't virtualize class _javax (as included in, say, #636)
656  
657  
      //srcDir = applyTranslator(srcDir, "#2000351"); // I/O-virtualize the translator
658  
      // that doesn't work because it recurses infinitely...
659  
660  
      // So we do it right here:
661  
      String s = loadTextFile(new File(srcDir, "main.java").getPath(), null);
662  
      s = s.replaceAll("new\\s+File\\(", "virtual.newFile(");
663  
      s = s.replaceAll("new\\s+FileInputStream\\(", "virtual.newFileInputStream(");
664  
      s = s.replaceAll("new\\s+FileOutputStream\\(", "virtual.newFileOutputStream(");
665  
      s += "\n\n" + loadSnippet("#2000355"); // load class virtual
666  
667  
      // forward snippet cache (virtualized one)
668  
      File dir = virtCache != null ? virtCache : DiskSnippetCache_dir;
669  
      s = s.replace("static File DiskSnippetCache_dir" + ";",
670  
        "static File DiskSnippetCache_dir " + "= new File(" + javaQuote(dir.getAbsolutePath()) + ");"); // extra + is necessary for Dumb TinyBrain :)
671  
      s = s.replace("static boolean preferCached = false;", "static boolean preferCached = true;");
672  
673  
      if (verbose) {
674  
        System.out.println("==BEGIN VIRTUALIZED TRANSLATOR==");
675  
        System.out.println(s);
676  
        System.out.println("==END VIRTUALIZED TRANSLATOR==");
677  
      }
678  
      srcDir = TempDirMaker_make();
679  
      saveTextFile(new File(srcDir, "main.java").getPath(), s);
680  
681  
      // TODO: silence translator also
682  
      runInProcess = true;
683  
    }
684  
685  
    return runJavaX(ioBaseDir, srcDir, input, silent, runInProcess, libraries,
686  
      args, cacheTranslators ? "" + id : null, "" + id);
687  
  }
688  
689  
  private static String getServerTranspiled(String snippetID) throws IOException {
690  
    long id = parseSnippetID(snippetID);
691  
    /*S t = getTranspilationFromBossBot(id);
692  
    if (t != null) return t;*/
693  
    
694  
    URL url = new URL("http://tinybrain.de:8080/tb-int/get-transpiled.php?raw=1&withlibs=1&id=" + id);
695  
    return loadPage(url);
696  
  }
697  
698  
  static void checkProgramSafety(String snippetID) throws IOException {
699  
    if (!safeOnly) return;
700  
    checkProgramSafetyImpl(snippetID);
701  
  }
702  
703  
  static void checkProgramSafetyImpl(String snippetID) throws IOException {
704  
    URL url = new URL("http://tinybrain.de:8080/tb-int/is-javax-safe.php?id=" + parseSnippetID(snippetID));
705  
    String text = loadPage(url);
706  
    if (!text.startsWith("{\"safe\":\"1\"}"))
707  
      throw new RuntimeException("Program not safe: #" + parseSnippetID(snippetID));
708  
  }
709  
710  
  static void loadLibrary(String snippetID, List<File> libraries_out, File libraryFile) throws IOException {
711  
    if (verbose)
712  
      System.out.println("Assuming " + snippetID + " is a library.");
713  
714  
    if (libraryFile == null) {
715  
      byte[] data = loadDataSnippetImpl(snippetID);
716  
      DiskSnippetCache_putLibrary(parseSnippetID(snippetID), data);
717  
      libraryFile = DiskSnippetCache_getLibrary(parseSnippetID(snippetID));
718  
    }
719  
720  
    if (!libraries_out.contains(libraryFile))
721  
      libraries_out.add(libraryFile);
722  
  }
723  
724  
  /** returns output dir */
725  
  private static File runJavaX(File ioBaseDir, File originalSrcDir, File originalInput,
726  
                               boolean silent, boolean runInProcess,
727  
                               List<File> libraries, String[] args, String cacheAs,
728  
                               String programID) throws Exception {
729  
    File srcDir = new File(ioBaseDir, "src");
730  
    File inputDir = new File(ioBaseDir, "input");
731  
    File outputDir = new File(ioBaseDir, "output");
732  
    copyInput(originalSrcDir, srcDir);
733  
    copyInput(originalInput, inputDir);
734  
    javax2(srcDir, ioBaseDir, silent, runInProcess, libraries, args, cacheAs, programID, null);
735  
    return outputDir;
736  
  }
737  
738  
  private static void copyInput(File src, File dst) throws IOException {
739  
    copyDirectory(src, dst);
740  
  }
741  
742  
  public static boolean hasFile(File inputDir, String name) {
743  
    return new File(inputDir, name).exists();
744  
  }
745  
746  
  public static void copyDirectory(File src, File dst) throws IOException {
747  
    if (verbose) System.out.println("Copying " + src.getAbsolutePath() + " to " + dst.getAbsolutePath());
748  
    dst.mkdirs();
749  
    File[] files = src.listFiles();
750  
    if (files == null) return;
751  
    for (File file : files) {
752  
      File dst1 = new File(dst, file.getName());
753  
      if (file.isDirectory())
754  
        copyDirectory(file, dst1);
755  
      else {
756  
        if (verbose) System.out.println("Copying " + file.getAbsolutePath() + " to " + dst1.getAbsolutePath());
757  
        copy(file, dst1);
758  
      }
759  
    }
760  
  }
761  
762  
  /** Quickly copy a file without a progress bar or any other fancy GUI... :) */
763  
  public static void copy(File src, File dest) throws IOException {
764  
    FileInputStream inputStream = newFileInputStream(src);
765  
    FileOutputStream outputStream = newFileOutputStream(dest);
766  
    try {
767  
      copy(inputStream, outputStream);
768  
      inputStream.close();
769  
    } finally {
770  
      outputStream.close();
771  
    }
772  
  }
773  
774  
  private static FileInputStream newFileInputStream(File f) throws FileNotFoundException {
775  
    /*if (androidContext != null)
776  
      return (FileInputStream) call(androidContext,
777  
        "openFileInput", f.getPath());
778  
    else*/
779  
    return new // line break for Dumb TinyBrain :)
780  
    FileInputStream(f);
781  
  }
782  
783  
  private static FileOutputStream newFileOutputStream(File f) throws FileNotFoundException {
784  
    /*if (androidContext != null)
785  
      return (FileOutputStream) call(androidContext,
786  
        "openFileOutput", f.getPath(), 0);
787  
    else*/
788  
    return new // line break for Dumb TinyBrain :)
789  
    FileOutputStream(f);
790  
  }
791  
792  
  public static void copy(InputStream in, OutputStream out) throws IOException {
793  
    byte[] buf = new byte[65536];
794  
    while (true) {
795  
      int n = in.read(buf);
796  
      if (n <= 0) return;
797  
      out.write(buf, 0, n);
798  
    }
799  
  }
800  
801  
  /** writes safely (to temp file, then rename) */
802  
  public static void saveTextFile(String fileName, String contents) throws IOException {
803  
    File file = new File(fileName);
804  
    File parentFile = file.getParentFile();
805  
    if (parentFile != null)
806  
      parentFile.mkdirs();
807  
    String tempFileName = fileName + "_temp";
808  
    FileOutputStream fileOutputStream = newFileOutputStream(new File(tempFileName));
809  
    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, charsetForTextFiles);
810  
    PrintWriter printWriter = new PrintWriter(outputStreamWriter);
811  
    printWriter.print(contents);
812  
    printWriter.close();
813  
    if (file.exists() && !file.delete())
814  
      throw new IOException("Can't delete " + fileName);
815  
816  
    if (!new File(tempFileName).renameTo(file))
817  
      throw new IOException("Can't rename " + tempFileName + " to " + fileName);
818  
  }
819  
820  
  /** writes safely (to temp file, then rename) */
821  
  public static void saveBinaryFile(String fileName, byte[] contents) throws IOException {
822  
    File file = new File(fileName);
823  
    File parentFile = file.getParentFile();
824  
    if (parentFile != null)
825  
      parentFile.mkdirs();
826  
    String tempFileName = fileName + "_temp";
827  
    FileOutputStream fileOutputStream = newFileOutputStream(new File(tempFileName));
828  
    fileOutputStream.write(contents);
829  
    fileOutputStream.close();
830  
    if (file.exists() && !file.delete())
831  
      throw new IOException("Can't delete " + fileName);
832  
833  
    if (!new File(tempFileName).renameTo(file))
834  
      throw new IOException("Can't rename " + tempFileName + " to " + fileName);
835  
  }
836  
837  
  !include #1001049 // loadTextFile
838  
  
839  
  static File DiskSnippetCache_dir;
840  
841  
  public static void initDiskSnippetCache(File dir) {
842  
    DiskSnippetCache_dir = dir;
843  
    dir.mkdirs();
844  
  }
845  
846  
  // Data files are immutable, use centralized cache
847  
  public static synchronized File DiskSnippetCache_getLibrary(long snippetID) throws IOException {
848  
    File file = new File(getGlobalCache(), "data_" + snippetID + ".jar");
849  
    if (verbose)
850  
      System.out.println("Checking data cache: " + file.getPath());
851  
    return file.exists() ? file : null;
852  
  }
853  
854  
  public static synchronized String DiskSnippetCache_get(long snippetID) throws IOException {
855  
    return loadTextFile(DiskSnippetCache_getFile(snippetID).getPath(), null);
856  
  }
857  
858  
  private static File DiskSnippetCache_getFile(long snippetID) {
859  
    return new File(DiskSnippetCache_dir, "" + snippetID);
860  
  }
861  
862  
  public static synchronized void DiskSnippetCache_put(long snippetID, String snippet) throws IOException {
863  
    saveTextFile(DiskSnippetCache_getFile(snippetID).getPath(), snippet);
864  
  }
865  
866  
  public static synchronized void DiskSnippetCache_putLibrary(long snippetID, byte[] data) throws IOException {
867  
    saveBinaryFile(new File(getGlobalCache(), "data_" + snippetID).getPath() + ".jar", data);
868  
  }
869  
870  
  public static File DiskSnippetCache_getDir() {
871  
    return DiskSnippetCache_dir;
872  
  }
873  
874  
  public static void initSnippetCache() {
875  
    if (DiskSnippetCache_dir == null)
876  
      initDiskSnippetCache(getGlobalCache());
877  
  }
878  
879  
  private static File getGlobalCache() {
880  
    File file = new File(userHome(), ".tinybrain/snippet-cache");
881  
    file.mkdirs();
882  
    return file;
883  
  }
884  
885  
  public static String loadSnippetVerified(String snippetID, String hash) throws IOException {
886  
    String text = loadSnippet(snippetID);
887  
    String realHash = getHash(text.getBytes("UTF-8"));
888  
    if (!realHash.equals(hash)) {
889  
      String msg;
890  
      if (hash.isEmpty())
891  
        msg = "Here's your hash for " + snippetID + ", please put in your program: " + realHash;
892  
      else
893  
        msg = "Hash mismatch for " + snippetID + ": " + realHash + " (new) vs " + hash + " - has tinybrain.de been hacked??";
894  
      throw new RuntimeException(msg);
895  
    }
896  
    return text;
897  
  }
898  
899  
  public static String getHash(byte[] data) {
900  
    return bytesToHex(getFullFingerprint(data));
901  
  }
902  
903  
  public static byte[] getFullFingerprint(byte[] data) {
904  
    try {
905  
      return MessageDigest.getInstance("MD5").digest(data);
906  
    } catch (NoSuchAlgorithmException e) {
907  
      throw new RuntimeException(e);
908  
    }
909  
  }
910  
911  
  public static String bytesToHex(byte[] bytes) {
912  
    return bytesToHex(bytes, 0, bytes.length);
913  
  }
914  
915  
  public static String bytesToHex(byte[] bytes, int ofs, int len) {
916  
    StringBuilder stringBuilder = new StringBuilder(len*2);
917  
    for (int i = 0; i < len; i++) {
918  
      String s = "0" + Integer.toHexString(bytes[ofs+i]);
919  
      stringBuilder.append(s.substring(s.length()-2, s.length()));
920  
    }
921  
    return stringBuilder.toString();
922  
  }
923  
924  
  public static String loadSnippet(String snippetID) throws IOException {
925  
    return loadSnippet(parseSnippetID(snippetID));
926  
  }
927  
928  
  public static long parseSnippetID(String snippetID) {
929  
    return Long.parseLong(shortenSnippetID(snippetID));
930  
  }
931  
932  
  private static String shortenSnippetID(String snippetID) {
933  
    if (snippetID.startsWith("#"))
934  
      snippetID = snippetID.substring(1);
935  
    String httpBlaBla = "http://tinybrain.de/";
936  
    if (snippetID.startsWith(httpBlaBla))
937  
      snippetID = snippetID.substring(httpBlaBla.length());
938  
    return snippetID;
939  
  }
940  
941  
  public static boolean isSnippetID(String snippetID) {
942  
    snippetID = shortenSnippetID(snippetID);
943  
    return isInteger(snippetID) && Long.parseLong(snippetID) != 0;
944  
  }
945  
946  
  public static boolean isInteger(String s) {
947  
    return Pattern.matches("\\-?\\d+", s);
948  
  }
949  
  
950  
  static String getTranspilationFromBossBot(long snippetID) {
951  
    return boss(format3("get transpilation for *", snippetID));
952  
  }
953  
  
954  
  public static String loadSnippet(long snippetID) throws IOException {
955  
    String text = getSnippetFromBossBot(snippetID);
956  
    if (text != null) return text;
957  
    
958  
    text = memSnippetCache.get(snippetID);
959  
    if (text != null) {
960  
      if (verbose)
961  
        System.out.println("Getting " + snippetID + " from mem cache");
962  
      return text;
963  
    }
964  
    
965  
    initSnippetCache();
966  
    text = DiskSnippetCache_get(snippetID);
967  
    if (preferCached && text != null) {
968  
      if (verbose)
969  
        System.out.println("Getting " + snippetID + " from disk cache (preferCached)");
970  
      return text;
971  
    }
972  
973  
    String md5 = text != null ? md5(text) : "-";
974  
    if (text != null) {
975  
      String hash = prefetched.get(snippetID);
976  
      if (hash != null) {
977  
        if (md5.equals(hash)) {
978  
          memSnippetCache.put(snippetID, text);
979  
          if (verbose)
980  
            System.out.println("Getting " + snippetID + " from prefetched");
981  
          return text;
982  
        } else
983  
          prefetched.remove(snippetID); // (maybe this is not necessary)
984  
      }
985  
    }
986  
987  
    try {
988  
      /*URL url = new URL("http://tinybrain.de:8080/getraw.php?id=" + snippetID);
989  
      text = loadPage(url);*/
990  
      String theURL = "http://tinybrain.de:8080/getraw.php?id=" + snippetID + "&getmd5=1&utf8=1&usetranspiled=1";
991  
      if (text != null) {
992  
        //System.err.println("MD5: " + md5);
993  
        theURL += "&md5=" + md5;
994  
      }
995  
      URL url = new URL(theURL);
996  
      String page = loadPage(url);
997  
998  
      // parse & drop transpilation flag available line
999  
      int i = page.indexOf('\n');
1000  
      boolean hasTranspiled = page.substring(0, i).trim().equals("1");
1001  
      if (hasTranspiled)
1002  
        hasTranspiledSet.add(snippetID);
1003  
      else
1004  
        hasTranspiledSet.remove(snippetID);
1005  
      page = page.substring(i+1);
1006  
1007  
      if (page.startsWith("==*#*==")) {
1008  
        // same, keep text
1009  
        //System.err.println("Snippet unchanged, keeping.");
1010  
      } else {
1011  
        // drop md5 line
1012  
        i = page.indexOf('\n');
1013  
        String hash = page.substring(0, i).trim();
1014  
        text = page.substring(i+1);
1015  
1016  
        String myHash = md5(text);
1017  
        if (myHash.equals(hash)) {
1018  
          //System.err.println("Hash match: " + hash);
1019  
        } else
1020  
          System.err.println("Hash mismatch");
1021  
      }
1022  
    } catch (FileNotFoundException e) {
1023  
      e.printStackTrace();
1024  
      throw new IOException("Snippet #" + snippetID + " not found or not public");
1025  
    }
1026  
1027  
    memSnippetCache.put(snippetID, text);
1028  
1029  
    try {
1030  
      initSnippetCache();
1031  
      DiskSnippetCache_put(snippetID, text);
1032  
    } catch (IOException e) {
1033  
      System.err.println("Minor warning: Couldn't save snippet to cache ("  + DiskSnippetCache_getDir() + ")");
1034  
    }
1035  
1036  
    return text;
1037  
  }
1038  
1039  
  private static String md5(String text) {
1040  
    try {
1041  
      return bytesToHex(md5impl(text.getBytes("UTF-8"))); // maybe different than the way PHP does it...
1042  
    } catch (UnsupportedEncodingException e) {
1043  
      throw new RuntimeException(e);
1044  
    }
1045  
  }
1046  
1047  
  public static byte[] md5impl(byte[] data) {
1048  
    try {
1049  
      return MessageDigest.getInstance("MD5").digest(data);
1050  
    } catch (NoSuchAlgorithmException e) {
1051  
      throw new RuntimeException(e);
1052  
    }
1053  
  }
1054  
1055  
  private static String loadPage(URL url) throws IOException {
1056  
    System.err.println("Loading: " + url.toExternalForm());
1057  
    URLConnection con = url.openConnection();
1058  
    return loadPage(con, url);
1059  
  }
1060  
1061  
  public static String loadPage(URLConnection con, URL url) throws IOException {
1062  
    setHeaders(con);
1063  
    String contentType = con.getContentType();
1064  
    if (contentType == null)
1065  
      throw new IOException("Page could not be read: " + url);
1066  
    //Log.info("Content-Type: " + contentType);
1067  
    String charset = guessCharset(contentType);
1068  
    //System.err.println("Charset: " + charset);
1069  
    Reader r = new InputStreamReader(con.getInputStream(), charset);
1070  
    StringBuilder buf = new StringBuilder();
1071  
    while (true) {
1072  
      int ch = r.read();
1073  
      if (ch < 0)
1074  
        break;
1075  
      //Log.info("Chars read: " + buf.length());
1076  
      buf.append((char) ch);
1077  
    }
1078  
    return buf.toString();
1079  
  }
1080  
1081  
  public static byte[] loadBinaryPage(URLConnection con) throws IOException {
1082  
    setHeaders(con);
1083  
    return loadBinaryPage_noHeaders(con);
1084  
  }
1085  
1086  
  private static byte[] loadBinaryPage_noHeaders(URLConnection con) throws IOException {
1087  
    ByteArrayOutputStream buf = new ByteArrayOutputStream();
1088  
    InputStream inputStream = con.getInputStream();
1089  
    while (true) {
1090  
      int ch = inputStream.read();
1091  
      if (ch < 0)
1092  
        break;
1093  
      buf.write(ch);
1094  
    }
1095  
    inputStream.close();
1096  
    return buf.toByteArray();
1097  
  }
1098  
1099  
  private static void setHeaders(URLConnection con) throws IOException {
1100  
    String computerID = getComputerID();
1101  
    if (computerID != null)
1102  
      con.setRequestProperty("X-ComputerID", computerID);
1103  
  }
1104  
1105  
  public static String guessCharset(String contentType) {
1106  
    Pattern p = Pattern.compile("text/html;\\s+charset=([^\\s]+)\\s*");
1107  
    Matcher m = p.matcher(contentType);
1108  
    /* If Content-Type doesn't match this pre-conception, choose default and hope for the best. */
1109  
    return m.matches() ? m.group(1) : "ISO-8859-1";
1110  
  }
1111  
1112  
  /** runs a transpiled set of sources */
1113  
  public static void javax2(File srcDir, File ioBaseDir, boolean silent, boolean runInProcess,
1114  
                            List<File> libraries, String[] args, String cacheAs,
1115  
                            String programID, Info info) throws Exception {
1116  
    if (android) {
1117  
      // TODO: no translator virtualization? huh?
1118  
      javax2android(srcDir, args, programID);
1119  
    } else {
1120  
      File classesDir = TempDirMaker_make();
1121  
      String javacOutput = compileJava(srcDir, libraries, classesDir);
1122  
1123  
      // run
1124  
1125  
      if (verbose) System.out.println("Running program (" + srcDir.getAbsolutePath()
1126  
        + ") on io dir " + ioBaseDir.getAbsolutePath() + (runInProcess ? "[in-process]" : "") + "\n");
1127  
      runProgram(javacOutput, classesDir, ioBaseDir, silent, runInProcess, libraries, args, cacheAs, programID, info);
1128  
    }
1129  
  }
1130  
1131  
  static Class<?> loadx2android(File srcDir, String programID) throws Exception {
1132  
    // TODO: optimize if it's a loaded snippet anyway
1133  
    URL url = new URL("http://tinybrain.de:8080/dexcompile.php");
1134  
    URLConnection conn = url.openConnection();
1135  
    String postData = "src=" + URLEncoder.encode(loadTextFile(new File(srcDir, "main.java").getPath(), null), "UTF-8");
1136  
    byte[] dexData = doPostBinary(postData, conn);
1137  
    if (!isDex(dexData))
1138  
      throw new RuntimeException("Dex generation error: " + dexData.length + " bytes - " + new String(dexData, "UTF-8"));
1139  
    System.out.println("Dex loaded: " + dexData.length + "b");
1140  
1141  
    File dexDir = TempDirMaker_make();
1142  
    File dexFile = new File(dexDir, System.currentTimeMillis() + ".dex");
1143  
    File dexOutputDir = TempDirMaker_make();
1144  
1145  
    System.out.println("Saving dex to: " + dexDir.getAbsolutePath());
1146  
    try {
1147  
      saveBinaryFile(dexFile.getPath(), dexData);
1148  
    } catch (Throwable e) {
1149  
      System.out.println("Whoa!");
1150  
      throw new RuntimeException(e);
1151  
    }
1152  
1153  
    System.out.println("Getting parent class loader.");
1154  
    ClassLoader parentClassLoader =
1155  
      //ClassLoader.getSystemClassLoader(); // does not find support jar
1156  
      //getClass().getClassLoader(); // Let's try this...
1157  
      x28.class.getClassLoader().getParent(); // XXX !
1158  
1159  
    //System.out.println("Making DexClassLoader.");
1160  
    //DexClassLoader classLoader = new DexClassLoader(dexFile.getAbsolutePath(), dexOutputDir.getAbsolutePath(), null,
1161  
    //  parentClassLoader);
1162  
    Class dcl = Class.forName("dalvik.system.DexClassLoader");
1163  
    Object classLoader = dcl.getConstructors()[0].newInstance(dexFile.getAbsolutePath(), dexOutputDir.getAbsolutePath(), null,
1164  
      parentClassLoader);
1165  
1166  
    //System.out.println("Loading main class.");
1167  
    //Class<?> theClass = classLoader.loadClass(mainClassName);
1168  
    Class<?> theClass = (Class<?>) call(classLoader, "loadClass", "main");
1169  
1170  
    //System.out.println("Main class loaded.");
1171  
    try {
1172  
      set(theClass, "androidContext", androidContext);
1173  
    } catch (Throwable e) {}
1174  
1175  
    setVars(theClass, programID);
1176  
    
1177  
    addInstance(programID, theClass);
1178  
    
1179  
    return theClass;
1180  
  }
1181  
  
1182  
  static void addInstance(S programID, Class mainClass) {
1183  
    programID = "" + parseSnippetID(programID);
1184  
    instances.put(programID, new WeakReference<Class>(mainClass));
1185  
  }
1186  
  
1187  
  static Class getInstance(S programID) {
1188  
    programID = "" + parseSnippetID(programID);
1189  
    L<WeakReference<Class>> l = instances.get(programID);
1190  
    for (WeakReference<Class> c : l) {
1191  
      Class theClass = c.get();
1192  
      // TODO: shorten the list
1193  
      if (theClass != null)
1194  
        return theClass;
1195  
    }
1196  
    return null;
1197  
  }
1198  
  
1199  
  static MultiMap<String, WeakReference<Class>> instances = new MultiMap<String, WeakReference<Class>>();
1200  
  
1201  
  !include #1001296 // MultiMap
1202  
1203  
  static void javax2android(File srcDir, String[] args, String programID) throws Exception {
1204  
    Class<?> theClass = loadx2android(srcDir, programID);
1205  
1206  
    Method main = null;
1207  
    try {
1208  
      main = call_findStaticMethod(theClass, "main", new Object[]{androidContext}, false);
1209  
    } catch (RuntimeException e) {
1210  
    }
1211  
1212  
    //System.out.println("main method for " + androidContext + " of " + theClass + ": " + main);
1213  
1214  
    if (main != null) {
1215  
      // old style main program that returns a View
1216  
      System.out.println("Calling main (old-style)");
1217  
      Object view = main.invoke(null, androidContext);
1218  
      System.out.println("Calling setContentView with " + view);
1219  
      call(Class.forName("main"), "setContentViewInUIThread", view);
1220  
      //call(androidContext, "setContentView", view);
1221  
      System.out.println("Done.");
1222  
    } else {
1223  
      System.out.println("New-style main method running.\n\n====\n");
1224  
      runMainMethod(args, theClass);
1225  
    }
1226  
  }
1227  
1228  
  static byte[] DEX_FILE_MAGIC = { 0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x35, 0x00 };
1229  
1230  
  static boolean isDex(byte[] dexData) {
1231  
    if (dexData.length < DEX_FILE_MAGIC.length) return false;
1232  
    for (int i = 0; i < DEX_FILE_MAGIC.length; i++)
1233  
      if (dexData[i] != DEX_FILE_MAGIC[i])
1234  
        return false;
1235  
    return true;
1236  
  }
1237  
1238  
  static byte[] doPostBinary(String urlParameters, URLConnection conn) throws IOException {
1239  
    // connect and do POST
1240  
    setHeaders(conn);
1241  
    conn.setDoOutput(true);
1242  
1243  
    OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
1244  
    writer.write(urlParameters);
1245  
    writer.flush();
1246  
1247  
    byte[] contents = loadBinaryPage_noHeaders(conn);
1248  
    writer.close();
1249  
    return contents;
1250  
  }
1251  
1252  
  static String compileJava(File srcDir, List<File> libraries, File classesDir) throws IOException {
1253  
    javaCompilerOutput = null;
1254  
    ++compilations;
1255  
1256  
    // collect sources
1257  
1258  
    List<File> sources = new ArrayList<File>();
1259  
    if (verbose) System.out.println("Scanning for sources in " + srcDir.getPath());
1260  
    scanForSources(srcDir, sources, true);
1261  
    if (sources.isEmpty())
1262  
      throw new IOException("No sources found");
1263  
1264  
    // compile
1265  
1266  
    File optionsFile = File.createTempFile("javax", "");
1267  
    if (verbose) System.out.println("Compiling " + sources.size() + " source(s) to " + classesDir.getPath());
1268  
    if (verbose) System.out.println("Libraries: " + libraries);
1269  
    String options = "-d " + bashQuote(classesDir.getPath());
1270  
    writeOptions(sources, libraries, optionsFile, options);
1271  
    classesDir.mkdirs();
1272  
    return javaCompilerOutput = invokeJavaCompiler(optionsFile);
1273  
  }
1274  
1275  
  private static void runProgram(String javacOutput, File classesDir, File ioBaseDir,
1276  
                                 boolean silent, boolean runInProcess,
1277  
                                 List<File> libraries, String[] args, String cacheAs,
1278  
                                 String programID, Info info) throws Exception {
1279  
    // print javac output if compile failed and it hasn't been printed yet
1280  
    if (info != null) {
1281  
      info.programID = programID;
1282  
      info.programArgs = args;
1283  
    }
1284  
    boolean didNotCompile = !didCompile(classesDir);
1285  
    if (verbose || didNotCompile)
1286  
      System.out.println(javacOutput);
1287  
    if (didNotCompile)
1288  
      return;
1289  
1290  
    if (runInProcess
1291  
      || (ioBaseDir.getAbsolutePath().equals(new File(".").getAbsolutePath()) && !silent)) {
1292  
      runProgramQuick(classesDir, libraries, args, cacheAs, programID, info, ioBaseDir);
1293  
      return;
1294  
    }
1295  
1296  
    boolean echoOK = false;
1297  
    // TODO: add libraries to class path
1298  
    String bashCmd = "(cd " + bashQuote(ioBaseDir.getAbsolutePath()) + " && (java -cp "
1299  
      + bashQuote(classesDir.getAbsolutePath()) + " main" + (echoOK ? "; echo ok" : "") + "))";
1300  
    if (verbose) System.out.println(bashCmd);
1301  
    String output = backtick(bashCmd);
1302  
    lastOutput = output;
1303  
    if (verbose || !silent)
1304  
      System.out.println(output);
1305  
  }
1306  
1307  
  static boolean didCompile(File classesDir) {
1308  
    return hasFile(classesDir, "main.class");
1309  
  }
1310  
1311  
  private static void runProgramQuick(File classesDir, List<File> libraries,
1312  
                                      String[] args, String cacheAs,
1313  
                                      String programID, Info info,
1314  
                                      File ioBaseDir) throws Exception {
1315  
    // collect urls
1316  
    URL[] urls = new URL[libraries.size()+1];
1317  
    urls[0] = classesDir.toURI().toURL();
1318  
    for (int i = 0; i < libraries.size(); i++)
1319  
      urls[i+1] = libraries.get(i).toURI().toURL();
1320  
1321  
    // make class loader
1322  
    URLClassLoader classLoader = new URLClassLoader(urls);
1323  
1324  
    // load JavaX main class
1325  
    Class<?> mainClass = classLoader.loadClass("main");
1326  
    
1327  
    if (info != null)
1328  
      info.mainClass = mainClass;
1329  
      
1330  
    if (cacheAs != null)
1331  
      programCache.put(cacheAs, mainClass);
1332  
      
1333  
    // change baseDir
1334  
    try {
1335  
      //print("Changing base dir to " + ioBaseDir.getAbsolutePath());
1336  
      Class virtual = mainClass.getClassLoader().loadClass("virtual");
1337  
      set(virtual, "virtual_baseDir", ioBaseDir.getAbsolutePath());
1338  
    } catch (Throwable e) { /* whatever */ }
1339  
1340  
    setVars(mainClass, programID);
1341  
    addInstance(programID, mainClass);
1342  
    runMainMethod(args, mainClass);
1343  
  }
1344  
1345  
  static void setVars(Class<?> theClass, String programID) {
1346  
    try {
1347  
      set(theClass, "programID", programID);
1348  
    } catch (Throwable e) {}
1349  
1350  
    try {
1351  
      set(theClass, "__javax", x28.class);
1352  
    } catch (Throwable e) {}
1353  
  }
1354  
1355  
1356  
  static void runMainMethod(Object args, Class<?> mainClass) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
1357  
    Method main = mainClass.getMethod("main", String[].class);
1358  
    main.invoke(null, args);
1359  
  }
1360  
1361  
  static String invokeJavaCompiler(File optionsFile) throws IOException {
1362  
    String output;
1363  
    if (hasEcj() && !javacOnly)
1364  
      output = invokeEcj(optionsFile);
1365  
    else
1366  
      output = invokeJavac(optionsFile);
1367  
    if (verbose) System.out.println(output);
1368  
    return output;
1369  
  }
1370  
1371  
  private static boolean hasEcj() {
1372  
    try {
1373  
      Class.forName("org.eclipse.jdt.internal.compiler.batch.Main");
1374  
      return true;
1375  
    } catch (ClassNotFoundException e) {
1376  
      return false;
1377  
    }
1378  
  }
1379  
1380  
  private static String invokeJavac(File optionsFile) throws IOException {
1381  
    String output;
1382  
    output = backtick("javac " + bashQuote("@" + optionsFile.getPath()));
1383  
    if (exitValue != 0) {
1384  
      System.out.println(output);
1385  
      throw new RuntimeException("javac returned errors.");
1386  
    }
1387  
    return output;
1388  
  }
1389  
1390  
  // throws ClassNotFoundException if ecj is not in classpath
1391  
  static String invokeEcj(File optionsFile) {
1392  
    try {
1393  
      StringWriter writer = new StringWriter();
1394  
      PrintWriter printWriter = new PrintWriter(writer);
1395  
1396  
      // add more eclipse options in the line below
1397  
1398  
      String[] args = {"@" + optionsFile.getPath(),
1399  
        "-source", javaTarget,
1400  
        "-target", javaTarget,
1401  
        "-nowarn"
1402  
      };
1403  
1404  
      Class ecjClass = Class.forName("org.eclipse.jdt.internal.compiler.batch.Main");
1405  
      Object main = newInstance(ecjClass, printWriter, printWriter, false);
1406  
      call(main, "compile", new Object[]{args});
1407  
      int errors = (Integer) get(main, "globalErrorsCount");
1408  
1409  
      String output = writer.toString();
1410  
      if (errors != 0) {
1411  
        System.out.println(output);
1412  
        throw new RuntimeException("Java compiler returned errors.");
1413  
      }
1414  
      return output;
1415  
    } catch (Exception e) {
1416  
      throw e instanceof RuntimeException ? (RuntimeException) e : new RuntimeException(e);
1417  
    }
1418  
  }
1419  
1420  
  static Object newInstance(Class c, Object... args) { try {
1421  
    Constructor m = findConstructor(c, args);
1422  
    m.setAccessible(true);
1423  
    return m.newInstance(args);
1424  
  } catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
1425  
1426  
  static Constructor findConstructor(Class c, Object... args) {
1427  
    for (Constructor m : c.getDeclaredConstructors()) {
1428  
      if (!checkArgs(m.getParameterTypes(), args, verbose))
1429  
        continue;
1430  
      return m;
1431  
    }
1432  
    throw new RuntimeException("Constructor with " + args.length + " matching parameter(s) not found in " + c.getName());
1433  
  }
1434  
1435  
  static boolean checkArgs(Class[] types, Object[] args, boolean debug) {
1436  
    if (types.length != args.length) {
1437  
      if (debug)
1438  
        System.out.println("Bad parameter length: " + args.length + " vs " + types.length);
1439  
      return false;
1440  
    }
1441  
    for (int i = 0; i < types.length; i++)
1442  
      if (!(args[i] == null || isInstanceX(types[i], args[i]))) {
1443  
        if (debug)
1444  
          System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]);
1445  
        return false;
1446  
      }
1447  
    return true;
1448  
  }
1449  
1450  
  // extended to handle primitive types
1451  
  private static boolean isInstanceX(Class type, Object arg) {
1452  
    if (type == boolean.class) return arg instanceof Boolean;
1453  
    if (type == int.class) return arg instanceof Integer;
1454  
    if (type == long.class) return arg instanceof Long;
1455  
    if (type == float.class) return arg instanceof Float;
1456  
    if (type == short.class) return arg instanceof Short;
1457  
    if (type == char.class) return arg instanceof Character;
1458  
    if (type == byte.class) return arg instanceof Byte;
1459  
    return type.isInstance(arg);
1460  
  }
1461  
1462  
  private static void writeOptions(List<File> sources, List<File> libraries,
1463  
                                   File optionsFile, String moreOptions) throws IOException {
1464  
    FileWriter writer = new FileWriter(optionsFile);
1465  
    for (File source : sources)
1466  
      writer.write(bashQuote(source.getPath()) + " ");
1467  
    if (!libraries.isEmpty()) {
1468  
      List<String> cp = new ArrayList<String>();
1469  
      for (File lib : libraries)
1470  
        cp.add(lib.getAbsolutePath());
1471  
      writer.write("-cp " + bashQuote(join(File.pathSeparator, cp)) + " ");
1472  
    }
1473  
    writer.write(moreOptions);
1474  
    writer.close();
1475  
  }
1476  
1477  
  static void scanForSources(File source, List<File> sources, boolean topLevel) {
1478  
    if (source.isFile() && source.getName().endsWith(".java"))
1479  
      sources.add(source);
1480  
    else if (source.isDirectory() && !isSkippedDirectoryName(source.getName(), topLevel)) {
1481  
      File[] files = source.listFiles();
1482  
      for (File file : files)
1483  
        scanForSources(file, sources, false);
1484  
    }
1485  
  }
1486  
1487  
  private static boolean isSkippedDirectoryName(String name, boolean topLevel) {
1488  
    if (topLevel) return false; // input or output ok as highest directory (intentionally specified by user, not just found by a directory scan in which case we probably don't want it. it's more like heuristics actually.)
1489  
    return name.equalsIgnoreCase("input") || name.equalsIgnoreCase("output");
1490  
  }
1491  
1492  
  static int exitValue;
1493  
  public static String backtick(String cmd) throws IOException {
1494  
    ++processesStarted;
1495  
    File outFile = File.createTempFile("_backtick", "");
1496  
    File scriptFile = File.createTempFile("_backtick", isWindows() ? ".bat" : "");
1497  
1498  
    String command = cmd + " >" + bashQuote(outFile.getPath()) + " 2>&1";
1499  
    //Log.info("[Backtick] " + command);
1500  
    try {
1501  
      saveTextFile(scriptFile.getPath(), command);
1502  
      String[] command2;
1503  
      if (isWindows())
1504  
        command2 = new String[] { scriptFile.getPath() };
1505  
      else
1506  
        command2 = new String[] { "/bin/bash", scriptFile.getPath() };
1507  
      Process process = Runtime.getRuntime().exec(command2);
1508  
      try {
1509  
        process.waitFor();
1510  
      } catch (InterruptedException e) {
1511  
        throw new RuntimeException(e);
1512  
      }
1513  
      exitValue = process.exitValue();
1514  
      if (verbose)
1515  
        System.out.println("Process return code: " + exitValue);
1516  
      return loadTextFile(outFile.getPath(), "");
1517  
    } finally {
1518  
      scriptFile.delete();
1519  
    }
1520  
  }
1521  
1522  
  /** possibly improvable */
1523  
  public static String javaQuote(String text) {
1524  
    return bashQuote(text);
1525  
  }
1526  
1527  
  /** possibly improvable */
1528  
  public static String bashQuote(String text) {
1529  
    if (text == null) return null;
1530  
    return "\"" + text
1531  
      .replace("\\", "\\\\")
1532  
      .replace("\"", "\\\"")
1533  
      .replace("\n", "\\n")
1534  
      .replace("\r", "\\r") + "\"";
1535  
  }
1536  
1537  
  public final static String charsetForTextFiles = "UTF8";
1538  
1539  
  static long TempDirMaker_lastValue;
1540  
1541  
  public static File TempDirMaker_make() {
1542  
    File dir = new File(userHome(), ".javax/" + TempDirMaker_newValue());
1543  
    dir.mkdirs();
1544  
    return dir;
1545  
  }
1546  
1547  
  private static long TempDirMaker_newValue() {
1548  
    long value;
1549  
    do
1550  
      value = System.currentTimeMillis();
1551  
    while (value == TempDirMaker_lastValue);
1552  
    TempDirMaker_lastValue = value;
1553  
    return value;
1554  
  }
1555  
1556  
  !include #1000810 // join
1557  
  
1558  
  public static boolean isWindows() {
1559  
    return System.getProperty("os.name").contains("Windows");
1560  
  }
1561  
1562  
  public static String makeRandomID(int length) {
1563  
    Random random = new Random();
1564  
    char[] id = new char[length];
1565  
    for (int i = 0; i< id.length; i++)
1566  
      id[i] = (char) ((int) 'a' + random.nextInt(26));
1567  
    return new String(id);
1568  
  }
1569  
1570  
  static String computerID;
1571  
  public static String getComputerID() throws IOException {
1572  
    if (noID) return null;
1573  
    if (computerID == null) {
1574  
      File file = new File(userHome(), ".tinybrain/computer-id");
1575  
      computerID = loadTextFile(file.getPath(), null);
1576  
      if (computerID == null) {
1577  
        computerID = makeRandomID(12);
1578  
        saveTextFile(file.getPath(), computerID);
1579  
      }
1580  
      if (verbose)
1581  
        System.out.println("Local computer ID: " + computerID);
1582  
    }
1583  
    return computerID;
1584  
  }
1585  
1586  
  static int fileDeletions;
1587  
1588  
  static void cleanCache() {
1589  
    try {
1590  
      if (verbose)
1591  
        System.out.println("Cleaning cache");
1592  
      fileDeletions = 0;
1593  
      File javax = new File(userHome(), ".javax");
1594  
      long now = System.currentTimeMillis();
1595  
      File[] files = javax.listFiles();
1596  
      if (files != null) for (File dir : files) {
1597  
        if (dir.isDirectory() && Pattern.compile("\\d+").matcher(dir.getName()).matches()) {
1598  
          long time = Long.parseLong(dir.getName());
1599  
          long seconds = (now - time) / 1000;
1600  
          long minutes = seconds / 60;
1601  
          long hours = minutes / 60;
1602  
          if (hours >= tempFileRetentionTime) {
1603  
            //System.out.println("Can delete " + dir.getAbsolutePath() + ", age: " + hours + " h");
1604  
            removeDir(dir);
1605  
          }
1606  
        }
1607  
      }
1608  
      if (verbose && fileDeletions != 0)
1609  
        System.out.println("Cleaned cache. File deletions: " + fileDeletions);
1610  
    } catch (Throwable e) {
1611  
      e.printStackTrace();
1612  
    }
1613  
  }
1614  
1615  
  static void removeDir(File dir) {
1616  
    if (dir.getAbsolutePath().indexOf(".javax") < 0)  // security check!
1617  
      return;
1618  
    for (File f : dir.listFiles()) {
1619  
      if (f.isDirectory())
1620  
        removeDir(f);
1621  
      else {
1622  
        if (verbose)
1623  
          System.out.println("Deleting " + f.getAbsolutePath());
1624  
        f.delete();
1625  
        ++fileDeletions;
1626  
      }
1627  
    }
1628  
    dir.delete();
1629  
  }
1630  
1631  
  static void showSystemProperties() {
1632  
    System.out.println("System properties:\n");
1633  
    for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
1634  
      System.out.println("  " + entry.getKey() + " = " + entry.getValue());
1635  
    }
1636  
    System.out.println();
1637  
  }
1638  
1639  
  static void showVersion() {
1640  
    //showSystemProperties();
1641  
    boolean eclipseFound = hasEcj();
1642  
    //String platform = System.getProperty("java.vendor") + " " + System.getProperty("java.runtime.name") + " " + System.getProperty("java.version");
1643  
    String platform = System.getProperty("java.vm.name") + " " + System.getProperty("java.version");
1644  
    String os = System.getProperty("os.name"), arch = System.getProperty("os.arch");
1645  
    System.out.println("This is " + version + ".");
1646  
    System.out.println("[Details: " +
1647  
      (eclipseFound ? "Eclipse compiler (good)" : "javac (not so good)")
1648  
      + ", " + platform + ", " + arch + ", " + os + "]");
1649  
  }
1650  
1651  
  static boolean isAndroid() {
1652  
    return System.getProperty("java.vendor").toLowerCase().indexOf("android") >= 0;
1653  
  }
1654  
  
1655  
  !include #1000415 // set function
1656  
1657  
  static String smartJoin(String[] args) {
1658  
    String[] a2 = new String[args.length];
1659  
    for (int i = 0; i < args.length; i++) {
1660  
      a2[i] = Pattern.compile("\\w+").matcher(args[i]).matches() ? args[i] : quote(args[i]);
1661  
    }
1662  
    return join(" ", a2);
1663  
  }
1664  
  
1665  
  static void logStart(String[] args) throws IOException {
1666  
    String line = smartJoin(args);
1667  
    appendToLog(new File(userHome(), ".javax/log.txt").getPath(), line);
1668  
  }
1669  
  
1670  
  static String quote(String s) {
1671  
    if (s == null) return "null";
1672  
    return "\"" + s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\r", "\\r").replace("\n", "\\n") + "\"";
1673  
  }
1674  
  
1675  
  static void appendToLog(String path, String line) throws IOException {
1676  
    appendToFile(path, "\n" + line + "\n");
1677  
  }
1678  
  
1679  
  static void appendToFile(String path, String s) throws IOException {
1680  
    new File(path).getParentFile().mkdirs();
1681  
    Writer writer = new BufferedWriter(new OutputStreamWriter(
1682  
      new FileOutputStream(path, true), "UTF-8"));
1683  
    writer.write(s);
1684  
    writer.close();
1685  
  }
1686  
1687  
  !include #1000943
1688  
1689  
  static PrintStream oldOut, oldErr;
1690  
  static Thread reader, reader2;
1691  
  static boolean quit; // always false now
1692  
  static PipedInputStream pin=new PipedInputStream();
1693  
  static PipedInputStream pin2=new PipedInputStream();
1694  
  static PipedInputStream pin3=new PipedInputStream();
1695  
1696  
  static class Console extends WindowAdapter implements WindowListener, ActionListener {
1697  
    JFrame frame;
1698  
    JTextArea textArea;
1699  
    JTextField tfInput;
1700  
    StringBuffer buf = new StringBuffer();
1701  
    JButton buttonclear, buttonkill, buttonrestart, buttonduplicate, buttonstacktrace;
1702  
    String[] args;
1703  
1704  
    final DelayedUpdate du = new DelayedUpdate(new Runnable() {
1705  
      public void run() { try {
1706  
1707  
        textArea.append(buf.substring(textArea.getText().length()));
1708  
1709  
      } catch (Exception __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}});
1710  
1711  
    public Console(final String[] args) ctex {
1712  
      this.args = args;
1713  
      // create all components and add them
1714  
      frame=new JFrame(args.length == 0 ? "JavaX Starter Output" : "JavaX Output - " + join(" ", args));
1715  
1716  
		/*Dimension screenSize=Toolkit.getDefaultToolkit().getScreenSize();
1717  
		Dimension frameSize=new Dimension((int)(screenSize.width/2),(int)(screenSize.height/2));
1718  
		int x=(int)(frameSize.width/2);
1719  
		int y=(int)(frameSize.height/2);
1720  
		frame.setBounds(x,y,frameSize.width,frameSize.height);*/
1721  
1722  
      // put in right-bottom corner
1723  
      Rectangle r = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
1724  
      int w = 550, h = 200;
1725  
      frame.setBounds(r.x+r.width-w, r.y+r.height-h, w, h);
1726  
1727  
      textArea=new JTextArea();
1728  
      textArea.setEditable(false);
1729  
      buttonclear = new JButton("clear");
1730  
      buttonkill = new JButton("kill");
1731  
      buttonrestart = new JButton("restart");
1732  
      buttonduplicate = new JButton("duplicate");
1733  
      buttonstacktrace = new JButton("status");
1734  
      buttonstacktrace.setToolTipText("Show threads & stack traces.");
1735  
1736  
      JPanel buttons = new JPanel(new GridLayout(1, 5));
1737  
      buttons.add(buttonclear);
1738  
      buttons.add(buttonkill);
1739  
      buttons.add(buttonrestart);
1740  
      buttons.add(buttonduplicate);
1741  
      buttons.add(buttonstacktrace);
1742  
1743  
      final PipedOutputStream pout3=new PipedOutputStream(pin3);
1744  
      tfInput = new JTextField();
1745  
      tfInput.addActionListener(actionListener {
1746  
        S line = tfInput.getText();
1747  
        try {
1748  
          pout3.write((line + "\n").getBytes("UTF-8"));
1749  
          pout3.flush();
1750  
        } catch (Exception e) {}
1751  
        tfInput.setText("");
1752  
      });
1753  
      
1754  
      JPanel panel = new JPanel(new BorderLayout());
1755  
      panel.add(new JScrollPane(textArea), BorderLayout.CENTER);
1756  
      panel.add(tfInput, BorderLayout.SOUTH);
1757  
      
1758  
      frame.addWindowListener(new WindowAdapter() {
1759  
        public void windowActivated(WindowEvent e) {
1760  
          tfInput.requestFocus();
1761  
        }
1762  
      });
1763  
      
1764  
      frame.getContentPane().setLayout(new BorderLayout());
1765  
      frame.getContentPane().add(panel, BorderLayout.CENTER);
1766  
      frame.getContentPane().add(buttons, BorderLayout.SOUTH);
1767  
      frame.setVisible(true);
1768  
      
1769  
      //frame.addWindowListener(this); // disabled for now
1770  
      buttonclear.addActionListener(this);
1771  
      buttonkill.addActionListener(this);
1772  
      buttonrestart.addActionListener(this);
1773  
      buttonduplicate.addActionListener(this);
1774  
      buttonstacktrace.addActionListener(this);
1775  
1776  
      quit=false; // signals the Threads that they should exit
1777  
      
1778  
      if (args.length != 0) {
1779  
        print("Starting title updater");
1780  
        new Thread("Console Title Updater :)") {
1781  
          public void run() {
1782  
            if (args.length != 0) {
1783  
              int i = 0;
1784  
              while (i < args.length && !isSnippetID(args[i])) ++i;
1785  
              print("Getting title for " + args[i]);
1786  
              String title = getSnippetTitle(args[i]);
1787  
              print("Title: " + title);
1788  
              if (title != null && title.length() != 0)
1789  
                frame.setTitle(title + " [Output]");
1790  
            }
1791  
          }
1792  
        }.start();
1793  
      }
1794  
      
1795  
      System.setIn(pin3);
1796  
      
1797  
    }
1798  
1799  
    public synchronized void windowClosed(WindowEvent evt)
1800  
    {
1801  
      console = null;
1802  
      /*quit=true;
1803  
      this.notifyAll(); // stop all threads
1804  
      try { reader.join(1000);pin.close();   } catch (Exception e){}
1805  
      try { reader2.join(1000);pin2.close(); } catch (Exception e){}
1806  
      System.exit(0);*/
1807  
    }
1808  
1809  
    public synchronized void windowClosing(WindowEvent evt)
1810  
    {
1811  
      frame.setVisible(false); // default behaviour of JFrame
1812  
      frame.dispose();
1813  
    }
1814  
1815  
    public synchronized void actionPerformed(ActionEvent evt) {
1816  
      if (evt.getSource() == buttonkill) {
1817  
        print("Console: Kill button pressed!");
1818  
        // TODO: give threads time to finish, e.g. reportToChat?
1819  
        System.exit(0);
1820  
      } else if (evt.getSource() == buttonrestart) {
1821  
        print("Console: Restart button pressed.");
1822  
        nohupJavax(smartJoin(args));
1823  
        System.exit(0);
1824  
      } else if (evt.getSource() == buttonduplicate) {
1825  
        print("Console: Duplicate button pressed.");
1826  
        nohupJavax(smartJoin(args));
1827  
      } else if (evt.getSource() == buttonstacktrace) {
1828  
        listUserThreadsWithStackTraces();
1829  
      } else {
1830  
        textArea.setText("");
1831  
        buf = new StringBuffer();
1832  
      }
1833  
    }
1834  
1835  
    public void appendText(String s, boolean outNotErr) {
1836  
      //if (verbose) oldOut.println("Console appendText " + outNotErr + " " + quote(s));
1837  
      buf.append(s);
1838  
      du.trigger();
1839  
    }
1840  
  } // Console
1841  
1842  
	static void tryToOpenConsole(String[] args) {
1843  
	  try {
1844  
	    console = new Console(args);
1845  
	  } catch (HeadlessException e) {
1846  
	    // ok, we're headless.
1847  
	  } catch (Throwable e) {
1848  
	    // some other error in console - continue without it
1849  
	    e.printStackTrace();
1850  
	  }
1851  
	}
1852  
1853  
  //// END CONSOLE STUFF
1854  
1855  
  static long now_virtualTime;
1856  
  static long now() {
1857  
    return now_virtualTime != 0 ? now_virtualTime : System.currentTimeMillis();
1858  
  }
1859  
1860  
  static void print(Object o) {
1861  
    System.out.println(o);
1862  
  }
1863  
1864  
  public synchronized void run()
1865  
  {
1866  
    try
1867  
    {
1868  
      while (Thread.currentThread()==reader)
1869  
      {
1870  
        try { this.wait(100);}catch(InterruptedException ie) {}
1871  
        if (pin.available()!=0)
1872  
        {
1873  
          String input=readLine(pin);
1874  
          //if (verbose) oldOut.println("reader: " + quote(input));
1875  
          appendText(input, true);
1876  
        }
1877  
        if (quit) return;
1878  
      }
1879  
1880  
      while (Thread.currentThread()==reader2)
1881  
      {
1882  
        try { this.wait(100);}catch(InterruptedException ie) {}
1883  
        if (pin2.available()!=0)
1884  
        {
1885  
          String input=readLine(pin2);
1886  
          //if (verbose) oldOut.println("reader2: " + quote(input));
1887  
          appendText(input, false);
1888  
        }
1889  
        if (quit) return;
1890  
      }
1891  
    } catch (Exception e)
1892  
    {
1893  
      appendText("\nConsole reports an Internal error.", false);
1894  
      appendText("The error is: "+e, false);
1895  
    }
1896  
  }
1897  
1898  
  static void redirectSystemOutAndErr() {
1899  
    if (reader != null) return; // did this already
1900  
1901  
    x28 _this = new x28();
1902  
    
1903  
    if (verbose) System.out.println("Redirecting System.out");
1904  
    try
1905  
    {
1906  
      PipedOutputStream pout=new PipedOutputStream(pin);
1907  
      oldOut = System.out;
1908  
      TeeOutputStream tee = new TeeOutputStream(oldOut, pout);
1909  
      System.setOut(new PrintStream(tee,true));
1910  
    }
1911  
    catch (Exception io)
1912  
    {
1913  
      System.err.println("Couldn't redirect STDOUT - " + io.getMessage());
1914  
    }
1915  
1916  
    if (verbose) System.out.println("Redirecting System.err");
1917  
    try
1918  
    {
1919  
      PipedOutputStream pout2=new PipedOutputStream(pin2);
1920  
      oldErr = System.err;
1921  
      TeeOutputStream tee = new TeeOutputStream(oldErr, pout2);
1922  
      System.setErr(new PrintStream(tee,true));
1923  
    }
1924  
    catch (Exception io)
1925  
    {
1926  
      System.err.println("Couldn't redirect STDERR - " + io.getMessage());
1927  
    }
1928  
1929  
    if (verbose) System.out.println("Redirects done. Starting readers");
1930  
    
1931  
    // Starting two seperate threads to read from the PipedInputStreams
1932  
    //
1933  
    reader=new Thread(_this, "StdOut Piper");
1934  
    reader.setDaemon(true);
1935  
    reader.start();
1936  
    //
1937  
    reader2 = new Thread(_this, "StdErr Piper");
1938  
    reader2.setDaemon(true);
1939  
    reader2.start();
1940  
  }
1941  
1942  
  static Appendable customSystemOut;
1943  
1944  
  static void appendText(String s, boolean outNotErr) {
1945  
    // We do this with a TeeOutputStream now (safer).
1946  
    // (outNotErr ? oldOut : oldErr).print(s);
1947  
    
1948  
    if (console != null)
1949  
      console.appendText(s, outNotErr);
1950  
    if (customSystemOut != null)
1951  
      try {
1952  
        customSystemOut.append(s);
1953  
      } catch (IOException e) {
1954  
        e.printStackTrace();
1955  
      }
1956  
  }
1957  
1958  
  static String readLine(PipedInputStream in) throws IOException
1959  
  {
1960  
    String input="";
1961  
    do
1962  
    {
1963  
      int available=in.available();
1964  
      if (available==0) break;
1965  
      byte b[]=new byte[available];
1966  
      in.read(b);
1967  
      input=input+new String(b,0,b.length);
1968  
    }while( !input.endsWith("\n") &&  !input.endsWith("\r\n") && !quit);
1969  
    return input;
1970  
  }
1971  
1972  
  static void nohupJavax(String javaxargs) {
1973  
    try {
1974  
      File xfile = new File(userHome(), ".javax/x28.jar");
1975  
      if (!xfile.isFile()) {
1976  
        String url = "http://tinybrain.de/x28.jar";
1977  
        byte[] data = loadBinaryPage(new URL(url).openConnection());
1978  
        if (data.length < 1000000)
1979  
          throw new RuntimeException("Could not load " + url);
1980  
        saveBinaryFile(xfile.getPath(), data);
1981  
      }
1982  
      String jarPath = xfile.getPath();
1983  
      nohup("java -jar " + (isWindows() ? winQuote(jarPath) : bashQuote(jarPath)) + " " + javaxargs);
1984  
    } catch (Exception e) { throw new RuntimeException(e); }
1985  
  }
1986  
1987  
  /** possibly improvable */
1988  
  public static String winQuote(String text) {
1989  
    if (text == null) return null;
1990  
    return "\"" + text
1991  
      .replace("\\", "\\\\")
1992  
      .replace("\"", "\\\"")
1993  
      .replace("\n", "\\n")
1994  
      .replace("\r", "\\r") + "\"";
1995  
  }
1996  
1997  
  public static File nohup(String cmd) throws IOException {
1998  
    File outFile = File.createTempFile("nohup_" + nohup_sanitize(cmd), ".out");
1999  
    nohup(cmd, outFile, false);
2000  
    return outFile;
2001  
  }
2002  
2003  
  static String nohup_sanitize(String s) {
2004  
    return s.replaceAll("[^a-zA-Z0-9\\-_]", "");
2005  
  }
2006  
2007  
  /** outFile takes stdout and stderr. */
2008  
  public static void nohup(String cmd, File outFile, boolean append) throws IOException {
2009  
    String command = nohup_makeNohupCommand(cmd, outFile, append);
2010  
2011  
    File scriptFile = File.createTempFile("_realnohup", isWindows() ? ".bat" : "");
2012  
    System.out.println("[Nohup] " + command);
2013  
    try {
2014  
      //System.out.println("[RealNohup] Script file: " + scriptFile.getPath());
2015  
      saveTextFile(scriptFile.getPath(), command);
2016  
      String[] command2;
2017  
      if (isWindows())
2018  
        command2 = new String[] {"cmd", "/c", "start", "/b", scriptFile.getPath() };
2019  
      else
2020  
        command2 = new String[] {"/bin/bash", scriptFile.getPath() };
2021  
2022  
      Process process = Runtime.getRuntime().exec(command2);
2023  
      try {
2024  
        process.waitFor();
2025  
      } catch (InterruptedException e) {
2026  
        throw new RuntimeException(e);
2027  
      }
2028  
      int value = process.exitValue();
2029  
      //System.out.println("exit value: " + value);
2030  
    } finally {
2031  
      if (!isWindows())
2032  
        scriptFile.delete();
2033  
    }
2034  
  }
2035  
2036  
  public static String nohup_makeNohupCommand(String cmd, File outFile, boolean append) {
2037  
    mkdirsForFile(outFile);
2038  
2039  
    String command;
2040  
    if (isWindows())
2041  
      command = cmd + (append ? " >>" : " >") + winQuote(outFile.getPath()) + " 2>&1";
2042  
    else
2043  
      command = "nohup " + cmd + (append ? " >>" : " >") + bashQuote(outFile.getPath()) + " 2>&1 &";
2044  
    return command;
2045  
  }
2046  
2047  
  public static void mkdirsForFile(File file) {
2048  
    File dir = file.getParentFile();
2049  
    if (dir != null) // is null if file is in current dir
2050  
      dir.mkdirs();
2051  
  }
2052  
 
2053  
  static void autoReportToChat() {
2054  
    if (customSystemOut == null) {
2055  
      print("Auto-reporting to chat.");
2056  
      customSystemOut = new Appendable() {
2057  
        LineBuf buf = new LineBuf();
2058  
        
2059  
        // only using this one
2060  
        public Appendable append(CharSequence cs) {
2061  
          buf.append(cs.toString());
2062  
          while (true) {
2063  
            String s = buf.nextLine();
2064  
            if (s == null) break;
2065  
            reportToChat(s, true);
2066  
          }
2067  
          return this;
2068  
        }
2069  
    
2070  
        public Appendable append(char c) { return this; }
2071  
        public Appendable append(CharSequence s, int start, int end) { return this; }
2072  
      };
2073  
     }
2074  
  }
2075  
  
2076  
  static class Q {
2077  
    LinkedBlockingQueue<Runnable> q = new LinkedBlockingQueue<Runnable>();
2078  
    
2079  
    static class Done extends RuntimeException {}
2080  
    
2081  
    Q() {}
2082  
    
2083  
    Q(String name, boolean startThread) {
2084  
      if (startThread)
2085  
        new Thread(name) {
2086  
          public void run() {
2087  
            Q.this.run();
2088  
          }
2089  
        }.start();
2090  
    }
2091  
    
2092  
    Iterable<Runnable> master() {
2093  
      return new Iterable<Runnable>() {
2094  
        public Iterator<Runnable> iterator() {
2095  
          return new Iterator<Runnable>() {
2096  
            Runnable x;
2097  
            
2098  
            public boolean hasNext() { try {
2099  
   
2100  
              //debug("hasNext");
2101  
              while (x == null)
2102  
                x = q.poll(1, TimeUnit.DAYS);
2103  
              //debug("hasNext true");
2104  
              return true;
2105  
            
2106  
  } catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
2107  
            
2108  
            public Runnable next() {
2109  
              //debug("next");
2110  
              hasNext();
2111  
              Runnable _x = x;
2112  
              x = null;
2113  
              //debug("next " + structure(x));
2114  
              return _x;
2115  
            }
2116  
            
2117  
            public void remove() {
2118  
            }
2119  
          };
2120  
        }
2121  
      };
2122  
    }
2123  
    
2124  
    void add(Runnable r) {
2125  
      q.add(r);
2126  
    }
2127  
    
2128  
    void run() {
2129  
      for (Runnable r : master()) {
2130  
        try {
2131  
          r.run();
2132  
        } catch (Done e) {
2133  
          return; // break signal
2134  
        } catch (Throwable e) {
2135  
          e.printStackTrace();
2136  
        }
2137  
      }
2138  
    }
2139  
    
2140  
    void done() {
2141  
      add(new Runnable() {
2142  
        public void run() {
2143  
          throw new Done();
2144  
        }
2145  
      });
2146  
    }
2147  
  } // class Q
2148  
2149  
static void reportToChat(final String s, boolean silent) {
2150  
    if (s == null || s.length() == 0) return;
2151  
    if (!silent)
2152  
      print("reportToChat: " + quote(s));
2153  
    reportToChat_getChatThread().add(new Runnable() {
2154  
    public void run() { try {
2155  
        startChatServerIfNotUp();
2156  
        waitForChatServer();
2157  
        chatSend(s);
2158  
    } catch (Exception __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}});
2159  
   }
2160  
  
2161  
  static Q reportToChat_q;
2162  
  
2163  
  static Q reportToChat_getChatThread() {
2164  
    if (reportToChat_q == null)
2165  
      reportToChat_q = new Q("reportToChat", true);
2166  
    return reportToChat_q;
2167  
  }
2168  
  
2169  
  static void startChatServerIfNotUp() {
2170  
    if (portIsBound(9751)) {
2171  
      //print("Chat seems to be up.");
2172  
    } else {
2173  
      nohupJavax("1000867");
2174  
      print("Chat server should be coming up any minute now.");
2175  
    }
2176  
  }
2177  
  
2178  
  static void waitForChatServer() {
2179  
    if (!portIsBound(9751)) {
2180  
      //System.out.print("Waiting for chat server... ");
2181  
      do {
2182  
        sleep(1000);
2183  
      } while (!portIsBound(9751));
2184  
      //print("OK.");
2185  
    }
2186  
  }
2187  
2188  
  static boolean portIsBound(int port) {
2189  
    try {
2190  
      ServerSocket s = new ServerSocket(port);
2191  
      s.close();
2192  
      return false;
2193  
    } catch (IOException e) {
2194  
      return true;
2195  
    }
2196  
  }
2197  
  
2198  
  static class LineBuf {
2199  
    StringBuffer buf = new StringBuffer();
2200  
    
2201  
    void append(String s) {
2202  
      buf.append(s);
2203  
    }
2204  
    
2205  
    String nextLine() {
2206  
      int i = buf.indexOf("\n");
2207  
      if (i >= 0) {
2208  
        String s = buf.substring(0, i > 0 && buf.charAt(i-1) == '\r' ? i-1 : i);
2209  
        buf.delete(0, i+1);
2210  
        return s;
2211  
      }
2212  
      return null;
2213  
    }
2214  
  } // LineBuf
2215  
2216  
  static void sleep(long ms) {
2217  
    try {
2218  
      Thread.sleep(ms);
2219  
    } catch (Exception e) { throw new RuntimeException(e); }
2220  
  }
2221  
2222  
  !include #1000937 // chatSend
2223  
2224  
  static class TeeOutputStream extends OutputStream {
2225  
    
2226  
    protected OutputStream out, branch;
2227  
2228  
    public TeeOutputStream( OutputStream out, OutputStream branch ) {
2229  
      this.out = out;
2230  
      this.branch = branch;
2231  
    }
2232  
2233  
    @Override
2234  
    public synchronized void write(byte[] b) throws IOException {
2235  
      write(b, 0, b.length);
2236  
    }
2237  
2238  
    @Override
2239  
    public synchronized void write(byte[] b, int off, int len) throws IOException {
2240  
      //if (verbose) oldOut.println("Tee write " + new String(b, "UTF-8"));
2241  
      out.write(b, off, len);
2242  
      this.branch.write(b, off, len);
2243  
    }
2244  
2245  
    @Override
2246  
    public synchronized void write(int b) throws IOException {
2247  
      write(new byte[] {(byte) b});
2248  
    }
2249  
2250  
    /**
2251  
     * Flushes both streams.
2252  
     * @throws IOException if an I/O error occurs
2253  
     */
2254  
    @Override
2255  
    public void flush() throws IOException {
2256  
      out.flush();
2257  
      this.branch.flush();
2258  
    }
2259  
2260  
    /**
2261  
     * Closes both streams.
2262  
     * @throws IOException if an I/O error occurs
2263  
     */
2264  
    @Override
2265  
    public void close() throws IOException {
2266  
      out.close();
2267  
      this.branch.close();
2268  
    }
2269  
  }
2270  
  
2271  
  static boolean isChatServer(String[] args) {
2272  
    for (int i = 0; i < args.length; i++)
2273  
      if (isSnippetID(args[i]))
2274  
        return parseSnippetID(args[i]) == 1000867;
2275  
    return false;
2276  
  }
2277  
  
2278  
  static String getSnippetTitle(String id) {
2279  
    try {
2280  
      return loadPage(new URL("http://tinybrain.de:8080/tb-int/getfield.php?id=" + parseSnippetID(id) + "&field=title"));
2281  
    } catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }
2282  
  }
2283  
  
2284  
  static void listUserThreadsWithStackTraces() {
2285  
    print("");
2286  
    Map<Thread, StackTraceElement[]> threadMap = Thread.getAllStackTraces();
2287  
    int n = 0;
2288  
    for (Thread t : threadMap.keySet()) {
2289  
      ThreadGroup g = t.getThreadGroup();
2290  
      if (g != null && g.getName().equals("system")) continue;
2291  
      ++n;
2292  
      print(t);
2293  
      for (StackTraceElement e : threadMap.get(t)) {
2294  
        print("  " + e);
2295  
      }
2296  
      print("");
2297  
    }
2298  
    print(n + " user threads.");
2299  
  }
2300  
  
2301  
  static void killMyself() {
2302  
    print("Killing myself. (insert overall feeling here)");
2303  
    System.exit(0);
2304  
  }
2305  
  
2306  
  static void makeVMAndroid() {
2307  
    Android3 a = new Android3("This is a JavaX VM.");
2308  
    a.responder = new Responder() {
2309  
      S answer(S s, L<S> history) {
2310  
        return x28.answer(s);
2311  
      }
2312  
    };
2313  
    a.daemon = true;
2314  
    a.console = false;
2315  
    makeAndroid3(a);
2316  
  }
2317  
  
2318  
  static class Info {
2319  
    S programID;
2320  
    S[] programArgs;
2321  
    File transpiledSrc;
2322  
    Class mainClass;
2323  
  }
2324  
  
2325  
  static new Info info; // hmm...
2326  
  
2327  
  // injectable info
2328  
  
2329  
  static new L<PaA> injectable_programsInjected;
2330  
  static boolean injectable_on = true;
2331  
  static class PaA {
2332  
    S injectionID;
2333  
    S progID;
2334  
    S[] arguments;
2335  
    Class mainClass; // TODO: release eventually...
2336  
    volatile boolean mainDone;
2337  
    volatile Throwable exception;
2338  
    
2339  
    *(S *progID, S[] *arguments) {}
2340  
    *() {}
2341  
  }  
2342  
  
2343  
  static synchronized S answer(S s) {
2344  
    new Matches m;
2345  
    
2346  
    if (match3("kill!", s)) {
2347  
      killMyself();
2348  
      return "ok";
2349  
    }
2350  
    if (match3("What is your process ID?", s) || match3("what is your pid?", s))
2351  
      return getPID();
2352  
    if (match3("what is your program id?", s))
2353  
      return "#1001370";
2354  
    if (match3("what are your program arguments?", s))
2355  
      return structure(info.programArgs);
2356  
    if (match3("get fields of main class", s))
2357  
      return structure(listFields(info.mainClass));
2358  
    if (match3("get field * of main class", s, m))
2359  
      return structure(get(info.mainClass, m.m[0]));
2360  
    if (match3("invoke function * of main class", s, m))
2361  
      return structure(call(info.mainClass, m.m[0]));
2362  
    if (match3("set field * of main class to *", s, m)) {
2363  
      set(info.mainClass, m.m[0], unstructure(m.m[1]));
2364  
      return "ok";
2365  
    }
2366  
    if (match3("how much memory are you consuming", s))
2367  
      return "Java heap size: " + (Runtime.getRuntime().totalMemory()+1024*1024-1)/1024/1024 + " MB";
2368  
    if (match3("how much memory is used after GC?", s)) {
2369  
      System.gc();
2370  
      return "Java heap used: " + (Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory()+1024*1024-1)/1024/1024 + " MB";
2371  
    }
2372  
    if (match3("how much memory is used?", s))
2373  
      return "Java heap used: " + (Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory()+1024*1024-1)/1024/1024 + " MB";
2374  
      
2375  
    if (match3("please inject program *", s, m) || match3("please inject program * with arguments *", s, m)) {
2376  
      final S progID = formatSnippetID(unquote(m.m[0]));
2377  
      final S[] arguments = m.m.length > 1 ? toStringArray(unstructure(unquote(m.m[1]))) : new S[0];
2378  
      final PaA paa = new PaA(progID, arguments);
2379  
      paa.injectionID = randomID(8);
2380  
      injectable_programsInjected.add(paa);
2381  
  
2382  
      // better call JavaX for translation in a single thread.
2383  
      paa.mainClass = hotwire(progID);
2384  
  
2385  
      // program may run in its own thread.
2386  
      thread progID {
2387  
        try {
2388  
          callMain(paa.mainClass, arguments);
2389  
        } catch (Throwable e) {
2390  
          paa.exception = e;
2391  
          e.printStackTrace();
2392  
        } finally {
2393  
          paa.mainDone = true;
2394  
          synchronized(x28.class) {}
2395  
        }
2396  
      }
2397  
  
2398  
      ret format3("OK. Injection ID: *", paa.injectionID);
2399  
    }
2400  
    
2401  
    if (match3("get injection exception *", s, m)) {
2402  
      S injectionID = unquote(m.m[0]);
2403  
      PaA paa = findInjection(injectionID);
2404  
      if (paa == null)
2405  
        ret "Sorry. Injection not found";
2406  
      ret "OK: " + paa.exception == null ? "no exception" : getStackTrace(paa.exception);
2407  
    }
2408  
     
2409  
    if (match3("get injection * variable *", s, m)) {
2410  
      S injectionID = unquote(m.m[0]);
2411  
      S var = unquote(m.m[1]);
2412  
      PaA paa = findInjection(injectionID);
2413  
      if (paa == null)
2414  
        ret "Sorry. Injection not found";
2415  
      ret "OK: " + structure(getOpt(paa.mainClass, var));
2416  
    }
2417  
     
2418  
    if (match3("get injection result *", s, m)) {
2419  
      S injectionID = unquote(m.m[0]);
2420  
      PaA paa = findInjection(injectionID);
2421  
      if (paa == null)
2422  
        ret "Sorry. Injection not found";
2423  
      ret "OK: " + structure(getOpt(paa.mainClass, "result"));
2424  
    }
2425  
     
2426  
    if (match3("is injection's * main done", s, m)) {
2427  
      S injectionID = unquote(m.m[0]);
2428  
      PaA paa = findInjection(injectionID);
2429  
      if (paa == null)
2430  
        ret "Sorry. Injection not found";
2431  
      ret paa.mainDone ? "Yes." : "No.";
2432  
    }
2433  
    
2434  
    if (match3("which programs are you running (ids only)", s, m)) {
2435  
      new L<S> l;
2436  
      for (S progID : instances.keySet())
2437  
        if (getInstance(progID) != null)
2438  
          l.add(progID);
2439  
      return format3("these: *", structure(l));
2440  
    }
2441  
     
2442  
    return null;
2443  
  }
2444  
  
2445  
  static PaA findInjection(S injectionID) {
2446  
    for (PaA paa : injectable_programsInjected)
2447  
      if (eq(paa.injectionID, injectionID))
2448  
        ret paa;
2449  
    ret null;
2450  
  }
2451  
  
2452  
  !include #1001103 // makeAndroid / makeAndroidNoConsole
2453  
  !include #1001074 // readLine
2454  
  !include #1000891 // setOpt
2455  
  !include #1000619 // get
2456  
  !include #1001152 // getMainClass
2457  
  !include #1001076 // talkTo
2458  
  !include #1001235 // toStringArray
2459  
  
2460  
    static byte[] loadDataSnippetImpl(String snippetID) throws IOException {
2461  
    byte[] data;
2462  
    try {
2463  
      URL url = new URL("http://eyeocr.sourceforge.net/filestore/filestore.php?cmd=serve&file=blob_"
2464  
        + parseSnippetID(snippetID) + "&contentType=application/binary");
2465  
      System.err.println("Loading library: " + url);
2466  
      try {
2467  
        data = loadBinaryPage(url.openConnection());
2468  
      } catch (IOException e) {
2469  
        url = new URL("http://data.tinybrain.de/blobs/"
2470  
          + parseSnippetID(snippetID));
2471  
        System.err.println("Loading library: " + url);
2472  
        data = loadBinaryPage(url.openConnection());
2473  
      }
2474  
      System.err.println("Bytes loaded: " + data.length);
2475  
    } catch (FileNotFoundException e) {
2476  
      throw new IOException("Binary snippet #" + snippetID + " not found or not public");
2477  
    }
2478  
    return data;
2479  
  }
2480  
}

Author comment

Began life as a copy of #1001148

download  show line numbers  debug dex  old transpilations   

Travelled to 14 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1001370
Snippet name: x28.java (JavaX)
Eternal ID of this version: #1001370/1
Text MD5: a1d923d854cb6f3483a443a52efa15d2
Transpilation MD5: 89bf118a6b2409cda2aacee66ac19eb3
Author: stefan
Category: javax
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2015-10-16 20:11:08
Source code size: 86035 bytes / 2480 lines
Pitched / IR pitched: No / Yes
Views / Downloads: 878 / 1168
Referenced in: [show references]