Salome HOME
- Fix query
[modules/gde.git] / projects / GDE_App / GDE-war / test / com / edf / gde / test / restapi / SimpleRestApi.java
1 package gdetester.restapi;
2
3 import com.google.gson.Gson;
4 import java.io.BufferedOutputStream;
5 import java.io.BufferedReader;
6 import java.io.ByteArrayOutputStream;
7 import java.io.FileNotFoundException;
8 import java.io.IOException;
9 import java.io.InputStream;
10 import java.io.InputStreamReader;
11 import java.io.OutputStream;
12 import java.lang.reflect.Type;
13 import java.net.HttpURLConnection;
14 import java.net.URL;
15 import java.nio.ByteBuffer;
16 import java.nio.channels.Channels;
17 import java.nio.channels.ReadableByteChannel;
18 import java.nio.channels.WritableByteChannel;
19 import java.security.KeyManagementException;
20 import java.security.KeyStore;
21 import java.security.KeyStoreException;
22 import java.security.NoSuchAlgorithmException;
23 import java.security.cert.Certificate;
24 import java.security.cert.CertificateException;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.List;
28 import javax.net.ssl.HostnameVerifier;
29 import javax.net.ssl.HttpsURLConnection;
30 import javax.net.ssl.SSLContext;
31 import javax.net.ssl.SSLSession;
32 import javax.net.ssl.TrustManagerFactory;
33 import gdetester.restapi.providers.CertificateProvider;
34
35 /**
36  *
37  * @author Kavoos Bojnourdi
38  */
39 public class SimpleRestApi {
40
41     /**
42      * RestContext
43      */
44     protected RestContext restContext;
45
46     private KeyStore keyStore;
47     private TrustManagerFactory tmf;
48     private SSLContext context;
49     private boolean verifyHostName;
50     private HttpURLConnection connection;
51     protected Gson gson;
52     
53     public SimpleRestApi() {
54         restContext = new RestContext();
55         gson = new Gson();
56     }
57
58     public SimpleRestApi(RestContext context) {
59         this.restContext = context;
60         gson = new Gson();
61     }
62
63     public boolean isVerifyHostName() {
64         return verifyHostName;
65     }
66
67     public void setVerifyHostName(boolean verifyHostName) {
68         this.verifyHostName = verifyHostName;
69     }
70
71     protected void setContext(RestContext context) {
72         this.restContext = context;
73         if (context.getBaseResource() != null) {
74             initResource();
75         }
76     }
77
78     private void initResource() {
79
80     }
81
82     public RestContext getContext() {
83         return restContext;
84     }
85
86     protected void setResource(String resource) {
87         restContext.setBaseResource(resource);
88         initResource();
89     }
90
91     protected void setResource(String base, String resource) {
92         restContext.setBaseResource(base + resource);
93         initResource();
94     }
95
96     public void closeConnection() {
97         if (connection != null) {
98             connection.disconnect();
99         }
100     }
101
102     public void setCertificateProvider(CertificateProvider certificateProvider) {
103         restContext.setCertificateProvider(certificateProvider);
104     }
105     
106     /**
107      *
108      * @param connection
109      */
110     protected void initAuthentication(HttpURLConnection connection) {
111         if (restContext.getUserName() == null) {
112             return;
113         }
114         String userCredentials = restContext.getUserName() + ":" + restContext.getPassword();
115         String basicAuth = "Basic " + new String(Base64.encode(userCredentials.getBytes()));
116         connection.setRequestProperty("Authorization", basicAuth);
117         connection.setRequestProperty("User-Agent", "Deuterium/1.0");
118     }
119
120     /**
121      *
122      * @param rh
123      * @return
124      * @throws IOException
125      */
126     protected boolean remove(ResponseHandler rh) throws IOException {
127         setUpHttpConnection();
128
129         try {
130             connection.setDoInput(true);
131             connection.setDoOutput(false);
132             initAuthentication(connection);
133
134             connection.setRequestMethod("DELETE");
135
136             // Open and do query
137             int responseCode = connection.getResponseCode();
138             String resultString = readStringResponse(connection);
139
140             if (rh == null) {
141                 rh = new DefaultResponseHandler();
142             }
143             return rh.checkResponse(responseCode, resultString);
144         } finally {
145             closeConnection();
146         }
147     }
148
149     /**
150      *
151      * @param data
152      * @param rh
153      * @return
154      * @throws IOException
155      */
156     protected boolean putAsJSonData(Object data, ResponseHandler rh) throws IOException {
157         setUpHttpConnection();
158         try {
159             connection.setRequestMethod("PUT");
160             return writeJsonData(data, connection, rh);
161         } finally {
162             closeConnection();
163         }
164     }
165
166     /**
167      *
168      * @param data
169      * @return
170      * @throws IOException
171      */
172     protected boolean putAsJSonData(Object data) throws IOException {
173         return putAsJSonData(data, null);
174     }
175
176     /**
177      *
178      * @param data
179      * @param rh
180      * @return
181      * @throws IOException
182      */
183     protected boolean postAsJSonData(Object data, ResponseHandler rh) throws IOException {
184         setUpHttpConnection();
185         try {
186             connection.setRequestMethod("POST");
187             return writeJsonData(data, connection, rh);
188         } finally {
189             closeConnection();
190         }
191     }
192
193     /**
194      *
195      * @param data
196      * @return
197      * @throws IOException
198      */
199     protected boolean postAsJSonData(Object data) throws IOException {
200         return postAsJSonData(data, null);
201     }
202
203     /**
204      *
205      * @param data
206      * @param rh
207      * @return
208      * @throws IOException
209      */
210     protected boolean postAsBinaryData(byte[] data, ResponseHandler rh) throws IOException {
211         setUpHttpConnection();
212         try {
213             connection.setRequestMethod("POST");
214             return sendBinaryData(connection, data, rh);
215         } finally {
216             closeConnection();
217         }
218     }
219
220     /**
221      *
222      * @param data
223      * @param rh
224      * @return
225      * @throws IOException
226      */
227     protected boolean putAsBinaryData(byte[] data, ResponseHandler rh) throws IOException {
228         setUpHttpConnection();
229         try {
230             connection.setRequestMethod("PUT");
231             return sendBinaryData(connection, data, rh);
232         } finally {
233             closeConnection();
234         }
235     }
236
237     /**
238      *
239      * @param data
240      * @return
241      * @throws IOException
242      */
243     protected boolean putAsBinaryData(byte[] data) throws IOException {
244         return putAsBinaryData(data, null);
245     }
246
247     /**
248      *
249      * @param in
250      * @param rh
251      * @return
252      * @throws IOException
253      */
254     protected boolean postAsBinaryStream(InputStream in, ResponseHandler rh) throws IOException {
255         setUpHttpConnection();
256         try {
257             connection.setRequestMethod("POST");
258             return sendBinaryStream(connection, in, rh);
259         } finally {
260             closeConnection();
261         }
262     }
263
264     /**
265      *
266      * @param in
267      * @return
268      * @throws IOException
269      */
270     protected boolean postAsBinaryStream(InputStream in) throws IOException {
271         return postAsBinaryStream(in, null);
272     }
273
274     /**
275      *
276      * @param in
277      * @param rh
278      * @return
279      * @throws IOException
280      */
281     protected boolean putAsBinaryStream(InputStream in, ResponseHandler rh) throws IOException {
282         setUpHttpConnection();
283         try {
284             connection.setRequestMethod("PUT");
285             return sendBinaryStream(connection, in, rh);
286
287         } finally {
288             closeConnection();
289         }
290     }
291
292     /**
293      *
294      * @param in
295      * @return
296      * @throws IOException
297      */
298     protected boolean putAsBinaryStream(InputStream in) throws IOException {
299         return putAsBinaryStream(in, null);
300     }
301
302     /**
303      *
304      * @param rh
305      * @return
306      * @throws IOException
307      */
308     protected byte[] getBinaryData(ResponseHandler rh) throws IOException {
309         setUpHttpConnection();
310         try {
311             connection.setRequestMethod("GET");
312             connection.setDoInput(true);
313             connection.setDoOutput(false);
314             initAuthentication(connection);
315
316             int responseCode = connection.getResponseCode();
317
318             ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
319             copy(connection.getInputStream(), outputStream);
320
321             if (rh == null) {
322                 rh = new DefaultResponseHandler();
323             }
324             rh.checkResponse(responseCode, connection.getResponseMessage());
325
326             return outputStream.toByteArray();
327         } finally {
328             closeConnection();
329         }
330     }
331
332     /**
333      *
334      * @return @throws IOException
335      */
336     protected byte[] getBinaryData() throws IOException {
337         return getBinaryData(null);
338     }
339
340     /**
341      *
342      * @param rh
343      * @return
344      * @throws IOException
345      */
346     protected InputStream getBinaryStream(ResponseHandler rh) throws IOException {
347         setUpHttpConnection();
348         connection.setRequestMethod("GET");
349         connection.setDoInput(true);
350         connection.setDoOutput(false);
351         initAuthentication(connection);
352
353         int responseCode = connection.getResponseCode();
354         if (rh == null) {
355             rh = new DefaultResponseHandler();
356         }
357         rh.checkResponse(responseCode, connection.getResponseMessage());
358         return connection.getInputStream();
359     }
360
361     /**
362      *
363      * @return @throws IOException
364      */
365     protected InputStream getBinaryStream() throws IOException {
366         return getBinaryStream(null);
367     }
368
369     /**
370      *
371      * @param <T>
372      * @param classOfT
373      * @param rh
374      * @return
375      * @throws IOException
376      */
377     protected <T> T getData(Class<T> classOfT, ResponseHandler rh) throws IOException {
378         setUpHttpConnection();
379         try {
380             connection.setRequestMethod("GET");
381             connection.setDoInput(true);
382             connection.setDoOutput(false);
383             initAuthentication(connection);
384             
385             String data = readStringResponse(connection);
386             int responseCode = connection.getResponseCode();
387             if (rh == null) {
388                 rh = new DefaultResponseHandler();
389             }
390             rh.checkResponse(responseCode, connection.getResponseMessage());
391             T o = gson.fromJson(data, classOfT);
392             return o;
393         } finally {
394             closeConnection();
395         }
396     }
397
398     /**
399      *
400      * @param <T>
401      * @param classOfT
402      * @return
403      * @throws IOException
404      */
405     protected <T> T getData(Class<T> classOfT) throws IOException {
406         return getData(classOfT, null);
407     }
408
409     protected <T> List<T> getDataList(Type typeOfT, ResponseHandler rh) throws IOException {
410
411         setUpHttpConnection();
412         try {
413
414         connection.setRequestMethod("GET");
415         connection.setDoInput(true);
416         connection.setDoOutput(false);
417         initAuthentication(connection);
418
419         int responseCode = connection.getResponseCode();
420         if (rh == null) {
421             rh = new DefaultResponseHandler();
422         }
423         rh.checkResponse(responseCode, connection.getResponseMessage());
424
425         String data = readStringResponse(connection);
426         T[] o = gson.fromJson(data, typeOfT);
427         List<T> ret = new ArrayList<T>();
428         ret.addAll(Arrays.asList(o));
429         return ret;
430         } finally {
431             closeConnection();
432         }
433     }
434
435     /* Private methods */
436     /* ********************************************************************** */
437     private boolean sendBinaryStream(HttpURLConnection connection, InputStream in, ResponseHandler rh) throws IOException {
438         initAuthentication(connection);
439         connection.setDoInput(true);
440         connection.setDoOutput(true);
441         connection.setChunkedStreamingMode(4096);
442         connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
443         copy(in, connection.getOutputStream());
444         int responseCode = connection.getResponseCode();
445         String response = readStringResponse(connection);
446         if (rh == null) {
447             rh = new DefaultResponseHandler();
448         }
449
450         return rh.checkResponse(responseCode, response);
451
452     }
453
454     private void copy(InputStream in, OutputStream out) throws IOException {
455         ReadableByteChannel source = Channels.newChannel(in);
456         WritableByteChannel target = Channels.newChannel(out);
457
458         ByteBuffer buffer = ByteBuffer.allocate(16 * 1024);
459         while (source.read(buffer) != -1) {
460             buffer.flip(); // Prepare the buffer to be drained
461             while (buffer.hasRemaining()) {
462                 target.write(buffer);
463             }
464             buffer.clear(); // Empty buffer to get ready for filling
465         }
466
467         source.close();
468         target.close();
469
470     }
471
472     private boolean sendBinaryData(HttpURLConnection connection, byte[] data, ResponseHandler rh) throws IOException {
473         initAuthentication(connection);
474         writeData(connection, data);
475         int responseCode = connection.getResponseCode();
476         String response = readStringResponse(connection);
477         if (rh == null) {
478             rh = new DefaultResponseHandler();
479         }
480
481         return rh.checkResponse(responseCode, response);
482     }
483
484     private void writeData(HttpURLConnection connection, byte[] data) throws IOException {
485         connection.setDoInput(true);
486         connection.setDoOutput(true);
487         connection.setChunkedStreamingMode(4096);
488         connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
489         BufferedOutputStream outputStream = new BufferedOutputStream(connection.getOutputStream());
490         outputStream.write(data);
491         outputStream.flush();
492         outputStream.close();
493
494     }
495
496     private boolean writeJsonData(Object data, HttpURLConnection connection, ResponseHandler rh) throws IOException {
497
498         String dataStr = gson.toJson(data);
499         initAuthentication(connection);
500         writeData(connection, dataStr.getBytes("UTF-8"));
501         int responseCode = connection.getResponseCode();
502         String response = readStringResponse(connection);
503         if (rh == null) {
504             rh = new DefaultResponseHandler();
505         }
506
507         return rh.checkResponse(responseCode, response);
508     }
509
510     private String readStringResponse(HttpURLConnection connection) throws IOException {
511         BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
512         String inputLine;
513         StringBuilder builder = new StringBuilder();
514         while ((inputLine = reader.readLine()) != null) {
515             builder.append(inputLine);
516         }
517         String resultString = builder.toString();
518         reader.close();
519         return resultString;
520     }
521
522     private void setUpHttpConnection() {
523         try {
524
525             String urlString = restContext.getResource();
526             URL url = new URL(urlString);
527             if (url.getProtocol().equals("http")) {
528                 connection = (HttpURLConnection) url.openConnection();
529
530             }
531             if (url.getProtocol().equals("https")) {
532                 connection = makeHttpsConnection(url);
533             }
534
535         } catch (Exception ex) {
536             throw new RuntimeException(ex);
537         }
538     }
539
540     /**
541      *
542      * @param url
543      * @return
544      * @throws CertificateException
545      * @throws IOException
546      * @throws KeyManagementException
547      * @throws NoSuchAlgorithmException
548      * @throws KeyStoreException
549      * @throws FileNotFoundException
550      */
551     private HttpURLConnection makeHttpsConnection(URL url) throws CertificateException, IOException, KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
552         if (keyStore == null) {
553             CertificateProvider certificateProvider = restContext.getCertificateProvider();
554             if (certificateProvider == null) {
555                 throw new CertificateException("Need a certification provider");
556             }
557             Certificate ca = certificateProvider.getCertificate();
558             
559             String keyStoreType = KeyStore.getDefaultType();
560             keyStore = KeyStore.getInstance(keyStoreType);
561             keyStore.load(null, null);
562             keyStore.setCertificateEntry("ca", ca);
563
564             // Create a TrustManager that trusts the CAs in our KeyStore
565             String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
566             tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
567             tmf.init(keyStore);
568             
569             // Create an SSLContext that uses our TrustManager
570             context = SSLContext.getInstance("TLS");
571             context.init(null, tmf.getTrustManagers(), null);
572         }
573
574         // Tell the URLConnection to use a SocketFactory from our SSLContext
575         HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
576         urlConnection.setSSLSocketFactory(context.getSocketFactory());
577
578         if (!verifyHostName) {
579             HostnameVerifier hv = new HostnameVerifier() {
580
581                 @Override
582                 public boolean verify(String string, SSLSession ssls) {
583                     return true;
584                 }
585             };
586             urlConnection.setHostnameVerifier(hv);
587         }
588
589         return urlConnection;
590     }
591 }