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.HashMap;
24  import java.util.List;
25  import java.util.Locale;
26  import java.util.Map;
27  import java.util.StringTokenizer;
28  import java.util.regex.Pattern;
29  
30  import org.eclipse.aether.repository.Proxy;
31  import org.eclipse.aether.repository.ProxySelector;
32  import org.eclipse.aether.repository.RemoteRepository;
33  
34  /**
35   * A simple proxy selector that selects the first matching proxy from a list of configured proxies.
36   */
37  public final class DefaultProxySelector
38      implements ProxySelector
39  {
40  
41      private List<ProxyDef> proxies = new ArrayList<ProxyDef>();
42  
43      /**
44       * Adds the specified proxy definition to the selector. Proxy definitions are ordered, the first matching proxy for
45       * a given repository will be used.
46       * 
47       * @param proxy The proxy definition to add, must not be {@code null}.
48       * @param nonProxyHosts The list of (case-insensitive) host names to exclude from proxying, may be {@code null}.
49       * @return This proxy selector for chaining, never {@code null}.
50       */
51      public DefaultProxySelector add( Proxy proxy, String nonProxyHosts )
52      {
53          if ( proxy == null )
54          {
55              throw new IllegalArgumentException( "proxy not specified" );
56          }
57          proxies.add( new ProxyDef( proxy, nonProxyHosts ) );
58  
59          return this;
60      }
61  
62      public Proxy getProxy( RemoteRepository repository )
63      {
64          Map<String, ProxyDef> candidates = new HashMap<String, ProxyDef>();
65  
66          String host = repository.getHost();
67          for ( ProxyDef proxy : proxies )
68          {
69              if ( !proxy.nonProxyHosts.isNonProxyHost( host ) )
70              {
71                  String key = proxy.proxy.getType().toLowerCase( Locale.ENGLISH );
72                  if ( !candidates.containsKey( key ) )
73                  {
74                      candidates.put( key, proxy );
75                  }
76              }
77          }
78  
79          String protocol = repository.getProtocol().toLowerCase( Locale.ENGLISH );
80  
81          if ( "davs".equals( protocol ) )
82          {
83              protocol = "https";
84          }
85          else if ( "dav".equals( protocol ) )
86          {
87              protocol = "http";
88          }
89          else if ( protocol.startsWith( "dav:" ) )
90          {
91              protocol = protocol.substring( "dav:".length() );
92          }
93  
94          ProxyDef proxy = candidates.get( protocol );
95          if ( proxy == null && "https".equals( protocol ) )
96          {
97              proxy = candidates.get( "http" );
98          }
99  
100         return ( proxy != null ) ? proxy.proxy : null;
101     }
102 
103     static class NonProxyHosts
104     {
105 
106         private final Pattern[] patterns;
107 
108         public NonProxyHosts( String nonProxyHosts )
109         {
110             List<Pattern> patterns = new ArrayList<Pattern>();
111             if ( nonProxyHosts != null )
112             {
113                 for ( StringTokenizer tokenizer = new StringTokenizer( nonProxyHosts, "|" ); tokenizer.hasMoreTokens(); )
114                 {
115                     String pattern = tokenizer.nextToken();
116                     pattern = pattern.replace( ".", "\\." ).replace( "*", ".*" );
117                     patterns.add( Pattern.compile( pattern, Pattern.CASE_INSENSITIVE ) );
118                 }
119             }
120             this.patterns = patterns.toArray( new Pattern[patterns.size()] );
121         }
122 
123         boolean isNonProxyHost( String host )
124         {
125             if ( host != null )
126             {
127                 for ( Pattern pattern : patterns )
128                 {
129                     if ( pattern.matcher( host ).matches() )
130                     {
131                         return true;
132                     }
133                 }
134             }
135             return false;
136         }
137 
138     }
139 
140     static class ProxyDef
141     {
142 
143         final Proxy proxy;
144 
145         final NonProxyHosts nonProxyHosts;
146 
147         public ProxyDef( Proxy proxy, String nonProxyHosts )
148         {
149             this.proxy = proxy;
150             this.nonProxyHosts = new NonProxyHosts( nonProxyHosts );
151         }
152 
153     }
154 
155 }