From 93dc7d542a55802eb96d8200b0ff42b67296cb63 Mon Sep 17 00:00:00 2001 From: Tom Marble Date: Thu, 3 Jan 2013 18:57:19 -0600 Subject: [PATCH] ooutils.py sent to bkuhn by tmarble in this email: Date: Thu, 03 Jan 2013 18:57:19 -0600 From: Tom Marble To: "Bradley M. Kuhn" Subject: ods2xlsx.py Message-ID: <50E628EF.7080207@info9.net> Tom indicates it was adapted from Mirko Nasato's code. I don't know if Tom adapted it himself. The license therefore is clearly LGPLv2.1-or-later, but Tom may also have copyrights here. I've asked him to add his copyright notice if he does. --- ooutils.py | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 ooutils.py diff --git a/ooutils.py b/ooutils.py new file mode 100644 index 0000000..fac7afa --- /dev/null +++ b/ooutils.py @@ -0,0 +1,173 @@ +#!/usr/bin/python +# ooutils.py +# from http://www.linuxjournal.com/node/1007788 + +# OpenOffice utils. +# +# Based on code from: +# PyODConverter (Python OpenDocument Converter) v1.0.0 - 2008-05-05 +# Copyright (C) 2008 Mirko Nasato +# Licensed under the GNU LGPL v2.1 - or any later version. +# http://www.gnu.org/licenses/lgpl-2.1.html +# + +import sys +import os +import time +import atexit + + +OPENOFFICE_PORT = 8100 + +# Find OpenOffice. +_oopaths=( + ('/usr/lib/libreoffice/program', '/usr/lib/libreoffice/program'), + ('/usr/lib64/ooo-2.0/program', '/usr/lib64/ooo-2.0/program'), + ('/opt/openoffice.org3/program', '/opt/openoffice.org/basis3.0/program'), + ) + +for p in _oopaths: + if os.path.exists(p[0]): + OPENOFFICE_PATH = p[0] + OPENOFFICE_BIN = os.path.join(OPENOFFICE_PATH, 'soffice') + OPENOFFICE_LIBPATH = p[1] + + # Add to path so we can find uno. + if sys.path.count(OPENOFFICE_LIBPATH) == 0: + sys.path.insert(0, OPENOFFICE_LIBPATH) + break + + +import uno +from com.sun.star.beans import PropertyValue +from com.sun.star.connection import NoConnectException + + +class OORunner: + """ + Start, stop, and connect to OpenOffice. + """ + def __init__(self, port=OPENOFFICE_PORT): + """ Create OORunner that connects on the specified port. """ + self.port = port + + + def connect(self, no_startup=False): + """ + Connect to OpenOffice. + If a connection cannot be established try to start OpenOffice. + """ + localContext = uno.getComponentContext() + resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext) + context = None + did_start = False + + n = 0 + while n < 6: + try: + context = resolver.resolve("uno:socket,host=localhost,port=%d;urp;StarOffice.ComponentContext" % self.port) + break + except NoConnectException: + pass + + # If first connect failed then try starting OpenOffice. + if n == 0: + # Exit loop if startup not desired. + if no_startup: + break + self.startup() + did_start = True + + # Pause and try again to connect + time.sleep(1) + n += 1 + + if not context: + raise Exception, "Failed to connect to OpenOffice on port %d" % self.port + + desktop = context.ServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", context) + + if not desktop: + raise Exception, "Failed to create OpenOffice desktop on port %d" % self.port + + if did_start: + _started_desktops[self.port] = desktop + + return desktop + + + def startup(self): + """ + Start a headless instance of OpenOffice. + """ + args = [OPENOFFICE_BIN, + '-accept=socket,host=localhost,port=%d;urp;StarOffice.ServiceManager' % self.port, + '-norestore', + '-nofirststartwizard', + '-nologo', + '-headless', + ] + env = {'PATH' : '/bin:/usr/bin:%s' % OPENOFFICE_PATH, + 'PYTHONPATH' : OPENOFFICE_LIBPATH, + } + + try: + pid = os.spawnve(os.P_NOWAIT, args[0], args, env) + except Exception, e: + raise Exception, "Failed to start OpenOffice on port %d: %s" % (self.port, e.message) + + if pid <= 0: + raise Exception, "Failed to start OpenOffice on port %d" % self.port + + + def shutdown(self): + """ + Shutdown OpenOffice. + """ + try: + if _started_desktops.get(self.port): + _started_desktops[self.port].terminate() + del _started_desktops[self.port] + except Exception, e: + pass + + + +# Keep track of started desktops and shut them down on exit. +_started_desktops = {} + +def _shutdown_desktops(): + """ Shutdown all OpenOffice desktops that were started by the program. """ + for port, desktop in _started_desktops.items(): + try: + if desktop: + desktop.terminate() + except Exception, e: + pass + + +atexit.register(_shutdown_desktops) + + +def oo_shutdown_if_running(port=OPENOFFICE_PORT): + """ Shutdown OpenOffice if it's running on the specified port. """ + oorunner = OORunner(port) + try: + desktop = oorunner.connect(no_startup=True) + desktop.terminate() + except Exception, e: + pass + + +def oo_properties(**args): + """ + Convert args to OpenOffice property values. + """ + props = [] + for key in args: + prop = PropertyValue() + prop.Name = key + prop.Value = args[key] + props.append(prop) + + return tuple(props)