1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.gridsystems.innergrid.api;
18
19 import java.io.BufferedReader;
20 import java.io.IOException;
21 import java.io.InputStreamReader;
22 import java.io.Reader;
23 import java.net.ConnectException;
24 import java.net.HttpURLConnection;
25 import java.net.MalformedURLException;
26 import java.net.SocketException;
27 import java.net.URL;
28 import java.net.URLConnection;
29 import java.util.Formatter;
30 import java.util.HashMap;
31 import java.util.Map;
32
33 import javax.net.ssl.SSLHandshakeException;
34
35 import org.apache.axis.AxisProperties;
36 import org.apache.commons.io.IOUtils;
37
38 import com.gridsystems.innergrid.kernel.KernelException;
39
40
41
42
43
44
45
46 public abstract class AbstractConnection implements Connection {
47
48
49
50
51 private static final Map<Class<?>, String> PATH_TEMPLATES;
52
53 static {
54 PATH_TEMPLATES = new HashMap<Class<?>, String>();
55 PATH_TEMPLATES.put(UsernameTokenCredentials.class, "/kernel/api/%s");
56 PATH_TEMPLATES.put(X509CertificateCredentials.class, "/kernel/api/%s_cert");
57 PATH_TEMPLATES.put(null, "/kernel/api/%s");
58 }
59
60
61
62
63 public static final int DEFAULT_RETRIES = 5;
64
65
66
67
68 protected String host = null;
69
70
71
72
73 protected int port = -1;
74
75
76
77
78 protected String contextPath;
79
80
81
82
83 protected boolean secured = false;
84
85
86
87
88 protected SSLConnectionInfo sslInfo = null;
89
90
91
92
93 protected Credentials credentials = null;
94
95
96
97
98 protected int timeout = DEFAULT_TIMEOUT;
99
100
101
102
103 protected boolean chunkedTransferEnabled = true;
104
105
106
107
108 protected boolean keepAliveEnabled = false;
109
110
111
112
113 protected String attachmentFormat;
114
115
116
117
118 protected int retries = DEFAULT_RETRIES;
119
120
121
122
123 protected boolean connChecked = false;
124
125
126
127
128 protected Object sync = new Object();
129
130 static {
131
132 AxisProperties.setProperty("axis.socketFactory",
133 NoLingerSocketFactory.class.getName(), true);
134
135
136 AxisProperties.setProperty("axis.socketSecureFactory",
137 InnergridJSSESocketFactory.class.getName(), true);
138 }
139
140
141
142
143
144
145
146
147 private static String getDefaultPathFor(Credentials cred) {
148 String path = null;
149 if (cred != null) {
150 path = PATH_TEMPLATES.get(cred.getClass());
151 }
152
153 if (path == null) {
154 path = PATH_TEMPLATES.get(null);
155 }
156
157 return path;
158 }
159
160
161
162
163
164
165
166
167
168
169
170
171
172 public AbstractConnection(String h, int p, String ctxPath, boolean secure,
173 SSLConnectionInfo sslinfo, Credentials credentials) {
174 this.host = h;
175 this.port = p;
176 this.contextPath = (ctxPath == null) ? getDefaultPathFor(credentials) : ctxPath;
177 this.secured = secure;
178 if (this.secured) {
179 if (sslinfo == null) {
180 this.sslInfo = new AcceptAllCertificates();
181 } else {
182 this.sslInfo = sslinfo;
183 }
184 InnergridJSSESocketFactory.registrySSLConnectionInfo(h, p, sslInfo);
185 }
186 this.credentials = credentials;
187 }
188
189
190
191
192
193
194
195
196
197
198
199 public AbstractConnection(String h, int p, boolean secure,
200 SSLConnectionInfo sslinfo, Credentials credentials) {
201 this(h, p, null, secure, sslinfo, credentials);
202 }
203
204
205
206
207
208 public String getHost() {
209 synchronized (sync) {
210 return this.host;
211 }
212 }
213
214
215
216
217
218 public int getPort() {
219 synchronized (sync) {
220 return this.port;
221 }
222 }
223
224
225
226
227 public String getContextPath() {
228 synchronized (sync) {
229 return this.contextPath;
230 }
231 }
232
233
234
235
236
237
238 public void setContextPath(String ctxPath) {
239 if (ctxPath == null) {
240 ctxPath = getDefaultPathFor(this.credentials);
241 }
242 this.contextPath = ctxPath;
243 }
244
245
246
247
248
249 public boolean isSecured() {
250 synchronized (sync) {
251 return this.secured;
252 }
253 }
254
255
256
257
258 public int getTimeout() {
259 synchronized (sync) {
260 return this.timeout;
261 }
262 }
263
264
265
266
267 public void setTimeout(int timeout) {
268 synchronized (sync) {
269 this.timeout = timeout;
270 }
271 }
272
273
274
275
276 public boolean isChunkedTransferEnabled() {
277 synchronized (sync) {
278 return this.chunkedTransferEnabled;
279 }
280 }
281
282
283
284
285 public void setChunkedTransferEnabled(boolean enabled) {
286 synchronized (sync) {
287 this.chunkedTransferEnabled = enabled;
288 }
289 }
290
291
292
293
294 public boolean isKeepAliveEnabled() {
295 synchronized (sync) {
296 return this.keepAliveEnabled;
297 }
298 }
299
300
301
302
303 public void setKeepAliveEnabled(boolean enabled) {
304 synchronized (sync) {
305 this.keepAliveEnabled = enabled;
306 }
307 }
308
309
310
311
312 public String getAttachmentFormat() {
313 synchronized (sync) {
314 return this.attachmentFormat;
315 }
316 }
317
318
319
320
321 public void setAttachmentFormat(String format) {
322 synchronized (sync) {
323 this.attachmentFormat = format;
324 }
325 }
326
327
328
329
330
331 public int getRetries() {
332 return this.retries;
333 }
334
335
336
337
338
339 public void setRetries(int retries) {
340 this.retries = retries;
341 }
342
343
344
345
346
347 public URL getUrl(String apiName) throws KernelException {
348 String baseUrl = getBaseUrl();
349 try {
350 Formatter f = new Formatter();
351 f.format(baseUrl, apiName);
352 return new URL(f.toString());
353 } catch (MalformedURLException e) {
354 throw new CKernelException(e, "CLT008", "[ " + baseUrl + ", " + apiName + " ]");
355 }
356 }
357
358
359
360
361 public Credentials getCredentials() {
362 return this.credentials;
363 }
364
365
366
367
368
369 public SSLConnectionInfo getSSLConnectionInfo() {
370 return sslInfo;
371 }
372
373
374
375
376
377
378
379 public abstract String getBaseUrl() throws KernelException;
380
381
382
383
384
385
386
387
388
389 public abstract void manageException(KernelException ke, int retry)
390 throws KernelException;
391
392
393
394
395
396
397
398
399
400 public final void clearChecks() {
401 this.connChecked = true;
402 }
403
404
405
406
407 public final void checkConnection() throws KernelException {
408 if (!connChecked && !checkPort(secured)) {
409 String url = this.host + ":" + this.port;
410 String[] protocols = { "http", "https" };
411 int i = secured ? 1 : 0;
412 throw new CKernelException("CLT061", protocols[i], url, protocols[1 - i]);
413 }
414 connChecked = true;
415 }
416
417
418
419
420
421
422
423
424
425
426 private boolean checkPort(boolean secure) throws KernelException {
427
428 if (secure && checkPort(false)) {
429 return false;
430 }
431
432 BufferedReader reader = null;
433 URLConnection con = null;
434 try {
435 URL url = new URL(secure ? "https" : "http", this.host, this.port, "");
436 con = url.openConnection();
437 con.setUseCaches(false);
438
439 reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
440
441
442
443
444 return test(reader);
445
446 } catch (MalformedURLException e) {
447 throw new CKernelException(e, "CLT062", "malformed");
448 } catch (ConnectException e) {
449 throw new CKernelException(e, "CLT000", host + ":" + port);
450 } catch (SocketException e) {
451 return false;
452 } catch (SSLHandshakeException e) {
453
454 return this.secured;
455 } catch (IOException ioe) {
456 if (ioe.getMessage().indexOf("hostname wrong") != -1) {
457 return secure;
458 }
459
460
461 throw new CKernelException(ioe, "CLT062", ioe.getMessage());
462 } catch (Throwable t) {
463
464 throw new CKernelException(t, "CLT062", t.getMessage());
465 } finally {
466 IOUtils.closeQuietly(reader);
467 if (con instanceof HttpURLConnection) {
468 ((HttpURLConnection)con).disconnect();
469 }
470 }
471 }
472
473
474
475
476
477
478
479
480 private boolean test(Reader reader) throws IOException {
481 char ch = (char)reader.read();
482 while (ch != -1) {
483 if (!Character.isISOControl(ch)) {
484 return true;
485 }
486 ch = (char)reader.read();
487 }
488 return false;
489 }
490 }