You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by ga...@apache.org on 2014/03/12 22:38:08 UTC
svn commit: r1576931 - in /chemistry/objectivecmis/trunk:
ObjectiveCMIS/Bindings/ ObjectiveCMIS/Bindings/AtomPub/
ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/ ObjectiveCMIS/Client/
ObjectiveCMISTests/
Author: gavincornwell
Date: Wed Mar 12 21:38:07 2014
New Revision: 1576931
URL: http://svn.apache.org/r1576931
Log:
Added support for checkin, checkout and cancel checkout on the versioning service.
Modified:
chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomEntryParser.m
chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomParserUtil.m
chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomPubConstants.h
chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomPubConstants.m
chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubBaseService+Protected.h
chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubBaseService.m
chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubObjectService.m
chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubVersioningService.m
chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISBindingSession.h
chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISBindingSession.m
chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISVersioningService.h
chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISDocument.h
chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISDocument.m
chemistry/objectivecmis/trunk/ObjectiveCMISTests/CMISBaseTest.m
chemistry/objectivecmis/trunk/ObjectiveCMISTests/ObjectiveCMISTests.m
Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomEntryParser.m
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomEntryParser.m?rev=1576931&r1=1576930&r2=1576931&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomEntryParser.m (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomEntryParser.m Wed Mar 12 21:38:07 2014
@@ -35,6 +35,7 @@
@property (nonatomic, strong) CMISRenditionData *currentRendition;
@property (nonatomic, strong) NSMutableArray *currentRenditions;
@property (nonatomic, strong) NSMutableString *string;
+@property (nonatomic, assign) BOOL parsingRelationship;
@property (nonatomic, weak) id<NSXMLParserDelegate, CMISAtomEntryParserDelegate> parentDelegate;
@property (nonatomic, strong) NSDictionary *entryAttributesDict;
@@ -56,6 +57,7 @@
self = [super init];
if (self) {
self.currentLinkRelations = [NSMutableSet set];
+ self.parsingRelationship = NO;
}
return self;
}
@@ -100,6 +102,7 @@
self.objectData = [[CMISObjectData alloc] init];
self.entryAttributesDict = attributes;
self.parentDelegate = parentDelegate;
+ self.parsingRelationship = NO;
// Setting ourself, the entry parser, as the delegate, we reset back to our parent when we're done
[parser setDelegate:self];
@@ -120,7 +123,7 @@
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
- if ([namespaceURI isEqualToString:kCMISNamespaceCmis]) {
+ if ([namespaceURI isEqualToString:kCMISNamespaceCmis] && !self.parsingRelationship) {
if ([elementName isEqualToString:kCMISAtomEntryPropertyId] ||
[elementName isEqualToString:kCMISAtomEntryPropertyString] ||
[elementName isEqualToString:kCMISAtomEntryPropertyInteger] ||
@@ -147,6 +150,9 @@
} else if ([elementName isEqualToString:kCMISAtomEntryAllowableActions]) {
// Delegate parsing to child parser for allowableActions element
self.childParserDelegate = [CMISAllowableActionsParser allowableActionsParserWithParentDelegate:self parser:parser];
+ } else if ([elementName isEqualToString:kCMISCoreRelationship]) {
+ // NOTE: we're currently ignoring the relationship element so set a flag to check
+ self.parsingRelationship = YES;
}
} else if ([namespaceURI isEqualToString:kCMISNamespaceCmisRestAtom]) {
if ([elementName isEqualToString:kCMISAtomEntryObject]) {
@@ -208,29 +214,39 @@
}
if ([namespaceURI isEqualToString:kCMISNamespaceCmis]) {
- if ([elementName isEqualToString:kCMISAtomEntryPropertyId] ||
- [elementName isEqualToString:kCMISAtomEntryPropertyString] ||
- [elementName isEqualToString:kCMISAtomEntryPropertyInteger] ||
- [elementName isEqualToString:kCMISAtomEntryPropertyDateTime] ||
- [elementName isEqualToString:kCMISAtomEntryPropertyBoolean] ||
- [elementName isEqualToString:kCMISAtomEntryPropertyUri] ||
- [elementName isEqualToString:kCMISAtomEntryPropertyHtml] ||
- [elementName isEqualToString:kCMISAtomEntryPropertyDecimal]) {
- // add the property to the properties dictionary
- self.currentPropertyData.values = self.propertyValues;
- self.propertyValues = nil;
- [self.currentObjectProperties addProperty:self.currentPropertyData];
- self.currentPropertyData = nil;
- } else if ([elementName isEqualToString:kCMISCoreProperties]) {
- // Finished parsing Properties & its ExtensionData
- [self saveCurrentExtensionsAndPushPreviousExtensionData];
- } else if ([elementName isEqualToString:kCMISCoreRendition]) {
- if (self.currentRenditions == nil) {
- self.currentRenditions = [[NSMutableArray alloc] init];
+ if (!self.parsingRelationship)
+ {
+ // ignore the properties within the relationship element
+ if ([elementName isEqualToString:kCMISAtomEntryPropertyId] ||
+ [elementName isEqualToString:kCMISAtomEntryPropertyString] ||
+ [elementName isEqualToString:kCMISAtomEntryPropertyInteger] ||
+ [elementName isEqualToString:kCMISAtomEntryPropertyDateTime] ||
+ [elementName isEqualToString:kCMISAtomEntryPropertyBoolean] ||
+ [elementName isEqualToString:kCMISAtomEntryPropertyUri] ||
+ [elementName isEqualToString:kCMISAtomEntryPropertyHtml] ||
+ [elementName isEqualToString:kCMISAtomEntryPropertyDecimal]) {
+ // add the property to the properties dictionary
+ self.currentPropertyData.values = self.propertyValues;
+ self.propertyValues = nil;
+ [self.currentObjectProperties addProperty:self.currentPropertyData];
+ self.currentPropertyData = nil;
+ } else if ([elementName isEqualToString:kCMISCoreProperties]) {
+ // Finished parsing Properties & its ExtensionData
+ [self saveCurrentExtensionsAndPushPreviousExtensionData];
+ } else if ([elementName isEqualToString:kCMISCoreRendition]) {
+ if (self.currentRenditions == nil) {
+ self.currentRenditions = [[NSMutableArray alloc] init];
+ }
+ [self.currentRenditions addObject:self.currentRendition];
+ self.currentRendition = nil;
}
- [self.currentRenditions addObject:self.currentRendition];
- self.currentRendition = nil;
}
+
+ // the relationship element has ended
+ if ([elementName isEqualToString:kCMISCoreRelationship]) {
+ self.parsingRelationship = NO;
+ }
+
} else if ([namespaceURI isEqualToString:kCMISNamespaceAtom]) {
if ( [elementName isEqualToString:kCMISAtomEntry]) {
// set the properties on the objectData object
Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomParserUtil.m
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomParserUtil.m?rev=1576931&r1=1576930&r2=1576931&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomParserUtil.m (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomParserUtil.m Wed Mar 12 21:38:07 2014
@@ -46,7 +46,7 @@
} else if ([atomPubType isEqualToString:kCMISAtomEntryPropertyUri]) {
return CMISPropertyTypeUri;
} else {
- CMISLogDebug(@"Unknow property type %@. Go tell a developer to fix this.", atomPubType);
+ CMISLogDebug(@"Unknown property type %@. Go tell a developer to fix this.", atomPubType);
return CMISPropertyTypeString;
}
}
@@ -68,7 +68,7 @@
} else if ([propertyType isEqualToString:kCMISAtomEntryPropertyUri]) {
[array addObject:[NSURL URLWithString:stringValue]];
} else {
- CMISLogDebug(@"Unknow property type %@. Go tell a developer to fix this.", propertyType);
+ CMISLogDebug(@"Unknown property type %@. Go tell a developer to fix this.", propertyType);
}
}
Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomPubConstants.h
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomPubConstants.h?rev=1576931&r1=1576930&r2=1576931&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomPubConstants.h (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomPubConstants.h Wed Mar 12 21:38:07 2014
@@ -50,6 +50,7 @@ extern NSString * const kCMISAtomEntryAl
// Collections
extern NSString * const kCMISAtomCollectionQuery;
+extern NSString * const kCMISAtomCollectionCheckedout;
// Links
extern NSString * const kCMISLinkRelationDown;
@@ -59,6 +60,7 @@ extern NSString * const kCMISLinkRelatio
extern NSString * const kCMISLinkVersionHistory;
extern NSString * const kCMISLinkEditMedia;
extern NSString * const kCMISLinkRelationNext;
+extern NSString * const kCMISLinkRelationWorkingCopy;
// URL parameters
extern NSString * const kCMISParameterChangeToken;
@@ -77,7 +79,13 @@ extern NSString * const kCMISParameterAl
extern NSString * const kCMISParameterContinueOnFailure;
extern NSString * const kCMISParameterUnfileObjects;
extern NSString * const kCMISParameterRelativePathSegment;
-
+extern NSString * const kCMISParameterMajor;
+extern NSString * const kCMISParameterCheckin;
+extern NSString * const kCMISParameterCheckinComment;
+
+// Parameter Values
+extern NSString * const kCMISParameterValueTrue;
+extern NSString * const kCMISParameterValueFalse;
// Namespaces
extern NSString * const kCMISNamespaceCmis;
@@ -178,6 +186,7 @@ extern NSString * const kCMISCoreHeight;
extern NSString * const kCMISCoreWidth;
extern NSString * const kCMISCoreTitle;
extern NSString * const kCMISCoreRenditionDocumentId;
+extern NSString * const kCMISCoreRelationship;
// URI Templates
extern NSString * const kCMISUriTemplateObjectById;
Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomPubConstants.m
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomPubConstants.m?rev=1576931&r1=1576930&r2=1576931&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomPubConstants.m (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomPubConstants.m Wed Mar 12 21:38:07 2014
@@ -50,6 +50,7 @@ NSString * const kCMISAtomEntryAllowable
// Collections
NSString * const kCMISAtomCollectionQuery = @"query";
+NSString * const kCMISAtomCollectionCheckedout = @"checkedout";
// Links
NSString * const kCMISLinkRelationDown = @"down";
@@ -59,6 +60,7 @@ NSString * const kCMISLinkRelationFolder
NSString * const kCMISLinkVersionHistory = @"version-history";
NSString * const kCMISLinkEditMedia = @"edit-media";
NSString * const kCMISLinkRelationNext = @"next";
+NSString * const kCMISLinkRelationWorkingCopy = @"working-copy";
// Parameters
NSString * const kCMISParameterChangeToken = @"changeToken";
@@ -77,6 +79,13 @@ NSString * const kCMISParameterAllVersio
NSString * const kCMISParameterContinueOnFailure= @"continueOnFailure";
NSString * const kCMISParameterUnfileObjects = @"unfileObjects";
NSString * const kCMISParameterRelativePathSegment = @"includeRelativePathSegment";
+NSString * const kCMISParameterMajor = @"major";
+NSString * const kCMISParameterCheckin = @"checkin";
+NSString * const kCMISParameterCheckinComment = @"checkinComment";
+
+// Parameter Values
+NSString * const kCMISParameterValueTrue = @"true";
+NSString * const kCMISParameterValueFalse = @"false";
// Namespaces
NSString * const kCMISNamespaceCmis = @"http://docs.oasis-open.org/ns/cmis/core/200908/";
@@ -177,6 +186,7 @@ NSString * const kCMISCoreHeight = @"hei
NSString * const kCMISCoreWidth = @"width";
NSString * const kCMISCoreTitle = @"title";
NSString * const kCMISCoreRenditionDocumentId = @"renditionDocumentId";
+NSString * const kCMISCoreRelationship = @"relationship";
// URI Templates
NSString * const kCMISUriTemplateObjectById = @"objectbyid";
Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubBaseService+Protected.h
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubBaseService%2BProtected.h?rev=1576931&r1=1576930&r2=1576931&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubBaseService+Protected.h (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubBaseService+Protected.h Wed Mar 12 21:38:07 2014
@@ -93,4 +93,26 @@
cmisRequest:(CMISRequest *)cmisRequest
completionBlock:(void (^)(NSString *link, NSError *error))completionBlock;
+/**
+ Generates and sends an atom entry to the given link url
+ */
+- (void)sendAtomEntryXmlToLink:(NSString *)link
+ httpRequestMethod:(CMISHttpRequestMethod)httpRequestMethod
+ properties:(CMISProperties *)properties
+ cmisRequest:(CMISRequest *)request
+ completionBlock:(void (^)(CMISObjectData *objectData, NSError *error))completionBlock;
+
+/**
+ Generates and sends an atom entry (including content) to the given link url
+ */
+- (void)sendAtomEntryXmlToLink:(NSString *)link
+ httpRequestMethod:(CMISHttpRequestMethod)httpRequestMethod
+ properties:(CMISProperties *)properties
+ contentInputStream:(NSInputStream *)contentInputStream
+ contentMimeType:(NSString *)contentMimeType
+ bytesExpected:(unsigned long long)bytesExpected
+ cmisRequest:(CMISRequest*)request
+ completionBlock:(void (^)(CMISObjectData *objectData, NSError *error))completionBlock
+ progressBlock:(void (^)(unsigned long long bytesUploaded, unsigned long long bytesTotal))progressBlock;
+
@end
Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubBaseService.m
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubBaseService.m?rev=1576931&r1=1576930&r2=1576931&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubBaseService.m (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubBaseService.m Wed Mar 12 21:38:07 2014
@@ -29,6 +29,7 @@
#import "CMISTypeByIdUriBuilder.h"
#import "CMISLinkCache.h"
#import "CMISLog.h"
+#import "CMISAtomEntryWriter.h"
@interface CMISAtomPubBaseService ()
@@ -90,6 +91,7 @@
// Cache collections
[self.bindingSession setObject:[workspace collectionHrefForCollectionType:kCMISAtomCollectionQuery] forKey:kCMISBindingSessionKeyQueryCollection];
+ [self.bindingSession setObject:[workspace collectionHrefForCollectionType:kCMISAtomCollectionCheckedout] forKey:kCMISBindingSessionKeyCheckedoutCollection];
// Cache uri's and uri templates
@@ -330,4 +332,121 @@
}
}
+- (void)sendAtomEntryXmlToLink:(NSString *)link
+ httpRequestMethod:(CMISHttpRequestMethod)httpRequestMethod
+ properties:(CMISProperties *)properties
+ cmisRequest:(CMISRequest *)request
+ completionBlock:(void (^)(CMISObjectData *objectData, NSError *error))completionBlock
+{
+ // Validate params
+ if (link == nil) {
+ CMISLogError(@"Must provide link to send atom entry");
+ if (completionBlock) {
+ completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument detailedDescription:nil]);
+ }
+ return;
+ }
+
+ // Generate atom entry XML in memory
+ CMISAtomEntryWriter *atomEntryWriter = [[CMISAtomEntryWriter alloc] init];
+ atomEntryWriter.cmisProperties = properties;
+ atomEntryWriter.generateXmlInMemory = YES;
+ NSString *writeResult = [atomEntryWriter generateAtomEntryXml];
+
+ // Execute call
+ [self.bindingSession.networkProvider invoke:[NSURL URLWithString:link]
+ httpMethod:httpRequestMethod
+ session:self.bindingSession
+ body:[writeResult dataUsingEncoding:NSUTF8StringEncoding]
+ headers:[NSDictionary dictionaryWithObject:kCMISMediaTypeEntry forKey:@"Content-type"]
+ cmisRequest:request
+ completionBlock:^(CMISHttpResponse *response, NSError *error) {
+ if (error) {
+ CMISLogError(@"HTTP error when sending atom entry: %@", error);
+ if (completionBlock) {
+ completionBlock(nil, error);
+ }
+ } else if (response.statusCode == 200 || response.statusCode == 201 || response.statusCode == 204) {
+ if (completionBlock) {
+ CMISAtomEntryParser *atomEntryParser = [[CMISAtomEntryParser alloc] initWithData:response.data];
+ NSError *parseError = nil;
+ [atomEntryParser parseAndReturnError:&parseError];
+ if (parseError == nil) {
+ completionBlock(atomEntryParser.objectData, nil);
+ } else {
+ CMISLogError(@"Error while parsing response: %@", [parseError description]);
+ completionBlock(nil, [CMISErrors cmisError:parseError cmisErrorCode:kCMISErrorCodeRuntime]);
+ }
+ }
+ } else {
+ CMISLogError(@"Invalid http response status code when sending atom entry: %d", response.statusCode);
+ CMISLogError(@"Error content: %@", [[NSString alloc] initWithData:response.data encoding:NSUTF8StringEncoding]);
+ if (completionBlock) {
+ completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeRuntime
+ detailedDescription:[NSString stringWithFormat:@"Failed to send atom entry: http status code %li", (long)response.statusCode]]);
+ }
+ }
+ }];
+}
+
+- (void)sendAtomEntryXmlToLink:(NSString *)link
+ httpRequestMethod:(CMISHttpRequestMethod)httpRequestMethod
+ properties:(CMISProperties *)properties
+ contentInputStream:(NSInputStream *)contentInputStream
+ contentMimeType:(NSString *)contentMimeType
+ bytesExpected:(unsigned long long)bytesExpected
+ cmisRequest:(CMISRequest*)request
+ completionBlock:(void (^)(CMISObjectData *objectData, NSError *error))completionBlock
+ progressBlock:(void (^)(unsigned long long bytesUploaded, unsigned long long bytesTotal))progressBlock
+{
+ // Validate param
+ if (link == nil) {
+ CMISLogError(@"Must provide link to send atom entry");
+ if (completionBlock) {
+ completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument detailedDescription:nil]);
+ }
+ return;
+ }
+
+ // The underlying CMISHttpUploadRequest object generates the atom entry. The base64 encoded content is generated on
+ // the fly to support very large files.
+ [self.bindingSession.networkProvider invoke:[NSURL URLWithString:link]
+ httpMethod:httpRequestMethod
+ session:self.bindingSession
+ inputStream:contentInputStream
+ headers:[NSDictionary dictionaryWithObject:kCMISMediaTypeEntry forKey:@"Content-type"]
+ bytesExpected:bytesExpected
+ cmisRequest:request
+ cmisProperties:properties
+ mimeType:contentMimeType
+ completionBlock:^(CMISHttpResponse *response, NSError *error) {
+ if (error) {
+ CMISLogError(@"HTTP error when sending atom entry: %@", error);
+ if (completionBlock) {
+ completionBlock(nil, error);
+ }
+ } else if (response.statusCode == 200 || response.statusCode == 201 || response.statusCode == 204) {
+ if (completionBlock) {
+ NSError *parseError = nil;
+ CMISAtomEntryParser *atomEntryParser = [[CMISAtomEntryParser alloc] initWithData:response.data];
+ [atomEntryParser parseAndReturnError:&parseError];
+ if (parseError == nil) {
+ completionBlock(atomEntryParser.objectData, nil);
+ } else {
+ CMISLogError(@"Error while parsing response: %@", [parseError description]);
+ completionBlock(nil, [CMISErrors cmisError:parseError cmisErrorCode:kCMISErrorCodeRuntime]);
+ }
+ }
+ } else {
+ CMISLogError(@"Invalid http response status code when sending atom entry: %d", response.statusCode);
+ CMISLogError(@"Error content: %@", [[NSString alloc] initWithData:response.data encoding:NSUTF8StringEncoding]);
+ if (completionBlock) {
+ completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeRuntime
+ detailedDescription:[NSString stringWithFormat:@"Failed to send atom entry: http status code %li", (long)response.statusCode]]);
+ }
+ }
+ }
+ progressBlock:progressBlock];
+}
+
@end
Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubObjectService.m
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubObjectService.m?rev=1576931&r1=1576930&r2=1576931&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubObjectService.m (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubObjectService.m Wed Mar 12 21:38:07 2014
@@ -401,7 +401,9 @@
contentMimeType:mimeType
bytesExpected:bytesExpected
cmisRequest:request
- completionBlock:completionBlock
+ completionBlock:^(CMISObjectData *objectData, NSError *error) {
+ completionBlock(objectData.identifier, error);
+ }
progressBlock:progressBlock];
}
}];
@@ -621,247 +623,4 @@
return cmisRequest;
}
-#pragma mark Helper methods
-
-- (void)sendAtomEntryXmlToLink:(NSString *)link
- httpRequestMethod:(CMISHttpRequestMethod)httpRequestMethod
- properties:(CMISProperties *)properties
- cmisRequest:(CMISRequest *)request
- completionBlock:(void (^)(CMISObjectData *objectData, NSError *error))completionBlock
-{
- // Validate params
- if (link == nil) {
- CMISLogError(@"Could not retrieve link from object to do creation or update");
- if (completionBlock) {
- completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument detailedDescription:nil]);
- }
- return;
- }
-
- // Generate XML
- NSString *writeResult = [self createAtomEntryWriter:properties
- contentFilePath:nil
- contentMimeType:nil
- isXmlStoredInMemory:YES];
-
- // Execute call
- [self.bindingSession.networkProvider invoke:[NSURL URLWithString:link]
- httpMethod:httpRequestMethod
- session:self.bindingSession
- body:[writeResult dataUsingEncoding:NSUTF8StringEncoding]
- headers:[NSDictionary dictionaryWithObject:kCMISMediaTypeEntry forKey:@"Content-type"]
- cmisRequest:request
- completionBlock:^(CMISHttpResponse *response, NSError *error) {
- if (error) {
- CMISLogError(@"HTTP error when creating/uploading content: %@", error);
- if (completionBlock) {
- completionBlock(nil, error);
- }
- } else if (response.statusCode == 200 || response.statusCode == 201 || response.statusCode == 204) {
- if (completionBlock) {
- CMISAtomEntryParser *atomEntryParser = [[CMISAtomEntryParser alloc] initWithData:response.data];
- NSError *parseError = nil;
- [atomEntryParser parseAndReturnError:&parseError];
- if (parseError == nil) {
- completionBlock(atomEntryParser.objectData, nil);
- } else {
- CMISLogError(@"Error while parsing response: %@", [parseError description]);
- completionBlock(nil, [CMISErrors cmisError:parseError cmisErrorCode:kCMISErrorCodeUpdateConflict]);
- }
- }
- } else {
- CMISLogError(@"Invalid http response status code when creating/uploading content: %d", response.statusCode);
- CMISLogError(@"Error content: %@", [[NSString alloc] initWithData:response.data encoding:NSUTF8StringEncoding]);
- if (completionBlock) {
- completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeConnection]);
- }
- }
- }];
-}
-
-/**
- This method uses a new invoke call on the CMISNetworkProvider. This new method was introduced to allow for base64 encoding while
- streaming. See CMISHttpUploadRequest for more details on how it is done.
- */
-- (void)sendAtomEntryXmlToLink:(NSString *)link
- httpRequestMethod:(CMISHttpRequestMethod)httpRequestMethod
- properties:(CMISProperties *)properties
- contentInputStream:(NSInputStream *)contentInputStream
- contentMimeType:(NSString *)contentMimeType
- bytesExpected:(unsigned long long)bytesExpected
- cmisRequest:(CMISRequest*)request
- completionBlock:(void (^)(NSString *objectId, NSError *error))completionBlock
- progressBlock:(void (^)(unsigned long long bytesUploaded, unsigned long long bytesTotal))progressBlock
-{
- // Validate param
- if (link == nil) {
- CMISLogError(@"Could not retrieve link from object to do creation or update");
- if (completionBlock) {
- completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument detailedDescription:nil]);
- }
- return;
- }
-
-
- [self.bindingSession.networkProvider invoke:[NSURL URLWithString:link]
- httpMethod:HTTP_POST
- session:self.bindingSession
- inputStream:contentInputStream
- headers:[NSDictionary dictionaryWithObject:kCMISMediaTypeEntry forKey:@"Content-type"]
- bytesExpected:bytesExpected
- cmisRequest:request
- cmisProperties:properties
- mimeType:contentMimeType
- completionBlock:^(CMISHttpResponse *response, NSError *error) {
- if (error) {
- CMISLogError(@"HTTP error when creating/uploading content: %@", error);
- if (completionBlock) {
- completionBlock(nil, error);
- }
- } else if (response.statusCode == 200 || response.statusCode == 201 || response.statusCode == 204) {
- if (completionBlock) {
- NSError *parseError = nil;
- CMISAtomEntryParser *atomEntryParser = [[CMISAtomEntryParser alloc] initWithData:response.data];
- [atomEntryParser parseAndReturnError:&parseError];
- if (parseError == nil) {
- completionBlock(atomEntryParser.objectData.identifier, nil);
- } else {
- CMISLogError(@"Error while parsing response: %@", [parseError description]);
- completionBlock(nil, [CMISErrors cmisError:parseError cmisErrorCode:kCMISErrorCodeUpdateConflict]);
- }
- }
- } else {
- CMISLogError(@"Invalid http response status code when creating/uploading content: %d", response.statusCode);
- CMISLogError(@"Error content: %@", [[NSString alloc] initWithData:response.data encoding:NSUTF8StringEncoding]);
- if (completionBlock) {
- completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeRuntime
- detailedDescription:[NSString stringWithFormat:@"Could not create content: http status code %li", (long)response.statusCode]]);
- }
- }
- }
- progressBlock:progressBlock];
-}
-
-/**
- This is the original version of the 'sendAtomEntryXmlToLink' method.
- It creates a temporary file to store the base64 encoded data in. It is from this file that the upload starts
- */
-- (void)sendAtomEntryXmlToLinkUsingTmpFile:(NSString *)link
- httpRequestMethod:(CMISHttpRequestMethod)httpRequestMethod
- properties:(CMISProperties *)properties
- contentInputStream:(NSInputStream *)contentInputStream
- contentMimeType:(NSString *)contentMimeType
- bytesExpected:(unsigned long long)bytesExpected
- cmisRequest:(CMISRequest*)request
- completionBlock:(void (^)(NSString *objectId, NSError *error))completionBlock
- progressBlock:(void (^)(unsigned long long bytesUploaded, unsigned long long bytesTotal))progressBlock
-{
- // Validate param
- if (link == nil) {
- CMISLogError(@"Could not retrieve link from object to do creation or update");
- if (completionBlock) {
- completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument detailedDescription:nil]);
- }
- return;
- }
-
-
- // Generate XML
- NSString *writeResult = [self createAtomEntryWriter:properties
- contentInputStream:contentInputStream
- contentMimeType:contentMimeType
- isXmlStoredInMemory:NO];
-
-
- NSInputStream *inputStream = [NSInputStream inputStreamWithFileAtPath:writeResult];
- NSError *fileSizeError = nil;
- unsigned long long fileSize = [CMISFileUtil fileSizeForFileAtPath:writeResult error:&fileSizeError];
- if (fileSizeError) {
- CMISLogError(@"Could not determine file size of %@ : %@", writeResult, [fileSizeError description]);
- }
-
- [self.bindingSession.networkProvider invoke:[NSURL URLWithString:link]
- httpMethod:HTTP_POST
- session:self.bindingSession
- inputStream:inputStream
- headers:[NSDictionary dictionaryWithObject:kCMISMediaTypeEntry forKey:@"Content-type"]
- bytesExpected:fileSize
- cmisRequest:request
- completionBlock:^(CMISHttpResponse *response, NSError *error) {
- // close stream to and delete temporary file
- [inputStream close];
-
- NSError *fileError = nil;
- [[NSFileManager defaultManager] removeItemAtPath:writeResult error:&fileError];
- if (fileError) {
- // the upload itself is not impacted by this error, so do not report it in the completion block
- CMISLogError(@"Could not delete temporary file %@: %@", writeResult, [fileError description]);
- }
- if (error) {
- CMISLogError(@"HTTP error when creating/uploading content: %@", error);
- if (completionBlock) {
- completionBlock(nil, error);
- }
- } else if (response.statusCode == 200 || response.statusCode == 201 || response.statusCode == 204) {
- if (completionBlock) {
- NSError *parseError = nil;
- CMISAtomEntryParser *atomEntryParser = [[CMISAtomEntryParser alloc] initWithData:response.data];
- [atomEntryParser parseAndReturnError:&parseError];
- if (parseError == nil) {
- completionBlock(atomEntryParser.objectData.identifier, nil);
- } else {
- CMISLogError(@"Error while parsing response: %@", [parseError description]);
- completionBlock(nil, [CMISErrors cmisError:parseError cmisErrorCode:kCMISErrorCodeUpdateConflict]);
- }
- }
- } else {
- CMISLogError(@"Invalid http response status code when creating/uploading content: %d", response.statusCode);
- CMISLogError(@"Error content: %@", [[NSString alloc] initWithData:response.data encoding:NSUTF8StringEncoding]);
- if (completionBlock) {
- completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeRuntime
- detailedDescription:[NSString stringWithFormat:@"Could not create content: http status code %li", (long)response.statusCode]]);
- }
- }
- }
- progressBlock:progressBlock];
-}
-
-
-
-
-/**
- * Helper method: creates a writer for the xml needed to upload a file.
- * The atom entry XML can become huge, as the whole file is stored as base64 in the XML itself
- * Hence, we're allowing to store the atom entry xml in a temporary file and stream the body of the http post
- */
-- (NSString *)createAtomEntryWriter:(CMISProperties *)properties
- contentFilePath:(NSString *)contentFilePath
- contentMimeType:(NSString *)contentMimeType
- isXmlStoredInMemory:(BOOL)isXmlStoredInMemory
-{
-
- CMISAtomEntryWriter *atomEntryWriter = [[CMISAtomEntryWriter alloc] init];
- atomEntryWriter.contentFilePath = contentFilePath;
- atomEntryWriter.mimeType = contentMimeType;
- atomEntryWriter.cmisProperties = properties;
- atomEntryWriter.generateXmlInMemory = isXmlStoredInMemory;
- NSString *writeResult = [atomEntryWriter generateAtomEntryXml];
- return writeResult;
-}
-
-- (NSString *)createAtomEntryWriter:(CMISProperties *)properties
- contentInputStream:(NSInputStream *)contentInputStream
- contentMimeType:(NSString *)contentMimeType
- isXmlStoredInMemory:(BOOL)isXmlStoredInMemory
-{
-
- CMISAtomEntryWriter *atomEntryWriter = [[CMISAtomEntryWriter alloc] init];
- atomEntryWriter.inputStream= contentInputStream;
- atomEntryWriter.mimeType = contentMimeType;
- atomEntryWriter.cmisProperties = properties;
- atomEntryWriter.generateXmlInMemory = isXmlStoredInMemory;
- NSString *writeResult = [atomEntryWriter generateAtomEntryXml];
- return writeResult;
-}
-
@end
Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubVersioningService.m
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubVersioningService.m?rev=1576931&r1=1576930&r2=1576931&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubVersioningService.m (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubVersioningService.m Wed Mar 12 21:38:07 2014
@@ -20,11 +20,14 @@
#import "CMISAtomPubVersioningService.h"
#import "CMISAtomPubBaseService+Protected.h"
#import "CMISAtomPubConstants.h"
+#import "CMISAtomPubObjectService.h"
#import "CMISHttpResponse.h"
+#import "CMISAtomEntryWriter.h"
#import "CMISAtomFeedParser.h"
#import "CMISErrors.h"
#import "CMISURLUtil.h"
#import "CMISLog.h"
+#import "CMISFileUtil.h"
@implementation CMISAtomPubVersioningService
@@ -105,4 +108,183 @@
return request;
}
+- (CMISRequest*)checkOut:(NSString *)objectId
+ completionBlock:(void (^)(CMISObjectData *objectData, NSError *error))completionBlock
+{
+ // Validate params
+ if (!objectId) {
+ CMISLogError(@"Must provide an objectId when checking out");
+ completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeObjectNotFound detailedDescription:nil]);
+ return nil;
+ }
+
+ NSString *checkedoutUrlString = [self.bindingSession objectForKey:kCMISBindingSessionKeyCheckedoutCollection];
+ if (checkedoutUrlString == nil) {
+ CMISLogDebug(@"Checkedout not supported!");
+ completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeNotSupported detailedDescription:nil]);
+ return nil;
+ }
+
+ CMISProperties *properties = [CMISProperties new];
+ [properties addProperty:[CMISPropertyData createPropertyForId:kCMISPropertyObjectId idValue:objectId]];
+
+ CMISRequest *request = [CMISRequest new];
+
+ // send an atom entry to check out the file
+ [self sendAtomEntryXmlToLink:checkedoutUrlString
+ httpRequestMethod:HTTP_POST
+ properties:properties
+ cmisRequest:request
+ completionBlock:^(CMISObjectData *objectData, NSError *error) {
+ if (error) {
+ completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeVersioning]);
+ } else {
+ completionBlock(objectData, nil);
+ }
+ }];
+
+ return request;
+}
+
+- (CMISRequest*)cancelCheckOut:(NSString *)objectId
+ completionBlock:(void (^)(BOOL checkoutCancelled, NSError *error))completionBlock
+{
+ // Validate params
+ if (!objectId) {
+ CMISLogError(@"Must provide an objectId when cancelling check out");
+ completionBlock(NO, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeObjectNotFound detailedDescription:nil]);
+ return nil;
+ }
+
+ CMISRequest *request = [CMISRequest new];
+
+ [self workingCopyLinkForObjectId:objectId completionBlock:^(NSString *workingCopyLink, NSError *error) {
+ NSURL *deleteUrl = [NSURL URLWithString:workingCopyLink];
+ [self.bindingSession.networkProvider invokeDELETE:deleteUrl
+ session:self.bindingSession
+ cmisRequest:request
+ completionBlock:^(CMISHttpResponse *httpResponse, NSError *error) {
+ if (httpResponse) {
+ completionBlock(YES, nil);
+ } else {
+ completionBlock(NO, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeVersioning]);
+ }
+ }];
+ }];
+
+ return request;
+}
+
+- (CMISRequest*)checkIn:(NSString *)objectId
+ asMajorVersion:(BOOL)asMajorVersion
+ filePath:(NSString *)filePath
+ mimeType:(NSString *)mimeType
+ properties:(CMISProperties *)properties
+ checkinComment:(NSString *)checkinComment
+ completionBlock:(void (^)(CMISObjectData *objectData, NSError *error))completionBlock
+ progressBlock:(void (^)(unsigned long long bytesUploaded, unsigned long long bytesTotal))progressBlock
+{
+ NSInputStream *inputStream = [NSInputStream inputStreamWithFileAtPath:filePath];
+ if (inputStream == nil) {
+ CMISLogError(@"Could not find file %@", filePath);
+ if (completionBlock) {
+ completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument detailedDescription:nil]);
+ }
+ return nil;
+ }
+
+ NSError *fileError = nil;
+ unsigned long long fileSize = [CMISFileUtil fileSizeForFileAtPath:filePath error:&fileError];
+ if (fileError) {
+ CMISLogError(@"Could not determine size of file %@: %@", filePath, [fileError description]);
+ }
+
+ return [self checkIn:objectId
+ asMajorVersion:asMajorVersion
+ inputStream:inputStream
+ bytesExpected:fileSize
+ mimeType:mimeType
+ properties:properties
+ checkinComment:checkinComment
+ completionBlock:completionBlock
+ progressBlock:progressBlock];
+}
+
+- (CMISRequest*)checkIn:(NSString *)objectId
+ asMajorVersion:(BOOL)asMajorVersion
+ inputStream:(NSInputStream *)inputStream
+ bytesExpected:(unsigned long long)bytesExpected
+ mimeType:(NSString *)mimeType
+ properties:(CMISProperties *)properties
+ checkinComment:(NSString *)checkinComment
+ completionBlock:(void (^)(CMISObjectData *objectData, NSError *error))completionBlock
+ progressBlock:(void (^)(unsigned long long bytesUploaded, unsigned long long bytesTotal))progressBlock
+{
+ // Validate params
+ if (!objectId) {
+ CMISLogError(@"Must provide an objectId when checking in");
+ completionBlock(NO, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeObjectNotFound detailedDescription:nil]);
+ return nil;
+ }
+
+ CMISRequest *request = [CMISRequest new];
+
+ [self workingCopyLinkForObjectId:objectId completionBlock:^(NSString *workingCopyLink, NSError *error) {
+
+ // add the necessary parameters to the URL
+ NSString *link = [CMISURLUtil urlStringByAppendingParameter:kCMISParameterCheckin value:kCMISParameterValueTrue urlString:workingCopyLink];
+ link = [CMISURLUtil urlStringByAppendingParameter:kCMISParameterMajor
+ value:asMajorVersion ? kCMISParameterValueTrue : kCMISParameterValueFalse urlString:link];
+ if (checkinComment != nil)
+ {
+ link = [CMISURLUtil urlStringByAppendingParameter:kCMISParameterCheckinComment value:checkinComment urlString:link];
+ }
+
+ // send an atom entry to have the file checked in
+ [self sendAtomEntryXmlToLink:link
+ httpRequestMethod:HTTP_PUT
+ properties:properties
+ contentInputStream:inputStream
+ contentMimeType:mimeType
+ bytesExpected:bytesExpected
+ cmisRequest:request
+ completionBlock:^(CMISObjectData *objectData, NSError *error) {
+ if (error) {
+ completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeVersioning]);
+ } else {
+ completionBlock(objectData, nil);
+ }
+ }
+ progressBlock:progressBlock];
+ }];
+
+ return request;
+}
+
+#pragma mark Internal methods
+
+- (CMISRequest *)workingCopyLinkForObjectId:(NSString *)objectId completionBlock:(void(^)(NSString *workingCopyLink, NSError *error))completionBlock
+{
+ CMISRequest *request = [CMISRequest new];
+ [self loadLinkForObjectId:objectId
+ relation:kCMISLinkRelationSelf
+ cmisRequest:request
+ completionBlock:^(NSString *selfLink, NSError *error) {
+ if (!selfLink) {
+ completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument detailedDescription:nil]);
+ } else {
+ // Prefer working copy link if available
+ [self loadLinkForObjectId:objectId
+ relation:kCMISLinkRelationWorkingCopy
+ cmisRequest:request
+ completionBlock:^(NSString *workingCopyLink, NSError *error) {
+ NSString *link = (nil != workingCopyLink) ? workingCopyLink : selfLink;
+ completionBlock(link, nil);
+ }];
+ }
+ }];
+
+ return request;
+}
+
@end
\ No newline at end of file
Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISBindingSession.h
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISBindingSession.h?rev=1576931&r1=1576930&r2=1576931&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISBindingSession.h (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISBindingSession.h Wed Mar 12 21:38:07 2014
@@ -29,6 +29,7 @@ extern NSString * const kCMISBindingSess
extern NSString * const kCMISBindingSessionKeyQueryUri;
extern NSString * const kCMISBindingSessionKeyQueryCollection;
+extern NSString * const kCMISBindingSessionKeyCheckedoutCollection;
extern NSString * const kCMISBindingSessionKeyLinkCache;
Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISBindingSession.m
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISBindingSession.m?rev=1576931&r1=1576930&r2=1576931&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISBindingSession.m (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISBindingSession.m Wed Mar 12 21:38:07 2014
@@ -26,6 +26,7 @@ NSString * const kCMISBindingSessionKeyT
NSString * const kCMISBindingSessionKeyQueryUri = @"cmis_session_key_query_uri";
NSString * const kCMISBindingSessionKeyQueryCollection = @"cmis_session_key_query_collection";
+NSString * const kCMISBindingSessionKeyCheckedoutCollection = @"cmis_session_key_checkedout_collection";
NSString * const kCMISBindingSessionKeyLinkCache = @"cmis_session_key_link_cache";
Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISVersioningService.h
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISVersioningService.h?rev=1576931&r1=1576930&r2=1576931&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISVersioningService.h (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISVersioningService.h Wed Mar 12 21:38:07 2014
@@ -23,6 +23,7 @@
@class CMISCollection;
@class CMISObject;
@class CMISObjectData;
+@class CMISProperties;
@class CMISRequest;
@protocol CMISVersioningService <NSObject>
@@ -61,6 +62,66 @@
includeAllowableActions:(BOOL)includeAllowableActions
completionBlock:(void (^)(NSArray *objects, NSError *error))completionBlock;
+/**
+ * Create a private working copy of a document given an object identifier.
+ *
+ * @param objectId
+ * @param completionBlock returns PWC object data or nil
+ */
+- (CMISRequest*)checkOut:(NSString *)objectId
+ completionBlock:(void (^)(CMISObjectData *objectData, NSError *error))completionBlock;
+
+/**
+ * Reverses the effect of a check-out.
+ *
+ * @param objectId
+ * @param completionBlock returns object data or nil
+ */
+- (CMISRequest*)cancelCheckOut:(NSString *)objectId
+ completionBlock:(void (^)(BOOL checkOutCancelled, NSError *error))completionBlock;
+
+/**
+ * Checks-in the private working copy (PWC) document from the given path.
+ *
+ * @param objectId the identifier for the PWC
+ * @param asMajorVersion indicator if the new version should become a major (YES) or minor (NO) version
+ * @param filePath (optional) Path to the file containing the content to be uploaded
+ * @param mimeType (optional) Mime type of the content to be uploaded
+ * @param properties (optional) the property values that must be applied to the checked-in document object
+ * @param checkinComment (optional) a version comment
+ * @param completionBlock returns object data or nil
+ * @param progressBlock periodic file upload status
+ */
+- (CMISRequest*)checkIn:(NSString *)objectId
+ asMajorVersion:(BOOL)asMajorVersion
+ filePath:(NSString *)filePath
+ mimeType:(NSString *)mimeType
+ properties:(CMISProperties *)properties
+ checkinComment:(NSString *)checkinComment
+ completionBlock:(void (^)(CMISObjectData *objectData, NSError *error))completionBlock
+ progressBlock:(void (^)(unsigned long long bytesUploaded, unsigned long long bytesTotal))progressBlock;
+/**
+ * Checks-in the private working copy (PWC) document from the given an input stream.
+ *
+ * @param objectId the identifier for the PWC
+ * @param asMajorVersion indicator if the new version should become a major (YES) or minor (NO) version
+ * @param inputStream (optional) Input stream containing the content to be uploaded
+ * @param bytesExpected The size of content to be uploaded (must be provided if an inputStream is given)
+ * @param mimeType (optional) Mime type of the content to be uploaded
+ * @param properties (optional) the property values that must be applied to the checked-in document object
+ * @param checkinComment (optional) a version comment
+ * @param completionBlock returns object data or nil
+ * @param progressBlock periodic file upload status
+ */
+- (CMISRequest*)checkIn:(NSString *)objectId
+ asMajorVersion:(BOOL)asMajorVersion
+ inputStream:(NSInputStream *)inputStream
+ bytesExpected:(unsigned long long)bytesExpected
+ mimeType:(NSString *)mimeType
+ properties:(CMISProperties *)properties
+ checkinComment:(NSString *)checkinComment
+ completionBlock:(void (^)(CMISObjectData *objectData, NSError *error))completionBlock
+ progressBlock:(void (^)(unsigned long long bytesUploaded, unsigned long long bytesTotal))progressBlock;
@end
Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISDocument.h
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISDocument.h?rev=1576931&r1=1576930&r2=1576931&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISDocument.h (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISDocument.h Wed Mar 12 21:38:07 2014
@@ -120,4 +120,37 @@
*/
- (CMISRequest*)deleteAllVersionsWithCompletionBlock:(void (^)(BOOL documentDeleted, NSError *error))completionBlock;
+/**
+ * Checkout the document and return the PWC via the completion block
+ */
+- (CMISRequest*)checkOutWithCompletionBlock:(void (^)(CMISDocument *privateWorkingCopy, NSError *error))completionBlock;
+
+/**
+ * Cancel checkout if this is a PWC
+ */
+- (CMISRequest*)cancelCheckOutWithCompletionBlock:(void (^)(BOOL checkoutCancelled, NSError *error))completionBlock;
+
+/**
+ * Checkin this PWC from a specified file path and return the checked-in document
+ */
+- (CMISRequest*)checkInAsMajorVersion:(BOOL)majorVersion
+ filePath:(NSString *)filePath
+ mimeType:(NSString *)mimeType
+ properties:(CMISProperties *)properties
+ checkinComment:(NSString *)checkinComment
+ completionBlock:(void (^)(CMISDocument *document, NSError *error))completionBlock
+ progressBlock:(void (^)(unsigned long long bytesUploaded, unsigned long long bytesTotal))progressBlock;
+
+/**
+ * Checkin this PWC from a specified input stream and return the checked-in document
+ */
+- (CMISRequest*)checkInAsMajorVersion:(BOOL)majorVersion
+ inputStream:(NSInputStream *)inputStream
+ bytesExpected:(unsigned long long)bytesExpected
+ mimeType:(NSString *)mimeType
+ properties:(CMISProperties *)properties
+ checkinComment:(NSString *)checkinComment
+ completionBlock:(void (^)(CMISDocument *document, NSError *error))completionBlock
+ progressBlock:(void (^)(unsigned long long bytesUploaded, unsigned long long bytesTotal))progressBlock;
+
@end
Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISDocument.m
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISDocument.m?rev=1576931&r1=1576930&r2=1576931&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISDocument.m (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISDocument.m Wed Mar 12 21:38:07 2014
@@ -47,7 +47,7 @@
- (id)initWithObjectData:(CMISObjectData *)objectData session:(CMISSession *)session
{
self = [super initWithObjectData:objectData session:session];
- if (self){
+ if (self) {
self.contentStreamId = [[objectData.properties.propertiesDictionary objectForKey:kCMISPropertyContentStreamId] firstValue];
self.contentStreamMediaType = [[objectData.properties.propertiesDictionary objectForKey:kCMISPropertyContentStreamMediaType] firstValue];
self.contentStreamLength = [[[objectData.properties.propertiesDictionary objectForKey:kCMISPropertyContentStreamLength] firstValue] unsignedLongLongValue];
@@ -182,4 +182,98 @@
return [self.binding.objectService deleteObject:self.identifier allVersions:YES completionBlock:completionBlock];
}
+- (CMISRequest *)checkOutWithCompletionBlock:(void (^)(CMISDocument *privateWorkingCopy, NSError *error))completionBlock
+{
+ return [self.binding.versioningService checkOut:self.identifier completionBlock:^(CMISObjectData *objectData, NSError *error) {
+ if (error) {
+ completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeVersioning]);
+ } else {
+ [self.session.objectConverter convertObject:objectData completionBlock:^(CMISObject *object, NSError *error) {
+ if (error) {
+ [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeVersioning];
+ } else {
+ completionBlock((CMISDocument*)object, nil);
+ }
+ }];
+ }
+ }];
+}
+
+- (CMISRequest *)cancelCheckOutWithCompletionBlock:(void (^)(BOOL, NSError *))completionBlock
+{
+ return [self.binding.versioningService cancelCheckOut:self.identifier completionBlock:^(BOOL checkOutCancelled, NSError *error) {
+ if (error) {
+ completionBlock(NO, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeVersioning]);
+ } else {
+ completionBlock(YES, nil);
+ }
+ }];
+}
+
+- (CMISRequest*)checkInAsMajorVersion:(BOOL)majorVersion
+ filePath:(NSString *)filePath
+ mimeType:(NSString *)mimeType
+ properties:(CMISProperties *)properties
+ checkinComment:(NSString *)checkinComment
+ completionBlock:(void (^)(CMISDocument *document, NSError *error))completionBlock
+ progressBlock:(void (^)(unsigned long long bytesUploaded, unsigned long long bytesTotal))progressBlock
+{
+ return [self.binding.versioningService checkIn:self.identifier
+ asMajorVersion:majorVersion
+ filePath:filePath
+ mimeType:mimeType
+ properties:properties
+ checkinComment:checkinComment
+ completionBlock:^(CMISObjectData *objectData, NSError *error) {
+ if (error) {
+ completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeVersioning]);
+ } else {
+ // convert the object data to document object
+ [self.session.objectConverter convertObject:objectData completionBlock:^(CMISObject *object, NSError *error) {
+ if (error) {
+ [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeVersioning];
+ } else {
+ completionBlock((CMISDocument*)object, nil);
+ }
+ }];
+ }
+ } progressBlock:^(unsigned long long bytesUploaded, unsigned long long bytesTotal) {
+ progressBlock(bytesUploaded, bytesTotal);
+ }];
+}
+
+- (CMISRequest*)checkInAsMajorVersion:(BOOL)majorVersion
+ inputStream:(NSInputStream *)inputStream
+ bytesExpected:(unsigned long long)bytesExpected
+ mimeType:(NSString *)mimeType
+ properties:(CMISProperties *)properties
+ checkinComment:(NSString *)checkinComment
+ completionBlock:(void (^)(CMISDocument *document, NSError *error))completionBlock
+ progressBlock:(void (^)(unsigned long long bytesUploaded, unsigned long long bytesTotal))progressBlock
+{
+ return [self.binding.versioningService checkIn:self.identifier
+ asMajorVersion:majorVersion
+ inputStream:inputStream
+ bytesExpected:bytesExpected
+ mimeType:mimeType
+ properties:properties
+ checkinComment:checkinComment
+ completionBlock:^(CMISObjectData *objectData, NSError *error) {
+ if (error) {
+ completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeVersioning]);
+ } else {
+ // convert the object data to document object
+ [self.session.objectConverter convertObject:objectData completionBlock:^(CMISObject *object, NSError *error) {
+ if (error) {
+ [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeVersioning];
+ } else {
+ completionBlock((CMISDocument*)object, nil);
+ }
+ }];
+ }
+ } progressBlock:^(unsigned long long bytesUploaded, unsigned long long bytesTotal) {
+ progressBlock(bytesUploaded, bytesTotal);
+ }];
+}
+
@end
Modified: chemistry/objectivecmis/trunk/ObjectiveCMISTests/CMISBaseTest.m
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMISTests/CMISBaseTest.m?rev=1576931&r1=1576930&r2=1576931&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMISTests/CMISBaseTest.m (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMISTests/CMISBaseTest.m Wed Mar 12 21:38:07 2014
@@ -88,7 +88,8 @@
}
[CMISSession connectWithSessionParameters:self.parameters completionBlock:^(CMISSession *session, NSError *error){
if (nil == session) {
-
+ XCTFail(@"Failed to create session: %@", error.localizedDescription);
+ self.testCompleted = YES;
} else {
self.session = session;
XCTAssertTrue(self.session.isAuthenticated, @"Session should be authenticated");
Modified: chemistry/objectivecmis/trunk/ObjectiveCMISTests/ObjectiveCMISTests.m
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMISTests/ObjectiveCMISTests.m?rev=1576931&r1=1576930&r2=1576931&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMISTests/ObjectiveCMISTests.m (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMISTests/ObjectiveCMISTests.m Wed Mar 12 21:38:07 2014
@@ -1714,4 +1714,113 @@
}];
}
+- (void)testCheckoutCheckin
+{
+ [self runTest:^ {
+ // Upload test file
+ [self uploadTestFileWithCompletionBlock:^(CMISDocument *testDocument) {
+
+ XCTAssertNotNil(testDocument, @"Expected testDocument to be uploaded!");
+
+ // checkout the uploaded test document
+ [testDocument checkOutWithCompletionBlock:^(CMISDocument *privateWorkingCopy, NSError *error) {
+
+ // check we got the working copy
+ XCTAssertNotNil(privateWorkingCopy, @"Expected to recieve the private working copy object");
+
+ // checkin the test document
+ NSString *updatedFilePath = [[NSBundle bundleForClass:[self class]] pathForResource:@"test_file_2.txt" ofType:nil];
+ [privateWorkingCopy checkInAsMajorVersion:YES filePath:updatedFilePath mimeType:@"text/plain" properties:nil checkinComment:@"Next version" completionBlock:^(CMISDocument *checkedInDocument, NSError *error) {
+
+ // check we got back the checked in document
+ XCTAssertNotNil(checkedInDocument, @"Expected to receive the checked in document object");
+
+ // validate the content was updated
+ NSString *tempDownloadFilePath = [NSString stringWithFormat:@"%@/temp_download_file.txt", NSTemporaryDirectory()];
+ [checkedInDocument downloadContentToFile:tempDownloadFilePath completionBlock:^(NSError *error) {
+
+ // check the content has been updated
+ NSString *contentOfDownloadedFile = [NSString stringWithContentsOfFile:tempDownloadFilePath encoding:NSUTF8StringEncoding error:nil];
+ XCTAssertEqualObjects(@"In theory, there is no difference between theory and practice. But in practice, there is.",
+ contentOfDownloadedFile, @"Downloaded file content does not match, it was: '%@'", contentOfDownloadedFile);
+
+ // retrieve all versions of the document and make sure there are 2 and the last one has the correct info
+ [checkedInDocument retrieveAllVersionsWithCompletionBlock:^(CMISCollection *allVersionsOfDocument, NSError *error) {
+
+ // make sure there are 2 versions
+ XCTAssertTrue(allVersionsOfDocument.items.count == 2,
+ @"Expected to find 2 versions but there were %lu", (unsigned long)allVersionsOfDocument.items.count);
+
+ // get the first item (should be the latest one) and check the version label and checkin comment
+ CMISDocument *secondVersion = allVersionsOfDocument.items[0];
+ XCTAssertTrue([secondVersion.versionLabel isEqualToString:@"2.0"],
+ @"Expected version label to be 2.0 but was %@", secondVersion.versionLabel);
+ XCTAssertTrue(secondVersion.isLatestVersion, @"Expected document to be the latest version");
+ XCTAssertTrue(secondVersion.isLatestMajorVersion, @"Expected document to be the latest major version");
+ XCTAssertTrue(secondVersion.isMajorVersion, @"Expected document to be a major version");
+ NSString *checkinComment = [secondVersion.properties propertyValueForId:kCMISPropertyCheckinComment];
+ XCTAssertTrue([checkinComment isEqualToString:@"Next version"],
+ @"Expected checkin comment to be 'Next version' but was %@", checkinComment);
+
+ CMISDocument *firstVersion = allVersionsOfDocument.items[1];
+ XCTAssertTrue([firstVersion.versionLabel isEqualToString:@"1.0"],
+ @"Expected version label to be 1.0 but was %@", firstVersion.versionLabel);
+ XCTAssertFalse(firstVersion.isLatestVersion, @"Did not expect document to be the latest version");
+ XCTAssertFalse(firstVersion.isLatestMajorVersion, @"Did not expect document to be the latest major version");
+ XCTAssertTrue(firstVersion.isMajorVersion, @"Expected document to be a major version");
+
+ // delete the document
+ [self deleteDocumentAndVerify:checkedInDocument completionBlock:^{
+ // mark the test as completed
+ self.testCompleted = YES;
+ }];
+ }];
+
+ } progressBlock:^(unsigned long long bytesDownloaded, unsigned long long bytesTotal) {
+ CMISLogDebug(@"download progress %i/%i", bytesDownloaded, bytesTotal);
+ }];
+ } progressBlock:^(unsigned long long bytesUploaded, unsigned long long bytesTotal) {
+ CMISLogDebug(@"upload progress %i/%i", bytesUploaded, bytesTotal);
+ }];
+ }];
+ }];
+ }];
+}
+
+- (void)testCancelCheckout
+{
+ [self runTest:^ {
+ // Upload test file
+ [self uploadTestFileWithCompletionBlock:^(CMISDocument *testDocument) {
+
+ XCTAssertNotNil(testDocument, @"Expected testDocument to be uploaded!");
+
+ // checkout the uploaded test document
+ [testDocument checkOutWithCompletionBlock:^(CMISDocument *privateWorkingCopy, NSError *checkOutError) {
+ XCTAssertNotNil(privateWorkingCopy, @"Expected to recieve the private working copy object");
+
+ // cancel checkout of the test document
+ [privateWorkingCopy cancelCheckOutWithCompletionBlock:^(BOOL checkoutCancelled, NSError *cancelError) {
+
+ // make sure the pwc has been deleted
+ [self.session retrieveObject:privateWorkingCopy.identifier completionBlock:^(CMISObject *object, NSError *retrieveError) {
+
+ // make sure the object is nill and error is not nil
+ XCTAssertNil(object, @"Did not expect to receive a document, the pwc should have been deleted");
+ XCTAssertNotNil(retrieveError, @"Expected there to be an error object");
+ XCTAssertTrue(retrieveError.code == kCMISErrorCodeObjectNotFound,
+ @"Expected the error code to be 257 (kCMISErrorCodeObjectNotFound) but was %ld", (long)retrieveError.code);
+
+ // delete the document
+ [self deleteDocumentAndVerify:testDocument completionBlock:^{
+ // mark the test as completed
+ self.testCompleted = YES;
+ }];
+ }];
+ }];
+ }];
+ }];
+ }];
+}
+
@end