1 package org.eclipse.aether.transport.http;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.Closeable;
23 import java.util.Arrays;
24 import java.util.Iterator;
25 import java.util.Map;
26 import java.util.concurrent.ConcurrentHashMap;
27 import java.util.concurrent.ConcurrentMap;
28
29 import org.apache.http.HttpHost;
30 import org.apache.http.conn.ClientConnectionManager;
31 import org.apache.http.conn.scheme.PlainSocketFactory;
32 import org.apache.http.conn.scheme.Scheme;
33 import org.apache.http.conn.scheme.SchemeRegistry;
34 import org.apache.http.impl.conn.PoolingClientConnectionManager;
35 import org.eclipse.aether.RepositoryCache;
36 import org.eclipse.aether.RepositorySystemSession;
37 import org.eclipse.aether.util.ConfigUtils;
38
39
40
41
42
43 final class GlobalState
44 implements Closeable
45 {
46
47 static class CompoundKey
48 {
49
50 private final Object[] keys;
51
52 CompoundKey( Object... keys )
53 {
54 this.keys = keys;
55 }
56
57 @Override
58 public boolean equals( Object obj )
59 {
60 if ( this == obj )
61 {
62 return true;
63 }
64 if ( obj == null || !getClass().equals( obj.getClass() ) )
65 {
66 return false;
67 }
68 CompoundKey that = (CompoundKey) obj;
69 return Arrays.equals( keys, that.keys );
70 }
71
72 @Override
73 public int hashCode()
74 {
75 int hash = 17;
76 hash = hash * 31 + Arrays.hashCode( keys );
77 return hash;
78 }
79
80 @Override
81 public String toString()
82 {
83 return Arrays.toString( keys );
84 }
85 }
86
87 private static final String KEY = GlobalState.class.getName();
88
89 private static final String CONFIG_PROP_CACHE_STATE = "aether.connector.http.cacheState";
90
91 private final ConcurrentMap<SslConfig, ClientConnectionManager> connectionManagers;
92
93 private final ConcurrentMap<CompoundKey, Object> userTokens;
94
95 private final ConcurrentMap<HttpHost, AuthSchemePool> authSchemePools;
96
97 private final ConcurrentMap<CompoundKey, Boolean> expectContinues;
98
99 public static GlobalState get( RepositorySystemSession session )
100 {
101 GlobalState cache;
102 RepositoryCache repoCache = session.getCache();
103 if ( repoCache == null || !ConfigUtils.getBoolean( session, true, CONFIG_PROP_CACHE_STATE ) )
104 {
105 cache = null;
106 }
107 else
108 {
109 Object tmp = repoCache.get( session, KEY );
110 if ( tmp instanceof GlobalState )
111 {
112 cache = (GlobalState) tmp;
113 }
114 else
115 {
116 synchronized ( GlobalState.class )
117 {
118 tmp = repoCache.get( session, KEY );
119 if ( tmp instanceof GlobalState )
120 {
121 cache = (GlobalState) tmp;
122 }
123 else
124 {
125 cache = new GlobalState();
126 repoCache.put( session, KEY, cache );
127 }
128 }
129 }
130 }
131 return cache;
132 }
133
134 private GlobalState()
135 {
136 connectionManagers = new ConcurrentHashMap<>();
137 userTokens = new ConcurrentHashMap<>();
138 authSchemePools = new ConcurrentHashMap<>();
139 expectContinues = new ConcurrentHashMap<>();
140 }
141
142 public void close()
143 {
144 for ( Iterator<Map.Entry<SslConfig, ClientConnectionManager>> it = connectionManagers.entrySet().iterator();
145 it.hasNext(); )
146 {
147 ClientConnectionManager connMgr = it.next().getValue();
148 it.remove();
149 connMgr.shutdown();
150 }
151 }
152
153 public ClientConnectionManager getConnectionManager( SslConfig config )
154 {
155 ClientConnectionManager manager = connectionManagers.get( config );
156 if ( manager == null )
157 {
158 ClientConnectionManager connMgr = newConnectionManager( config );
159 manager = connectionManagers.putIfAbsent( config, connMgr );
160 if ( manager != null )
161 {
162 connMgr.shutdown();
163 }
164 else
165 {
166 manager = connMgr;
167 }
168 }
169 return manager;
170 }
171
172 @SuppressWarnings( "checkstyle:magicnumber" )
173 public static ClientConnectionManager newConnectionManager( SslConfig sslConfig )
174 {
175 SchemeRegistry schemeReg = new SchemeRegistry();
176 schemeReg.register( new Scheme( "http", 80, new PlainSocketFactory() ) );
177 schemeReg.register( new Scheme( "https", 443, new SslSocketFactory( sslConfig ) ) );
178
179 PoolingClientConnectionManager connMgr = new PoolingClientConnectionManager( schemeReg );
180 connMgr.setMaxTotal( 100 );
181 connMgr.setDefaultMaxPerRoute( 50 );
182 return connMgr;
183 }
184
185 public Object getUserToken( CompoundKey key )
186 {
187 return userTokens.get( key );
188 }
189
190 public void setUserToken( CompoundKey key, Object userToken )
191 {
192 if ( userToken != null )
193 {
194 userTokens.put( key, userToken );
195 }
196 else
197 {
198 userTokens.remove( key );
199 }
200 }
201
202 public ConcurrentMap<HttpHost, AuthSchemePool> getAuthSchemePools()
203 {
204 return authSchemePools;
205 }
206
207 public Boolean getExpectContinue( CompoundKey key )
208 {
209 return expectContinues.get( key );
210 }
211
212 public void setExpectContinue( CompoundKey key, boolean enabled )
213 {
214 expectContinues.put( key, enabled );
215 }
216
217 }