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