25
25
import java .io .IOException ;
26
26
import java .util .ArrayList ;
27
27
import java .util .Arrays ;
28
- import java .util .Enumeration ;
28
+ import java .util .Collections ;
29
29
import java .util .HashMap ;
30
30
import java .util .List ;
31
31
import java .util .Map ;
32
32
import java .util .Properties ;
33
- import java .util .jar .JarEntry ;
34
33
import java .util .jar .JarFile ;
35
34
import java .util .regex .Pattern ;
36
35
39
38
*/
40
39
public abstract class AbstractLauncher <T extends AbstractLauncher > extends LauncherCommon {
41
40
41
+ private static final String DEFAULT_PROPERTIES_FILE = "spark-defaults.conf" ;
42
42
protected static final String DEFAULT_MEM = "512m" ;
43
43
44
44
protected String javaHome ;
@@ -93,18 +93,19 @@ public T setConf(String key, String value) {
93
93
*/
94
94
protected abstract List <String > buildLauncherCommand () throws IOException ;
95
95
96
+ /**
97
+ * Loads the configuration file for the application, if it exists. This is either the
98
+ * user-specified properties file, or the spark-defaults.conf file under the Spark configuration
99
+ * directory.
100
+ */
96
101
protected Properties loadPropertiesFile () throws IOException {
97
102
Properties props = new Properties ();
98
103
File propsFile ;
99
104
if (propertiesFile != null ) {
100
105
propsFile = new File (propertiesFile );
101
106
checkArgument (propsFile .isFile (), "Invalid properties file '%s'." , propertiesFile );
102
107
} else {
103
- String confDir = getenv ("SPARK_CONF_DIR" );
104
- if (confDir == null ) {
105
- confDir = join (File .separator , getSparkHome (), "conf" );
106
- }
107
- propsFile = new File (confDir , "spark-defaults.conf" );
108
+ propsFile = new File (getConfDir (), DEFAULT_PROPERTIES_FILE );
108
109
}
109
110
110
111
if (propsFile .isFile ()) {
@@ -127,16 +128,16 @@ protected Properties loadPropertiesFile() throws IOException {
127
128
}
128
129
129
130
protected String getSparkHome () {
130
- String path = first (sparkHome , getenv ("SPARK_HOME" ));
131
+ String path = firstNonEmpty (sparkHome , getenv ("SPARK_HOME" ));
131
132
checkState (path != null ,
132
- "Spark home not found; set it explicitly or use the SPARK_HOME environment variable." );
133
+ "Spark home not found; set it explicitly or use the SPARK_HOME environment variable." );
133
134
return path ;
134
135
}
135
136
136
- protected List <String > createJavaCommand () throws IOException {
137
+ protected List <String > buildJavaCommand () throws IOException {
137
138
List <String > cmd = new ArrayList <String >();
138
139
if (javaHome == null ) {
139
- cmd .add (join (File .separator , System .getProperty ("java.home" ), ".." , " bin" , "java" ));
140
+ cmd .add (join (File .separator , System .getProperty ("java.home" ), "bin" , "java" ));
140
141
} else {
141
142
cmd .add (join (File .separator , javaHome , "bin" , "java" ));
142
143
}
@@ -186,12 +187,7 @@ protected List<String> buildClassPath(String appClassPath) throws IOException {
186
187
addToClassPath (cp , getenv ("SPARK_CLASSPATH" ));
187
188
addToClassPath (cp , appClassPath );
188
189
189
- String confDir = getenv ("SPARK_CONF_DIR" );
190
- if (!isEmpty (confDir )) {
191
- addToClassPath (cp , confDir );
192
- } else {
193
- addToClassPath (cp , join (File .separator , getSparkHome (), "conf" ));
194
- }
190
+ addToClassPath (cp , getConfDir ());
195
191
196
192
boolean prependClasses = !isEmpty (getenv ("SPARK_PREPEND_CLASSES" ));
197
193
boolean isTesting = "1" .equals (getenv ("SPARK_TESTING" ));
@@ -236,7 +232,7 @@ protected List<String> buildClassPath(String appClassPath) throws IOException {
236
232
} catch (IOException ioe ) {
237
233
if (ioe .getMessage ().indexOf ("invalid CEN header" ) > 0 ) {
238
234
System .err .println (
239
- "Loading Spark jar with '$JAR_CMD' failed.\n " +
235
+ "Loading Spark jar failed.\n " +
240
236
"This is likely because Spark was compiled with Java 7 and run\n " +
241
237
"with Java 6 (see SPARK-1703). Please use Java 7 to run Spark\n " +
242
238
"or build Spark with Java 6." );
@@ -279,6 +275,12 @@ protected List<String> buildClassPath(String appClassPath) throws IOException {
279
275
return cp ;
280
276
}
281
277
278
+ /**
279
+ * Adds entries to the classpath.
280
+ *
281
+ * @param cp List where to appended the new classpath entries.
282
+ * @param entries New classpath entries (separated by File.pathSeparator).
283
+ */
282
284
private void addToClassPath (List <String > cp , String entries ) {
283
285
if (isEmpty (entries )) {
284
286
return ;
@@ -317,7 +319,14 @@ protected String getScalaVersion() {
317
319
throw new IllegalStateException ("Should not reach here." );
318
320
}
319
321
322
+ protected List <String > prepareForOs (List <String > cmd , String libPath ) {
323
+ return prepareForOs (cmd , libPath , Collections .<String , String >emptyMap ());
324
+ }
325
+
320
326
/**
327
+ * Prepare the command for execution under the current OS, setting the passed environment
328
+ * variables.
329
+ *
321
330
* Which OS is running defines two things:
322
331
* - the name of the environment variable used to define the lookup path for native libs
323
332
* - how to execute the command in general.
@@ -329,7 +338,8 @@ protected String getScalaVersion() {
329
338
*
330
339
* For Win32, see {@link #prepareForWindows(List<String>,String)}.
331
340
*/
332
- protected List <String > prepareForOs (List <String > cmd ,
341
+ protected List <String > prepareForOs (
342
+ List <String > cmd ,
333
343
String libPath ,
334
344
Map <String , String > env ) {
335
345
@@ -365,128 +375,6 @@ protected List<String> prepareForOs(List<String> cmd,
365
375
return newCmd ;
366
376
}
367
377
368
- protected String shQuote (String s ) {
369
- StringBuilder quoted = new StringBuilder ();
370
- boolean hasWhitespace = false ;
371
- for (int i = 0 ; i < s .length (); i ++) {
372
- if (Character .isWhitespace (s .codePointAt (i ))) {
373
- quoted .append ('"' );
374
- hasWhitespace = true ;
375
- break ;
376
- }
377
- }
378
-
379
- for (int i = 0 ; i < s .length (); i ++) {
380
- int cp = s .codePointAt (i );
381
- switch (cp ) {
382
- case '\'' :
383
- if (hasWhitespace ) {
384
- quoted .appendCodePoint (cp );
385
- break ;
386
- }
387
- case '"' :
388
- case '\\' :
389
- quoted .append ('\\' );
390
- // Fall through.
391
- default :
392
- if (Character .isWhitespace (cp )) {
393
- hasWhitespace =true ;
394
- }
395
- quoted .appendCodePoint (cp );
396
- }
397
- }
398
- if (hasWhitespace ) {
399
- quoted .append ('"' );
400
- }
401
- return quoted .toString ();
402
- }
403
-
404
- // Visible for testing.
405
- List <String > parseOptionString (String s ) {
406
- List <String > opts = new ArrayList <String >();
407
- StringBuilder opt = new StringBuilder ();
408
- boolean inOpt = false ;
409
- boolean inSingleQuote = false ;
410
- boolean inDoubleQuote = false ;
411
- boolean escapeNext = false ;
412
- boolean hasData = false ;
413
-
414
- for (int i = 0 ; i < s .length (); i ++) {
415
- int c = s .codePointAt (i );
416
- if (escapeNext ) {
417
- if (!inOpt ) {
418
- inOpt = true ;
419
- }
420
- opt .appendCodePoint (c );
421
- escapeNext = false ;
422
- } else if (inOpt ) {
423
- switch (c ) {
424
- case '\\' :
425
- if (inSingleQuote ) {
426
- opt .appendCodePoint (c );
427
- } else {
428
- escapeNext = true ;
429
- }
430
- break ;
431
- case '\'' :
432
- if (inDoubleQuote ) {
433
- opt .appendCodePoint (c );
434
- } else {
435
- inSingleQuote = !inSingleQuote ;
436
- }
437
- break ;
438
- case '"' :
439
- if (inSingleQuote ) {
440
- opt .appendCodePoint (c );
441
- } else {
442
- inDoubleQuote = !inDoubleQuote ;
443
- }
444
- break ;
445
- default :
446
- if (inSingleQuote || inDoubleQuote || !Character .isWhitespace (c )) {
447
- opt .appendCodePoint (c );
448
- } else {
449
- finishOpt (opts , opt );
450
- inOpt = false ;
451
- hasData = false ;
452
- }
453
- }
454
- } else {
455
- switch (c ) {
456
- case '\'' :
457
- inSingleQuote = true ;
458
- inOpt = true ;
459
- hasData = true ;
460
- break ;
461
- case '"' :
462
- inDoubleQuote = true ;
463
- inOpt = true ;
464
- hasData = true ;
465
- break ;
466
- case '\\' :
467
- escapeNext = true ;
468
- break ;
469
- default :
470
- if (!Character .isWhitespace (c )) {
471
- inOpt = true ;
472
- opt .appendCodePoint (c );
473
- }
474
- }
475
- }
476
- }
477
-
478
- checkArgument (!inSingleQuote && !inDoubleQuote && !escapeNext , "Invalid option string: %s" , s );
479
- if (opt .length () > 0 || hasData ) {
480
- opts .add (opt .toString ());
481
- }
482
- return opts ;
483
- }
484
-
485
- private void finishOpt (List <String > opts , StringBuilder opt ) {
486
- opts .add (opt .toString ());
487
- opt .setLength (0 );
488
- }
489
-
490
378
private String findAssembly (String scalaVersion ) {
491
379
String sparkHome = getSparkHome ();
492
380
File libdir ;
@@ -512,7 +400,12 @@ public boolean accept(File file) {
512
400
}
513
401
514
402
private String getenv (String key ) {
515
- return first (env != null ? env .get (key ) : null , System .getenv (key ));
403
+ return firstNonEmpty (env != null ? env .get (key ) : null , System .getenv (key ));
404
+ }
405
+
406
+ private String getConfDir () {
407
+ String confDir = getenv ("SPARK_CONF_DIR" );
408
+ return confDir != null ? confDir : join (File .separator , getSparkHome (), "conf" );
516
409
}
517
410
518
411
/**
@@ -526,43 +419,48 @@ private String getenv(String key) {
526
419
* - Quote all arguments so that spaces are handled as expected. Quotes within arguments are
527
420
* "double quoted" (which is batch for escaping a quote). This page has more details about
528
421
* quoting and other batch script fun stuff: http://ss64.com/nt/syntax-esc.html
422
+ *
423
+ * The command is executed using "cmd /c" and formatted in a single line, since that's the
424
+ * easiest way to consume this from a batch script (see spark-class2.cmd).
529
425
*/
530
- private List <String > prepareForWindows (List <String > cmd ,
426
+ private List <String > prepareForWindows (
427
+ List <String > cmd ,
531
428
String libPath ,
532
429
Map <String , String > env ) {
533
430
StringBuilder cmdline = new StringBuilder ("cmd /c \" " );
534
431
if (libPath != null ) {
535
432
cmdline .append ("set PATH=%PATH%;" ).append (libPath ).append (" &&" );
536
433
}
537
434
for (Map .Entry <String , String > e : env .entrySet ()) {
435
+ if (cmdline .length () > 0 ) {
436
+ cmdline .append (" " );
437
+ }
538
438
cmdline .append (String .format ("set %s=%s" , e .getKey (), e .getValue ()));
539
439
cmdline .append (" &&" );
540
440
}
541
441
for (String arg : cmd ) {
542
442
if (cmdline .length () > 0 ) {
543
443
cmdline .append (" " );
544
444
}
545
- cmdline .append (quote (arg ));
445
+ cmdline .append (quoteForBatchScript (arg ));
546
446
}
547
447
cmdline .append ("\" " );
548
448
return Arrays .asList (cmdline .toString ());
549
449
}
550
450
551
451
/**
552
- * Quoting arguments that don't need quoting in Windows seems to cause weird issues. So only
553
- * quote arguments when there is whitespace in them .
452
+ * Quote a command argument for a command to be run by a Windows batch script, if the argument
453
+ * needs quoting. Arguments only seem to need quotes in batch scripts if they have whitespace .
554
454
*/
555
- private boolean needsQuoting (String arg ) {
455
+ private String quoteForBatchScript (String arg ) {
456
+ boolean needsQuotes = false ;
556
457
for (int i = 0 ; i < arg .length (); i ++) {
557
458
if (Character .isWhitespace (arg .codePointAt (i ))) {
558
- return true ;
459
+ needsQuotes = true ;
460
+ break ;
559
461
}
560
462
}
561
- return false ;
562
- }
563
-
564
- private String quote (String arg ) {
565
- if (!needsQuoting (arg )) {
463
+ if (!needsQuotes ) {
566
464
return arg ;
567
465
}
568
466
StringBuilder quoted = new StringBuilder ();
@@ -578,23 +476,4 @@ private String quote(String arg) {
578
476
return quoted .toString ();
579
477
}
580
478
581
- // Visible for testing.
582
- String getLibPathEnvName () {
583
- if (isWindows ()) {
584
- return "PATH" ;
585
- }
586
-
587
- String os = System .getProperty ("os.name" );
588
- if (os .startsWith ("Mac OS X" )) {
589
- return "DYLD_LIBRARY_PATH" ;
590
- } else {
591
- return "LD_LIBRARY_PATH" ;
592
- }
593
- }
594
-
595
- protected boolean isWindows () {
596
- String os = System .getProperty ("os.name" );
597
- return os .startsWith ("Windows" );
598
- }
599
-
600
479
}
0 commit comments