09cbf057d7bdefda852cfbdbdad3640dd3429990
[pithos] / src / gr / ebs / gss / web / client / rest / GetCommand.java
1 /*
2  * Copyright 2009 Electronic Business Systems Ltd.
3  *
4  * This file is part of GSS.
5  *
6  * GSS is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GSS is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GSS.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 package gr.ebs.gss.web.client.rest;
20
21 import gr.ebs.gss.web.client.GSS;
22 import gr.ebs.gss.web.client.rest.resource.FileResource;
23 import gr.ebs.gss.web.client.rest.resource.FolderResource;
24 import gr.ebs.gss.web.client.rest.resource.GroupResource;
25 import gr.ebs.gss.web.client.rest.resource.GroupUserResource;
26 import gr.ebs.gss.web.client.rest.resource.GroupsResource;
27 import gr.ebs.gss.web.client.rest.resource.OtherUserResource;
28 import gr.ebs.gss.web.client.rest.resource.OthersResource;
29 import gr.ebs.gss.web.client.rest.resource.RestResource;
30 import gr.ebs.gss.web.client.rest.resource.SearchResource;
31 import gr.ebs.gss.web.client.rest.resource.SharedResource;
32 import gr.ebs.gss.web.client.rest.resource.TagsResource;
33 import gr.ebs.gss.web.client.rest.resource.TrashResource;
34 import gr.ebs.gss.web.client.rest.resource.UploadStatusResource;
35 import gr.ebs.gss.web.client.rest.resource.UserResource;
36 import gr.ebs.gss.web.client.rest.resource.UserSearchResource;
37
38 import java.util.HashMap;
39 import java.util.Map;
40
41 import com.google.gwt.core.client.GWT;
42 import com.google.gwt.http.client.Request;
43 import com.google.gwt.http.client.RequestBuilder;
44 import com.google.gwt.http.client.Response;
45
46 /**
47  * @author kman
48  */
49 public abstract class GetCommand<T extends RestResource> extends RestCommand{
50
51         boolean complete = false;
52         T result = null;
53         Throwable exception = null;
54         Class<T> aclass;
55         private final String path;
56         private String username;
57         private boolean requestSent = false;
58         T cached;
59         
60         private static final long MAX_CACHE_AGE = 1000;
61         
62         private static class RequestData {
63                 public String path;
64                 public String username;
65                 
66                 public RequestData(String _path, String _username) {
67                         path = _path;
68                         username = _username;
69                 }
70
71                 @Override
72                 public int hashCode() {
73                         final int prime = 31;
74                         int result = 1;
75                         result = prime * result + ((path == null) ? 0 : path.hashCode());
76                         result = prime * result + ((username == null) ? 0 : username.hashCode());
77                         return result;
78                 }
79
80                 @Override
81                 public boolean equals(Object obj) {
82                         if (this == obj)
83                                 return true;
84                         if (obj == null)
85                                 return false;
86                         if (getClass() != obj.getClass())
87                                 return false;
88                         RequestData other = (RequestData) obj;
89                         if (path == null) {
90                                 if (other.path != null)
91                                         return false;
92                         } else if (!path.equals(other.path))
93                                 return false;
94                         if (username == null) {
95                                 if (other.username != null)
96                                         return false;
97                         } else if (!username.equals(other.username))
98                                 return false;
99                         return true;
100                 }
101         }
102         
103         private static class ResponseData {
104                 public long timestamp;
105                 public Object result;
106                 public ResponseData(long _timestamp, Object _result) {
107                         timestamp = _timestamp;
108                         result = _result;
109                 }
110         }
111         
112         private static Map<RequestData, ResponseData> cache = new HashMap<RequestData, ResponseData>();
113         
114
115         public GetCommand(Class<T> theclass, String pathToGet, T theCached){
116                 this(theclass, pathToGet, true, theCached);
117         }
118
119         public GetCommand(Class<T> theclass, String pathToGet, boolean showLoading, T theCached){
120                 setShowLoadingIndicator(showLoading);
121                 if(isShowLoadingIndicator())
122                         GSS.get().showLoadingIndicator();
123                 this.aclass = theclass;
124                 if(pathToGet.indexOf("?") != -1)
125                         path = pathToGet;
126                 else
127                         path =fixPath(pathToGet);
128                 this.cached = theCached;
129         }
130
131         public GetCommand(Class<T> theclass, String aUsername , String pathToGet, T theCached){
132                 this(theclass, aUsername, pathToGet, true, theCached);
133         }
134
135         public GetCommand(Class<T> theclass, String aUsername , String pathToGet, boolean showLoading, T theCached){
136                 setShowLoadingIndicator(showLoading);
137                 if(isShowLoadingIndicator())
138                         GSS.get().showLoadingIndicator();
139                 this.aclass = theclass;
140                 path = fixPath(pathToGet);
141                 this.username = aUsername;
142                 this.cached = theCached;
143         }
144
145         private void sendRequest(){
146                 if(requestSent)
147                         return;
148                 requestSent=true;
149                 RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, path);
150                 if(cached!=null && cached.getLastModifiedSince() != null)
151                         builder.setHeader("If-Modified-Since", cached.getLastModifiedSince());
152                 try {
153                         if(username == null)
154                                 handleHeaders(builder, path);
155                         else
156                                 handleHeaders(username, builder, path);
157                         builder.sendRequest("", new RestCallback(path) {
158
159                                 @Override
160                                 public Object deserialize(Response response) {
161                                         return deserializeResponse(path, response);
162                                 }
163
164                                 @Override
165                                 public void handleError(Request request, Throwable _exception) {
166                                         result = null;
167                                         complete = true;
168                                         exception = _exception;
169                                         if(_exception instanceof RestException)
170                                                 if(((RestException)_exception).getHttpStatusCode() == 304 && cached != null){
171                                                         GWT.log("Using cache:"+cached.getUri(), null);
172                                                         handleSuccess(cached);
173                                                         return;
174                                                 }
175                                         
176                                 }
177
178                                 @Override
179                                 public void handleSuccess(Object object) {
180                                         result = (T) object;
181                                         complete = true;
182                                 }
183
184                         });
185                 } catch (Exception ex) {
186                         complete = true;
187                         exception = ex;
188                 }
189         }
190         public boolean isComplete() {
191                 return complete;
192         }
193
194         public T getResult(){
195                 return result;
196         }
197
198         @Override
199         public boolean execute() {
200                 boolean com = isComplete();
201                 RequestData key = new RequestData(path, username);
202                 if (!com) {
203                         if (cache.containsKey(key)) {
204                                 ResponseData resp = cache.get(key);
205                                 if (resp==null) {
206                                         return true;
207                                 }
208                                 
209                                 // Cache hit
210                                 if (System.currentTimeMillis()-resp.timestamp>MAX_CACHE_AGE) {
211                                         // Cache stale, remove
212                                         cache.put(key,null);
213                                 }
214                                 else {
215                                         // Use cache data
216                                         if(isShowLoadingIndicator())
217                                                 GSS.get().hideLoadingIndicator();
218                                         if (resp.result instanceof Throwable) {
219                                                 // Error to be handled
220                                                 Throwable ex = (Throwable) resp.result;
221                                                 onError(ex);
222                                                 return false;
223                                         }
224                                         result = (T) resp.result;
225                                         if (result != null) {
226                                                 onComplete();
227                                         }
228                                         complete = true;
229                                         return false;
230                                 }
231                         }
232                 
233                         if(!requestSent) {
234                                 cache.put(key,null);
235                                 sendRequest();
236                         }
237                 }
238                 
239                 if(com){
240                         if(isShowLoadingIndicator())
241                                 GSS.get().hideLoadingIndicator();
242                         if(getResult() != null) {
243                                 // Add to cache
244                                 cache.put(key, new ResponseData(System.currentTimeMillis(), getResult()));
245                                 onComplete();
246                         }
247                         else {
248                                 cache.put(key, new ResponseData(System.currentTimeMillis(), exception));
249                                 onError(exception);
250                         }
251                         return false;
252                 }
253                 return true;
254         }
255
256         public Object deserializeResponse(String aPath, Response response) {
257                 RestResource result1 = null;
258                 if(aclass.equals(FolderResource.class)){
259                         result1 = new FolderResource(aPath);
260                         result1.createFromJSON(response.getText());
261                 }
262                 else if(aclass.equals(FileResource.class)){
263                         result1 = new FileResource(aPath);
264                         result1.createFromJSON(response.getHeader("X-GSS-Metadata"));
265                 }
266                 else if(aclass.equals(GroupsResource.class)){
267                         result1 = new GroupsResource(aPath);
268                         result1.createFromJSON(response.getText());
269                 }
270                 else if(aclass.equals(TrashResource.class)){
271                         result1 = new TrashResource(aPath);
272                         result1.createFromJSON(response.getText());
273                 }
274                 else if(aclass.equals(SharedResource.class)){
275                         result1 = new SharedResource(aPath);
276                         result1.createFromJSON(response.getText());
277                 }
278                 else if(aclass.equals(OthersResource.class)){
279                         result1 = new OthersResource(aPath);
280                         result1.createFromJSON(response.getText());
281                 }
282                 else if(aclass.equals(OtherUserResource.class)){
283                         result1 = new OtherUserResource(aPath);
284                         result1.createFromJSON(response.getText());
285                 }
286                 else if(aclass.equals(GroupResource.class)){
287                         result1 = new GroupResource(aPath);
288                         result1.createFromJSON(response.getText());
289                 }
290                 else if(aclass.equals(GroupUserResource.class)){
291                         result1 = new GroupUserResource(aPath);
292                         result1.createFromJSON(response.getText());
293                 }
294                 else if(aclass.equals(UserResource.class)){
295                         result1 = new UserResource(aPath);
296                         result1.createFromJSON(response.getText());
297                 }
298                 else if(aclass.equals(TagsResource.class)){
299                         result1 = new TagsResource(aPath);
300                         result1.createFromJSON(response.getText());
301                 }
302                 else if(aclass.equals(SearchResource.class)){
303                         result1 = new SearchResource(aPath);
304                         result1.createFromJSON(response.getText());
305                 }
306                 else if(aclass.equals(UserSearchResource.class)){
307                         result1 = new UserSearchResource(aPath);
308                         result1.createFromJSON(response.getText());
309                 }
310                 else if(aclass.equals(UploadStatusResource.class)){
311                         result1 = new UploadStatusResource(aPath);
312                         result1.createFromJSON(response.getText());
313                 }
314                 return result1;
315         }
316
317         public T getCached() {
318                 return cached;
319         }
320
321         public void setCached(T theCached) {
322                 this.cached = theCached;
323         }
324         
325         public boolean usedCachedVersion(){
326                 if(exception !=null && exception instanceof RestException)
327                         if(((RestException)exception).getHttpStatusCode() == 304){
328                                 return true;
329                         }
330                 return false;
331         }
332 }