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<SslConfig, ClientConnectionManager>();
137 userTokens = new ConcurrentHashMap<CompoundKey, Object>();
138 authSchemePools = new ConcurrentHashMap<HttpHost, AuthSchemePool>();
139 expectContinues = new ConcurrentHashMap<CompoundKey, Boolean>();
140 }
141
142 public void close()
143 {
144 for ( Iterator<Map.Entry<SslConfig, ClientConnectionManager>> it = connectionManagers.entrySet().iterator(); it.hasNext(); )
145 {
146 ClientConnectionManager connMgr = it.next().getValue();
147 it.remove();
148 connMgr.shutdown();
149 }
150 }
151
152 public ClientConnectionManager getConnectionManager( SslConfig config )
153 {
154 ClientConnectionManager manager = connectionManagers.get( config );
155 if ( manager == null )
156 {
157 ClientConnectionManager connMgr = newConnectionManager( config );
158 manager = connectionManagers.putIfAbsent( config, connMgr );
159 if ( manager != null )
160 {
161 connMgr.shutdown();
162 }
163 else
164 {
165 manager = connMgr;
166 }
167 }
168 return manager;
169 }
170
171 public static ClientConnectionManager newConnectionManager( SslConfig sslConfig )
172 {
173 SchemeRegistry schemeReg = new SchemeRegistry();
174 schemeReg.register( new Scheme( "http", 80, new PlainSocketFactory() ) );
175 schemeReg.register( new Scheme( "https", 443, new SslSocketFactory( sslConfig ) ) );
176
177 PoolingClientConnectionManager connMgr = new PoolingClientConnectionManager( schemeReg );
178 connMgr.setMaxTotal( 100 );
179 connMgr.setDefaultMaxPerRoute( 50 );
180 return connMgr;
181 }
182
183 public Object getUserToken( CompoundKey key )
184 {
185 return userTokens.get( key );
186 }
187
188 public void setUserToken( CompoundKey key, Object userToken )
189 {
190 if ( userToken != null )
191 {
192 userTokens.put( key, userToken );
193 }
194 else
195 {
196 userTokens.remove( key );
197 }
198 }
199
200 public ConcurrentMap<HttpHost, AuthSchemePool> getAuthSchemePools()
201 {
202 return authSchemePools;
203 }
204
205 public Boolean getExpectContinue( CompoundKey key )
206 {
207 return expectContinues.get( key );
208 }
209
210 public void setExpectContinue( CompoundKey key, boolean enabled )
211 {
212 expectContinues.put( key, enabled );
213 }
214
215 }