Commit 0e28e647 authored by Sebastien Robin's avatar Sebastien Robin

ERP5Syncml now support synchronization by :

- files
- email
- http


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@564 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 3f1855f5
...@@ -108,19 +108,9 @@ class PublicationSynchronization(XMLSyncUtils): ...@@ -108,19 +108,9 @@ class PublicationSynchronization(XMLSyncUtils):
xml += ' </SyncBody>\n' xml += ' </SyncBody>\n'
xml += '</SyncML>\n' xml += '</SyncML>\n'
#file.write(xml)
#file.close()
else: self.sendResponse(from_url=publication.getPublicationUrl(),
pass to_url=subscriber.getSubscriptionUrl(),sync_id=publication.id,xml=xml)
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)
def PubSync(self, id, msg=None, RESPONSE=None, subscriber=None): def PubSync(self, id, msg=None, RESPONSE=None, subscriber=None):
...@@ -128,19 +118,15 @@ class PublicationSynchronization(XMLSyncUtils): ...@@ -128,19 +118,15 @@ class PublicationSynchronization(XMLSyncUtils):
This is the synchronization method for the server This is the synchronization method for the server
""" """
LOG('PubSync',0,'Starting... id: %s' % str(id)) LOG('PubSync',0,'Starting... id: %s' % str(id))
LOG('PubSync',0,'Starting... msg: %s' % str(msg))
# Read the request from the client # Read the request from the client
xml_client = None xml_client = msg
if self.email is None: if xml_client is None:
file = open('/tmp/sync_client','r') xml_client = self.readResponse(from_url='file://tmp/sync_server')
xml_client = FromXmlStream(file) LOG('PubSync',0,'Starting... msg: %s' % str(xml_client))
file.seek(0)
LOG('PubSync',0,'Starting... msg: %s' % str(file.read()))
file.close()
elif msg is not None:
xml_client = FromXml(msg)
if xml_client is not None: 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] first_node = xml_client.childNodes[1]
if first_node.nodeName != "SyncML": if first_node.nodeName != "SyncML":
......
...@@ -73,13 +73,8 @@ class SubscriptionSynchronization(XMLSyncUtils): ...@@ -73,13 +73,8 @@ class SubscriptionSynchronization(XMLSyncUtils):
xml += '</SyncML>\n' xml += '</SyncML>\n'
if self.email is None: self.sendResponse(from_url=subscription.subscription_url, to_url=subscription.publication_url,
file = open('/tmp/sync_client','w') sync_id=subscription.id, xml=xml)
file.write(xml)
file.close()
else:
self.sendMail(subscription.subscription_url, subscription.publication_url,
subscription.id, xml)
def SubSync(self, id, msg=None, RESPONSE=None): def SubSync(self, id, msg=None, RESPONSE=None):
""" """
...@@ -89,27 +84,18 @@ class SubscriptionSynchronization(XMLSyncUtils): ...@@ -89,27 +84,18 @@ class SubscriptionSynchronization(XMLSyncUtils):
LOG('SubSync',0,'starting... msg: %s' % str(msg)) LOG('SubSync',0,'starting... msg: %s' % str(msg))
has_response = 0 #check if subsync replies to this messages has_response = 0 #check if subsync replies to this messages
subscription = self.getSubscription(id)
# first synchronization if msg==None:
if self.email is None: msg = self.readResponse(sync_id=id,from_url=subscription.getSubscriptionUrl())
file = open('/tmp/sync','r') if msg==None:
if file.readlines() == []: self.SubSyncInit(self.getSubscription(id))
self.SubSyncInit(self.getSubscription(id)) has_response = 1
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()
else: else:
if msg==None: xml_client = msg
self.SubSyncInit(self.getSubscription(id)) if type(xml_client) in (type('a'),type(u'a')):
has_response = 1 xml_client = FromXml(xml_client)
else: has_response = self.SubSyncModif(self.getSubscription(id),xml_client)
xml_client = FromXml(msg)
has_response = self.SubSyncModif(self.getSubscription(id),xml_client)
if RESPONSE is not None: if RESPONSE is not None:
......
...@@ -48,6 +48,7 @@ import urllib ...@@ -48,6 +48,7 @@ import urllib
import string import string
from zLOG import * from zLOG import *
from Conduit.ERP5Conduit import ERP5Conduit from Conduit.ERP5Conduit import ERP5Conduit
class SynchronizationError( Exception ): class SynchronizationError( Exception ):
...@@ -518,22 +519,95 @@ class SynchronizationTool( UniqueObject, SimpleItem, ...@@ -518,22 +519,95 @@ class SynchronizationTool( UniqueObject, SimpleItem,
else: else:
return context.getPhysicalPath() 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 We will look at the url and we will see if we need to send mail, http
response, or just copy to a file. response, or just copy to a file.
""" """
if type(url) is type('a'): LOG('sendResponse, to_url: ',0,to_url)
if url.find('http://')==0: 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 # we will send an http response
to_encode = (('file',xml)) self.activate(activity='RAMQueue').sendHttpResponse(sync_id=sync_id,
encoded = urrlib.urlencode(to_encode) to_url=to_url,
urrlib.open(url, encoded).read() xml=xml)
elif url.find('file://')==0: 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 # we have to use local files (unit testing for example
pass elif to_url.find('mailto:')==0:
elif url.find('mailto:')==0:
# we will send an email # 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 ) InitializeClass( SynchronizationTool )
...@@ -32,10 +32,16 @@ from Products.ERP5SyncML.Subscription import Signature ...@@ -32,10 +32,16 @@ from Products.ERP5SyncML.Subscription import Signature
from xml.dom.ext.reader.Sax2 import FromXml from xml.dom.ext.reader.Sax2 import FromXml
from cStringIO import StringIO from cStringIO import StringIO
from xml.dom.ext import PrettyPrint 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 import commands
from zLOG import LOG from zLOG import LOG
class XMLSyncUtilsMixin(SyncCode): class XMLSyncUtilsMixin(SyncCode, ActiveObject):
def SyncMLHeader(self, session_id, msg_id, target, source): def SyncMLHeader(self, session_id, msg_id, target, source):
""" """
...@@ -413,22 +419,6 @@ class XMLSyncUtilsMixin(SyncCode): ...@@ -413,22 +419,6 @@ class XMLSyncUtilsMixin(SyncCode):
return subnode return subnode
return next_status 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): def getDataSubNode(self, action):
""" """
Return the node starting with <object....> of the action Return the node starting with <object....> of the action
...@@ -971,34 +961,15 @@ class XMLSyncUtils(XMLSyncUtilsMixin): ...@@ -971,34 +961,15 @@ class XMLSyncUtils(XMLSyncUtilsMixin):
xml += ' <Final/>\n' xml += ' <Final/>\n'
xml += ' </SyncBody>\n' xml += ' </SyncBody>\n'
xml += '</SyncML>\n' xml += '</SyncML>\n'
if self.email is None: if domain.domain_type == self.PUB: # We always reply
# We do not want to use email self.sendResponse(from_url=domain.publication_url, to_url=subscriber.subscription_url,
if domain.domain_type == self.PUB: # We always reply sync_id=domain.id, xml=xml)
#if (xml_confirmation,syncml_data)!=('','') or has_status_list: has_response = 1
if 1: elif domain.domain_type == self.SUB:
file = open('/tmp/sync','w') if self.checkAlert(remote_xml) or \
file.write(xml) (xml_confirmation,syncml_data)!=('','') or \
file.close() has_status_list:
has_response = 1 self.sendResponse(from_url=domain.subscription_url, to_url=domain.publication_url,
elif domain.domain_type == self.SUB : sync_id=domain.id, xml=xml)
if self.checkAlert(remote_xml) or \ has_response = 1
(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)
return has_response return has_response
...@@ -31,7 +31,7 @@ Setting up Synchronization ...@@ -31,7 +31,7 @@ Setting up Synchronization
the publication should looks like this :: the publication should looks like this ::
id : Repository id : Repository
Publication Url : cps_server@localhost Publication Url : mailto:cps_server@localhost
Destination Path : /cps/portal_repository Destination Path : /cps/portal_repository
Query : objectValues (it will be completed automatically) Query : objectValues (it will be completed automatically)
XML Mapping : asXML XML Mapping : asXML
...@@ -39,8 +39,8 @@ Setting up Synchronization ...@@ -39,8 +39,8 @@ Setting up Synchronization
Inside the synchronization tool, the subscription should looks like this :: Inside the synchronization tool, the subscription should looks like this ::
id : Repository id : Repository
Publication Url : cps_server@localhost Publication Url : mailto:cps_server@localhost
Subscription Url : cps_client@localhost Subscription Url : mailto:cps_client@localhost
Destination Path : /cps_client/portal_repository Destination Path : /cps_client/portal_repository
Query : objectValues (it will be completed automatically) Query : objectValues (it will be completed automatically)
XML Mapping : asXML XML Mapping : asXML
......
...@@ -81,8 +81,12 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -81,8 +81,12 @@ class TestERP5SyncML(ERP5TypeTestCase):
nb_publication = 1 nb_publication = 1
nb_synchronization = 3 nb_synchronization = 3
nb_message_first_synchronization = 6 nb_message_first_synchronization = 6
subscription_url1 = 'client1@localhost' subscription_url1 = 'file://tmp/sync_client1'
subscription_url2 = 'client2@localhost' 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): def getBusinessTemplateList(self):
""" """
...@@ -128,7 +132,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -128,7 +132,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
LOG('Testing... ',0,'testAddPublication') LOG('Testing... ',0,'testAddPublication')
portal_id = self.getPortalName() portal_id = self.getPortalName()
portal_sync = self.getSynchronizationTool() 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,'', '/%s/person_server' % portal_id,'',
self.xml_mapping) self.xml_mapping)
pub = portal_sync.getPublication(self.pub_id) pub = portal_sync.getPublication(self.pub_id)
...@@ -141,7 +145,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -141,7 +145,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
LOG('Testing... ',0,'testAddSubscription1') LOG('Testing... ',0,'testAddSubscription1')
portal_id = self.getPortalId() portal_id = self.getPortalId()
portal_sync = self.getSynchronizationTool() 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.subscription_url1,'/%s/person_client1' % portal_id,'',
self.xml_mapping) self.xml_mapping)
sub = portal_sync.getSubscription(self.sub_id1) sub = portal_sync.getSubscription(self.sub_id1)
...@@ -154,7 +158,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -154,7 +158,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
LOG('Testing... ',0,'testAddSubscription2') LOG('Testing... ',0,'testAddSubscription2')
portal_id = self.getPortalId() portal_id = self.getPortalId()
portal_sync = self.getSynchronizationTool() 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.subscription_url2,'/%s/person_client2' % portal_id,'',
self.xml_mapping) self.xml_mapping)
sub = portal_sync.getSubscription(self.sub_id2) sub = portal_sync.getSubscription(self.sub_id2)
...@@ -282,7 +286,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -282,7 +286,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
to define it here because it is specific to the unit testing to define it here because it is specific to the unit testing
""" """
portal_sync = self.getSynchronizationTool() portal_sync = self.getSynchronizationTool()
portal_sync.email = None #portal_sync.email = None # XXX To be removed
subscription = portal_sync.getSubscription(id) subscription = portal_sync.getSubscription(id)
publication = None publication = None
for publication in portal_sync.getPublicationList(): for publication in portal_sync.getPublicationList():
...@@ -290,7 +294,10 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -290,7 +294,10 @@ class TestERP5SyncML(ERP5TypeTestCase):
publication = publication publication = publication
self.failUnless(publication is not None) self.failUnless(publication is not None)
# reset files, because we do sync by files # 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.write('')
file.close() file.close()
file = open('/tmp/sync','w') file = open('/tmp/sync','w')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment