11/*
2- * Copyright (c) 2014, 2019 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2014, 2020 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
3434import java .net .InetAddress ;
3535import java .net .InetSocketAddress ;
3636import java .net .Socket ;
37+ import java .nio .charset .StandardCharsets ;
38+ import java .nio .file .Files ;
39+ import java .nio .file .Path ;
3740import java .util .ArrayList ;
3841import java .util .Arrays ;
3942import java .util .List ;
4245import com .sun .tools .javac .main .Main .Result ;
4346import com .sun .tools .sjavac .Log ;
4447import com .sun .tools .sjavac .Util ;
45- import com .sun .tools .sjavac .options .OptionHelper ;
4648import com .sun .tools .sjavac .options .Options ;
47- import com .sun .tools .sjavac .server .CompilationSubResult ;
4849import com .sun .tools .sjavac .server .PortFile ;
4950import com .sun .tools .sjavac .server .Sjavac ;
5051import com .sun .tools .sjavac .server .SjavacServer ;
5152
52- import static java .util .stream .Collectors .joining ;
53-
5453/**
5554 * Sjavac implementation that delegates requests to a SjavacServer.
5655 *
6160 */
6261public class SjavacClient implements Sjavac {
6362
64- // The id can perhaps be used in the future by the javac server to reuse the
65- // JavaCompiler instance for several compiles using the same id.
66- private final String id ;
67- private final PortFile portFile ;
68-
69- // Default keepalive for server is 120 seconds.
70- // I.e. it will accept 120 seconds of inactivity before quitting.
71- private final int keepalive ;
72- private final int poolsize ;
63+ private PortFile portFile ;
7364
74- // The sjavac option specifies how the server part of sjavac is spawned.
75- // If you have the experimental sjavac in your path, you are done. If not, you have
76- // to point to a com.sun.tools.sjavac.Main that supports --startserver
77- // for example by setting: sjavac=java%20-jar%20...javac.jar%com.sun.tools.sjavac.Main
78- private final String sjavacForkCmd ;
65+ // The servercmd option specifies how the server part of sjavac is spawned.
66+ // It should point to a com.sun.tools.sjavac.Main that supports --startserver
67+ private String serverCommand ;
7968
69+ // Accept 120 seconds of inactivity before quitting.
70+ private static final int KEEPALIVE = 120 ;
71+ private static final int POOLSIZE = Runtime .getRuntime ().availableProcessors ();
8072 // Wait 2 seconds for response, before giving up on javac server.
81- static int CONNECTION_TIMEOUT = 2000 ;
82- static int MAX_CONNECT_ATTEMPTS = 3 ;
83- static int WAIT_BETWEEN_CONNECT_ATTEMPTS = 2000 ;
84-
85- // Store the server conf settings here.
86- private final String settings ;
73+ private static final int CONNECTION_TIMEOUT = 2000 ;
74+ private static final int MAX_CONNECT_ATTEMPTS = 3 ;
75+ private static final int WAIT_BETWEEN_CONNECT_ATTEMPTS = 2000 ;
8776
8877 public SjavacClient (Options options ) {
89- String tmpServerConf = options .getServerConf ();
90- String serverConf = (tmpServerConf !=null )? tmpServerConf : "" ;
91- String tmpId = Util .extractStringOption ("id" , serverConf );
92- id = (tmpId !=null ) ? tmpId : "id" +(((new java .util .Random ()).nextLong ())&Long .MAX_VALUE );
93- String defaultPortfile = options .getDestDir ()
94- .resolve ("javac_server" )
95- .toAbsolutePath ()
96- .toString ();
97- String portfileName = Util .extractStringOption ("portfile" , serverConf , defaultPortfile );
98- portFile = SjavacServer .getPortFile (portfileName );
99- sjavacForkCmd = Util .extractStringOption ("sjavac" , serverConf , "sjavac" );
100- int poolsize = Util .extractIntOption ("poolsize" , serverConf );
101- keepalive = Util .extractIntOption ("keepalive" , serverConf , 120 );
78+ String serverConf = options .getServerConf ();
79+ String configFile = Util .extractStringOption ("conf" , serverConf , "" );
10280
103- this . poolsize = poolsize > 0 ? poolsize : Runtime . getRuntime (). availableProcessors ();
104- settings = ( serverConf . equals ( "" )) ? "id=" + id + ",portfile=" + portfileName : serverConf ;
105- }
81+ try {
82+ List < String > configFileLines = Files . readAllLines ( Path . of ( configFile ), StandardCharsets . UTF_8 ) ;
83+ String configFileContent = String . join ( " \n " , configFileLines );
10684
107- /**
108- * Hand out the server settings.
109- * @return The server settings, possibly a default value.
110- */
111- public String serverSettings () {
112- return settings ;
85+ String portfileName = Util .extractStringOptionLine ("portfile" , configFileContent , "" );
86+ if (portfileName .isEmpty ()) {
87+ Log .error ("Configuration file missing value for 'portfile'" );
88+ portFile = null ;
89+ } else {
90+ portFile = SjavacServer .getPortFile (portfileName );
91+ }
92+
93+ String serverCommandString = Util .extractStringOptionLine ("servercmd" , configFileContent , "" );
94+ if (serverCommandString .isEmpty ()) {
95+ Log .error ("Configuration file missing value for 'servercmd'" );
96+ serverCommand = null ;
97+ } else {
98+ serverCommand = serverCommandString ;
99+ }
100+ } catch (IOException e ) {
101+ Log .error ("Cannot read configuration file " + configFile );
102+ Log .debug (e );
103+ portFile = null ;
104+ serverCommand = null ;
105+ }
113106 }
114107
115108 @ Override
116109 public Result compile (String [] args ) {
110+ if (portFile == null || serverCommand == null ) {
111+ Log .error ("Incorrect configuration, portfile and/or servercmd missing" );
112+ return Result .ERROR ;
113+ }
114+
117115 Result result = null ;
118116 try (Socket socket = tryConnect ()) {
119117 PrintWriter out = new PrintWriter (new OutputStreamWriter (socket .getOutputStream ()));
@@ -176,7 +174,7 @@ public Result compile(String[] args) {
176174 * Makes MAX_CONNECT_ATTEMPTS attempts to connect to server.
177175 */
178176 private Socket tryConnect () throws IOException , InterruptedException {
179- makeSureServerIsRunning (portFile );
177+ makeSureServerIsRunning ();
180178 int attempt = 0 ;
181179 while (true ) {
182180 Log .debug ("Trying to connect. Attempt " + (++attempt ) + " of " + MAX_CONNECT_ATTEMPTS );
@@ -206,7 +204,7 @@ private Socket makeConnectionAttempt() throws IOException {
206204 * Will return immediately if a server already seems to be running,
207205 * otherwise fork a new server and block until it seems to be running.
208206 */
209- private void makeSureServerIsRunning (PortFile portFile )
207+ private void makeSureServerIsRunning ()
210208 throws IOException , InterruptedException {
211209
212210 if (portFile .exists ()) {
@@ -221,10 +219,7 @@ private void makeSureServerIsRunning(PortFile portFile)
221219 }
222220
223221 // Fork a new server and wait for it to start
224- SjavacClient .fork (sjavacForkCmd ,
225- portFile ,
226- poolsize ,
227- keepalive );
222+ startNewServer ();
228223 }
229224
230225 @ Override
@@ -235,14 +230,14 @@ public void shutdown() {
235230 /*
236231 * Fork a server process process and wait for server to come around
237232 */
238- public static void fork ( String sjavacCmd , PortFile portFile , int poolsize , int keepalive )
233+ public void startNewServer ( )
239234 throws IOException , InterruptedException {
240235 List <String > cmd = new ArrayList <>();
241- cmd .addAll (Arrays .asList (OptionHelper . unescapeCmdArg ( sjavacCmd ) .split (" " )));
236+ cmd .addAll (Arrays .asList (serverCommand .split (" " )));
242237 cmd .add ("--startserver:"
243238 + "portfile=" + portFile .getFilename ()
244- + ",poolsize=" + poolsize
245- + ",keepalive=" + keepalive );
239+ + ",poolsize=" + POOLSIZE
240+ + ",keepalive=" + KEEPALIVE );
246241
247242 Process serverProcess ;
248243 Log .debug ("Starting server. Command: " + String .join (" " , cmd ));
0 commit comments