KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > http > client > Request


1 /*
2  * Copyright 2006 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */

16 package com.google.gwt.http.client;
17
18 import com.google.gwt.core.client.GWT;
19 import com.google.gwt.core.client.JavaScriptObject;
20 import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
21 import com.google.gwt.user.client.Timer;
22
23 /**
24  * An HTTP request that is waiting for a response. Requests can be queried for
25  * their pending status or they can be canceled.
26  *
27  * <h3>Required Module</h3>
28  * Modules that use this class should inherit
29  * <code>com.google.gwt.http.HTTP</code>.
30  *
31  * {@gwt.include com/google/gwt/examples/http/InheritsExample.gwt.xml}
32  *
33  */

34 public class Request {
35   /**
36    * Creates a {@link Response} instance for the given JavaScript XmlHttpRequest
37    * object.
38    *
39    * @param xmlHttpRequest xmlHttpRequest object for which we need a response
40    * @return a {@link Response} object instance
41    */

42   private static Response createResponse(final JavaScriptObject xmlHttpRequest) {
43     assert (XMLHTTPRequest.isResponseReady(xmlHttpRequest));
44     Response response = new Response() {
45       public String JavaDoc getHeader(String JavaDoc header) {
46         StringValidator.throwIfEmptyOrNull("header", header);
47
48         return XMLHTTPRequest.getResponseHeader(xmlHttpRequest, header);
49       }
50
51       public Header[] getHeaders() {
52         return XMLHTTPRequest.getHeaders(xmlHttpRequest);
53       }
54
55       public String JavaDoc getHeadersAsString() {
56         return XMLHTTPRequest.getAllResponseHeaders(xmlHttpRequest);
57       }
58
59       public int getStatusCode() {
60         return XMLHTTPRequest.getStatusCode(xmlHttpRequest);
61       }
62
63       public String JavaDoc getStatusText() {
64         return XMLHTTPRequest.getStatusText(xmlHttpRequest);
65       }
66
67       public String JavaDoc getText() {
68         return XMLHTTPRequest.getResponseText(xmlHttpRequest);
69       }
70     };
71     return response;
72   }
73
74   /**
75    * The number of milliseconds to wait for this HTTP request to complete.
76    */

77   private final int timeoutMillis;
78
79   /*
80    * Timer used to force HTTPRequest timeouts. If the user has not requested a
81    * timeout then this field is null.
82    */

83   private final Timer timer;
84
85   /*
86    * JavaScript XmlHttpRequest object that this Java class wraps. This field is
87    * not final because we transfer ownership of it to the HTTPResponse object
88    * and set this field to null.
89    */

90   private JavaScriptObject xmlHttpRequest;
91
92   /**
93    * Constructs an instance of the Request object.
94    *
95    * @param xmlHttpRequest JavaScript XmlHttpRequest object instance
96    * @param timeoutMillis number of milliseconds to wait for a response
97    * @param callback callback interface to use for notification
98    *
99    * @throws IllegalArgumentException if timeoutMillis &lt; 0
100    * @throws NullPointerException if xmlHttpRequest, or callback are null
101    */

102   Request(JavaScriptObject xmlHttpRequest, int timeoutMillis,
103       final RequestCallback callback) {
104     if (xmlHttpRequest == null) {
105       throw new NullPointerException JavaDoc();
106     }
107
108     if (callback == null) {
109       throw new NullPointerException JavaDoc();
110     }
111
112     if (timeoutMillis < 0) {
113       throw new IllegalArgumentException JavaDoc();
114     }
115
116     this.timeoutMillis = timeoutMillis;
117
118     this.xmlHttpRequest = xmlHttpRequest;
119
120     if (timeoutMillis > 0) {
121       // create and start a Timer
122
timer = new Timer() {
123         public void run() {
124           fireOnTimeout(callback);
125         }
126       };
127
128       timer.schedule(timeoutMillis);
129     } else {
130       // no Timer required
131
timer = null;
132     }
133   }
134
135   /**
136    * Cancels a pending request. If the request has already been canceled or if
137    * it has timed out no action is taken.
138    */

139   public void cancel() {
140     /*
141      * There is a strange race condition that occurs on Mozilla when you cancel
142      * a request while the response is coming in. It appears that in some cases
143      * the onreadystatechange handler is still called after the handler function
144      * has been deleted and during the call to XmlHttpRequest.abort(). So we
145      * null the xmlHttpRequest here and that will prevent the
146      * fireOnResponseReceived method from calling the callback function.
147      *
148      * Setting the onreadystatechange handler to null gives us the correct
149      * behavior in Mozilla but crashes IE. That is why we have chosen to fixed
150      * this in Java by nulling out our reference to the XmlHttpRequest object.
151      */

152     if (xmlHttpRequest != null) {
153       JavaScriptObject xmlHttp = xmlHttpRequest;
154       xmlHttpRequest = null;
155
156       XMLHTTPRequest.abort(xmlHttp);
157
158       cancelTimer();
159     }
160   }
161
162   /**
163    * Returns true if this request is waiting for a response.
164    *
165    * @return true if this request is waiting for a response
166    */

167   public boolean isPending() {
168     if (xmlHttpRequest == null) {
169       return false;
170     }
171
172     int readyState = XMLHTTPRequest.getReadyState(xmlHttpRequest);
173
174     /*
175      * Because we are doing asynchronous requests it is possible that we can
176      * call XmlHttpRequest.send and still have the XmlHttpRequest.getReadyState
177      * method return the state as XmlHttpRequest.OPEN. That is why we include
178      * open although it is not *technically* true since open implies that the
179      * request has not been sent.
180      */

181     switch (readyState) {
182       case XMLHTTPRequest.OPEN:
183       case XMLHTTPRequest.SENT:
184       case XMLHTTPRequest.RECEIVING:
185         return true;
186     }
187
188     return false;
189   }
190
191   /*
192    * Stops the current HTTPRequest timer if there is one.
193    */

194   private void cancelTimer() {
195     if (timer != null) {
196       timer.cancel();
197     }
198   }
199
200   /*
201    * Method called when the JavaScript XmlHttpRequest object's readyState
202    * reaches 4 (LOADED).
203    *
204    * NOTE: this method is called from JSNI
205    */

206   private void fireOnResponseReceived(RequestCallback callback) {
207     UncaughtExceptionHandler handler = GWT.getUncaughtExceptionHandler();
208     if (handler != null) {
209       fireOnResponseReceivedAndCatch(handler, callback);
210     } else {
211       fireOnResponseReceivedImpl(callback);
212     }
213   }
214
215   private void fireOnResponseReceivedAndCatch(UncaughtExceptionHandler handler,
216       RequestCallback callback) {
217     try {
218       fireOnResponseReceivedImpl(callback);
219     } catch (Throwable JavaDoc e) {
220       handler.onUncaughtException(e);
221     }
222   }
223
224   private void fireOnResponseReceivedImpl(RequestCallback callback) {
225     if (xmlHttpRequest == null) {
226       // the request has timed out at this point
227
return;
228     }
229
230     cancelTimer();
231
232     /*
233      * We cannot use cancel here because it would clear the contents of the
234      * JavaScript XmlHttpRequest object so we manually null out our reference to
235      * the JavaScriptObject
236      */

237     final JavaScriptObject xmlHttp = xmlHttpRequest;
238     xmlHttpRequest = null;
239
240     String JavaDoc errorMsg = XMLHTTPRequest.getBrowserSpecificFailure(xmlHttp);
241     if (errorMsg != null) {
242       Throwable JavaDoc exception = new RuntimeException JavaDoc(errorMsg);
243       callback.onError(this, exception);
244     } else {
245       Response response = createResponse(xmlHttp);
246       callback.onResponseReceived(this, response);
247     }
248   }
249
250   /*
251    * Method called when this request times out.
252    *
253    * NOTE: this method is called from JSNI
254    */

255   private final void fireOnTimeout(RequestCallback callback) {
256     if (xmlHttpRequest == null) {
257       // the request has been received at this point
258
return;
259     }
260
261     cancel();
262
263     callback.onError(this, new RequestTimeoutException(this, timeoutMillis));
264   }
265 }
266
Popular Tags