Statistics
| Branch: | Revision:

root / asi-http-request-with-pithos / Classes / Pithos / ASIPithosContainerRequest.m @ 2f6bc433

History | View | Annotate | Download (22.6 kB)

1
//  ASIPithosContainerRequest.m
2
//  Based on ASICloudFilesContainerRequest.m
3
//
4
// Copyright 2011-2012 GRNET S.A. All rights reserved.
5
//
6
// Redistribution and use in source and binary forms, with or
7
// without modification, are permitted provided that the following
8
// conditions are met:
9
// 
10
//   1. Redistributions of source code must retain the above
11
//      copyright notice, this list of conditions and the following
12
//      disclaimer.
13
// 
14
//   2. Redistributions in binary form must reproduce the above
15
//      copyright notice, this list of conditions and the following
16
//      disclaimer in the documentation and/or other materials
17
//      provided with the distribution.
18
// 
19
// THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
20
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
23
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26
// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27
// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
// POSSIBILITY OF SUCH DAMAGE.
31
// 
32
// The views and conclusions contained in the software and
33
// documentation are those of the authors and should not be
34
// interpreted as representing official policies, either expressed
35
// or implied, of GRNET S.A.
36

    
37
#import "ASIPithosContainerRequest.h"
38
#import "ASIPithos.h"
39
#import "ASIPithosContainer.h"
40
#import "ASIPithosObject.h"
41

    
42
@implementation ASIPithosContainerRequest
43
@synthesize containerName;
44
@synthesize currentObject, currentKey;
45

    
46
#pragma mark -
47
#pragma mark Constructors
48

    
49
+ (id)storageRequestWithMethod:(NSString *)method 
50
                        pithos:(ASIPithos *)pithos 
51
                 containerName:(NSString *)containerName 
52
                   queryString:(NSString *)queryString {
53
    NSString *urlString = [NSString stringWithFormat:@"%@/%@", pithos.storageURL, [self encodeToPercentEscape:containerName]];
54
    if (queryString)
55
        urlString = [urlString stringByAppendingString:queryString];
56

    
57
	ASIPithosContainerRequest *request = [self requestWithURL:[NSURL URLWithString:urlString]];
58
	[request setRequestMethod:method];
59
	[request addRequestHeader:@"X-Auth-Token" value:pithos.authToken];
60
    request.containerName = containerName;
61
    request.validatesSecureCertificate = !pithos.ignoreSSLErrors;
62
    request.retryBaseURLString = pithos.storageURLPrefix;
63
    request.retryType = ASIPithosRequestTypeStorage;
64
	return request;
65
}
66

    
67
+ (id)storageRequestWithMethod:(NSString *)method pithos:(ASIPithos *)pithos containerName:(NSString *)containerName {
68
	return [self storageRequestWithMethod:method pithos:pithos containerName:containerName queryString:nil];
69
}
70

    
71
#pragma mark -
72
#pragma mark Memory Management
73

    
74
- (void)dealloc {
75
    [currentKey release];
76
	[currentObject release];
77
    [objects release];
78
    [metadata release];
79
    [policy release];
80
    [containerName release];
81
	[super dealloc];
82
}
83

    
84
#pragma mark -
85
#pragma mark HEAD
86

    
87
// HEAD storageURL/container
88
+ (id)containerMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName {
89
    return [self storageRequestWithMethod:@"HEAD" pithos:pithos containerName:containerName];
90
}
91

    
92
// HEAD storageURL/container?[until=untilTimestamp]
93
+ (id)containerMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName until:(NSDate *)untilTimestamp {
94
    NSString *queryString = nil;
95
    if (untilTimestamp)
96
        queryString = [NSString stringWithFormat:@"?until=%d", (int)[untilTimestamp timeIntervalSince1970]];
97
    
98
	return [self storageRequestWithMethod:@"HEAD" pithos:pithos containerName:containerName queryString:queryString];
99
}
100

    
101
// HEAD storageURL/container?[until=untilTimestamp] [If-Modified-Since]
102
+ (id)containerMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName 
103
                                   until:(NSDate *)untilTimestamp 
104
                         ifModifiedSince:(NSDate *)sinceTimestamp {
105
    ASIPithosContainerRequest *request = [self containerMetadataRequestWithPithos:pithos containerName:containerName until:untilTimestamp];
106
    [request addRequestIfModifiedSinceHeader:sinceTimestamp];
107
    return request;
108
}
109

    
110
// HEAD storageURL/container?[until=untilTimestamp] [If-Unmodified-Since]
111
+ (id)containerMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName 
112
                                   until:(NSDate *)untilTimestamp 
113
                       ifUnmodifiedSince:(NSDate *)sinceTimestamp {
114
    ASIPithosContainerRequest *request = [self containerMetadataRequestWithPithos:pithos containerName:containerName until:untilTimestamp];
115
    [request addRequestIfUnmodifiedSinceHeader:sinceTimestamp];
116
    return request;
117
}
118

    
119
- (NSUInteger)objectCount {
120
	return [[[self responseHeaders] objectForKey:@"X-Container-Object-Count"] integerValue];
121
}
122

    
123
- (NSUInteger)bytesUsed {
124
	return [[[self responseHeaders] objectForKey:@"X-Container-Bytes-Used"] integerValue];
125
}
126

    
127
- (NSUInteger)blockSize {
128
	return [[[self responseHeaders] objectForKey:@"X-Container-Block-Size"] integerValue];
129
}
130

    
131
- (NSString *)blockHash {
132
	return [[self responseHeaders] objectForKey:@"X-Container-Block-Hash"];
133
}
134

    
135
- (NSArray *)objectMeta {
136
    return [[self decodeFromPercentEscape:[[self responseHeaders] objectForKey:@"X-Container-Object-Meta"]] 
137
            componentsSeparatedByString:@","];
138
}
139

    
140
- (NSDate *)untilTimestamp {
141
    NSString *untilTimestampString = [[self responseHeaders] objectForKey:@"X-Container-Until-Timestamp"];
142
    if (untilTimestampString)
143
        return [[self dateFormatterWithFormatId:1] dateFromString:untilTimestampString];
144
    return nil;
145
}
146

    
147
- (NSDictionary *)policy {
148
    if (policy == nil) {
149
        policy = [self getHeadersDictionaryForPrefix:@"X-Container-Policy-"];
150
        [policy retain];
151
    }
152
    return policy;
153
}
154

    
155
- (NSDictionary *)metadata {
156
    if (metadata == nil) {
157
        metadata = [self getHeadersDictionaryForPrefix:@"X-Container-Meta-"];
158
        [metadata retain];
159
    }
160
    return metadata;
161
}
162

    
163
- (NSDate *)lastModified {
164
    NSString *lastModifiedString = [[self responseHeaders] objectForKey:@"Last-Modified"];
165
    if (lastModifiedString)
166
        return [[self dateFormatterWithFormatId:1] dateFromString:lastModifiedString];
167
    return nil;
168
}
169

    
170
- (ASIPithosContainer *)container {
171
    ASIPithosContainer *container = [ASIPithosContainer container];
172
    container.name = containerName;
173
    container.count = [self objectCount];
174
    container.bytes = [self bytesUsed];
175
    container.lastModified = [self lastModified];
176
    container.untilTimestamp = [self untilTimestamp];
177
    container.policy = (NSMutableDictionary *)[self policy];
178
    container.metadata = (NSMutableDictionary *)[self metadata];
179
    container.blockSize =  [self blockSize];
180
    container.blockHash =  [self blockHash];
181
    container.objectMeta = (NSMutableArray *)[self objectMeta];
182
    return container;
183
}
184

    
185
#pragma mark -
186
#pragma mark GET
187

    
188
// GET storageURL/container
189
+ (id)listObjectsRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName {
190
    return [self storageRequestWithMethod:@"GET" pithos:pithos containerName:containerName queryString:@"?format=xml"];
191
}
192

    
193
// GET storageURL?[limit=limit]&[marker=marker]&[prefix=prefix]&[delimiter=delimiter]&[path=path]&[meta=meta]&[shared=]&[until=untilTimestamp]
194
+ (id)listObjectsRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName
195
                             limit:(NSUInteger)limit 
196
                            marker:(NSString *)marker 
197
                            prefix:(NSString *)prefix 
198
                         delimiter:(NSString *)delimiter 
199
                              path:(NSString *)path 
200
                              meta:(NSArray *)meta 
201
                            shared:(BOOL)shared
202
                             until:(NSDate *)untilTimestamp {
203
    NSString *queryString = @"?format=xml";
204
	if (limit && (limit > 0))
205
		queryString = [queryString stringByAppendingString:[NSString stringWithFormat:@"&limit=%lu", limit]];
206
	if (marker)
207
		queryString = [queryString stringByAppendingString:[NSString stringWithFormat:@"&marker=%@", [self encodeToPercentEscape:marker]]];
208
	if (prefix)
209
		queryString = [queryString stringByAppendingString:[NSString stringWithFormat:@"&prefix=%@", [self encodeToPercentEscape:prefix]]];
210
	if (delimiter)
211
		queryString = [queryString stringByAppendingString:[NSString stringWithFormat:@"&delimiter=%@", [self encodeToPercentEscape:delimiter]]];
212
	if (path)
213
		queryString = [queryString stringByAppendingString:[NSString stringWithFormat:@"&path=%@", [self encodeToPercentEscape:path]]];
214
    if (meta)
215
        queryString = [queryString stringByAppendingString:[NSString stringWithFormat:@"&meta=%@", [self encodeToPercentEscape:[meta componentsJoinedByString:@","]]]];
216
	if (shared)
217
		queryString = [queryString stringByAppendingString:@"&shared="];
218
    if (untilTimestamp)
219
        queryString = [queryString stringByAppendingString:[NSString stringWithFormat:@"&until=%d", (int)[untilTimestamp timeIntervalSince1970]]];
220
    
221
    return [self storageRequestWithMethod:@"GET" pithos:pithos containerName:containerName queryString:queryString];
222
}
223

    
224
// GET storageURL?[limit=limit]&[marker=marker]&[prefix=prefix]&[delimiter=delimiter]&[path=path]&[meta=meta]&[shared=]&[until=untilTimestamp] [If-Modified-Since]
225
+ (id)listObjectsRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName
226
                             limit:(NSUInteger)limit 
227
                            marker:(NSString *)marker 
228
                            prefix:(NSString *)prefix 
229
                         delimiter:(NSString *)delimiter 
230
                              path:(NSString *)path 
231
                              meta:(NSArray *)meta 
232
                            shared:(BOOL)shared
233
                             until:(NSDate *)untilTimestamp 
234
                   ifModifiedSince:(NSDate *)sinceTimestamp {
235
    ASIPithosContainerRequest *request = [self listObjectsRequestWithPithos:pithos 
236
                                                              containerName:containerName 
237
                                                                      limit:limit 
238
                                                                     marker:marker 
239
                                                                     prefix:prefix 
240
                                                                  delimiter:delimiter 
241
                                                                       path:path 
242
                                                                       meta:meta 
243
                                                                     shared:shared 
244
                                                                      until:untilTimestamp];
245
    [request addRequestIfModifiedSinceHeader:sinceTimestamp];
246
    return request;
247
}
248

    
249
// GET storageURL?[limit=limit]&[marker=marker]&[prefix=prefix]&[delimiter=delimiter]&[path=path]&[meta=meta]&[shared=]&[until=untilTimestamp] [If-Unmodified-Since]
250
+ (id)listObjectsRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName
251
                             limit:(NSUInteger)limit 
252
                            marker:(NSString *)marker 
253
                            prefix:(NSString *)prefix 
254
                         delimiter:(NSString *)delimiter 
255
                              path:(NSString *)path 
256
                              meta:(NSArray *)meta 
257
                            shared:(BOOL)shared
258
                             until:(NSDate *)untilTimestamp 
259
                 ifUnmodifiedSince:(NSDate *)sinceTimestamp {
260
    ASIPithosContainerRequest *request = [self listObjectsRequestWithPithos:pithos 
261
                                                              containerName:containerName 
262
                                                                      limit:limit 
263
                                                                     marker:marker 
264
                                                                     prefix:prefix 
265
                                                                  delimiter:delimiter 
266
                                                                       path:path 
267
                                                                       meta:meta 
268
                                                                     shared:shared 
269
                                                                      until:untilTimestamp];
270
    [request addRequestIfUnmodifiedSinceHeader:sinceTimestamp];
271
    return request;
272
}
273

    
274

    
275
- (NSArray *)objects {
276
    if (objects == nil) {
277
        objects = [[NSMutableArray alloc] init];
278
        
279
        NSXMLParser *parser = [[[NSXMLParser alloc] initWithData:[self responseData]] autorelease];
280
        [parser setDelegate:self];
281
        [parser setShouldProcessNamespaces:NO];
282
        [parser setShouldReportNamespacePrefixes:NO];
283
        [parser setShouldResolveExternalEntities:NO];
284
        [parser parse];
285
    }    
286
	return objects;
287
}
288

    
289
#pragma mark -
290
#pragma mark PUT
291

    
292
// PUT storageURL/container
293
+ (id)createOrUpdateContainerRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName {
294
    return [self storageRequestWithMethod:@"PUT" pithos:pithos containerName:containerName];
295
}
296

    
297
// PUT storageURL/container [X-Container-Policy-*] [X-Container-Meta-*]
298
+ (id)createOrUpdateContainerRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName 
299
                                        policy:(NSDictionary *)policy 
300
                                      metadata:(NSDictionary *)metadata {
301
    ASIPithosContainerRequest *request = [self storageRequestWithMethod:@"PUT" pithos:pithos containerName:containerName];
302
	
303
    if (policy) {
304
        for (NSString *key in policy) {
305
            [request addRequestHeader:[NSString stringWithFormat:@"X-Container-Policy-%@", key] value:[policy objectForKey:key]];
306
        }
307
    }
308
    
309
    if (metadata) {
310
        for (NSString *key in metadata) {
311
            [request addRequestHeader:[self encodeToPercentEscape:[NSString stringWithFormat:@"X-Container-Meta-%@", key]] 
312
                                value:[self encodeToPercentEscape:[metadata objectForKey:key]]];
313
        }
314
    }
315
    
316
	return request;
317
}
318

    
319
#pragma mark -
320
#pragma mark POST
321

    
322
// POST storageURL/container
323
+ (id)updateContainerMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName {
324
    return [self storageRequestWithMethod:@"POST" pithos:pithos containerName:containerName];
325
}
326

    
327
// POST storageURL/container?[update=] [X-Container-Policy-*] [X-Container-Meta-*]
328
+ (id)updateContainerMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName 
329
                                        policy:(NSDictionary *)policy 
330
                                      metadata:(NSDictionary *)metadata 
331
                                        update:(BOOL)update {
332
    NSString *queryString = nil;
333
    if (update)
334
        queryString = @"?update=";
335
    ASIPithosContainerRequest *request = [self storageRequestWithMethod:@"POST" 
336
                                                                 pithos:pithos 
337
                                                          containerName:containerName 
338
                                                            queryString:queryString];
339
    if (policy) {
340
        for (NSString *key in policy) {
341
            [request addRequestHeader:[NSString stringWithFormat:@"X-Container-Policy-%@", key] value:[policy objectForKey:key]];
342
        }
343
    }
344
    
345
    if (metadata) {
346
        for (NSString *key in metadata) {
347
            [request addRequestHeader:[self encodeToPercentEscape:[NSString stringWithFormat:@"X-Container-Meta-%@", key]] 
348
                                value:[self encodeToPercentEscape:[metadata objectForKey:key]]];
349
        }
350
    }
351
    
352
	return request;
353
}
354

    
355
// POST storageURL/container?[update=] [X-Container-Policy-*] [X-Container-Meta-*] (update data from ASIPithosObject with data)
356
+ (id)updateContainerDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName 
357
                                    policy:(NSDictionary *)policy 
358
                                  metadata:(NSDictionary *)metadata 
359
                                    update:(BOOL)update
360
                                    object:(ASIPithosObject *)object {
361
    return [self updateContainerDataRequestWithPithos:pithos 
362
                                        containerName:containerName 
363
                                               policy:policy 
364
                                             metadata:metadata 
365
                                               update:update 
366
                                                 data:object.data];
367
}
368

    
369
// POST storageURL/container?[update=] [X-Container-Policy-*] [X-Container-Meta-*] (update data from NSData)
370
+ (id)updateContainerDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName 
371
                                    policy:(NSDictionary *)policy 
372
                                  metadata:(NSDictionary *)metadata 
373
                                    update:(BOOL)update
374
                                      data:(NSData *)data {
375
    ASIPithosContainerRequest *request = [self updateContainerMetadataRequestWithPithos:pithos 
376
                                                                          containerName:containerName 
377
                                                                                 policy:policy 
378
                                                                               metadata:metadata 
379
                                                                                 update:update];    
380
    [request addRequestHeader:@"Content-Type" value:@"application/octet-stream"];
381
	[request appendPostData:data];
382
	return request;
383
}
384

    
385
// POST storageURL/container?[update=] [X-Container-Policy-*] [X-Container-Meta-*] (update data from file)
386
+ (id)updateContainerDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName 
387
                                    policy:(NSDictionary *)policy 
388
                                  metadata:(NSDictionary *)metadata 
389
                                    update:(BOOL)update
390
                                      file:(NSString *)filePath {
391
    ASIPithosContainerRequest *request = [self updateContainerMetadataRequestWithPithos:pithos 
392
                                                                          containerName:containerName 
393
                                                                                 policy:policy 
394
                                                                               metadata:metadata 
395
                                                                                 update:update];    
396
    [request addRequestHeader:@"Content-Type" value:@"application/octet-stream"];
397
	request.shouldStreamPostDataFromDisk = YES;
398
    request.postBodyFilePath = filePath;
399
	return request;
400
}
401

    
402
#pragma mark -
403
#pragma mark DELETE
404

    
405
// DELETE storageURL/container
406
+ (id)deleteContainerRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName {
407
    return [self storageRequestWithMethod:@"DELETE" pithos:pithos containerName:containerName];
408
}
409

    
410
// DELETE storageURL/container?[until=untilTimestamp]
411
+ (id)deleteContainerRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName until:(NSDate *)untilTimestamp {
412
    NSString *queryString = nil;
413
    if (untilTimestamp)
414
        queryString = [NSString stringWithFormat:@"?until=%d", (int)[untilTimestamp timeIntervalSince1970]];
415
	return [self storageRequestWithMethod:@"DELETE" pithos:pithos containerName:containerName queryString:queryString];    
416
}
417

    
418
#pragma mark -
419
#pragma mark NSXMLParserDelegate
420

    
421
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
422
	self.currentElement = elementName;
423
	if ([elementName isEqualToString:@"object"]) {
424
		self.currentObject = [ASIPithosObject object];
425
	} else if ([elementName isEqualToString:@"subdir"]) {
426
		[objects addObject:[ASIPithosObject subdirWithName:[attributeDict valueForKey:@"name"]]];
427
	}
428

    
429
	self.currentContent = @"";
430
}
431

    
432
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
433
	if ([elementName isEqualToString:@"name"]) {
434
        currentObject.name = currentContent;
435
	} else if ([elementName isEqualToString:@"hash"]) {
436
        currentObject.hash = currentContent;
437
	} else if ([elementName isEqualToString:@"x_object_hash"]) {
438
        currentObject.objectHash = currentContent;
439
	} else if ([elementName isEqualToString:@"x_object_uuid"]) {
440
        currentObject.UUID = currentContent;
441
	} else if ([elementName isEqualToString:@"bytes"]) {
442
        currentObject.bytes = [currentContent integerValue];
443
	} else if ([elementName isEqualToString:@"content_type"]) {
444
        currentObject.contentType = currentContent;
445
    } else if ([elementName isEqualToString:@"last_modified"]) {
446
        currentObject.lastModified = [[self dateFormatterWithFormatId:0] dateFromString:
447
         [currentContent stringByReplacingOccurrencesOfString:@":" 
448
                                                   withString:@"" 
449
                                                      options:NSBackwardsSearch 
450
                                                        range:NSMakeRange(([currentContent length] - 3), 1)]];
451
	} else if ([elementName isEqualToString:@"x_object_version"]) {
452
        currentObject.version = currentContent;
453
    } else if ([elementName isEqualToString:@"x_object_version_timestamp"]) {
454
        currentObject.versionTimestamp = [NSDate dateWithTimeIntervalSince1970:[currentContent doubleValue]];
455
	} else if ([elementName isEqualToString:@"x_object_modified_by"]) {
456
        currentObject.modifiedBy = currentContent;
457
	} else if ([elementName isEqualToString:@"x_object_sharing"]) {
458
        currentObject.sharing = currentContent;
459
	} else if ([elementName isEqualToString:@"x_object_shared_by"]) {
460
        currentObject.sharedBy = currentContent;
461
	} else if ([elementName isEqualToString:@"x_object_public"]) {
462
        currentObject.publicURI = currentContent;
463
	} else if ([elementName isEqualToString:@"x_object_allowed_to"]) {
464
        currentObject.allowedTo = currentContent;
465
	} else if ([elementName isEqualToString:@"object"]) {
466
		[objects addObject:currentObject];
467
        self.currentObject = nil;
468
	}
469
}
470

    
471
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
472
    self.currentContent = [currentContent stringByAppendingString:string];
473
}
474
    
475
@end