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

com.google.cloud.tools.opensource.classpath.LinkageCheckerArguments Maven / Gradle / Ivy

/*
 * Copyright 2018 Google LLC.
 *
 * 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.google.cloud.tools.opensource.classpath;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableList.toImmutableList;

import com.google.cloud.tools.opensource.dependencies.RepositoryUtility;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.eclipse.aether.RepositoryException;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;

/**
 * Option for {@link LinkageChecker}. To construct an input class path, the checker requires
 * exactly one of the following types of input:
 *
 * 
    *
  • {@code bom}: a Maven BOM specified by its Maven coordinates *
  • {@code artifacts}: list of Maven artifacts specified by their Maven coordinates *
  • {@code jarFiles}: list of jar files in the filesystem *
* * @see * Linkage Checker: Input */ final class LinkageCheckerArguments { private static final Options options = configureOptions(); private static final HelpFormatter helpFormatter = new HelpFormatter(); private final CommandLine commandLine; private ImmutableList cachedInputClasspath; private ImmutableList cachedArtifacts; private final ImmutableList extraMavenRepositoryUrls; private final boolean addMavenCentral; private LinkageCheckerArguments(CommandLine commandLine) { this.commandLine = checkNotNull(commandLine); this.extraMavenRepositoryUrls = commandLine.hasOption("m") ? ImmutableList.copyOf(commandLine.getOptionValues("m")) : ImmutableList.of(); // this may throw IllegalArgumentException upon validating the syntax extraMavenRepositoryUrls.forEach(RepositoryUtility::mavenRepositoryFromUrl); this.addMavenCentral = !commandLine.hasOption("nm"); } static LinkageCheckerArguments readCommandLine(String... arguments) throws ParseException { // TODO is this reentrant? Can we reuse it? // https://issues.apache.org/jira/browse/CLI-291 CommandLineParser parser = new DefaultParser(); try { return new LinkageCheckerArguments(parser.parse(options, arguments)); } catch (IllegalArgumentException ex) { throw new ParseException("Invalid URL syntax in Maven repository URL"); } catch (ParseException ex) { helpFormatter.printHelp("LinkageChecker", options); throw ex; } } private static Options configureOptions() { Options options = new Options(); OptionGroup inputGroup = new OptionGroup(); inputGroup.setRequired(true); Option bomOption = Option.builder("b") .longOpt("bom") .hasArg() .desc("BOM to generate a class path, specified by its Maven coordinates") .build(); inputGroup.addOption(bomOption); Option artifactOption = Option.builder("a") .longOpt("artifacts") .hasArgs() .valueSeparator(',') .desc( "Maven coordinates for Maven artifacts (separated by ',') to generate a class path") .build(); inputGroup.addOption(artifactOption); Option jarOption = Option.builder("j") .longOpt("jars") .hasArgs() .valueSeparator(',') .desc("Jar files (separated by ',') to generate a class path") .build(); inputGroup.addOption(jarOption); Option repositoryOption = Option.builder("m") .longOpt("maven-repositories") .hasArgs() .valueSeparator(',') .desc( "Maven repository URLs to search for dependencies. " + "The repositories are added to a repository list in order before " + "the default Maven Central (http://repo1.maven.org/maven2/).") .build(); options.addOption(repositoryOption); Option noMavenCentralOption = Option.builder("nm") .longOpt("no-maven-central") .hasArg(false) .desc( "Do not search Maven Central in addition to the repositories specified by -m. " + "Useful when Maven Central is inaccessible.") .build(); options.addOption(noMavenCentralOption); options.addOptionGroup(inputGroup); return options; } /** Returns a list of artifacts specified in the option of BOM or coordinates list. */ ImmutableList getArtifacts() throws RepositoryException { if (cachedArtifacts != null) { return cachedArtifacts; } if (commandLine.hasOption("b")) { String bomCoordinates = commandLine.getOptionValue("b"); DefaultArtifact bomArtifact = new DefaultArtifact(bomCoordinates); return cachedArtifacts = ImmutableList.copyOf(RepositoryUtility.readBom(bomArtifact)); } else if (commandLine.hasOption("a")) { // option 'a' String[] mavenCoordinatesOption = commandLine.getOptionValues("a"); return cachedArtifacts = Arrays.stream(mavenCoordinatesOption) .map(DefaultArtifact::new) .collect(toImmutableList()); } else { throw new IllegalArgumentException( "The arguments must have option 'a' or 'b' to list Maven artifacts"); } } /** * Returns a list of absolute paths to jar files for the option. The list includes dependencies if * BOM or Maven coordinates are specified in the option. */ ImmutableList getInputClasspath() throws RepositoryException { if (cachedInputClasspath != null) { // Avoid unnecessary dependency resolution, which Cloud OSS BOM takes around 4 seconds return cachedInputClasspath; } if (commandLine.hasOption("b") || commandLine.hasOption("a")) { List artifacts = getArtifacts(); cachedInputClasspath = ClassPathBuilder.artifactsToClasspath(artifacts); } else { // b, a, or j is specified in OptionGroup String[] jarFiles = commandLine.getOptionValues("j"); cachedInputClasspath = Arrays.stream(jarFiles) .map(name -> Paths.get(name).toAbsolutePath()) .collect(toImmutableList()); } return cachedInputClasspath; } /** Returns a set of jar files that hold entry point classes. */ ImmutableSet getEntryPointJars() throws RepositoryException { if (commandLine.hasOption("a") || commandLine.hasOption('b')) { // For an artifact list (or a BOM), the first elements in inputClasspath are the artifacts // specified the list, followed by their dependencies. int artifactCount = getArtifacts().size(); // For Maven artifact list (or a BOM), entry point classes are ones in the list return ImmutableSet.copyOf(getInputClasspath().subList(0, artifactCount)); } else { // For list of jar files, entry point classes are all classes in the files return ImmutableSet.copyOf(getInputClasspath()); } } ImmutableList getExtraMavenRepositoryUrls() { return extraMavenRepositoryUrls; } boolean getAddMavenCentral() { return addMavenCentral; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy