content: package org.apache.archiva.proxy.base;
  
  /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   */
  
  import org.apache.archiva.configuration.provider.ArchivaConfiguration;
  import org.apache.archiva.configuration.model.NetworkProxyConfiguration;
  import org.apache.archiva.configuration.model.ProxyConnectorConfiguration;
  import org.apache.archiva.policies.Policy;
  import org.apache.archiva.policies.PolicyOption;
  import org.apache.archiva.policies.PolicyUtil;
  import org.apache.archiva.proxy.ProxyRegistry;
  import org.apache.archiva.proxy.model.NetworkProxy;
  import org.apache.archiva.proxy.model.ProxyConnector;
  import org.apache.archiva.proxy.model.RepositoryProxyHandler;
  import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
  import org.apache.archiva.repository.ManagedRepository;
  import org.apache.archiva.repository.RemoteRepository;
  import org.apache.archiva.repository.RepositoryType;
  import org.apache.archiva.event.EventHandler;
  import org.apache.archiva.repository.event.RepositoryRegistryEvent;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.springframework.stereotype.Service;
  
  import javax.annotation.PostConstruct;
  import javax.inject.Inject;
  import java.util.*;
  import java.util.function.Function;
  import java.util.stream.Collectors;
  
  /**
   * Default proxy registry implementation. Uses the archiva configuration for accessing and storing the
   * proxy information.
   *
   */
  @SuppressWarnings( "SpringJavaInjectionPointsAutowiringInspection" )
  @Service("proxyRegistry#default")
  public class ArchivaProxyRegistry implements ProxyRegistry, EventHandler<RepositoryRegistryEvent> {
  
      private static final Logger log = LoggerFactory.getLogger(ArchivaProxyRegistry.class);
  
      @Inject
      ArchivaConfiguration archivaConfiguration;
  
      @Inject
      List<RepositoryProxyHandler> repositoryProxyHandlers;
  
      @Inject
      List<Policy> policies;
  
      @Inject
      ArchivaRepositoryRegistry repositoryRegistry;
  
      private Map<String, NetworkProxy> networkProxyMap = new HashMap<>();
      private Map<RepositoryType, List<RepositoryProxyHandler>> handlerMap = new HashMap<>();
      private ProxyConnectorOrderComparator comparator = ProxyConnectorOrderComparator.getInstance();
  
      private Map<String, List<ProxyConnector>> connectorMap = new HashMap<>();
      private List<ProxyConnector> connectorList = new ArrayList<>();
      private Map<Policy, PolicyOption> policyMap = new HashMap<>( );
  
  
      @PostConstruct
      private void init() {
          if (repositoryProxyHandlers == null) {
              repositoryProxyHandlers = new ArrayList<>();
          }
          updateHandler();
          updateConnectors();
          updateNetworkProxies();
          repositoryRegistry.registerEventHandler(RepositoryRegistryEvent.RELOADED, this);
      }
  
      private ArchivaConfiguration getArchivaConfiguration() {
          return archivaConfiguration;
      }
  
      private void updateNetworkProxies() {
          this.networkProxyMap.clear();
          List<NetworkProxyConfiguration> networkProxies = getArchivaConfiguration().getConfiguration().getNetworkProxies();
          for (NetworkProxyConfiguration networkProxyConfig : networkProxies) {
              String key = networkProxyConfig.getId();
  
              NetworkProxy proxy = new NetworkProxy();
  
              proxy.setProtocol(networkProxyConfig.getProtocol());
              proxy.setHost(networkProxyConfig.getHost());
              proxy.setPort(networkProxyConfig.getPort());
              proxy.setUsername(networkProxyConfig.getUsername());
              proxy.setPassword(networkProxyConfig.getPassword()==null? new char[0] : networkProxyConfig.getPassword().toCharArray());
              proxy.setUseNtlm(networkProxyConfig.isUseNtlm());
  
              this.networkProxyMap.put(key, proxy);
          }
          for (RepositoryProxyHandler proxyHandler : repositoryProxyHandlers) {
              proxyHandler.setNetworkProxies(this.networkProxyMap);
          }
      }
  
      private void updateHandler( ) {
  
          for (RepositoryProxyHandler handler : repositoryProxyHandlers) {
              List<RepositoryType> types = handler.supports();
              for (RepositoryType type : types) {
                  if (!handlerMap.containsKey(type)) {
                      handlerMap.put(type, new ArrayList<>());
                  }
                  handlerMap.get(type).add(handler);
              }
              handler.setPolicies( policies );
          }
      }
  
      private void updateConnectors() {
          List<ProxyConnectorConfiguration> proxyConnectorConfigurations =
              getArchivaConfiguration().getConfiguration().getProxyConnectors();
  
          connectorList = proxyConnectorConfigurations.stream()
                  .map(this::buildProxyConnector)
                  .filter(Optional::isPresent)
                  .map(Optional::get)
                  .sorted(comparator).collect(Collectors.toList());
          connectorMap = connectorList.stream().collect(Collectors.groupingBy(a -> a.getSourceRepository().getId()));
          for (RepositoryProxyHandler handler : repositoryProxyHandlers) {
              handler.setProxyConnectors( connectorList );
          }
      }
  
  
      private Map<Policy, PolicyOption> getPolicyMap(ProxyConnectorConfiguration configuration) {
          Map<String, String> policyConfig = configuration.getPolicies( );
          return policies.stream().collect( Collectors.toMap( Function.identity(), p -> PolicyUtil.findOption( policyConfig.get(p.getId()), p ) ) );
      }
  
      private Optional<ProxyConnector> buildProxyConnector(ProxyConnectorConfiguration configuration) {
          ProxyConnector proxyConnector = new ProxyConnector();
          proxyConnector.setOrder(configuration.getOrder());
          proxyConnector.setBlacklist(configuration.getBlackListPatterns());
          proxyConnector.setWhitelist(configuration.getWhiteListPatterns());
          if (configuration.isDisabled()) {
              proxyConnector.disable();
          } else {
              proxyConnector.enable();
          }
          proxyConnector.setPolicies(getPolicyMap( configuration ));
          proxyConnector.setProperties(configuration.getProperties());
          proxyConnector.setProxyId(configuration.getProxyId());
          ManagedRepository srcRepo = repositoryRegistry.getManagedRepository(configuration.getSourceRepoId());
          if (srcRepo==null) {
              return Optional.empty();
          }
          proxyConnector.setSourceRepository(srcRepo);
          RemoteRepository targetRepo = repositoryRegistry.getRemoteRepository(configuration.getTargetRepoId());
          if (targetRepo==null) {
              return Optional.empty();
          }
          proxyConnector.setTargetRepository(targetRepo);
          return Optional.of(proxyConnector);
      }
  
      @Override
      public NetworkProxy getNetworkProxy(String id) {
          return this.networkProxyMap.get(id);
      }
  
      @Override
      public Map<RepositoryType, List<RepositoryProxyHandler>> getAllHandler() {
          return this.handlerMap;
      }
  
      @Override
      public List<RepositoryProxyHandler> getHandler(RepositoryType type) {
          if (this.handlerMap.containsKey(type)) {
              return this.handlerMap.get(type);
          } else {
              return new ArrayList<>();
          }
      }
  
      @Override
      public boolean hasHandler(RepositoryType type) {
          return this.handlerMap.containsKey(type);
      }
  
  
      @Override
      public List<ProxyConnector> getProxyConnectors() {
          return connectorList;
  
      }
  
      @Override
      public Map<String, List<ProxyConnector>> getProxyConnectorAsMap() {
          return connectorMap;
      }
  
      @Override
      public void reload( )
      {
          init();
      }
  
      @Override
      public void handle(RepositoryRegistryEvent event) {
          log.debug("Reload happened, updating proxy list");
          if (event.getType()== RepositoryRegistryEvent.RELOADED) {
              init();
          }
      }
  }
  