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