mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 11:04:34 +02:00
8048594: The sjavac client/server protocol should be hidden behind an interface
Reviewed-by: jfranck
This commit is contained in:
parent
ce0935812b
commit
8baafcf7ef
17 changed files with 697 additions and 459 deletions
|
@ -36,6 +36,7 @@ import java.util.Map;
|
|||
import java.util.Properties;
|
||||
|
||||
import com.sun.tools.sjavac.options.Options;
|
||||
import com.sun.tools.sjavac.server.JavacService;
|
||||
|
||||
/**
|
||||
* The clean properties transform should not be necessary.
|
||||
|
@ -56,7 +57,8 @@ public class CleanProperties implements Transformer
|
|||
// Any extra information is ignored for clean properties.
|
||||
}
|
||||
|
||||
public boolean transform(Map<String,Set<URI>> pkgSrcs,
|
||||
public boolean transform(JavacService javacService,
|
||||
Map<String,Set<URI>> pkgSrcs,
|
||||
Set<URI> visibleSrcs,
|
||||
Map<URI,Set<String>> visibleClasses,
|
||||
Map<String,Set<String>> oldPackageDependencies,
|
||||
|
|
|
@ -25,15 +25,18 @@
|
|||
|
||||
package com.sun.tools.sjavac;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sun.tools.sjavac.options.Options;
|
||||
import com.sun.tools.sjavac.server.JavacServer;
|
||||
import com.sun.tools.sjavac.server.CompilationResult;
|
||||
import com.sun.tools.sjavac.server.JavacService;
|
||||
import com.sun.tools.sjavac.server.SysInfo;
|
||||
|
||||
/**
|
||||
|
@ -64,9 +67,10 @@ public class CompileJavaPackages implements Transformer {
|
|||
args = a;
|
||||
}
|
||||
|
||||
public boolean transform(Map<String,Set<URI>> pkgSrcs,
|
||||
Set<URI> visibleSources,
|
||||
Map<URI,Set<String>> visibleClasses,
|
||||
public boolean transform(final JavacService javacService,
|
||||
Map<String,Set<URI>> pkgSrcs,
|
||||
final Set<URI> visibleSources,
|
||||
final Map<URI,Set<String>> visibleClasses,
|
||||
Map<String,Set<String>> oldPackageDependents,
|
||||
URI destRoot,
|
||||
final Map<String,Set<URI>> packageArtifacts,
|
||||
|
@ -75,24 +79,25 @@ public class CompileJavaPackages implements Transformer {
|
|||
int debugLevel,
|
||||
boolean incremental,
|
||||
int numCores,
|
||||
PrintStream out,
|
||||
PrintStream err)
|
||||
final PrintStream out,
|
||||
final PrintStream err)
|
||||
{
|
||||
boolean rc = true;
|
||||
boolean concurrentCompiles = true;
|
||||
|
||||
// Fetch the id.
|
||||
String id = Util.extractStringOption("id", args.getServerConf());
|
||||
if (id == null || id.equals("")) {
|
||||
String idOpt = Util.extractStringOption("id", args.getServerConf());
|
||||
if (idOpt == null || idOpt.equals("")) {
|
||||
// No explicit id set. Create a random id so that the requests can be
|
||||
// grouped properly in the server.
|
||||
id = "id"+(((new Random()).nextLong())&Long.MAX_VALUE);
|
||||
idOpt = "id"+(((new Random()).nextLong())&Long.MAX_VALUE);
|
||||
}
|
||||
final String id = idOpt;
|
||||
// Only keep portfile and sjavac settings..
|
||||
String psServerSettings = Util.cleanSubOptions(Util.set("portfile","sjavac","background","keepalive"), args.getServerConf());
|
||||
|
||||
// Get maximum heap size from the server!
|
||||
SysInfo sysinfo = JavacServer.connectGetSysInfo(psServerSettings, out, err);
|
||||
SysInfo sysinfo = javacService.getSysInfo();
|
||||
if (sysinfo.numCores == -1) {
|
||||
Log.error("Could not query server for sysinfo!");
|
||||
return false;
|
||||
|
@ -201,13 +206,10 @@ public class CompileJavaPackages implements Transformer {
|
|||
}
|
||||
|
||||
// The return values for each chunked compile.
|
||||
final int[] rn = new int[numCompiles];
|
||||
final CompilationResult[] rn = new CompilationResult[numCompiles];
|
||||
// The requets, might or might not run as a background thread.
|
||||
final Thread[] requests = new Thread[numCompiles];
|
||||
|
||||
final Set<URI> fvisible_sources = visibleSources;
|
||||
final Map<URI,Set<String>> fvisible_classes = visibleClasses;
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
for (int i=0; i<numCompiles; ++i) {
|
||||
|
@ -215,23 +217,20 @@ public class CompileJavaPackages implements Transformer {
|
|||
final CompileChunk cc = compileChunks[i];
|
||||
|
||||
// Pass the num_cores and the id (appended with the chunk number) to the server.
|
||||
final String cleanedServerSettings = psServerSettings+",poolsize="+numCores+",id="+id+"-"+ii;
|
||||
final PrintStream fout = out;
|
||||
final PrintStream ferr = err;
|
||||
final String cleanedServerSettings = psServerSettings+",poolsize="+numCores+",id="+id+"-"+i;
|
||||
|
||||
requests[ii] = new Thread() {
|
||||
requests[i] = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
rn[ii] = JavacServer.useServer(cleanedServerSettings,
|
||||
rn[ii] = javacService.compile("n/a",
|
||||
id + "-" + ii,
|
||||
args.prepJavacArgs(),
|
||||
Collections.<File>emptyList(),
|
||||
cc.srcs,
|
||||
fvisible_sources,
|
||||
fvisible_classes,
|
||||
packageArtifacts,
|
||||
packageDependencies,
|
||||
packagePubapis,
|
||||
null,
|
||||
fout, ferr);
|
||||
visibleSources);
|
||||
packageArtifacts.putAll(rn[ii].packageArtifacts);
|
||||
packageDependencies.putAll(rn[ii].packageDependencies);
|
||||
packagePubapis.putAll(rn[ii].packagePubapis);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -253,7 +252,7 @@ public class CompileJavaPackages implements Transformer {
|
|||
else {
|
||||
requests[ii].run();
|
||||
// If there was an error, then stop early when running single threaded.
|
||||
if (rn[i] != 0) {
|
||||
if (rn[i].returnCode != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -269,7 +268,7 @@ public class CompileJavaPackages implements Transformer {
|
|||
// Check the return values.
|
||||
for (int i=0; i<numCompiles; ++i) {
|
||||
if (compileChunks[i].srcs.size() > 0) {
|
||||
if (rn[i] != 0) {
|
||||
if (rn[i].returnCode != 0) {
|
||||
rc = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import java.util.HashSet;
|
|||
import java.util.Map;
|
||||
|
||||
import com.sun.tools.sjavac.options.Options;
|
||||
import com.sun.tools.sjavac.server.JavacService;
|
||||
|
||||
/**
|
||||
* Compile properties transform a properties file into a Java source file.
|
||||
|
@ -63,7 +64,8 @@ public class CompileProperties implements Transformer
|
|||
public void setExtra(Options a) {
|
||||
}
|
||||
|
||||
public boolean transform(Map<String,Set<URI>> pkgSrcs,
|
||||
public boolean transform(JavacService javacService,
|
||||
Map<String,Set<URI>> pkgSrcs,
|
||||
Set<URI> visibleSrcs,
|
||||
Map<URI,Set<String>> visibleClasses,
|
||||
Map<String,Set<String>> oldPackageDependents,
|
||||
|
|
|
@ -32,6 +32,7 @@ import java.util.HashSet;
|
|||
import java.util.Map;
|
||||
|
||||
import com.sun.tools.sjavac.options.Options;
|
||||
import com.sun.tools.sjavac.server.JavacService;
|
||||
|
||||
/**
|
||||
* The copy file transform simply copies a matching file from -src to -d .
|
||||
|
@ -50,7 +51,8 @@ public class CopyFile implements Transformer {
|
|||
public void setExtra(Options a) {
|
||||
}
|
||||
|
||||
public boolean transform(Map<String,Set<URI>> pkgSrcs,
|
||||
public boolean transform(JavacService javacService,
|
||||
Map<String,Set<URI>> pkgSrcs,
|
||||
Set<URI> visibleSrcs,
|
||||
Map<URI,Set<String>> visibleClasses,
|
||||
Map<String,Set<String>> oldPackageDependents,
|
||||
|
|
|
@ -40,6 +40,7 @@ import java.util.*;
|
|||
|
||||
import com.sun.tools.sjavac.options.Options;
|
||||
import com.sun.tools.sjavac.options.SourceLocation;
|
||||
import com.sun.tools.sjavac.server.JavacService;
|
||||
|
||||
/**
|
||||
* The javac state class maintains the previous (prev) and the current (now)
|
||||
|
@ -625,7 +626,7 @@ public class JavacState
|
|||
sr.put(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
perform(binDir, sr);
|
||||
perform(null, binDir, sr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -641,20 +642,21 @@ public class JavacState
|
|||
|
||||
sr.put(e.getKey(), e.getValue());
|
||||
}
|
||||
perform(gensrcDir, sr);
|
||||
perform(null, gensrcDir, sr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile all the java sources. Return true, if it needs to be called again!
|
||||
*/
|
||||
public boolean performJavaCompilations(Options args,
|
||||
public boolean performJavaCompilations(JavacService javacService,
|
||||
Options args,
|
||||
Set<String> recentlyCompiled,
|
||||
boolean[] rcValue) {
|
||||
Map<String,Transformer> suffixRules = new HashMap<>();
|
||||
suffixRules.put(".java", compileJavaPackages);
|
||||
compileJavaPackages.setExtra(args);
|
||||
|
||||
rcValue[0] = perform(binDir, suffixRules);
|
||||
rcValue[0] = perform(javacService, binDir, suffixRules);
|
||||
recentlyCompiled.addAll(taintedPackages());
|
||||
clearTaintedPackages();
|
||||
boolean again = !packagesWithChangedPublicApis.isEmpty();
|
||||
|
@ -684,7 +686,9 @@ public class JavacState
|
|||
* For all packages, find all sources belonging to the package, group the sources
|
||||
* based on their transformers and apply the transformers on each source code group.
|
||||
*/
|
||||
private boolean perform(File outputDir, Map<String,Transformer> suffixRules)
|
||||
private boolean perform(JavacService javacService,
|
||||
File outputDir,
|
||||
Map<String,Transformer> suffixRules)
|
||||
{
|
||||
boolean rc = true;
|
||||
// Group sources based on transforms. A source file can only belong to a single transform.
|
||||
|
@ -709,7 +713,8 @@ public class JavacState
|
|||
Map<String,String> packagePublicApis =
|
||||
Collections.synchronizedMap(new HashMap<String, String>());
|
||||
|
||||
boolean r = t.transform(srcs,
|
||||
boolean r = t.transform(javacService,
|
||||
srcs,
|
||||
visibleSrcs,
|
||||
visibleClasses,
|
||||
prev.dependents(),
|
||||
|
|
|
@ -33,7 +33,9 @@ import java.nio.file.Files;
|
|||
|
||||
import com.sun.tools.sjavac.options.Options;
|
||||
import com.sun.tools.sjavac.options.SourceLocation;
|
||||
import com.sun.tools.sjavac.server.JavacService;
|
||||
import com.sun.tools.sjavac.server.JavacServer;
|
||||
import com.sun.tools.sjavac.server.JavacServiceClient;
|
||||
|
||||
/**
|
||||
* The main class of the smart javac wrapper tool.
|
||||
|
@ -339,7 +341,12 @@ public class Main {
|
|||
do {
|
||||
// Clean out artifacts in tainted packages.
|
||||
javac_state.deleteClassArtifactsInTaintedPackages();
|
||||
again = javac_state.performJavaCompilations(options, recently_compiled, rc);
|
||||
// Create a JavacService to delegate the actual compilation to.
|
||||
// Currently sjavac always connects to a server through a socket
|
||||
// regardless if sjavac runs as a background service or not.
|
||||
// This will most likely change in the future.
|
||||
JavacService javacService = new JavacServiceClient(options.getServerConf());
|
||||
again = javac_state.performJavaCompilations(javacService, options, recently_compiled, rc);
|
||||
if (!rc[0]) break;
|
||||
} while (again);
|
||||
// Only update the state if the compile went well.
|
||||
|
|
|
@ -31,6 +31,7 @@ import java.util.Set;
|
|||
import java.util.Map;
|
||||
|
||||
import com.sun.tools.sjavac.options.Options;
|
||||
import com.sun.tools.sjavac.server.JavacService;
|
||||
|
||||
/**
|
||||
* The transform interface is used to transform content inside a package, from one form to another.
|
||||
|
@ -82,7 +83,8 @@ public interface Transformer
|
|||
* If num_cores is set to a non-zero value. The transform should attempt to use no more than these
|
||||
* number of threads for heavy work.
|
||||
*/
|
||||
boolean transform(Map<String,Set<URI>> pkgSrcs,
|
||||
boolean transform(JavacService javacService,
|
||||
Map<String,Set<URI>> pkgSrcs,
|
||||
Set<URI> visibleSources,
|
||||
Map<URI,Set<String>> visibleClasses,
|
||||
Map<String,Set<String>> oldPackageDependencies,
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
package com.sun.tools.sjavac;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
@ -67,17 +69,32 @@ public class Util {
|
|||
}
|
||||
|
||||
public static String extractStringOption(String opName, String s) {
|
||||
return extractStringOption(opName, s, null);
|
||||
}
|
||||
|
||||
public static String extractStringOption(String opName, String s, String deflt) {
|
||||
int p = s.indexOf(opName+"=");
|
||||
if (p == -1) return null;
|
||||
if (p == -1) return deflt;
|
||||
p+=opName.length()+1;
|
||||
int pe = s.indexOf(',', p);
|
||||
if (pe == -1) pe = s.length();
|
||||
return s.substring(p, pe);
|
||||
}
|
||||
|
||||
public static boolean extractBooleanOption(String opName, String s, boolean deflt) {
|
||||
String str = extractStringOption(opName, s);
|
||||
return "true".equals(str) ? true
|
||||
: "false".equals(str) ? false
|
||||
: deflt;
|
||||
}
|
||||
|
||||
public static int extractIntOption(String opName, String s) {
|
||||
return extractIntOption(opName, s, 0);
|
||||
}
|
||||
|
||||
public static int extractIntOption(String opName, String s, int deflt) {
|
||||
int p = s.indexOf(opName+"=");
|
||||
if (p == -1) return 0;
|
||||
if (p == -1) return deflt;
|
||||
p+=opName.length()+1;
|
||||
int pe = s.indexOf(',', p);
|
||||
if (pe == -1) pe = s.length();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -29,8 +29,6 @@ import java.util.StringTokenizer;
|
|||
import com.sun.tools.javac.main.JavaCompiler;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import com.sun.tools.javac.code.Symbol.ClassSymbol;
|
||||
import com.sun.tools.sjavac.server.CompilerThread;
|
||||
import java.io.File;
|
||||
|
||||
/** Subclass to Resolve that overrides collect.
|
||||
*
|
||||
|
@ -44,16 +42,16 @@ public class JavaCompilerWithDeps extends JavaCompiler {
|
|||
/** The dependency database
|
||||
*/
|
||||
protected Dependencies deps;
|
||||
protected CompilerThread compilerThread;
|
||||
protected JavacServiceImpl javacService;
|
||||
|
||||
public JavaCompilerWithDeps(Context context, CompilerThread t) {
|
||||
public JavaCompilerWithDeps(Context context, JavacServiceImpl jsi) {
|
||||
super(context);
|
||||
deps = Dependencies.instance(context);
|
||||
compilerThread = t;
|
||||
javacService = jsi;
|
||||
needRootClasses = true;
|
||||
}
|
||||
|
||||
public static void preRegister(Context context, final CompilerThread t) {
|
||||
public static void preRegister(Context context, final JavacServiceImpl t) {
|
||||
context.put(compilerKey, new Context.Factory<JavaCompiler>() {
|
||||
public JavaCompiler make(Context c) {
|
||||
JavaCompiler instance = new JavaCompilerWithDeps(c, t);
|
||||
|
@ -99,7 +97,7 @@ public class JavaCompilerWithDeps extends JavaCompiler {
|
|||
|
||||
// Now check if the truncated uri ends with the path. (It does not == failure!)
|
||||
if (path.length() > 0 && !path.equals("/unnamed package/") && !pp.endsWith(path)) {
|
||||
compilerThread.logError("Error: The source file "+sym.sourcefile.getName()+
|
||||
javacService.logError("Error: The source file "+sym.sourcefile.getName()+
|
||||
" is located in the wrong package directory, because it contains the class "+
|
||||
sym.getQualifiedName());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
package com.sun.tools.sjavac.comp;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.tools.JavaCompiler.CompilationTask;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
|
||||
import com.sun.tools.javac.api.JavacTaskImpl;
|
||||
import com.sun.tools.javac.api.JavacTool;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import com.sun.tools.javac.util.ListBuffer;
|
||||
import com.sun.tools.sjavac.Util;
|
||||
import com.sun.tools.sjavac.server.CompilationResult;
|
||||
import com.sun.tools.sjavac.server.JavacServer;
|
||||
import com.sun.tools.sjavac.server.JavacService;
|
||||
import com.sun.tools.sjavac.server.SysInfo;
|
||||
|
||||
public class JavacServiceImpl implements JavacService {
|
||||
|
||||
JavacServer javacServer;
|
||||
private ThreadLocal<Boolean> forcedExit;
|
||||
|
||||
public JavacServiceImpl(JavacServer javacServer) {
|
||||
this.javacServer = javacServer;
|
||||
|
||||
}
|
||||
|
||||
public void logError(String msg) {
|
||||
// stderr.println(msg);
|
||||
forcedExit.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysInfo getSysInfo() {
|
||||
return new SysInfo(Runtime.getRuntime().availableProcessors(),
|
||||
Runtime.getRuntime().maxMemory());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompilationResult compile(String protocolId,
|
||||
String invocationId,
|
||||
String[] args,
|
||||
List<File> explicitSources,
|
||||
Set<URI> sourcesToCompile,
|
||||
Set<URI> visibleSources) {
|
||||
|
||||
JavacTool compiler = JavacTool.create();
|
||||
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
|
||||
SmartFileManager smartFileManager = new SmartFileManager(fileManager);
|
||||
Context context = new Context();
|
||||
ResolveWithDeps.preRegister(context);
|
||||
AttrWithDeps.preRegister(context);
|
||||
JavaCompilerWithDeps.preRegister(context, this);
|
||||
|
||||
// Now setup the actual compilation....
|
||||
CompilationResult compilationResult = new CompilationResult(0);
|
||||
|
||||
// First deal with explicit source files on cmdline and in at file.
|
||||
ListBuffer<JavaFileObject> compilationUnits = new ListBuffer<>();
|
||||
for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(explicitSources)) {
|
||||
compilationUnits.append(i);
|
||||
}
|
||||
// Now deal with sources supplied as source_to_compile.
|
||||
ListBuffer<File> sourcesToCompileFiles = new ListBuffer<>();
|
||||
for (URI u : sourcesToCompile) {
|
||||
sourcesToCompileFiles.append(new File(u));
|
||||
}
|
||||
for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(sourcesToCompileFiles)) {
|
||||
compilationUnits.append(i);
|
||||
}
|
||||
// Log the options to be used.
|
||||
StringBuilder options = new StringBuilder();
|
||||
for (String s : args) {
|
||||
options.append(">").append(s).append("< ");
|
||||
}
|
||||
javacServer.log(protocolId+" <"+invocationId+"> options "+options.toString());
|
||||
|
||||
forcedExit.set(false);
|
||||
// Create a new logger.
|
||||
StringWriter stdoutLog = new StringWriter();
|
||||
StringWriter stderrLog = new StringWriter();
|
||||
PrintWriter stdout = new PrintWriter(stdoutLog);
|
||||
PrintWriter stderr = new PrintWriter(stderrLog);
|
||||
com.sun.tools.javac.main.Main.Result rc = com.sun.tools.javac.main.Main.Result.OK;
|
||||
try {
|
||||
if (compilationUnits.size() > 0) {
|
||||
smartFileManager.setVisibleSources(visibleSources);
|
||||
smartFileManager.cleanArtifacts();
|
||||
smartFileManager.setLog(stdout);
|
||||
|
||||
|
||||
// Do the compilation!
|
||||
CompilationTask task = compiler.getTask(stderr, smartFileManager, null, Arrays.asList(args), null, compilationUnits, context);
|
||||
rc = ((JavacTaskImpl) task).doCall();
|
||||
smartFileManager.flush();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
stderr.println(e.getMessage());
|
||||
forcedExit.set(true);
|
||||
}
|
||||
|
||||
compilationResult.packageArtifacts = smartFileManager.getPackageArtifacts();
|
||||
|
||||
Dependencies deps = Dependencies.instance(context);
|
||||
compilationResult.packageDependencies = deps.getDependencies();
|
||||
compilationResult.packagePubapis = deps.getPubapis();
|
||||
|
||||
compilationResult.stdout = stdoutLog.toString();
|
||||
compilationResult.stderr = stderrLog.toString();
|
||||
compilationResult.returnCode = rc.exitCode == 0 && forcedExit.get() ? -1 : rc.exitCode;
|
||||
|
||||
return compilationResult;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package com.sun.tools.sjavac.server;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class CompilationResult {
|
||||
|
||||
// Return code constants
|
||||
public final static int ERROR_BUT_TRY_AGAIN = -4712;
|
||||
public final static int ERROR_FATAL = -1;
|
||||
|
||||
public int returnCode;
|
||||
public Map<String, Set<URI>> packageArtifacts = new HashMap<>();
|
||||
public Map<String, Set<String>> packageDependencies = new HashMap<>();
|
||||
public Map<String, String> packagePubapis = new HashMap<>();
|
||||
public SysInfo sysinfo;
|
||||
public String stdout;
|
||||
public String stderr;
|
||||
|
||||
public CompilationResult(int returnCode) {
|
||||
this.returnCode = returnCode;
|
||||
this.sysinfo = new SysInfo(-1, -1);
|
||||
}
|
||||
|
||||
public void setReturnCode(int returnCode) {
|
||||
this.returnCode = returnCode;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -31,6 +31,8 @@ import java.util.concurrent.Semaphore;
|
|||
import java.util.Stack;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import com.sun.tools.sjavac.comp.JavacServiceImpl;
|
||||
|
||||
/** The compiler pool maintains compiler threads.
|
||||
*
|
||||
* <p><b>This is NOT part of any supported API.
|
||||
|
@ -147,7 +149,7 @@ public class CompilerPool {
|
|||
public CompilerThread grabCompilerThread() throws InterruptedException {
|
||||
available.acquire();
|
||||
if (compilers.empty()) {
|
||||
return new CompilerThread(this);
|
||||
return new CompilerThread(this, new JavacServiceImpl(javacServer));
|
||||
}
|
||||
return compilers.pop();
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ import com.sun.tools.javac.util.StringUtils;
|
|||
import com.sun.tools.sjavac.comp.AttrWithDeps;
|
||||
import com.sun.tools.sjavac.comp.Dependencies;
|
||||
import com.sun.tools.sjavac.comp.JavaCompilerWithDeps;
|
||||
import com.sun.tools.sjavac.comp.JavacServiceImpl;
|
||||
import com.sun.tools.sjavac.comp.ResolveWithDeps;
|
||||
import com.sun.tools.sjavac.comp.SmartFileManager;
|
||||
|
||||
|
@ -71,6 +72,7 @@ import com.sun.tools.sjavac.comp.SmartFileManager;
|
|||
public class CompilerThread implements Runnable {
|
||||
private JavacServer javacServer;
|
||||
private CompilerPool compilerPool;
|
||||
private JavacServiceImpl javacServiceImpl;
|
||||
private List<Future<?>> subTasks;
|
||||
|
||||
// Communicating over this socket.
|
||||
|
@ -85,9 +87,10 @@ public class CompilerThread implements Runnable {
|
|||
// If true, then this thread is serving a request.
|
||||
private boolean inUse = false;
|
||||
|
||||
CompilerThread(CompilerPool cp) {
|
||||
CompilerThread(CompilerPool cp, JavacServiceImpl javacServiceImpl) {
|
||||
compilerPool = cp;
|
||||
javacServer = cp.getJavacServer();
|
||||
this.javacServiceImpl = javacServiceImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,7 +134,7 @@ public class CompilerThread implements Runnable {
|
|||
context = new Context();
|
||||
ResolveWithDeps.preRegister(context);
|
||||
AttrWithDeps.preRegister(context);
|
||||
JavaCompilerWithDeps.preRegister(context, this);
|
||||
JavaCompilerWithDeps.preRegister(context, javacServiceImpl);
|
||||
subTasks = new ArrayList<>();
|
||||
}
|
||||
|
||||
|
|
|
@ -24,30 +24,22 @@
|
|||
*/
|
||||
package com.sun.tools.sjavac.server;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.net.URI;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
import com.sun.tools.sjavac.Util;
|
||||
import com.sun.tools.sjavac.ProblemException;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* The JavacServer class contains methods both to setup a server that responds to requests and methods to connect to this server.
|
||||
|
@ -73,8 +65,6 @@ public class JavacServer {
|
|||
// Though usually only one javac server is started by a client.
|
||||
private static Map<String, PortFile> allPortFiles;
|
||||
private static Map<String, Long> maxServerMemory;
|
||||
final static int ERROR_FATAL = -1;
|
||||
final static int ERROR_BUT_TRY_AGAIN = -4712;
|
||||
final static String PROTOCOL_COOKIE_VERSION = "----THE-COOKIE-V2----";
|
||||
final static String PROTOCOL_CWD = "----THE-CWD----";
|
||||
final static String PROTOCOL_ID = "----THE-ID----";
|
||||
|
@ -99,7 +89,7 @@ public class JavacServer {
|
|||
/**
|
||||
* Acquire the port file. Synchronized since several threads inside an smart javac wrapper client acquires the same port file at the same time.
|
||||
*/
|
||||
private static synchronized PortFile getPortFile(String filename) throws FileNotFoundException {
|
||||
public static synchronized PortFile getPortFile(String filename) throws FileNotFoundException {
|
||||
if (allPortFiles == null) {
|
||||
allPortFiles = new HashMap<>();
|
||||
}
|
||||
|
@ -179,17 +169,12 @@ public class JavacServer {
|
|||
// and stderr are redirected already.
|
||||
// The pool size is a limit the number of concurrent compiler threads used.
|
||||
// The server might use less than these to avoid memory problems.
|
||||
int poolsize = Util.extractIntOption("poolsize", settings);
|
||||
if (poolsize <= 0) {
|
||||
// If not set, default to the number of cores.
|
||||
poolsize = Runtime.getRuntime().availableProcessors();
|
||||
}
|
||||
int defaultPoolSize = Runtime.getRuntime().availableProcessors();
|
||||
int poolsize = Util.extractIntOption("poolsize", settings, defaultPoolSize);
|
||||
|
||||
// How many seconds of inactivity will the server accept before quitting?
|
||||
int keepalive = Util.extractIntOption("keepalive", settings);
|
||||
if (keepalive <= 0) {
|
||||
keepalive = 120;
|
||||
}
|
||||
int keepalive = Util.extractIntOption("keepalive", settings, 120);
|
||||
|
||||
// The port file is locked and the server port and cookie is written into it.
|
||||
PortFile portFile = getPortFile(portfile);
|
||||
JavacServer s;
|
||||
|
@ -219,134 +204,6 @@ public class JavacServer {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a compilation request to a javac server.
|
||||
*
|
||||
* @param args are the command line args to javac and is allowed to contain source files, @file and other command line options to javac.
|
||||
*
|
||||
* The generated classes, h files and other artifacts from the javac invocation are stored by the javac server to disk.
|
||||
*
|
||||
* @param sources_to_compile The sources to compile.
|
||||
*
|
||||
* @param visibleSources If visible sources has a non zero size, then visible_sources are the only files in the file system that the javac server can see!
|
||||
* (Sources to compile are always visible.) The visible sources are those supplied by the (filtered) -sourcepath
|
||||
*
|
||||
* @param visibleClasses If visible classes for a specific root/jar has a non zero size, then visible_classes are the only class files that the javac server
|
||||
* can see, in that root/jar. It maps from a classpath root or a jar file to the set of visible classes for that root/jar.
|
||||
*
|
||||
* The server return meta data about the build in the following parameters.
|
||||
* @param package_artifacts, map from package name to set of created artifacts for that package.
|
||||
* @param package_dependencies, map from package name to set of packages that it depends upon.
|
||||
* @param package_pubapis, map from package name to unique string identifying its pub api.
|
||||
*/
|
||||
public static int useServer(String settings, String[] args,
|
||||
Set<URI> sourcesToCompile,
|
||||
Set<URI> visibleSources,
|
||||
Map<URI, Set<String>> visibleClasses,
|
||||
Map<String, Set<URI>> packageArtifacts,
|
||||
Map<String, Set<String>> packageDependencies,
|
||||
Map<String, String> packagePubapis,
|
||||
SysInfo sysinfo,
|
||||
PrintStream out,
|
||||
PrintStream err) {
|
||||
try {
|
||||
// The id can perhaps be used in the future by the javac server to reuse the
|
||||
// JavaCompiler instance for several compiles using the same id.
|
||||
String id = Util.extractStringOption("id", settings);
|
||||
String portfile = Util.extractStringOption("portfile", settings);
|
||||
String logfile = Util.extractStringOption("logfile", settings);
|
||||
String stdouterrfile = Util.extractStringOption("stdouterrfile", settings);
|
||||
String background = Util.extractStringOption("background", settings);
|
||||
if (background == null || !background.equals("false")) {
|
||||
background = "true";
|
||||
}
|
||||
// The sjavac option specifies how the server part of sjavac is spawned.
|
||||
// If you have the experimental sjavac in your path, you are done. If not, you have
|
||||
// to point to a com.sun.tools.sjavac.Main that supports --startserver
|
||||
// for example by setting: sjavac=java%20-jar%20...javac.jar%com.sun.tools.sjavac.Main
|
||||
String sjavac = Util.extractStringOption("sjavac", settings);
|
||||
int poolsize = Util.extractIntOption("poolsize", settings);
|
||||
int keepalive = Util.extractIntOption("keepalive", settings);
|
||||
|
||||
if (keepalive <= 0) {
|
||||
// Default keepalive for server is 120 seconds.
|
||||
// I.e. it will accept 120 seconds of inactivity before quitting.
|
||||
keepalive = 120;
|
||||
}
|
||||
if (portfile == null) {
|
||||
err.println("No portfile was specified!");
|
||||
return -1;
|
||||
}
|
||||
if (logfile == null) {
|
||||
logfile = portfile + ".javaclog";
|
||||
}
|
||||
if (stdouterrfile == null) {
|
||||
stdouterrfile = portfile + ".stdouterr";
|
||||
}
|
||||
// Default to sjavac and hope it is in the path.
|
||||
if (sjavac == null) {
|
||||
sjavac = "sjavac";
|
||||
}
|
||||
|
||||
int attempts = 0;
|
||||
int rc = -1;
|
||||
do {
|
||||
PortFile port_file = getPortFile(portfile);
|
||||
synchronized (port_file) {
|
||||
port_file.lock();
|
||||
port_file.getValues();
|
||||
port_file.unlock();
|
||||
}
|
||||
if (!port_file.containsPortInfo()) {
|
||||
String cmd = fork(sjavac, port_file.getFilename(), logfile, poolsize, keepalive, err, stdouterrfile, background);
|
||||
|
||||
if (background.equals("true") && !port_file.waitForValidValues()) {
|
||||
// Ouch the server did not start! Lets print its stdouterrfile and the command used.
|
||||
printFailedAttempt(cmd, stdouterrfile, err);
|
||||
// And give up.
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
rc = connectAndCompile(port_file, id, args, sourcesToCompile, visibleSources,
|
||||
packageArtifacts, packageDependencies, packagePubapis, sysinfo,
|
||||
out, err);
|
||||
// Try again until we manage to connect. Any error after that
|
||||
// will cause the compilation to fail.
|
||||
if (rc == ERROR_BUT_TRY_AGAIN) {
|
||||
// We could not connect to the server. Try again.
|
||||
attempts++;
|
||||
try {
|
||||
Thread.sleep(WAIT_BETWEEN_CONNECT_ATTEMPTS * 1000);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
} while (rc == ERROR_BUT_TRY_AGAIN && attempts < MAX_NUM_CONNECT_ATTEMPTS);
|
||||
return rc;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace(err);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static void printFailedAttempt(String cmd, String f, PrintStream err) {
|
||||
err.println("---- Failed to start javac server with this command -----");
|
||||
err.println(cmd);
|
||||
try {
|
||||
BufferedReader in = new BufferedReader(new FileReader(f));
|
||||
err.println("---- stdout/stderr output from attempt to start javac server -----");
|
||||
for (;;) {
|
||||
String l = in.readLine();
|
||||
if (l == null) {
|
||||
break;
|
||||
}
|
||||
err.println(l);
|
||||
}
|
||||
err.println("------------------------------------------------------------------");
|
||||
} catch (Exception e) {
|
||||
err.println("The stdout/stderr output in file " + f + " does not exist and the server did not start.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn the server instance.
|
||||
*/
|
||||
|
@ -367,15 +224,15 @@ public class JavacServer {
|
|||
/**
|
||||
* Fork a background process. Returns the command line used that can be printed if something failed.
|
||||
*/
|
||||
private static String fork(String sjavac, String portfile, String logfile, int poolsize, int keepalive,
|
||||
final PrintStream err, String stdouterrfile, String background)
|
||||
public static String fork(String sjavac, String portfile, String logfile, int poolsize, int keepalive,
|
||||
final PrintStream err, String stdouterrfile, boolean background)
|
||||
throws IOException, ProblemException {
|
||||
if (stdouterrfile != null && stdouterrfile.trim().equals("")) {
|
||||
stdouterrfile = null;
|
||||
}
|
||||
final String startserver = "--startserver:portfile=" + portfile + ",logfile=" + logfile + ",stdouterrfile=" + stdouterrfile + ",poolsize=" + poolsize + ",keepalive="+ keepalive;
|
||||
|
||||
if (background.equals("true")) {
|
||||
if (background) {
|
||||
sjavac += "%20" + startserver;
|
||||
sjavac = sjavac.replaceAll("%20", " ");
|
||||
sjavac = sjavac.replaceAll("%2C", ",");
|
||||
|
@ -420,243 +277,6 @@ public class JavacServer {
|
|||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Expect this key on the next line read from the reader.
|
||||
*/
|
||||
private static boolean expect(BufferedReader in, String key) throws IOException {
|
||||
String s = in.readLine();
|
||||
if (s != null && s.equals(key)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a request to the server only to get the maximum possible heap size to use for compilations.
|
||||
*
|
||||
* @param port_file The port file used to synchronize creation of this server.
|
||||
* @param id The identify of the compilation.
|
||||
* @param out Standard out information.
|
||||
* @param err Standard err information.
|
||||
* @return The maximum heap size in bytes.
|
||||
*/
|
||||
public static SysInfo connectGetSysInfo(String serverSettings, PrintStream out, PrintStream err) {
|
||||
SysInfo sysinfo = new SysInfo(-1, -1);
|
||||
String id = Util.extractStringOption("id", serverSettings);
|
||||
String portfile = Util.extractStringOption("portfile", serverSettings);
|
||||
try {
|
||||
PortFile pf = getPortFile(portfile);
|
||||
useServer(serverSettings, new String[0],
|
||||
new HashSet<URI>(),
|
||||
new HashSet<URI>(),
|
||||
new HashMap<URI, Set<String>>(),
|
||||
new HashMap<String, Set<URI>>(),
|
||||
new HashMap<String, Set<String>>(),
|
||||
new HashMap<String, String>(),
|
||||
sysinfo, out, err);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace(err);
|
||||
}
|
||||
return sysinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect and compile using the javac server settings and the args. When using more advanced features, the sources_to_compile and visible_sources are
|
||||
* supplied to the server and meta data is returned in package_artifacts, package_dependencies and package_pubapis.
|
||||
*/
|
||||
private static int connectAndCompile(PortFile portFile, String id, String[] args,
|
||||
Set<URI> sourcesToCompile,
|
||||
Set<URI> visibleSources,
|
||||
Map<String, Set<URI>> packageArtifacts,
|
||||
Map<String, Set<String>> packageDependencies,
|
||||
Map<String, String> packagePublicApis,
|
||||
SysInfo sysinfo,
|
||||
PrintStream out,
|
||||
PrintStream err) {
|
||||
int rc = -3;
|
||||
try {
|
||||
int port = portFile.containsPortInfo() ? portFile.getPort() : 0;
|
||||
if (port == 0) {
|
||||
return ERROR_BUT_TRY_AGAIN;
|
||||
}
|
||||
long cookie = portFile.getCookie();
|
||||
|
||||
// Acquire the localhost/127.0.0.1 address.
|
||||
InetAddress addr = InetAddress.getByName(null);
|
||||
SocketAddress sockaddr = new InetSocketAddress(addr, port);
|
||||
Socket sock = new Socket();
|
||||
int timeoutMs = CONNECTION_TIMEOUT * 1000;
|
||||
try {
|
||||
sock.connect(sockaddr, timeoutMs);
|
||||
} catch (java.net.ConnectException e) {
|
||||
err.println("Could not connect to javac server found in portfile: " + portFile.getFilename() + " " + e);
|
||||
return ERROR_BUT_TRY_AGAIN;
|
||||
}
|
||||
if (!sock.isConnected()) {
|
||||
err.println("Could not connect to javac server found in portfile: " + portFile.getFilename());
|
||||
return ERROR_BUT_TRY_AGAIN;
|
||||
}
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
|
||||
PrintWriter sockout = new PrintWriter(sock.getOutputStream());
|
||||
|
||||
sockout.println(PROTOCOL_COOKIE_VERSION);
|
||||
sockout.println("" + cookie);
|
||||
sockout.println(PROTOCOL_CWD);
|
||||
sockout.println(System.getProperty("user.dir"));
|
||||
sockout.println(PROTOCOL_ID);
|
||||
sockout.println(id);
|
||||
sockout.println(PROTOCOL_ARGS);
|
||||
for (String s : args) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
String[] paths = s.split(File.pathSeparator);
|
||||
int c = 0;
|
||||
for (String path : paths) {
|
||||
File f = new File(path);
|
||||
if (f.isFile() || f.isDirectory()) {
|
||||
buf.append(f.getAbsolutePath());
|
||||
c++;
|
||||
if (c < paths.length) {
|
||||
buf.append(File.pathSeparator);
|
||||
}
|
||||
} else {
|
||||
buf = new StringBuffer(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
sockout.println(buf.toString());
|
||||
}
|
||||
sockout.println(PROTOCOL_SOURCES_TO_COMPILE);
|
||||
for (URI uri : sourcesToCompile) {
|
||||
sockout.println(uri.toString());
|
||||
}
|
||||
sockout.println(PROTOCOL_VISIBLE_SOURCES);
|
||||
for (URI uri : visibleSources) {
|
||||
sockout.println(uri.toString());
|
||||
}
|
||||
sockout.println(PROTOCOL_END);
|
||||
sockout.flush();
|
||||
|
||||
StringBuffer stdout = new StringBuffer();
|
||||
StringBuffer stderr = new StringBuffer();
|
||||
|
||||
if (!expect(in, PROTOCOL_STDOUT)) {
|
||||
return ERROR_FATAL;
|
||||
}
|
||||
// Load stdout
|
||||
for (;;) {
|
||||
String l = in.readLine();
|
||||
if (l == null) {
|
||||
return ERROR_FATAL;
|
||||
}
|
||||
if (l.equals(PROTOCOL_STDERR)) {
|
||||
break;
|
||||
}
|
||||
stdout.append(l);
|
||||
stdout.append('\n');
|
||||
}
|
||||
// Load stderr
|
||||
for (;;) {
|
||||
String l = in.readLine();
|
||||
if (l == null) {
|
||||
return ERROR_FATAL;
|
||||
}
|
||||
if (l.equals(PROTOCOL_PACKAGE_ARTIFACTS)) {
|
||||
break;
|
||||
}
|
||||
stderr.append(l);
|
||||
stderr.append('\n');
|
||||
}
|
||||
// Load the package artifacts
|
||||
Set<URI> lastUriSet = null;
|
||||
for (;;) {
|
||||
String l = in.readLine();
|
||||
if (l == null) {
|
||||
return ERROR_FATAL;
|
||||
}
|
||||
if (l.equals(PROTOCOL_PACKAGE_DEPENDENCIES)) {
|
||||
break;
|
||||
}
|
||||
if (l.length() > 1 && l.charAt(0) == '+') {
|
||||
String pkg = l.substring(1);
|
||||
lastUriSet = new HashSet<>();
|
||||
packageArtifacts.put(pkg, lastUriSet);
|
||||
} else if (l.length() > 1 && lastUriSet != null) {
|
||||
lastUriSet.add(new URI(l.substring(1)));
|
||||
}
|
||||
}
|
||||
// Load package dependencies
|
||||
Set<String> lastPackageSet = null;
|
||||
for (;;) {
|
||||
String l = in.readLine();
|
||||
if (l == null) {
|
||||
return ERROR_FATAL;
|
||||
}
|
||||
if (l.equals(PROTOCOL_PACKAGE_PUBLIC_APIS)) {
|
||||
break;
|
||||
}
|
||||
if (l.length() > 1 && l.charAt(0) == '+') {
|
||||
String pkg = l.substring(1);
|
||||
lastPackageSet = new HashSet<>();
|
||||
packageDependencies.put(pkg, lastPackageSet);
|
||||
} else if (l.length() > 1 && lastPackageSet != null) {
|
||||
lastPackageSet.add(l.substring(1));
|
||||
}
|
||||
}
|
||||
// Load package pubapis
|
||||
Map<String, StringBuffer> tmp = new HashMap<>();
|
||||
StringBuffer lastPublicApi = null;
|
||||
for (;;) {
|
||||
String l = in.readLine();
|
||||
if (l == null) {
|
||||
return ERROR_FATAL;
|
||||
}
|
||||
if (l.equals(PROTOCOL_SYSINFO)) {
|
||||
break;
|
||||
}
|
||||
if (l.length() > 1 && l.charAt(0) == '+') {
|
||||
String pkg = l.substring(1);
|
||||
lastPublicApi = new StringBuffer();
|
||||
tmp.put(pkg, lastPublicApi);
|
||||
} else if (l.length() > 1 && lastPublicApi != null) {
|
||||
lastPublicApi.append(l.substring(1));
|
||||
lastPublicApi.append("\n");
|
||||
}
|
||||
}
|
||||
for (String p : tmp.keySet()) {
|
||||
assert (packagePublicApis.get(p) == null);
|
||||
String api = tmp.get(p).toString();
|
||||
packagePublicApis.put(p, api);
|
||||
}
|
||||
// Now reading the max memory possible.
|
||||
for (;;) {
|
||||
String l = in.readLine();
|
||||
if (l == null) {
|
||||
return ERROR_FATAL;
|
||||
}
|
||||
if (l.equals(PROTOCOL_RETURN_CODE)) {
|
||||
break;
|
||||
}
|
||||
if (l.startsWith("num_cores=") && sysinfo != null) {
|
||||
sysinfo.numCores = Integer.parseInt(l.substring(10));
|
||||
}
|
||||
if (l.startsWith("max_memory=") && sysinfo != null) {
|
||||
sysinfo.maxMemory = Long.parseLong(l.substring(11));
|
||||
}
|
||||
}
|
||||
String l = in.readLine();
|
||||
if (l == null) {
|
||||
err.println("No return value from the server!");
|
||||
return ERROR_FATAL;
|
||||
}
|
||||
rc = Integer.parseInt(l);
|
||||
out.print(stdout);
|
||||
err.print(stderr);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace(err);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the server thread until it exits. Either because of inactivity or because the port file has been deleted by someone else, or overtaken by some other
|
||||
* javac server.
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package com.sun.tools.sjavac.server;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface JavacService {
|
||||
|
||||
SysInfo getSysInfo();
|
||||
|
||||
CompilationResult compile(String protocolId,
|
||||
String invocationId,
|
||||
String[] args,
|
||||
List<File> explicitSources,
|
||||
Set<URI> sourcesToCompile,
|
||||
Set<URI> visibleSources);
|
||||
}
|
|
@ -0,0 +1,408 @@
|
|||
package com.sun.tools.sjavac.server;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sun.tools.sjavac.Util;
|
||||
|
||||
import static com.sun.tools.sjavac.server.CompilationResult.ERROR_BUT_TRY_AGAIN;
|
||||
import static com.sun.tools.sjavac.server.CompilationResult.ERROR_FATAL;
|
||||
|
||||
public class JavacServiceClient implements JavacService {
|
||||
|
||||
|
||||
// The id can perhaps be used in the future by the javac server to reuse the
|
||||
// JavaCompiler instance for several compiles using the same id.
|
||||
private final String id;
|
||||
private final String portfile;
|
||||
private final String logfile;
|
||||
private final String stdouterrfile;
|
||||
private final boolean background;
|
||||
|
||||
// Default keepalive for server is 120 seconds.
|
||||
// I.e. it will accept 120 seconds of inactivity before quitting.
|
||||
private final int keepalive;
|
||||
private final int poolsize;
|
||||
|
||||
// The sjavac option specifies how the server part of sjavac is spawned.
|
||||
// If you have the experimental sjavac in your path, you are done. If not, you have
|
||||
// to point to a com.sun.tools.sjavac.Main that supports --startserver
|
||||
// for example by setting: sjavac=java%20-jar%20...javac.jar%com.sun.tools.sjavac.Main
|
||||
private final String sjavac;
|
||||
|
||||
public JavacServiceClient(String settings) {
|
||||
id = Util.extractStringOption("id", settings);
|
||||
portfile = Util.extractStringOption("portfile", settings);
|
||||
logfile = Util.extractStringOption("logfile", settings, portfile + ".javaclog");
|
||||
stdouterrfile = Util.extractStringOption("stdouterrfile", settings, portfile + ".stdouterr");
|
||||
background = Util.extractBooleanOption("background", settings, true);
|
||||
sjavac = Util.extractStringOption("sjavac", settings, "sjavac");
|
||||
int poolsize = Util.extractIntOption("poolsize", settings);
|
||||
keepalive = Util.extractIntOption("keepalive", settings, 120);
|
||||
|
||||
this.poolsize = poolsize > 0 ? poolsize : Runtime.getRuntime().availableProcessors();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make a request to the server only to get the maximum possible heap size to use for compilations.
|
||||
*
|
||||
* @param port_file The port file used to synchronize creation of this server.
|
||||
* @param id The identify of the compilation.
|
||||
* @param out Standard out information.
|
||||
* @param err Standard err information.
|
||||
* @return The maximum heap size in bytes.
|
||||
*/
|
||||
@Override
|
||||
public SysInfo getSysInfo() {
|
||||
try {
|
||||
CompilationResult cr = useServer(new String[0],
|
||||
Collections.<URI>emptySet(),
|
||||
Collections.<URI>emptySet(),
|
||||
Collections.<URI, Set<String>>emptyMap());
|
||||
return cr.sysinfo;
|
||||
} catch (Exception e) {
|
||||
return new SysInfo(-1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompilationResult compile(String protocolId,
|
||||
String invocationId,
|
||||
String[] args,
|
||||
List<File> explicitSources,
|
||||
Set<URI> sourcesToCompile,
|
||||
Set<URI> visibleSources) {
|
||||
// Delegate to useServer, which delegates to compileHelper
|
||||
return useServer(args, sourcesToCompile, visibleSources, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect and compile using the javac server settings and the args. When using more advanced features, the sources_to_compile and visible_sources are
|
||||
* supplied to the server and meta data is returned in package_artifacts, package_dependencies and package_pubapis.
|
||||
*/
|
||||
public CompilationResult compileHelper(String id,
|
||||
String[] args,
|
||||
Set<URI> sourcesToCompile,
|
||||
Set<URI> visibleSources) {
|
||||
|
||||
CompilationResult rc = new CompilationResult(-3);
|
||||
|
||||
try {
|
||||
PortFile portFile = JavacServer.getPortFile(this.portfile);
|
||||
|
||||
int port = portFile.containsPortInfo() ? portFile.getPort() : 0;
|
||||
if (port == 0) {
|
||||
return new CompilationResult(ERROR_BUT_TRY_AGAIN);
|
||||
}
|
||||
long cookie = portFile.getCookie();
|
||||
// Acquire the localhost/127.0.0.1 address.
|
||||
InetAddress addr = InetAddress.getByName(null);
|
||||
SocketAddress sockaddr = new InetSocketAddress(addr, port);
|
||||
Socket sock = new Socket();
|
||||
int timeoutMs = JavacServer.CONNECTION_TIMEOUT * 1000;
|
||||
try {
|
||||
sock.connect(sockaddr, timeoutMs);
|
||||
} catch (java.net.ConnectException e) {
|
||||
rc.setReturnCode(ERROR_BUT_TRY_AGAIN);
|
||||
rc.stderr = "Could not connect to javac server found in portfile: " + portFile.getFilename() + " " + e;
|
||||
return rc;
|
||||
}
|
||||
if (!sock.isConnected()) {
|
||||
rc.setReturnCode(ERROR_BUT_TRY_AGAIN);
|
||||
rc.stderr = "Could not connect to javac server found in portfile: " + portFile.getFilename();
|
||||
return rc;
|
||||
}
|
||||
|
||||
//
|
||||
// Send arguments
|
||||
//
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
|
||||
PrintWriter sockout = new PrintWriter(sock.getOutputStream());
|
||||
|
||||
sockout.println(JavacServer.PROTOCOL_COOKIE_VERSION);
|
||||
sockout.println("" + cookie);
|
||||
sockout.println(JavacServer.PROTOCOL_CWD);
|
||||
sockout.println(System.getProperty("user.dir"));
|
||||
sockout.println(JavacServer.PROTOCOL_ID);
|
||||
sockout.println(id);
|
||||
sockout.println(JavacServer.PROTOCOL_ARGS);
|
||||
for (String s : args) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
String[] paths = s.split(File.pathSeparator);
|
||||
int c = 0;
|
||||
for (String path : paths) {
|
||||
File f = new File(path);
|
||||
if (f.isFile() || f.isDirectory()) {
|
||||
buf.append(f.getAbsolutePath());
|
||||
c++;
|
||||
if (c < paths.length) {
|
||||
buf.append(File.pathSeparator);
|
||||
}
|
||||
} else {
|
||||
buf = new StringBuffer(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
sockout.println(buf.toString());
|
||||
}
|
||||
sockout.println(JavacServer.PROTOCOL_SOURCES_TO_COMPILE);
|
||||
for (URI uri : sourcesToCompile) {
|
||||
sockout.println(uri.toString());
|
||||
}
|
||||
sockout.println(JavacServer.PROTOCOL_VISIBLE_SOURCES);
|
||||
for (URI uri : visibleSources) {
|
||||
sockout.println(uri.toString());
|
||||
}
|
||||
sockout.println(JavacServer.PROTOCOL_END);
|
||||
sockout.flush();
|
||||
|
||||
//
|
||||
// Receive result
|
||||
//
|
||||
StringBuffer stdout = new StringBuffer();
|
||||
StringBuffer stderr = new StringBuffer();
|
||||
|
||||
if (!JavacServiceClient.expect(in, JavacServer.PROTOCOL_STDOUT)) {
|
||||
return new CompilationResult(ERROR_FATAL);
|
||||
}
|
||||
// Load stdout
|
||||
for (;;) {
|
||||
String l = in.readLine();
|
||||
if (l == null) {
|
||||
return new CompilationResult(ERROR_FATAL);
|
||||
}
|
||||
if (l.equals(JavacServer.PROTOCOL_STDERR)) {
|
||||
break;
|
||||
}
|
||||
stdout.append(l);
|
||||
stdout.append('\n');
|
||||
}
|
||||
// Load stderr
|
||||
for (;;) {
|
||||
String l = in.readLine();
|
||||
if (l == null) {
|
||||
return new CompilationResult(ERROR_FATAL);
|
||||
}
|
||||
if (l.equals(JavacServer.PROTOCOL_PACKAGE_ARTIFACTS)) {
|
||||
break;
|
||||
}
|
||||
stderr.append(l);
|
||||
stderr.append('\n');
|
||||
}
|
||||
// Load the package artifacts
|
||||
Set<URI> lastUriSet = null;
|
||||
for (;;) {
|
||||
String l = in.readLine();
|
||||
if (l == null) {
|
||||
return new CompilationResult(ERROR_FATAL);
|
||||
}
|
||||
if (l.equals(JavacServer.PROTOCOL_PACKAGE_DEPENDENCIES)) {
|
||||
break;
|
||||
}
|
||||
if (l.length() > 1 && l.charAt(0) == '+') {
|
||||
String pkg = l.substring(1);
|
||||
lastUriSet = new HashSet<>();
|
||||
rc.packageArtifacts.put(pkg, lastUriSet);
|
||||
} else if (l.length() > 1 && lastUriSet != null) {
|
||||
lastUriSet.add(new URI(l.substring(1)));
|
||||
}
|
||||
}
|
||||
// Load package dependencies
|
||||
Set<String> lastPackageSet = null;
|
||||
for (;;) {
|
||||
String l = in.readLine();
|
||||
if (l == null) {
|
||||
return new CompilationResult(ERROR_FATAL);
|
||||
}
|
||||
if (l.equals(JavacServer.PROTOCOL_PACKAGE_PUBLIC_APIS)) {
|
||||
break;
|
||||
}
|
||||
if (l.length() > 1 && l.charAt(0) == '+') {
|
||||
String pkg = l.substring(1);
|
||||
lastPackageSet = new HashSet<>();
|
||||
rc.packageDependencies.put(pkg, lastPackageSet);
|
||||
} else if (l.length() > 1 && lastPackageSet != null) {
|
||||
lastPackageSet.add(l.substring(1));
|
||||
}
|
||||
}
|
||||
// Load package pubapis
|
||||
Map<String, StringBuffer> tmp = new HashMap<>();
|
||||
StringBuffer lastPublicApi = null;
|
||||
for (;;) {
|
||||
String l = in.readLine();
|
||||
if (l == null) {
|
||||
return new CompilationResult(ERROR_FATAL);
|
||||
}
|
||||
if (l.equals(JavacServer.PROTOCOL_SYSINFO)) {
|
||||
break;
|
||||
}
|
||||
if (l.length() > 1 && l.charAt(0) == '+') {
|
||||
String pkg = l.substring(1);
|
||||
lastPublicApi = new StringBuffer();
|
||||
tmp.put(pkg, lastPublicApi);
|
||||
} else if (l.length() > 1 && lastPublicApi != null) {
|
||||
lastPublicApi.append(l.substring(1));
|
||||
lastPublicApi.append("\n");
|
||||
}
|
||||
}
|
||||
for (String p : tmp.keySet()) {
|
||||
//assert (packagePublicApis.get(p) == null);
|
||||
String api = tmp.get(p).toString();
|
||||
rc.packagePubapis.put(p, api);
|
||||
}
|
||||
// Now reading the max memory possible.
|
||||
for (;;) {
|
||||
String l = in.readLine();
|
||||
if (l == null) {
|
||||
return new CompilationResult(ERROR_FATAL);
|
||||
}
|
||||
if (l.equals(JavacServer.PROTOCOL_RETURN_CODE)) {
|
||||
break;
|
||||
}
|
||||
if (l.startsWith("num_cores=")) {
|
||||
rc.sysinfo.numCores = Integer.parseInt(l.substring(10));
|
||||
}
|
||||
if (l.startsWith("max_memory=")) {
|
||||
rc.sysinfo.maxMemory = Long.parseLong(l.substring(11));
|
||||
}
|
||||
}
|
||||
String l = in.readLine();
|
||||
if (l == null) {
|
||||
rc.setReturnCode(ERROR_FATAL);
|
||||
rc.stderr = "No return value from the server!";
|
||||
return rc;
|
||||
}
|
||||
rc.setReturnCode(Integer.parseInt(l));
|
||||
rc.stdout = stdout.toString();
|
||||
rc.stderr = stderr.toString();
|
||||
} catch (Exception e) {
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
rc.stderr = sw.toString();
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a compilation request to a javac server.
|
||||
*
|
||||
* @param args are the command line args to javac and is allowed to contain source files, @file and other command line options to javac.
|
||||
*
|
||||
* The generated classes, h files and other artifacts from the javac invocation are stored by the javac server to disk.
|
||||
*
|
||||
* @param sources_to_compile The sources to compile.
|
||||
*
|
||||
* @param visibleSources If visible sources has a non zero size, then visible_sources are the only files in the file system that the javac server can see!
|
||||
* (Sources to compile are always visible.) The visible sources are those supplied by the (filtered) -sourcepath
|
||||
*
|
||||
* @param visibleClasses If visible classes for a specific root/jar has a non zero size, then visible_classes are the only class files that the javac server
|
||||
* can see, in that root/jar. It maps from a classpath root or a jar file to the set of visible classes for that root/jar.
|
||||
*
|
||||
* The server return meta data about the build in the following parameters.
|
||||
* @param package_artifacts, map from package name to set of created artifacts for that package.
|
||||
* @param package_dependencies, map from package name to set of packages that it depends upon.
|
||||
* @param package_pubapis, map from package name to unique string identifying its pub api.
|
||||
*/
|
||||
public CompilationResult useServer(String[] args,
|
||||
Set<URI> sourcesToCompile,
|
||||
Set<URI> visibleSources,
|
||||
Map<URI, Set<String>> visibleClasses) {
|
||||
try {
|
||||
if (portfile == null) {
|
||||
CompilationResult cr = new CompilationResult(CompilationResult.ERROR_FATAL);
|
||||
cr.stderr = "No portfile was specified!";
|
||||
return cr;
|
||||
}
|
||||
|
||||
int attempts = 0;
|
||||
CompilationResult rc;
|
||||
do {
|
||||
PortFile port_file = JavacServer.getPortFile(portfile);
|
||||
synchronized (port_file) {
|
||||
port_file.lock();
|
||||
port_file.getValues();
|
||||
port_file.unlock();
|
||||
}
|
||||
if (!port_file.containsPortInfo()) {
|
||||
String cmd = JavacServer.fork(sjavac, port_file.getFilename(), logfile, poolsize, keepalive, System.err, stdouterrfile, background);
|
||||
|
||||
if (background && !port_file.waitForValidValues()) {
|
||||
// Ouch the server did not start! Lets print its stdouterrfile and the command used.
|
||||
StringWriter sw = new StringWriter();
|
||||
JavacServiceClient.printFailedAttempt(cmd, stdouterrfile, new PrintWriter(sw));
|
||||
// And give up.
|
||||
CompilationResult cr = new CompilationResult(ERROR_FATAL);
|
||||
cr.stderr = sw.toString();
|
||||
return cr;
|
||||
}
|
||||
}
|
||||
rc = compileHelper(id, args, sourcesToCompile, visibleSources);
|
||||
// Try again until we manage to connect. Any error after that
|
||||
// will cause the compilation to fail.
|
||||
if (rc.returnCode == CompilationResult.ERROR_BUT_TRY_AGAIN) {
|
||||
// We could not connect to the server. Try again.
|
||||
attempts++;
|
||||
try {
|
||||
Thread.sleep(JavacServer.WAIT_BETWEEN_CONNECT_ATTEMPTS * 1000);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
} while (rc.returnCode == ERROR_BUT_TRY_AGAIN && attempts < JavacServer.MAX_NUM_CONNECT_ATTEMPTS);
|
||||
return rc;
|
||||
} catch (Exception e) {
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
CompilationResult cr = new CompilationResult(ERROR_FATAL);
|
||||
cr.stderr = sw.toString();
|
||||
return cr;
|
||||
}
|
||||
}
|
||||
|
||||
public static void printFailedAttempt(String cmd, String f, PrintWriter err) {
|
||||
err.println("---- Failed to start javac server with this command -----");
|
||||
err.println(cmd);
|
||||
try {
|
||||
BufferedReader in = new BufferedReader(new FileReader(f));
|
||||
err.println("---- stdout/stderr output from attempt to start javac server -----");
|
||||
for (;;) {
|
||||
String l = in.readLine();
|
||||
if (l == null) {
|
||||
break;
|
||||
}
|
||||
err.println(l);
|
||||
}
|
||||
err.println("------------------------------------------------------------------");
|
||||
} catch (Exception e) {
|
||||
err.println("The stdout/stderr output in file " + f + " does not exist and the server did not start.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Expect this key on the next line read from the reader.
|
||||
*/
|
||||
public static boolean expect(BufferedReader in, String key) throws IOException {
|
||||
String s = in.readLine();
|
||||
if (s != null && s.equals(key)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.nio.charset.*;
|
||||
|
@ -43,6 +42,9 @@ class SJavac {
|
|||
}
|
||||
|
||||
FileSystem defaultfs = FileSystems.getDefault();
|
||||
String serverArg = "--server:"
|
||||
+ "portfile=testportfile,"
|
||||
+ "background=false";
|
||||
|
||||
// Where to put generated sources that will
|
||||
// test aspects of sjavac, ie JTWork/scratch/gensrc
|
||||
|
@ -136,7 +138,7 @@ class SJavac {
|
|||
"private int b() { return A.DEFINITION; } native void foo(); }");
|
||||
|
||||
compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
|
||||
"--server:portfile=testserver,background=false", "--log=debug");
|
||||
serverArg, "--log=debug");
|
||||
previous_bin_state = collectState(bin);
|
||||
previous_headers_state = collectState(headers);
|
||||
}
|
||||
|
@ -145,7 +147,7 @@ class SJavac {
|
|||
System.out.println("\nTesting that no change in sources implies no change in binaries.");
|
||||
System.out.println("------------------------------------------------------------------");
|
||||
compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
|
||||
"--server:portfile=testserver,background=false", "--log=debug");
|
||||
serverArg, "--log=debug");
|
||||
Map<String,Long> new_bin_state = collectState(bin);
|
||||
verifyEqual(new_bin_state, previous_bin_state);
|
||||
Map<String,Long> new_headers_state = collectState(headers);
|
||||
|
@ -158,7 +160,7 @@ class SJavac {
|
|||
System.out.println("-----------------------------------------");
|
||||
removeFrom(gensrc, "alfa/omega/AA.java");
|
||||
compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
|
||||
"--server:portfile=testserver,background=false", "--log=debug");
|
||||
serverArg, "--log=debug");
|
||||
Map<String,Long> new_bin_state = collectState(bin);
|
||||
verifyThatFilesHaveBeenRemoved(previous_bin_state, new_bin_state,
|
||||
"bin/alfa/omega/AA$1.class",
|
||||
|
@ -185,7 +187,7 @@ class SJavac {
|
|||
"public final static int DEFINITION = 18; public void aint() { } private void foo() { } }");
|
||||
|
||||
compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
|
||||
"--server:portfile=testserver,background=false", "--log=debug");
|
||||
serverArg, "--log=debug");
|
||||
Map<String,Long> new_bin_state = collectState(bin);
|
||||
|
||||
verifyNewerFiles(previous_bin_state, new_bin_state,
|
||||
|
@ -211,7 +213,7 @@ class SJavac {
|
|||
"private int b() { return A.DEFINITION; } }");
|
||||
|
||||
compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
|
||||
"--server:portfile=testserver,background=false", "--log=debug");
|
||||
serverArg, "--log=debug");
|
||||
Map<String,Long> new_bin_state = collectState(bin);
|
||||
verifyNewerFiles(previous_bin_state, new_bin_state,
|
||||
"bin/beta/B.class",
|
||||
|
@ -236,7 +238,7 @@ class SJavac {
|
|||
"@java.lang.annotation.Native final static int alfa = 42; }");
|
||||
|
||||
compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
|
||||
"--server:portfile=testserver,background=false", "--log=debug");
|
||||
serverArg, "--log=debug");
|
||||
Map<String,Long> new_bin_state = collectState(bin);
|
||||
verifyNewerFiles(previous_bin_state, new_bin_state,
|
||||
"bin/beta/B.class",
|
||||
|
@ -262,7 +264,7 @@ class SJavac {
|
|||
"@java.lang.annotation.Native final static int alfa = 43; }");
|
||||
|
||||
compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
|
||||
"--server:portfile=testserver,background=false", "--log=debug");
|
||||
serverArg, "--log=debug");
|
||||
Map<String,Long> new_bin_state = collectState(bin);
|
||||
verifyNewerFiles(previous_bin_state, new_bin_state,
|
||||
"bin/beta/B.class",
|
||||
|
@ -299,7 +301,7 @@ class SJavac {
|
|||
"package beta; public class B { }");
|
||||
|
||||
compile("-x", "beta", "gensrc", "gensrc2", "-d", "bin", "-h", "headers", "-j", "1",
|
||||
"--server:portfile=testserver,background=false");
|
||||
serverArg);
|
||||
Map<String,Long> new_bin_state = collectState(bin);
|
||||
verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state,
|
||||
"bin/alfa/omega/A.class",
|
||||
|
@ -310,7 +312,7 @@ class SJavac {
|
|||
System.out.println("----- Compile with exluded beta went well!");
|
||||
delete(bin);
|
||||
compileExpectFailure("gensrc", "gensrc2", "-d", "bin", "-h", "headers", "-j", "1",
|
||||
"--server:portfile=testserver,background=false");
|
||||
serverArg);
|
||||
|
||||
System.out.println("----- Compile without exluded beta failed, as expected! Good!");
|
||||
delete(bin);
|
||||
|
@ -341,7 +343,7 @@ class SJavac {
|
|||
|
||||
compile("gensrc", "-x", "beta", "-sourcepath", "gensrc2",
|
||||
"-sourcepath", "gensrc3", "-d", "bin", "-h", "headers", "-j", "1",
|
||||
"--server:portfile=testserver,background=false");
|
||||
serverArg);
|
||||
|
||||
System.out.println("The first compile went well!");
|
||||
Map<String,Long> new_bin_state = collectState(bin);
|
||||
|
@ -353,7 +355,7 @@ class SJavac {
|
|||
delete(bin);
|
||||
compileExpectFailure("gensrc", "-sourcepath", "gensrc2", "-sourcepath", "gensrc3",
|
||||
"-d", "bin", "-h", "headers", "-j", "1",
|
||||
"--server:portfile=testserver,background=false");
|
||||
serverArg);
|
||||
|
||||
System.out.println("----- Compile without exluded beta failed, as expected! Good!");
|
||||
delete(bin);
|
||||
|
@ -378,7 +380,7 @@ class SJavac {
|
|||
"package gamma; public class C { alfa.omega.A a; }");
|
||||
|
||||
compile("gensrc", "-d", "bin", "-h", "headers", "-j", "3",
|
||||
"--server:portfile=testserver,background=false","--log=debug");
|
||||
serverArg,"--log=debug");
|
||||
Map<String,Long> new_bin_state = collectState(bin);
|
||||
verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state,
|
||||
"bin/alfa/omega/A.class",
|
||||
|
@ -407,7 +409,7 @@ class SJavac {
|
|||
"package beta; public class B { }");
|
||||
|
||||
compile("-x", "beta", "-src", "gensrc", "-x", "alfa/omega", "-sourcepath", "gensrc",
|
||||
"-d", "bin", "--server:portfile=testserver,background=false");
|
||||
"-d", "bin", serverArg);
|
||||
|
||||
Map<String,Long> new_bin_state = collectState(bin);
|
||||
verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state,
|
||||
|
@ -431,7 +433,7 @@ class SJavac {
|
|||
"}");
|
||||
|
||||
compile("gensrc", "-d", "bin", "-j", "1",
|
||||
"--server:portfile=testserver,background=false", "--log=debug");
|
||||
serverArg, "--log=debug");
|
||||
Map<String,Long> previous_bin_state = collectState(bin);
|
||||
|
||||
// Change pubapi of A, this should trigger a recompile of B.
|
||||
|
@ -443,7 +445,7 @@ class SJavac {
|
|||
"}");
|
||||
|
||||
compile("gensrc", "-d", "bin", "-j", "1",
|
||||
"--server:portfile=testserver,background=false", "--log=debug");
|
||||
serverArg, "--log=debug");
|
||||
Map<String,Long> new_bin_state = collectState(bin);
|
||||
|
||||
verifyNewerFiles(previous_bin_state, new_bin_state,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue