001package org.eclipse.aether.internal.impl;
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.util.ArrayList;
023import java.util.Collection;
024import java.util.List;
025import static java.util.Objects.requireNonNull;
026import java.util.Set;
027
028import javax.inject.Inject;
029import javax.inject.Named;
030import javax.inject.Singleton;
031
032import org.eclipse.aether.RepositorySystemSession;
033import org.eclipse.aether.impl.RepositoryConnectorProvider;
034import org.eclipse.aether.repository.Authentication;
035import org.eclipse.aether.repository.Proxy;
036import org.eclipse.aether.repository.RemoteRepository;
037import org.eclipse.aether.spi.connector.RepositoryConnector;
038import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
039import org.eclipse.aether.spi.locator.Service;
040import org.eclipse.aether.spi.locator.ServiceLocator;
041import org.eclipse.aether.transfer.NoRepositoryConnectorException;
042import org.slf4j.Logger;
043import org.slf4j.LoggerFactory;
044
045/**
046 */
047@Singleton
048@Named
049public class DefaultRepositoryConnectorProvider
050    implements RepositoryConnectorProvider, Service
051{
052
053    private static final Logger LOGGER = LoggerFactory.getLogger( DefaultRepositoryConnectorProvider.class );
054
055    private Collection<RepositoryConnectorFactory> connectorFactories = new ArrayList<>();
056
057    public DefaultRepositoryConnectorProvider()
058    {
059        // enables default constructor
060    }
061
062    @Inject
063    DefaultRepositoryConnectorProvider( Set<RepositoryConnectorFactory> connectorFactories )
064    {
065        setRepositoryConnectorFactories( connectorFactories );
066    }
067
068    public void initService( ServiceLocator locator )
069    {
070        connectorFactories = locator.getServices( RepositoryConnectorFactory.class );
071    }
072
073    public DefaultRepositoryConnectorProvider addRepositoryConnectorFactory( RepositoryConnectorFactory factory )
074    {
075        connectorFactories.add( requireNonNull( factory, "repository connector factory cannot be null" ) );
076        return this;
077    }
078
079    public DefaultRepositoryConnectorProvider setRepositoryConnectorFactories(
080            Collection<RepositoryConnectorFactory> factories )
081    {
082        if ( factories == null )
083        {
084            this.connectorFactories = new ArrayList<>();
085        }
086        else
087        {
088            this.connectorFactories = factories;
089        }
090        return this;
091    }
092
093    public RepositoryConnector newRepositoryConnector( RepositorySystemSession session, RemoteRepository repository )
094        throws NoRepositoryConnectorException
095    {
096        requireNonNull( repository, "remote repository cannot be null" );
097
098        PrioritizedComponents<RepositoryConnectorFactory> factories = new PrioritizedComponents<>( session );
099        for ( RepositoryConnectorFactory factory : this.connectorFactories )
100        {
101            factories.add( factory, factory.getPriority() );
102        }
103
104        List<NoRepositoryConnectorException> errors = new ArrayList<>();
105        for ( PrioritizedComponent<RepositoryConnectorFactory> factory : factories.getEnabled() )
106        {
107            try
108            {
109                RepositoryConnector connector = factory.getComponent().newInstance( session, repository );
110
111                if ( LOGGER.isDebugEnabled() )
112                {
113                    StringBuilder buffer = new StringBuilder( 256 );
114                    buffer.append( "Using connector " ).append( connector.getClass().getSimpleName() );
115                    Utils.appendClassLoader( buffer, connector );
116                    buffer.append( " with priority " ).append( factory.getPriority() );
117                    buffer.append( " for " ).append( repository.getUrl() );
118
119                    Authentication auth = repository.getAuthentication();
120                    if ( auth != null )
121                    {
122                        buffer.append( " with " ).append( auth );
123                    }
124
125                    Proxy proxy = repository.getProxy();
126                    if ( proxy != null )
127                    {
128                        buffer.append( " via " ).append( proxy.getHost() ).append( ':' ).append( proxy.getPort() );
129
130                        auth = proxy.getAuthentication();
131                        if ( auth != null )
132                        {
133                            buffer.append( " with " ).append( auth );
134                        }
135                    }
136
137                    LOGGER.debug( buffer.toString() );
138                }
139
140                return connector;
141            }
142            catch ( NoRepositoryConnectorException e )
143            {
144                // continue and try next factory
145                errors.add( e );
146            }
147        }
148        if ( LOGGER.isDebugEnabled() && errors.size() > 1 )
149        {
150            for ( Exception e : errors )
151            {
152                LOGGER.debug( "Could not obtain connector factory for {}", repository, e );
153            }
154        }
155
156        StringBuilder buffer = new StringBuilder( 256 );
157        if ( factories.isEmpty() )
158        {
159            buffer.append( "No connector factories available" );
160        }
161        else
162        {
163            buffer.append( "Cannot access " ).append( repository.getUrl() );
164            buffer.append( " with type " ).append( repository.getContentType() );
165            buffer.append( " using the available connector factories: " );
166            factories.list( buffer );
167        }
168
169        throw new NoRepositoryConnectorException( repository, buffer.toString(), errors.size() == 1 ? errors.get( 0 )
170                        : null );
171    }
172
173}