fix lazy loading excpetions
[pithos] / src / gr / ebs / gss / 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.client.rest;
20
21 import gr.ebs.gss.client.GSS;
22 import gr.ebs.gss.client.rest.resource.FileResource;
23 import gr.ebs.gss.client.rest.resource.FolderResource;
24 import gr.ebs.gss.client.rest.resource.GroupResource;
25 import gr.ebs.gss.client.rest.resource.GroupUserResource;
26 import gr.ebs.gss.client.rest.resource.GroupsResource;
27 import gr.ebs.gss.client.rest.resource.OtherUserResource;
28 import gr.ebs.gss.client.rest.resource.OthersResource;
29 import gr.ebs.gss.client.rest.resource.RestResource;
30 import gr.ebs.gss.client.rest.resource.SearchResource;
31 import gr.ebs.gss.client.rest.resource.SharedResource;
32 import gr.ebs.gss.client.rest.resource.TagsResource;
33 import gr.ebs.gss.client.rest.resource.TrashResource;
34 import gr.ebs.gss.client.rest.resource.UploadStatusResource;
35 import gr.ebs.gss.client.rest.resource.UserResource;
36 import gr.ebs.gss.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                                         if(_exception instanceof RestException)
169                                                 if(((RestException)_exception).getHttpStatusCode() == 304 && cached != null){
170                                                         GWT.log("Using cache:"+cached.getUri(), null);
171                                                         handleSuccess(cached);
172                                                         return;
173                                                 }
174                                         exception = _exception;
175                                 }
176
177                                 @Override
178                                 public void handleSuccess(Object object) {
179                                         result = (T) object;
180                                         complete = true;
181                                 }
182
183                         });
184                 } catch (Exception ex) {
185                         complete = true;
186                         exception = ex;
187                 }
188         }
189         public boolean isComplete() {
190                 return complete;
191         }
192
193         public T getResult(){
194                 return result;
195         }
196
197         @Override
198         public boolean execute() {
199                 boolean com = isComplete();
200                 RequestData key = new RequestData(path, username);
201                 if (!com) {
202                         if (cache.containsKey(key)) {
203                                 ResponseData resp = cache.get(key);
204                                 if (resp==null) {
205                                         return true;
206                                 }
207                                 
208                                 // Cache hit
209                                 if (System.currentTimeMillis()-resp.timestamp>MAX_CACHE_AGE) {
210                                         // Cache stale, remove
211                                         cache.put(key,null);
212                                 }
213                                 else {
214                                         // Use cache data
215                                         if(isShowLoadingIndicator())
216                                                 GSS.get().hideLoadingIndicator();
217                                         if (resp.result instanceof Throwable) {
218                                                 // Error to be handled
219                                                 Throwable ex = (Throwable) resp.result;
220                                                 onError(ex);
221                                                 return false;
222                                         }
223                                         result = (T) resp.result;
224                                         if (result != null) {
225                                                 onComplete();
226                                         }
227                                         complete = true;
228                                         return false;
229                                 }
230                         }
231                 
232                         if(!requestSent) {
233                                 cache.put(key,null);
234                                 sendRequest();
235                         }
236                 }
237                 
238                 if(com){
239                         if(isShowLoadingIndicator())
240                                 GSS.get().hideLoadingIndicator();
241                         if(getResult() != null) {
242                                 // Add to cache
243                                 cache.put(key, new ResponseData(System.currentTimeMillis(), getResult()));
244                                 onComplete();
245                         }
246                         else {
247                                 cache.put(key, new ResponseData(System.currentTimeMillis(), exception));
248                                 onError(exception);
249                         }
250                         return false;
251                 }
252                 return true;
253         }
254
255         public Object deserializeResponse(String aPath, Response response) {
256                 RestResource result1 = null;
257                 if(aclass.equals(FolderResource.class)){
258                         result1 = new FolderResource(aPath);
259                         result1.createFromJSON(response.getText());
260                 }
261                 else if(aclass.equals(FileResource.class)){
262                         result1 = new FileResource(aPath);
263                         result1.createFromJSON(response.getHeader("X-GSS-Metadata"));
264                 }
265                 else if(aclass.equals(GroupsResource.class)){
266                         result1 = new GroupsResource(aPath);
267                         result1.createFromJSON(response.getText());
268                 }
269                 else if(aclass.equals(TrashResource.class)){
270                         result1 = new TrashResource(aPath);
271                         result1.createFromJSON(response.getText());
272                 }
273                 else if(aclass.equals(SharedResource.class)){
274                         result1 = new SharedResource(aPath);
275                         result1.createFromJSON(response.getText());
276                 }
277                 else if(aclass.equals(OthersResource.class)){
278                         result1 = new OthersResource(aPath);
279                         result1.createFromJSON(response.getText());
280                 }
281                 else if(aclass.equals(OtherUserResource.class)){
282                         result1 = new OtherUserResource(aPath);
283                         result1.createFromJSON(response.getText());
284                 }
285                 else if(aclass.equals(GroupResource.class)){
286                         result1 = new GroupResource(aPath);
287                         result1.createFromJSON(response.getText());
288                 }
289                 else if(aclass.equals(GroupUserResource.class)){
290                         result1 = new GroupUserResource(aPath);
291                         result1.createFromJSON(response.getText());
292                 }
293                 else if(aclass.equals(UserResource.class)){
294                         result1 = new UserResource(aPath);
295                         result1.createFromJSON(response.getText());
296                 }
297                 else if(aclass.equals(TagsResource.class)){
298                         result1 = new TagsResource(aPath);
299                         result1.createFromJSON(response.getText());
300                 }
301                 else if(aclass.equals(SearchResource.class)){
302                         result1 = new SearchResource(aPath);
303                         result1.createFromJSON(response.getText());
304                 }
305                 else if(aclass.equals(UserSearchResource.class)){
306                         result1 = new UserSearchResource(aPath);
307                         result1.createFromJSON(response.getText());
308                 }
309                 else if(aclass.equals(UploadStatusResource.class)){
310                         result1 = new UploadStatusResource(aPath);
311                         result1.createFromJSON(response.getText());
312                 }
313                 return result1;
314         }
315
316         public T getCached() {
317                 return cached;
318         }
319
320         public void setCached(T theCached) {
321                 this.cached = theCached;
322         }
323 }