001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.internal.impl; 020 021import javax.inject.Inject; 022import javax.inject.Named; 023import javax.inject.Singleton; 024 025import java.util.ArrayList; 026import java.util.Collections; 027import java.util.List; 028import java.util.Map; 029 030import org.eclipse.aether.RepositorySystemSession; 031import org.eclipse.aether.impl.RepositoryConnectorProvider; 032import org.eclipse.aether.repository.RemoteRepository; 033import org.eclipse.aether.spi.connector.PipelineRepositoryConnectorFactory; 034import org.eclipse.aether.spi.connector.RepositoryConnector; 035import org.eclipse.aether.spi.connector.RepositoryConnectorFactory; 036import org.eclipse.aether.transfer.NoRepositoryConnectorException; 037import org.slf4j.Logger; 038import org.slf4j.LoggerFactory; 039 040import static java.util.Objects.requireNonNull; 041 042/** 043 */ 044@Singleton 045@Named 046public class DefaultRepositoryConnectorProvider implements RepositoryConnectorProvider { 047 048 private static final Logger LOGGER = LoggerFactory.getLogger(DefaultRepositoryConnectorProvider.class); 049 050 private final Map<String, RepositoryConnectorFactory> connectorFactories; 051 052 private final Map<String, PipelineRepositoryConnectorFactory> pipelineConnectorFactories; 053 054 @Inject 055 public DefaultRepositoryConnectorProvider( 056 Map<String, RepositoryConnectorFactory> connectorFactories, 057 Map<String, PipelineRepositoryConnectorFactory> pipelineConnectorFactories) { 058 this.connectorFactories = Collections.unmodifiableMap(connectorFactories); 059 this.pipelineConnectorFactories = Collections.unmodifiableMap(pipelineConnectorFactories); 060 } 061 062 @Override 063 public RepositoryConnector newRepositoryConnector(RepositorySystemSession session, RemoteRepository repository) 064 throws NoRepositoryConnectorException { 065 requireNonNull(repository, "remote repository cannot be null"); 066 067 if (repository.isBlocked()) { 068 if (repository.getMirroredRepositories().isEmpty()) { 069 throw new NoRepositoryConnectorException(repository, "Blocked repository: " + repository); 070 } else { 071 throw new NoRepositoryConnectorException( 072 repository, "Blocked mirror for repositories: " + repository.getMirroredRepositories()); 073 } 074 } 075 076 PrioritizedComponents<RepositoryConnectorFactory> factories = PrioritizedComponents.reuseOrCreate( 077 session, RepositoryConnectorFactory.class, connectorFactories, RepositoryConnectorFactory::getPriority); 078 079 List<NoRepositoryConnectorException> errors = new ArrayList<>(); 080 for (PrioritizedComponent<RepositoryConnectorFactory> factory : factories.getEnabled()) { 081 try { 082 RepositoryConnector connector = factory.getComponent().newInstance(session, repository); 083 084 if (LOGGER.isDebugEnabled()) { 085 StringBuilder buffer = new StringBuilder(256); 086 buffer.append("Using connector ") 087 .append(connector.getClass().getSimpleName()); 088 Utils.appendClassLoader(buffer, connector); 089 buffer.append(" with priority ").append(factory.getPriority()); 090 buffer.append(" for ").append(repository.getUrl()); 091 LOGGER.debug(buffer.toString()); 092 } 093 094 connector = pipelineConnector(session, repository, connector); 095 096 if (LOGGER.isDebugEnabled()) { 097 LOGGER.debug("Final pipeline: {}", connector); 098 } 099 100 return connector; 101 } catch (NoRepositoryConnectorException e) { 102 // continue and try next factory 103 LOGGER.debug("Could not obtain connector factory for {}", repository, e); 104 errors.add(e); 105 } 106 } 107 108 StringBuilder buffer = new StringBuilder(256); 109 if (factories.isEmpty()) { 110 buffer.append("No connector factories available"); 111 } else { 112 buffer.append("Cannot access ").append(repository.getUrl()); 113 buffer.append(" with type ").append(repository.getContentType()); 114 buffer.append(" using the available connector factories: "); 115 factories.list(buffer); 116 } 117 118 // create exception: if one error, make it cause 119 NoRepositoryConnectorException ex = new NoRepositoryConnectorException( 120 repository, buffer.toString(), errors.size() == 1 ? errors.get(0) : null); 121 // if more errors, make them all suppressed 122 if (errors.size() > 1) { 123 errors.forEach(ex::addSuppressed); 124 } 125 throw ex; 126 } 127 128 protected RepositoryConnector pipelineConnector( 129 RepositorySystemSession session, RemoteRepository repository, RepositoryConnector delegate) { 130 PrioritizedComponents<PipelineRepositoryConnectorFactory> factories = PrioritizedComponents.reuseOrCreate( 131 session, 132 PipelineRepositoryConnectorFactory.class, 133 pipelineConnectorFactories, 134 PipelineRepositoryConnectorFactory::getPriority); 135 for (PrioritizedComponent<PipelineRepositoryConnectorFactory> factory : factories.getEnabled()) { 136 delegate = factory.getComponent().newInstance(session, repository, delegate); 137 } 138 return delegate; 139 } 140}