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.net.Authenticator;
23  import java.net.InetSocketAddress;
24  import java.net.PasswordAuthentication;
25  import java.net.SocketAddress;
26  import java.net.URI;
27  import java.net.URL;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.UUID;
31  
32  import org.eclipse.aether.repository.Authentication;
33  import org.eclipse.aether.repository.AuthenticationContext;
34  import org.eclipse.aether.repository.AuthenticationDigest;
35  import org.eclipse.aether.repository.Proxy;
36  import org.eclipse.aether.repository.ProxySelector;
37  import org.eclipse.aether.repository.RemoteRepository;
38  
39  /**
40   * A proxy selector that uses the {@link java.net.ProxySelector#getDefault() JRE's global proxy selector}. In
41   * combination with the system property {@code java.net.useSystemProxies}, this proxy selector can be employed to pick
42   * up the proxy configuration from the operating system, see <a
43   * href="http://docs.oracle.com/javase/6/docs/technotes/guides/net/proxies.html">Java Networking and Proxies</a> for
44   * details. The {@link java.net.Authenticator JRE's global authenticator} is used to look up credentials for a proxy
45   * when needed.
46   */
47  public final class JreProxySelector
48      implements ProxySelector
49  {
50  
51      /**
52       * Creates a new proxy selector that delegates to {@link java.net.ProxySelector#getDefault()}.
53       */
54      public JreProxySelector()
55      {
56      }
57  
58      public Proxy getProxy( RemoteRepository repository )
59      {
60          List<java.net.Proxy> proxies = null;
61          try
62          {
63              URI uri = new URI( repository.getUrl() ).parseServerAuthority();
64              proxies = java.net.ProxySelector.getDefault().select( uri );
65          }
66          catch ( Exception e )
67          {
68              // URL invalid or not accepted by selector or no selector at all, simply use no proxy
69          }
70          if ( proxies != null )
71          {
72              for ( java.net.Proxy proxy : proxies )
73              {
74                  if ( java.net.Proxy.Type.DIRECT.equals( proxy.type() ) )
75                  {
76                      break;
77                  }
78                  if ( java.net.Proxy.Type.HTTP.equals( proxy.type() ) && isValid( proxy.address() ) )
79                  {
80                      InetSocketAddress addr = (InetSocketAddress) proxy.address();
81                      return new Proxy( Proxy.TYPE_HTTP, addr.getHostName(), addr.getPort(),
82                                        JreProxyAuthentication.INSTANCE );
83                  }
84              }
85          }
86          return null;
87      }
88  
89      private static boolean isValid( SocketAddress address )
90      {
91          if ( address instanceof InetSocketAddress )
92          {
93              /*
94               * NOTE: On some platforms with java.net.useSystemProxies=true, unconfigured proxies show up as proxy
95               * objects with empty host and port 0.
96               */
97              InetSocketAddress addr = (InetSocketAddress) address;
98              if ( addr.getPort() <= 0 )
99              {
100                 return false;
101             }
102             if ( addr.getHostName() == null || addr.getHostName().length() <= 0 )
103             {
104                 return false;
105             }
106             return true;
107         }
108         return false;
109     }
110 
111     private static final class JreProxyAuthentication
112         implements Authentication
113     {
114 
115         public static final Authentication INSTANCE = new JreProxyAuthentication();
116 
117         public void fill( AuthenticationContext context, String key, Map<String, String> data )
118         {
119             Proxy proxy = context.getProxy();
120             if ( proxy == null )
121             {
122                 return;
123             }
124             if ( !AuthenticationContext.USERNAME.equals( key ) && !AuthenticationContext.PASSWORD.equals( key ) )
125             {
126                 return;
127             }
128 
129             try
130             {
131                 URL url;
132                 try
133                 {
134                     url = new URL( context.getRepository().getUrl() );
135                 }
136                 catch ( Exception e )
137                 {
138                     url = null;
139                 }
140 
141                 PasswordAuthentication auth =
142                     Authenticator.requestPasswordAuthentication( proxy.getHost(), null, proxy.getPort(), "http",
143                                                                  "Credentials for proxy " + proxy, null, url,
144                                                                  Authenticator.RequestorType.PROXY );
145                 if ( auth != null )
146                 {
147                     context.put( AuthenticationContext.USERNAME, auth.getUserName() );
148                     context.put( AuthenticationContext.PASSWORD, auth.getPassword() );
149                 }
150                 else
151                 {
152                     context.put( AuthenticationContext.USERNAME, System.getProperty( "http.proxyUser" ) );
153                     context.put( AuthenticationContext.PASSWORD, System.getProperty( "http.proxyPassword" ) );
154                 }
155             }
156             catch ( SecurityException e )
157             {
158                 // oh well, let's hope the proxy can do without auth
159             }
160         }
161 
162         public void digest( AuthenticationDigest digest )
163         {
164             // we don't know anything about the JRE's current authenticator, assume the worst (i.e. interactive)
165             digest.update( UUID.randomUUID().toString() );
166         }
167 
168         @Override
169         public boolean equals( Object obj )
170         {
171             return this == obj || ( obj != null && getClass().equals( obj.getClass() ) );
172         }
173 
174         @Override
175         public int hashCode()
176         {
177             return getClass().hashCode();
178         }
179 
180     }
181 
182 }