All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.terracotta.angela.common.TerracottaCommandLineEnvironment Maven / Gradle / Ivy

There is a newer version: 3.3.40
Show newest version
/*
 * Copyright Terracotta, Inc.
 * Copyright Super iPaaS Integration LLC, an IBM Company 2024
 *
 * 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 org.terracotta.angela.common;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terracotta.angela.common.util.JDK;
import org.terracotta.angela.common.util.JavaLocationResolver;
import org.terracotta.angela.common.util.OS;

import java.io.Serializable;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;

import static java.util.Arrays.asList;
import static java.util.Collections.emptySet;
import static java.util.Collections.unmodifiableSet;
import static java.util.Objects.requireNonNull;
import static org.terracotta.angela.common.AngelaProperties.JAVA_HOME;
import static org.terracotta.angela.common.AngelaProperties.JAVA_OPTS;
import static org.terracotta.angela.common.AngelaProperties.JAVA_RESOLVER;
import static org.terracotta.angela.common.AngelaProperties.JAVA_VENDOR;
import static org.terracotta.angela.common.AngelaProperties.JAVA_VERSION;

/**
 * Instances of this class are immutable.
 * 

* WARNING *

* This object goes sadly through a lot of ignite calls... * This is really error-prone because it represents a specific env for one host. * Only the Java args are relevant to be transferred remotely to spawn a new Ignite agent. */ public class TerracottaCommandLineEnvironment implements Serializable { private static final long serialVersionUID = 1L; private final static Logger LOGGER = LoggerFactory.getLogger(TerracottaCommandLineEnvironment.class); public static final TerracottaCommandLineEnvironment DEFAULT; static { Set opts = JAVA_OPTS.getValue().equals("") ? new LinkedHashSet<>() : new LinkedHashSet<>(Arrays.asList(JAVA_OPTS.getValue().split("\\s"))); opts.removeIf(s -> s.trim().isEmpty()); switch (JAVA_RESOLVER.getValue()) { case "toolchain": { String version = JAVA_VERSION.getValue(); // Important - Use a LinkedHashSet to preserve the order of preferred Java vendor Set vendors = JAVA_VENDOR.getValue() == null ? Collections.emptySet() : new LinkedHashSet<>(Arrays.asList(JAVA_VENDOR.getValue().split("[,\\s]"))); // Important - Use a LinkedHashSet to preserve the order of opts, as some opts are position-sensitive DEFAULT = new TerracottaCommandLineEnvironment(false, version, vendors, opts); break; } case "user": { DEFAULT = new TerracottaCommandLineEnvironment(true, null, emptySet(), opts); break; } default: throw new AssertionError("Unsupported value for '" + JAVA_RESOLVER.getPropertyName() + "': " + JAVA_RESOLVER.getValue()); } } private final boolean useJavaHome; private final String javaVersion; private final Set javaVendors; private final Set javaOpts; /** * Create a new instance that contains whatever is necessary to build a JVM command line, minus classpath and main class. * * @param javaVersion the java version specified in toolchains.xml, can be empty if any version will fit. * @param javaVendors a set of acceptable java vendors specified in toolchains.xml, can be empty if any vendor will fit. * @param javaOpts some command line arguments to give to the JVM, like -Xmx2G, -XX:Whatever or -Dsomething=abc. * Can be empty if no JVM argument is needed. */ private TerracottaCommandLineEnvironment(boolean useJavaHome, String javaVersion, Set javaVendors, Set javaOpts) { validate(useJavaHome, javaVersion, javaVendors, javaOpts); this.useJavaHome = useJavaHome; this.javaVersion = javaVersion; this.javaVendors = unmodifiableSet(new LinkedHashSet<>(javaVendors)); this.javaOpts = unmodifiableSet(new LinkedHashSet<>(javaOpts)); } private static void validate(boolean useJavaHome, String javaVersion, Set javaVendors, Set javaOpts) { requireNonNull(javaVendors); requireNonNull(javaOpts); if (javaOpts.stream().anyMatch(opt -> opt == null || opt.isEmpty())) { throw new IllegalArgumentException("None of the java opts can be null or empty"); } if (useJavaHome) { // user mode if (javaVersion != null) { throw new IllegalArgumentException("Java version must be null in user mode"); } if (!javaVendors.isEmpty()) { throw new IllegalArgumentException("Java vendors must be empty in user mode"); } } else { // toolchain mode if (javaVersion == null || javaVersion.trim().isEmpty()) { throw new IllegalArgumentException("Java version must be set"); } if (javaVendors.isEmpty()) { throw new IllegalArgumentException("Java vendor required"); } if (javaVendors.stream().anyMatch(vendor -> vendor == null || vendor.trim().isEmpty())) { throw new IllegalArgumentException("None of the java vendor can be null or empty"); } } } public boolean isToolchainBased() { return !useJavaHome; } public TerracottaCommandLineEnvironment withJavaVersion(String javaVersion) { return useJavaHome ? // resolver mode user => we do not have some vendors set, so use the default one withJava(javaVersion, JAVA_VENDOR.getDefaultValue()) : // resolver mode toolchain => we do have some vendors set => reuse them withJava(javaVersion, javaVendors.toArray(new String[0])); } public TerracottaCommandLineEnvironment withJavaVendors(String... javaVendors) { return useJavaHome ? // resolver mode user => we do not have version set, so use the default one withJava(JAVA_VERSION.getDefaultValue(), javaVendors) : // resolver mode toolchain => we do have version set => reuse it withJava(javaVersion, javaVendors); } public TerracottaCommandLineEnvironment withJava(String javaVersion, String... javaVendors) { return new TerracottaCommandLineEnvironment(false, javaVersion, new LinkedHashSet<>(asList(javaVendors)), javaOpts); } public TerracottaCommandLineEnvironment withJavaOpts(String... javaOpts) { return new TerracottaCommandLineEnvironment(useJavaHome, javaVersion, javaVendors, new LinkedHashSet<>(asList(javaOpts))); } public TerracottaCommandLineEnvironment withCurrentJavaHome() { return new TerracottaCommandLineEnvironment(true, null, emptySet(), javaOpts); } public Path getJava() { return getJavaHome().resolve("bin").resolve("java" + (OS.INSTANCE.isWindows() ? ".exe" : "")); } public Path getJavaHome() { if (useJavaHome) { return Paths.get(JAVA_HOME.getValue()); } else { List jdks = new JavaLocationResolver().resolveJavaLocations(getJavaVersion(), getJavaVendors(), true); if (jdks.size() > 1) { LOGGER.warn("Multiple matching java versions found: {} - using the 1st one", jdks); } // we can interpret the path since we are loading the toolchain file locally and accessing the jvm home locally (same machine) return Paths.get(jdks.get(0).getHome()); } } public String getJavaVersion() { return javaVersion; } public Set getJavaVendors() { return javaVendors; } public Set getJavaOpts() { return javaOpts; } public Map buildEnv(Map overrides) { LOGGER.debug("overrides={}", overrides); Map env = new HashMap<>(); Path javaHome = getJavaHome(); env.put("JAVA_HOME", javaHome.toString()); Set javaOpts = getJavaOpts(); if (!javaOpts.isEmpty()) { String joinedJavaOpts = String.join(" ", javaOpts); env.put("JAVA_OPTS", joinedJavaOpts); } for (Map.Entry entry : overrides.entrySet()) { if (entry.getValue() == null) { env.remove(entry.getKey()); // ability to clear an existing entry } else { env.put(entry.getKey(), entry.getValue()); } } Stream.of("JAVA_HOME", "JAVA_OPTS").forEach(key -> LOGGER.debug(" {} = {}", key, env.get(key))); return env; } @Override public String toString() { return "TerracottaCommandLineEnvironment{" + "javaVersion='" + javaVersion + '\'' + ", javaVendors=" + javaVendors + ", javaOpts=" + javaOpts + '}'; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy