Statistics
| Branch: | Revision:

root / asi-http-request-with-pithos / Classes / Pithos / ASIPithosContainerRequest.m @ 40db2cf7

History | View | Annotate | Download (22.4 kB)

1
//  ASIPithosContainerRequest.m
2
//  Based on ASICloudFilesContainerRequest.m
3
//
4
// Copyright 2011 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 "ASIPithosContainer.h"
39
#import "ASIPithosObject.h"
40

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

    
45
#pragma mark -
46
#pragma mark Constructors
47

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

    
53
	ASIPithosContainerRequest *request = [[[self alloc] initWithURL:[NSURL URLWithString:urlString]] autorelease];
54
	[request setRequestMethod:method];
55
	[request addRequestHeader:@"X-Auth-Token" value:[self authToken]];
56
    request.containerName = containerName;
57
	return request;
58
}
59

    
60
+ (id)storageRequestWithMethod:(NSString *)method containerName:(NSString *)containerName {
61
	return [self storageRequestWithMethod:method containerName:containerName queryString:nil];
62
}
63

    
64
#pragma mark -
65
#pragma mark Memory Management
66

    
67
- (void)dealloc {
68
    [currentKey release];
69
	[currentObject release];
70
    [objects release];
71
    [metadata release];
72
    [policy release];
73
    [containerName release];
74
	[super dealloc];
75
}
76

    
77
#pragma mark -
78
#pragma mark HEAD
79

    
80
// HEAD storageURL/container
81
+ (id)containerMetadataRequestWithContainerName:(NSString *)containerName {
82
    return [self storageRequestWithMethod:@"HEAD" containerName:containerName];
83
}
84

    
85
// HEAD storageURL/container?[until=untilTimestamp]
86
+ (id)containerMetadataRequestWithContainerName:(NSString *)containerName until:(NSDate *)untilTimestamp {
87
    NSString *queryString = nil;
88
    if (untilTimestamp)
89
        queryString = [NSString stringWithFormat:@"?until=%d", (int)[untilTimestamp timeIntervalSince1970]];
90
    
91
	return [self storageRequestWithMethod:@"HEAD" containerName:containerName queryString:queryString];
92
}
93

    
94
// HEAD storageURL/container?[until=untilTimestamp] [If-Modified-Since]
95
+ (id)containerMetadataRequestWithContainerName:(NSString *)containerName 
96
                                          until:(NSDate *)untilTimestamp 
97
                                ifModifiedSince:(NSDate *)sinceTimestamp {
98
    ASIPithosContainerRequest *request = [self containerMetadataRequestWithContainerName:containerName until:untilTimestamp];
99
    [request addRequestIfModifiedSinceHeader:sinceTimestamp];
100
    return request;
101
}
102

    
103
// HEAD storageURL/container?[until=untilTimestamp] [If-Unmodified-Since]
104
+ (id)containerMetadataRequestWithContainerName:(NSString *)containerName 
105
                                          until:(NSDate *)untilTimestamp 
106
                              ifUnmodifiedSince:(NSDate *)sinceTimestamp {
107
    ASIPithosContainerRequest *request = [self containerMetadataRequestWithContainerName:containerName until:untilTimestamp];
108
    [request addRequestIfUnmodifiedSinceHeader:sinceTimestamp];
109
    return request;
110
}
111

    
112
- (NSUInteger)objectCount {
113
	return [[[self responseHeaders] objectForKey:@"X-Container-Object-Count"] intValue];
114
}
115

    
116
- (NSUInteger)bytesUsed {
117
	return [[[self responseHeaders] objectForKey:@"X-Container-Bytes-Used"] intValue];
118
}
119

    
120
- (NSUInteger)blockSize {
121
	return [[[self responseHeaders] objectForKey:@"X-Container-Block-Size"] intValue];
122
}
123

    
124
- (NSString *)blockHash {
125
	return [[self responseHeaders] objectForKey:@"X-Container-Block-Hash"];
126
}
127

    
128
- (NSArray *)objectMeta {
129
    return [[self decodeFromPercentEscape:[[self responseHeaders] objectForKey:@"X-Container-Object-Meta"]] 
130
            componentsSeparatedByString:@","];
131
}
132

    
133
- (NSDate *)untilTimestamp {
134
    NSString *untilTimestampString = [[self responseHeaders] objectForKey:@"X-Container-Until-Timestamp"];
135
    if (untilTimestampString)
136
        return [[self dateFormatterWithFormatId:1] dateFromString:untilTimestampString];
137
    return nil;
138
}
139

    
140
- (NSDictionary *)policy {
141
    if (policy == nil) {
142
        policy = [self getHeadersDictionaryForPrefix:@"X-Container-Policy-"];
143
        [policy retain];
144
    }
145
    return policy;
146
}
147

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

    
156
- (NSDate *)lastModified {
157
    NSString *lastModifiedString = [[self responseHeaders] objectForKey:@"Last-Modified"];
158
    if (lastModifiedString)
159
        return [[self dateFormatterWithFormatId:1] dateFromString:lastModifiedString];
160
    return nil;
161
}
162

    
163
- (ASIPithosContainer *)container {
164
    ASIPithosContainer *container = [ASIPithosContainer container];
165
    container.name = containerName;
166
    container.count = [self objectCount];
167
    container.bytes = [self bytesUsed];
168
    container.lastModified = [self lastModified];
169
    container.untilTimestamp = [self untilTimestamp];
170
    container.policy = (NSMutableDictionary *)[self policy];
171
    container.metadata = (NSMutableDictionary *)[self metadata];
172
    container.blockSize =  [self blockSize];
173
    container.blockHash =  [self blockHash];
174
    container.objectMeta = (NSMutableArray *)[self objectMeta];
175
    return container;
176
}
177

    
178
#pragma mark -
179
#pragma mark GET
180

    
181
// GET storageURL/container
182
+ (id)listObjectsRequestWithContainerName:(NSString *)containerName {
183
    return [self storageRequestWithMethod:@"GET" containerName:containerName queryString:@"?format=xml"];
184
}
185

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

    
217
// GET storageURL?[limit=limit]&[marker=marker]&[prefix=prefix]&[delimiter=delimiter]&[path=path]&[meta=meta]&[shared=]&[until=untilTimestamp] [If-Modified-Since]
218
+ (id)listObjectsRequestWithContainerName:(NSString *)containerName
219
                                    limit:(NSUInteger)limit 
220
                                   marker:(NSString *)marker 
221
                                   prefix:(NSString *)prefix 
222
                                delimiter:(NSString *)delimiter 
223
                                     path:(NSString *)path 
224
                                     meta:(NSArray *)meta 
225
                                   shared:(BOOL)shared
226
                                    until:(NSDate *)untilTimestamp 
227
                          ifModifiedSince:(NSDate *)sinceTimestamp {
228
    ASIPithosContainerRequest *request = [self listObjectsRequestWithContainerName:containerName 
229
                                                                             limit:limit 
230
                                                                            marker:marker 
231
                                                                            prefix:prefix 
232
                                                                         delimiter:delimiter 
233
                                                                              path:path 
234
                                                                              meta:meta 
235
                                                                            shared:shared 
236
                                                                             until:untilTimestamp];
237
    [request addRequestIfModifiedSinceHeader:sinceTimestamp];
238
    return request;
239
}
240

    
241
// GET storageURL?[limit=limit]&[marker=marker]&[prefix=prefix]&[delimiter=delimiter]&[path=path]&[meta=meta]&[shared=]&[until=untilTimestamp] [If-Unmodified-Since]
242
+ (id)listObjectsRequestWithContainerName:(NSString *)containerName
243
                                    limit:(NSUInteger)limit 
244
                                   marker:(NSString *)marker 
245
                                   prefix:(NSString *)prefix 
246
                                delimiter:(NSString *)delimiter 
247
                                     path:(NSString *)path 
248
                                     meta:(NSArray *)meta 
249
                                   shared:(BOOL)shared
250
                                    until:(NSDate *)untilTimestamp 
251
                        ifUnmodifiedSince:(NSDate *)sinceTimestamp {
252
    ASIPithosContainerRequest *request = [self listObjectsRequestWithContainerName:containerName 
253
                                                                             limit:limit 
254
                                                                            marker:marker 
255
                                                                            prefix:prefix 
256
                                                                         delimiter:delimiter 
257
                                                                              path:path 
258
                                                                              meta:meta 
259
                                                                            shared:shared 
260
                                                                             until:untilTimestamp];
261
    [request addRequestIfUnmodifiedSinceHeader:sinceTimestamp];
262
    return request;
263
}
264

    
265

    
266
- (NSArray *)objects {
267
    if (objects == nil) {
268
        objects = [[NSMutableArray alloc] init];
269
        
270
        NSXMLParser *parser = [[[NSXMLParser alloc] initWithData:[self responseData]] autorelease];
271
        [parser setDelegate:self];
272
        [parser setShouldProcessNamespaces:NO];
273
        [parser setShouldReportNamespacePrefixes:NO];
274
        [parser setShouldResolveExternalEntities:NO];
275
        [parser parse];
276
    }    
277
	return objects;
278
}
279

    
280
#pragma mark -
281
#pragma mark PUT
282

    
283
// PUT storageURL/container
284
+ (id)createOrUpdateContainerRequestWithContainerName:(NSString *)containerName {
285
    return [self storageRequestWithMethod:@"PUT" containerName:containerName];
286
}
287

    
288
// PUT storageURL/container [X-Container-Policy-*] [X-Container-Meta-*]
289
+ (id)createOrUpdateContainerRequestWithContainerName:(NSString *)containerName policy:(NSDictionary *)policy metadata:(NSDictionary *)metadata {
290
    ASIPithosContainerRequest *request = [self storageRequestWithMethod:@"PUT" containerName:containerName];
291
	
292
    if (policy) {
293
        for (NSString *key in [policy keyEnumerator]) {
294
            [request addRequestHeader:[NSString stringWithFormat:@"X-Container-Policy-%@", key] value:[policy objectForKey:key]];
295
        }
296
    }
297
    
298
    if (metadata) {
299
        for (NSString *key in [metadata keyEnumerator]) {
300
            [request addRequestHeader:[self encodeToPercentEscape:[NSString stringWithFormat:@"X-Container-Meta-%@", key]] 
301
                                value:[self encodeToPercentEscape:[metadata objectForKey:key]]];
302
        }
303
    }
304
    
305
	return request;
306
}
307

    
308
#pragma mark -
309
#pragma mark POST
310

    
311
// POST storageURL/container
312
+ (id)updateContainerMetadataRequestWithContainerName:(NSString *)containerName {
313
    return [self storageRequestWithMethod:@"POST" containerName:containerName];
314
}
315

    
316
// POST storageURL/container?[update=] [X-Container-Policy-*] [X-Container-Meta-*]
317
+ (id)updateContainerMetadataRequestWithContainerName:(NSString *)containerName 
318
                                               policy:(NSDictionary *)policy 
319
                                             metadata:(NSDictionary *)metadata 
320
                                               update:(BOOL)update {
321
    NSString *queryString = nil;
322
    if (update)
323
        queryString = @"?update=";
324
    ASIPithosContainerRequest *request = [self storageRequestWithMethod:@"POST" 
325
                                                                               containerName:containerName
326
                                                                                 queryString:queryString];
327
    if (policy) {
328
        for (NSString *key in [policy keyEnumerator]) {
329
            [request addRequestHeader:[NSString stringWithFormat:@"X-Container-Policy-%@", key] value:[policy objectForKey:key]];
330
        }
331
    }
332
    
333
    if (metadata) {
334
        for (NSString *key in [metadata keyEnumerator]) {
335
            [request addRequestHeader:[self encodeToPercentEscape:[NSString stringWithFormat:@"X-Container-Meta-%@", key]] 
336
                                value:[self encodeToPercentEscape:[metadata objectForKey:key]]];
337
        }
338
    }
339
    
340
	return request;
341
}
342

    
343
// POST storageURL/container?[update=] [X-Container-Policy-*] [X-Container-Meta-*] (update data from ASIPithosObject with data)
344
+ (id)updateContainerDataRequestWithContainerName:(NSString *)containerName 
345
                                           policy:(NSDictionary *)policy 
346
                                         metadata:(NSDictionary *)metadata 
347
                                           update:(BOOL)update
348
                                           object:(ASIPithosObject *)object {
349
    return [self updateContainerDataRequestWithContainerName:containerName 
350
                                                      policy:policy 
351
                                                    metadata:metadata 
352
                                                      update:update 
353
                                                        data:object.data];
354
}
355

    
356
// POST storageURL/container?[update=] [X-Container-Policy-*] [X-Container-Meta-*] (update data from NSData)
357
+ (id)updateContainerDataRequestWithContainerName:(NSString *)containerName 
358
                                           policy:(NSDictionary *)policy 
359
                                         metadata:(NSDictionary *)metadata 
360
                                           update:(BOOL)update
361
                                             data:(NSData *)data {
362
    ASIPithosContainerRequest *request = [self updateContainerMetadataRequestWithContainerName:containerName 
363
                                                                                        policy:policy 
364
                                                                                      metadata:metadata 
365
                                                                                        update:update];    
366
    [request addRequestHeader:@"Content-Type" value:@"application/octet-stream"];
367
	[request appendPostData:data];
368
	return request;
369
}
370

    
371
// POST storageURL/container?[update=] [X-Container-Policy-*] [X-Container-Meta-*] (update data from file)
372
+ (id)updateContainerDataRequestWithContainerName:(NSString *)containerName 
373
                                           policy:(NSDictionary *)policy 
374
                                         metadata:(NSDictionary *)metadata 
375
                                           update:(BOOL)update
376
                                             file:(NSString *)filePath {
377
    ASIPithosContainerRequest *request = [self updateContainerMetadataRequestWithContainerName:containerName 
378
                                                                                        policy:policy 
379
                                                                                      metadata:metadata 
380
                                                                                        update:update];    
381
    [request addRequestHeader:@"Content-Type" value:@"application/octet-stream"];
382
	request.shouldStreamPostDataFromDisk = YES;
383
    request.postBodyFilePath = filePath;
384
	return request;
385
}
386

    
387
#pragma mark -
388
#pragma mark DELETE
389

    
390
// DELETE storageURL/container
391
+ (id)deleteContainerRequestWithContainerName:(NSString *)containerName {
392
    return [self storageRequestWithMethod:@"DELETE" containerName:containerName];
393
}
394

    
395
// DELETE storageURL/container?[until=untilTimestamp]
396
+ (id)deleteContainerRequestWithContainerName:(NSString *)containerName until:(NSDate *)untilTimestamp {
397
    NSString *queryString = nil;
398
    if (untilTimestamp)
399
        queryString = [NSString stringWithFormat:@"?until=%d", (int)[untilTimestamp timeIntervalSince1970]];
400
	return [self storageRequestWithMethod:@"DELETE" containerName:containerName queryString:queryString];    
401
}
402

    
403
#pragma mark -
404
#pragma mark NSXMLParserDelegate
405

    
406
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
407
	self.currentElement = elementName;
408
	if ([elementName isEqualToString:@"object"]) {
409
		self.currentObject = [ASIPithosObject object];
410
	} else if ([elementName isEqualToString:@"subdir"]) {
411
		[objects addObject:[ASIPithosObject subdirWithName:[attributeDict valueForKey:@"name"]]];
412
	} else if ([elementName isEqualToString:@"x_object_meta"]) {
413
        if (currentObject.metadata == nil)
414
            currentObject.metadata = [NSMutableDictionary dictionary];
415
	}
416

    
417
	self.currentContent = @"";
418
}
419

    
420
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
421
	if ([elementName isEqualToString:@"name"]) {
422
        currentObject.name = currentContent;
423
	} else if ([elementName isEqualToString:@"hash"]) {
424
        currentObject.hash = currentContent;
425
	} else if ([elementName isEqualToString:@"x_object_hash"]) {
426
        currentObject.objectHash = currentContent;
427
	} else if ([elementName isEqualToString:@"bytes"]) {
428
        currentObject.bytes = [currentContent intValue];
429
	} else if ([elementName isEqualToString:@"content_type"]) {
430
        currentObject.contentType = currentContent;
431
	} else if ([elementName isEqualToString:@"content_encoding"]) {
432
        currentObject.contentEncoding = currentContent;
433
	} else if ([elementName isEqualToString:@"content_disposition"]) {
434
        currentObject.contentDisposition = currentContent;
435
    } else if ([elementName isEqualToString:@"last_modified"]) {
436
        currentObject.lastModified = [[self dateFormatterWithFormatId:0] dateFromString:
437
         [currentContent stringByReplacingOccurrencesOfString:@":" 
438
                                                   withString:@"" 
439
                                                      options:NSBackwardsSearch 
440
                                                        range:NSMakeRange(([currentContent length] - 3), 1)]];
441
	} else if ([elementName isEqualToString:@"x_object_version"]) {
442
        currentObject.version = currentContent;
443
    } else if ([elementName isEqualToString:@"x_object_version_timestamp"]) {
444
        currentObject.versionTimestamp = [NSDate dateWithTimeIntervalSince1970:[currentContent doubleValue]];
445
	} else if ([elementName isEqualToString:@"x_object_modified_by"]) {
446
        currentObject.modifiedBy = currentContent;
447
	} else if ([elementName isEqualToString:@"x_object_manifest"]) {
448
        currentObject.manifest = currentContent;
449
	} else if ([elementName isEqualToString:@"x_object_sharing"]) {
450
        currentObject.sharing = currentContent;
451
	} else if ([elementName isEqualToString:@"x_object_shared_by"]) {
452
        currentObject.sharedBy = currentContent;
453
	} else if ([elementName isEqualToString:@"x_object_public"]) {
454
        currentObject.publicURI = currentContent;
455
    } else if ([elementName isEqualToString:@"key"]) {
456
        self.currentKey = currentContent;
457
    } else if ([elementName isEqualToString:@"value"]) {
458
        [currentObject.metadata setObject:currentContent forKey:currentKey];
459
        self.currentKey = nil;
460
	} else if ([elementName isEqualToString:@"x_object_allowed_to"]) {
461
        currentObject.allowedTo = currentContent;
462
	} else if ([elementName isEqualToString:@"object"]) {
463
		[objects addObject:currentObject];
464
        self.currentObject = nil;
465
	}
466
}
467

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