root/trunk/grails-app/services/dbnp/modules/ModuleCommunicationService.groovy @ 1506

Revision 1506, 5.6 KB (checked in by robert@…, 3 years ago)

Removed some comments

  • Property svn:keywords set to Rev Author Date
Line 
1/**
2 * SynchronizationService Service
3 *
4 * Description of my service
5 *
6 * @author  your email (+name?)
7 * @since       2010mmdd
8 * @package     ???
9 *
10 * Revision information:
11 * $Rev$
12 * $Author$
13 * $Date$
14 */
15package dbnp.modules
16
17import dbnp.studycapturing.*
18import grails.converters.*
19import javax.servlet.http.HttpServletResponse
20import org.codehaus.groovy.grails.commons.ConfigurationHolder
21
22class ModuleCommunicationService implements Serializable {
23        boolean transactional = false
24        def authenticationService
25        def moduleNotificationService
26
27        /**
28         * Cache containing the contents of different URLs. These urls are
29         * saved per user, since the data could be different for different users.
30         */
31        def cache = [:]
32
33        /**
34         * Number of seconds to save the data in cache
35         */
36        def numberOfSecondsInCache = Integer.valueOf( ConfigurationHolder.config.modules.cacheDuration )
37
38        /**
39         * Sends a notification to assay modules that some part of a study has changed.
40         *
41         * Only modules that have the notify flag set to true will be notified. They will be notified on the URL
42         *
43         * [moduleUrl]/rest/notifyStudyChange?studyToken=abc
44         *
45         * Errors that occur when calling this URL are ignored. The module itself is responsible of
46         * maintaining a synchronized state.
47         *
48         * @param study
49         * @return
50         */
51        def invalidateStudy( def study ) {
52                moduleNotificationService.invalidateStudy( study );
53        }
54
55        /**
56         * Checks whether a specific method on a module is reachable and returns a SC_OK response code.
57         *
58         * This method will return false if a method returns an error (including 403 and 401 errors) or
59         * a redirect
60         *
61         * @param moduleUrl             URL of the module
62         * @param path                  Path of the rest method on that module. If omitted, the module reachablility itself is tested
63         * @return                              True if the module is reachable, false otherwise
64         */
65        def isModuleReachable(moduleUrl, path = "") {
66                def connection = ( moduleUrl + path ).toURL().openConnection()
67                try {
68                        return connection.responseCode == HttpServletResponse.SC_OK
69                } catch(e) {
70                        return false
71                }
72        }
73
74        /**
75         * Calls a rest method on a module
76         *
77         * @param consumer      Consumer of that specific module
78         * @param restUrl       Full URL for the method to call
79         * @return                      JSON    JSON object of the parsed text
80         */
81        def callModuleRestMethodJSON( consumer, restUrl ) throws Exception {
82                if (!authenticationService.isLoggedIn()) {
83                        // should not happen because we can only get here when a user is
84                        // logged in...
85                        throw new Exception('User is not logged in.')
86                }
87
88                // Check whether the url is present in cache
89                def cacheData = retrieveFromCache( restUrl );
90                if( cacheData && cacheData[ "success" ] )
91                        return cacheData[ "contents" ];
92                else if( cacheData && !cacheData[ "success" ] )
93                        throw new Exception( "Error while fetching data from " + restUrl + " (from cache): " + cacheData[ "error" ] )
94
95                // create a random session token that will be used to allow to module to
96                // sync with gscf prior to presenting the measurement data
97                def sessionToken = UUID.randomUUID().toString()
98
99                // put the session token to work
100                authenticationService.logInRemotely( consumer, sessionToken, authenticationService.getLoggedInUser() )
101
102                // Append the sessionToken to the URL
103                def url = restUrl
104                if( restUrl.indexOf( '?' ) > 0 ) {
105                        // The url itself also has parameters
106                        url += '&sessionToken=' + sessionToken
107                } else {
108                        // The url itself doesn't have parameters
109                        url += '?sessionToken=' + sessionToken
110                }
111
112                // Perform a call to the url
113                def restResponse
114                try {
115                        def textResponse = url.toURL().getText()
116                        log.trace "GSCF call to " + consumer + " URL: " + url
117                        log.trace "GSCF response: " + textResponse
118                        restResponse = JSON.parse( textResponse )
119                } catch (Exception e) {
120                        storeErrorInCache( restUrl, e.getMessage() );
121                        throw new Exception( "An error occurred while fetching " + url + ".", e )
122                } finally {
123                        // Dispose of the ephemeral session token
124                        authenticationService.logOffRemotely(consumer, sessionToken)
125                }
126
127                // Store the response in cache
128                storeInCache( restUrl, restResponse );
129               
130                return restResponse
131        }
132
133        /**
134         * Checks whether a specific url exists in cache
135         * @param url   URL to call
136         * @return              true if the url is present in cache
137         */
138        def existsInCache( url ) {
139                return retrieveFromCache( url ) == null;
140        }
141
142        /**
143         * Retrieves the contents of a specific URL from cache
144         * @param url   URL to call
145         * @return              JSON object with the contents of the URL or null if the url doesn't exist in cache
146         */
147        def retrieveFromCache( url ) {
148                def user = authenticationService.getLoggedInUser();
149                def userId = user ? user.id : -1;
150               
151                if( cache[ userId ] && cache[ userId ][ url ] && ( System.currentTimeMillis() - cache[ userId ][ url ][ "timestamp" ] ) < numberOfSecondsInCache * 1000 ) {
152                        return cache[ userId ][ url ];
153                } else {
154                        return null;
155                }
156        }
157
158        /**
159         * Store the retrieved contents from a url in cache
160         * @param url           URL that has been called
161         * @param contents      Contents of the URL
162         */
163        def storeInCache( url, contents ) {
164                def user = authenticationService.getLoggedInUser();
165                def userId = user ? user.id : -1;
166
167                if( !cache[ userId ] )
168                        cache[ userId ] = [:]
169
170                cache[ userId ][ url ] = [
171                        "timestamp": System.currentTimeMillis(),
172                        "success": true,
173                        "contents": contents
174                ];
175        }
176       
177        /**
178        * Store the retrieved error from a url in cache
179        * @param url            URL that has been called
180        * @param contents       Contents of the URL
181        */
182   def storeErrorInCache( url, error ) {
183           def user = authenticationService.getLoggedInUser();
184           def userId = user ? user.id : -1;
185
186           if( !cache[ userId ] )
187                   cache[ userId ] = [:]
188
189           cache[ userId ][ url ] = [
190                   "timestamp": System.currentTimeMillis(),
191                   "success": false,
192                   "error": error
193           ];
194   }
195
196}
Note: See TracBrowser for help on using the browser.