View Javadoc
1   package org.eclipse.aether.util.repository;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   * 
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   * 
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.HashMap;
25  import java.util.List;
26  import java.util.Locale;
27  import java.util.Map;
28  import static java.util.Objects.requireNonNull;
29  import java.util.StringTokenizer;
30  import java.util.regex.Pattern;
31  
32  import org.eclipse.aether.repository.Proxy;
33  import org.eclipse.aether.repository.ProxySelector;
34  import org.eclipse.aether.repository.RemoteRepository;
35  
36  /**
37   * A simple proxy selector that selects the first matching proxy from a list of configured proxies.
38   */
39  public final class DefaultProxySelector
40      implements ProxySelector
41  {
42  
43      private List<ProxyDef> proxies = new ArrayList<ProxyDef>();
44  
45      /**
46       * Adds the specified proxy definition to the selector. Proxy definitions are ordered, the first matching proxy for
47       * a given repository will be used.
48       * 
49       * @param proxy The proxy definition to add, must not be {@code null}.
50       * @param nonProxyHosts The list of (case-insensitive) host names to exclude from proxying, may be {@code null}.
51       * @return This proxy selector for chaining, never {@code null}.
52       */
53      public DefaultProxySelector add( Proxy proxy, String nonProxyHosts )
54      {
55          requireNonNull( proxy, "proxy cannot be null" );
56          proxies.add( new ProxyDef( proxy, nonProxyHosts ) );
57  
58          return this;
59      }
60  
61      public Proxy getProxy( RemoteRepository repository )
62      {
63          Map<String, ProxyDef> candidates = new HashMap<String, ProxyDef>();
64  
65          String host = repository.getHost();
66          for ( ProxyDef proxy : proxies )
67          {
68              if ( !proxy.nonProxyHosts.isNonProxyHost( host ) )
69              {
70                  String key = proxy.proxy.getType().toLowerCase( Locale.ENGLISH );
71                  if ( !candidates.containsKey( key ) )
72                  {
73                      candidates.put( key, proxy );
74                  }
75              }
76          }
77  
78          String protocol = repository.getProtocol().toLowerCase( Locale.ENGLISH );
79  
80          if ( "davs".equals( protocol ) )
81          {
82              protocol = "https";
83          }
84          else if ( "dav".equals( protocol ) )
85          {
86              protocol = "http";
87          }
88          else if ( protocol.startsWith( "dav:" ) )
89          {
90              protocol = protocol.substring( "dav:".length() );
91          }
92  
93          ProxyDef proxy = candidates.get( protocol );
94          if ( proxy == null && "https".equals( protocol ) )
95          {
96              proxy = candidates.get( "http" );
97          }
98  
99          return ( proxy != null ) ? proxy.proxy : null;
100     }
101 
102     static class NonProxyHosts
103     {
104 
105         private final Pattern[] patterns;
106 
107         public NonProxyHosts( String nonProxyHosts )
108         {
109             List<Pattern> patterns = new ArrayList<Pattern>();
110             if ( nonProxyHosts != null )
111             {
112                 for ( StringTokenizer tokenizer = new StringTokenizer( nonProxyHosts, "|" ); tokenizer.hasMoreTokens(); )
113                 {
114                     String pattern = tokenizer.nextToken();
115                     pattern = pattern.replace( ".", "\\." ).replace( "*", ".*" );
116                     patterns.add( Pattern.compile( pattern, Pattern.CASE_INSENSITIVE ) );
117                 }
118             }
119             this.patterns = patterns.toArray( new Pattern[patterns.size()] );
120         }
121 
122         boolean isNonProxyHost( String host )
123         {
124             if ( host != null )
125             {
126                 for ( Pattern pattern : patterns )
127                 {
128                     if ( pattern.matcher( host ).matches() )
129                     {
130                         return true;
131                     }
132                 }
133             }
134             return false;
135         }
136 
137     }
138 
139     static class ProxyDef
140     {
141 
142         final Proxy proxy;
143 
144         final NonProxyHosts nonProxyHosts;
145 
146         public ProxyDef( Proxy proxy, String nonProxyHosts )
147         {
148             this.proxy = proxy;
149             this.nonProxyHosts = new NonProxyHosts( nonProxyHosts );
150         }
151 
152     }
153 
154 }