Statistics
| Branch: | Revision:

root / asi-http-request-with-pithos / Classes / Pithos / ASIPithosContainerRequest.m @ 8fb25a1b

History | View | Annotate | Download (22.5 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
	return request;
63
}
64

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

    
69
#pragma mark -
70
#pragma mark Memory Management
71

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

    
82
#pragma mark -
83
#pragma mark HEAD
84

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
183
#pragma mark -
184
#pragma mark GET
185

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

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

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

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

    
272

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

    
287
#pragma mark -
288
#pragma mark PUT
289

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

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

    
317
#pragma mark -
318
#pragma mark POST
319

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

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

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

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

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

    
400
#pragma mark -
401
#pragma mark DELETE
402

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

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

    
416
#pragma mark -
417
#pragma mark NSXMLParserDelegate
418

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

    
427
	self.currentContent = @"";
428
}
429

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

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