001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.reef.runtime.local; 020 021import org.apache.reef.runtime.common.files.RuntimeClasspathProvider; 022import org.apache.reef.util.Optional; 023 024import javax.inject.Inject; 025import java.io.File; 026import java.nio.file.Path; 027import java.util.ArrayList; 028import java.util.Collections; 029import java.util.LinkedHashSet; 030import java.util.List; 031 032/** 033 * RuntimeClasspathProvider for the local runtime. 034 * <p> 035 * The prefix for the local runtime is empty, the suffix is the classpath of the current JVM. That classpath is filtered 036 * to not contain subfolders of JAVA_HOME. Also, duplicates are removed. 037 */ 038public final class LocalClasspathProvider implements RuntimeClasspathProvider { 039 private final List<String> classPathSuffix; 040 041 @Inject 042 LocalClasspathProvider() { 043 this.classPathSuffix = Collections.unmodifiableList(new ArrayList<>(getFilteredClasspath())); 044 } 045 046 /** 047 * @return the classpath filtered by entries in subfolders of JAVA_HOME are removed, so are duplicate entries. 048 */ 049 private static LinkedHashSet<String> getFilteredClasspath() { 050 final LinkedHashSet<String> result = new LinkedHashSet<>(); 051 final Optional<Path> javaHome = getJavaHome(); 052 053 if (javaHome.isPresent()) { 054 final Path javaHomePath = javaHome.get(); 055 for (final Path classPathEntry : getClasspath()) { 056 if (!classPathEntry.startsWith(javaHomePath)) { 057 result.add(toAbsolutePathString(classPathEntry)); 058 } 059 } 060 } else { 061 for (final Path classPathEntry : getClasspath()) { 062 result.add(toAbsolutePathString(classPathEntry)); 063 } 064 } 065 return result; 066 } 067 068 /** 069 * @return the path to "JAVA_HOME", if that is set. Optional.empty(), else. 070 */ 071 private static Optional<Path> getJavaHome() { 072 final Optional<String> javaHome = getEnv("JAVA_HOME"); 073 074 if (javaHome.isPresent()) { 075 final File javaHomeFile = new File(javaHome.get()); 076 if (javaHomeFile.exists()) { 077 return Optional.of(javaHomeFile.toPath()); 078 } 079 } 080 return Optional.empty(); 081 } 082 083 /** 084 * @param envName 085 * @return the value of the environment variable, if there is one. 086 */ 087 private static Optional<String> getEnv(final String envName) { 088 return Optional.ofNullable(System.getenv(envName)); 089 } 090 091 /** 092 * @return the classpath of the current JVM. Duplicates are removed. 093 */ 094 private static LinkedHashSet<Path> getClasspath() { 095 final LinkedHashSet<Path> result = new LinkedHashSet<>(); 096 for (final String classPathEntry : System.getProperty("java.class.path").split(File.pathSeparator)) { 097 final File file = new File(classPathEntry); 098 if (file.exists()) { 099 result.add(file.toPath()); 100 } 101 } 102 return result; 103 } 104 105 /** 106 * Concerts the given path into a String representing the absolute path. 107 * 108 * @param path 109 * @return 110 */ 111 private static String toAbsolutePathString(final Path path) { 112 return path.toAbsolutePath().toString(); 113 } 114 115 @Override 116 public List<String> getDriverClasspathPrefix() { 117 return Collections.emptyList(); 118 } 119 120 @Override 121 public List<String> getDriverClasspathSuffix() { 122 return this.classPathSuffix; 123 } 124 125 @Override 126 public List<String> getEvaluatorClasspathPrefix() { 127 return Collections.emptyList(); 128 } 129 130 @Override 131 public List<String> getEvaluatorClasspathSuffix() { 132 return this.classPathSuffix; 133 } 134}