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