Author: jpotts
Date: Sat May 3 20:38:23 2014
New Revision: 1592276
URL: http://svn.apache.org/r1592276
Log:
cmislib browser binding createDocument and createDocumentFromString now working
Added:
chemistry/cmislib/trunk/src/cmislib/atompub/
chemistry/cmislib/trunk/src/cmislib/atompub/__init__.py
chemistry/cmislib/trunk/src/cmislib/atompub/binding.py
- copied, changed from r1550344,
chemistry/cmislib/trunk/src/cmislib/atompub_binding.py
chemistry/cmislib/trunk/src/cmislib/browser/
chemistry/cmislib/trunk/src/cmislib/browser/__init__.py
chemistry/cmislib/trunk/src/cmislib/browser/binding.py
- copied, changed from r1513723,
chemistry/cmislib/trunk/src/cmislib/browser_binding.py
chemistry/cmislib/trunk/src/cmislib/browser/serializers.py
Removed:
chemistry/cmislib/trunk/src/cmislib/atompub_binding.py
chemistry/cmislib/trunk/src/cmislib/browser_binding.py
Modified:
chemistry/cmislib/trunk/src/cmislib/__init__.py
chemistry/cmislib/trunk/src/cmislib/cmis_services.py
chemistry/cmislib/trunk/src/cmislib/domain.py
chemistry/cmislib/trunk/src/cmislib/model.py
Modified: chemistry/cmislib/trunk/src/cmislib/__init__.py
URL:
http://svn.apache.org/viewvc/chemistry/cmislib/trunk/src/cmislib/__init__.py?rev=1592276&r1=1592275&r2=1592276&view=diff
==============================================================================
--- chemistry/cmislib/trunk/src/cmislib/__init__.py (original)
+++ chemistry/cmislib/trunk/src/cmislib/__init__.py Sat May 3 20:38:23 2014
@@ -20,7 +20,8 @@
Define package contents so that they are easy to import.
"""
-from model import CmisClient
-from domain import Repository, Folder
+from cmislib.model import CmisClient
+from cmislib.domain import Repository, Folder
+from cmislib.cmis_services import Binding, RepositoryServiceIfc
-__all__ = ["CmisClient", "Repository", "Folder"]
+__all__ = ["Binding", "CmisClient", "RepositoryServiceIfc", "Repository",
"Folder"]
Added: chemistry/cmislib/trunk/src/cmislib/atompub/__init__.py
URL:
http://svn.apache.org/viewvc/chemistry/cmislib/trunk/src/cmislib/atompub/__init__.py?rev=1592276&view=auto
==============================================================================
--- chemistry/cmislib/trunk/src/cmislib/atompub/__init__.py (added)
+++ chemistry/cmislib/trunk/src/cmislib/atompub/__init__.py Sat May 3 20:38:23
2014
@@ -0,0 +1 @@
+__author__ = 'jpotts'
Copied: chemistry/cmislib/trunk/src/cmislib/atompub/binding.py (from r1550344,
chemistry/cmislib/trunk/src/cmislib/atompub_binding.py)
URL:
http://svn.apache.org/viewvc/chemistry/cmislib/trunk/src/cmislib/atompub/binding.py?p2=chemistry/cmislib/trunk/src/cmislib/atompub/binding.py&p1=chemistry/cmislib/trunk/src/cmislib/atompub_binding.py&r1=1550344&r2=1592276&rev=1592276&view=diff
==============================================================================
--- chemistry/cmislib/trunk/src/cmislib/atompub_binding.py (original)
+++ chemistry/cmislib/trunk/src/cmislib/atompub/binding.py Sat May 3 20:38:23
2014
@@ -20,15 +20,14 @@
Module containing the Atom Pub binding-specific objects used to work with a
CMIS
provider.
"""
-from cmis_services import RepositoryServiceIfc
-from cmis_services import Binding
-from domain import CmisId, CmisObject, ObjectType, Property, ACL, ACE,
ChangeEntry, ResultSet, Rendition
-from net import RESTService as Rest
-from exceptions import CmisException, \
+from cmislib.cmis_services import Binding, RepositoryServiceIfc
+from cmislib.domain import CmisId, CmisObject, ObjectType, Property, ACL, ACE,
ChangeEntry, ResultSet, Rendition
+from cmislib.net import RESTService as Rest
+from cmislib.exceptions import CmisException, \
ObjectNotFoundException, InvalidArgumentException, \
NotSupportedException
-from util import parseDateTimeValue
-import messages
+from cmislib.util import multiple_replace, parsePropValue, parseBoolValue,
toCMISValue, parseDateTimeValue
+import cmislib.messages
from urllib import quote
from urlparse import urlparse, urlunparse
@@ -39,7 +38,6 @@ import datetime
import StringIO
import logging
from xml.dom import minidom
-from util import multiple_replace, parsePropValue, parseBoolValue, toCMISValue
moduleLogger = logging.getLogger('cmislib.atompub_binding')
@@ -1487,7 +1485,7 @@ class AtomPubRepository(object):
- includeAllowableActions
"""
- return getSpecializedObject(AtomPubCmisObject(self._cmisClient, self,
objectId, **kwargs), **kwargs)
+ return getSpecializedObject(AtomPubCmisObject(self._cmisClient, self,
CmisId(objectId), **kwargs), **kwargs)
def getObjectByPath(self, path, **kwargs):
@@ -1882,7 +1880,7 @@ class AtomPubRepository(object):
If the types collection is specified, the method returns the result of
`getTypeDefinitions` and ignores any optional params passed in.
- >>> from cmislib.atompub_binding import TYPES_COLL
+ >>> from cmislib.atompub.atompub_binding import TYPES_COLL
>>> types = repo.getCollection(TYPES_COLL)
>>> len(types)
4
@@ -1892,7 +1890,7 @@ class AtomPubRepository(object):
Otherwise, the collection URL is invoked, and a :class:`ResultSet` is
returned.
- >>> from cmislib.atompub_binding import CHECKED_OUT_COLL
+ >>> from cmislib.atompub.atompub_binding import CHECKED_OUT_COLL
>>> resultSet = repo.getCollection(CHECKED_OUT_COLL)
>>> len(resultSet.getResults())
1
@@ -1917,7 +1915,7 @@ class AtomPubRepository(object):
Returns the link HREF from the specified collectionType
('checkedout', for example).
- >>> from cmislib.atompub_binding import CHECKED_OUT_COLL
+ >>> from cmislib.atompub.atompub_binding import CHECKED_OUT_COLL
>>> repo.getCollectionLink(CHECKED_OUT_COLL)
u'http://localhost:8080/alfresco/s/cmis/checkedout'
@@ -3189,7 +3187,7 @@ class AtomPubObjectType(ObjectType):
"""
Gets the HREF for the link element with the specified rel and linkType.
- >>> from cmislib.atompub_binding import ATOM_XML_FEED_TYPE
+ >>> from cmislib.atompub.atompub_binding import ATOM_XML_FEED_TYPE
>>> docType.getLink('down', ATOM_XML_FEED_TYPE)
u'http://localhost:8080/alfresco/s/cmis/type/cmis:document/children'
"""
Added: chemistry/cmislib/trunk/src/cmislib/browser/__init__.py
URL:
http://svn.apache.org/viewvc/chemistry/cmislib/trunk/src/cmislib/browser/__init__.py?rev=1592276&view=auto
==============================================================================
--- chemistry/cmislib/trunk/src/cmislib/browser/__init__.py (added)
+++ chemistry/cmislib/trunk/src/cmislib/browser/__init__.py Sat May 3 20:38:23
2014
@@ -0,0 +1 @@
+__author__ = 'jpotts'
Copied: chemistry/cmislib/trunk/src/cmislib/browser/binding.py (from r1513723,
chemistry/cmislib/trunk/src/cmislib/browser_binding.py)
URL:
http://svn.apache.org/viewvc/chemistry/cmislib/trunk/src/cmislib/browser/binding.py?p2=chemistry/cmislib/trunk/src/cmislib/browser/binding.py&p1=chemistry/cmislib/trunk/src/cmislib/browser_binding.py&r1=1513723&r2=1592276&rev=1592276&view=diff
==============================================================================
--- chemistry/cmislib/trunk/src/cmislib/browser_binding.py (original)
+++ chemistry/cmislib/trunk/src/cmislib/browser/binding.py Sat May 3 20:38:23
2014
@@ -20,20 +20,20 @@
Module containing the browser binding-specific objects used to work with a CMIS
provider.
"""
-from cmis_services import RepositoryServiceIfc
-from cmis_services import Binding
-from net import RESTService as Rest
-from exceptions import CmisException, RuntimeException, ObjectNotFoundException
-from domain import CmisId, CmisObject, Repository, Relationship, Policy,
ObjectType, Property, Folder, Document, ACL, ACE, ChangeEntry, ResultSet,
ChangeEntryResultSet, Rendition
-from util import parsePropValueByType, parseBoolValue
+from cmislib.cmis_services import Binding, RepositoryServiceIfc
+from cmislib.domain import CmisId, CmisObject, Repository, Relationship,
Policy, ObjectType, Property, Folder, Document, ACL, ACE, ChangeEntry,
ResultSet, ChangeEntryResultSet, Rendition
+from cmislib.exceptions import CmisException, RuntimeException,
ObjectNotFoundException
+from cmislib.net import RESTService as Rest
+from cmislib.util import parsePropValueByType, parseBoolValue
import json
-import StringIO
import logging
+import StringIO
+import time
from urllib import urlencode, quote
CMIS_FORM_TYPE = 'application/x-www-form-urlencoded;charset=utf-8'
-moduleLogger = logging.getLogger('cmislib.browser_binding')
+moduleLogger = logging.getLogger('cmislib.browser.binding')
class BrowserBinding(Binding):
def __init__(self, **kwargs):
@@ -1027,7 +1027,7 @@ class BrowserRepository(object):
- includeAllowableActions
"""
- return getSpecializedObject(BrowserCmisObject(self._cmisClient, self,
objectId, **kwargs), **kwargs)
+ return getSpecializedObject(BrowserCmisObject(self._cmisClient, self,
CmisId(objectId), **kwargs), **kwargs)
def query(self, statement, **kwargs):
@@ -1155,7 +1155,19 @@ class BrowserRepository(object):
<cmislib.model.Document object at 0x101352ed0>
"""
- pass
+ # if you didn't pass in a parent folder
+ if parentFolder is None:
+ # if the repository doesn't require fileable objects to be filed
+ if self.getCapabilities()['Unfiling']:
+ # has not been implemented
+ #postUrl = self.getCollectionLink(UNFILED_COLL)
+ raise NotImplementedError
+ else:
+ # this repo requires fileable objects to be filed
+ raise InvalidArgumentException
+
+ return parentFolder.createDocument(name, properties,
StringIO.StringIO(contentString),
+ contentType, contentEncoding)
def createDocument(self,
name,
@@ -1189,7 +1201,47 @@ class BrowserRepository(object):
- removeACEs
"""
- pass
+ # if you didn't pass in a parent folder
+ if parentFolder is None:
+ # if the repository doesn't require fileable objects to be filed
+ if self.getCapabilities()['Unfiling']:
+ # has not been implemented
+ raise NotImplementedError
+ else:
+ # this repo requires fileable objects to be filed
+ raise InvalidArgumentException
+
+ # get the root folder URL
+ createDocUrl = self.getRootFolderUrl()
+
+ props = {"objectId" : parentFolder.id,
+ "cmisaction" : "createDocument",
+ "propertyId[0]" : "cmis:name",
+ "propertyValue[0]" : name}
+
+ props["propertyId[1]"] = "cmis:objectTypeId"
+ if properties.has_key('cmis:objectTypeId'):
+ props["propertyValue[1]"] = properties['cmis:objectTypeId']
+ else:
+ props["propertyValue[1]"] = "cmis:document"
+
+ propCount = 2
+ for prop in properties:
+ props["propertyId[%s]" % propCount] = prop.key
+ props["propertyValue[%s]" % propCount] = prop
+ propCount += 1
+
+ contentType, body = encode_multipart_formdata(props, contentFile,
contentType)
+
+ # invoke the URL
+ result = self._cmisClient.binding.post(createDocUrl.encode('utf-8'),
+ body,
+ contentType,
+ self._cmisClient.username,
+ self._cmisClient.password)
+
+ # return the result set
+ return BrowserDocument(self._cmisClient, self, data=result)
def createDocumentFromSource(self,
sourceId,
@@ -1783,7 +1835,7 @@ class BrowserDocument(BrowserCmisObject)
of cmis:path with the relativePathSegment.
"""
- byObjectIdUrl = self._repository.getRootFolderUrl() + "?objectId=" +
self.getObjectId() + "&cmisselector=parents"
+ byObjectIdUrl = self._repository.getRootFolderUrl() + "?objectId=" +
self.getObjectId() + "&cmisselector=parents&includerelativepathsegment=true"
result = self._cmisClient.binding.get(byObjectIdUrl.encode('utf-8'),
self._cmisClient.username,
self._cmisClient.password)
@@ -1793,6 +1845,7 @@ class BrowserDocument(BrowserCmisObject)
#TODO why is the call to getObjectParents() made if it isn't used?
for res in result:
path = res['object']['properties']['cmis:path']['value']
+ logging.debug(path)
relativePathSegment = res['relativePathSegment']
# concat with a slash
@@ -1881,39 +1934,12 @@ class BrowserFolder(BrowserCmisObject):
>>> testFolder.createDocumentFromString('testdoc3',
contentString='hello, world', contentType='text/plain')
"""
- # get the root folder URL
- createDocUrl = self._repository.getRootFolderUrl()
-
- props = {"objectId" : self.id,
- "cmisaction" : "createDocument",
- "propertyId[0]" : "cmis:name",
- "propertyValue[0]" : name}
-
- props["propertyId[1]"] = "cmis:objectTypeId"
- if properties.has_key('cmis:objectTypeId'):
- props["propertyValue[1]"] = properties['cmis:objectTypeId']
- else:
- props["propertyValue[1]"] = "cmis:document"
-
- propCount = 2
- for prop in properties:
- props["propertyId[%s]" % propCount] = prop.key
- props["propertyValue[%s]" % propCount] = prop
- propCount += 1
-
- #TODO this isn't working at the moment
- props["content"] = contentString
-
- # invoke the URL
- result = self._cmisClient.binding.post(createDocUrl.encode('utf-8'),
- urlencode(props),
-
'application/x-www-form-urlencoded',
- self._cmisClient.username,
- self._cmisClient.password)
-
- # return the result set
- return BrowserDocument(self._cmisClient, self._repository, data=result)
-
+ return self._repository.createDocumentFromString(name,
+ properties,
+ self,
+ contentString,
+ contentType,
+ contentEncoding)
def createDocument(self, name, properties={}, contentFile=None,
contentType=None, contentEncoding=None):
@@ -1956,40 +1982,12 @@ class BrowserFolder(BrowserCmisObject):
- removeACEs
"""
- #TODO work in progress
-
- # get the root folder URL
- createDocUrl = self._repository.getRootFolderUrl()
-
- props = {"objectId" : self.id,
- "cmisaction" : "createDocument",
- "propertyId[0]" : "cmis:name",
- "propertyValue[0]" : name}
-
- props["propertyId[1]"] = "cmis:objectTypeId"
- if properties.has_key('cmis:objectTypeId'):
- pass
- else:
- props["propertyValue[1]"] = "cmis:document"
-
- propCount = 2
- for prop in properties:
- props["propertyId[%s]" % propCount] = prop
- props["propertyValue[%s]" % propCount] = properties[prop]
- propCount += 1
-
- #TODO this isn't working at the moment
- props["content"] = 'this is a test'
-
- # invoke the URL
- result = self._cmisClient.binding.post(createDocUrl.encode('utf-8'),
- urlencode(props),
-
'application/x-www-form-urlencoded',
- self._cmisClient.username,
- self._cmisClient.password)
-
- # return the result set
- return BrowserDocument(self._cmisClient, self._repository, data=result)
+ return self._repository.createDocument(name,
+ properties,
+ self,
+ contentFile,
+ contentType,
+ contentEncoding)
def getChildren(self, **kwargs):
@@ -2896,3 +2894,36 @@ def getSpecializedObject(obj, **kwargs):
# specify baseTypeId) or if the type isn't one of the known base
# types, give the object back
return obj
+
+def encode_multipart_formdata(fields, file, contentType):
+ """
+ fields is a sequence of (name, value) elements for regular form fields.
+ files is a sequence of (name, filename, value) elements for data to be
uploaded as files
+ Return (content_type, body) ready for httplib.HTTP instance
+ """
+ boundary = 'aPacHeCheMIStrycMisLIb%s' % (int(time.time()))
+ crlf = '\r\n'
+ L = []
+ fileName = None
+ for (key, value) in fields.iteritems():
+ if (key == 'cmis:name'):
+ fileName = value
+ L.append('--' + boundary)
+ L.append('Content-Disposition: form-data; name="%s"' % key)
+ L.append('Content-Type: text/plain; charset=utf-8')
+ L.append('')
+ L.append(value)
+
+ if file:
+ L.append('--' + boundary)
+ L.append('Content-Disposition: form-data; name="%s"; filename=%s' %
('content', fileName))
+ L.append('Content-Type: %s' % contentType)
+ L.append('Content-Transfer-Encoding: binary')
+ L.append('')
+ L.append(file.read()) # content of file goes here
+
+ L.append('--' + boundary + '--')
+ L.append('')
+ body = crlf.join(L)
+ content_type = 'multipart/form-data; boundary=%s' % boundary
+ return content_type, body
\ No newline at end of file
Added: chemistry/cmislib/trunk/src/cmislib/browser/serializers.py
URL:
http://svn.apache.org/viewvc/chemistry/cmislib/trunk/src/cmislib/browser/serializers.py?rev=1592276&view=auto
==============================================================================
--- chemistry/cmislib/trunk/src/cmislib/browser/serializers.py (added)
+++ chemistry/cmislib/trunk/src/cmislib/browser/serializers.py Sat May 3
20:38:23 2014
@@ -0,0 +1,14 @@
+import json
+
+from cmislib.browser.binding import BrowserFolder
+
+
+class FolderSerializer(object):
+ def toJSON(self, obj):
+ pass
+
+ def fromJSON(self, client, repo, jsonString):
+ obj = json.loads(jsonString)
+ objectId = obj['succinctProperties']['cmis:objectId']
+ folder = BrowserFolder(client, repo, objectId,
properties=obj['succinctProperties'])
+ return folder
\ No newline at end of file
Modified: chemistry/cmislib/trunk/src/cmislib/cmis_services.py
URL:
http://svn.apache.org/viewvc/chemistry/cmislib/trunk/src/cmislib/cmis_services.py?rev=1592276&r1=1592275&r2=1592276&view=diff
==============================================================================
--- chemistry/cmislib/trunk/src/cmislib/cmis_services.py (original)
+++ chemistry/cmislib/trunk/src/cmislib/cmis_services.py Sat May 3 20:38:23
2014
@@ -19,7 +19,7 @@
"""
Module containing the base Binding class and other service objects.
"""
-from exceptions import CmisException, RuntimeException, \
+from cmislib.exceptions import CmisException, RuntimeException, \
ObjectNotFoundException, InvalidArgumentException, \
PermissionDeniedException, NotSupportedException, \
UpdateConflictException
Modified: chemistry/cmislib/trunk/src/cmislib/domain.py
URL:
http://svn.apache.org/viewvc/chemistry/cmislib/trunk/src/cmislib/domain.py?rev=1592276&r1=1592275&r2=1592276&view=diff
==============================================================================
--- chemistry/cmislib/trunk/src/cmislib/domain.py (original)
+++ chemistry/cmislib/trunk/src/cmislib/domain.py Sat May 3 20:38:23 2014
@@ -957,7 +957,7 @@ class Repository(object):
If the types collection is specified, the method returns the result of
`getTypeDefinitions` and ignores any optional params passed in.
- >>> from cmislib.atompub_binding import TYPES_COLL
+ >>> from cmislib.atompub.atompub_binding import TYPES_COLL
>>> types = repo.getCollection(TYPES_COLL)
>>> len(types)
4
@@ -967,7 +967,7 @@ class Repository(object):
Otherwise, the collection URL is invoked, and a :class:`ResultSet` is
returned.
- >>> from cmislib.atompub_binding import CHECKED_OUT_COLL
+ >>> from cmislib.atompub.atompub_binding import CHECKED_OUT_COLL
>>> resultSet = repo.getCollection(CHECKED_OUT_COLL)
>>> len(resultSet.getResults())
1
@@ -1766,7 +1766,7 @@ class ObjectType(object):
"""
Gets the HREF for the link element with the specified rel and linkType.
- >>> from cmislib.atompub_binding import ATOM_XML_FEED_TYPE
+ >>> from cmislib.atompub.atompub_binding import ATOM_XML_FEED_TYPE
>>> docType.getLink('down', ATOM_XML_FEED_TYPE)
u'http://localhost:8080/alfresco/s/cmis/type/cmis:document/children'
"""
Modified: chemistry/cmislib/trunk/src/cmislib/model.py
URL:
http://svn.apache.org/viewvc/chemistry/cmislib/trunk/src/cmislib/model.py?rev=1592276&r1=1592275&r2=1592276&view=diff
==============================================================================
--- chemistry/cmislib/trunk/src/cmislib/model.py (original)
+++ chemistry/cmislib/trunk/src/cmislib/model.py Sat May 3 20:38:23 2014
@@ -21,11 +21,12 @@ Module containing the CmisClient object,
keeping track of connection information. The name 'model' is no longer
really appropriate, but it is kept for backwards compatibility.
"""
-from atompub_binding import AtomPubBinding
-from cmis_services import Binding
-from domain import CmisObject, Repository
import logging
+from atompub.binding import AtomPubBinding
+from cmis_services import Binding
+
+
moduleLogger = logging.getLogger('cmislib.model')
class CmisClient(object):