001package org.apache.maven.internal.aether;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.maven.RepositoryUtils;
023import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
024import org.apache.maven.bridge.MavenRepositorySystem;
025import org.apache.maven.eventspy.internal.EventSpyDispatcher;
026import org.apache.maven.execution.MavenExecutionRequest;
027import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
028import org.apache.maven.settings.Mirror;
029import org.apache.maven.settings.Proxy;
030import org.apache.maven.settings.Server;
031import org.apache.maven.settings.building.SettingsProblem;
032import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
033import org.apache.maven.settings.crypto.SettingsDecrypter;
034import org.apache.maven.settings.crypto.SettingsDecryptionResult;
035import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
036import org.codehaus.plexus.logging.Logger;
037import org.codehaus.plexus.util.xml.Xpp3Dom;
038import org.eclipse.aether.ConfigurationProperties;
039import org.eclipse.aether.DefaultRepositorySystemSession;
040import org.eclipse.aether.RepositorySystem;
041import org.eclipse.aether.repository.LocalRepository;
042import org.eclipse.aether.repository.NoLocalRepositoryManagerException;
043import org.eclipse.aether.repository.RepositoryPolicy;
044import org.eclipse.aether.repository.WorkspaceReader;
045import org.eclipse.aether.resolution.ResolutionErrorPolicy;
046import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory;
047import org.eclipse.aether.util.repository.AuthenticationBuilder;
048import org.eclipse.aether.util.repository.DefaultAuthenticationSelector;
049import org.eclipse.aether.util.repository.DefaultMirrorSelector;
050import org.eclipse.aether.util.repository.DefaultProxySelector;
051import org.eclipse.aether.util.repository.SimpleResolutionErrorPolicy;
052import org.eclipse.sisu.Nullable;
053
054import javax.inject.Inject;
055import javax.inject.Named;
056import java.io.IOException;
057import java.io.InputStream;
058import java.util.LinkedHashMap;
059import java.util.Map;
060import java.util.Properties;
061
062/**
063 * @since 3.3.0
064 */
065@Named
066public class DefaultRepositorySystemSessionFactory
067{
068    @Inject
069    private Logger logger;
070
071    @Inject
072    private ArtifactHandlerManager artifactHandlerManager;
073
074    @Inject
075    private RepositorySystem repoSystem;
076
077    @Inject
078    @Nullable
079    @Named( "simple" )
080    private LocalRepositoryManagerFactory simpleLocalRepoMgrFactory;
081
082    @Inject
083    @Nullable
084    @Named( "ide" )
085    private WorkspaceReader workspaceRepository;
086
087    @Inject
088    private SettingsDecrypter settingsDecrypter;
089
090    @Inject
091    private EventSpyDispatcher eventSpyDispatcher;
092
093    @Inject
094    MavenRepositorySystem mavenRepositorySystem;
095
096    public DefaultRepositorySystemSession newRepositorySession( MavenExecutionRequest request )
097    {
098        DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
099
100        session.setCache( request.getRepositoryCache() );
101
102        Map<Object, Object> configProps = new LinkedHashMap<>();
103        configProps.put( ConfigurationProperties.USER_AGENT, getUserAgent() );
104        configProps.put( ConfigurationProperties.INTERACTIVE, request.isInteractiveMode() );
105        configProps.putAll( request.getSystemProperties() );
106        configProps.putAll( request.getUserProperties() );
107
108        session.setOffline( request.isOffline() );
109        session.setChecksumPolicy( request.getGlobalChecksumPolicy() );
110        if ( request.isNoSnapshotUpdates() )
111        {
112            session.setUpdatePolicy( RepositoryPolicy.UPDATE_POLICY_NEVER );
113        }
114        else if ( request.isUpdateSnapshots() )
115        {
116            session.setUpdatePolicy( RepositoryPolicy.UPDATE_POLICY_ALWAYS );
117        }
118        else
119        {
120            session.setUpdatePolicy( null );
121        }
122
123        int errorPolicy = 0;
124        errorPolicy |= request.isCacheNotFound() ? ResolutionErrorPolicy.CACHE_NOT_FOUND : 0;
125        errorPolicy |= request.isCacheTransferError() ? ResolutionErrorPolicy.CACHE_TRANSFER_ERROR : 0;
126        session.setResolutionErrorPolicy(
127            new SimpleResolutionErrorPolicy( errorPolicy, errorPolicy | ResolutionErrorPolicy.CACHE_NOT_FOUND ) );
128
129        session.setArtifactTypeRegistry( RepositoryUtils.newArtifactTypeRegistry( artifactHandlerManager ) );
130
131        LocalRepository localRepo = new LocalRepository( request.getLocalRepository().getBasedir() );
132
133        if ( request.isUseLegacyLocalRepository() )
134        {
135            logger.warn( "Disabling enhanced local repository: using legacy is strongly discouraged to ensure"
136                             + " build reproducibility." );
137            try
138            {
139                session.setLocalRepositoryManager( simpleLocalRepoMgrFactory.newInstance( session, localRepo ) );
140            }
141            catch ( NoLocalRepositoryManagerException e )
142            {
143
144                logger.warn( "Failed to configure legacy local repository: back to default" );
145                session.setLocalRepositoryManager( repoSystem.newLocalRepositoryManager( session, localRepo ) );
146            }
147        }
148        else
149        {
150            session.setLocalRepositoryManager( repoSystem.newLocalRepositoryManager( session, localRepo ) );
151        }
152
153        if ( request.getWorkspaceReader() != null )
154        {
155            session.setWorkspaceReader( request.getWorkspaceReader() );
156        }
157        else
158        {
159            session.setWorkspaceReader( workspaceRepository );
160        }
161
162        DefaultSettingsDecryptionRequest decrypt = new DefaultSettingsDecryptionRequest();
163        decrypt.setProxies( request.getProxies() );
164        decrypt.setServers( request.getServers() );
165        SettingsDecryptionResult decrypted = settingsDecrypter.decrypt( decrypt );
166
167        if ( logger.isDebugEnabled() )
168        {
169            for ( SettingsProblem problem : decrypted.getProblems() )
170            {
171                logger.debug( problem.getMessage(), problem.getException() );
172            }
173        }
174
175        DefaultMirrorSelector mirrorSelector = new DefaultMirrorSelector();
176        for ( Mirror mirror : request.getMirrors() )
177        {
178            mirrorSelector.add( mirror.getId(), mirror.getUrl(), mirror.getLayout(), false, mirror.getMirrorOf(),
179                                mirror.getMirrorOfLayouts() );
180        }
181        session.setMirrorSelector( mirrorSelector );
182
183        DefaultProxySelector proxySelector = new DefaultProxySelector();
184        for ( Proxy proxy : decrypted.getProxies() )
185        {
186            AuthenticationBuilder authBuilder = new AuthenticationBuilder();
187            authBuilder.addUsername( proxy.getUsername() ).addPassword( proxy.getPassword() );
188            proxySelector.add(
189                new org.eclipse.aether.repository.Proxy( proxy.getProtocol(), proxy.getHost(), proxy.getPort(),
190                                                         authBuilder.build() ), proxy.getNonProxyHosts() );
191        }
192        session.setProxySelector( proxySelector );
193
194        DefaultAuthenticationSelector authSelector = new DefaultAuthenticationSelector();
195        for ( Server server : decrypted.getServers() )
196        {
197            AuthenticationBuilder authBuilder = new AuthenticationBuilder();
198            authBuilder.addUsername( server.getUsername() ).addPassword( server.getPassword() );
199            authBuilder.addPrivateKey( server.getPrivateKey(), server.getPassphrase() );
200            authSelector.add( server.getId(), authBuilder.build() );
201
202            if ( server.getConfiguration() != null )
203            {
204                Xpp3Dom dom = (Xpp3Dom) server.getConfiguration();
205                for ( int i = dom.getChildCount() - 1; i >= 0; i-- )
206                {
207                    Xpp3Dom child = dom.getChild( i );
208                    if ( "wagonProvider".equals( child.getName() ) )
209                    {
210                        dom.removeChild( i );
211                    }
212                }
213
214                XmlPlexusConfiguration config = new XmlPlexusConfiguration( dom );
215                configProps.put( "aether.connector.wagon.config." + server.getId(), config );
216            }
217
218            configProps.put( "aether.connector.perms.fileMode." + server.getId(), server.getFilePermissions() );
219            configProps.put( "aether.connector.perms.dirMode." + server.getId(), server.getDirectoryPermissions() );
220        }
221        session.setAuthenticationSelector( authSelector );
222
223        session.setTransferListener( request.getTransferListener() );
224
225        session.setRepositoryListener( eventSpyDispatcher.chainListener( new LoggingRepositoryListener( logger ) ) );
226
227        session.setUserProperties( request.getUserProperties() );
228        session.setSystemProperties( request.getSystemProperties() );
229        session.setConfigProperties( configProps );
230
231        mavenRepositorySystem.injectMirror( request.getRemoteRepositories(), request.getMirrors() );
232        mavenRepositorySystem.injectProxy( session, request.getRemoteRepositories() );
233        mavenRepositorySystem.injectAuthentication( session, request.getRemoteRepositories() );
234
235        mavenRepositorySystem.injectMirror( request.getPluginArtifactRepositories(), request.getMirrors() );
236        mavenRepositorySystem.injectProxy( session, request.getPluginArtifactRepositories() );
237        mavenRepositorySystem.injectAuthentication( session, request.getPluginArtifactRepositories() );
238
239        return session;
240    }
241
242    private String getUserAgent()
243    {
244        return "Apache-Maven/" + getMavenVersion() + " (Java " + System.getProperty( "java.version" ) + "; "
245            + System.getProperty( "os.name" ) + " " + System.getProperty( "os.version" ) + ")";
246    }
247
248    private String getMavenVersion()
249    {
250        Properties props = new Properties();
251
252        try ( InputStream is = getClass().getResourceAsStream(
253            "/META-INF/maven/org.apache.maven/maven-core/pom.properties" ) )
254        {
255            if ( is != null )
256            {
257                props.load( is );
258            }
259        }
260        catch ( IOException e )
261        {
262            logger.debug( "Failed to read Maven version", e );
263        }
264
265        return props.getProperty( "version", "unknown-version" );
266    }
267
268}