/**
 * Copyright (C) 2014 Microsoft Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.microsoft.reef.runtime.local;

import com.microsoft.reef.runtime.common.files.RuntimeClasspathProvider;
import com.microsoft.reef.util.Optional;

import javax.inject.Inject;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.logging.Level;

/**
 * RuntimeClasspathProvider for the local runtime.
 */
public final class LocalClasspathProvider implements RuntimeClasspathProvider {
  private static final Level CLASSPATH_LOG_LEVEL = Level.FINEST;

  private final List<String> classPathSuffix;

  @Inject
  LocalClasspathProvider() {
    this.classPathSuffix = Collections.unmodifiableList(new ArrayList<>(getFilteredClasspath()));
  }

  @Override
  public List<String> getDriverClasspathPrefix() {
    return Collections.emptyList();
  }

  @Override
  public List<String> getDriverClasspathSuffix() {
    return this.classPathSuffix;
  }

  @Override
  public List<String> getEvaluatorClasspathPrefix() {
    return Collections.emptyList();
  }

  @Override
  public List<String> getEvaluatorClasspathSuffix() {
    return this.classPathSuffix;
  }


  private static LinkedHashSet<String> getFilteredClasspath() {
    final LinkedHashSet<String> result = new LinkedHashSet<>();
    final Optional<Path> javaHome = getJavaHome();

    if (javaHome.isPresent()) {
      final Path javaHomePath = javaHome.get();
      for (final Path classPathEntry : getClasspath()) {
        if (!classPathEntry.startsWith(javaHomePath)) {
          result.add(classPathEntry.toString());
        }
      }
    } else {
      for (final Path classPathEntry : getClasspath()) {
        result.add(classPathEntry.toString());
      }
    }
    return result;
  }

  private static Optional<Path> getJavaHome() {
    final Optional<String> javaHome = getEnv("JAVA_HOME");

    if (javaHome.isPresent()) {
      final File javaHomeFile = new File(javaHome.get());
      if (javaHomeFile.exists()) {
        return Optional.of(javaHomeFile.toPath());
      }
    }
    return Optional.empty();
  }

  private static Optional<String> getEnv(final String envName) {
    return Optional.ofNullable(System.getenv(envName));
  }

  private static LinkedHashSet<Path> getClasspath() {
    final LinkedHashSet<Path> result = new LinkedHashSet<>();
    for (final String classPathEntry : System.getProperty("java.class.path").split(File.pathSeparator)) {
      final File file = new File(classPathEntry);
      if (file.exists()) {
        result.add(file.toPath());
      }
    }
    return result;
  }

}

@@ -957,40 +957,8 @@
 ist;
-%0Aimport java.util.logging.Level;
 %0A%0A/*
@@ -1010,16 +1010,218 @@
 untime.%0A
+ * %3Cp/%3E%0A * The prefix for the local runtime is empty, the suffix is the classpath of the current JVM. That classpath is filtered%0A * to not contain subfolders of JAVA_HOME. Also, duplicates are removed.%0A
  */%0Apubl
@@ -1300,74 +1300,8 @@
 r %7B%0A
-  private static final Level CLASSPATH_LOG_LEVEL = Level.FINEST;%0A%0A
   pr
@@ -1902,16 +1902,141 @@
 ;%0A  %7D%0A%0A%0A
+  /**%0A   * @return the classpath filtered by entries in subfolders of JAVA_HOME are removed, so are duplicate entries.%0A   */%0A
   privat
@@ -2413,32 +2413,53 @@
      result.add(
+toAbsolutePathString(
 classPathEntry.t
@@ -2452,34 +2452,24 @@
 assPathEntry
-.toString(
 ));%0A        
@@ -2567,16 +2567,37 @@
 ult.add(
+toAbsolutePathString(
 classPat
@@ -2606,18 +2606,8 @@
 ntry
-.toString(
 ));%0A
@@ -2640,24 +2640,114 @@
 esult;%0A  %7D%0A%0A
+  /**%0A   * @return the path to %22JAVA_HOME%22, if that is set. Optional.empty(), else.%0A   */%0A
   private st
@@ -3058,32 +3058,133 @@
 l.empty();%0A  %7D%0A%0A
+  /**%0A   * @param envName%0A   * @return the value of the environment variable, if there is one.%0A   */%0A
   private static
@@ -3293,16 +3293,99 @@
 );%0A  %7D%0A%0A
+  /**%0A   * @return the classpath of the current JVM. Duplicates are removed.%0A   */%0A
   privat
@@ -3748,10 +3748,246 @@
 t;%0A  %7D%0A%0A
+%0A  /**%0A   * Concerts the given path into a String representing the absolute path.%0A   *%0A   * @param path%0A   * @return%0A   */%0A  private static String toAbsolutePathString(final Path path) %7B%0A    return path.toAbsolutePath().toString();%0A  %7D%0A
 %7D%0A

Make classpath entries in LocalClassPathProvider absolute