You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2022/05/10 06:53:03 UTC
[maven-build-cache-extension] branch master updated: [MBUILDCACHE-18] Use m-resolver transport layer instead of redefining another one (#10)
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-build-cache-extension.git
The following commit(s) were added to refs/heads/master by this push:
new a3a44e7 [MBUILDCACHE-18] Use m-resolver transport layer instead of redefining another one (#10)
a3a44e7 is described below
commit a3a44e72404228c536b5a8c21d2e67f0183452a1
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Tue May 10 08:52:58 2022 +0200
[MBUILDCACHE-18] Use m-resolver transport layer instead of redefining another one (#10)
* [MBUILDCACHE-18] Use m-resolver transport layer instead of redefining another one
* Move m-resolver as provided, clean other dependencies
---
pom.xml | 17 +-
.../maven/buildcache/CacheControllerImpl.java | 2 +-
.../maven/buildcache/RemoteCacheRepository.java | 3 +
...oryImpl.java => RemoteCacheRepositoryImpl.java} | 164 ++---
.../apache/maven/buildcache/WagonConfigurator.java | 101 ---
.../org/apache/maven/buildcache/WagonProvider.java | 65 --
.../buildcache/WagonRemoteCacheRepository.java | 696 ---------------------
src/main/mdo/build-cache-config.mdo | 4 +-
src/site/markdown/getting-started.md | 2 +-
src/site/markdown/remote-cache.md | 4 +-
10 files changed, 96 insertions(+), 962 deletions(-)
diff --git a/pom.xml b/pom.xml
index 5700d9a..9f625cc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -98,9 +98,10 @@ under the License.
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpclient</artifactId>
- <version>4.5.13</version>
+ <groupId>org.apache.maven.resolver</groupId>
+ <artifactId>maven-resolver-transport-http</artifactId>
+ <version>${resolverVersion}</version>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>net.openhft</groupId>
@@ -132,16 +133,6 @@ under the License.
<artifactId>plexus-utils</artifactId>
<version>${plexusUtilsVersion}</version>
</dependency>
- <dependency>
- <groupId>org.apache.maven.wagon</groupId>
- <artifactId>wagon-http</artifactId>
- <version>${wagonVersion}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.maven.resolver</groupId>
- <artifactId>maven-resolver-util</artifactId>
- <version>${resolverVersion}</version>
- </dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
diff --git a/src/main/java/org/apache/maven/buildcache/CacheControllerImpl.java b/src/main/java/org/apache/maven/buildcache/CacheControllerImpl.java
index 9989d94..8cfb145 100644
--- a/src/main/java/org/apache/maven/buildcache/CacheControllerImpl.java
+++ b/src/main/java/org/apache/maven/buildcache/CacheControllerImpl.java
@@ -91,7 +91,7 @@ import static org.apache.maven.buildcache.CacheResult.failure;
import static org.apache.maven.buildcache.CacheResult.partialSuccess;
import static org.apache.maven.buildcache.CacheResult.rebuilded;
import static org.apache.maven.buildcache.CacheResult.success;
-import static org.apache.maven.buildcache.HttpCacheRepositoryImpl.BUILDINFO_XML;
+import static org.apache.maven.buildcache.RemoteCacheRepository.BUILDINFO_XML;
import static org.apache.maven.buildcache.checksum.KeyUtils.getVersionlessProjectKey;
import static org.apache.maven.buildcache.checksum.MavenProjectInput.CACHE_IMPLEMENTATION_VERSION;
diff --git a/src/main/java/org/apache/maven/buildcache/RemoteCacheRepository.java b/src/main/java/org/apache/maven/buildcache/RemoteCacheRepository.java
index 7e5768f..2615803 100644
--- a/src/main/java/org/apache/maven/buildcache/RemoteCacheRepository.java
+++ b/src/main/java/org/apache/maven/buildcache/RemoteCacheRepository.java
@@ -32,6 +32,9 @@ import org.apache.maven.project.MavenProject;
public interface RemoteCacheRepository extends CacheRepository
{
+ String BUILDINFO_XML = "buildinfo.xml";
+ String CACHE_REPORT_XML = "build-cache-report.xml";
+
/**
* Download an artifact to the given location.
* Returns <code>true</code> if success, <code>false</code> if the artifact does not exists
diff --git a/src/main/java/org/apache/maven/buildcache/HttpCacheRepositoryImpl.java b/src/main/java/org/apache/maven/buildcache/RemoteCacheRepositoryImpl.java
similarity index 66%
rename from src/main/java/org/apache/maven/buildcache/HttpCacheRepositoryImpl.java
rename to src/main/java/org/apache/maven/buildcache/RemoteCacheRepositoryImpl.java
index 748fcee..b4664fd 100644
--- a/src/main/java/org/apache/maven/buildcache/HttpCacheRepositoryImpl.java
+++ b/src/main/java/org/apache/maven/buildcache/RemoteCacheRepositoryImpl.java
@@ -18,10 +18,10 @@
*/
package org.apache.maven.buildcache;
-import java.io.ByteArrayInputStream;
+import java.io.Closeable;
+import java.io.File;
import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
+import java.net.URI;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
@@ -29,16 +29,6 @@ import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.inject.Named;
-import org.apache.commons.io.IOUtils;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.config.RequestConfig;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPut;
-import org.apache.http.entity.InputStreamEntity;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.maven.SessionScoped;
import org.apache.maven.buildcache.checksum.MavenProjectInput;
import org.apache.maven.buildcache.xml.Build;
@@ -50,46 +40,69 @@ import org.apache.maven.buildcache.xml.report.CacheReport;
import org.apache.maven.buildcache.xml.report.ProjectReport;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.project.MavenProject;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.repository.Authentication;
+import org.eclipse.aether.repository.Proxy;
+import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.spi.connector.transport.GetTask;
+import org.eclipse.aether.spi.connector.transport.PutTask;
+import org.eclipse.aether.spi.connector.transport.Transporter;
+import org.eclipse.aether.spi.connector.transport.TransporterProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * HTTP remote cache repository implementation.
+ * Remote cache repository implementation.
*/
@SessionScoped
-@Named( "http" )
-public class HttpCacheRepositoryImpl implements RemoteCacheRepository
+@Named( "resolver" )
+public class RemoteCacheRepositoryImpl implements RemoteCacheRepository, Closeable
{
- public static final String BUILDINFO_XML = "buildinfo.xml";
- public static final String CACHE_REPORT_XML = "build-cache-report.xml";
-
- private static final Logger LOGGER = LoggerFactory.getLogger( HttpCacheRepositoryImpl.class );
+ private static final Logger LOGGER = LoggerFactory.getLogger( RemoteCacheRepositoryImpl.class );
private final XmlService xmlService;
private final CacheConfig cacheConfig;
+ private final Transporter transporter;
@Inject
- public HttpCacheRepositoryImpl( XmlService xmlService, CacheConfig cacheConfig )
+ public RemoteCacheRepositoryImpl(
+ XmlService xmlService,
+ CacheConfig cacheConfig,
+ MavenSession mavenSession,
+ TransporterProvider transporterProvider )
+ throws Exception
{
this.xmlService = xmlService;
this.cacheConfig = cacheConfig;
+ if ( cacheConfig.isRemoteCacheEnabled() )
+ {
+ RepositorySystemSession session = mavenSession.getRepositorySession();
+ RemoteRepository repo = new RemoteRepository.Builder(
+ cacheConfig.getId(), "cache", cacheConfig.getUrl() ).build();
+ RemoteRepository mirror = session.getMirrorSelector().getMirror( repo );
+ RemoteRepository repoOrMirror = mirror != null ? mirror : repo;
+ Proxy proxy = session.getProxySelector().getProxy( repoOrMirror );
+ Authentication auth = session.getAuthenticationSelector().getAuthentication( repoOrMirror );
+ RemoteRepository repository = new RemoteRepository.Builder( repoOrMirror )
+ .setProxy( proxy )
+ .setAuthentication( auth )
+ .build();
+ this.transporter = transporterProvider.newTransporter( session, repository );
+ }
+ else
+ {
+ this.transporter = null;
+ }
}
- @SuppressWarnings( "checkstyle:constantname" )
- private static final ThreadLocal<HttpClient> httpClient = ThreadLocal
- .withInitial( HttpCacheRepositoryImpl::newHttpClient );
-
- @SuppressWarnings( "checkstyle:magicnumber" )
- private static CloseableHttpClient newHttpClient()
+ @Override
+ public void close() throws IOException
{
- int timeoutSeconds = 60;
- RequestConfig config = RequestConfig.custom()
- .setConnectTimeout( timeoutSeconds * 1000 )
- .setConnectionRequestTimeout( timeoutSeconds * 1000 )
- .setSocketTimeout( timeoutSeconds * 1000 )
- .build();
- return HttpClientBuilder.create().setDefaultRequestConfig( config ).build();
+ if ( transporter != null )
+ {
+ transporter.close();
+ }
}
@Nonnull
@@ -113,7 +126,7 @@ public class HttpCacheRepositoryImpl implements RemoteCacheRepository
throws IOException
{
final String resourceUrl = getResourceUrl( cacheResult.getContext(), BUILDINFO_XML );
- putToRemoteCache( new ByteArrayInputStream( xmlService.toBytes( build.getDto() ) ), resourceUrl );
+ putToRemoteCache( xmlService.toBytes( build.getDto() ), resourceUrl );
}
@Override
@@ -125,7 +138,7 @@ public class HttpCacheRepositoryImpl implements RemoteCacheRepository
+ "/" + rootProject.getArtifactId()
+ "/" + buildId
+ "/" + CACHE_REPORT_XML;
- putToRemoteCache( new ByteArrayInputStream( xmlService.toBytes( cacheReport ) ), resourceUrl );
+ putToRemoteCache( xmlService.toBytes( cacheReport ), resourceUrl );
}
@Override
@@ -133,10 +146,7 @@ public class HttpCacheRepositoryImpl implements RemoteCacheRepository
org.apache.maven.artifact.Artifact artifact ) throws IOException
{
final String resourceUrl = getResourceUrl( cacheResult.getContext(), CacheUtils.normalizedName( artifact ) );
- try ( InputStream inputStream = Files.newInputStream( artifact.getFile().toPath() ) )
- {
- putToRemoteCache( inputStream, resourceUrl );
- }
+ putToRemoteCache( artifact.getFile(), resourceUrl );
}
/**
@@ -147,50 +157,33 @@ public class HttpCacheRepositoryImpl implements RemoteCacheRepository
@Nonnull
public Optional<byte[]> getResourceContent( String url ) throws IOException
{
- HttpGet get = new HttpGet( url );
try
{
LOGGER.info( "Downloading {}", url );
- HttpResponse response = httpClient.get().execute( get );
- int statusCode = response.getStatusLine().getStatusCode();
- if ( statusCode != HttpStatus.SC_OK )
- {
- LOGGER.info( "Cannot download {}, status code: {}", url, statusCode );
- return Optional.empty();
- }
- try ( InputStream content = response.getEntity().getContent() )
- {
- return Optional.of( IOUtils.toByteArray( content ) );
- }
+ GetTask task = new GetTask( new URI( url ) );
+ transporter.get( task );
+ return Optional.of( task.getDataBytes() );
}
- finally
+ catch ( Exception e )
{
- get.releaseConnection();
+ LOGGER.info( "Cannot download {}", url, e );
+ return Optional.empty();
}
}
public boolean getResourceContent( String url, Path target ) throws IOException
{
- HttpGet get = new HttpGet( url );
try
{
LOGGER.info( "Downloading {}", url );
- HttpResponse response = httpClient.get().execute( get );
- int statusCode = response.getStatusLine().getStatusCode();
- if ( statusCode != HttpStatus.SC_OK )
- {
- LOGGER.info( "Cannot download {}, status code: {}", url, statusCode );
- return false;
- }
- try ( InputStream content = response.getEntity().getContent() )
- {
- Files.copy( content, target );
- return true;
- }
+ GetTask task = new GetTask( new URI( url ) ).setDataFile( target.toFile() );
+ transporter.get( task );
+ return true;
}
- finally
+ catch ( Exception e )
{
- get.releaseConnection();
+ LOGGER.info( "Cannot download {}: {}", url, e.toString() );
+ return false;
}
}
@@ -208,22 +201,33 @@ public class HttpCacheRepositoryImpl implements RemoteCacheRepository
+ artifactId + "/" + checksum + "/" + filename;
}
- /**
- * @param instream to be closed externally
- */
- private void putToRemoteCache( InputStream instream, String url ) throws IOException
+ private void putToRemoteCache( byte[] bytes, String url ) throws IOException
{
- HttpPut httpPut = new HttpPut( url );
try
{
- httpPut.setEntity( new InputStreamEntity( instream ) );
- HttpResponse response = httpClient.get().execute( httpPut );
- int statusCode = response.getStatusLine().getStatusCode();
- LOGGER.info( "Saved to remote cache {}. Status: {}", url, statusCode );
+ PutTask put = new PutTask( new URI( url ) );
+ put.setDataBytes( bytes );
+ transporter.put( put );
+ LOGGER.info( "Saved to remote cache {}", url );
}
- finally
+ catch ( Exception e )
+ {
+ LOGGER.info( "Unable to save to remote cache {}", url, e );
+ }
+ }
+
+ private void putToRemoteCache( File file, String url ) throws IOException
+ {
+ try
+ {
+ PutTask put = new PutTask( new URI( url ) );
+ put.setDataFile( file );
+ transporter.put( put );
+ LOGGER.info( "Saved to remote cache {}", url );
+ }
+ catch ( Exception e )
{
- httpPut.releaseConnection();
+ LOGGER.info( "Unable to save to remote cache {}", url, e );
}
}
diff --git a/src/main/java/org/apache/maven/buildcache/WagonConfigurator.java b/src/main/java/org/apache/maven/buildcache/WagonConfigurator.java
deleted file mode 100644
index a41c0cc..0000000
--- a/src/main/java/org/apache/maven/buildcache/WagonConfigurator.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.buildcache;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import org.apache.maven.wagon.Wagon;
-import org.codehaus.plexus.PlexusContainer;
-import org.codehaus.plexus.classworlds.realm.ClassRealm;
-import org.codehaus.plexus.component.configurator.AbstractComponentConfigurator;
-import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
-import org.codehaus.plexus.component.configurator.ConfigurationListener;
-import org.codehaus.plexus.component.configurator.converters.composite.ObjectWithFieldsConverter;
-import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
-import org.codehaus.plexus.configuration.PlexusConfiguration;
-import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
-import org.codehaus.plexus.util.xml.Xpp3Dom;
-
-import static java.util.Objects.requireNonNull;
-
-/**
- * A wagon configurator based on the Plexus component configuration framework.
- */
-@Singleton
-public class WagonConfigurator
-{
-
- private final PlexusContainer container;
-
- /**
- * Creates a wagon configurator using the specified Plexus container.
- *
- * @param container The Plexus container instance to use, must not be {@code null}.
- */
- @Inject
- public WagonConfigurator( final PlexusContainer container )
- {
- this.container = requireNonNull( container, "plexus container cannot be null" );
- }
-
- public void configure( Wagon wagon, Object configuration )
- throws Exception
- {
- requireNonNull( wagon, "wagon cannot be null" );
- requireNonNull( configuration, "configuration cannot be null" );
-
- PlexusConfiguration config;
- if ( configuration instanceof PlexusConfiguration )
- {
- config = ( PlexusConfiguration ) configuration;
- }
- else if ( configuration instanceof Xpp3Dom )
- {
- config = new XmlPlexusConfiguration( ( Xpp3Dom ) configuration );
- }
- else
- {
- throw new IllegalArgumentException( "unexpected configuration type: "
- + configuration.getClass().getName() );
- }
-
- WagonComponentConfigurator configurator = new WagonComponentConfigurator();
-
- configurator.configureComponent( wagon, config, container.getContainerRealm() );
- }
-
- static class WagonComponentConfigurator
- extends AbstractComponentConfigurator
- {
-
- @Override
- public void configureComponent( Object component, PlexusConfiguration configuration,
- ExpressionEvaluator expressionEvaluator, ClassRealm containerRealm,
- ConfigurationListener listener )
- throws ComponentConfigurationException
- {
- ObjectWithFieldsConverter converter = new ObjectWithFieldsConverter();
-
- converter.processConfiguration( converterLookup, component, containerRealm, configuration,
- expressionEvaluator, listener );
- }
-
- }
-
-}
diff --git a/src/main/java/org/apache/maven/buildcache/WagonProvider.java b/src/main/java/org/apache/maven/buildcache/WagonProvider.java
deleted file mode 100644
index f98c52a..0000000
--- a/src/main/java/org/apache/maven/buildcache/WagonProvider.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.buildcache;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import org.apache.maven.wagon.Wagon;
-import org.codehaus.plexus.PlexusContainer;
-import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
-import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
-
-import static java.util.Objects.requireNonNull;
-
-/**
- * A wagon provider backed by a Plexus container and the wagons registered with this container.
- */
-@Singleton
-public class WagonProvider
-{
-
- private final PlexusContainer container;
-
- /**
- * Creates a wagon provider using the specified Plexus container.
- *
- * @param container The Plexus container instance to use, must not be {@code null}.
- */
- @Inject
- public WagonProvider( final PlexusContainer container )
- {
- this.container = requireNonNull( container, "plexus container cannot be null" );
- }
-
- public Wagon lookup( String roleHint )
- throws ComponentLookupException
- {
- return container.lookup( Wagon.class, roleHint );
- }
-
- public void release( Wagon wagon )
- throws ComponentLifecycleException
- {
- if ( wagon != null )
- {
- container.release( wagon );
- }
- }
-
-}
diff --git a/src/main/java/org/apache/maven/buildcache/WagonRemoteCacheRepository.java b/src/main/java/org/apache/maven/buildcache/WagonRemoteCacheRepository.java
deleted file mode 100644
index b5ca255..0000000
--- a/src/main/java/org/apache/maven/buildcache/WagonRemoteCacheRepository.java
+++ /dev/null
@@ -1,696 +0,0 @@
-/*
- * 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.buildcache;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Properties;
-import java.util.Queue;
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicReference;
-import javax.annotation.Nonnull;
-import javax.annotation.PreDestroy;
-import javax.inject.Inject;
-import javax.inject.Named;
-import org.apache.maven.SessionScoped;
-import org.apache.maven.buildcache.checksum.MavenProjectInput;
-import org.apache.maven.buildcache.xml.Build;
-import org.apache.maven.buildcache.xml.CacheConfig;
-import org.apache.maven.buildcache.xml.CacheSource;
-import org.apache.maven.buildcache.xml.XmlService;
-import org.apache.maven.buildcache.xml.build.Artifact;
-import org.apache.maven.buildcache.xml.report.CacheReport;
-import org.apache.maven.buildcache.xml.report.ProjectReport;
-import org.apache.maven.execution.MavenExecutionRequest;
-import org.apache.maven.execution.MavenSession;
-import org.apache.maven.project.MavenProject;
-import org.apache.maven.repository.RepositorySystem;
-import org.apache.maven.wagon.ResourceDoesNotExistException;
-import org.apache.maven.wagon.StreamingWagon;
-import org.apache.maven.wagon.Wagon;
-import org.apache.maven.wagon.WagonException;
-import org.apache.maven.wagon.authentication.AuthenticationInfo;
-import org.apache.maven.wagon.proxy.ProxyInfo;
-import org.apache.maven.wagon.proxy.ProxyInfoProvider;
-import org.apache.maven.wagon.repository.Repository;
-import org.apache.maven.wagon.repository.RepositoryPermissions;
-import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
-import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
-import org.eclipse.aether.ConfigurationProperties;
-import org.eclipse.aether.RepositoryException;
-import org.eclipse.aether.RepositorySystemSession;
-import org.eclipse.aether.repository.Authentication;
-import org.eclipse.aether.repository.AuthenticationContext;
-import org.eclipse.aether.repository.Proxy;
-import org.eclipse.aether.repository.RemoteRepository;
-import org.eclipse.aether.transfer.NoTransporterException;
-import org.eclipse.aether.util.ConfigUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@SessionScoped
-@Named( "wagon" )
-@SuppressWarnings( "unused" )
-public class WagonRemoteCacheRepository implements RemoteCacheRepository
-{
-
- public static final String BUILDINFO_XML = "buildinfo.xml";
- public static final String CACHE_REPORT_XML = "cache-report.xml";
-
- private static final String CONFIG_PROP_CONFIG = "remote.caching.wagon.config";
- private static final String CONFIG_PROP_FILE_MODE = "remote.caching.wagon.perms.fileMode";
- private static final String CONFIG_PROP_DIR_MODE = "remote.caching.wagon.perms.dirMode";
- private static final String CONFIG_PROP_GROUP = "remote.caching.wagon.perms.group";
-
- private static final Logger LOGGER = LoggerFactory.getLogger( HttpCacheRepositoryImpl.class );
-
- private final MavenSession mavenSession;
- private final XmlService xmlService;
- private final CacheConfig cacheConfig;
- private final WagonConfigurator wagonConfigurator;
- private final WagonProvider wagonProvider;
-
- private final RemoteRepository repository;
- private final AuthenticationContext repoAuthContext;
- private final AuthenticationContext proxyAuthContext;
- private final String wagonHint;
- private final Repository wagonRepo;
- private final AuthenticationInfo wagonAuth;
- private final ProxyInfoProvider wagonProxy;
- private final Properties headers;
- private final AtomicBoolean closed = new AtomicBoolean();
- private final Queue<Wagon> wagons = new ConcurrentLinkedQueue<>();
- private final AtomicReference<Optional<CacheReport>> cacheReportSupplier = new AtomicReference<>();
-
- @Inject
- public WagonRemoteCacheRepository( MavenSession mavenSession,
- XmlService xmlService,
- CacheConfig cacheConfig,
- WagonProvider wagonProvider,
- WagonConfigurator wagonConfigurator,
- RepositorySystem repositorySystem )
- throws RepositoryException
- {
- this.xmlService = xmlService;
- this.cacheConfig = cacheConfig;
- this.mavenSession = mavenSession;
- this.wagonProvider = wagonProvider;
- this.wagonConfigurator = wagonConfigurator;
-
- MavenExecutionRequest request = mavenSession.getRequest();
- RepositorySystemSession session = mavenSession.getRepositorySession();
-
- cacheConfig.initialize();
-
- RemoteRepository repo = new RemoteRepository.Builder(
- cacheConfig.getId(), "cache", cacheConfig.getUrl() ).build();
- RemoteRepository mirror = session.getMirrorSelector().getMirror( repo );
- RemoteRepository repoOrMirror = mirror != null ? mirror : repo;
- Proxy proxy = session.getProxySelector().getProxy( repoOrMirror );
- Authentication auth = session.getAuthenticationSelector().getAuthentication( repoOrMirror );
- repository = new RemoteRepository.Builder( repoOrMirror )
- .setProxy( proxy )
- .setAuthentication( auth )
- .build();
-
- wagonRepo = new Repository( repository.getId(), repository.getUrl() );
- wagonRepo.setPermissions( getPermissions( repository.getId(), session ) );
-
- wagonHint = wagonRepo.getProtocol().toLowerCase( Locale.ENGLISH );
- if ( wagonHint.isEmpty() )
- {
- throw new IllegalArgumentException( "Could not find a wagon provider for " + wagonRepo );
- }
-
- try
- {
- wagons.add( lookupWagon() );
- }
- catch ( Exception e )
- {
- LOGGER.debug( "No transport {}", e, e );
- throw new NoTransporterException( repository, e );
- }
-
- repoAuthContext = AuthenticationContext.forRepository( session, repository );
- proxyAuthContext = AuthenticationContext.forProxy( session, repository );
-
- wagonAuth = getAuthenticationInfo( repoAuthContext );
- wagonProxy = getProxy( repository, proxyAuthContext );
-
- this.headers = new Properties();
- this.headers.put( "User-Agent", ConfigUtils.getString( session, ConfigurationProperties.DEFAULT_USER_AGENT,
- ConfigurationProperties.USER_AGENT ) );
- Map<?, ?> headers = ConfigUtils.getMap( session, null,
- ConfigurationProperties.HTTP_HEADERS + "." + repository.getId(),
- ConfigurationProperties.HTTP_HEADERS );
- if ( headers != null )
- {
- this.headers.putAll( headers );
- }
- }
-
- @PreDestroy
- void destroy()
- {
- if ( closed.compareAndSet( false, true ) )
- {
- AuthenticationContext.close( repoAuthContext );
- AuthenticationContext.close( proxyAuthContext );
-
- for ( Wagon wagon = wagons.poll(); wagon != null; wagon = wagons.poll() )
- {
- disconnectWagon( wagon );
- releaseWagon( wagon );
- }
- }
- }
-
- private static RepositoryPermissions getPermissions( String repoId, RepositorySystemSession session )
- {
- RepositoryPermissions result = null;
- RepositoryPermissions perms = new RepositoryPermissions();
- String suffix = '.' + repoId;
- String fileMode = ConfigUtils.getString( session, null, CONFIG_PROP_FILE_MODE + suffix );
- if ( fileMode != null )
- {
- perms.setFileMode( fileMode );
- result = perms;
- }
- String dirMode = ConfigUtils.getString( session, null, CONFIG_PROP_DIR_MODE + suffix );
- if ( dirMode != null )
- {
- perms.setDirectoryMode( dirMode );
- result = perms;
- }
- String group = ConfigUtils.getString( session, null, CONFIG_PROP_GROUP + suffix );
- if ( group != null )
- {
- perms.setGroup( group );
- result = perms;
- }
- return result;
- }
-
- private AuthenticationInfo getAuthenticationInfo( final AuthenticationContext authContext )
- {
- AuthenticationInfo auth = null;
-
- if ( authContext != null )
- {
- auth = new AuthenticationInfo()
- {
-
- @Override
- public String getUserName()
- {
- return authContext.get( AuthenticationContext.USERNAME );
- }
-
- @Override
- public String getPassword()
- {
- return authContext.get( AuthenticationContext.PASSWORD );
- }
-
- @Override
- public String getPrivateKey()
- {
- return authContext.get( AuthenticationContext.PRIVATE_KEY_PATH );
- }
-
- @Override
- public String getPassphrase()
- {
- return authContext.get( AuthenticationContext.PRIVATE_KEY_PASSPHRASE );
- }
- };
- }
-
- return auth;
- }
-
- private ProxyInfoProvider getProxy( RemoteRepository repository, final AuthenticationContext authContext )
- {
- ProxyInfoProvider proxy = null;
-
- Proxy p = repository.getProxy();
- if ( p != null )
- {
- final ProxyInfo prox;
- if ( authContext != null )
- {
- prox = new ProxyInfo()
- {
-
- @Override
- public String getUserName()
- {
- return authContext.get( AuthenticationContext.USERNAME );
- }
-
- @Override
- public String getPassword()
- {
- return authContext.get( AuthenticationContext.PASSWORD );
- }
-
- @Override
- public String getNtlmDomain()
- {
- return authContext.get( AuthenticationContext.NTLM_DOMAIN );
- }
-
- @Override
- public String getNtlmHost()
- {
- return authContext.get( AuthenticationContext.NTLM_WORKSTATION );
- }
- };
- }
- else
- {
- prox = new ProxyInfo();
- }
- prox.setType( p.getType() );
- prox.setHost( p.getHost() );
- prox.setPort( p.getPort() );
-
- proxy = protocol -> prox;
- }
-
- return proxy;
- }
-
- @Override
- @Nonnull
- public Optional<Build> findBuild( CacheContext context ) throws IOException
- {
- final String resourceUrl = doGetResourceUrl( context, BUILDINFO_XML );
- return doGet( resourceUrl )
- .map( content -> new Build( xmlService.loadBuild( content ), CacheSource.REMOTE ) );
- }
-
- @Override
- public boolean getArtifactContent( CacheContext context, Artifact artifact, Path target )
- throws IOException
- {
- return doGet( doGetResourceUrl( context, artifact.getFileName() ), target );
- }
-
- @Override
- public void saveBuildInfo( CacheResult cacheResult, Build build )
- throws IOException
- {
- final String resourceUrl = doGetResourceUrl( cacheResult.getContext(), BUILDINFO_XML );
- doPut( resourceUrl, xmlService.toBytes( build.getDto() ) );
- }
-
- @Override
- public void saveCacheReport( String buildId, MavenSession session, CacheReport cacheReport ) throws IOException
- {
- MavenProject rootProject = session.getTopLevelProject();
- final String resourceUrl = doGetResourceUrl( CACHE_REPORT_XML, rootProject, buildId );
- doPut( resourceUrl, xmlService.toBytes( cacheReport ) );
- }
-
- @Override
- public void saveArtifactFile( CacheResult cacheResult,
- org.apache.maven.artifact.Artifact artifact ) throws IOException
- {
- final String resourceUrl = doGetResourceUrl( cacheResult.getContext(), CacheUtils.normalizedName( artifact ) );
- doPut( resourceUrl, artifact.getFile().toPath() );
- }
-
- @Override
- public String getResourceUrl( CacheContext context, String filename )
- {
- String base = cacheConfig.getUrl();
- return base.endsWith( "/" )
- ? base + doGetResourceUrl( context, filename )
- : base + "/" + doGetResourceUrl( context, filename );
- }
-
- public String doGetResourceUrl( CacheContext context, String filename )
- {
- return doGetResourceUrl( filename, context.getProject(), context.getInputInfo().getChecksum() );
- }
-
- private String doGetResourceUrl( String filename, MavenProject project, String checksum )
- {
- return doGetResourceUrl( filename, project.getGroupId(), project.getArtifactId(), checksum );
- }
-
- private String doGetResourceUrl( String filename, String groupId, String artifactId, String checksum )
- {
- return MavenProjectInput.CACHE_IMPLEMENTATION_VERSION + "/" + groupId + "/"
- + artifactId + "/" + checksum + "/" + filename;
- }
-
- @Override
- public Optional<Build> findBaselineBuild( MavenProject project )
- {
- Optional<List<ProjectReport>> cachedProjectsHolder = findCacheInfo()
- .map( CacheReport::getProjects );
-
- if ( !cachedProjectsHolder.isPresent() )
- {
- return Optional.empty();
- }
-
- final List<ProjectReport> projects = cachedProjectsHolder.get();
- final Optional<ProjectReport> projectReportHolder = projects.stream()
- .filter( p -> project.getArtifactId().equals( p.getArtifactId() )
- && project.getGroupId().equals( p.getGroupId() ) )
- .findFirst();
-
- if ( !projectReportHolder.isPresent() )
- {
- return Optional.empty();
- }
-
- final ProjectReport projectReport = projectReportHolder.get();
-
- String url;
- if ( projectReport.getUrl() != null )
- {
- url = projectReport.getUrl();
- LOGGER.info( "Retrieving baseline buildinfo: {}", url );
- }
- else
- {
- url = doGetResourceUrl( BUILDINFO_XML, project, projectReport.getChecksum() );
- LOGGER.info( "Baseline project record doesn't have url, trying default location {}", url );
- }
-
- try
- {
- return doGet( url )
- .map( content -> new Build( xmlService.loadBuild( content ), CacheSource.REMOTE ) );
- }
- catch ( Exception e )
- {
- LOGGER.warn( "Error restoring baseline build at url: {}, skipping diff", url, e );
- return Optional.empty();
- }
- }
-
- private Optional<CacheReport> findCacheInfo()
- {
- Optional<CacheReport> report = cacheReportSupplier.get();
- if ( !report.isPresent() )
- {
- try
- {
- LOGGER.info( "Downloading baseline cache report from: {}", cacheConfig.getBaselineCacheUrl() );
- return doGet( cacheConfig.getBaselineCacheUrl() ).map( xmlService::loadCacheReport );
- }
- catch ( Exception e )
- {
- LOGGER.error( "Error downloading baseline report from: {}, skipping diff.",
- cacheConfig.getBaselineCacheUrl(), e );
- report = Optional.empty();
- }
- cacheReportSupplier.compareAndSet( null, report );
- }
- return report;
- }
-
- private void doPut( String url, Path path ) throws IOException
- {
- try
- {
- Wagon wagon = pollWagon();
- try
- {
- wagon.put( path.toFile(), url );
- }
- finally
- {
- wagons.add( wagon );
- }
- }
- catch ( Exception e )
- {
- throw new IOException( "Unable to upload resource " + url, e );
- }
- }
-
- private void doPut( String url, byte[] data ) throws IOException
- {
- try
- {
- Wagon wagon = pollWagon();
- try
- {
- if ( wagon instanceof StreamingWagon )
- {
- ( ( StreamingWagon ) wagon ).putFromStream(
- new ByteArrayInputStream( data ), url, data.length, 0 );
- }
- else
- {
- File temp = createTempFile();
- try
- {
- Files.write( temp.toPath(), data );
- wagon.put( temp, url );
- }
- finally
- {
- delete( temp );
- }
- }
- }
- finally
- {
- wagons.add( wagon );
- }
- }
- catch ( Exception e )
- {
- throw new IOException( "Unable to upload resource " + url, e );
- }
- }
-
- private Optional<byte[]> doGet( String url ) throws IOException
- {
- try
- {
- Wagon wagon = pollWagon();
- try
- {
- if ( wagon instanceof StreamingWagon )
- {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ( ( StreamingWagon ) wagon ).getToStream( url, baos );
- return Optional.of( baos.toByteArray() );
- }
- else
- {
- File temp = createTempFile();
- try
- {
- wagon.get( url, temp );
- return Optional.of( Files.readAllBytes( temp.toPath() ) );
- }
- finally
- {
- delete( temp );
- }
- }
- }
- finally
- {
- wagons.add( wagon );
- }
- }
- catch ( ResourceDoesNotExistException e )
- {
- return Optional.empty();
- }
- catch ( Exception e )
- {
- throw new IOException( "Unable to download resource " + url, e );
- }
- }
-
- private boolean doGet( String url, Path target ) throws IOException
- {
- try
- {
- Wagon wagon = pollWagon();
- try
- {
- wagon.get( url, target.toFile() );
- return true;
- }
- finally
- {
- wagons.add( wagon );
- }
- }
- catch ( ResourceDoesNotExistException e )
- {
- return false;
- }
- catch ( Exception e )
- {
- throw new IOException( "Unable to download resource " + url, e );
- }
- }
-
- private File createTempFile() throws IOException
- {
- return File.createTempFile( "maven-build-cache-", ".temp" );
- }
-
- @SuppressWarnings( "ResultOfMethodCallIgnored" )
- private void delete( File temp )
- {
- temp.delete();
- }
-
- private Wagon lookupWagon() throws ComponentLookupException
- {
- return wagonProvider.lookup( wagonHint );
- }
-
- private void releaseWagon( Wagon wagon )
- {
- try
- {
- wagonProvider.release( wagon );
- }
- catch ( ComponentLifecycleException e )
- {
- // ignore
- }
- }
-
- private void connectWagon( Wagon wagon )
- throws WagonException
- {
- if ( !headers.isEmpty() )
- {
- try
- {
- Method setHttpHeaders = wagon.getClass().getMethod( "setHttpHeaders", Properties.class );
- setHttpHeaders.invoke( wagon, headers );
- }
- catch ( NoSuchMethodException e )
- {
- // normal for non-http wagons
- }
- catch ( InvocationTargetException | IllegalAccessException | RuntimeException e )
- {
- LOGGER.debug( "Could not set user agent for Wagon {}", wagon.getClass().getName(), e );
- }
- }
-
- RepositorySystemSession session = mavenSession.getRepositorySession();
- int connectTimeout = ConfigUtils.getInteger( session, ConfigurationProperties.DEFAULT_CONNECT_TIMEOUT,
- ConfigurationProperties.CONNECT_TIMEOUT );
- int requestTimeout = ConfigUtils.getInteger( session, ConfigurationProperties.DEFAULT_REQUEST_TIMEOUT,
- ConfigurationProperties.REQUEST_TIMEOUT );
-
- wagon.setTimeout( Math.max( Math.max( connectTimeout, requestTimeout ), 0 ) );
-
- wagon.setInteractive( ConfigUtils.getBoolean( session, ConfigurationProperties.DEFAULT_INTERACTIVE,
- ConfigurationProperties.INTERACTIVE ) );
-
- Object configuration = ConfigUtils.getObject( session, null,
- CONFIG_PROP_CONFIG + "." + repository.getId() );
- if ( configuration != null && wagonConfigurator != null )
- {
- try
- {
- wagonConfigurator.configure( wagon, configuration );
- }
- catch ( Exception e )
- {
- LOGGER.warn( "Could not apply configuration for {} to Wagon {}",
- repository.getId(), wagon.getClass().getName(), e );
- }
- }
-
- wagon.connect( wagonRepo, wagonAuth, wagonProxy );
- }
-
- private void disconnectWagon( Wagon wagon )
- {
- try
- {
- if ( wagon != null )
- {
- wagon.disconnect();
- }
- }
- catch ( WagonException e )
- {
- LOGGER.debug( "Could not disconnect Wagon {}", wagon, e );
- }
- }
-
- private Wagon pollWagon()
- throws Exception
- {
- Wagon wagon = wagons.poll();
-
- if ( wagon == null )
- {
- try
- {
- wagon = lookupWagon();
- connectWagon( wagon );
- }
- catch ( Exception e )
- {
- releaseWagon( wagon );
- throw e;
- }
- }
- else if ( wagon.getRepository() == null )
- {
- try
- {
- connectWagon( wagon );
- }
- catch ( WagonException e )
- {
- wagons.add( wagon );
- throw e;
- }
- }
-
- return wagon;
- }
-
-}
diff --git a/src/main/mdo/build-cache-config.mdo b/src/main/mdo/build-cache-config.mdo
index 9465aa5..b7815e7 100644
--- a/src/main/mdo/build-cache-config.mdo
+++ b/src/main/mdo/build-cache-config.mdo
@@ -92,8 +92,8 @@ under the License.
<field xml.attribute="true">
<name>transport</name>
<type>String</type>
- <defaultValue>http</defaultValue>
- <description>The transport to use, either 'http' or 'wagon'.</description>
+ <defaultValue>resolver</defaultValue>
+ <description>The transport to use, currently, only 'resolver' is supported.</description>
</field>
<field xml.attribute="true">
<name>id</name>
diff --git a/src/site/markdown/getting-started.md b/src/site/markdown/getting-started.md
index f93212d..eb83536 100644
--- a/src/site/markdown/getting-started.md
+++ b/src/site/markdown/getting-started.md
@@ -66,6 +66,6 @@ checks could reduce both performance and cache efficiency (hit rate).
### Adding caching CI and remote cache
To leverage remote cache feature there should a shared storage provide. Any technology supported
-by [Maven Wagon](https://maven.apache.org/wagon/) will suffice. In simplest form it could be a http web server which
+by [Maven Resolver](https://maven.apache.org/resolver/) will suffice. In simplest form it could be a http web server which
supports get/put operations ([Nginx OSS](http://nginx.org/en/) with fs module or any other equivalent).
See [Remote cache setup](remote-cache.md) for detailed description of cache setup.
diff --git a/src/site/markdown/remote-cache.md b/src/site/markdown/remote-cache.md
index fa35ff6..3cadd1f 100644
--- a/src/site/markdown/remote-cache.md
+++ b/src/site/markdown/remote-cache.md
@@ -69,9 +69,7 @@ in [Servers](https://maven.apache.org/settings.html#Servers). The server should
TBD
```
-Beside the http server, remote cache could be configured using any storage which is supported
-by [Maven Wagon](https://maven.apache.org/wagon/). That includes a wide set of options, including SSH, FTP and many
-others. See Wagon documentation for a full list of options and other details.
+Beside the http server, remote cache could be configured using any storage which is supported by [Maven Resolver](https://maven.apache.org/resolver/). That includes a wide set of options, including SSH, FTP and many others through the use of [Maven Wagon](https://maven.apache.org/wagon/). See Wagon documentation for a full list of options and other details.
### Build selection