예제 #1
0
    def testMove(self):
        """ Test for the move method. """

        item_support.move("", "")

        self._repositoryMock.error = ItemError("")
        self.assertRaises(ItemSupportError, item_support.move, "", "")

        self._repositoryMock.error = None
        self._itemMock.methodNameResultMap = {"move": (None, ItemError(""))}
        self.assertRaises(ItemSupportError, item_support.move, "", "")
예제 #2
0
    def testCopy(self):
        """ Test for the copy method. """

        item_support.copy("", "")

        self._repositoryMock.error = ItemError("")
        self.assertRaises(ItemSupportError, item_support.copy, "", "")

        self._repositoryMock.error = None
        self._itemMock.methodNameResultMap = {"copy": (None, ItemError(""))}
        self.assertRaises(ItemSupportError, item_support.copy, "", "")
예제 #3
0
 def checkDatamodelConsistency(self, parentDataType, childDataType, isRoot=False):
     """ Checks the data model consistency of both items. """
     
     if self._configuration.isManagedRepository:
         if childDataType is None:
             raise ItemError("Data type is invalid.")
         if parentDataType is None and not isRoot:
             raise ItemError("Data type is invalid.")
         if not self._existsConnection(parentDataType, childDataType):
             raise ItemError("Cannot perform action because no relation between " \
                             + "both data types is defined by the underlying data model.")
예제 #4
0
 def _checkPreConditions(self, sourceItem, properties):
     """ Sanity checks before the archive process starts. """
     
     if not sourceItem.capabilities.canArchive:
         raise ItemError("The item '%s' cannot be archived." %  sourceItem.path)
     
     missingPropertyIds = list()
     for property_ in properties:
         if not property_.propertyDefinition in self._repository.configuration.defaultArchivePropertyDefinitions:
             missingPropertyIds.append(property_.propertyDefinition.identifier)
     if len(missingPropertyIds) > 0:
         errorMessage = "The following properties are missing:"
         for propertyId in missingPropertyIds:
             errorMessage += "\n" + propertyId
         raise ItemError(errorMessage)
예제 #5
0
    def _storeArchiveData(self, sourceCollection, archiveRoot):
        """ Collects data which has to be archived and stores it. """
        
        importedLeafs = list()
        temporaryFilePath = self._determineTemporaryFilePath()
        try:
            # put everything in a temporary file
            cwr = self._repositoryManager.workingRepository
            archiveRepository = self._repositoryManager.connectRepository("arch:" + temporaryFilePath)
            try:
                importer = Importer(_STOP_TRAVERSAL_STATES, _STOP_PROCESSING_STATES)
                for item in sourceCollection.getChildren():
                    importer.performImport(item, archiveRepository.root, ignoreLinks=True)
                    importedLeafs += importer.importedLeafs
            finally:
                self._repositoryManager.disconnectRepository(archiveRepository)
                self._repositoryManager.workingRepository = cwr

            # store it - when necessary
            if len(importedLeafs) > 0:
                try:
                    archiveRoot.dataPersister.storeData(open(temporaryFilePath, "rb")) 
                except (OSError, IOError):
                    raise ItemError("Unable to access temporary created archive data.")
        finally:
            try:
                os.remove(temporaryFilePath)
            except OSError:
                _log.debug("Cannot remove temporary file '%s'" % temporaryFilePath)
        return importedLeafs
예제 #6
0
    def _ensureReadableSystem(self):
        """
        Make sure, self._archiveFileSystem contains a valid readable file system. If
        none is present, the corresponding ZIP file will be downloaded.
        """

        if self._fileSystem is None:
            key = self._rootItem.path + str(self._index)
            if key in _temporaryFileMap:
                self._fileSystem = _temporaryFileMap[key][1]
            else:
                fd, path = mkstemp()
                fileHandle = os.fdopen(fd, "w+b")
                inStream = self._rootItem.dataPersister.retrieveData(
                    self._index)
                try:
                    block = inStream.read(_BLOCK_SIZE)
                    while len(block) > 0:
                        fileHandle.write(block)
                        block = inStream.read(_BLOCK_SIZE)
                        while len(block) > 0:
                            fileHandle.write(block)
                            block = inStream.read(_BLOCK_SIZE)
                    fileHandle.close()
                except (OSError, IOError), error:
                    reason = os.strerror(error.errno or 0)
                    raise ItemError("Cannot retrieve archive.\nReason: '%s'" %
                                    reason)
                else:
                    config = BaseConfiguration('arch:' + path)
                    _log.debug("Downloaded %s to %s." %
                               (self._rootItem.path, path))
                    self._fileSystem = FileSystem(config)
                    _temporaryFileMap[key] = (path, self._fileSystem)
예제 #7
0
    def testDelete(self):
        """ Test for the delete method. """

        item_support.delete("")

        self._itemMock.error = ItemError("")
        self.assertRaises(ItemSupportError, item_support.delete, "")
예제 #8
0
    def testCreateLink(self):
        """ Test for the createLink method. """

        item_support.createLink("", "")

        self._itemMock.methodNameResultMap = {"create": (None, ItemError(""))}
        self.assertRaises(ItemSupportError, item_support.createLink, "", "")
예제 #9
0
    def testRefresh(self):
        """ Test for the refresh method. """

        item_support.refresh("")

        self._itemMock.error = ItemError("")
        self.assertRaises(ItemSupportError, item_support.refresh, "")
예제 #10
0
    def _performFileActionWin32(self, item, command):
        """ Performs the given command on the specific file. """
        # pylint: disable=E1101
        # E1101: Pylint cannot resolve specific win32 modules.

        localContentPath, alreadyLocal = self._getContent(item)
        print localContentPath, alreadyLocal
        if not alreadyLocal and len(
                self._checkUntilClosedWorker) == self._MAX_WORKER_THREADS:
            errorMessage = "The maximum number (%i) of parallel opened editors " % self._MAX_WORKER_THREADS \
                           + "has been reached. Please close at least one external application."
            raise ItemError(errorMessage)

        fMask = 0
        if not alreadyLocal:
            fMask = shellcon.SEE_MASK_NOCLOSEPROCESS
        try:
            result = shell.ShellExecuteEx(fMask, 0, command, localContentPath,
                                          "", "", 1)
        except pywintypes.error:
            return
        else:
            if not alreadyLocal:
                workerId = str(result["hProcess"])
                worker = startNewQtThread(
                    self._checkUntilClosed,
                    self._createCheckUntilClosedCallback(workerId),
                    result["hProcess"], command == self._OPEN_COMMAND, item,
                    localContentPath)
                self._checkUntilClosedWorker[workerId] = worker
예제 #11
0
    def testStoreData(self):
        """ Test for the storeData method. """

        item_support.storeData("", "")

        self._itemMock.error = ItemError("")
        self.assertRaises(ItemSupportError, item_support.storeData, "", "")
예제 #12
0
    def testRetrieveData(self):
        """ Test for the retrieveData method. """

        item_support.retrieveData("")

        self._itemMock.error = ItemError("")
        self.assertRaises(ItemSupportError, item_support.retrieveData, "")
예제 #13
0
    def create(self, properties):
        """ @see: L{ItemBase.create<datafinder.core.item.base.ItemBase.create>} """

        if self._linkTarget is None:
            raise ItemError(
                "Cannot create link because the link target is missing.")
        else:
            ItemBase.create(self, properties)
            try:
                if not self.fileStorer.exists():
                    self.fileStorer.createLink(self._linkTarget.fileStorer)
                    self._refreshProperties()
            except PersistenceError, error:
                raise ItemError("Unable to create leaf item.\nReason:'%s'" %
                                error.message)
            else:
예제 #14
0
 def testCreate(self):
     """ Test creation method of the archive data persister. """
     
     self._persister.create()
     
     self._baseDataPersisterMock.error = ItemError("Already exists.")
     self.assertRaises(ItemError, self._persister.create)
예제 #15
0
    def testCreateCollection(self):
        """ Test for the createCollection method. """

        item_support.createCollection("", dict())

        self._itemMock.methodNameResultMap = {"create": (None, ItemError(""))}
        self.assertRaises(ItemSupportError, item_support.createCollection, "",
                          dict())
예제 #16
0
    def testSearch(self):
        """ Test for the search method. """

        self._itemMock.value = list()
        item_support.search("", "")

        self._itemMock.error = ItemError("")
        self.assertRaises(ItemSupportError, item_support.search, "", "")
예제 #17
0
    def performImport(self,
                      source,
                      targetCollection,
                      newSourceName=None,
                      defaultProperties=None,
                      copyData=True,
                      ignoreLinks=False,
                      determinePropertiesCallback=None):
        """
        This method initiates the copy process and starts walking the source creating a
        new node in the destination tree for each item it passes.
        
        @param source: The item that should be imported.
        @type source: L{ItemBase<datafinder.core.item.base.ItemBase>}
        @param targetCollection: The collection that should afterwards contain the copy.
        @type targetCollection: L{ItemCollection<datafinder.core.item.collection.ItemCollection>}
        @param newSourceName: Optional new name of the source item. Default: C{None}
        @type newSourceName: C{unicode}
        @param defaultProperties: Optional list of properties which are set for every item. Default: C{None}
        @type defaultProperties: C{list} of L{Property<datafinder.core.item.property.Property>}
        @param copyData: Flag indicating whether data has to be copied or not.
        @type copyData: C{bool}
        @param ignoreLinks: Flag indicating the links are ignored during import. Default: C{False}
        @type ignoreLinks: C{bool}
        @param determinePropertiesCallback: Function determining properties used when importing a specific item.
        @type: determinePropertiesCallback: C{callable} using an item description as input and returns a dictionary
                                            describing the properties.
    
        
        @raise ItemError: Indicating errors during import.
        """

        self._pwd = targetCollection
        self._deferredLinks = list()
        self._destinationRootPath = targetCollection.path
        self._itemFactory = targetCollection.itemFactory
        self._newSourceName = newSourceName
        self._defaultProperties = defaultProperties
        self._source = source
        self._copyData = copyData
        self.importedLeafs = list()
        self._ignoreLinks = ignoreLinks
        self._determinePropertiesCallback = determinePropertiesCallback

        self.walk(source)

        missingDefferedLinkPaths = list()
        for source, importName, destinationParent in self._deferredLinks:
            try:
                self._copyLink(source, importName, destinationParent)
            except ItemError:
                missingDefferedLinkPaths.append(source.path)

        if len(missingDefferedLinkPaths) > 0:
            errorMessage = "The following links could not be imported:"
            for linkPath in missingDefferedLinkPaths:
                errorMessage += "\n" + linkPath
            raise ItemError(errorMessage)
예제 #18
0
 def _determineTemporaryFilePath():
     """ Determines a temporary file path and returns it. """
     
     try:
         tmpFile = NamedTemporaryFile()
         tmpFile.close()
     except (OSError, IOError):
         raise ItemError("Cannot determine temporary file name.")
     else:
         return tmpFile.name
예제 #19
0
    def create(self):
        """ Creates the file resource on separated storage system under the path of the item. """

        if not self._fileStorer.exists():
            self._createParentCollection(self._fileStorer.parent)
            self._fileStorer.createResource()
        else:
            errorMessage = "The data persister '%s' does already exist." % (
                self._fileStorer.identifier)
            raise ItemError(errorMessage)
예제 #20
0
    def testWalk(self):
        """ Tests the walk method. """

        self._repositoryMock.value = [
            SimpleMock(path="/"),
            SimpleMock(path="/test")
        ]
        self.assertEquals(item_support.walk("/"), ["/", "/test"])

        self._repositoryMock.error = ItemError("")
        self.assertRaises(ItemSupportError, item_support.walk, "")
예제 #21
0
    def create(self):
        """ 
        Initially creates the referenced file resource on the separated storage system. 
        Additionally, sets the content identifier property in the item properties.
        This is required to identify the resource on the separated storage system. 
        """

        self._prepareAction()
        if self._fileStorer.exists():
            raise ItemError("The unique identifier '%s' generated for item '%s' does already exist." \
                            % (self._fileStorer.name, self._item.path))
        else:
            self._fileStorer.createResource()
            propertyDefinition = self._propertyRegistry.getPropertyDefinition(
                CONTENT_IDENTIFIER_ID)
            self._item.updateProperties(
                [Property(propertyDefinition, self._fileStorer.name)])
            if not CONTENT_IDENTIFIER_ID in self._item.properties:
                raise ItemError("Unable to set the unique identifier property " \
                                + "to '%s' for item '%s'." % (self._fileStorer.name, self._item.path))
예제 #22
0
 def create(self, path, parent=None, fileStorer=None):
     """
     Returns an item for the given path. If it does not exist
     an error is raised.
     
     @param path: Path relative to the root item. E.g. "/a/b/c".
     @type path: C{unicode}
     
     @return: An item.
     @rtype: L{ItemBase<datafinder.core.item.base.ItemBase>}
     
     @raise ItemError: Raised when the item does not exist.
     """
     
     try:
         if fileStorer is None \
         and path not in self._itemCache:
             fileStorer = self._fileSystem.createFileStorer(path)
         elif fileStorer is not None:
             path = fileStorer.identifier
         if path in self._itemCache:
             item = self._itemCache[path]
             if not parent is None:
                 item.parent = parent
             return item
         
         if path == "/":
             item = self._createItem(ItemRoot, fileStorer, None, parent)
         else:
             if fileStorer.isCollection:
                 item = self._createItem(ItemCollection, fileStorer, None, parent)
             elif fileStorer.isLink:
                 item = self._createItem(ItemLink, fileStorer, None, parent)
             elif fileStorer.isLeaf:
                 item = self._createItem(ItemLeaf, fileStorer, None, parent)
             else:
                 raise ItemError("No valid item representation found for '%s'" % path)
     except PersistenceError, error:
         raise ItemError("Problem accessing item '%s'. Reason: '%s'" % (path, error.message))
예제 #23
0
 def _createItem(self, itemClass, fileStorer=None, name=None, parent=None):
     """ Creates the concrete item. """
     
     item = itemClass(name, fileStorer)
     item.itemFactory = self
     if not parent is None:
         if parent.hasChild(item.name):
             raise ItemError("The item '%s' already has a child '%s'." % (parent.path, item.name))
         item.parent = parent
     item._created = False
     if not parent is None:
         item._ignoreChecks = parent.ignoreChecks
     self._itemCache[item.path] = item
     return item 
예제 #24
0
    def create(self, properties):
        """ @see: L{ItemBase.create<datafinder.core.item.base.ItemBase.create>} """

        ItemBase.create(self, properties)
        try:
            if not self.fileStorer.exists():
                canStoreProperties = self.capabilities.canStoreProperties
                self.fileStorer.createResource()
                if canStoreProperties:
                    self.updateProperties(properties)
                self.dataPersister.create()
                self._refreshProperties()
        except PersistenceError, error:
            raise ItemError("Unable to create leaf item.\nReason:'%s'" %
                            error.message)
예제 #25
0
    def create(self, properties):
        """ @see: L{ItemBase.create<datafinder.core.item.base.ItemBase.create>} """

        ItemBase.create(self, properties)
        self.itemFactory.checkDatamodelConsistency(self.parent.dataType, self.dataType, self.parent.isRoot)
        
        try:
            if not self.fileStorer.exists():
                canStoreProperties = self.capabilities.canStoreProperties
                self.fileStorer.createCollection()
                if canStoreProperties:
                    self.updateProperties(properties)
                self.dataPersister.create()
                self._refreshProperties()
        except PersistenceError, error:
            raise ItemError("Unable to create collection item.\nReason:'%s'" % error.message)
예제 #26
0
 def _performFileAction(self, item, command):
     """ Performs the given command on the specific file. """
     print _isWin32
     if _isWin32:
         self._performFileActionWin32(item, command)
     else:
         if self._OPEN_COMMAND:  # Run a default viewer
             defaultViewer = os.environ.get(
                 self._DF_DEFAULT_FILE_VIEWER_ENV,
                 self._DF_DEFAULT_LINUX_VIEWER)
             localContentPath, _ = self._getContent(item)
             try:
                 subprocess.Popen((defaultViewer, localContentPath))
             except OSError, error:
                 raise ItemError("Cannot open file. Reason: '%s'" %
                                 str(error))
         else:
예제 #27
0
 def getChildren(self):
     """ @see: L{ItemBase.getChildren<datafinder.core.item.base.ItemBase.getChildren>} """
     
     if self._children is None:
         self._children = list()
         try:
             try:
                 children = self.fileStorer.getChildren()
             except PersistenceError, error:
                 self._childrenPopulated = True
                 raise ItemError(error.args)
             else:
                 for fileStorer in children:
                     try:
                         self._createItem(fileStorer)
                     except ItemError:
                         continue
예제 #28
0
    def copy(self, item):
        """ 
        Duplicates resource with the help of the data persister of the newly created target item.
        Updates the properties of the target item accordingly.
        """

        self._prepareAction()
        uniqueName = _generateUniqueIdentifier(item.uri)
        targetFileStorer = self._baseFileStorer.getChild(uniqueName)
        self._fileStorer.copy(targetFileStorer)

        propertyDefinition = self._propertyRegistry.getPropertyDefinition(
            CONTENT_IDENTIFIER_ID)
        item.updateProperties([Property(propertyDefinition, uniqueName)])
        item._dataPersister = None
        if not CONTENT_IDENTIFIER_ID in item.properties:
            raise ItemError("Unable to set the unique identifier property " \
                            + "to '%s' for item '%s'." % (uniqueName, item.path))
예제 #29
0
    def move(self, sourceIndexes, targetParentIndex, newName=None):
        """ 
        Moves the item referenced by C{sourceIndex} under the 
        item referenced by C{targetParentIndex}.
        
        @param sourceIndex: List of indexes identifying the source items.
        @type sourceIndex: C{list} of L{QModelIndex<PyQt4.QtCore.QModelIndex>}
        @param targetParentIndex: Index identifying the new parent item of the source item.
        @type targetParentIndex: L{QModelIndex<PyQt4.QtCore.QModelIndex>}
        @param newName: Optional new of the moved item.
        @type newName: C{unicode}
        
        @raise ItemError: Indicating problems on moving.
        """

        for sourceIndex in sourceIndexes:
            if sourceIndex.isValid():
                sourceItem = self._parentModel.nodeFromIndex(sourceIndex)
                targetParentItem = self._parentModel.nodeFromIndex(
                    targetParentIndex)
                if targetParentItem.path.startswith(sourceItem.path):
                    postPath = targetParentItem.path[len(sourceItem.path):]
                    if len(postPath) == 0 or postPath[0] == "/":
                        raise ItemError(
                            "Cannot move item in its own sub-structure.")
                targetName = self._repository.determineUniqueItemName(
                    newName or sourceItem.name, targetParentItem)
                try:
                    targetItem = self._createNewItem(targetName,
                                                     targetParentItem,
                                                     sourceItem.isCollection,
                                                     sourceItem.linkTarget,
                                                     sourceItem.isLink)
                    sourceItem.move(targetItem)
                except ItemError, error:
                    targetItem.invalidate()
                    raise error
                else:
                    del sourceItem
예제 #30
0
 def _performPostArchivingActions(self, sourceItem, targetItem):
     """ Performs post archiving actions. """
     
     if self._repository.configuration.isManagedRepository:
         properties = [self._repository.createProperty(ARCHIVE_ROOT_COLLECTION_ID, targetItem.path),
                       self._repository.createProperty(ARCHIVE_PART_INDEX_ID, 0)]
         failedCopiedItems = list()
         importer = Importer(_STOP_TRAVERSAL_STATES, _STOP_PROCESSING_STATES)
         for sourceItem in sourceItem.getChildren():
             try:
                 importer.performImport(sourceItem, targetItem, defaultProperties=properties, 
                                        copyData=False, ignoreLinks=True)
             except CoreError, error:
                 failedCopiedItems.append((sourceItem, error.message))
         
         if len(failedCopiedItems) > 0:
             errorMessage = "Problems occurred while performing post archiving action." \
                            + "The following items could not be copied:"
             for sourceItem, message in failedCopiedItems:
                 errorMessage += "\n" + sourceItem.path + " Reason: " + message
             raise ItemError(errorMessage)
         else:
             targetItem.refresh()