mirror of https://github.com/apache/maven.git
[MNG-8332] Detach CLIng from deprecated Embedder (#1882)
Detach maven-cli from maven-embedder (deprecated). Basically, classes are copied from embedder to cli, while embedder points to old classes and cli to new classes. **One important exception is logging**: the classes are _moved_ to cli, and embedder modified to use those classes (and dependency reversed: embedder now depends on cli). Reason is Verifier, that still calls into "hack method" of deprecated MavenCli, and then without logging classes move would explode due casting. --- https://issues.apache.org/jira/browse/MNG-8332
This commit is contained in:
parent
37b8a62bd5
commit
4f79f2d876
|
@ -30,7 +30,7 @@ under the License.
|
|||
|
||||
<artifactId>maven-embedder</artifactId>
|
||||
|
||||
<name>Maven Embedder</name>
|
||||
<name>Maven Embedder (deprecated)</name>
|
||||
<description>Maven embeddable component, with CLI and logging support.</description>
|
||||
|
||||
<dependencies>
|
||||
|
@ -38,6 +38,10 @@ under the License.
|
|||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-api-cli</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-cli</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-settings</artifactId>
|
||||
|
@ -183,34 +187,6 @@ under the License.
|
|||
<groupId>org.eclipse.sisu</groupId>
|
||||
<artifactId>sisu-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.modello</groupId>
|
||||
<artifactId>modello-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<version>1.2.0</version>
|
||||
<models>
|
||||
<model>../../api/maven-api-cli/src/main/mdo/core-extensions.mdo</model>
|
||||
</models>
|
||||
<templates>
|
||||
<template>reader-stax.vm</template>
|
||||
<template>writer-stax.vm</template>
|
||||
</templates>
|
||||
<params>
|
||||
<param>packageModelV4=org.apache.maven.api.cli.extensions</param>
|
||||
<param>packageToolV4=org.apache.maven.cli.internal.extension.io</param>
|
||||
</params>
|
||||
<velocityBasedir>${project.basedir}/../../src/mdo</velocityBasedir>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>modello</id>
|
||||
<goals>
|
||||
<goal>velocity</goal>
|
||||
<goal>xsd</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.apache.maven.jline.MessageUtils;
|
|||
|
||||
/**
|
||||
*/
|
||||
@Deprecated
|
||||
public class CLIManager {
|
||||
public static final char ALTERNATE_POM_FILE = 'f';
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.slf4j.Logger;
|
|||
* Utility class used to report errors, statistics, application version info, etc.
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public final class CLIReportingUtils {
|
||||
// CHECKSTYLE_OFF: MagicNumber
|
||||
public static final long MB = 1024 * 1024;
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.List;
|
|||
/**
|
||||
* CleanArgument
|
||||
*/
|
||||
@Deprecated
|
||||
public class CleanArgument {
|
||||
public static String[] cleanArgs(String[] args) {
|
||||
try {
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.codehaus.plexus.classworlds.ClassWorld;
|
|||
/**
|
||||
* CliRequest
|
||||
*/
|
||||
@Deprecated
|
||||
public class CliRequest {
|
||||
String[] args;
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.apache.maven.internal.xml.XmlPlexusConfiguration;
|
|||
import org.apache.maven.model.v4.MavenTransformer;
|
||||
import org.codehaus.plexus.configuration.PlexusConfiguration;
|
||||
|
||||
@Deprecated
|
||||
public class ExtensionConfigurationModule implements Module {
|
||||
|
||||
private final CoreExtensionEntry extension;
|
||||
|
|
|
@ -70,16 +70,16 @@ import org.apache.maven.cli.configuration.SettingsXmlConfigurationProcessor;
|
|||
import org.apache.maven.cli.event.DefaultEventSpyContext;
|
||||
import org.apache.maven.cli.event.ExecutionEventLogger;
|
||||
import org.apache.maven.cli.internal.BootstrapCoreExtensionManager;
|
||||
import org.apache.maven.cli.internal.extension.io.CoreExtensionsStaxReader;
|
||||
import org.apache.maven.cli.logging.Slf4jConfiguration;
|
||||
import org.apache.maven.cli.logging.Slf4jConfigurationFactory;
|
||||
import org.apache.maven.cli.logging.Slf4jLoggerManager;
|
||||
import org.apache.maven.cli.logging.Slf4jStdoutLogger;
|
||||
import org.apache.maven.cli.props.MavenPropertiesLoader;
|
||||
import org.apache.maven.cli.transfer.ConsoleMavenTransferListener;
|
||||
import org.apache.maven.cli.transfer.QuietMavenTransferListener;
|
||||
import org.apache.maven.cli.transfer.SimplexTransferListener;
|
||||
import org.apache.maven.cli.transfer.Slf4jMavenTransferListener;
|
||||
import org.apache.maven.cling.internal.extension.io.CoreExtensionsStaxReader;
|
||||
import org.apache.maven.cling.logging.Slf4jConfiguration;
|
||||
import org.apache.maven.cling.logging.Slf4jConfigurationFactory;
|
||||
import org.apache.maven.cling.logging.Slf4jLoggerManager;
|
||||
import org.apache.maven.di.Injector;
|
||||
import org.apache.maven.eventspy.internal.EventSpyDispatcher;
|
||||
import org.apache.maven.exception.DefaultExceptionHandler;
|
||||
|
@ -141,6 +141,7 @@ import static org.apache.maven.cli.ResolveFile.resolveFile;
|
|||
|
||||
/**
|
||||
*/
|
||||
@Deprecated
|
||||
public class MavenCli {
|
||||
|
||||
public static final String MULTIMODULE_PROJECT_DIRECTORY = "maven.multiModuleProjectDirectory";
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.nio.file.Paths;
|
|||
/**
|
||||
* Resolve relative file path against the given base directory
|
||||
*/
|
||||
@Deprecated
|
||||
public class ResolveFile {
|
||||
public static File resolveFile(File file, String baseDirectory) {
|
||||
if (file == null) {
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.apache.maven.cli.CliRequest;
|
|||
/**
|
||||
* ConfigurationProcessor
|
||||
*/
|
||||
@Deprecated
|
||||
public interface ConfigurationProcessor {
|
||||
void process(CliRequest request) throws Exception;
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ import static org.apache.maven.cli.ResolveFile.resolveFile;
|
|||
*/
|
||||
@Named(SettingsXmlConfigurationProcessor.HINT)
|
||||
@Singleton
|
||||
@Deprecated
|
||||
public class SettingsXmlConfigurationProcessor implements ConfigurationProcessor {
|
||||
public static final String HINT = "settings";
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.apache.maven.eventspy.EventSpy;
|
|||
/**
|
||||
* DefaultEventSpyContext
|
||||
*/
|
||||
@Deprecated
|
||||
public class DefaultEventSpyContext implements EventSpy.Context {
|
||||
|
||||
private final Map<String, Object> data = new HashMap<>();
|
||||
|
|
|
@ -46,6 +46,7 @@ import static org.apache.maven.cli.CLIReportingUtils.formatTimestamp;
|
|||
* Logs execution events to logger, eventually user-supplied.
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public class ExecutionEventLogger extends AbstractExecutionListener {
|
||||
private static final int MAX_LOG_PREFIX_SIZE = 8; // "[ERROR] "
|
||||
private static final int PROJECT_STATUS_SUFFIX_SIZE = 20; // "SUCCESS [ 0.000 s]"
|
||||
|
|
|
@ -87,6 +87,7 @@ import org.slf4j.LoggerFactory;
|
|||
/**
|
||||
* BootstrapCoreExtensionManager
|
||||
*/
|
||||
@Deprecated
|
||||
@Named
|
||||
public class BootstrapCoreExtensionManager {
|
||||
public static final String STRATEGY_PARENT_FIRST = "parent-first";
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.apache.maven.api.cli.extensions.CoreExtension;
|
|||
* Exception occurring trying to resolve a plugin.
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public class ExtensionResolutionException extends Exception {
|
||||
|
||||
private final CoreExtension extension;
|
||||
|
|
|
@ -28,6 +28,7 @@ import static java.util.Objects.requireNonNull;
|
|||
/**
|
||||
* @since 3.1.0
|
||||
*/
|
||||
@Deprecated
|
||||
public class Slf4jStdoutLogger implements Logger {
|
||||
private static final String ERROR = "[ERROR] ";
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ import org.apache.maven.internal.impl.model.DefaultInterpolator;
|
|||
* Enhancement of the standard <code>Properties</code>
|
||||
* managing the maintain of comments, etc.
|
||||
*/
|
||||
@Deprecated
|
||||
public class MavenProperties extends AbstractMap<String, String> {
|
||||
|
||||
/** Constant for the supported comment characters.*/
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.function.Function;
|
|||
|
||||
import org.apache.maven.internal.impl.model.DefaultInterpolator;
|
||||
|
||||
@Deprecated
|
||||
public class MavenPropertiesLoader {
|
||||
|
||||
public static final String INCLUDES_PROPERTY = "${includes}"; // includes
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.eclipse.aether.transfer.TransferResource;
|
|||
/**
|
||||
* AbstractMavenTransferListener
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class AbstractMavenTransferListener extends AbstractTransferListener {
|
||||
public static final String STYLE = ".transfer:-faint";
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.eclipse.aether.transfer.TransferResource;
|
|||
* <p>
|
||||
* This listener is not thread-safe and should be wrapped in the {@link SimplexTransferListener} in a multi-threaded scenario.
|
||||
*/
|
||||
@Deprecated
|
||||
public class ConsoleMavenTransferListener extends AbstractMavenTransferListener {
|
||||
|
||||
private final Map<TransferResourceIdentifier, TransferResourceAndSize> transfers = new LinkedHashMap<>();
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.apache.maven.api.services.MessageBuilder;
|
|||
* @see <a
|
||||
* href="https://en.wikipedia.org/wiki/Octet_%28computing%29">https://en.wikipedia.org/wiki/Octet_(computing)</a>
|
||||
*/
|
||||
@Deprecated
|
||||
public class FileSizeFormat {
|
||||
public enum ScaleUnit {
|
||||
BYTE {
|
||||
|
|
|
@ -22,4 +22,5 @@ import org.eclipse.aether.transfer.AbstractTransferListener;
|
|||
|
||||
/**
|
||||
*/
|
||||
@Deprecated
|
||||
public class QuietMavenTransferListener extends AbstractTransferListener {}
|
||||
|
|
|
@ -42,6 +42,7 @@ import static java.util.Objects.requireNonNull;
|
|||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Deprecated
|
||||
public final class SimplexTransferListener extends AbstractTransferListener {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SimplexTransferListener.class);
|
||||
private static final int QUEUE_SIZE = 1024;
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.slf4j.LoggerFactory;
|
|||
/**
|
||||
* Slf4jMavenTransferListener
|
||||
*/
|
||||
@Deprecated
|
||||
public class Slf4jMavenTransferListener extends AbstractTransferListener {
|
||||
|
||||
protected final Logger out;
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.eclipse.aether.transfer.TransferResource;
|
|||
* The {@link TransferResource} is not immutable and does not implement {@code Objects#equals} and {@code Objects#hashCode} methods,
|
||||
* making it not very suitable for usage in collections.
|
||||
*/
|
||||
@Deprecated
|
||||
record TransferResourceIdentifier(String repositoryId, String repositoryUrl, String resourceName, @Nullable File file) {
|
||||
TransferResourceIdentifier(TransferResource resource) {
|
||||
this(resource.getRepositoryId(), resource.getRepositoryUrl(), resource.getResourceName(), resource.getFile());
|
||||
|
|
|
@ -53,6 +53,7 @@ import org.eclipse.sisu.inject.TypeArguments;
|
|||
*/
|
||||
@Singleton
|
||||
@Priority(10)
|
||||
@Deprecated
|
||||
public final class PlexusXmlBeanConverter implements PlexusBeanConverter {
|
||||
// ----------------------------------------------------------------------
|
||||
// Constants
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.ArrayList;
|
|||
* with maven-shared-utils, while Maven has migrated to JLine (into which Jansi has been merged
|
||||
* since JLine 3.25.0).
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("unused")
|
||||
public class Ansi implements Appendable {
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ under the License.
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-embedder</artifactId>
|
||||
<artifactId>maven-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
|
@ -78,6 +78,11 @@ under the License.
|
|||
<groupId>commons-cli</groupId>
|
||||
<artifactId>commons-cli</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
|
@ -98,6 +103,33 @@ under the License.
|
|||
<groupId>org.eclipse.sisu</groupId>
|
||||
<artifactId>sisu-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.modello</groupId>
|
||||
<artifactId>modello-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<version>1.2.0</version>
|
||||
<models>
|
||||
<model>../../api/maven-api-cli/src/main/mdo/core-extensions.mdo</model>
|
||||
</models>
|
||||
<templates>
|
||||
<template>reader-stax.vm</template>
|
||||
<template>writer-stax.vm</template>
|
||||
</templates>
|
||||
<params>
|
||||
<param>packageModelV4=org.apache.maven.api.cli.extensions</param>
|
||||
<param>packageToolV4=org.apache.maven.cling.internal.extension.io</param>
|
||||
</params>
|
||||
<velocityBasedir>${project.basedir}/../../src/mdo</velocityBasedir>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>modello</id>
|
||||
<goals>
|
||||
<goal>velocity</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
|
|
|
@ -0,0 +1,479 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cling.event;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.maven.api.services.MessageBuilder;
|
||||
import org.apache.maven.api.services.MessageBuilderFactory;
|
||||
import org.apache.maven.execution.AbstractExecutionListener;
|
||||
import org.apache.maven.execution.BuildFailure;
|
||||
import org.apache.maven.execution.BuildSuccess;
|
||||
import org.apache.maven.execution.BuildSummary;
|
||||
import org.apache.maven.execution.ExecutionEvent;
|
||||
import org.apache.maven.execution.MavenExecutionResult;
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.plugin.MojoExecution;
|
||||
import org.apache.maven.plugin.descriptor.MojoDescriptor;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.slf4j.ILoggerFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.apache.maven.cling.utils.CLIReportingUtils.formatDuration;
|
||||
import static org.apache.maven.cling.utils.CLIReportingUtils.formatTimestamp;
|
||||
|
||||
/**
|
||||
* Logs execution events to logger, eventually user-supplied.
|
||||
*
|
||||
*/
|
||||
public class ExecutionEventLogger extends AbstractExecutionListener {
|
||||
private static final int MAX_LOG_PREFIX_SIZE = 8; // "[ERROR] "
|
||||
private static final int PROJECT_STATUS_SUFFIX_SIZE = 20; // "SUCCESS [ 0.000 s]"
|
||||
private static final int MIN_TERMINAL_WIDTH = 60;
|
||||
private static final int DEFAULT_TERMINAL_WIDTH = 80;
|
||||
private static final int MAX_TERMINAL_WIDTH = 130;
|
||||
private static final int MAX_PADDED_BUILD_TIME_DURATION_LENGTH = 9;
|
||||
|
||||
private final MessageBuilderFactory messageBuilderFactory;
|
||||
private final Logger logger;
|
||||
private int terminalWidth;
|
||||
private int lineLength;
|
||||
private int maxProjectNameLength;
|
||||
private int totalProjects;
|
||||
private volatile int currentVisitedProjectCount;
|
||||
|
||||
public ExecutionEventLogger(MessageBuilderFactory messageBuilderFactory) {
|
||||
this(messageBuilderFactory, LoggerFactory.getLogger(ExecutionEventLogger.class));
|
||||
}
|
||||
|
||||
public ExecutionEventLogger(MessageBuilderFactory messageBuilderFactory, Logger logger) {
|
||||
this(messageBuilderFactory, logger, -1);
|
||||
}
|
||||
|
||||
public ExecutionEventLogger(MessageBuilderFactory messageBuilderFactory, Logger logger, int terminalWidth) {
|
||||
this.logger = Objects.requireNonNull(logger, "logger cannot be null");
|
||||
this.messageBuilderFactory = messageBuilderFactory;
|
||||
this.terminalWidth = terminalWidth;
|
||||
}
|
||||
|
||||
private static String chars(char c, int count) {
|
||||
return String.valueOf(c).repeat(Math.max(0, count));
|
||||
}
|
||||
|
||||
private void infoLine(char c) {
|
||||
infoMain(chars(c, lineLength));
|
||||
}
|
||||
|
||||
private void infoMain(String msg) {
|
||||
logger.info(builder().strong(msg).toString());
|
||||
}
|
||||
|
||||
private void init() {
|
||||
if (maxProjectNameLength == 0) {
|
||||
if (terminalWidth < 0) {
|
||||
terminalWidth = messageBuilderFactory.getTerminalWidth();
|
||||
}
|
||||
terminalWidth = Math.min(
|
||||
MAX_TERMINAL_WIDTH,
|
||||
Math.max(terminalWidth <= 0 ? DEFAULT_TERMINAL_WIDTH : terminalWidth, MIN_TERMINAL_WIDTH));
|
||||
lineLength = terminalWidth - MAX_LOG_PREFIX_SIZE;
|
||||
maxProjectNameLength = lineLength - PROJECT_STATUS_SUFFIX_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void projectDiscoveryStarted(ExecutionEvent event) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
init();
|
||||
logger.info("Scanning for projects...");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionStarted(ExecutionEvent event) {
|
||||
if (logger.isInfoEnabled() && event.getSession().getProjects().size() > 1) {
|
||||
init();
|
||||
infoLine('-');
|
||||
|
||||
infoMain("Reactor Build Order:");
|
||||
|
||||
logger.info("");
|
||||
|
||||
final List<MavenProject> projects = event.getSession().getProjects();
|
||||
for (MavenProject project : projects) {
|
||||
int len = lineLength
|
||||
- project.getName().length()
|
||||
- project.getPackaging().length()
|
||||
- 2;
|
||||
logger.info("{}{}[{}]", project.getName(), chars(' ', (len > 0) ? len : 1), project.getPackaging());
|
||||
}
|
||||
|
||||
final List<MavenProject> allProjects = event.getSession().getAllProjects();
|
||||
|
||||
currentVisitedProjectCount = allProjects.size() - projects.size();
|
||||
totalProjects = allProjects.size();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionEnded(ExecutionEvent event) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
init();
|
||||
if (event.getSession().getProjects().size() > 1) {
|
||||
logReactorSummary(event.getSession());
|
||||
}
|
||||
|
||||
ILoggerFactory iLoggerFactory = LoggerFactory.getILoggerFactory();
|
||||
|
||||
if (iLoggerFactory instanceof org.apache.maven.logging.api.LogLevelRecorder recorder
|
||||
&& recorder.hasReachedMaxLevel()) {
|
||||
event.getSession()
|
||||
.getResult()
|
||||
.addException(
|
||||
new Exception("Build failed due to log statements with a higher severity than allowed. "
|
||||
+ "Fix the logged issues or remove flag --fail-on-severity (-fos)."));
|
||||
}
|
||||
|
||||
logResult(event.getSession());
|
||||
|
||||
logStats(event.getSession());
|
||||
|
||||
infoLine('-');
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSingleVersionedReactor(MavenSession session) {
|
||||
boolean result = true;
|
||||
|
||||
MavenProject topProject = session.getTopLevelProject();
|
||||
List<MavenProject> sortedProjects = session.getProjectDependencyGraph().getSortedProjects();
|
||||
for (MavenProject mavenProject : sortedProjects) {
|
||||
if (!topProject.getVersion().equals(mavenProject.getVersion())) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void logReactorSummary(MavenSession session) {
|
||||
boolean isSingleVersion = isSingleVersionedReactor(session);
|
||||
|
||||
infoLine('-');
|
||||
|
||||
StringBuilder summary = new StringBuilder("Reactor Summary");
|
||||
if (isSingleVersion) {
|
||||
summary.append(" for ");
|
||||
summary.append(session.getTopLevelProject().getName());
|
||||
summary.append(" ");
|
||||
summary.append(session.getTopLevelProject().getVersion());
|
||||
}
|
||||
summary.append(":");
|
||||
infoMain(summary.toString());
|
||||
|
||||
logger.info("");
|
||||
|
||||
MavenExecutionResult result = session.getResult();
|
||||
|
||||
List<MavenProject> projects = session.getProjects();
|
||||
|
||||
StringBuilder buffer = new StringBuilder(128);
|
||||
|
||||
for (MavenProject project : projects) {
|
||||
buffer.append(project.getName());
|
||||
buffer.append(' ');
|
||||
|
||||
if (!isSingleVersion) {
|
||||
buffer.append(project.getVersion());
|
||||
buffer.append(' ');
|
||||
}
|
||||
|
||||
if (buffer.length() <= maxProjectNameLength) {
|
||||
while (buffer.length() < maxProjectNameLength) {
|
||||
buffer.append('.');
|
||||
}
|
||||
buffer.append(' ');
|
||||
}
|
||||
|
||||
BuildSummary buildSummary = result.getBuildSummary(project);
|
||||
|
||||
if (buildSummary == null) {
|
||||
buffer.append(builder().warning("SKIPPED"));
|
||||
} else if (buildSummary instanceof BuildSuccess) {
|
||||
buffer.append(builder().success("SUCCESS"));
|
||||
buffer.append(" [");
|
||||
String buildTimeDuration = formatDuration(buildSummary.getTime());
|
||||
int padSize = MAX_PADDED_BUILD_TIME_DURATION_LENGTH - buildTimeDuration.length();
|
||||
if (padSize > 0) {
|
||||
buffer.append(chars(' ', padSize));
|
||||
}
|
||||
buffer.append(buildTimeDuration);
|
||||
buffer.append(']');
|
||||
} else if (buildSummary instanceof BuildFailure) {
|
||||
buffer.append(builder().failure("FAILURE"));
|
||||
buffer.append(" [");
|
||||
String buildTimeDuration = formatDuration(buildSummary.getTime());
|
||||
int padSize = MAX_PADDED_BUILD_TIME_DURATION_LENGTH - buildTimeDuration.length();
|
||||
if (padSize > 0) {
|
||||
buffer.append(chars(' ', padSize));
|
||||
}
|
||||
buffer.append(buildTimeDuration);
|
||||
buffer.append(']');
|
||||
}
|
||||
|
||||
logger.info(buffer.toString());
|
||||
buffer.setLength(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void logResult(MavenSession session) {
|
||||
infoLine('-');
|
||||
MessageBuilder buffer = builder();
|
||||
|
||||
if (session.getResult().hasExceptions()) {
|
||||
buffer.failure("BUILD FAILURE");
|
||||
} else {
|
||||
buffer.success("BUILD SUCCESS");
|
||||
}
|
||||
logger.info(buffer.toString());
|
||||
}
|
||||
|
||||
private MessageBuilder builder() {
|
||||
return messageBuilderFactory.builder();
|
||||
}
|
||||
|
||||
private void logStats(MavenSession session) {
|
||||
infoLine('-');
|
||||
|
||||
long finish = System.currentTimeMillis();
|
||||
|
||||
long time = finish - session.getRequest().getStartTime().getTime();
|
||||
|
||||
String wallClock = session.getRequest().getDegreeOfConcurrency() > 1 ? " (Wall Clock)" : "";
|
||||
|
||||
logger.info("Total time: {}{}", formatDuration(time), wallClock);
|
||||
|
||||
logger.info("Finished at: {}", formatTimestamp(finish));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void projectSkipped(ExecutionEvent event) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
init();
|
||||
logger.info("");
|
||||
infoLine('-');
|
||||
String name = event.getProject().getName();
|
||||
infoMain("Skipping " + name);
|
||||
logger.info("{} was not built because a module it depends on failed to build.", name);
|
||||
|
||||
infoLine('-');
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void projectStarted(ExecutionEvent event) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
init();
|
||||
MavenProject project = event.getProject();
|
||||
|
||||
logger.info("");
|
||||
|
||||
// -------< groupId:artifactId >-------
|
||||
String projectKey = project.getGroupId() + ':' + project.getArtifactId();
|
||||
|
||||
final String preHeader = "--< ";
|
||||
final String postHeader = " >--";
|
||||
|
||||
final int headerLen = preHeader.length() + projectKey.length() + postHeader.length();
|
||||
|
||||
String prefix = chars('-', Math.max(0, (lineLength - headerLen) / 2)) + preHeader;
|
||||
|
||||
String suffix =
|
||||
postHeader + chars('-', Math.max(0, lineLength - headerLen - prefix.length() + preHeader.length()));
|
||||
|
||||
logger.info(
|
||||
builder().strong(prefix).project(projectKey).strong(suffix).toString());
|
||||
|
||||
// Building Project Name Version [i/n]
|
||||
String building = "Building " + event.getProject().getName() + " "
|
||||
+ event.getProject().getVersion();
|
||||
|
||||
if (totalProjects <= 1) {
|
||||
infoMain(building);
|
||||
} else {
|
||||
// display progress [i/n]
|
||||
int number;
|
||||
synchronized (this) {
|
||||
number = ++currentVisitedProjectCount;
|
||||
}
|
||||
String progress = " [" + number + '/' + totalProjects + ']';
|
||||
|
||||
int pad = lineLength - building.length() - progress.length();
|
||||
|
||||
infoMain(building + ((pad > 0) ? chars(' ', pad) : "") + progress);
|
||||
}
|
||||
|
||||
// path to pom.xml
|
||||
File currentPom = project.getFile();
|
||||
if (currentPom != null) {
|
||||
MavenSession session = event.getSession();
|
||||
Path current = currentPom.toPath().toAbsolutePath().normalize();
|
||||
Path topDirectory = session.getTopDirectory();
|
||||
if (topDirectory != null && current.startsWith(topDirectory)) {
|
||||
current = topDirectory.relativize(current);
|
||||
}
|
||||
logger.info(" from " + current);
|
||||
}
|
||||
|
||||
// ----------[ packaging ]----------
|
||||
prefix = chars('-', Math.max(0, (lineLength - project.getPackaging().length() - 4) / 2));
|
||||
suffix = chars('-', Math.max(0, lineLength - project.getPackaging().length() - 4 - prefix.length()));
|
||||
infoMain(prefix + "[ " + project.getPackaging() + " ]" + suffix);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mojoSkipped(ExecutionEvent event) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
init();
|
||||
logger.warn(
|
||||
"Goal '{}' requires online mode for execution but Maven is currently offline, skipping",
|
||||
event.getMojoExecution().getGoal());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>--- mojo-artifactId:version:goal (mojo-executionId) @ project-artifactId ---</pre>
|
||||
*/
|
||||
@Override
|
||||
public void mojoStarted(ExecutionEvent event) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
init();
|
||||
logger.info("");
|
||||
|
||||
MessageBuilder buffer = builder().strong("--- ");
|
||||
append(buffer, event.getMojoExecution());
|
||||
append(buffer, event.getProject());
|
||||
buffer.strong(" ---");
|
||||
|
||||
logger.info(buffer.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// CHECKSTYLE_OFF: LineLength
|
||||
/**
|
||||
* <pre>>>> mojo-artifactId:version:goal (mojo-executionId) > :forked-goal @ project-artifactId >>></pre>
|
||||
* <pre>>>> mojo-artifactId:version:goal (mojo-executionId) > [lifecycle]phase @ project-artifactId >>></pre>
|
||||
*/
|
||||
// CHECKSTYLE_ON: LineLength
|
||||
@Override
|
||||
public void forkStarted(ExecutionEvent event) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
init();
|
||||
logger.info("");
|
||||
|
||||
MessageBuilder buffer = builder().strong(">>> ");
|
||||
append(buffer, event.getMojoExecution());
|
||||
buffer.strong(" > ");
|
||||
appendForkInfo(buffer, event.getMojoExecution().getMojoDescriptor());
|
||||
append(buffer, event.getProject());
|
||||
buffer.strong(" >>>");
|
||||
|
||||
logger.info(buffer.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// CHECKSTYLE_OFF: LineLength
|
||||
/**
|
||||
* <pre><<< mojo-artifactId:version:goal (mojo-executionId) < :forked-goal @ project-artifactId <<<</pre>
|
||||
* <pre><<< mojo-artifactId:version:goal (mojo-executionId) < [lifecycle]phase @ project-artifactId <<<</pre>
|
||||
*/
|
||||
// CHECKSTYLE_ON: LineLength
|
||||
@Override
|
||||
public void forkSucceeded(ExecutionEvent event) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
init();
|
||||
logger.info("");
|
||||
|
||||
MessageBuilder buffer = builder().strong("<<< ");
|
||||
append(buffer, event.getMojoExecution());
|
||||
buffer.strong(" < ");
|
||||
appendForkInfo(buffer, event.getMojoExecution().getMojoDescriptor());
|
||||
append(buffer, event.getProject());
|
||||
buffer.strong(" <<<");
|
||||
|
||||
logger.info(buffer.toString());
|
||||
|
||||
logger.info("");
|
||||
}
|
||||
}
|
||||
|
||||
private void append(MessageBuilder buffer, MojoExecution me) {
|
||||
String prefix = me.getMojoDescriptor().getPluginDescriptor().getGoalPrefix();
|
||||
if (prefix == null || prefix.isEmpty()) {
|
||||
prefix = me.getGroupId() + ":" + me.getArtifactId();
|
||||
}
|
||||
buffer.mojo(prefix + ':' + me.getVersion() + ':' + me.getGoal());
|
||||
if (me.getExecutionId() != null) {
|
||||
buffer.a(' ').strong('(' + me.getExecutionId() + ')');
|
||||
}
|
||||
}
|
||||
|
||||
private void appendForkInfo(MessageBuilder buffer, MojoDescriptor md) {
|
||||
StringBuilder buff = new StringBuilder();
|
||||
if (md.getExecutePhase() != null && !md.getExecutePhase().isEmpty()) {
|
||||
// forked phase
|
||||
if (md.getExecuteLifecycle() != null && !md.getExecuteLifecycle().isEmpty()) {
|
||||
buff.append('[');
|
||||
buff.append(md.getExecuteLifecycle());
|
||||
buff.append(']');
|
||||
}
|
||||
buff.append(md.getExecutePhase());
|
||||
} else {
|
||||
// forked goal
|
||||
buff.append(':');
|
||||
buff.append(md.getExecuteGoal());
|
||||
}
|
||||
buffer.strong(buff.toString());
|
||||
}
|
||||
|
||||
private void append(MessageBuilder buffer, MavenProject project) {
|
||||
buffer.a(" @ ").project(project.getArtifactId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forkedProjectStarted(ExecutionEvent event) {
|
||||
if (logger.isInfoEnabled()
|
||||
&& event.getMojoExecution().getForkedExecutions().size() > 1) {
|
||||
init();
|
||||
logger.info("");
|
||||
infoLine('>');
|
||||
|
||||
infoMain("Forking " + event.getProject().getName() + " "
|
||||
+ event.getProject().getVersion());
|
||||
|
||||
infoLine('>');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cling.extensions;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.maven.RepositoryUtils;
|
||||
import org.apache.maven.api.Service;
|
||||
import org.apache.maven.api.Session;
|
||||
import org.apache.maven.api.cli.extensions.CoreExtension;
|
||||
import org.apache.maven.api.model.Plugin;
|
||||
import org.apache.maven.api.services.ArtifactCoordinatesFactory;
|
||||
import org.apache.maven.api.services.ArtifactManager;
|
||||
import org.apache.maven.api.services.ArtifactResolver;
|
||||
import org.apache.maven.api.services.Interpolator;
|
||||
import org.apache.maven.api.services.InterpolatorException;
|
||||
import org.apache.maven.api.services.RepositoryFactory;
|
||||
import org.apache.maven.api.services.VersionParser;
|
||||
import org.apache.maven.api.services.VersionRangeResolver;
|
||||
import org.apache.maven.execution.DefaultMavenExecutionResult;
|
||||
import org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.extension.internal.CoreExports;
|
||||
import org.apache.maven.extension.internal.CoreExtensionEntry;
|
||||
import org.apache.maven.internal.impl.DefaultArtifactCoordinatesFactory;
|
||||
import org.apache.maven.internal.impl.DefaultArtifactManager;
|
||||
import org.apache.maven.internal.impl.DefaultArtifactResolver;
|
||||
import org.apache.maven.internal.impl.DefaultModelVersionParser;
|
||||
import org.apache.maven.internal.impl.DefaultRepositoryFactory;
|
||||
import org.apache.maven.internal.impl.DefaultSession;
|
||||
import org.apache.maven.internal.impl.DefaultVersionParser;
|
||||
import org.apache.maven.internal.impl.DefaultVersionRangeResolver;
|
||||
import org.apache.maven.internal.impl.InternalSession;
|
||||
import org.apache.maven.internal.impl.model.DefaultInterpolator;
|
||||
import org.apache.maven.plugin.PluginResolutionException;
|
||||
import org.apache.maven.plugin.internal.DefaultPluginDependenciesResolver;
|
||||
import org.apache.maven.resolver.MavenChainedWorkspaceReader;
|
||||
import org.apache.maven.resolver.RepositorySystemSessionFactory;
|
||||
import org.codehaus.plexus.DefaultPlexusContainer;
|
||||
import org.codehaus.plexus.PlexusContainer;
|
||||
import org.codehaus.plexus.classworlds.ClassWorld;
|
||||
import org.codehaus.plexus.classworlds.realm.ClassRealm;
|
||||
import org.eclipse.aether.RepositorySystem;
|
||||
import org.eclipse.aether.RepositorySystemSession;
|
||||
import org.eclipse.aether.RepositorySystemSession.CloseableSession;
|
||||
import org.eclipse.aether.artifact.Artifact;
|
||||
import org.eclipse.aether.graph.DependencyFilter;
|
||||
import org.eclipse.aether.internal.impl.DefaultChecksumPolicyProvider;
|
||||
import org.eclipse.aether.internal.impl.DefaultRemoteRepositoryManager;
|
||||
import org.eclipse.aether.internal.impl.DefaultUpdatePolicyAnalyzer;
|
||||
import org.eclipse.aether.repository.RemoteRepository;
|
||||
import org.eclipse.aether.repository.WorkspaceReader;
|
||||
import org.eclipse.aether.resolution.ArtifactResult;
|
||||
import org.eclipse.aether.resolution.DependencyResult;
|
||||
import org.eclipse.aether.util.filter.ExclusionsDependencyFilter;
|
||||
import org.eclipse.aether.util.version.GenericVersionScheme;
|
||||
import org.eclipse.sisu.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* BootstrapCoreExtensionManager
|
||||
*/
|
||||
@Named
|
||||
public class BootstrapCoreExtensionManager {
|
||||
public static final String STRATEGY_PARENT_FIRST = "parent-first";
|
||||
public static final String STRATEGY_PLUGIN = "plugin";
|
||||
public static final String STRATEGY_SELF_FIRST = "self-first";
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final DefaultPluginDependenciesResolver pluginDependenciesResolver;
|
||||
|
||||
private final RepositorySystemSessionFactory repositorySystemSessionFactory;
|
||||
|
||||
private final CoreExports coreExports;
|
||||
|
||||
private final ClassWorld classWorld;
|
||||
|
||||
private final ClassRealm parentRealm;
|
||||
|
||||
private final WorkspaceReader ideWorkspaceReader;
|
||||
|
||||
private final RepositorySystem repoSystem;
|
||||
|
||||
@Inject
|
||||
public BootstrapCoreExtensionManager(
|
||||
DefaultPluginDependenciesResolver pluginDependenciesResolver,
|
||||
RepositorySystemSessionFactory repositorySystemSessionFactory,
|
||||
CoreExports coreExports,
|
||||
PlexusContainer container,
|
||||
@Nullable @Named("ide") WorkspaceReader ideWorkspaceReader,
|
||||
RepositorySystem repoSystem) {
|
||||
this.pluginDependenciesResolver = pluginDependenciesResolver;
|
||||
this.repositorySystemSessionFactory = repositorySystemSessionFactory;
|
||||
this.coreExports = coreExports;
|
||||
this.classWorld = ((DefaultPlexusContainer) container).getClassWorld();
|
||||
this.parentRealm = container.getContainerRealm();
|
||||
this.ideWorkspaceReader = ideWorkspaceReader;
|
||||
this.repoSystem = repoSystem;
|
||||
}
|
||||
|
||||
public List<CoreExtensionEntry> loadCoreExtensions(
|
||||
MavenExecutionRequest request, Set<String> providedArtifacts, List<CoreExtension> extensions)
|
||||
throws Exception {
|
||||
try (CloseableSession repoSession = repositorySystemSessionFactory
|
||||
.newRepositorySessionBuilder(request)
|
||||
.setWorkspaceReader(new MavenChainedWorkspaceReader(request.getWorkspaceReader(), ideWorkspaceReader))
|
||||
.build()) {
|
||||
MavenSession mSession = new MavenSession(repoSession, request, new DefaultMavenExecutionResult());
|
||||
InternalSession iSession = new SimpleSession(mSession, repoSystem, null);
|
||||
InternalSession.associate(repoSession, iSession);
|
||||
|
||||
List<RemoteRepository> repositories = RepositoryUtils.toRepos(request.getPluginArtifactRepositories());
|
||||
Function<String, String> interpolator = createInterpolator(request);
|
||||
|
||||
return resolveCoreExtensions(repoSession, repositories, providedArtifacts, extensions, interpolator);
|
||||
}
|
||||
}
|
||||
|
||||
private List<CoreExtensionEntry> resolveCoreExtensions(
|
||||
RepositorySystemSession repoSession,
|
||||
List<RemoteRepository> repositories,
|
||||
Set<String> providedArtifacts,
|
||||
List<CoreExtension> configuration,
|
||||
Function<String, String> interpolator)
|
||||
throws Exception {
|
||||
List<CoreExtensionEntry> extensions = new ArrayList<>();
|
||||
|
||||
DependencyFilter dependencyFilter = new ExclusionsDependencyFilter(providedArtifacts);
|
||||
|
||||
for (CoreExtension extension : configuration) {
|
||||
List<Artifact> artifacts =
|
||||
resolveExtension(extension, repoSession, repositories, dependencyFilter, interpolator);
|
||||
if (!artifacts.isEmpty()) {
|
||||
extensions.add(createExtension(extension, artifacts));
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(extensions);
|
||||
}
|
||||
|
||||
private CoreExtensionEntry createExtension(CoreExtension extension, List<Artifact> artifacts) throws Exception {
|
||||
String realmId = "coreExtension>" + extension.getGroupId() + ":" + extension.getArtifactId() + ":"
|
||||
+ extension.getVersion();
|
||||
final ClassRealm realm = classWorld.newRealm(realmId, null);
|
||||
Set<String> providedArtifacts = Collections.emptySet();
|
||||
String classLoadingStrategy = extension.getClassLoadingStrategy();
|
||||
if (STRATEGY_PARENT_FIRST.equals(classLoadingStrategy)) {
|
||||
realm.importFrom(parentRealm, "");
|
||||
} else if (STRATEGY_PLUGIN.equals(classLoadingStrategy)) {
|
||||
coreExports.getExportedPackages().forEach((p, cl) -> realm.importFrom(cl, p));
|
||||
providedArtifacts = coreExports.getExportedArtifacts();
|
||||
} else if (STRATEGY_SELF_FIRST.equals(classLoadingStrategy)) {
|
||||
realm.setParentRealm(parentRealm);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported class-loading strategy '"
|
||||
+ classLoadingStrategy + "'. Supported values are: " + STRATEGY_PARENT_FIRST
|
||||
+ ", " + STRATEGY_PLUGIN + " and " + STRATEGY_SELF_FIRST);
|
||||
}
|
||||
log.debug("Populating class realm {}", realm.getId());
|
||||
for (Artifact artifact : artifacts) {
|
||||
String id = artifact.getGroupId() + ":" + artifact.getArtifactId();
|
||||
if (providedArtifacts.contains(id)) {
|
||||
log.debug(" Excluded {}", id);
|
||||
} else {
|
||||
Path file = artifact.getPath();
|
||||
log.debug(" Included {} located at {}", id, file);
|
||||
realm.addURL(file.toUri().toURL());
|
||||
}
|
||||
}
|
||||
return CoreExtensionEntry.discoverFrom(
|
||||
realm,
|
||||
Collections.singleton(artifacts.get(0).getPath().toFile()),
|
||||
extension.getGroupId() + ":" + extension.getArtifactId(),
|
||||
extension.getConfiguration());
|
||||
}
|
||||
|
||||
private List<Artifact> resolveExtension(
|
||||
CoreExtension extension,
|
||||
RepositorySystemSession repoSession,
|
||||
List<RemoteRepository> repositories,
|
||||
DependencyFilter dependencyFilter,
|
||||
Function<String, String> interpolator)
|
||||
throws ExtensionResolutionException {
|
||||
try {
|
||||
/* TODO: Enhance the PluginDependenciesResolver to provide a
|
||||
* resolveCoreExtension method which uses a CoreExtension
|
||||
* object instead of a Plugin as this makes no sense.
|
||||
*/
|
||||
Plugin plugin = Plugin.newBuilder()
|
||||
.groupId(interpolator.apply(extension.getGroupId()))
|
||||
.artifactId(interpolator.apply(extension.getArtifactId()))
|
||||
.version(interpolator.apply(extension.getVersion()))
|
||||
.build();
|
||||
|
||||
DependencyResult result = pluginDependenciesResolver.resolveCoreExtension(
|
||||
new org.apache.maven.model.Plugin(plugin), dependencyFilter, repositories, repoSession);
|
||||
return result.getArtifactResults().stream()
|
||||
.filter(ArtifactResult::isResolved)
|
||||
.map(ArtifactResult::getArtifact)
|
||||
.collect(Collectors.toList());
|
||||
} catch (PluginResolutionException | InterpolatorException e) {
|
||||
throw new ExtensionResolutionException(extension, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Function<String, String> createInterpolator(MavenExecutionRequest request) {
|
||||
Interpolator interpolator = new DefaultInterpolator();
|
||||
Function<String, String> callback = v -> {
|
||||
String r = request.getUserProperties().getProperty(v);
|
||||
if (r == null) {
|
||||
r = request.getSystemProperties().getProperty(v);
|
||||
}
|
||||
return r != null ? r : v;
|
||||
};
|
||||
return v -> interpolator.interpolate(v, callback);
|
||||
}
|
||||
|
||||
static class SimpleSession extends DefaultSession {
|
||||
SimpleSession(
|
||||
MavenSession session,
|
||||
RepositorySystem repositorySystem,
|
||||
List<org.apache.maven.api.RemoteRepository> repositories) {
|
||||
super(session, repositorySystem, repositories, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Session newSession(
|
||||
MavenSession mavenSession, List<org.apache.maven.api.RemoteRepository> repositories) {
|
||||
return new SimpleSession(mavenSession, getRepositorySystem(), repositories);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Service> T getService(Class<T> clazz) throws NoSuchElementException {
|
||||
if (clazz == ArtifactCoordinatesFactory.class) {
|
||||
return (T) new DefaultArtifactCoordinatesFactory();
|
||||
} else if (clazz == VersionParser.class) {
|
||||
return (T) new DefaultVersionParser(new DefaultModelVersionParser(new GenericVersionScheme()));
|
||||
} else if (clazz == VersionRangeResolver.class) {
|
||||
return (T) new DefaultVersionRangeResolver(repositorySystem);
|
||||
} else if (clazz == ArtifactResolver.class) {
|
||||
return (T) new DefaultArtifactResolver();
|
||||
} else if (clazz == ArtifactManager.class) {
|
||||
return (T) new DefaultArtifactManager(this);
|
||||
} else if (clazz == RepositoryFactory.class) {
|
||||
return (T) new DefaultRepositoryFactory(new DefaultRemoteRepositoryManager(
|
||||
new DefaultUpdatePolicyAnalyzer(), new DefaultChecksumPolicyProvider()));
|
||||
} else if (clazz == Interpolator.class) {
|
||||
return (T) new DefaultInterpolator();
|
||||
// } else if (clazz == ModelResolver.class) {
|
||||
// return (T) new DefaultModelResolver();
|
||||
}
|
||||
throw new NoSuchElementException("No service for " + clazz.getName());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cling.extensions;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.name.Names;
|
||||
import org.apache.maven.api.services.Interpolator;
|
||||
import org.apache.maven.api.xml.XmlNode;
|
||||
import org.apache.maven.extension.internal.CoreExtensionEntry;
|
||||
import org.apache.maven.internal.impl.model.DefaultInterpolator;
|
||||
import org.apache.maven.internal.xml.XmlNodeImpl;
|
||||
import org.apache.maven.internal.xml.XmlPlexusConfiguration;
|
||||
import org.apache.maven.model.v4.MavenTransformer;
|
||||
import org.codehaus.plexus.configuration.PlexusConfiguration;
|
||||
|
||||
public class ExtensionConfigurationModule implements Module {
|
||||
|
||||
private final CoreExtensionEntry extension;
|
||||
private final Function<String, String> callback;
|
||||
private final DefaultInterpolator interpolator = new DefaultInterpolator();
|
||||
|
||||
public ExtensionConfigurationModule(CoreExtensionEntry extension, Function<String, String> callback) {
|
||||
this.extension = extension;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(Binder binder) {
|
||||
if (extension.getKey() != null) {
|
||||
XmlNode configuration = extension.getConfiguration();
|
||||
if (configuration == null) {
|
||||
configuration = new XmlNodeImpl("configuration");
|
||||
}
|
||||
Function<String, String> cb = Interpolator.memoize(callback);
|
||||
Function<String, String> it = s -> interpolator.interpolate(s, cb);
|
||||
configuration = new ExtensionInterpolator(it).transform(configuration);
|
||||
|
||||
binder.bind(XmlNode.class)
|
||||
.annotatedWith(Names.named(extension.getKey()))
|
||||
.toInstance(configuration);
|
||||
binder.bind(PlexusConfiguration.class)
|
||||
.annotatedWith(Names.named(extension.getKey()))
|
||||
.toInstance(XmlPlexusConfiguration.toPlexusConfiguration(configuration));
|
||||
}
|
||||
}
|
||||
|
||||
static class ExtensionInterpolator extends MavenTransformer {
|
||||
ExtensionInterpolator(Function<String, String> transformer) {
|
||||
super(transformer);
|
||||
}
|
||||
|
||||
public XmlNode transform(XmlNode node) {
|
||||
return super.transform(node);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cling.extensions;
|
||||
|
||||
import org.apache.maven.api.cli.extensions.CoreExtension;
|
||||
|
||||
/**
|
||||
* Exception occurring trying to resolve a plugin.
|
||||
*
|
||||
*/
|
||||
public class ExtensionResolutionException extends Exception {
|
||||
|
||||
private final CoreExtension extension;
|
||||
|
||||
public ExtensionResolutionException(CoreExtension extension, Throwable cause) {
|
||||
super(
|
||||
"Extension " + extension.getId() + " or one of its dependencies could not be resolved: "
|
||||
+ cause.getMessage(),
|
||||
cause);
|
||||
this.extension = extension;
|
||||
}
|
||||
|
||||
public CoreExtension getExtension() {
|
||||
return extension;
|
||||
}
|
||||
}
|
|
@ -42,9 +42,9 @@ import org.apache.maven.api.cli.Parser;
|
|||
import org.apache.maven.api.cli.ParserException;
|
||||
import org.apache.maven.api.cli.ParserRequest;
|
||||
import org.apache.maven.api.cli.extensions.CoreExtension;
|
||||
import org.apache.maven.cli.CLIReportingUtils;
|
||||
import org.apache.maven.cli.internal.extension.io.CoreExtensionsStaxReader;
|
||||
import org.apache.maven.cli.props.MavenPropertiesLoader;
|
||||
import org.apache.maven.cling.internal.extension.io.CoreExtensionsStaxReader;
|
||||
import org.apache.maven.cling.props.MavenPropertiesLoader;
|
||||
import org.apache.maven.cling.utils.CLIReportingUtils;
|
||||
import org.apache.maven.properties.internal.EnvironmentUtils;
|
||||
import org.apache.maven.properties.internal.SystemProperties;
|
||||
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cling.invoker;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* CleanArgument
|
||||
*/
|
||||
public class CleanArgument {
|
||||
public static String[] cleanArgs(String[] args) {
|
||||
try {
|
||||
return doCleanArgs(args);
|
||||
} catch (RuntimeException e) {
|
||||
for (String a : args) {
|
||||
System.out.println("Arg: '" + a + "'");
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private static String[] doCleanArgs(String[] args) {
|
||||
List<String> cleaned = new ArrayList<>();
|
||||
|
||||
StringBuilder currentArg = null;
|
||||
|
||||
for (String arg : args) {
|
||||
boolean addedToBuffer = false;
|
||||
|
||||
if (arg.startsWith("\"")) {
|
||||
// if we're in the process of building up another arg, push it and start over.
|
||||
// this is for the case: "-Dfoo=bar "-Dfoo2=bar two" (note the first unterminated quote)
|
||||
if (currentArg != null) {
|
||||
cleaned.add(currentArg.toString());
|
||||
}
|
||||
|
||||
// start building an argument here.
|
||||
currentArg = new StringBuilder(arg.substring(1));
|
||||
addedToBuffer = true;
|
||||
}
|
||||
|
||||
// this has to be a separate "if" statement, to capture the case of: "-Dfoo=bar"
|
||||
if (addedToBuffer && arg.endsWith("\"")) {
|
||||
// if we're building an argument, keep doing so.
|
||||
// if this is the case of "-Dfoo=bar", then we need to adjust the buffer.
|
||||
if (!currentArg.isEmpty()) {
|
||||
currentArg.setLength(currentArg.length() - 1);
|
||||
}
|
||||
|
||||
cleaned.add(currentArg.toString());
|
||||
|
||||
currentArg = null;
|
||||
addedToBuffer = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if we haven't added this arg to the buffer, and we ARE building an argument
|
||||
// buffer, then append it with a preceding space...again, not sure what else to
|
||||
// do other than collapse whitespace.
|
||||
// NOTE: The case of a trailing quote is handled by nullifying the arg buffer.
|
||||
if (!addedToBuffer) {
|
||||
if (currentArg != null) {
|
||||
currentArg.append(' ').append(arg);
|
||||
} else {
|
||||
cleaned.add(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentArg != null) {
|
||||
cleaned.add(currentArg.toString());
|
||||
}
|
||||
|
||||
int cleanedSz = cleaned.size();
|
||||
|
||||
String[] cleanArgs;
|
||||
|
||||
if (cleanedSz == 0) {
|
||||
cleanArgs = args;
|
||||
} else {
|
||||
cleanArgs = cleaned.toArray(new String[0]);
|
||||
}
|
||||
|
||||
return cleanArgs;
|
||||
}
|
||||
}
|
|
@ -34,7 +34,6 @@ import org.apache.commons.cli.Option;
|
|||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.maven.api.cli.Options;
|
||||
import org.apache.maven.api.cli.ParserRequest;
|
||||
import org.apache.maven.cli.CleanArgument;
|
||||
import org.apache.maven.jline.MessageUtils;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
|
|
@ -62,14 +62,14 @@ import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
|
|||
import org.apache.maven.artifact.repository.MavenArtifactRepository;
|
||||
import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
|
||||
import org.apache.maven.bridge.MavenRepositorySystem;
|
||||
import org.apache.maven.cli.CLIReportingUtils;
|
||||
import org.apache.maven.cli.logging.Slf4jConfiguration;
|
||||
import org.apache.maven.cli.logging.Slf4jConfigurationFactory;
|
||||
import org.apache.maven.cli.transfer.ConsoleMavenTransferListener;
|
||||
import org.apache.maven.cli.transfer.QuietMavenTransferListener;
|
||||
import org.apache.maven.cli.transfer.SimplexTransferListener;
|
||||
import org.apache.maven.cli.transfer.Slf4jMavenTransferListener;
|
||||
import org.apache.maven.cling.invoker.mvn.ProtoSession;
|
||||
import org.apache.maven.cling.logging.Slf4jConfiguration;
|
||||
import org.apache.maven.cling.logging.Slf4jConfigurationFactory;
|
||||
import org.apache.maven.cling.transfer.ConsoleMavenTransferListener;
|
||||
import org.apache.maven.cling.transfer.QuietMavenTransferListener;
|
||||
import org.apache.maven.cling.transfer.SimplexTransferListener;
|
||||
import org.apache.maven.cling.transfer.Slf4jMavenTransferListener;
|
||||
import org.apache.maven.cling.utils.CLIReportingUtils;
|
||||
import org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.internal.impl.SettingsUtilsV4;
|
||||
import org.apache.maven.jline.FastTerminal;
|
||||
|
|
|
@ -37,9 +37,9 @@ import org.apache.maven.api.cli.Options;
|
|||
import org.apache.maven.api.cli.extensions.CoreExtension;
|
||||
import org.apache.maven.api.services.MessageBuilderFactory;
|
||||
import org.apache.maven.api.services.SettingsBuilder;
|
||||
import org.apache.maven.cli.ExtensionConfigurationModule;
|
||||
import org.apache.maven.cli.internal.BootstrapCoreExtensionManager;
|
||||
import org.apache.maven.cli.logging.Slf4jLoggerManager;
|
||||
import org.apache.maven.cling.extensions.BootstrapCoreExtensionManager;
|
||||
import org.apache.maven.cling.extensions.ExtensionConfigurationModule;
|
||||
import org.apache.maven.cling.logging.Slf4jLoggerManager;
|
||||
import org.apache.maven.di.Injector;
|
||||
import org.apache.maven.execution.DefaultMavenExecutionRequest;
|
||||
import org.apache.maven.execution.MavenExecutionRequest;
|
||||
|
|
|
@ -32,7 +32,7 @@ import java.util.function.Function;
|
|||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.annotations.Nullable;
|
||||
import org.apache.maven.api.services.model.RootLocator;
|
||||
import org.apache.maven.cli.logging.Slf4jConfiguration;
|
||||
import org.apache.maven.cling.logging.Slf4jConfiguration;
|
||||
import org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.codehaus.plexus.interpolation.AbstractValueSource;
|
||||
import org.codehaus.plexus.interpolation.BasicInterpolator;
|
||||
|
|
|
@ -46,11 +46,11 @@ import org.apache.maven.api.services.ToolchainsBuilder;
|
|||
import org.apache.maven.api.services.ToolchainsBuilderRequest;
|
||||
import org.apache.maven.api.services.ToolchainsBuilderResult;
|
||||
import org.apache.maven.api.services.model.ModelProcessor;
|
||||
import org.apache.maven.cli.CLIReportingUtils;
|
||||
import org.apache.maven.cli.event.ExecutionEventLogger;
|
||||
import org.apache.maven.cling.event.ExecutionEventLogger;
|
||||
import org.apache.maven.cling.invoker.LookupInvoker;
|
||||
import org.apache.maven.cling.invoker.ProtoLookup;
|
||||
import org.apache.maven.cling.invoker.Utils;
|
||||
import org.apache.maven.cling.utils.CLIReportingUtils;
|
||||
import org.apache.maven.eventspy.internal.EventSpyDispatcher;
|
||||
import org.apache.maven.exception.DefaultExceptionHandler;
|
||||
import org.apache.maven.exception.ExceptionHandler;
|
||||
|
|
|
@ -26,9 +26,9 @@ import java.util.Map;
|
|||
import org.apache.maven.api.cli.mvnenc.EncryptInvoker;
|
||||
import org.apache.maven.api.cli.mvnenc.EncryptInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvnenc.EncryptOptions;
|
||||
import org.apache.maven.cli.CLIReportingUtils;
|
||||
import org.apache.maven.cling.invoker.LookupInvoker;
|
||||
import org.apache.maven.cling.invoker.ProtoLookup;
|
||||
import org.apache.maven.cling.utils.CLIReportingUtils;
|
||||
import org.jline.consoleui.prompt.ConsolePrompt;
|
||||
import org.jline.reader.LineReader;
|
||||
import org.jline.reader.LineReaderBuilder;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.maven.cli.logging;
|
||||
package org.apache.maven.cling.logging;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -29,10 +29,12 @@ import org.slf4j.LoggerFactory;
|
|||
public class BaseSlf4jConfiguration implements Slf4jConfiguration {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(BaseSlf4jConfiguration.class);
|
||||
|
||||
@Override
|
||||
public void setRootLoggerLevel(Level level) {
|
||||
LOGGER.warn("setRootLoggerLevel: operation not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate() {
|
||||
LOGGER.warn("activate(): operation not supported");
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.maven.cli.logging;
|
||||
package org.apache.maven.cling.logging;
|
||||
|
||||
/**
|
||||
* Interface for configuration operations on loggers, which are not available in slf4j, then require per-slf4f-binding
|
|
@ -16,15 +16,16 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.maven.cli.logging;
|
||||
package org.apache.maven.cling.logging;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.maven.cli.logging.impl.UnsupportedSlf4jBindingConfiguration;
|
||||
import org.apache.maven.cling.logging.impl.UnsupportedSlf4jBindingConfiguration;
|
||||
import org.slf4j.ILoggerFactory;
|
||||
|
||||
/**
|
||||
|
@ -56,9 +57,15 @@ public class Slf4jConfigurationFactory {
|
|||
}
|
||||
String impl = properties.getProperty(slf4jBinding);
|
||||
if (impl != null) {
|
||||
return (Slf4jConfiguration) Class.forName(impl).newInstance();
|
||||
return (Slf4jConfiguration)
|
||||
Class.forName(impl).getDeclaredConstructor().newInstance();
|
||||
}
|
||||
} catch (IOException | ClassNotFoundException | IllegalAccessException | InstantiationException ex) {
|
||||
} catch (IOException
|
||||
| ClassNotFoundException
|
||||
| NoSuchMethodException
|
||||
| InvocationTargetException
|
||||
| IllegalAccessException
|
||||
| InstantiationException ex) {
|
||||
// ignore and move on to the next
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.maven.cli.logging;
|
||||
package org.apache.maven.cling.logging;
|
||||
|
||||
import org.apache.maven.logging.ProjectBuildLogAppender;
|
||||
import org.codehaus.plexus.logging.Logger;
|
||||
|
@ -29,80 +29,95 @@ import org.codehaus.plexus.logging.Logger;
|
|||
*/
|
||||
public class Slf4jLogger implements Logger {
|
||||
|
||||
private org.slf4j.Logger logger;
|
||||
private String projectId;
|
||||
private final org.slf4j.Logger logger;
|
||||
private final String projectId;
|
||||
|
||||
public Slf4jLogger(org.slf4j.Logger logger) {
|
||||
this.logger = logger;
|
||||
this.projectId = ProjectBuildLogAppender.getProjectId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String message) {
|
||||
setMdc();
|
||||
logger.debug(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String message, Throwable throwable) {
|
||||
setMdc();
|
||||
logger.debug(message, throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugEnabled() {
|
||||
return logger.isDebugEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String message) {
|
||||
setMdc();
|
||||
logger.info(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String message, Throwable throwable) {
|
||||
setMdc();
|
||||
logger.info(message, throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInfoEnabled() {
|
||||
return logger.isInfoEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(String message) {
|
||||
setMdc();
|
||||
logger.warn(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(String message, Throwable throwable) {
|
||||
setMdc();
|
||||
logger.warn(message, throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWarnEnabled() {
|
||||
return logger.isWarnEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message) {
|
||||
setMdc();
|
||||
logger.error(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message, Throwable throwable) {
|
||||
setMdc();
|
||||
logger.error(message, throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isErrorEnabled() {
|
||||
return logger.isErrorEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatalError(String message) {
|
||||
setMdc();
|
||||
logger.error(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatalError(String message, Throwable throwable) {
|
||||
setMdc();
|
||||
logger.error(message, throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFatalErrorEnabled() {
|
||||
return logger.isErrorEnabled();
|
||||
}
|
||||
|
@ -110,6 +125,7 @@ public class Slf4jLogger implements Logger {
|
|||
/**
|
||||
* <b>Warning</b>: ignored (always return <code>0 == Logger.LEVEL_DEBUG</code>).
|
||||
*/
|
||||
@Override
|
||||
public int getThreshold() {
|
||||
return 0;
|
||||
}
|
||||
|
@ -117,15 +133,18 @@ public class Slf4jLogger implements Logger {
|
|||
/**
|
||||
* <b>Warning</b>: ignored.
|
||||
*/
|
||||
@Override
|
||||
public void setThreshold(int threshold) {}
|
||||
|
||||
/**
|
||||
* <b>Warning</b>: ignored (always return <code>null</code>).
|
||||
*/
|
||||
@Override
|
||||
public Logger getChildLogger(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return logger.getName();
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.maven.cli.logging;
|
||||
package org.apache.maven.cling.logging;
|
||||
|
||||
import org.codehaus.plexus.logging.Logger;
|
||||
import org.codehaus.plexus.logging.LoggerManager;
|
||||
|
@ -24,20 +24,21 @@ import org.slf4j.ILoggerFactory;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Use an SLF4J {@link org.slf4j.ILoggerFactory} as a backing for a Plexus
|
||||
* {@link org.codehaus.plexus.logging.LoggerManager},
|
||||
* Use an SLF4J {@link ILoggerFactory} as a backing for a Plexus
|
||||
* {@link LoggerManager},
|
||||
* ignoring Plexus logger API parts that are not classical and probably not really used.
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public class Slf4jLoggerManager implements LoggerManager {
|
||||
|
||||
private ILoggerFactory loggerFactory;
|
||||
private final ILoggerFactory loggerFactory;
|
||||
|
||||
public Slf4jLoggerManager() {
|
||||
loggerFactory = LoggerFactory.getILoggerFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getLoggerForComponent(String role) {
|
||||
return new Slf4jLogger(loggerFactory.getLogger(role));
|
||||
}
|
||||
|
@ -47,6 +48,7 @@ public class Slf4jLoggerManager implements LoggerManager {
|
|||
* <b>Warning</b>: this does not conform to logger name as class name convention.
|
||||
* (and what about <code>null</code> and <code>default</code> hint equivalence?)
|
||||
*/
|
||||
@Override
|
||||
public Logger getLoggerForComponent(String role, String hint) {
|
||||
return (null == hint
|
||||
? getLoggerForComponent(role)
|
||||
|
@ -60,16 +62,19 @@ public class Slf4jLoggerManager implements LoggerManager {
|
|||
/**
|
||||
* <b>Warning</b>: ignored.
|
||||
*/
|
||||
@Override
|
||||
public void returnComponentLogger(String role) {}
|
||||
|
||||
/**
|
||||
* <b>Warning</b>: ignored.
|
||||
*/
|
||||
@Override
|
||||
public void returnComponentLogger(String role, String hint) {}
|
||||
|
||||
/**
|
||||
* <b>Warning</b>: ignored (always return <code>0</code>).
|
||||
*/
|
||||
@Override
|
||||
public int getThreshold() {
|
||||
return 0;
|
||||
}
|
||||
|
@ -77,16 +82,19 @@ public class Slf4jLoggerManager implements LoggerManager {
|
|||
/**
|
||||
* <b>Warning</b>: ignored.
|
||||
*/
|
||||
@Override
|
||||
public void setThreshold(int threshold) {}
|
||||
|
||||
/**
|
||||
* <b>Warning</b>: ignored.
|
||||
*/
|
||||
@Override
|
||||
public void setThresholds(int threshold) {}
|
||||
|
||||
/**
|
||||
* <b>Warning</b>: ignored (always return <code>0</code>).
|
||||
*/
|
||||
@Override
|
||||
public int getActiveLoggerCount() {
|
||||
return 0;
|
||||
}
|
|
@ -16,9 +16,9 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.maven.cli.logging.impl;
|
||||
package org.apache.maven.cling.logging.impl;
|
||||
|
||||
import org.apache.maven.cli.logging.BaseSlf4jConfiguration;
|
||||
import org.apache.maven.cling.logging.BaseSlf4jConfiguration;
|
||||
|
||||
/**
|
||||
* Configuration for slf4j-log4j2.
|
|
@ -16,9 +16,9 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.maven.cli.logging.impl;
|
||||
package org.apache.maven.cling.logging.impl;
|
||||
|
||||
import org.apache.maven.cli.logging.BaseSlf4jConfiguration;
|
||||
import org.apache.maven.cling.logging.BaseSlf4jConfiguration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
|
@ -16,9 +16,9 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.maven.cli.logging.impl;
|
||||
package org.apache.maven.cling.logging.impl;
|
||||
|
||||
import org.apache.maven.cli.logging.BaseSlf4jConfiguration;
|
||||
import org.apache.maven.cling.logging.BaseSlf4jConfiguration;
|
||||
import org.apache.maven.slf4j.MavenLoggerFactory;
|
||||
import org.slf4j.ILoggerFactory;
|
||||
import org.slf4j.LoggerFactory;
|
|
@ -16,13 +16,13 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.maven.cli.logging.impl;
|
||||
package org.apache.maven.cling.logging.impl;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.maven.cli.logging.BaseSlf4jConfiguration;
|
||||
import org.apache.maven.cling.logging.BaseSlf4jConfiguration;
|
||||
|
||||
/**
|
||||
* Pseudo-configuration for unsupported SLF4J binding.
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cling.props;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.apache.maven.internal.impl.model.DefaultInterpolator;
|
||||
|
||||
public class MavenPropertiesLoader {
|
||||
|
||||
public static final String INCLUDES_PROPERTY = "${includes}"; // includes
|
||||
|
||||
public static final String OVERRIDE_PREFIX =
|
||||
"maven.override."; // prefix that marks that system property should override defaults.
|
||||
|
||||
public static void loadProperties(
|
||||
java.util.Properties properties, Path path, Function<String, String> callback, boolean escape)
|
||||
throws IOException {
|
||||
MavenProperties sp = new MavenProperties(false);
|
||||
if (Files.exists(path)) {
|
||||
sp.load(path);
|
||||
}
|
||||
properties.forEach(
|
||||
(k, v) -> sp.put(k.toString(), escape ? DefaultInterpolator.escape(v.toString()) : v.toString()));
|
||||
loadIncludes(path, sp, callback);
|
||||
substitute(sp, callback);
|
||||
sp.forEach(properties::setProperty);
|
||||
}
|
||||
|
||||
public static void substitute(MavenProperties props, Function<String, String> callback) {
|
||||
for (Enumeration<?> e = props.propertyNames(); e.hasMoreElements(); ) {
|
||||
String name = (String) e.nextElement();
|
||||
String value = props.getProperty(name);
|
||||
if (value == null) {
|
||||
value = callback.apply(name);
|
||||
}
|
||||
if (name.startsWith(OVERRIDE_PREFIX)) {
|
||||
String overrideName = name.substring(OVERRIDE_PREFIX.length());
|
||||
props.put(overrideName, substVars(value, name, props, callback));
|
||||
} else {
|
||||
props.put(name, substVars(value, name, props, callback));
|
||||
}
|
||||
}
|
||||
props.keySet().removeIf(k -> k.startsWith(OVERRIDE_PREFIX));
|
||||
}
|
||||
|
||||
private static MavenProperties loadPropertiesFile(
|
||||
Path path, boolean failIfNotFound, Function<String, String> callback) throws IOException {
|
||||
MavenProperties configProps = new MavenProperties(null, false);
|
||||
if (Files.exists(path) || failIfNotFound) {
|
||||
configProps.load(path);
|
||||
loadIncludes(path, configProps, callback);
|
||||
trimValues(configProps);
|
||||
}
|
||||
return configProps;
|
||||
}
|
||||
|
||||
private static void loadIncludes(Path configProp, MavenProperties configProps, Function<String, String> callback)
|
||||
throws IOException {
|
||||
String includes = configProps.get(INCLUDES_PROPERTY);
|
||||
if (includes != null) {
|
||||
includes = substVars(includes, INCLUDES_PROPERTY, configProps, callback);
|
||||
StringTokenizer st = new StringTokenizer(includes, "?\",", true);
|
||||
if (st.countTokens() > 0) {
|
||||
String location;
|
||||
do {
|
||||
location = nextLocation(st);
|
||||
if (location != null) {
|
||||
boolean mandatory = true;
|
||||
if (location.startsWith("?")) {
|
||||
mandatory = false;
|
||||
location = location.substring(1);
|
||||
}
|
||||
Path path = configProp.resolveSibling(location);
|
||||
MavenProperties props = loadPropertiesFile(path, mandatory, s -> {
|
||||
var v = callback.apply(s);
|
||||
return v != null ? v : configProps.getProperty(s);
|
||||
});
|
||||
configProps.putAll(props);
|
||||
}
|
||||
} while (location != null);
|
||||
}
|
||||
}
|
||||
configProps.remove(INCLUDES_PROPERTY);
|
||||
}
|
||||
|
||||
private static void trimValues(MavenProperties configProps) {
|
||||
configProps.replaceAll((k, v) -> v.trim());
|
||||
}
|
||||
|
||||
private static String nextLocation(StringTokenizer st) {
|
||||
boolean optional = false;
|
||||
String retVal = null;
|
||||
|
||||
if (st.countTokens() > 0) {
|
||||
String tokenList = "?\",";
|
||||
StringBuilder tokBuf = new StringBuilder(10);
|
||||
String tok;
|
||||
boolean inQuote = false;
|
||||
boolean tokStarted = false;
|
||||
boolean exit = false;
|
||||
while ((st.hasMoreTokens()) && (!exit)) {
|
||||
tok = st.nextToken(tokenList);
|
||||
switch (tok) {
|
||||
case "\"":
|
||||
inQuote = !inQuote;
|
||||
if (inQuote) {
|
||||
tokenList = "\"";
|
||||
} else {
|
||||
tokenList = "\" ";
|
||||
}
|
||||
break;
|
||||
case ",":
|
||||
if (tokStarted) {
|
||||
retVal = tokBuf.toString();
|
||||
tokStarted = false;
|
||||
tokBuf = new StringBuilder(10);
|
||||
exit = true;
|
||||
}
|
||||
break;
|
||||
case "?":
|
||||
optional = true;
|
||||
break;
|
||||
default:
|
||||
tokStarted = true;
|
||||
tokBuf.append(tok.trim());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle case where end of token stream and
|
||||
// still got data
|
||||
if ((!exit) && (tokStarted)) {
|
||||
retVal = tokBuf.toString();
|
||||
}
|
||||
}
|
||||
|
||||
return optional ? "?" + retVal : retVal;
|
||||
}
|
||||
|
||||
public static String substVars(
|
||||
String value, String name, Map<String, String> props, Function<String, String> callback) {
|
||||
return DefaultInterpolator.substVars(value, name, null, props, callback, null, false);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cling.transfer;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import org.apache.maven.api.services.MessageBuilder;
|
||||
import org.apache.maven.api.services.MessageBuilderFactory;
|
||||
import org.eclipse.aether.transfer.AbstractTransferListener;
|
||||
import org.eclipse.aether.transfer.TransferCancelledException;
|
||||
import org.eclipse.aether.transfer.TransferEvent;
|
||||
import org.eclipse.aether.transfer.TransferResource;
|
||||
|
||||
/**
|
||||
* AbstractMavenTransferListener
|
||||
*/
|
||||
public abstract class AbstractMavenTransferListener extends AbstractTransferListener {
|
||||
public static final String STYLE = ".transfer:-faint";
|
||||
|
||||
protected final MessageBuilderFactory messageBuilderFactory;
|
||||
protected final PrintWriter out;
|
||||
|
||||
protected AbstractMavenTransferListener(MessageBuilderFactory messageBuilderFactory, PrintStream out) {
|
||||
this(messageBuilderFactory, new PrintWriter(out));
|
||||
}
|
||||
|
||||
protected AbstractMavenTransferListener(MessageBuilderFactory messageBuilderFactory, PrintWriter out) {
|
||||
this.messageBuilderFactory = messageBuilderFactory;
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferInitiated(TransferEvent event) {
|
||||
String action = event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploading" : "Downloading";
|
||||
String direction = event.getRequestType() == TransferEvent.RequestType.PUT ? "to" : "from";
|
||||
|
||||
TransferResource resource = event.getResource();
|
||||
MessageBuilder message = messageBuilderFactory.builder();
|
||||
message.style(STYLE).append(action).append(' ').append(direction).append(' ');
|
||||
message.resetStyle().append(resource.getRepositoryId());
|
||||
message.style(STYLE).append(": ").append(resource.getRepositoryUrl());
|
||||
message.resetStyle().append(resource.getResourceName());
|
||||
|
||||
out.println(message.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferCorrupted(TransferEvent event) throws TransferCancelledException {
|
||||
TransferResource resource = event.getResource();
|
||||
// TODO This needs to be colorized
|
||||
out.println("[WARNING] " + event.getException().getMessage() + " from " + resource.getRepositoryId() + " for "
|
||||
+ resource.getRepositoryUrl() + resource.getResourceName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferSucceeded(TransferEvent event) {
|
||||
String action = (event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploaded" : "Downloaded");
|
||||
String direction = event.getRequestType() == TransferEvent.RequestType.PUT ? "to" : "from";
|
||||
|
||||
TransferResource resource = event.getResource();
|
||||
long contentLength = event.getTransferredBytes();
|
||||
FileSizeFormat format = new FileSizeFormat();
|
||||
|
||||
MessageBuilder message = messageBuilderFactory.builder();
|
||||
message.append(action).style(STYLE).append(' ').append(direction).append(' ');
|
||||
message.resetStyle().append(resource.getRepositoryId());
|
||||
message.style(STYLE).append(": ").append(resource.getRepositoryUrl());
|
||||
message.resetStyle().append(resource.getResourceName());
|
||||
message.style(STYLE).append(" (").append(format.format(contentLength));
|
||||
|
||||
long duration = System.currentTimeMillis() - resource.getTransferStartTime();
|
||||
if (duration > 0L) {
|
||||
double bytesPerSecond = contentLength / (duration / 1000.0);
|
||||
message.append(" at ");
|
||||
format.format(message, (long) bytesPerSecond);
|
||||
message.append("/s");
|
||||
}
|
||||
|
||||
message.append(')').resetStyle();
|
||||
out.println(message.toString());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cling.transfer;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.maven.api.services.MessageBuilderFactory;
|
||||
import org.eclipse.aether.transfer.TransferCancelledException;
|
||||
import org.eclipse.aether.transfer.TransferEvent;
|
||||
import org.eclipse.aether.transfer.TransferResource;
|
||||
|
||||
/**
|
||||
* Console download progress meter.
|
||||
* <p>
|
||||
* This listener is not thread-safe and should be wrapped in the {@link SimplexTransferListener} in a multi-threaded scenario.
|
||||
*/
|
||||
public class ConsoleMavenTransferListener extends AbstractMavenTransferListener {
|
||||
|
||||
private final Map<TransferResourceIdentifier, TransferResourceAndSize> transfers = new LinkedHashMap<>();
|
||||
private final FileSizeFormat format = new FileSizeFormat(); // use in a synchronized fashion
|
||||
private final StringBuilder buffer = new StringBuilder(128); // use in a synchronized fashion
|
||||
|
||||
private final boolean printResourceNames;
|
||||
private int lastLength;
|
||||
|
||||
public ConsoleMavenTransferListener(
|
||||
MessageBuilderFactory messageBuilderFactory, PrintStream out, boolean printResourceNames) {
|
||||
this(messageBuilderFactory, new PrintWriter(out), printResourceNames);
|
||||
}
|
||||
|
||||
public ConsoleMavenTransferListener(
|
||||
MessageBuilderFactory messageBuilderFactory, PrintWriter out, boolean printResourceNames) {
|
||||
super(messageBuilderFactory, out);
|
||||
this.printResourceNames = printResourceNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferInitiated(TransferEvent event) {
|
||||
overridePreviousTransfer(event);
|
||||
|
||||
super.transferInitiated(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferCorrupted(TransferEvent event) throws TransferCancelledException {
|
||||
overridePreviousTransfer(event);
|
||||
|
||||
super.transferCorrupted(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferProgressed(TransferEvent event) throws TransferCancelledException {
|
||||
TransferResource resource = event.getResource();
|
||||
transfers.put(
|
||||
new TransferResourceIdentifier(resource),
|
||||
new TransferResourceAndSize(resource, event.getTransferredBytes()));
|
||||
|
||||
buffer.append("Progress (").append(transfers.size()).append("): ");
|
||||
|
||||
Iterator<TransferResourceAndSize> entries = transfers.values().iterator();
|
||||
while (entries.hasNext()) {
|
||||
TransferResourceAndSize entry = entries.next();
|
||||
// just in case, make sure 0 <= complete <= total
|
||||
long complete = Math.max(0, entry.transferredBytes);
|
||||
long total = Math.max(complete, entry.resource.getContentLength());
|
||||
|
||||
String resourceName = entry.resource.getResourceName();
|
||||
|
||||
if (printResourceNames) {
|
||||
int idx = resourceName.lastIndexOf('/');
|
||||
|
||||
if (idx < 0) {
|
||||
buffer.append(resourceName);
|
||||
} else {
|
||||
buffer.append(resourceName, idx + 1, resourceName.length());
|
||||
}
|
||||
buffer.append(" (");
|
||||
}
|
||||
|
||||
format.formatProgress(buffer, complete, total);
|
||||
|
||||
if (printResourceNames) {
|
||||
buffer.append(")");
|
||||
}
|
||||
|
||||
if (entries.hasNext()) {
|
||||
buffer.append(" | ");
|
||||
}
|
||||
}
|
||||
|
||||
int pad = lastLength - buffer.length();
|
||||
lastLength = buffer.length();
|
||||
pad(buffer, pad);
|
||||
buffer.append('\r');
|
||||
out.print(buffer);
|
||||
out.flush();
|
||||
buffer.setLength(0);
|
||||
}
|
||||
|
||||
private void pad(StringBuilder buffer, int spaces) {
|
||||
String block = " ";
|
||||
while (spaces > 0) {
|
||||
int n = Math.min(spaces, block.length());
|
||||
buffer.append(block, 0, n);
|
||||
spaces -= n;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferSucceeded(TransferEvent event) {
|
||||
transfers.remove(new TransferResourceIdentifier(event.getResource()));
|
||||
overridePreviousTransfer(event);
|
||||
|
||||
super.transferSucceeded(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferFailed(TransferEvent event) {
|
||||
transfers.remove(new TransferResourceIdentifier(event.getResource()));
|
||||
overridePreviousTransfer(event);
|
||||
|
||||
super.transferFailed(event);
|
||||
}
|
||||
|
||||
private void overridePreviousTransfer(TransferEvent event) {
|
||||
if (lastLength > 0) {
|
||||
pad(buffer, lastLength);
|
||||
buffer.append('\r');
|
||||
out.print(buffer);
|
||||
out.flush();
|
||||
lastLength = 0;
|
||||
buffer.setLength(0);
|
||||
}
|
||||
}
|
||||
|
||||
private record TransferResourceAndSize(TransferResource resource, long transferredBytes) {}
|
||||
}
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cling.transfer;
|
||||
|
||||
import org.apache.maven.api.services.MessageBuilder;
|
||||
|
||||
/**
|
||||
* Formats file size with the associated <a href="https://en.wikipedia.org/wiki/Metric_prefix">SI</a> prefix
|
||||
* (GB, MB, kB) and using the patterns <code>#0.0</code> for numbers between 1 and 10
|
||||
* and <code>###0</code> for numbers between 10 and 1000+ by default.
|
||||
*
|
||||
* @see <a href="https://en.wikipedia.org/wiki/Metric_prefix">https://en.wikipedia.org/wiki/Metric_prefix</a>
|
||||
* @see <a href="https://en.wikipedia.org/wiki/Binary_prefix">https://en.wikipedia.org/wiki/Binary_prefix</a>
|
||||
* @see <a
|
||||
* href="https://en.wikipedia.org/wiki/Octet_%28computing%29">https://en.wikipedia.org/wiki/Octet_(computing)</a>
|
||||
*/
|
||||
public class FileSizeFormat {
|
||||
public enum ScaleUnit {
|
||||
BYTE {
|
||||
@Override
|
||||
public long bytes() {
|
||||
return 1L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String symbol() {
|
||||
return "B";
|
||||
}
|
||||
},
|
||||
KILOBYTE {
|
||||
@Override
|
||||
public long bytes() {
|
||||
return 1000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String symbol() {
|
||||
return "kB";
|
||||
}
|
||||
},
|
||||
MEGABYTE {
|
||||
@Override
|
||||
public long bytes() {
|
||||
return KILOBYTE.bytes() * KILOBYTE.bytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String symbol() {
|
||||
return "MB";
|
||||
}
|
||||
},
|
||||
GIGABYTE {
|
||||
@Override
|
||||
public long bytes() {
|
||||
return MEGABYTE.bytes() * KILOBYTE.bytes();
|
||||
}
|
||||
;
|
||||
|
||||
@Override
|
||||
public String symbol() {
|
||||
return "GB";
|
||||
}
|
||||
};
|
||||
|
||||
public abstract long bytes();
|
||||
|
||||
public abstract String symbol();
|
||||
|
||||
public static ScaleUnit getScaleUnit(long size) {
|
||||
if (size < 0L) {
|
||||
throw new IllegalArgumentException("file size cannot be negative: " + size);
|
||||
}
|
||||
|
||||
if (size >= GIGABYTE.bytes()) {
|
||||
return GIGABYTE;
|
||||
} else if (size >= MEGABYTE.bytes()) {
|
||||
return MEGABYTE;
|
||||
} else if (size >= KILOBYTE.bytes()) {
|
||||
return KILOBYTE;
|
||||
} else {
|
||||
return BYTE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String format(long size) {
|
||||
return format(size, null);
|
||||
}
|
||||
|
||||
public String format(long size, ScaleUnit unit) {
|
||||
return format(size, unit, false);
|
||||
}
|
||||
|
||||
public String format(long size, ScaleUnit unit, boolean omitSymbol) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
format(sb, size, unit, omitSymbol);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void format(StringBuilder builder, long size) {
|
||||
format(builder, size, null, false);
|
||||
}
|
||||
|
||||
public void format(StringBuilder builder, long size, ScaleUnit unit) {
|
||||
format(builder, size, unit, false);
|
||||
}
|
||||
|
||||
private void format(StringBuilder builder, long size, ScaleUnit unit, boolean omitSymbol) {
|
||||
if (size < 0L) {
|
||||
throw new IllegalArgumentException("file size cannot be negative: " + size);
|
||||
}
|
||||
if (unit == null) {
|
||||
unit = ScaleUnit.getScaleUnit(size);
|
||||
}
|
||||
|
||||
double scaledSize = (double) size / unit.bytes();
|
||||
|
||||
if (unit == ScaleUnit.BYTE) {
|
||||
builder.append(size);
|
||||
} else if (scaledSize < 0.05d || scaledSize >= 10.0d) {
|
||||
builder.append(Math.round(scaledSize));
|
||||
} else {
|
||||
builder.append(Math.round(scaledSize * 10d) / 10d);
|
||||
}
|
||||
|
||||
if (!omitSymbol) {
|
||||
builder.append(" ").append(unit.symbol());
|
||||
}
|
||||
}
|
||||
|
||||
public void format(MessageBuilder builder, long size) {
|
||||
format(builder, size, null, false);
|
||||
}
|
||||
|
||||
public void format(MessageBuilder builder, long size, ScaleUnit unit) {
|
||||
format(builder, size, unit, false);
|
||||
}
|
||||
|
||||
private void format(MessageBuilder builder, long size, ScaleUnit unit, boolean omitSymbol) {
|
||||
if (size < 0L) {
|
||||
throw new IllegalArgumentException("file size cannot be negative: " + size);
|
||||
}
|
||||
if (unit == null) {
|
||||
unit = ScaleUnit.getScaleUnit(size);
|
||||
}
|
||||
|
||||
double scaledSize = (double) size / unit.bytes();
|
||||
|
||||
if (unit == ScaleUnit.BYTE) {
|
||||
builder.append(Long.toString(size));
|
||||
} else if (scaledSize < 0.05d || scaledSize >= 10.0d) {
|
||||
builder.append(Long.toString(Math.round(scaledSize)));
|
||||
} else {
|
||||
builder.append(Double.toString(Math.round(scaledSize * 10d) / 10d));
|
||||
}
|
||||
|
||||
if (!omitSymbol) {
|
||||
builder.append(" ").append(unit.symbol());
|
||||
}
|
||||
}
|
||||
|
||||
public String formatProgress(long progressedSize, long size) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
formatProgress(sb, progressedSize, size);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void formatProgress(StringBuilder builder, long progressedSize, long size) {
|
||||
if (progressedSize < 0L) {
|
||||
throw new IllegalArgumentException("progressed file size cannot be negative: " + size);
|
||||
}
|
||||
if (size >= 0 && progressedSize > size) {
|
||||
throw new IllegalArgumentException(
|
||||
"progressed file size cannot be greater than size: " + progressedSize + " > " + size);
|
||||
}
|
||||
|
||||
if (size >= 0L && progressedSize != size) {
|
||||
ScaleUnit unit = ScaleUnit.getScaleUnit(size);
|
||||
format(builder, progressedSize, unit, true);
|
||||
builder.append("/");
|
||||
format(builder, size, unit, false);
|
||||
} else {
|
||||
ScaleUnit unit = ScaleUnit.getScaleUnit(progressedSize);
|
||||
|
||||
format(builder, progressedSize, unit, false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cling.transfer;
|
||||
|
||||
import org.eclipse.aether.transfer.AbstractTransferListener;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class QuietMavenTransferListener extends AbstractTransferListener {}
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cling.transfer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.eclipse.aether.transfer.AbstractTransferListener;
|
||||
import org.eclipse.aether.transfer.TransferCancelledException;
|
||||
import org.eclipse.aether.transfer.TransferEvent;
|
||||
import org.eclipse.aether.transfer.TransferListener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* A {@link TransferListener} implementation that wraps another delegate {@link TransferListener} but makes it run
|
||||
* on single thread, keeping the listener logic simple. This listener also blocks on last transfer event to allow
|
||||
* output to perform possible cleanup. It spawns a daemon thread to consume queued events that may fall in even
|
||||
* concurrently.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public final class SimplexTransferListener extends AbstractTransferListener {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SimplexTransferListener.class);
|
||||
private static final int QUEUE_SIZE = 1024;
|
||||
private static final int BATCH_MAX_SIZE = 500;
|
||||
private final TransferListener delegate;
|
||||
private final int batchMaxSize;
|
||||
private final boolean blockOnLastEvent;
|
||||
private final ArrayBlockingQueue<Exchange> eventQueue;
|
||||
|
||||
/**
|
||||
* Constructor that makes passed in delegate run on single thread, and will block on last event.
|
||||
*/
|
||||
public SimplexTransferListener(TransferListener delegate) {
|
||||
this(delegate, QUEUE_SIZE, BATCH_MAX_SIZE, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that may alter behaviour of this listener.
|
||||
*
|
||||
* @param delegate The delegate that should run on single thread.
|
||||
* @param queueSize The event queue size (default {@code 1024}).
|
||||
* @param batchMaxSize The maximum batch size delegate should receive (default {@code 500}).
|
||||
* @param blockOnLastEvent Should this listener block on last transfer end (completed or corrupted) block? (default {@code true}).
|
||||
*/
|
||||
public SimplexTransferListener(
|
||||
TransferListener delegate, int queueSize, int batchMaxSize, boolean blockOnLastEvent) {
|
||||
this.delegate = requireNonNull(delegate);
|
||||
if (queueSize < 1 || batchMaxSize < 1) {
|
||||
throw new IllegalArgumentException("Queue and batch sizes must be greater than 1");
|
||||
}
|
||||
this.batchMaxSize = batchMaxSize;
|
||||
this.blockOnLastEvent = blockOnLastEvent;
|
||||
|
||||
this.eventQueue = new ArrayBlockingQueue<>(queueSize);
|
||||
Thread updater = new Thread(this::feedConsumer);
|
||||
updater.setDaemon(true);
|
||||
updater.start();
|
||||
}
|
||||
|
||||
public TransferListener getDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
private void feedConsumer() {
|
||||
final ArrayList<Exchange> batch = new ArrayList<>(batchMaxSize);
|
||||
try {
|
||||
while (true) {
|
||||
batch.clear();
|
||||
if (eventQueue.drainTo(batch, BATCH_MAX_SIZE) == 0) {
|
||||
batch.add(eventQueue.take());
|
||||
}
|
||||
demux(batch);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void demux(List<Exchange> exchanges) {
|
||||
for (Exchange exchange : exchanges) {
|
||||
exchange.process(transferEvent -> {
|
||||
TransferEvent.EventType type = transferEvent.getType();
|
||||
try {
|
||||
switch (type) {
|
||||
case INITIATED:
|
||||
delegate.transferInitiated(transferEvent);
|
||||
break;
|
||||
case STARTED:
|
||||
delegate.transferStarted(transferEvent);
|
||||
break;
|
||||
case PROGRESSED:
|
||||
delegate.transferProgressed(transferEvent);
|
||||
break;
|
||||
case CORRUPTED:
|
||||
delegate.transferCorrupted(transferEvent);
|
||||
break;
|
||||
case SUCCEEDED:
|
||||
delegate.transferSucceeded(transferEvent);
|
||||
break;
|
||||
case FAILED:
|
||||
delegate.transferFailed(transferEvent);
|
||||
break;
|
||||
default:
|
||||
LOGGER.warn("Invalid TransferEvent.EventType={}; ignoring it", type);
|
||||
}
|
||||
} catch (TransferCancelledException e) {
|
||||
ongoing.put(new TransferResourceIdentifier(transferEvent.getResource()), Boolean.FALSE);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void put(TransferEvent event, boolean last) {
|
||||
try {
|
||||
Exchange exchange;
|
||||
if (blockOnLastEvent && last) {
|
||||
exchange = new BlockingExchange(event);
|
||||
} else {
|
||||
exchange = new Exchange(event);
|
||||
}
|
||||
eventQueue.put(exchange);
|
||||
exchange.waitForProcessed();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final ConcurrentHashMap<TransferResourceIdentifier, Boolean> ongoing = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void transferInitiated(TransferEvent event) {
|
||||
ongoing.putIfAbsent(new TransferResourceIdentifier(event.getResource()), Boolean.TRUE);
|
||||
put(event, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferStarted(TransferEvent event) throws TransferCancelledException {
|
||||
if (ongoing.get(new TransferResourceIdentifier(event.getResource())) == Boolean.FALSE) {
|
||||
throw new TransferCancelledException();
|
||||
}
|
||||
put(event, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferProgressed(TransferEvent event) throws TransferCancelledException {
|
||||
if (ongoing.get(new TransferResourceIdentifier(event.getResource())) == Boolean.FALSE) {
|
||||
throw new TransferCancelledException();
|
||||
}
|
||||
put(event, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferCorrupted(TransferEvent event) throws TransferCancelledException {
|
||||
if (ongoing.get(new TransferResourceIdentifier(event.getResource())) == Boolean.FALSE) {
|
||||
throw new TransferCancelledException();
|
||||
}
|
||||
put(event, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferSucceeded(TransferEvent event) {
|
||||
ongoing.remove(new TransferResourceIdentifier(event.getResource()));
|
||||
put(event, ongoing.isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferFailed(TransferEvent event) {
|
||||
ongoing.remove(new TransferResourceIdentifier(event.getResource()));
|
||||
put(event, ongoing.isEmpty());
|
||||
}
|
||||
|
||||
private static class Exchange {
|
||||
private final TransferEvent event;
|
||||
|
||||
private Exchange(TransferEvent event) {
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
public void process(Consumer<TransferEvent> consumer) {
|
||||
consumer.accept(event);
|
||||
}
|
||||
|
||||
public void waitForProcessed() throws InterruptedException {
|
||||
// nothing, is async
|
||||
}
|
||||
}
|
||||
|
||||
private static class BlockingExchange extends Exchange {
|
||||
private final CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
private BlockingExchange(TransferEvent event) {
|
||||
super(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(Consumer<TransferEvent> consumer) {
|
||||
super.process(consumer);
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void waitForProcessed() throws InterruptedException {
|
||||
latch.await();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cling.transfer;
|
||||
|
||||
import org.eclipse.aether.transfer.AbstractTransferListener;
|
||||
import org.eclipse.aether.transfer.TransferCancelledException;
|
||||
import org.eclipse.aether.transfer.TransferEvent;
|
||||
import org.eclipse.aether.transfer.TransferResource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Slf4jMavenTransferListener
|
||||
*/
|
||||
public class Slf4jMavenTransferListener extends AbstractTransferListener {
|
||||
|
||||
protected final Logger out;
|
||||
|
||||
public Slf4jMavenTransferListener() {
|
||||
this.out = LoggerFactory.getLogger(Slf4jMavenTransferListener.class);
|
||||
}
|
||||
|
||||
// TODO should we deprecate?
|
||||
public Slf4jMavenTransferListener(Logger out) {
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferInitiated(TransferEvent event) {
|
||||
String action = event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploading" : "Downloading";
|
||||
String direction = event.getRequestType() == TransferEvent.RequestType.PUT ? "to" : "from";
|
||||
|
||||
TransferResource resource = event.getResource();
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.append(action).append(' ').append(direction).append(' ').append(resource.getRepositoryId());
|
||||
message.append(": ");
|
||||
message.append(resource.getRepositoryUrl()).append(resource.getResourceName());
|
||||
|
||||
out.info(message.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferCorrupted(TransferEvent event) throws TransferCancelledException {
|
||||
TransferResource resource = event.getResource();
|
||||
out.warn(
|
||||
"{} from {} for {}{}",
|
||||
event.getException().getMessage(),
|
||||
resource.getRepositoryId(),
|
||||
resource.getRepositoryUrl(),
|
||||
resource.getResourceName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferSucceeded(TransferEvent event) {
|
||||
String action = (event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploaded" : "Downloaded");
|
||||
String direction = event.getRequestType() == TransferEvent.RequestType.PUT ? "to" : "from";
|
||||
|
||||
TransferResource resource = event.getResource();
|
||||
long contentLength = event.getTransferredBytes();
|
||||
FileSizeFormat format = new FileSizeFormat();
|
||||
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.append(action).append(' ').append(direction).append(' ').append(resource.getRepositoryId());
|
||||
message.append(": ");
|
||||
message.append(resource.getRepositoryUrl())
|
||||
.append(resource.getResourceName())
|
||||
.append(" (");
|
||||
format.format(message, contentLength);
|
||||
|
||||
long duration = System.currentTimeMillis() - resource.getTransferStartTime();
|
||||
if (duration > 0L) {
|
||||
double bytesPerSecond = contentLength / (duration / 1000.0);
|
||||
message.append(" at ");
|
||||
format.format(message, (long) bytesPerSecond);
|
||||
message.append("/s");
|
||||
}
|
||||
|
||||
message.append(')');
|
||||
out.info(message.toString());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cling.transfer;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.apache.maven.api.annotations.Nullable;
|
||||
import org.eclipse.aether.transfer.TransferResource;
|
||||
|
||||
/**
|
||||
* Immutable identifier of a {@link TransferResource}.
|
||||
* The {@link TransferResource} is not immutable and does not implement {@code Objects#equals} and {@code Objects#hashCode} methods,
|
||||
* making it not very suitable for usage in collections.
|
||||
*/
|
||||
record TransferResourceIdentifier(String repositoryId, String repositoryUrl, String resourceName, @Nullable Path file) {
|
||||
TransferResourceIdentifier(TransferResource resource) {
|
||||
this(resource.getRepositoryId(), resource.getRepositoryUrl(), resource.getResourceName(), resource.getPath());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cling.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.maven.jline.MessageUtils;
|
||||
import org.codehaus.plexus.util.Os;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* Utility class used to report errors, statistics, application version info, etc.
|
||||
*
|
||||
*/
|
||||
public final class CLIReportingUtils {
|
||||
// CHECKSTYLE_OFF: MagicNumber
|
||||
public static final long MB = 1024 * 1024;
|
||||
|
||||
private static final long ONE_SECOND = 1000L;
|
||||
|
||||
private static final long ONE_MINUTE = 60 * ONE_SECOND;
|
||||
|
||||
private static final long ONE_HOUR = 60 * ONE_MINUTE;
|
||||
|
||||
private static final long ONE_DAY = 24 * ONE_HOUR;
|
||||
// CHECKSTYLE_ON: MagicNumber
|
||||
|
||||
public static final String BUILD_VERSION_PROPERTY = "version";
|
||||
|
||||
public static String showVersion() {
|
||||
return showVersion(null, null);
|
||||
}
|
||||
|
||||
public static String showVersion(String commandLine, String terminal) {
|
||||
final String ls = System.lineSeparator();
|
||||
Properties properties = getBuildProperties();
|
||||
StringBuilder version = new StringBuilder(256);
|
||||
version.append(MessageUtils.builder().strong(createMavenVersionString(properties)))
|
||||
.append(ls);
|
||||
version.append(reduce(properties.getProperty("distributionShortName") + " home: "
|
||||
+ System.getProperty("maven.home", "<unknown Maven " + "home>")))
|
||||
.append(ls);
|
||||
version.append("Java version: ")
|
||||
.append(System.getProperty("java.version", "<unknown Java version>"))
|
||||
.append(", vendor: ")
|
||||
.append(System.getProperty("java.vendor", "<unknown vendor>"))
|
||||
.append(", runtime: ")
|
||||
.append(System.getProperty("java.home", "<unknown runtime>"))
|
||||
.append(ls);
|
||||
version.append("Default locale: ")
|
||||
.append(Locale.getDefault())
|
||||
.append(", platform encoding: ")
|
||||
.append(System.getProperty("file.encoding", "<unknown encoding>"))
|
||||
.append(ls);
|
||||
version.append("OS name: \"")
|
||||
.append(Os.OS_NAME)
|
||||
.append("\", version: \"")
|
||||
.append(Os.OS_VERSION)
|
||||
.append("\", arch: \"")
|
||||
.append(Os.OS_ARCH)
|
||||
.append("\", family: \"")
|
||||
.append(Os.OS_FAMILY)
|
||||
.append('\"');
|
||||
// Add process information using modern Java API
|
||||
if (commandLine != null) {
|
||||
version.append(ls).append("Command line: ").append(commandLine);
|
||||
}
|
||||
if (terminal != null) {
|
||||
version.append(ls).append("Terminal: ").append(terminal);
|
||||
}
|
||||
return version.toString();
|
||||
}
|
||||
|
||||
public static String showVersionMinimal() {
|
||||
Properties properties = getBuildProperties();
|
||||
String version = reduce(properties.getProperty(BUILD_VERSION_PROPERTY));
|
||||
return (version != null ? version : "<version unknown>");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a human-readable string containing the Maven version, buildnumber, and time of build
|
||||
*
|
||||
* @param buildProperties The build properties
|
||||
* @return Readable build info
|
||||
*/
|
||||
public static String createMavenVersionString(Properties buildProperties) {
|
||||
String timestamp = reduce(buildProperties.getProperty("timestamp"));
|
||||
String version = reduce(buildProperties.getProperty(BUILD_VERSION_PROPERTY));
|
||||
String rev = reduce(buildProperties.getProperty("buildNumber"));
|
||||
String distributionName = reduce(buildProperties.getProperty("distributionName"));
|
||||
|
||||
String msg = distributionName + " ";
|
||||
msg += (version != null ? version : "<version unknown>");
|
||||
if (rev != null || timestamp != null) {
|
||||
msg += " (";
|
||||
msg += (rev != null ? rev : "");
|
||||
if (timestamp != null && !timestamp.isEmpty()) {
|
||||
String ts = formatTimestamp(Long.parseLong(timestamp));
|
||||
msg += (rev != null ? "; " : "") + ts;
|
||||
}
|
||||
msg += ")";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
private static String reduce(String s) {
|
||||
return (s != null ? (s.startsWith("${") && s.endsWith("}") ? null : s) : null);
|
||||
}
|
||||
|
||||
public static Properties getBuildProperties() {
|
||||
Properties properties = new Properties();
|
||||
|
||||
try (InputStream resourceAsStream =
|
||||
CLIReportingUtils.class.getResourceAsStream("/org/apache/maven/messages/build.properties")) {
|
||||
|
||||
if (resourceAsStream != null) {
|
||||
properties.load(resourceAsStream);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("Unable determine version from JAR file: " + e.getMessage());
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
public static void showError(Logger logger, String message, Throwable e, boolean showStackTrace) {
|
||||
if (logger == null) {
|
||||
System.err.println(message);
|
||||
if (showStackTrace && e != null) {
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (showStackTrace) {
|
||||
logger.error(message, e);
|
||||
} else {
|
||||
logger.error(message);
|
||||
|
||||
if (e != null) {
|
||||
logger.error(e.getMessage());
|
||||
|
||||
for (Throwable cause = e.getCause();
|
||||
cause != null && cause != cause.getCause();
|
||||
cause = cause.getCause()) {
|
||||
logger.error("Caused by: {}", cause.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String formatTimestamp(long timestamp) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
|
||||
return sdf.format(new Date(timestamp));
|
||||
}
|
||||
|
||||
public static String formatDuration(long duration) {
|
||||
// CHECKSTYLE_OFF: MagicNumber
|
||||
long ms = duration % 1000;
|
||||
long s = (duration / ONE_SECOND) % 60;
|
||||
long m = (duration / ONE_MINUTE) % 60;
|
||||
long h = (duration / ONE_HOUR) % 24;
|
||||
long d = duration / ONE_DAY;
|
||||
// CHECKSTYLE_ON: MagicNumber
|
||||
|
||||
String format;
|
||||
if (d > 0) {
|
||||
// Length 11+ chars
|
||||
format = "%d d %02d:%02d h";
|
||||
} else if (h > 0) {
|
||||
// Length 7 chars
|
||||
format = "%2$02d:%3$02d h";
|
||||
} else if (m > 0) {
|
||||
// Length 9 chars
|
||||
format = "%3$02d:%4$02d min";
|
||||
} else {
|
||||
// Length 7-8 chars
|
||||
format = "%4$d.%5$03d s";
|
||||
}
|
||||
|
||||
return String.format(format, d, h, m, s, ms);
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
# key = Slf4j effective logger factory implementation
|
||||
# value = corresponding o.a.m.cli.logging.Slf4jConfiguration class
|
||||
org.slf4j.impl.SimpleLoggerFactory=org.apache.maven.cli.logging.impl.MavenSimpleConfiguration
|
||||
org.apache.maven.slf4j.MavenLoggerFactory=org.apache.maven.cli.logging.impl.MavenSimpleConfiguration
|
||||
org.apache.logging.slf4j.Log4jLoggerFactory=org.apache.maven.cli.logging.impl.Log4j2Configuration
|
||||
ch.qos.logback.classic.LoggerContext=org.apache.maven.cli.logging.impl.LogbackConfiguration
|
||||
org.slf4j.impl.SimpleLoggerFactory=org.apache.maven.cling.logging.impl.MavenSimpleConfiguration
|
||||
org.apache.maven.slf4j.MavenLoggerFactory=org.apache.maven.cling.logging.impl.MavenSimpleConfiguration
|
||||
org.apache.logging.slf4j.Log4jLoggerFactory=org.apache.maven.cling.logging.impl.Log4j2Configuration
|
||||
ch.qos.logback.classic.LoggerContext=org.apache.maven.cling.logging.impl.LogbackConfiguration
|
Loading…
Reference in New Issue