/*
* Copyright 2017-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.jvm.java;
import com.facebook.buck.model.Either;
import com.facebook.buck.rules.RuleKeyAppendable;
import com.facebook.buck.rules.RuleKeyObjectSink;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.buck.util.immutables.BuckStyleImmutable;
import java.nio.file.Path;
import java.util.Optional;
import org.immutables.value.Value;
@Value.Immutable
@BuckStyleImmutable
abstract class AbstractJavacSpec implements RuleKeyAppendable {
public static final String COM_SUN_TOOLS_JAVAC_API_JAVAC_TOOL =
"com.sun.tools.javac.api.JavacTool";
protected abstract Optional<Either<BuiltInJavac, SourcePath>> getCompiler();
protected abstract Optional<Either<Path, SourcePath>> getJavacPath();
protected abstract Optional<SourcePath> getJavacJarPath();
protected abstract Optional<String> getCompilerClassName();
@Value.Lazy
public JavacProvider getJavacProvider() {
if (getCompiler().isPresent() && getCompiler().get().isRight()) {
return new ExternalOrJarBackedJavacProvider(
getCompiler().get().getRight(),
// compiler_class_name has no effect when compiler is specified
COM_SUN_TOOLS_JAVAC_API_JAVAC_TOOL);
}
String compilerClassName = getCompilerClassName().orElse(COM_SUN_TOOLS_JAVAC_API_JAVAC_TOOL);
final Javac.Source javacSource = getJavacSource();
final Javac.Location javacLocation = getJavacLocation();
switch (javacSource) {
case EXTERNAL:
return new ConstantJavacProvider(ExternalJavac.createJavac(getJavacPath().get()));
case JAR:
return new JarBackedJavacProvider(
getJavacJarPath().get(), compilerClassName, javacLocation);
case JDK:
switch (javacLocation) {
case IN_PROCESS:
return new ConstantJavacProvider(new JdkProvidedInMemoryJavac());
case OUT_OF_PROCESS:
return new ConstantJavacProvider(new OutOfProcessJdkProvidedInMemoryJavac());
}
break;
}
throw new AssertionError(
"Unknown javac source/javac location pair: " + javacSource + "/" + javacLocation);
}
public Javac.Source getJavacSource() {
if (getJavacPath().isPresent() && getJavacJarPath().isPresent()) {
throw new HumanReadableException("Cannot set both javac and javacjar");
}
if (getJavacPath().isPresent()) {
return Javac.Source.EXTERNAL;
} else if (getJavacJarPath().isPresent()) {
return Javac.Source.JAR;
} else {
return Javac.Source.JDK;
}
}
@Value.Default
public Javac.Location getJavacLocation() {
return Javac.Location.IN_PROCESS;
}
@Override
public void appendToRuleKey(RuleKeyObjectSink sink) {
getJavacProvider().appendToRuleKey(sink);
}
}