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