source: trunk/grails-app/services/nl/tno/massSequencing/integration/GscfService.groovy @ 52

Last change on this file since 52 was 52, checked in by robert@…, 8 years ago
  • Updated a bug on production with org.apache.tools.zip
  • Added tooltips to all icons
File size: 14.0 KB
Line 
1package nl.tno.massSequencing.integration
2
3import grails.converters.JSON
4import org.codehaus.groovy.grails.commons.ConfigurationHolder
5import org.springframework.web.context.request.RequestContextHolder;
6
7/**
8 * EDP (External Data Provider) for GSCF
9 *
10 * @author Robert Horlings (robert@isdat.nl)
11 * @version 0.9
12 * @see nmcdsp.GscfService
13 */
14class GscfService {
15        def config = ConfigurationHolder.config
16
17        static transactional = true
18
19        /**
20         * Returns the URL to let the user login at GSCF
21         *
22         * @param params        Parameters of the action called
23         * @param token         Session token
24         * @return                      URL to redirect the user to
25         */
26        public String urlAuthRemote( def params, def token ) {
27                def redirectURL = "${config.gscf.baseURL}/login/auth_remote?moduleURL=${this.moduleURL()}&consumer=${this.consumerID()}&token=${token}&"
28
29                def returnUrl = config.grails.serverURL
30                if (params.controller != null){
31                        returnUrl += "/${params.controller}"
32                        if (params.action != null){
33                                returnUrl += "/${params.action}"
34                                if (params.id != null){
35                                        returnUrl += "/${params.id}"
36                                }
37                        }
38                }
39
40                // Append other parameters
41                returnUrl += "?" + params.collect {
42                        if( it.key != "controller" && it.key != "action" && it.key != "id" )
43                                return it.key.toString().encodeAsURL() + "=" + it.value.toString().encodeAsURL();
44                        else
45                                return ""
46                }.findAll { it }.join( "&" );
47
48                // After logging in, send the user to /synchronize/authorization first to synchronize
49                // authorization for this user
50                returnUrl = config.grails.serverURL + '/synchronize/authorization?redirectUrl=' + returnUrl.encodeAsURL()
51               
52                return redirectURL + "returnUrl=" + returnUrl.encodeAsURL();
53        }
54
55        /**
56         * Returns the url to show details of a study in GSCF
57         *
58         * @param study         Study object to view in GSCF
59         * @return                      URL to redirect the user to
60         */
61        public String urlViewStudy( String studyToken ) {
62                return "${config.gscf.baseURL}/study/showByToken/" + studyToken
63        }
64
65        /**
66         * Returns the url to add a new study in GSCF
67         *
68         * @return                      URL to redirect the user to
69         */
70        public String urlAddStudy( String studyToken ) {
71                return config.gscf.baseURL + config.gscf.addStudyPath
72        }
73
74        /**
75         * Retrieves the currently logged in user from GSCF
76         *
77         * @param sessionToken String
78         *
79         * @return Map
80         */
81        public Map getUser(String sessionToken) throws Exception {
82                def user = [:]
83                try {
84                        this.callGSCF(sessionToken, "getUser").each {
85                                user[ it.key ] = it.value;
86                        }
87                        return user
88                } catch( Exception e ) {
89                        e.printStackTrace();
90                        return null
91                        throw new Exception( "Retrieving user details from GSCF failed", e );
92                }
93        }
94
95        /**
96         * Retrieve a list of Studies from the GSCF
97         *
98         * @param sessionToken String
99         *
100         * @return ArrayList
101         */
102        public ArrayList getStudies(String sessionToken) throws BadRequestException, NotAuthenticatedException, NotAuthorizedException, ResourceNotFoundException, Exception {
103                return this.callGSCF(sessionToken, "getStudies")
104        }
105
106
107        /**
108         * Retrieve a list of Studies from the GSCF
109         *
110         * @param sessionToken String
111         *
112         * @return ArrayList
113         */
114        public ArrayList getStudies(String sessionToken, ArrayList studyTokens ) throws BadRequestException, NotAuthenticatedException, NotAuthorizedException, ResourceNotFoundException, Exception  {
115                return this.callGSCF(sessionToken, "getStudies", [ "studyToken": studyTokens ] );
116        }
117
118        /**
119         * Retrieve a single Study from the GSCF
120         *
121         * @param sessionToken String
122         * @param study Study
123         *
124         * @return ArrayList
125         */
126        public def getStudy(String sessionToken, String studyToken) throws BadRequestException, NotAuthenticatedException, NotAuthorizedException, ResourceNotFoundException, Exception  {
127                def list
128
129                try {
130                        list = this.callGSCF(sessionToken, "getStudies", ["studyToken": studyToken])
131                } catch( NotAuthorizedException e ) {
132                        throw new NotAuthorizedException( "User is not authorized to access study with token " + studyToken )
133                } catch( ResourceNotFoundException e ) {
134                        throw new ResourceNotFoundException( "Study with token " + studyToken + " not found in GSCF" )
135                } // Other exceptions are thrown as they appear
136
137                // Return only the first element of the list, since we are only interested in one study
138                if( list?.size() ) {
139                        return list[0];
140                } else {
141                        return []
142                }
143        }
144
145        /**
146         * Retrieve a list of Assays from the GSCF
147         *
148         * @param sessionToken String
149         * @param study Study
150         *
151         * @return ArrayList
152         */
153        public ArrayList getAssays(String sessionToken, String studyToken) throws BadRequestException, NotAuthenticatedException, NotAuthorizedException, ResourceNotFoundException, Exception  {
154                try {
155                        return this.callGSCF(sessionToken, "getAssays", ["studyToken": studyToken])
156                } catch( NotAuthorizedException e ) {
157                        throw new NotAuthorizedException( "User is not authorized to access study with token " + studyToken )
158                } catch( ResourceNotFoundException e ) {
159                        throw new ResourceNotFoundException( "Study with token " + studyToken + " not found in GSCF" )
160                } // Other exceptions are thrown as they appear
161        }
162
163        /**
164         * Retrieve a single Assay from the GSCF
165         *
166         * @param sessionToken String
167         * @param study Study
168         * @param assay Assay
169         *
170         * @return ArrayList
171         */     
172        public def getAssay(String sessionToken, String studyToken, String assayToken )throws BadRequestException, NotAuthenticatedException, NotAuthorizedException, ResourceNotFoundException, Exception  {
173                def list
174                try {
175                        list = this.callGSCF(sessionToken, "getAssays", ["studyToken": studyToken, "assayToken": assayToken])
176                } catch( NotAuthorizedException e ) {
177                        throw new NotAuthorizedException( "User is not authorized to access study with token " + studyToken )
178                } catch( ResourceNotFoundException e ) {
179                        throw new ResourceNotFoundException( "Assay with token " + assayToken + " not found in GSCF" )
180                } // Other exceptions are thrown as they appear
181
182                // Return only the first element of the list, since we are only interested in one assay
183                if( list.size() == 0 ) {
184                        return []
185                } else {
186                        return list[0];
187                }
188        }
189
190       
191        /**
192         * Retrieve a single Sample from the GSCF
193         *
194         * @param sessionToken String
195         * @param assay Assay
196         * @param sample Sample
197         *
198         * @return ArrayList
199         */
200        public def getSample(String sessionToken, String assayToken, String sampleToken) throws BadRequestException, NotAuthenticatedException, NotAuthorizedException, ResourceNotFoundException, Exception  {
201                def list
202
203                try {
204                        list = this.callGSCF(sessionToken, "getSamples", ["assayToken": assayToken , "sampleToken": sampleToken])
205                } catch( NotAuthorizedException e ) {
206                        throw new NotAuthorizedException( "User is not authorized to access study for assay with token " + assayToken )
207                } catch( ResourceNotFoundException e ) {1
208                        throw new ResourceNotFoundException( "Assay with token " + assayToken + " not found in GSCF" )
209                } // Other exceptions are thrown as they appear
210
211                // Return only the first element of the list, since we are only interested in one sample
212                if( list.size() == 0 )
213                        return []
214                else
215                        return list[ 0 ];
216
217        }
218       
219        /**
220         * Retrieve a list of Samples from the GSCF
221         *
222         * @param sessionToken String
223         * @param assay Assay (parameter assay is optional, only used when you want to limit the list of samples of an Assay within a Study)
224         *
225         * @return ArrayList
226         */
227        public ArrayList getSamples(String sessionToken, String assayToken) throws BadRequestException, NotAuthenticatedException, NotAuthorizedException, ResourceNotFoundException, Exception  {
228                // Samples of a Study limited to a single Assay
229                try {
230                        return this.callGSCF(sessionToken, "getSamples", ["assayToken":assayToken])
231                } catch( NotAuthorizedException e ) {
232                        throw new NotAuthorizedException( "User is not authorized to access study for assay with token " + assayToken )
233                } catch( ResourceNotFoundException e ) {1
234                        throw new ResourceNotFoundException( "Assay with token " + assayToken + " not found in GSCF" )
235                } // Other exceptions are thrown as they appear
236
237        }
238
239        /**
240         * Retrieve a list of samples from the GSCF
241         *
242         * @param sessionToken String
243         * @param sampleTokens List of sampleTokens
244         *
245         * @return ArrayList
246         */
247        public def getSamples(String sessionToken, List sampleTokens) throws BadRequestException, NotAuthenticatedException, NotAuthorizedException, ResourceNotFoundException, Exception  {
248                def list
249
250                try {
251                        list = this.callGSCF(sessionToken, "getSamples", ["sampleToken": sampleTokens])
252                } catch( NotAuthorizedException e ) {
253                        throw new NotAuthorizedException( "User is not authorized to access samples" )
254                } catch( ResourceNotFoundException e ) {
255                        throw new ResourceNotFoundException( "Samples with token " + sampleTokens + " not found in GSCF" )
256                } // Other exceptions are thrown as they appear
257
258                // Return only the first element of the list, since we are only interested in one sample
259                return list
260        }
261
262
263        /**
264         * Retrieve study access
265         *
266         * @param sessionToken String
267         * @param study Study
268         *
269         * @return ArrayList
270         */
271        public HashMap getAuthorizationLevel(String sessionToken, String studyToken) throws BadRequestException, NotAuthenticatedException, NotAuthorizedException, ResourceNotFoundException, Exception  {
272                ArrayList list
273
274                try {
275                        list = this.callGSCF(sessionToken, "getAuthorizationLevel", ["studyToken":studyToken])
276                } catch( ResourceNotFoundException e ) {
277                        throw new ResourceNotFoundException( "Study with token " + studyToken + " not found in GSCF")
278                } // Other exceptions are thrown as they appear
279
280                HashMap map = [:]
281
282                // Convert the list back to a hashmap
283                list.each { entry ->
284                        map[ entry.key ] = entry.value
285                }
286
287                return map
288        }
289
290        /**
291         * Base URL of GSCF Rest Controller/API
292         *
293         * @return      url String
294         */
295        private String restURL() {
296                return "${config.gscf.baseURL}/rest"
297        }
298
299        /**
300         * Call GSCF Service via a secure call
301         *
302         * @param       sessionToken Session token for connection to GSCF
303         * @param       restMethod Method to call on GSCF rest controller
304         * @param       restParams Parameters to provide to the GSCF rest method
305         * @param       requestMethod   Request method to retrieve data
306         *
307         * @return      ArrayList
308         */
309        private ArrayList callGSCF(String sessionToken, String restMethod, HashMap restParams = [:], String requestMethod = "GET" ) throws BadRequestException, NotAuthenticatedException, NotAuthorizedException, ResourceNotFoundException, Exception {
310
311                // Create a string of arguments to send to GSCF
312                def args = "moduleURL=${this.moduleURL()}&consumer=${this.consumerID()}&token=${sessionToken}";
313               
314                // concat all Rest Call specific arguments behind args
315                restParams.each {parameter ->
316                        // If a list is given as value, the parameter should show up multiple times
317                        if( parameter.value instanceof Collection ) {
318                                parameter.value.each { value ->
319                                        args += "&${parameter.key}=" + value.toString().encodeAsURL()
320                                }
321                        } else {
322                                args += "&${parameter.key}=" + parameter.value.toString().encodeAsURL()
323                        }
324                }
325               
326                // construct GSCF address
327                def addr = "${this.restURL()}/${restMethod}"
328                def connection
329               
330                // If the data to be sent is longer than appr 2000 characters, the GET method will fail
331                // For that reason, we switch to POST if needed
332                if( addr.size() + args.size() > 2000 && requestMethod != "POST" ) {
333                        log.warn "Calling " + addr + " with request method POST instead of " + requestMethod + " because content length is too long: " + ( addr.size() + args.size() )
334                        requestMethod = "POST";
335                }
336               
337                // Call GSCF, depending on the requestmethod that is asked for
338                try {
339                        log.info("GSCF REST-CALL (" + requestMethod + "): ${addr}")
340                       
341                        switch( requestMethod.toUpperCase() ) {
342                                case "GET":
343                                        def url = addr + "?" + args;
344                                        connection = url.toURL().openConnection();
345                               
346                                        break
347                                case "POST":
348                                        connection = addr.toURL().openConnection()
349                                        connection.setRequestMethod( "POST" );
350                                        connection.doOutput = true
351                                       
352                                        def writer = new OutputStreamWriter( connection.outputStream )
353                                        writer.write( args );
354                                        writer.flush()
355                                        writer.close()
356                                       
357                                        connection.connect();
358                                       
359                                        break
360                                default:
361                                        throw new Exception( "Unknown request method given. Use GET or POST" )
362                        }
363               
364                } catch( Exception e ) {
365                        log.error("GSCF Call failed when calling service: ${addr}",e)
366                        throw new Exception( "Calling GSCF Rest method ${restMethod} failed. Please check log for more information.", e )
367                }
368               
369                // Handle the response given by GSCF
370                def gscfResponse = []
371
372                switch( connection.responseCode ) {
373                        case 400:       // Bad request
374                                throw new BadRequestException( "Bad request made to GSCF server: " + addr );
375                                break;
376                        case 401:       // Not allowed to access this resource
377                                throw new NotAuthorizedException( "User is not authorized to access the resource " + addr );
378                                break;
379                        case 403:       // Incorrect authentication
380                                println "Not authenticated (" + addr + "): " + connection.responseCode
381                               
382                                // The user is logged in to the metagenomics module, but not to GSCF. We log the user out of the module
383                                RequestContextHolder.currentRequestAttributes().getSession().user = null
384                               
385                                throw new NotAuthenticatedException( "User is not authenticated with GSCF." );
386                                break;
387                        case 404:       // Resource not found
388                                throw new ResourceNotFoundException( "Specified resource could not be found: "  + addr );
389                                break;
390                        case 500:       // Internal server error
391                                throw new Exception( "An unknown error occured when calling service: " + addr + " - " + connection.responseMessage )
392                                break;
393                        default:
394                                try {
395                                        def jsonResponse = JSON.parse(connection.content.text)
396                                        jsonResponse.each { jsonProperty ->
397                                                gscfResponse << jsonProperty
398                                        }
399
400                                        log.info("GSCF REST-RESP: ${jsonResponse}")
401                                } catch(Exception e) {
402                                        log.error("Parsing GSCF JSON response failed at ${addr}. Reponse was " + connection.content.text,e)
403                                        throw new Exception( "Parsing GSCF JSON response failed at ${addr}.  Please check log for more information.", e )
404                                }
405                                break;
406                }
407
408                return gscfResponse
409        }
410
411        /**
412         * Consumer ID for connection to of GSCF Rest Controller/API
413         *
414         * @return      consumerID      String
415         */
416        private String consumerID() {
417                return config.massSequencing.consumerID
418        }
419
420        /**
421         * Module URL for connection to of GSCF Rest Controller/API
422         *
423         * @return      moduleURL       String
424         */
425        private String moduleURL() {
426                return config.grails.serverURL
427        }
428
429}
Note: See TracBrowser for help on using the repository browser.