001package org.eclipse.aether.util.repository; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.net.Authenticator; 023import java.net.InetSocketAddress; 024import java.net.PasswordAuthentication; 025import java.net.SocketAddress; 026import java.net.URI; 027import java.net.URL; 028import java.util.List; 029import java.util.Map; 030import java.util.UUID; 031 032import org.eclipse.aether.repository.Authentication; 033import org.eclipse.aether.repository.AuthenticationContext; 034import org.eclipse.aether.repository.AuthenticationDigest; 035import org.eclipse.aether.repository.Proxy; 036import org.eclipse.aether.repository.ProxySelector; 037import org.eclipse.aether.repository.RemoteRepository; 038 039/** 040 * A proxy selector that uses the {@link java.net.ProxySelector#getDefault() JRE's global proxy selector}. In 041 * combination with the system property {@code java.net.useSystemProxies}, this proxy selector can be employed to pick 042 * up the proxy configuration from the operating system, see <a 043 * href="http://docs.oracle.com/javase/6/docs/technotes/guides/net/proxies.html">Java Networking and Proxies</a> for 044 * details. The {@link java.net.Authenticator JRE's global authenticator} is used to look up credentials for a proxy 045 * when needed. 046 */ 047public final class JreProxySelector 048 implements ProxySelector 049{ 050 051 /** 052 * Creates a new proxy selector that delegates to {@link java.net.ProxySelector#getDefault()}. 053 */ 054 public JreProxySelector() 055 { 056 } 057 058 public Proxy getProxy( RemoteRepository repository ) 059 { 060 List<java.net.Proxy> proxies = null; 061 try 062 { 063 URI uri = new URI( repository.getUrl() ).parseServerAuthority(); 064 proxies = java.net.ProxySelector.getDefault().select( uri ); 065 } 066 catch ( Exception e ) 067 { 068 // URL invalid or not accepted by selector or no selector at all, simply use no proxy 069 } 070 if ( proxies != null ) 071 { 072 for ( java.net.Proxy proxy : proxies ) 073 { 074 if ( java.net.Proxy.Type.DIRECT.equals( proxy.type() ) ) 075 { 076 break; 077 } 078 if ( java.net.Proxy.Type.HTTP.equals( proxy.type() ) && isValid( proxy.address() ) ) 079 { 080 InetSocketAddress addr = (InetSocketAddress) proxy.address(); 081 return new Proxy( Proxy.TYPE_HTTP, addr.getHostName(), addr.getPort(), 082 JreProxyAuthentication.INSTANCE ); 083 } 084 } 085 } 086 return null; 087 } 088 089 private static boolean isValid( SocketAddress address ) 090 { 091 if ( address instanceof InetSocketAddress ) 092 { 093 /* 094 * NOTE: On some platforms with java.net.useSystemProxies=true, unconfigured proxies show up as proxy 095 * objects with empty host and port 0. 096 */ 097 InetSocketAddress addr = (InetSocketAddress) address; 098 if ( addr.getPort() <= 0 ) 099 { 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}