Exemplo n.º 1
0
class RemoteFilter(XMLFilter):

    def __init__(self, store, versionId, force=False):

        XMLFilter.__init__(self, None)

        self.store = store
        self.versionId = versionId
        self.force = force
        
        self._attrs = []
        self._isOn = False
        self._isSkipping = False
        
        self._txnStatus = 0
        self._lock = None
        self._buffer = cStringIO.StringIO()
        self._refBuffer = cStringIO.StringIO()
        self._keyBuffer = None
        self._document = None
        self._indexWriter = None
        self._count = 0
        
    def output(self):

        return self._isOn

    def getDocument(self):

        class doc(object):
            def __init__(self, xml):
                self._xml = xml
            def getContent(self):
                return self._xml
            
        return doc(self._document)

    def startElement(self, tag, attrs):

        if not self.errorOccurred():
            self.data = ''
            method = getattr(self, tag + 'Start', None)
            if method is not None:
                try:
                    method(attrs)
                except Exception:
                    self.saveException()
            self._attrs.append(attrs)

        XMLFilter.startElement(self, tag, attrs)

    def characters(self, data):

        self.data += data
        XMLFilter.characters(self, data)

    def cdataBlock(self, data):

        self.data += data
        XMLFilter.cdataBlock(self, data)

    def endElement(self, tag):

        if not self.errorOccurred():
            attrs = self._attrs.pop()
            method = getattr(self, tag + 'End', None)
            if method is not None:
                try:
                    method(attrs)
                except Exception:
                    self.saveException()
        else:
            if self._indexWriter is not None:
                self._indexWriter.close()
                self._indexWriter = None
            self.store.abortTransaction(self._txnStatus)
            self._txnStatus = 0
            if self._lock:
                self._lock = self.store.releaseLock(self._lock)

        XMLFilter.endElement(self, tag)

    def itemsStart(self, attrs):

        if attrs is not None and 'versionId' in attrs:
            versionId = UUID(attrs['versionId'])
            if versionId != self.versionId:
                raise ValueError, "remote version ids don't match"

        self._txnStatus = self.store.startTransaction()
        self._lock = self.store.acquireLock()

    def itemsEnd(self, attrs):

        if self._indexWriter is not None:
            self.store._index.optimizeIndex(self._indexWriter)
            self._indexWriter.close()
            self._indexWriter = None
            
        self.store.commitTransaction(self._txnStatus)
        self._txnStatus = 0
        if self._lock:
            self._lock = self.store.releaseLock(self._lock)

    def containerEnd(self, attrs):

        if not self._isSkipping:
            self.itemParent = UUID(self.data)

    def nameEnd(self, attrs):

        self.itemName = self.data

    def itemStart(self, attrs):

        self.itemUUID = UUID(attrs['uuid'])
        self.itemVersion = int(attrs['version'])

        version = self.store.getItemVersion(self.itemVersion, self.itemUUID)
        if not self.force and version == self.itemVersion:
            self._isSkipping = True
            self._isOn = False

        else:
            self._buffer.truncate(0)
            self._buffer.seek(0)
            self.generator = XMLGenerator(self._buffer)
            self.generator.startDocument()
            self._isOn = True

    def itemEnd(self, attrs):

        if not self._isSkipping:
            self.generator.endElement('item')
            self.generator.endDocument()
            self.generator = None
            self._isOn = False

            xml = self._buffer.getvalue()
            if self._document is None:
                self._document = xml

            self._count += 1
            self.store.saveItem(xml, self.itemUUID, self.itemVersion,
                                (self.itemParent, self.itemName), None, 0)

        else:
            self._isSkipping = False

    def attributeStart(self, attrs):

        if not self._isSkipping:
            self.attributeName = attrs['name']

    def refStart(self, attrs):

        if self._isSkipping:
            return 

        if attrs and 'first' in attrs:
            self._isOn = False

            self._refsUUID = UUID(attrs['uuid'])
            self._keyBuffer = self.store._refs.prepareKey(self.itemUUID,
                                                          self._refsUUID)
            self._ref = None
            self._previous = None
            self._alias = None

    def refEnd(self, attrs):

        if self._isSkipping:
            return
        
        if attrs and 'first' in attrs:
            generator = self.generator

            if self._ref is not None:
                self.store._refs.saveRef(self._keyBuffer, self._refBuffer,
                                         self.itemVersion, self._ref,
                                         self._ref, self._previous,
                                         None, self._alias)
                if self._alias is not None:
                    self.store.writeName(self.itemVersion, self._refsUUID,
                                         self._alias, self._ref)
                    
            uuid = attrs['uuid']
            del attrs['uuid']

            generator.startElement('ref', attrs)
            generator.startElement('db', None)
            generator.characters(uuid)
            generator.endElement('db')
            self._isOn = True

            self._keyBuffer.close()
            self._keyBuffer = None

        elif not self._isOn:
            uuid = UUID(self.data)

            if self._ref is not None:
                self.store._refs.saveRef(self._keyBuffer, self._refBuffer,
                                         self.itemVersion, self._ref,
                                         self._ref, self._previous,
                                         uuid, self._alias)
                if self._alias is not None:
                    self.store.writeName(self.itemVersion, self._refsUUID,
                                         self._alias, self._ref)

            self._previous = self._ref
            self._ref = uuid

            if attrs:
                self._alias = attrs.get('alias', None)
            else:
                self._alias = None

    def textStart(self, attrs):

        if not self._isSkipping:
            self._isOn = False

    def textEnd(self, attrs):

        if self._isSkipping:
            return
        
        uuid = UUID(attrs['uuid'])
        version = int(attrs['version'])
        encoding = attrs['encoding']
        compression = attrs.get('compression', None)
        store = self.store

        if encoding != 'utf-8':
            unicodeText = self.data.decode('utf-8')
            text = unicodeText.encode(encoding)
        else:
            unicodeText = None
            text = self.data

        out = store._lobs.createFile(store.lobName(uuid, version))
        if compression == 'bz2':
            out = BZ2OutputStream(out)
        elif compression == 'zlib':
            out = ZlibOutputStream(out)
        out.write(text)
        out.close()

        if attrs['indexed'] == 'True':
            if self._indexWriter is None:
                self._indexWriter = store._index.getIndexWriter()
            if unicodeText is None:
                unicodeText = text.decode(encoding)
            store._index.indexDocument(self._indexWriter,
                                       StringReader(unicodeText),
                                       uuid, self.itemUUID, self.attributeName,
                                       version)

        uuid = attrs['uuid']
        del attrs['uuid']
        attrs['type'] = 'uuid'

        self.generator.startElement('text', attrs)
        self.generator.characters(uuid)
        self._isOn = True
Exemplo n.º 2
0
class RemoteFilter(XMLFilter):
    def __init__(self, store, versionId, force=False):

        XMLFilter.__init__(self, None)

        self.store = store
        self.versionId = versionId
        self.force = force

        self._attrs = []
        self._isOn = False
        self._isSkipping = False

        self._txnStatus = 0
        self._lock = None
        self._buffer = cStringIO.StringIO()
        self._refBuffer = cStringIO.StringIO()
        self._keyBuffer = None
        self._document = None
        self._indexWriter = None
        self._count = 0

    def output(self):

        return self._isOn

    def getDocument(self):
        class doc(object):
            def __init__(self, xml):
                self._xml = xml

            def getContent(self):
                return self._xml

        return doc(self._document)

    def startElement(self, tag, attrs):

        if not self.errorOccurred():
            self.data = ''
            method = getattr(self, tag + 'Start', None)
            if method is not None:
                try:
                    method(attrs)
                except Exception:
                    self.saveException()
            self._attrs.append(attrs)

        XMLFilter.startElement(self, tag, attrs)

    def characters(self, data):

        self.data += data
        XMLFilter.characters(self, data)

    def cdataBlock(self, data):

        self.data += data
        XMLFilter.cdataBlock(self, data)

    def endElement(self, tag):

        if not self.errorOccurred():
            attrs = self._attrs.pop()
            method = getattr(self, tag + 'End', None)
            if method is not None:
                try:
                    method(attrs)
                except Exception:
                    self.saveException()
        else:
            if self._indexWriter is not None:
                self._indexWriter.close()
                self._indexWriter = None
            self.store.abortTransaction(self._txnStatus)
            self._txnStatus = 0
            if self._lock:
                self._lock = self.store.releaseLock(self._lock)

        XMLFilter.endElement(self, tag)

    def itemsStart(self, attrs):

        if attrs is not None and 'versionId' in attrs:
            versionId = UUID(attrs['versionId'])
            if versionId != self.versionId:
                raise ValueError, "remote version ids don't match"

        self._txnStatus = self.store.startTransaction()
        self._lock = self.store.acquireLock()

    def itemsEnd(self, attrs):

        if self._indexWriter is not None:
            self.store._index.optimizeIndex(self._indexWriter)
            self._indexWriter.close()
            self._indexWriter = None

        self.store.commitTransaction(self._txnStatus)
        self._txnStatus = 0
        if self._lock:
            self._lock = self.store.releaseLock(self._lock)

    def containerEnd(self, attrs):

        if not self._isSkipping:
            self.itemParent = UUID(self.data)

    def nameEnd(self, attrs):

        self.itemName = self.data

    def itemStart(self, attrs):

        self.itemUUID = UUID(attrs['uuid'])
        self.itemVersion = int(attrs['version'])

        version = self.store.getItemVersion(self.itemVersion, self.itemUUID)
        if not self.force and version == self.itemVersion:
            self._isSkipping = True
            self._isOn = False

        else:
            self._buffer.truncate(0)
            self._buffer.seek(0)
            self.generator = XMLGenerator(self._buffer)
            self.generator.startDocument()
            self._isOn = True

    def itemEnd(self, attrs):

        if not self._isSkipping:
            self.generator.endElement('item')
            self.generator.endDocument()
            self.generator = None
            self._isOn = False

            xml = self._buffer.getvalue()
            if self._document is None:
                self._document = xml

            self._count += 1
            self.store.saveItem(xml, self.itemUUID, self.itemVersion,
                                (self.itemParent, self.itemName), None, 0)

        else:
            self._isSkipping = False

    def attributeStart(self, attrs):

        if not self._isSkipping:
            self.attributeName = attrs['name']

    def refStart(self, attrs):

        if self._isSkipping:
            return

        if attrs and 'first' in attrs:
            self._isOn = False

            self._refsUUID = UUID(attrs['uuid'])
            self._keyBuffer = self.store._refs.prepareKey(
                self.itemUUID, self._refsUUID)
            self._ref = None
            self._previous = None
            self._alias = None

    def refEnd(self, attrs):

        if self._isSkipping:
            return

        if attrs and 'first' in attrs:
            generator = self.generator

            if self._ref is not None:
                self.store._refs.saveRef(self._keyBuffer, self._refBuffer,
                                         self.itemVersion, self._ref,
                                         self._ref, self._previous, None,
                                         self._alias)
                if self._alias is not None:
                    self.store.writeName(self.itemVersion, self._refsUUID,
                                         self._alias, self._ref)

            uuid = attrs['uuid']
            del attrs['uuid']

            generator.startElement('ref', attrs)
            generator.startElement('db', None)
            generator.characters(uuid)
            generator.endElement('db')
            self._isOn = True

            self._keyBuffer.close()
            self._keyBuffer = None

        elif not self._isOn:
            uuid = UUID(self.data)

            if self._ref is not None:
                self.store._refs.saveRef(self._keyBuffer, self._refBuffer,
                                         self.itemVersion, self._ref,
                                         self._ref, self._previous, uuid,
                                         self._alias)
                if self._alias is not None:
                    self.store.writeName(self.itemVersion, self._refsUUID,
                                         self._alias, self._ref)

            self._previous = self._ref
            self._ref = uuid

            if attrs:
                self._alias = attrs.get('alias', None)
            else:
                self._alias = None

    def textStart(self, attrs):

        if not self._isSkipping:
            self._isOn = False

    def textEnd(self, attrs):

        if self._isSkipping:
            return

        uuid = UUID(attrs['uuid'])
        version = int(attrs['version'])
        encoding = attrs['encoding']
        compression = attrs.get('compression', None)
        store = self.store

        if encoding != 'utf-8':
            unicodeText = self.data.decode('utf-8')
            text = unicodeText.encode(encoding)
        else:
            unicodeText = None
            text = self.data

        out = store._lobs.createFile(store.lobName(uuid, version))
        if compression == 'bz2':
            out = BZ2OutputStream(out)
        elif compression == 'zlib':
            out = ZlibOutputStream(out)
        out.write(text)
        out.close()

        if attrs['indexed'] == 'True':
            if self._indexWriter is None:
                self._indexWriter = store._index.getIndexWriter()
            if unicodeText is None:
                unicodeText = text.decode(encoding)
            store._index.indexDocument(self._indexWriter,
                                       StringReader(unicodeText), uuid,
                                       self.itemUUID, self.attributeName,
                                       version)

        uuid = attrs['uuid']
        del attrs['uuid']
        attrs['type'] = 'uuid'

        self.generator.startElement('text', attrs)
        self.generator.characters(uuid)
        self._isOn = True