@@ -23,6 +23,7 @@ import java.nio.ByteBuffer
2323
2424import  scala .collection .JavaConversions ._ 
2525import  scala .collection .mutable .{HashMap , ListBuffer , Map }
26+ import  scala .util .{Try , Success , Failure }
2627
2728import  org .apache .hadoop .conf .Configuration 
2829import  org .apache .hadoop .fs ._ 
@@ -378,7 +379,7 @@ trait ClientBase extends Logging {
378379  }
379380}
380381
381- object  ClientBase  {
382+ object  ClientBase  extends   Logging   {
382383  val  SPARK_JAR :  String  =  " __spark__.jar" 
383384  val  APP_JAR :  String  =  " __app__.jar" 
384385  val  LOG4J_PROP :  String  =  " log4j.properties" 
@@ -388,58 +389,78 @@ object ClientBase {
388389
389390  def  getSparkJar  =  sys.env.get(" SPARK_JAR" SparkContext .jarOfClass(this .getClass).head)
390391
391-   //  Based on code from org.apache.hadoop.mapreduce.v2.util.MRApps
392-   def  populateHadoopClasspath (conf : Configuration , env : HashMap [String , String ]) {
393-     val  classpathEntries  =  Option (conf.getStrings(
394-       YarnConfiguration .YARN_APPLICATION_CLASSPATH )).getOrElse(
395-         getDefaultYarnApplicationClasspath())
396-     if  (classpathEntries !=  null ) {
397-       for  (c <-  classpathEntries) {
398-         YarnSparkHadoopUtil .addToEnvironment(env, Environment .CLASSPATH .name, c.trim,
399-           File .pathSeparator)
400-       }
392+   def  populateHadoopClasspath (conf : Configuration , env : HashMap [String , String ]) =  {
393+     val  classPathElementsToAdd  =  getYarnAppClasspath(conf) ++  getMRAppClasspath(conf)
394+     for  (c <-  classPathElementsToAdd.flatten) {
395+       YarnSparkHadoopUtil .addToEnvironment(
396+         env,
397+         Environment .CLASSPATH .name,
398+         c.trim,
399+         File .pathSeparator)
401400    }
401+     classPathElementsToAdd
402+   }
402403
403-     val  mrClasspathEntries  =  Option (conf.getStrings(
404-       " mapreduce.application.classpath" 
405-         getDefaultMRApplicationClasspath())
406-     if  (mrClasspathEntries !=  null ) {
407-       for  (c <-  mrClasspathEntries) {
408-         YarnSparkHadoopUtil .addToEnvironment(env, Environment .CLASSPATH .name, c.trim,
409-           File .pathSeparator)
410-       }
411-     }
404+   private  def  getYarnAppClasspath (conf : Configuration ):  Option [Seq [String ]] = 
405+     Option (conf.getStrings(YarnConfiguration .YARN_APPLICATION_CLASSPATH )) match  {
406+       case  Some (s) =>  Some (s.toSeq)
407+       case  None  =>  getDefaultYarnApplicationClasspath
412408  }
413409
414-   def  getDefaultYarnApplicationClasspath ():  Array [String ] =  {
415-     try  {
416-       val  field  =  classOf [MRJobConfig ].getField(" DEFAULT_YARN_APPLICATION_CLASSPATH" 
417-       field.get(null ).asInstanceOf [Array [String ]]
418-     } catch  {
419-       case  err : NoSuchFieldError  =>  null 
420-       case  err : NoSuchFieldException  =>  null 
410+   private  def  getMRAppClasspath (conf : Configuration ):  Option [Seq [String ]] = 
411+     Option (conf.getStrings(" mapreduce.application.classpath" match  {
412+       case  Some (s) =>  Some (s.toSeq)
413+       case  None  =>  getDefaultMRApplicationClasspath
414+     }
415+ 
416+   def  getDefaultYarnApplicationClasspath :  Option [Seq [String ]] =  {
417+     val  triedDefault  =  Try [Seq [String ]] {
418+       val  field  =  classOf [YarnConfiguration ].getField(" DEFAULT_YARN_APPLICATION_CLASSPATH" 
419+       val  value  =  field.get(null ).asInstanceOf [Array [String ]]
420+       value.toSeq
421+     } recoverWith {
422+       case  e : NoSuchFieldException  =>  Success (Seq .empty[String ])
421423    }
424+ 
425+     triedDefault match  {
426+       case  f : Failure [_] => 
427+         logError(" Unable to obtain the default YARN Application classpath." 
428+       case  s : Success [_] => 
429+         logDebug(s " Using the default YARN application classpath:  ${s.get.mkString(" ," " )
430+     }
431+ 
432+     triedDefault.toOption
422433  }
423434
424435  /**  
425436   * In Hadoop 0.23, the MR application classpath comes with the YARN application 
426437   * classpath.  In Hadoop 2.0, it's an array of Strings, and in 2.2+ it's a String. 
427438   * So we need to use reflection to retrieve it. 
428439   */  
429-   def  getDefaultMRApplicationClasspath () :   Array [ String ] =  {
430-     try  {
440+   def  getDefaultMRApplicationClasspath :   Option [ Seq [ String ] ] =  {
441+     val   triedDefault   =   Try [ Seq [ String ]]  {
431442      val  field  =  classOf [MRJobConfig ].getField(" DEFAULT_MAPREDUCE_APPLICATION_CLASSPATH" 
432-       if  (field.getType ==  classOf [String ]) {
433-         StringUtils .getStrings(field.get(null ).asInstanceOf [String ])
443+       val   value   =   if  (field.getType ==  classOf [String ]) {
444+         StringUtils .getStrings(field.get(null ).asInstanceOf [String ]).toArray 
434445      } else  {
435446        field.get(null ).asInstanceOf [Array [String ]]
436447      }
437-     }  catch  { 
438-        case   err :  NoSuchFieldError   =>   null 
439-       case  err : NoSuchFieldException  =>  null 
448+       value.toSeq 
449+     } recoverWith { 
450+       case  e : NoSuchFieldException  =>  Success ( Seq .empty[ String ]) 
440451    }
452+ 
453+     triedDefault match  {
454+       case  f : Failure [_] => 
455+         logError(" Unable to obtain the default MR Application classpath." 
456+       case  s : Success [_] => 
457+         logDebug(s " Using the default MR application classpath:  ${s.get.mkString(" ," " )
458+     }
459+ 
460+     triedDefault.toOption
441461  }
442462
463+ 
443464  /**  
444465   * Returns the java command line argument for setting up log4j. If there is a log4j.properties 
445466   * in the given local resources, it is used, otherwise the SPARK_LOG4J_CONF environment variable 
0 commit comments