com.facebook.buck.util.env.BuckClasspath.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.buck.util.env.BuckClasspath.java

Source

/*
 * Copyright 2015-present Facebook, Inc.
 *
 * 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.facebook.buck.util.env;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Streams;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Optional;
import java.util.stream.Stream;
import javax.annotation.Nullable;

/** Current process classpath. Set by buckd or by launcher script. */
public class BuckClasspath {

    public static final String ENV_VAR_NAME = "BUCK_CLASSPATH";
    public static final String BOOTSTRAP_ENV_VAR_NAME = "CLASSPATH";
    public static final String TEST_ENV_VAR_NAME = "BUCK_TEST_CLASSPATH_FILE";

    public static String getBuckClasspathFromEnvVarOrThrow() {
        String envVarValue = getBuckClasspathFromEnvVarOrNull();
        if (envVarValue == null) {
            throw new IllegalStateException(ENV_VAR_NAME + " env var is not set");
        }
        if (envVarValue.isEmpty()) {
            throw new IllegalStateException(ENV_VAR_NAME + " env var is set to empty string");
        }
        return envVarValue;
    }

    // BUCK_TEST_CLASSPATH_FILE is internal variable, no need to use EnvVariablesProvider
    @SuppressWarnings("PMD.BlacklistedSystemGetenv")
    private static Optional<String> getBuckTestClasspath() {
        String envVarValue = System.getenv(TEST_ENV_VAR_NAME);
        return Optional.ofNullable(envVarValue);
    }

    @Nullable
    // BUCK_CLASSPATH is internal variable, no need to use EnvVariablesProvider
    @SuppressWarnings("PMD.BlacklistedSystemGetenv")
    public static String getBuckClasspathFromEnvVarOrNull() {
        return System.getenv(ENV_VAR_NAME);
    }

    @Nullable
    // CLASSPATH is internal variable, no need to use EnvVariablesProvider
    @SuppressWarnings("PMD.BlacklistedSystemGetenv")
    public static String getBuckBootstrapClasspathFromEnvVarOrNull() {
        return System.getenv(BOOTSTRAP_ENV_VAR_NAME);
    }

    /** Returns Buck's "bootstrap" classpath. See ClassLoaderBootstrapper. */
    public static ImmutableList<Path> getBootstrapClasspath() throws IOException {
        String classpathFromEnv = getBuckBootstrapClasspathFromEnvVarOrNull();
        if (classpathFromEnv != null) {
            return Arrays.stream(classpathFromEnv.split(File.pathSeparator)).map(Paths::get)
                    .collect(ImmutableList.toImmutableList());
        }
        return getBuckClasspathForIntellij();
    }

    /** Returns Buck's classpath. */
    public static ImmutableList<Path> getClasspath() throws IOException {
        String classpathFromEnv = getBuckClasspathFromEnvVarOrNull();
        if (classpathFromEnv != null) {
            Optional<String> buckTestClasspath = getBuckTestClasspath();
            Stream<Path> classpathStream = Arrays.stream(classpathFromEnv.split(File.pathSeparator))
                    .map(Paths::get);
            if (buckTestClasspath.isPresent()) {
                classpathStream = Streams.concat(classpathStream,
                        readClasspaths(Paths.get(buckTestClasspath.get())).stream());
            }
            return classpathStream.collect(ImmutableList.toImmutableList());
        }
        return getBuckClasspathForIntellij();
    }

    /**
     * Return Buck's classpath when running under Intellij. Use getClasspath() or
     * getBootstrapClasspath() instead.
     */
    public static ImmutableList<Path> getBuckClasspathForIntellij() throws IOException {
        ImmutableList.Builder<Path> classPathEntries = ImmutableList.builder();
        Path productionPath = getClassLocation(BuckClasspath.class);
        classPathEntries.add(productionPath.toAbsolutePath());
        Path testPath = productionPath.resolve("../../test/buck").normalize();
        classPathEntries.add(testPath.toAbsolutePath());
        classPathEntries.addAll(filterAntClasspaths(readClasspaths(Paths.get("programs", "classpaths"))));
        classPathEntries.addAll(filterAntClasspaths(readClasspaths(Paths.get("programs", "test_classpaths"))));
        return classPathEntries.build();
    }

    private static Path getClassLocation(Class<?> clazz) {
        // Move along, no ridiculous hacks here...
        // Should be something like file:/Users/you/buck/intellij-out/classes/production/buck/
        URL myLocation = clazz.getProtectionDomain().getCodeSource().getLocation();
        Preconditions.checkState(myLocation.getProtocol().equals("file"),
                "Don't know how to launch the worker process from %s.", myLocation);

        // CLASSPATH entries need to be absolute paths, mostly because the JVM gets exec'd with
        // IntelliJ's CWD when running tests from there.
        try {
            return new File(myLocation.toURI()).toPath();
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }

    private static ImmutableList<Path> filterAntClasspaths(ImmutableList<Path> classpaths) {
        return classpaths.stream()
                .filter(path -> !path.startsWith("src") && !path.startsWith("src-gen") && !path.startsWith("build"))
                .collect(ImmutableList.toImmutableList());
    }

    private static ImmutableList<Path> readClasspaths(Path classpathsFile) throws IOException {
        return Files.readAllLines(classpathsFile).stream().filter(line -> !line.startsWith("#")).map(Paths::get)
                .map(Path::toAbsolutePath).collect(ImmutableList.toImmutableList());
    }
}