API 0.9.5
Foundation/CPURLConnection.j
Go to the documentation of this file.
00001 /*
00002  * CPURLConnection.j
00003  * Foundation
00004  *
00005  * Created by Francisco Tolmasky.
00006  * Copyright 2008, 280 North, Inc.
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00021  */
00022 
00023 
00024 var CPURLConnectionDelegate = nil;
00025 
00070 @implementation CPURLConnection : CPObject
00071 {
00072     CPURLRequest    _request;
00073     id              _delegate;
00074     BOOL            _isCanceled;
00075     BOOL            _isLocalFileConnection;
00076 
00077     HTTPRequest     _HTTPRequest;
00078 }
00079 
00080 + (void)setClassDelegate:(id)delegate
00081 {
00082     CPURLConnectionDelegate = delegate;
00083 }
00084 
00085 /*
00086     Sends a request for the data from a URL. This is the easiest way to obtain data from a URL.
00087     @param aRequest contains the URL to request the data from
00088     @param aURLResponse not used
00089     @param anError not used
00090     @return the data at the URL or \c nil if there was an error
00091 */
00092 + (CPData)sendSynchronousRequest:(CPURLRequest)aRequest returningResponse:({CPURLResponse})aURLResponse
00093 {
00094     try
00095     {
00096         var request = new CFHTTPRequest();
00097 
00098         request.open([aRequest HTTPMethod], [[aRequest URL] absoluteString], NO);
00099 
00100         var fields = [aRequest allHTTPHeaderFields],
00101             key = nil,
00102             keys = [fields keyEnumerator];
00103 
00104         while (key = [keys nextObject])
00105             request.setRequestHeader(key, [fields objectForKey:key]);
00106 
00107         request.send([aRequest HTTPBody]);
00108 
00109         return [CPData dataWithRawString:request.responseText()];
00110     }
00111     catch (anException)
00112     {
00113     }
00114 
00115     return nil;
00116 }
00117 
00118 /*
00119     Creates a url connection with a delegate to monitor the request progress.
00120     @param aRequest contains the URL to obtain data from
00121     @param aDelegate will be sent messages related to the request progress
00122     @return a connection that can be \c started to initiate the request
00123 */
00124 + (CPURLConnection)connectionWithRequest:(CPURLRequest)aRequest delegate:(id)aDelegate
00125 {
00126     return [[self alloc] initWithRequest:aRequest delegate:aDelegate];
00127 }
00128 
00129 /*
00130     Default class initializer. Use one of the class methods instead.
00131     @param aRequest contains the URL to contact
00132     @param aDelegate will receive progress messages
00133     @param shouldStartImmediately whether the \c -start method should be called from here
00134     @return the initialized url connection
00135 */
00136 - (id)initWithRequest:(CPURLRequest)aRequest delegate:(id)aDelegate startImmediately:(BOOL)shouldStartImmediately
00137 {
00138     self = [super init];
00139 
00140     if (self)
00141     {
00142         _request = aRequest;
00143         _delegate = aDelegate;
00144         _isCanceled = NO;
00145 
00146         var URL = [_request URL],
00147             scheme = [URL scheme];
00148 
00149         // Browsers use "file:", Titanium uses "app:"
00150         _isLocalFileConnection =    scheme === "file" ||
00151                                     ((scheme === "http" || scheme === "https:") &&
00152                                     window.location &&
00153                                     (window.location.protocol === "file:" || window.location.protocol === "app:"));
00154 
00155         _HTTPRequest = new CFHTTPRequest();
00156 
00157         if (shouldStartImmediately)
00158             [self start];
00159     }
00160 
00161     return self;
00162 }
00163 
00164 - (id)initWithRequest:(CPURLRequest)aRequest delegate:(id)aDelegate
00165 {
00166     return [self initWithRequest:aRequest delegate:aDelegate startImmediately:YES];
00167 }
00168 
00169 /*
00170     return the delegate
00171 */
00172 - (id)delegate
00173 {
00174     return _delegate;
00175 }
00176 
00177 /*
00178     Start the connection. Not needed if you used the class method +connectionWithRequest:delegate:
00179 */
00180 - (void)start
00181 {
00182     _isCanceled = NO;
00183 
00184     try
00185     {
00186         _HTTPRequest.open([_request HTTPMethod], [[_request URL] absoluteString], YES);
00187 
00188         _HTTPRequest.onreadystatechange = function() { [self _readyStateDidChange]; }
00189 
00190         var fields = [_request allHTTPHeaderFields],
00191             key = nil,
00192             keys = [fields keyEnumerator];
00193 
00194         while (key = [keys nextObject])
00195             _HTTPRequest.setRequestHeader(key, [fields objectForKey:key]);
00196 
00197         _HTTPRequest.send([_request HTTPBody]);
00198     }
00199     catch (anException)
00200     {
00201         if ([_delegate respondsToSelector:@selector(connection:didFailWithError:)])
00202             [_delegate connection:self didFailWithError:anException];
00203     }
00204 }
00205 
00206 /*
00207     Cancels the current request.
00208 */
00209 - (void)cancel
00210 {
00211     _isCanceled = YES;
00212 
00213     try
00214     {
00215         _HTTPRequest.abort();
00216     }
00217     // We expect an exception in some browsers like FireFox.
00218     catch (anException)
00219     {
00220     }
00221 }
00222 
00223 - (BOOL)isLocalFileConnection
00224 {
00225     return _isLocalFileConnection;
00226 }
00227 
00228 /* @ignore */
00229 - (void)_readyStateDidChange
00230 {
00231     if (_HTTPRequest.readyState() === CFHTTPRequest.CompleteState)
00232     {
00233         var statusCode = _HTTPRequest.status(),
00234             URL = [_request URL];
00235 
00236         if (statusCode === 401 && [CPURLConnectionDelegate respondsToSelector:@selector(connectionDidReceiveAuthenticationChallenge:)])
00237             [CPURLConnectionDelegate connectionDidReceiveAuthenticationChallenge:self];
00238         else
00239         {
00240             if ([_delegate respondsToSelector:@selector(connection:didReceiveResponse:)])
00241             {
00242                 if (_isLocalFileConnection)
00243                     [_delegate connection:self didReceiveResponse:[[CPURLResponse alloc] initWithURL:URL]];
00244                 else
00245                 {
00246                     var response = [[CPHTTPURLResponse alloc] initWithURL:URL];
00247                     [response _setStatusCode:statusCode];
00248                     [_delegate connection:self didReceiveResponse:response];
00249                 }
00250             }
00251             if (!_isCanceled)
00252             {
00253                 if ([_delegate respondsToSelector:@selector(connection:didReceiveData:)])
00254                     [_delegate connection:self didReceiveData:_HTTPRequest.responseText()];
00255                 if ([_delegate respondsToSelector:@selector(connectionDidFinishLoading:)])
00256                     [_delegate connectionDidFinishLoading:self];
00257             }
00258         }
00259     }
00260 
00261     [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
00262 }
00263 
00264 /* @ignore */
00265 - (HTTPRequest)_HTTPRequest
00266 {
00267     return _HTTPRequest;
00268 }
00269 
00270 @end
00271 
00272 @implementation CPURLConnection (Deprecated)
00273 
00274 + (CPData)sendSynchronousRequest:(CPURLRequest)aRequest returningResponse:({CPURLResponse})aURLResponse error:(id)anError
00275 {
00276     _CPReportLenientDeprecation(self, _cmd, @selector(sendSynchronousRequest:returningResponse:));
00277 
00278     return [self sendSynchronousRequest:aRequest returningResponse:aURLResponse];
00279 }
00280 
00281 - (HTTPRequest)_XMLHTTPRequest
00282 {
00283     _CPReportLenientDeprecation(self, _cmd, @selector(_HTTPRequest));
00284 
00285     return [self _HTTPRequest];
00286 }
00287 
00288 @end
 All Classes Files Functions Variables Defines