[Erp5-report] r8963 - /erp5/trunk/utils/ooodoc_server/
nobody at svn.erp5.org
nobody at svn.erp5.org
Tue Aug 1 14:30:52 CEST 2006
Author: bartek
Date: Tue Aug 1 14:30:41 2006
New Revision: 8963
URL: http://svn.erp5.org?rev=8963&view=rev
Log:
Initial import
Added:
erp5/trunk/utils/ooodoc_server/
erp5/trunk/utils/ooodoc_server/README
erp5/trunk/utils/ooodoc_server/config.py
erp5/trunk/utils/ooodoc_server/factory.py
erp5/trunk/utils/ooodoc_server/lib.py
erp5/trunk/utils/ooodoc_server/mimemapper.py
erp5/trunk/utils/ooodoc_server/pool.py
erp5/trunk/utils/ooodoc_server/runserw.py (with props)
erp5/trunk/utils/ooodoc_server/runserw.sh (with props)
erp5/trunk/utils/ooodoc_server/serw.py (with props)
erp5/trunk/utils/ooodoc_server/start.py (with props)
erp5/trunk/utils/ooodoc_server/start.sh (with props)
erp5/trunk/utils/ooodoc_server/test_server.py
erp5/trunk/utils/ooodoc_server/test_worker.py
erp5/trunk/utils/ooodoc_server/worker.py
Added: erp5/trunk/utils/ooodoc_server/README
URL: http://svn.erp5.org/erp5/trunk/utils/ooodoc_server/README?rev=8963&view=auto
==============================================================================
--- erp5/trunk/utils/ooodoc_server/README (added)
+++ erp5/trunk/utils/ooodoc_server/README Tue Aug 1 14:30:41 2006
@@ -1,0 +1,45 @@
+DESCRIPTION
+
+A server for converting docs from other formats to OOo, generating pdf files, keeping unchangeable snapshots in pdf format, getting and setting metadata. To be used together with ERP5 Document business template, although can be run standalone for any other client application.
+
+Server tested using OOo 2.0.2, and everything works except for generating pdf - this is a known issue and hopefully will be fixed in the next release of OOo.
+
+It returns a file in a desired format; html files are zipped because they often consist of more than one file.
+
+INSTALLATION:
+
+Patch your SimpleXMLRPCServer.py with this:
+https://sourceforge.net/tracker/?func=detail&atid=305470&aid=893642&group_id=5470
+
+Install OOo 2.0.3 from RPMs.
+
+SETUP:
+
+Done in config.py. Important parts are:
+
+- paths to programs
+
+- loadtime - how long it takes for your machine to load an OOo instance; this is important because when it is restarted, a script spawns a new instance and then has to wait before trying to connect
+
+- timeout - when an OOo instance we called does not return for too long, we decide it has crashed; we kill it and start another one. This is the time after which we undertake this drastic action.
+
+USAGE:
+
+Start your OOo instances by running start.py
+
+Start the server by running serw.py; check the stdout and log.txt to see what is going on. If necessary, ctrl-c the server and rerun it.
+
+ CAUTION: if one of the OOo instances has been restarted because of a timeout, it dies together with the server!
+ so if you restart the server after there has been an OOo restart, rerun the start.py script.
+
+TESTING:
+
+Run test_worker.py to test the main tool.
+Run test_server.py to test communication and xmlrpc interface.
+Run test_timeout.py to check if the OOo gets properly restarted.
+
+PORTABILITY
+
+Not portable. Almost all the code can be run on any OS, except for the "rebuild" function in pool.py and pid recording in start.py. This is for killing and restarting OOo instance - done in a bit unclean way, but works. I don't know a better way to do that.
+
+BG
Added: erp5/trunk/utils/ooodoc_server/config.py
URL: http://svn.erp5.org/erp5/trunk/utils/ooodoc_server/config.py?rev=8963&view=auto
==============================================================================
--- erp5/trunk/utils/ooodoc_server/config.py (added)
+++ erp5/trunk/utils/ooodoc_server/config.py Tue Aug 1 14:30:41 2006
@@ -1,0 +1,40 @@
+#!/usr/bin/python2.4
+##############################################################################
+#
+# Copyright (c) 2002, 2006 Nexedi SARL and Contributors. All Rights Reserved.
+# Jean-Paul Smets-Solanes <jp at nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+basedir='/home/bartek/ERP/dev/ooodoc/serv/'
+serverhost='127.0.0.1'
+port=8080
+unopath='/opt/openoffice.org2.0/program'
+logfile=basedir+'/log.txt'
+number=1
+loadtime=20 # time we have to gave one OOo to load in restart
+
+timeout=20 # seconds to wait before killing and restarting OOo instance
+
+# vim: syntax=python filetype=python
Added: erp5/trunk/utils/ooodoc_server/factory.py
URL: http://svn.erp5.org/erp5/trunk/utils/ooodoc_server/factory.py?rev=8963&view=auto
==============================================================================
--- erp5/trunk/utils/ooodoc_server/factory.py (added)
+++ erp5/trunk/utils/ooodoc_server/factory.py Tue Aug 1 14:30:41 2006
@@ -1,0 +1,56 @@
+#!/usr/bin/python
+##############################################################################
+#
+# Copyright (c) 2002, 2006 Nexedi SARL and Contributors. All Rights Reserved.
+# Jean-Paul Smets-Solanes <jp at nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import os,sys,unittest
+import config
+import lib
+sys.path.append(config.unopath)
+import uno
+import worker
+
+class WorkerFactory(object):
+
+ def __init__(self):
+ self.ctxLocal=uno.getComponentContext()
+ self.smgrLocal=self.ctxLocal.ServiceManager
+ self.resolver=self.smgrLocal.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver",self.ctxLocal)
+
+ def build(self,pool,i):
+ '''create a context, bind it to next instance of OO using
+ calculated port number'''
+ print 'building',i
+ print str(2002+i)
+ ctx=self.resolver.resolve("uno:socket,host=localhost,port=%d;urp;StarOffice.ComponentContext" % (2002+i))
+ smgr=ctx.ServiceManager
+ desktop=smgr.createInstanceWithContext("com.sun.star.frame.Desktop",ctx)
+ return worker.Worker(i,desktop,pool)
+
+builder=WorkerFactory()
+
+# vim: shiftwidth=2
Added: erp5/trunk/utils/ooodoc_server/lib.py
URL: http://svn.erp5.org/erp5/trunk/utils/ooodoc_server/lib.py?rev=8963&view=auto
==============================================================================
--- erp5/trunk/utils/ooodoc_server/lib.py (added)
+++ erp5/trunk/utils/ooodoc_server/lib.py Tue Aug 1 14:30:41 2006
@@ -1,0 +1,52 @@
+#!/usr/bin/python
+##############################################################################
+#
+# Copyright (c) 2002, 2006 Nexedi SARL and Contributors. All Rights Reserved.
+# Jean-Paul Smets-Solanes <jp at nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import time,sys
+import config
+
+class WorkerException(Exception):pass
+class IllegalMimeType(WorkerException):pass
+class IllegalFormat(WorkerException):pass
+class IllegalMetaAttribute(WorkerException):pass
+class NotLoaded(WorkerException):pass
+class NotFound(WorkerException):pass
+class GenerationFailed(WorkerException):pass
+
+class ServerException(Exception):pass
+class WorkerNotAvailable(ServerException):pass
+class SetMetaFailed(ServerException):pass
+
+sv=['INFO','WARNING','ERROR','FATAL']
+def log(msg,severity=0):
+ f=open(config.logfile,'a')
+ s='%s: %s: %s\r\n' % (time.strftime('%Y-%m-%d %H:%M:%S'),sv[severity],msg)
+ f.write(s)
+ f.close()
+
+# vim: shiftwidth=2
Added: erp5/trunk/utils/ooodoc_server/mimemapper.py
URL: http://svn.erp5.org/erp5/trunk/utils/ooodoc_server/mimemapper.py?rev=8963&view=auto
==============================================================================
--- erp5/trunk/utils/ooodoc_server/mimemapper.py (added)
+++ erp5/trunk/utils/ooodoc_server/mimemapper.py Tue Aug 1 14:30:41 2006
@@ -1,0 +1,160 @@
+#!/usr/bin/python
+##############################################################################
+#
+# Copyright (c) 2002, 2006 Nexedi SARL and Contributors. All Rights Reserved.
+# Jean-Paul Smets-Solanes <jp at nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import sys
+import config
+sys.path.append(config.unopath)
+import uno
+from com.sun.star.beans import PropertyValue
+
+class MimeMapper:
+
+ types_map={
+ 'application/vnd.oasis.opendocument.text':
+ {'ext':'odt',
+ 'allowed_to':['pdf','doc','rtf','html-writer'],
+ 'allowed_from':['rtf','doc'],
+ },
+ 'application/vnd.oasis.opendocument.spreadsheet':
+ {'ext':'ods',
+ 'allowed_to':['csv','html-calc','xls','calc.pdf'],
+ 'allowed_from':['xls'],
+ },
+ 'application/vnd.oasis.opendocument.presentation':
+ {'ext':'odp',
+ 'allowed_to':['impr.pdf','ppt'],
+ 'allowed_from':['ppt'],
+ },
+ 'application/vnd.oasis.opendocument.graphics':
+ {'ext':'odg',
+ 'allowed_to':['jpg','draw.pdf'],
+ 'allowed_from':[],
+ },
+ }
+
+ property_map={
+ 'pdf':{
+ 'mime_type':None,
+ 'outprops':(PropertyValue("FilterName",0,"writer_pdf_Export",0),PropertyValue("Overwrite",0,True,0)),
+ 'label':'Pdf',
+ },
+ 'calc.pdf':{
+ 'mime_type':None,
+ 'outprops':(PropertyValue("FilterName",0,"calc_pdf_Export",0),PropertyValue("Overwrite",0,True,0)),
+ 'label':'Pdf',
+ },
+ 'impr.pdf':{
+ 'mime_type':None,
+ 'outprops':(PropertyValue("FilterName",0,"impress_pdf_Export",0),PropertyValue("Overwrite",0,True,0)),
+ 'label':'Pdf',
+ },
+ 'html-writer':{
+ 'mime_type':None,
+ 'outprops':(PropertyValue("FilterName",0,"HTML (StarWriter)",0),PropertyValue("Overwrite",0,True,0)),
+ 'label':'HTML document',
+ },
+ 'html-calc':{
+ 'mime_type':None,
+ 'outprops':(PropertyValue("FilterName",0,"HTML (StarCalc)",0),PropertyValue("Overwrite",0,True,0)),
+ 'label':'HTML document',
+ },
+ 'doc':{
+ 'mime_type':'application/msword',
+ 'outprops':(PropertyValue("FilterName",0,"MS Word 97",0),PropertyValue("Overwrite",0,True,0)),
+ 'label':'MS Word doc',
+ },
+ 'rtf':{
+ 'mime_type':'application/rtf',
+ 'outprops':(PropertyValue("FilterName",0,"Rich Text Format",0),PropertyValue("Overwrite",0,True,0)),
+ 'label':'Rich Text Format',
+ },
+ 'xls':{
+ 'mime_type':'application/vnd.ms-excel',
+ 'outprops':(PropertyValue("FilterName",0,"MS Excel 97",0),PropertyValue("Overwrite",0,True,0)),
+ 'label':'MS Excel spreadsheet',
+ },
+ 'csv':{
+ 'mime_type':None,
+ 'outprops':(PropertyValue("FilterName",0,"Text - txt - csv (StarCalc)",0),PropertyValue("Overwrite",0,True,0)),
+ 'label':'comma separated',
+ },
+ 'ppt':{
+ 'mime_type':'application/vnd.ms-powerpoint',
+ 'outprops':(PropertyValue("FilterName",0,"MS PowerPoint 97",0),PropertyValue("Overwrite",0,True,0)),
+ 'label':'Powerpoint presentation',
+ },
+ 'jpg':{
+ 'mime_type':None,
+ 'outprops':(PropertyValue("FilterName",0,"draw_jpg_Export",0),PropertyValue("Overwrite",0,True,0)),
+ },
+ 'draw.pdf':{
+ 'mime_type':None,
+ 'outprops':(PropertyValue("FilterName",0,"draw_pdf_Export",0),PropertyValue("Overwrite",0,True,0)),
+ },
+ }
+
+ def __init__(self):
+ # what can we convert from - [{non_OOo_mime_type:{'ext':target_OOo_extensions,'mime_type':target_OOo_mimetype'}},]
+ self.convertable={}
+ for k,v in self.types_map.iteritems():
+ for allowed in v['allowed_from']:
+ pm=self.property_map[allowed]
+ if pm['mime_type'] is None:
+ raise Exception('doc to convert from must have a mimetype')
+ self.convertable[pm['mime_type']]={'ext':v['ext'],'mime_type':k}
+ # convertions to - [{OOo_mime_type:{type:{'ext':target_non_OOo_extension,'outprops':properties'}},]
+ self.generable={}
+ for k,v in self.types_map.iteritems():
+ pm={}
+ for ext in v['allowed_to']:
+ props={'ext':ext,'outprops':self.property_map[ext]['outprops']}
+ pm[ext]=props
+ self.generable[k]=pm
+ # for convenience - lists of OOo and non-OOo mimetypes
+ self.ooo_types=self.types_map.keys()
+ self.non_ooo_types=[v['mime_type'] for v in self.property_map.values() if v['mime_type'] is not None]
+
+ def getAllowedTo(self,mimetype):
+ return [(type,self.property_map[type].get('label',type)) for type in self.types_map[mimetype]['allowed_to']]
+
+mimemapper=MimeMapper()
+
+if __name__=='__main__':
+ print mimemapper.getAllowedTo('application/vnd.oasis.opendocument.text')
+ print 'ooo_types',mimemapper.ooo_types
+ print 'non_ooo_types',mimemapper.non_ooo_types
+ #print mimemapper.convertable
+ #for k,v in mimemapper.generable.iteritems():
+ #print k
+ #print v
+
+
+
+
+# vim: shiftwidth=2
Added: erp5/trunk/utils/ooodoc_server/pool.py
URL: http://svn.erp5.org/erp5/trunk/utils/ooodoc_server/pool.py?rev=8963&view=auto
==============================================================================
--- erp5/trunk/utils/ooodoc_server/pool.py (added)
+++ erp5/trunk/utils/ooodoc_server/pool.py Tue Aug 1 14:30:41 2006
@@ -1,0 +1,118 @@
+#!/usr/bin/python
+##############################################################################
+#
+# Copyright (c) 2002, 2006 Nexedi SARL and Contributors. All Rights Reserved.
+# Jean-Paul Smets-Solanes <jp at nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+
+import lib,threading,os,time,sys
+import config
+import factory,start
+
+class Pool(object):
+ '''manages a pool of worker object; number of workers is
+ set in config directs requests to the first available
+ worker uses semaphore to hold request untill one is
+ available '''
+
+ total=config.number
+ inst={}
+ timers={}
+
+ def __init__(self):
+ '''set up semaphore, make workers'''
+ self.sem=threading.Semaphore(self.total)
+ for i in range(self.total):
+ self._mkWorker(i)
+
+ def acquire(self):
+ self.sem.acquire()
+
+ def release(self,i):
+ self.sem.release()
+ self.timers[i].cancel()
+ del(self.timers[i])
+
+ def getWorker(self):
+ '''
+ returns first available instance, marks it as busy etc.
+ we use index to name temporary files which are per
+ worker. IDEA: use additional threads to test OOo instance
+ that should be available and timeout if there is no
+ response or do sthg else to keep semaphore in sync if OOo
+ crashes, restart OOo instances etc.
+ '''
+ w=None
+ self.acquire() # wait untill something is free
+ for idx in range(self.total):
+ if not self.inst[idx].busy:
+ w=self.inst[idx]
+ break
+ if w is None: # means semaphore is out of sync with pool
+ raise lib.WorkerNotAvailable('sorry')
+ w.setBusy()
+ self.timers[idx]=threading.Timer(config.timeout,self.rebuild(idx))
+ self.timers[idx].start()
+ return idx,w
+
+ def rebuild(self,i):
+ '''
+ triggered by a timer thread in case worker takes too long
+ rebuilds the worker instance
+ '''
+ def _rebuild():
+ """
+ would be best to kill only one instance, but killing pid returned by
+ spawn leaves child process running, and killing by process group id
+ kills everything because all instances have the same pgid
+ (the one that start.py had).
+ Worse still, after restart instances have the same pgid as the server,
+ so we'd kill the server along with them.
+ So, we hack - we do "ps" to find parent process and explicitly kill both
+ it is not very portable, but I don't have a better idea...
+ """
+ print 'that takes too long!'
+ lib.log('instance '+str(i)+' not responding - restarting',3)
+ pidfile=os.path.join(config.basedir,'pid_%d' % i)
+ pid=int(open(pidfile).read())
+ pids=os.popen('ps -A -o pid,ppid | grep %d | cut -f 1 -d " "' % pid)
+ for p in pids:
+ lib.log('killing pid '+p.strip(),3)
+ os.kill(int(p),9)
+ start.startInstance(i)
+ # give it time to load before we try to connect
+ time.sleep(config.loadtime)
+ self._mkWorker(i)
+ return _rebuild
+
+ def _mkWorker(self,i):
+ if self.timers.has_key(i):
+ del(self.timers[i])
+ self.inst[i]=(factory.builder.build(self,i))
+
+pool=Pool()
+
+# vim: shiftwidth=2
Added: erp5/trunk/utils/ooodoc_server/runserw.py
URL: http://svn.erp5.org/erp5/trunk/utils/ooodoc_server/runserw.py?rev=8963&view=auto
==============================================================================
--- erp5/trunk/utils/ooodoc_server/runserw.py (added)
+++ erp5/trunk/utils/ooodoc_server/runserw.py Tue Aug 1 14:30:41 2006
@@ -1,0 +1,50 @@
+#!/usr/bin/python
+##############################################################################
+#
+# Copyright (c) 2002, 2006 Nexedi SARL and Contributors. All Rights Reserved.
+# Jean-Paul Smets-Solanes <jp at nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import sys
+from serw import *
+
+
+if __name__=='__main__':
+ proc=Procesor()
+ try:
+ debug=(sys.argv[1]=='debug')
+ except IndexError:
+ debug=False
+ if debug:
+ d=open('test.odt').read()
+ print proc.run_makepdf('test.odt',base64.encodestring(d))[0]
+ #d=open('doc/test.doc').read()
+ #print proc.run_setmetadata('test.odt',base64.encodestring(d),{'title':'zz'})[0]
+ else:
+ ser=MySerw((config.serverhost,config.port),allow_none=True)
+ ser.register_instance(proc)
+ ser.serve_forever()
+
+# vim: shiftwidth=2
Propchange: erp5/trunk/utils/ooodoc_server/runserw.py
------------------------------------------------------------------------------
svn:executable =
Added: erp5/trunk/utils/ooodoc_server/runserw.sh
URL: http://svn.erp5.org/erp5/trunk/utils/ooodoc_server/runserw.sh?rev=8963&view=auto
==============================================================================
--- erp5/trunk/utils/ooodoc_server/runserw.sh (added)
+++ erp5/trunk/utils/ooodoc_server/runserw.sh Tue Aug 1 14:30:41 2006
@@ -1,0 +1,3 @@
+#!/bin/bash
+
+python /var/lib/ooodoc_server/runserw.py
Propchange: erp5/trunk/utils/ooodoc_server/runserw.sh
------------------------------------------------------------------------------
svn:executable =
Added: erp5/trunk/utils/ooodoc_server/serw.py
URL: http://svn.erp5.org/erp5/trunk/utils/ooodoc_server/serw.py?rev=8963&view=auto
==============================================================================
--- erp5/trunk/utils/ooodoc_server/serw.py (added)
+++ erp5/trunk/utils/ooodoc_server/serw.py Tue Aug 1 14:30:41 2006
@@ -1,0 +1,182 @@
+#!/usr/bin/python
+##############################################################################
+#
+# Copyright (c) 2002, 2006 Nexedi SARL and Contributors. All Rights Reserved.
+# Jean-Paul Smets-Solanes <jp at nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+from SimpleXMLRPCServer import *
+from SocketServer import ThreadingMixIn
+import time,threading,base64,os,pdb,sys,socket,traceback
+import lib
+import config
+import pool
+
+class MySerw(ThreadingMixIn,SimpleXMLRPCServer):
+
+ def server_bind(self):
+ self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
+ self.socket.bind(self.server_address)
+
+class Procesor(object):
+ '''main request handler, registered with the server handler
+ functions are auto-generated named run_<funcname>, args:
+ filename, data, [metadata],*args, **kwargs
+ one of the **kwargs can be format (target format, default=appropriate
+ OOo format)'''
+
+ public_funcs=('convert','getmetadata','setmetadata','generate','getmetadatatoolong')
+
+ def __init__(self):
+ self._generateFuncs()
+
+ def _generateFuncs(self):
+ for f in self.public_funcs:
+ setattr(self,'run_'+f,self._wrap(f))
+
+ def _asciify(self,s):
+ '''for clearing chars out of filenames'''
+ return ''.join([(ord(c)<128 and c) or '_' for c in s])
+
+ def _mkName(self,fname):
+ '''make a complete file name with path we save the file
+ under a derivative of its original name, mostly for
+ debugging
+ '''
+ return os.path.join(config.basedir,fname)
+
+ def convert(self,w,fname,*args,**kwargs):
+ meta,newfname=w.run_convert(fname,**kwargs)
+ return meta,newfname
+
+ def getmetadatatoolong(self,w,fname,*args,**kwargs):
+ meta=w.run_getmetadatatoolong(fname)
+ return meta,None
+
+ def getmetadata(self,w,fname,*args,**kwargs):
+ meta=w.run_getmetadata(fname)
+ return meta,None
+
+ def setmetadata(self,w,fname,meta,*args,**kwargs):
+ res=w.run_setmetadata(fname,meta)
+ if res:
+ return meta,fname
+ else:
+ raise lib.SetMetaFailed()
+
+ def generate(self,w,fname,format,**kwargs):
+ '''generate file in a desired format (provided we already
+ have an OOo file)'''
+ newfname=w.run_generate(fname,format)
+ return None,newfname
+
+ def getAllowedTargets(self,mimetype):
+ '''get list of allowed target formats from worker
+ different interface (no file), so we don't wrap it'''
+ id,w=pool.pool.getWorker()
+ try:
+ return w.getAllowedTargets(mimetype)
+ finally:
+ w.setFree()
+
+ def _pre(self,name,data):
+ '''write data to a temp file, get worker instance'''
+ id,w=pool.pool.getWorker()
+ fname='%d_%s' % (id,name) # in case we have two files of the same name
+ f=open(self._mkName(fname),'w')
+ f2=open(self._mkName('temp64'),'w')
+ f2.write(data)
+ f.write(base64.decodestring(data))
+ f.close()
+ f2.close()
+ return w,fname
+
+ def _safeRemove(self,fname):
+ '''remove a file or log warning if none exists'''
+ any=False
+ for f in os.listdir(config.basedir):
+ if f.startswith(os.path.basename(fname)): # html formats generate a number of files
+ lib.log('removing %s' % f)
+ os.remove(self._mkName(f))
+ any=True
+ if not any:
+ lib.log('no file beginning with %s' % fname,1)
+
+ def _post(self,w,fname,newfname=None):
+ '''
+ remove temp files, free worker
+ newfname only if there was convertion
+ '''
+ try:
+ # because we are in finally, things can be none
+ # if there was an exception
+ if fname is not None:
+ self._safeRemove(self._mkName(fname))
+ if newfname is not None:
+ self._safeRemove(self._mkName(newfname))
+ finally:
+ if w is not None:
+ w.setFree()
+
+ def _wrap(self,funcname):
+ '''wrap function execute _pre and _post if newfname,
+ which means there was a convertion, send data back to the
+ user
+ '''
+ def _run(name,data,meta=None,**kwargs):
+ fname=newfname=w=None # or in case of exception we get UnboundLocalError
+ try:
+ try:
+ name=self._asciify(name)
+ w,fname=self._pre(name,data)
+ format=meta # when generating, this argument is a target format (grrr...)
+ # we need to store it to figure out whether to zip
+ meta,newfname=func(w,fname,meta,**kwargs)
+ if newfname is not None:
+ try: # we can do it only if the argument is a string
+ zip=format.startswith('html') # if html, we pack the output files
+ except AttributeError:
+ zip=False
+ if zip:
+ #first delete the original
+ os.remove(self._mkName(fname))
+ zipname=self._mkName(fname+'.zip')
+ zipwildcard=self._mkName(fname+'*')
+ cmd='zip -j %s %s' % (zipname,zipwildcard)
+ res=os.system(cmd)
+ data=base64.encodestring(open(zipname).read())
+ else:
+ data=base64.encodestring(open(self._mkName(newfname)).read())
+ return (meta,data)
+ except Exception,e:
+ print e
+ traceback.print_tb(sys.exc_info()[2])
+ raise e
+ finally:
+ self._post(w,fname,newfname)
+ func=getattr(self,funcname)
+ return _run
+
+# vim: shiftwidth=2
Propchange: erp5/trunk/utils/ooodoc_server/serw.py
------------------------------------------------------------------------------
svn:executable =
Added: erp5/trunk/utils/ooodoc_server/start.py
URL: http://svn.erp5.org/erp5/trunk/utils/ooodoc_server/start.py?rev=8963&view=auto
==============================================================================
--- erp5/trunk/utils/ooodoc_server/start.py (added)
+++ erp5/trunk/utils/ooodoc_server/start.py Tue Aug 1 14:30:41 2006
@@ -1,0 +1,75 @@
+#!/usr/bin/python
+##############################################################################
+#
+# Copyright (c) 2002, 2006 Nexedi SARL and Contributors. All Rights Reserved.
+# Jean-Paul Smets-Solanes <jp at nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import os,time,sys
+import lib
+import config
+
+'''
+Starts OO instances, number defined in config First, you must install OO 2.0.2
+from RPMs; user directories user_0, user_1 etc. will be created automatically
+by OOo on startup
+'''
+
+cmdtpl='%s/soffice'
+argtpl1='--headless'
+argtpl2='-accept=socket,host=localhost,port=%d;urp;'
+argtpl3='-env:UserInstallation=$SYSUSERCONFIG/./user_%d'
+#argtpl3='-env:UserInstallation=%s/./user_%d'
+
+def startInstance(i):
+ """
+ we spawn a new process and record its pid to be able to kill it
+ if necessary
+ """
+ print str(2002+i)
+ #lib.log('starting OOo for i='+str(i))
+ cmd=cmdtpl % config.unopath
+ arg1=argtpl1
+ arg2=argtpl2 % (2002+i)
+ arg3=argtpl3 % i
+ #arg3=argtpl3 % (config.basedir,i)
+ print arg3
+ pid=os.spawnlp(os.P_NOWAIT,cmd,'soffice',arg1,arg2,arg3)
+ pidfile='%s/pid_%d' % (config.basedir,i)
+ open(pidfile,'w').write(str(pid))
+ #lib.log('OOo started, pid '+str(pid))
+
+def startAll():
+ os.system('killall soffice.bin')
+ os.system('killall soffice')
+ for i in range(config.number):
+ startInstance(i)
+ time.sleep(config.loadtime)
+
+if __name__=='__main__':
+ startAll()
+
+# vim: shiftwidth=2
+
Propchange: erp5/trunk/utils/ooodoc_server/start.py
------------------------------------------------------------------------------
svn:executable =
Added: erp5/trunk/utils/ooodoc_server/start.sh
URL: http://svn.erp5.org/erp5/trunk/utils/ooodoc_server/start.sh?rev=8963&view=auto
==============================================================================
--- erp5/trunk/utils/ooodoc_server/start.sh (added)
+++ erp5/trunk/utils/ooodoc_server/start.sh Tue Aug 1 14:30:41 2006
@@ -1,0 +1,4 @@
+#!/bin/bash
+
+
+python /var/lib/ooodoc_server/start.py
Propchange: erp5/trunk/utils/ooodoc_server/start.sh
------------------------------------------------------------------------------
svn:executable =
Added: erp5/trunk/utils/ooodoc_server/test_server.py
URL: http://svn.erp5.org/erp5/trunk/utils/ooodoc_server/test_server.py?rev=8963&view=auto
==============================================================================
--- erp5/trunk/utils/ooodoc_server/test_server.py (added)
+++ erp5/trunk/utils/ooodoc_server/test_server.py Tue Aug 1 14:30:41 2006
@@ -1,0 +1,133 @@
+#!/usr/bin/python
+##############################################################################
+#
+# Copyright (c) 2002, 2006 Nexedi SARL and Contributors. All Rights Reserved.
+# Jean-Paul Smets-Solanes <jp at nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import sys,base64,unittest
+from xmlrpclib import *
+import config
+
+enc=base64.encodestring
+dec=base64.decodestring
+
+try:
+ f=open('doc/test.odt')
+except IOError:
+ print "you need a doc subdir with appropriate documents"
+ sys.exit(1)
+
+sp=ServerProxy('http://%s:%d' % (config.serverhost,config.port),allow_none=True)
+
+class TestMetaOperations(unittest.TestCase):
+
+ def testSetGetMeta(self):
+ # setting metadata
+ mime='application/vnd.oasis.opendocument.text'
+ newmeta={'Title':'HELLOOOOOO','Reference':'blaaaaaah','MIMEType':mime}
+ data=open('doc/test.odt').read()
+ res=sp.run_setmetadata('test.odt',base64.encodestring(data),newmeta)
+ open('doc/test_changed.odt','w').write(base64.decodestring(res[1]))
+ # getting metadata back after the change
+ data=open('doc/test_changed.odt').read()
+ res=sp.run_getmetadata('test_changed.odt',base64.encodestring(data))
+ self.assertEqual(res[0]['Title'],'HELLOOOOOO')
+ self.assertEqual(res[0]['Reference'],'blaaaaaah')
+
+class TestFileOperations(unittest.TestCase):
+
+ def testConvertDoc(self):
+ data=open('doc/test.doc').read()
+ res=sp.run_convert('test.doc',base64.encodestring(data))
+ open('doc/test.odt','w').write(base64.decodestring(res[1]))
+
+ def testConvertXls(self):
+ data=open('doc/test.xls').read()
+ res=sp.run_convert('test.xls',base64.encodestring(data))
+ open('doc/test.ods','w').write(base64.decodestring(res[1]))
+
+ def testConvertPpt(self):
+ data=open('doc/test.ppt').read()
+ res=sp.run_convert('test.ppt',base64.encodestring(data))
+ open('doc/test.odp','w').write(base64.decodestring(res[1]))
+
+ def testPdfTextGeneration(self):
+ try:
+ data=open('doc/test.odt').read()
+ res=sp.run_generate('test.odt',enc(data),'pdf')
+ self.assert_(res)
+ open('doc/test.pdf','w').write(base64.decodestring(res[1]))
+ except Fault,e:
+ print e
+
+ def testPdfCalcGeneration(self):
+ try:
+ data=open('doc/test.ods').read()
+ res=sp.run_generate('test.ods',enc(data),'calc.pdf')
+ self.assert_(res)
+ open('doc/test.calc.pdf','w').write(base64.decodestring(res[1]))
+ except Fault,e:
+ print e
+
+ def testPdfImpressGeneration(self):
+ try:
+ data=open('doc/test.odp').read()
+ res=sp.run_generate('test.odp',enc(data),'impr.pdf')
+ self.assert_(res)
+ open('doc/test.impr.pdf','w').write(base64.decodestring(res[1]))
+ except Fault,e:
+ print e
+
+ def testHtmlWriterGeneration(self):
+ self.generateFile('odt','html-writer')
+
+ def testRtfGeneration(self):
+ self.generateFile('odt','rtf')
+
+ def testPptGeneration(self):
+ self.generateFile('odp','ppt')
+
+ def testDocGeneration(self):
+ self.generateFile('odt','doc')
+
+ def testHtmlCalcGeneration(self):
+ self.generateFile('ods','html-calc')
+
+ def testCsvGeneration(self):
+ self.generateFile('ods','csv')
+
+ def generateFile(self,src,ext):
+ data=open('doc/test.%s' % src).read()
+ res=sp.run_generate('test.%s' % src,enc(data),ext)
+ self.assert_(res)
+ open('doc/test.%s' % ext,'w').write(base64.decodestring(res[1]))
+
+if __name__=='__main__':
+ #unittest.main()
+ tests=(TestMetaOperations,TestFileOperations)
+ for t in tests:
+ suite=unittest.makeSuite(t)
+ unittest.TextTestRunner(verbosity=2).run(suite)
Added: erp5/trunk/utils/ooodoc_server/test_worker.py
URL: http://svn.erp5.org/erp5/trunk/utils/ooodoc_server/test_worker.py?rev=8963&view=auto
==============================================================================
--- erp5/trunk/utils/ooodoc_server/test_worker.py (added)
+++ erp5/trunk/utils/ooodoc_server/test_worker.py Tue Aug 1 14:30:41 2006
@@ -1,0 +1,137 @@
+#!/usr/bin/python
+##############################################################################
+#
+# Copyright (c) 2002, 2006 Nexedi SARL and Contributors. All Rights Reserved.
+# Jean-Paul Smets-Solanes <jp at nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import os,sys,unittest,base64
+import config
+sys.path.append(config.unopath)
+import uno
+from unohelper import Base, systemPathToFileUrl, absolutize
+#from os import getcwd
+#from os.path import splitext
+from com.sun.star.beans import PropertyValue
+from com.sun.star.beans import PropertyExistException
+from com.sun.star.task import ErrorCodeIOException
+from com.sun.star.uno import Exception as UnoException
+#from com.sun.star.io import IOException, XOutputStream
+
+from lib import *
+import worker
+
+try:
+ f=open('doc/test.doc')
+ f=open('doc/test.xls')
+ f=open('doc/test.pdf')
+ f=open('doc/test.html')
+except IOError:
+ print "you need a doc subdir with appropriate documents"
+ sys.exit(1)
+
+ctxLocal=uno.getComponentContext()
+smgrLocal=ctxLocal.ServiceManager
+resolver=smgrLocal.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver",ctxLocal)
+ctx=resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")
+smgr=ctx.ServiceManager
+desktop=smgr.createInstanceWithContext("com.sun.star.frame.Desktop",ctx)
+
+w=worker.Worker(0,desktop)
+
+class TestGeneral(unittest.TestCase):
+
+ def testBadConvertion(self):
+ self.assertRaises(IllegalMimeType,w.run_convert,'doc/test.html')
+
+ def testBadFile(self):
+ self.assertRaises(NotLoaded,w.run_convert,'doc/test.pdf')
+
+class TestHandling(unittest.TestCase):
+
+ def testConvertion(self):
+ res=w.run_convert(self.name)
+ r=res[0]
+ self.assertEqual(r['Keywords'],u'keywords')
+ self.assertEqual(r['MIMEType'],self.mime)
+ self.assertEqual(r['Subject'],u'subject')
+ self.assertEqual(r['Description'],u'comments')
+ self.assertEqual(r['Title'],u'title')
+ self.assertEqual(res[1][-12:],unicode(os.path.basename(self.convname)))
+
+ def testSetMetadata(self):
+ newmeta={'Title':'New Title','Reference':'abc-def-gh'}
+ print 'newmeta',newmeta
+ res=w.run_setmetadata(self.convname,newmeta)
+ self.assert_(res)
+ got=w.run_getmetadata(self.convname)
+ print 'got',got
+ self.assert_(got['Title']==newmeta['Title'])
+ self.assert_(got['Subject']=='subject')
+ self.assert_(got['Keywords']=='keywords')
+ self.assert_(got['Reference']==u'abc-def-gh')
+
+class TestDocHandling(TestHandling):
+
+ name='doc/test.doc'
+ convname='doc/test.doc.odt'
+ mime='application/vnd.oasis.opendocument.text'
+
+ def testRtfGeneration(self):
+ self.assert_(w.run_generate(self.convname,'rtf'))
+
+ def testDocGeneration(self):
+ self.assert_(w.run_generate(self.convname,'doc'))
+
+ def testHtmlGeneration(self):
+ self.assert_(w.run_generate(self.convname,'html-writer'))
+
+ def testPdfGeneration(self):
+ self.assert_(w.run_generate(self.convname,'pdf'))
+
+
+class TestXlsHandling(TestHandling):
+
+ name='doc/test.xls'
+ convname='doc/test.xls.ods'
+ mime='application/vnd.oasis.opendocument.spreadsheet'
+
+ def testCsvGeneration(self):
+ self.assert_(w.run_generate(self.convname,'csv'))
+
+ def testHtmlGeneration(self):
+ self.assert_(w.run_generate(self.convname,'html-calc'))
+
+ def testPdfGeneration(self):
+ self.assert_(w.run_generate(self.convname,'calc.pdf'))
+
+if __name__=='__main__':
+ #unittest.main()
+ tests=(TestGeneral,TestDocHandling,TestXlsHandling)
+ for t in tests:
+ suite=unittest.makeSuite(t)
+ unittest.TextTestRunner(verbosity=2).run(suite)
+
+# vim: shiftwidth=2
Added: erp5/trunk/utils/ooodoc_server/worker.py
URL: http://svn.erp5.org/erp5/trunk/utils/ooodoc_server/worker.py?rev=8963&view=auto
==============================================================================
--- erp5/trunk/utils/ooodoc_server/worker.py (added)
+++ erp5/trunk/utils/ooodoc_server/worker.py Tue Aug 1 14:30:41 2006
@@ -1,0 +1,269 @@
+#!/usr/bin/python
+##############################################################################
+#
+# Copyright (c) 2002, 2006 Nexedi SARL and Contributors. All Rights Reserved.
+# Jean-Paul Smets-Solanes <jp at nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import os,sys,pdb,time
+import config
+sys.path.append(config.unopath)
+import uno
+from unohelper import Base, systemPathToFileUrl, fileUrlToSystemPath,absolutize
+from com.sun.star.beans import PropertyValue
+from com.sun.star.beans import PropertyExistException
+from com.sun.star.task import ErrorCodeIOException
+from com.sun.star.uno import Exception as UnoException
+from com.sun.star.lang import IllegalArgumentException
+
+import lib
+
+from mimemapper import mimemapper
+
+class Worker(object):
+
+ '''
+ This class encapsulates an OOo instance providing interface
+ to functions. Can be accessed directly by functions
+ "convert" etc., but should be through wrappers
+ "run_convert", which is safe and resets the worker finally.
+ '''
+
+ # for automatic interface generation
+ public_funcs=('convert','generate','setmetadata','getmetadata','getmetadatatoolong')
+
+ inProps = PropertyValue( "Hidden" , 0 , True, 0 ),
+
+ metafields=('Title','Subject','Keywords','Description','MIMEType')
+ userfields=('Reference','Version','Language')
+ busy=False
+
+ def __init__(self,idx,desktop,pool=None):
+ self.idx=idx
+ self.desktop=desktop
+ self.pool=pool
+ self.cwd=systemPathToFileUrl(config.basedir)
+ self._reset()
+ self._generateFuncs()
+
+ def setBusy(self):
+ self.busy=True
+
+ def setFree(self):
+ '''marks self as not busy, releases semaphore in the
+ pool object'''
+ self.busy=False
+ if self.pool is not None:
+ self.pool.release(self.idx)
+
+ def convert(self,fname):
+ '''convertion to OOo, returns metadata and OOo file url
+ we return metadata only if converting to OOo (the first conversion), otherwise
+ we don't need them'''
+ self._loadFile(fname)
+ self._convert()
+ # if the doc doesn't have title or reference, we use filename for them
+ # only on ERP5 object (we don't set them on file)
+ print 'fname',fname
+ try:
+ strippedfilename=fname[fname.index('_')+1:]
+ except ValueError:
+ strippedfilename=fname
+ if not self.metadata.get('Title'):
+ self.metadata['Title']=strippedfilename
+ if not self.metadata.get('Reference'):
+ self.metadata['Reference']=strippedfilename
+ return self.metadata,fileUrlToSystemPath(self.destUrl)
+
+ def generate(self,fname,format):
+ '''generate file in a requested format, return file url'''
+ self._loadFile(fname)
+ self._generate(format)
+ return fileUrlToSystemPath(self.destUrl)
+
+ def setmetadata(self,fname,meta):
+ '''set metadata on OOo file (fname does not change)'''
+ self._loadFile(fname)
+ self._setMetadata(meta)
+ self._saveFile()
+ return True
+
+ def getmetadatatoolong(self,fname):
+ """
+ for debugging - to see if timeout works
+ """
+ self._loadFile(fname)
+ meta=self._getMetadata()
+ time.sleep(config.timeout+1)
+ return meta
+
+ def getmetadata(self,fname):
+ self._loadFile(fname)
+ meta=self._getMetadata()
+ return meta
+
+ def _generateFuncs(self):
+ '''generates functions run_<funcname>
+ XXX we should prob'ly change naming convention and generate
+ automatically based on name pattern'''
+ for f in self.public_funcs:
+ fname='run_'+f
+ setattr(self,fname,self._gener(f))
+
+ def _gener(self,f):
+ def _run(*args,**kwargs):
+ '''if anything goes wrong, we reset the worker'''
+ try:
+ res=func(*args,**kwargs)
+ finally:
+ self._reset()
+ return res
+ func=getattr(self,f)
+ return _run
+
+ def _reset(self):
+ '''reset all worker's properties'''
+ try:
+ self.doc.close(True)
+ except:
+ pass
+ for atr in ('fileUrl','doc','dinfo','metadata','destUrl'):
+ setattr(self,atr,None)
+
+ def _loadFile(self,fname):
+ self.fileUrl=absolutize(self.cwd,systemPathToFileUrl(fname))
+ try:
+ self.doc=self.desktop.loadComponentFromURL(self.fileUrl,'_blank',0,self.inProps)
+ except IllegalArgumentException:
+ raise lib.NotFound(self.fileUrl)
+ if not self.doc:
+ raise lib.NotLoaded(self.fileUrl)
+
+ def _saveFile(self):
+ self.doc.store()
+
+ def _closeFile(self):
+ self.doc.close(True)
+
+ def _checkMimeType(self,format):
+ '''we check mime type - convert OOo and non-OOo files,
+ set metadata and generate other formats only on OOo
+ format: 0 - non-ooo, 1-ooo, 2-both'''
+ if not self.metadata or not self.metadata.has_key('MIMEType'): # sometimes missing
+ self.metadata=self._getMetadata()
+ if format==1 and self.metadata['MIMEType'] in mimemapper.ooo_types: return True
+ if format==0 and self.metadata['MIMEType'] in mimemapper.non_ooo_types: return True
+ if format==2 and self.metadata['MIMEType'] in mimemapper.ooo_types+mimemapper.non_ooo_types: return True
+ raise lib.IllegalMimeType(self.metadata['MIMEType'])
+
+ def _generate(self,format):
+ '''
+ pdf generation does not work right now because there is a problem
+ in OpenOffice 2.0.2
+ '''
+ self._checkMimeType(1)
+ outProps=mimemapper.generable[self.metadata['MIMEType']].get(format,None)
+ if outProps is None:
+ raise lib.IllegalFormat(format)
+ self.destUrl=self.fileUrl+'.'+outProps['ext'] # we want it very unique
+ try:
+ self.doc.storeToURL(self.destUrl,outProps['outprops'])
+ except ErrorCodeIOException:
+ raise lib.GenerationFailed(self.fileUrl+' to format '+format)
+ return self.destUrl
+
+ def _getMetadata(self):
+ '''extract metadata, assign as dictionary
+ no MIME check - we get them also before conversion'''
+ self.dinfo=self.doc.getDocumentInfo()
+ metadata={}
+ for n in self.metafields:
+ v=self.dinfo.getPropertyValue(n)
+ if v:
+ metadata[n]=v
+ for i in range(self.dinfo.getUserFieldCount()):
+ n=self.dinfo.getUserFieldName(i)
+ v=self.dinfo.getUserFieldValue(i)
+ if n.encode() in self.userfields:
+ if v:
+ metadata[n.encode()]=v
+ return metadata
+
+
+ def _convert(self):
+ '''convertion - only known mimetypes,store as a file with
+ appropriate extension we append extension instead of
+ replacing, because filename may have unusual extension or
+ none at all'''
+ self._checkMimeType(2)
+ pm=mimemapper.convertable.get(self.metadata['MIMEType'],None)
+ if pm is None:
+ if self.metadata['MIMEType'] in mimemapper.ooo_types: # we can convert OOo to itself
+ ext=mimemapper.types_map[self.metadata['MIMEType']]['ext']
+ else:
+ raise lib.IllegalMimeType(self.metadata['MIMEType'])
+ else:
+ ext=pm['ext']
+ self.destUrl=self.fileUrl+'.'+ext
+ self.doc.storeAsURL(self.destUrl,())
+ # we change mimetype to OOo before sending metadata back
+ if pm is not None:
+ self.metadata['MIMEType']=pm['mime_type']
+
+ def _setMetadata(self,meta):
+ '''set metadata given as a dictionary
+ add new property if does not exist'''
+ self._checkMimeType(1)
+ self.dinfo=self.doc.getDocumentInfo()
+ userfieldcounter=0
+ maxcount=self.dinfo.getUserFieldCount()
+ for k,v in meta.items():
+ if k in self.metafields:
+ try:
+ self.dinfo.addProperty(k,0,v)
+ except PropertyExistException:
+ self.dinfo.setPropertyValue(k,v)
+ elif k in self.userfields:
+ if userfieldcounter<maxcount:
+ self.dinfo.setUserFieldName(userfieldcounter,k)
+ self.dinfo.setUserFieldValue(userfieldcounter,v)
+ userfieldcounter+=1
+ # we silently ignore if there is too many user fields
+ else:
+ raise lib.IllegalMetaAttribute(k)
+
+ def getAllowedTargets(self,mimetype):
+ '''list types which can be generated from given OOo type'''
+ try:
+ return mimemapper.getAllowedTo(mimetype)
+ except KeyError:
+ return []
+
+if __name__=='__main__':
+ w=Worker(None)
+ print w.__dict__
+ w.run_convert('s')
+#
+# vim: shiftwidth=2
More information about the Erp5-report
mailing list