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

2514
LINES

< > BotCompany Repo | #1001600 // x29.java (JavaX)

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

Libraryless. Click here for Pure Java version (4408L/31K/97K).

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

Author comment

Began life as a copy of #1001370

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: #1001600
Snippet name: x29.java (JavaX)
Eternal ID of this version: #1001600/1
Text MD5: fa546b00b9f4888b919151fc59035cee
Transpilation MD5: 1d0fdaa740a0663e18ab8cc4e0946cd5
Author: stefan
Category: javax
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2015-10-29 18:09:58
Source code size: 87112 bytes / 2514 lines
Pitched / IR pitched: No / Yes
Views / Downloads: 625 / 972
Referenced in: [show references]