diff --git a/product/ERP5SyncML/PublicationSynchronization.py b/product/ERP5SyncML/PublicationSynchronization.py index 18168d8af8fc2eef22216c5d338825a1f89b9734..1f6cbe3fccd570d94e27ab7bc07fc5688df95247 100755 --- a/product/ERP5SyncML/PublicationSynchronization.py +++ b/product/ERP5SyncML/PublicationSynchronization.py @@ -108,19 +108,9 @@ class PublicationSynchronization(XMLSyncUtils): xml += ' </SyncBody>\n' xml += '</SyncML>\n' - #file.write(xml) - #file.close() - else: - pass - - if self.email is None: - file = open('/tmp/sync','w') - file.write(xml) - file.close() - else: - self.sendMail(publication.publication_url, subscriber.subscription_url, - publication.id, xml) + self.sendResponse(from_url=publication.getPublicationUrl(), + to_url=subscriber.getSubscriptionUrl(),sync_id=publication.id,xml=xml) def PubSync(self, id, msg=None, RESPONSE=None, subscriber=None): @@ -128,19 +118,15 @@ class PublicationSynchronization(XMLSyncUtils): This is the synchronization method for the server """ LOG('PubSync',0,'Starting... id: %s' % str(id)) - LOG('PubSync',0,'Starting... msg: %s' % str(msg)) # Read the request from the client - xml_client = None - if self.email is None: - file = open('/tmp/sync_client','r') - xml_client = FromXmlStream(file) - file.seek(0) - LOG('PubSync',0,'Starting... msg: %s' % str(file.read())) - file.close() - elif msg is not None: - xml_client = FromXml(msg) + xml_client = msg + if xml_client is None: + xml_client = self.readResponse(from_url='file://tmp/sync_server') + LOG('PubSync',0,'Starting... msg: %s' % str(xml_client)) if xml_client is not None: + if type(xml_client) in (type('a'),type(u'a')): + xml_client = FromXml(xml_client) first_node = xml_client.childNodes[1] if first_node.nodeName != "SyncML": diff --git a/product/ERP5SyncML/SubscriptionSynchronization.py b/product/ERP5SyncML/SubscriptionSynchronization.py index c3edf464973f0b839000224f5a501fd1685d57fc..eb4819d90c1961977a437f77accda9f12174e0d6 100755 --- a/product/ERP5SyncML/SubscriptionSynchronization.py +++ b/product/ERP5SyncML/SubscriptionSynchronization.py @@ -73,13 +73,8 @@ class SubscriptionSynchronization(XMLSyncUtils): xml += '</SyncML>\n' - if self.email is None: - file = open('/tmp/sync_client','w') - file.write(xml) - file.close() - else: - self.sendMail(subscription.subscription_url, subscription.publication_url, - subscription.id, xml) + self.sendResponse(from_url=subscription.subscription_url, to_url=subscription.publication_url, + sync_id=subscription.id, xml=xml) def SubSync(self, id, msg=None, RESPONSE=None): """ @@ -89,27 +84,18 @@ class SubscriptionSynchronization(XMLSyncUtils): LOG('SubSync',0,'starting... msg: %s' % str(msg)) has_response = 0 #check if subsync replies to this messages + subscription = self.getSubscription(id) - # first synchronization - if self.email is None: - file = open('/tmp/sync','r') - if file.readlines() == []: - self.SubSyncInit(self.getSubscription(id)) - has_response = 1 - else: - file.seek(0) - xml_client = FromXmlStream(file) - file.seek(0) - LOG('SubSync',0,'starting... msg: %s' % str(file.read())) - has_response = self.SubSyncModif(self.getSubscription(id),xml_client) - file.close() + if msg==None: + msg = self.readResponse(sync_id=id,from_url=subscription.getSubscriptionUrl()) + if msg==None: + self.SubSyncInit(self.getSubscription(id)) + has_response = 1 else: - if msg==None: - self.SubSyncInit(self.getSubscription(id)) - has_response = 1 - else: - xml_client = FromXml(msg) - has_response = self.SubSyncModif(self.getSubscription(id),xml_client) + xml_client = msg + if type(xml_client) in (type('a'),type(u'a')): + xml_client = FromXml(xml_client) + has_response = self.SubSyncModif(self.getSubscription(id),xml_client) if RESPONSE is not None: diff --git a/product/ERP5SyncML/SynchronizationTool.py b/product/ERP5SyncML/SynchronizationTool.py index 2826b1c88f3f28ef40b2ff2b4d21e8307f811b60..699fcc77e3d5957ed716cbef9193fdf2e01dff2e 100755 --- a/product/ERP5SyncML/SynchronizationTool.py +++ b/product/ERP5SyncML/SynchronizationTool.py @@ -48,6 +48,7 @@ import urllib import string from zLOG import * + from Conduit.ERP5Conduit import ERP5Conduit class SynchronizationError( Exception ): @@ -518,22 +519,95 @@ class SynchronizationTool( UniqueObject, SimpleItem, else: return context.getPhysicalPath() - def sendResponse(self,url=None, xml=None): + security.declarePublic('sendResponse') + def sendResponse(self, to_url=None, from_url=None, sync_id=None,xml=None): """ We will look at the url and we will see if we need to send mail, http response, or just copy to a file. """ - if type(url) is type('a'): - if url.find('http://')==0: + LOG('sendResponse, to_url: ',0,to_url) + LOG('sendResponse, from_url: ',0,from_url) + LOG('sendResponse, sync_id: ',0,sync_id) + LOG('sendResponse, xml: ',0,xml) + if type(to_url) is type('a'): + if to_url.find('http://')==0: # we will send an http response - to_encode = (('file',xml)) - encoded = urrlib.urlencode(to_encode) - urrlib.open(url, encoded).read() - elif url.find('file://')==0: + self.activate(activity='RAMQueue').sendHttpResponse(sync_id=sync_id, + to_url=to_url, + xml=xml) + return None + elif to_url.find('file://')==0: + filename = to_url[len('file:/'):] + stream = file(filename,'w') + LOG('sendResponse, filename: ',0,filename) + stream.write(xml) + stream.close() # we have to use local files (unit testing for example - pass - elif url.find('mailto:')==0: + elif to_url.find('mailto:')==0: # we will send an email - pass + to_address = to_url[len('mailto:'):] + from_address = from_url[len('mailto:'):] + self.sendMail(from_address,to_address,sync_id,xml) + + security.declarePrivate('sendHttpResponse') + def sendHttpResponse(self, to_url=None, sync_id=None, xml=None): + to_encode = (('text',xml),('sync_id',sync_id)) + LOG('sendResponse, before encoding, to encode: ',0,to_encode) + encoded = urllib.urlencode(to_encode) + LOG('sendResponse, before encoding, encoded: ',0,encoded) + to_url = to_url + '/portal_synchronizations/readResponse' + to_url + #result = urllib.urlopen(to_url, encoded).read() + result = urllib.urlopen(to_url, encoded).read() + LOG('sendResponse, stop: ',0,'stopped') + + security.declarePublic('readResponse') + def readResponse(self, text=None, sync_id=None, to_url=None, from_url=None): + """ + We will look at the url and we will see if we need to send mail, http + response, or just copy to a file. + """ + LOG('readResponse, ',0,'starting') + LOG('readResponse, sync_id: ',0,sync_id) + if text is not None: + LOG('readResponse, message: ',0,text) + # Get the target and then find the corresponding publication or + # Subscription + xml = FromXml(text) + url = '' + for subnode in self.getElementNodeList(xml): + if subnode.nodeName == 'SyncML': + for subnode1 in self.getElementNodeList(subnode): + if subnode1.nodeName == 'SyncHdr': + for subnode2 in self.getElementNodeList(subnode1): + if subnode2.nodeName == 'Target': + url = subnode2.childNodes[0].data + LOG('readResponse, url: ',0,url) + for publication in self.getPublicationList(): + if publication.getPublicationUrl()==url: + self.PubSync(sync_id,xml) + return None + for subscription in self.getSubscriptionList(): + if subscription.getSubscriptionUrl()==url: + self.SubSync(sync_id,xml) + return None + + + # we use from only if we have a file + elif type(from_url) is type('a'): + if from_url.find('file://')==0: + try: + filename = from_url[len('file:/'):] + stream = file(filename,'r') + LOG('readResponse, filename: ',0,filename) + xml = stream.read() + #stream.seek(0) + #LOG('readResponse',0,'Starting... msg: %s' % str(stream.read())) + except IOError: + LOG('readResponse, cannot read file: ',0,filename) + xml = None + if xml is not None and len(xml)==0: + xml = None + return xml InitializeClass( SynchronizationTool ) diff --git a/product/ERP5SyncML/XMLSyncUtils.py b/product/ERP5SyncML/XMLSyncUtils.py index c3ffc6a675afc523657e22ba25becbd82f82c32d..3a3c4f627024541fa0d38ce5faab29e5f2fc7c0e 100755 --- a/product/ERP5SyncML/XMLSyncUtils.py +++ b/product/ERP5SyncML/XMLSyncUtils.py @@ -32,10 +32,16 @@ from Products.ERP5SyncML.Subscription import Signature from xml.dom.ext.reader.Sax2 import FromXml from cStringIO import StringIO from xml.dom.ext import PrettyPrint +try: + from Products.CMFActivity.ActiveObject import ActiveObject +except ImportError: + LOG('XMLSyncUtils',0,"Can't import ActiveObject") + class ActiveObject: + pass import commands from zLOG import LOG -class XMLSyncUtilsMixin(SyncCode): +class XMLSyncUtilsMixin(SyncCode, ActiveObject): def SyncMLHeader(self, session_id, msg_id, target, source): """ @@ -413,22 +419,6 @@ class XMLSyncUtilsMixin(SyncCode): return subnode return next_status -# def getActionObjectId(self, action): -# """ -# XXX Deprecated -# Return the id of the object described by the action -# """ -# for subnode in action.childNodes: -# if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == 'Item': -# for subnode2 in subnode.childNodes: -# if subnode2.nodeType == subnode2.ELEMENT_NODE and subnode2.nodeName == 'Data': -# for subnode3 in subnode2.childNodes: -# if subnode3.nodeType == subnode3.ELEMENT_NODE and subnode3.nodeName == 'object': -# for subnode4 in subnode3.childNodes: -# if subnode4.nodeType == subnode4.ELEMENT_NODE and subnode4.nodeName == 'id': -# return str(subnode4.childNodes[0].data) - #return subnode4.childNodes[0].data - def getDataSubNode(self, action): """ Return the node starting with <object....> of the action @@ -971,34 +961,15 @@ class XMLSyncUtils(XMLSyncUtilsMixin): xml += ' <Final/>\n' xml += ' </SyncBody>\n' xml += '</SyncML>\n' - if self.email is None: - # We do not want to use email - if domain.domain_type == self.PUB: # We always reply - #if (xml_confirmation,syncml_data)!=('','') or has_status_list: - if 1: - file = open('/tmp/sync','w') - file.write(xml) - file.close() - has_response = 1 - elif domain.domain_type == self.SUB : - if self.checkAlert(remote_xml) or \ - (xml_confirmation,syncml_data)!=('','') or \ - has_status_list: - file = open('/tmp/sync_client','w') - has_response = 1 - file.write(xml) - file.close() - else: - # We use email - if domain.domain_type == self.PUB: # We always reply - #if (xml_confirmation,syncml_data)!=('','') or has_status_list: - if 1: - self.sendMail(domain.publication_url, subscriber.subscription_url, - domain.id, xml) - elif domain.domain_type == self.SUB: - if self.checkAlert(remote_xml) or \ - (xml_confirmation,syncml_data)!=('','') or \ - has_status_list: - self.sendMail(domain.subscription_url, domain.publication_url, - domain.id, xml) + if domain.domain_type == self.PUB: # We always reply + self.sendResponse(from_url=domain.publication_url, to_url=subscriber.subscription_url, + sync_id=domain.id, xml=xml) + has_response = 1 + elif domain.domain_type == self.SUB: + if self.checkAlert(remote_xml) or \ + (xml_confirmation,syncml_data)!=('','') or \ + has_status_list: + self.sendResponse(from_url=domain.subscription_url, to_url=domain.publication_url, + sync_id=domain.id, xml=xml) + has_response = 1 return has_response diff --git a/product/ERP5SyncML/help/install.stx b/product/ERP5SyncML/help/install.stx index d6691b6e3ccc6b51216f31d4b67c9c87fbb55948..e143565ec873cf9941497cbb07778de6d2e335e0 100755 --- a/product/ERP5SyncML/help/install.stx +++ b/product/ERP5SyncML/help/install.stx @@ -31,7 +31,7 @@ Setting up Synchronization the publication should looks like this :: id : Repository - Publication Url : cps_server@localhost + Publication Url : mailto:cps_server@localhost Destination Path : /cps/portal_repository Query : objectValues (it will be completed automatically) XML Mapping : asXML @@ -39,8 +39,8 @@ Setting up Synchronization Inside the synchronization tool, the subscription should looks like this :: id : Repository - Publication Url : cps_server@localhost - Subscription Url : cps_client@localhost + Publication Url : mailto:cps_server@localhost + Subscription Url : mailto:cps_client@localhost Destination Path : /cps_client/portal_repository Query : objectValues (it will be completed automatically) XML Mapping : asXML diff --git a/product/ERP5SyncML/tests/testERP5SyncML.py b/product/ERP5SyncML/tests/testERP5SyncML.py index 5194abd86883d2391c077bf5a4be6f1148a7d56e..d033cf115e438134a834c20d28a4090d17bae96b 100755 --- a/product/ERP5SyncML/tests/testERP5SyncML.py +++ b/product/ERP5SyncML/tests/testERP5SyncML.py @@ -81,8 +81,12 @@ class TestERP5SyncML(ERP5TypeTestCase): nb_publication = 1 nb_synchronization = 3 nb_message_first_synchronization = 6 - subscription_url1 = 'client1@localhost' - subscription_url2 = 'client2@localhost' + subscription_url1 = 'file://tmp/sync_client1' + subscription_url2 = 'file://tmp/sync_client2' + publication_url = 'file://tmp/sync_server' + #publication_url = 'server@localhost' + #subscription_url1 = 'client1@localhost' + #subscription_url2 = 'client2@localhost' def getBusinessTemplateList(self): """ @@ -128,7 +132,7 @@ class TestERP5SyncML(ERP5TypeTestCase): LOG('Testing... ',0,'testAddPublication') portal_id = self.getPortalName() portal_sync = self.getSynchronizationTool() - portal_sync.manage_addPublication(self.pub_id,'server@localhost', + portal_sync.manage_addPublication(self.pub_id,self.publication_url, '/%s/person_server' % portal_id,'', self.xml_mapping) pub = portal_sync.getPublication(self.pub_id) @@ -141,7 +145,7 @@ class TestERP5SyncML(ERP5TypeTestCase): LOG('Testing... ',0,'testAddSubscription1') portal_id = self.getPortalId() portal_sync = self.getSynchronizationTool() - portal_sync.manage_addSubscription(self.sub_id1,'server@localhost', + portal_sync.manage_addSubscription(self.sub_id1,self.publication_url, self.subscription_url1,'/%s/person_client1' % portal_id,'', self.xml_mapping) sub = portal_sync.getSubscription(self.sub_id1) @@ -154,7 +158,7 @@ class TestERP5SyncML(ERP5TypeTestCase): LOG('Testing... ',0,'testAddSubscription2') portal_id = self.getPortalId() portal_sync = self.getSynchronizationTool() - portal_sync.manage_addSubscription(self.sub_id2,'server@localhost', + portal_sync.manage_addSubscription(self.sub_id2,self.publication_url, self.subscription_url2,'/%s/person_client2' % portal_id,'', self.xml_mapping) sub = portal_sync.getSubscription(self.sub_id2) @@ -282,7 +286,7 @@ class TestERP5SyncML(ERP5TypeTestCase): to define it here because it is specific to the unit testing """ portal_sync = self.getSynchronizationTool() - portal_sync.email = None + #portal_sync.email = None # XXX To be removed subscription = portal_sync.getSubscription(id) publication = None for publication in portal_sync.getPublicationList(): @@ -290,7 +294,10 @@ class TestERP5SyncML(ERP5TypeTestCase): publication = publication self.failUnless(publication is not None) # reset files, because we do sync by files - file = open('/tmp/sync_client','w') + file = open('/tmp/sync_client1','w') + file.write('') + file.close() + file = open('/tmp/sync_client2','w') file.write('') file.close() file = open('/tmp/sync','w')