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