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.util.repository; 020 021import java.util.ArrayList; 022import java.util.HashMap; 023import java.util.List; 024import java.util.Locale; 025import java.util.Map; 026import java.util.StringTokenizer; 027import java.util.concurrent.CopyOnWriteArrayList; 028import java.util.regex.Pattern; 029 030import org.eclipse.aether.repository.Proxy; 031import org.eclipse.aether.repository.ProxySelector; 032import org.eclipse.aether.repository.RemoteRepository; 033 034import static java.util.Objects.requireNonNull; 035 036/** 037 * A simple proxy selector that selects the first matching proxy from a list of configured proxies. 038 */ 039public final class DefaultProxySelector implements ProxySelector { 040 041 private final List<ProxyDef> proxies = new CopyOnWriteArrayList<>(); 042 043 /** 044 * Adds the specified proxy definition to the selector. Proxy definitions are ordered, the first matching proxy for 045 * a given repository will be used. 046 * 047 * @param proxy the proxy definition to add, must not be {@code null} 048 * @param nonProxyHosts the list of (case-insensitive) host names to exclude from proxying, may be {@code null} 049 * @return this proxy selector for chaining, never {@code null} 050 */ 051 public DefaultProxySelector add(Proxy proxy, String nonProxyHosts) { 052 requireNonNull(proxy, "proxy cannot be null"); 053 proxies.add(new ProxyDef(proxy, nonProxyHosts)); 054 055 return this; 056 } 057 058 public Proxy getProxy(RemoteRepository repository) { 059 requireNonNull(repository, "repository cannot be null"); 060 Map<String, ProxyDef> candidates = new HashMap<>(); 061 062 String host = repository.getHost(); 063 for (ProxyDef proxy : proxies) { 064 if (!proxy.nonProxyHosts.isNonProxyHost(host)) { 065 String key = proxy.proxy.getType().toLowerCase(Locale.ENGLISH); 066 if (!candidates.containsKey(key)) { 067 candidates.put(key, proxy); 068 } 069 } 070 } 071 072 String protocol = repository.getProtocol().toLowerCase(Locale.ENGLISH); 073 074 if ("davs".equals(protocol)) { 075 protocol = "https"; 076 } else if ("dav".equals(protocol)) { 077 protocol = "http"; 078 } else if (protocol.startsWith("dav:")) { 079 protocol = protocol.substring("dav:".length()); 080 } 081 082 ProxyDef proxy = candidates.get(protocol); 083 if (proxy == null && "https".equals(protocol)) { 084 proxy = candidates.get("http"); 085 } 086 087 return (proxy != null) ? proxy.proxy : null; 088 } 089 090 static class NonProxyHosts { 091 092 private final Pattern[] patterns; 093 094 NonProxyHosts(String nonProxyHosts) { 095 List<Pattern> patterns = new ArrayList<>(); 096 if (nonProxyHosts != null) { 097 for (StringTokenizer tokenizer = new StringTokenizer(nonProxyHosts, "|"); tokenizer.hasMoreTokens(); ) { 098 String pattern = tokenizer.nextToken(); 099 pattern = pattern.replace(".", "\\.").replace("*", ".*"); 100 patterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE)); 101 } 102 } 103 this.patterns = patterns.toArray(new Pattern[0]); 104 } 105 106 boolean isNonProxyHost(String host) { 107 if (host != null) { 108 for (Pattern pattern : patterns) { 109 if (pattern.matcher(host).matches()) { 110 return true; 111 } 112 } 113 } 114 return false; 115 } 116 } 117 118 static class ProxyDef { 119 120 final Proxy proxy; 121 122 final NonProxyHosts nonProxyHosts; 123 124 ProxyDef(Proxy proxy, String nonProxyHosts) { 125 this.proxy = proxy; 126 this.nonProxyHosts = new NonProxyHosts(nonProxyHosts); 127 } 128 } 129}