aboutsummaryrefslogtreecommitdiff
path: root/nailgun_launcher/NailgunLauncher.java
blob: a7d89e2243727251346cfcaf40a94d017d98fc78 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package cbt;
import java.io.*;
import java.lang.reflect.*;
import java.net.*;
import java.security.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import static cbt.Stage0Lib.*;

/**
 * This launcher allows to start the JVM without loading anything else permanently into its
 * classpath except for the launcher itself. That's why it is written in Java without
 * dependencies outside the JDK.
 */
public class NailgunLauncher{
  public static String SCALA_VERSION = "2.11.8";
  public static String SCALA_XML_VERSION = "1.0.5";
  public static String ZINC_VERSION = "0.3.9";

  public static String CBT_HOME = System.getenv("CBT_HOME");
  public static String NAILGUN = System.getenv("NAILGUN");
  public static String TARGET = System.getenv("TARGET");
  public static String STAGE1 = CBT_HOME + "/stage1/";
  public static String MAVEN_CACHE = CBT_HOME + "/cache/maven";
  public static String MAVEN_URL = "https://repo1.maven.org/maven2";

  /**
   * Persistent cache for caching classloaders for the JVM life time. Can be used as needed by user
   * code to improve startup time.
   */
  public static ConcurrentHashMap<String, Object> classLoaderCacheKeys = new ConcurrentHashMap<String,Object>();
  public static ConcurrentHashMap<Object, ClassLoader> classLoaderCacheValues = new ConcurrentHashMap<Object,ClassLoader>();

  public static SecurityManager defaultSecurityManager = System.getSecurityManager();

  public static long lastSuccessfullCompile = 0;
  static ClassLoader stage1classLoader = null;
  public static ClassLoader stage2classLoader = null;

  public static void main(String[] args) throws ClassNotFoundException,
                                                NoSuchMethodException,
                                                IllegalAccessException,
                                                InvocationTargetException,
                                                MalformedURLException,
                                                IOException,
                                                NoSuchAlgorithmException {
    long now = System.currentTimeMillis();
    //System.err.println("ClassLoader: "+stage1classLoader);
    //System.err.println("lastSuccessfullCompile: "+lastSuccessfullCompile);
    //System.err.println("now: "+now);

    _assert(CBT_HOME != null, CBT_HOME);
    _assert(NAILGUN != null, NAILGUN);
    _assert(TARGET != null, TARGET);
    _assert(STAGE1 != null, STAGE1);

    if(args[0].equals("check-alive")){
      System.exit(33);
      return;
    }

    List<File> stage1SourceFiles = new ArrayList<File>();
    for( File f: new File(STAGE1).listFiles() ){
      if( f.isFile() && f.toString().endsWith(".scala") ){
        stage1SourceFiles.add(f);
      }
    }

    Boolean changed = lastSuccessfullCompile == 0;
    for( File file: stage1SourceFiles ){
      if( file.lastModified() > lastSuccessfullCompile ){
        changed = true;
        //System.err.println("File change: "+file.lastModified());
        break;
      }
    }

    if(changed){
      EarlyDependencies earlyDeps = new EarlyDependencies();
      int exitCode = zinc(earlyDeps, stage1SourceFiles);
      if( exitCode == 0 ){
        lastSuccessfullCompile = now;
      } else {
        System.exit( exitCode );
      }

      ClassLoader nailgunClassLoader;
      if( classLoaderCacheKeys.containsKey( NAILGUN+TARGET ) ){
        nailgunClassLoader = cacheGet( NAILGUN+TARGET );
      } else {
        nailgunClassLoader = cachePut( classLoader(NAILGUN+TARGET, earlyDeps.stage1), NAILGUN+TARGET ); // FIXME: key is wrong here, should be full CP
      }

      stage1classLoader = classLoader(STAGE1+TARGET, nailgunClassLoader);
      stage2classLoader = null;
    }

    try{
      Integer exitCode =
        (Integer) stage1classLoader
          .loadClass("cbt.Stage1")
          .getMethod("run", String[].class, ClassLoader.class, Boolean.class)
          .invoke( null, (Object) args, stage1classLoader, changed);
      System.exit(exitCode);
    }catch(Exception e){
      System.err.println(stage1classLoader);
      throw e;
    }
  }
}