title: How to debug crashing openoffice with pyuno
body: <p>I'd like to use openoffice to programmatically convert docx to pdf. I know unoconv can do this, and indeed unoconv will do this for me, even if I run a separate listener (using <code>unoconv -l</code>) and invoke <code>unoconv -n</code> (so that it will die if it can't connect to the listener). Accordingly, I assume that my openoffice/pyuno environment is sane.</p>
  
  <p>However, when I run an unoconv listener (or manually invoke openoffice as an acceptor), and try to connect with my own python code (derived from unoconv, and cross-checked with another openoffice library), the listener dies, and the uno bridge dies.</p>
  
  <p>The error I get from the listener is:</p>
  
  <pre><code>terminate called after throwing an instance of 'com::sun::star::uno::RuntimeException'
  </code></pre>
  
  <p>The error I get on the python end is:</p>
  
  <pre><code>unoconv: RuntimeException during import phase:
  Office probably died. Binary URP bridge disposed during call
  </code></pre>
  
  <p>I really have no idea how to go about diagnosing the problem here. Any suggestions as to the underlying cause or how to diagnose it would be greatly appreciated.</p>
  
  <p>Code below:</p>
  
  <pre><code>#dependency on openoffice-python
  import openoffice.streams as oostreams
  import openoffice.officehelper as oohelper
  import uno, unohelper
  from com.sun.star.beans import PropertyValue
  from com.sun.star.connection import NoConnectException
  from com.sun.star.document.UpdateDocMode import QUIET_UPDATE
  from com.sun.star.lang import DisposedException, IllegalArgumentException
  from com.sun.star.io import IOException, XOutputStream
  from com.sun.star.script import CannotConvertException
  from com.sun.star.uno import Exception as UnoException
  from com.sun.star.uno import RuntimeException
  
  import logging
  logger = logging.getLogger(__name__)
  
  
  #connectionstring = 'uno:socket,host=127.0.0.1,port=2002;urp;StarOffice.ComponentContext'
  connectionstring = 'socket,host=127.0.0.1,port=2002'
  ## context = uno.getComponentContext()
  ## svcmgr = context.ServiceManager
  ## resolver = svcmgr.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", context)
  
  ## unocontext = resolver.resolve("uno:%s" % connectionstring)
  unocontext = oohelper.connect(connectionstring)
  
  #unosvcmgr = unocontext.ServiceManager
  desktop = unocontext.ServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", unocontext)
  
  
  class OutputStream( unohelper.Base, XOutputStream ):
      def __init__(self, stream=None):
          self.closed = 0
          self.stream = stream if stream is not None else sys.stdout
  
      def closeOutput(self):
          self.closed = 1
  
      def writeBytes( self, seq ):
          self.stream.write( seq.value )
  
      def flush( self ):
          pass
  
  def UnoProps(**args):
      props = []
      for key in args:
          prop = PropertyValue()
          prop.Name = key
          prop.Value = args[key]
          props.append(prop)
      return tuple(props)
  
  
  
  FILTERS = {'pdf': 'writer_pdf_Export'}
  
  def convert_stream(instream, outstream,
                     outdoctype=None, outformat=None):
      '''instream and outstream are streams.
      outdoctype and outformat are strings. They correspond
      to the first two parameters to the Fmt constructor.To
      convert to pdf use outdoctype="document",
      outformat="pdf".
      If you choose inappropriate values, an ValueError
      will result.'''
      #fmts is a global object of type FmtList
  
      outputfilter = FILTERS[outformat]
  
      inputprops = UnoProps(Hidden=True, ReadOnly=True, UpdateDocMode=QUIET_UPDATE, InputStream=oostreams.InputStream(instream))
      inputurl = 'private:stream'
      convert_worker(inputurl,inputprops,outputfilter,outstream=outstream)
      return outstream
  
  
  def convert_worker(inputurl, inputprops, outputfilter, outstream=None,inputfn=None):
      global exitcode
  
      document = None
  
      try:
          ### Import phase
          phase = "import"
  
          document = desktop.loadComponentFromURL( inputurl , "_blank", 0, inputprops )
  
          if not document:
              raise UnoException("The document '%s' could not be opened." % inputurl, None)
  
          ### Import style template
          phase = "import-style"
  
          ### Update document links
          phase = "update-links"
          try:
              document.updateLinks()
          except AttributeError:
              # the document doesn't implement the XLinkUpdate interface
              pass
  
          ### Update document indexes
          phase = "update-indexes"
          for ii in range(2):
              # At first update Table-of-Contents.
              # ToC grows, so page numbers grows too.
              # On second turn update page numbers in ToC.
              try:
                  document.refresh()
                  indexes = document.getDocumentIndexes()
              except AttributeError:
                  # the document doesn't implement the XRefreshable and/or
                  # XDocumentIndexesSupplier interfaces
                  break
              else:
                  for i in range(0, indexes.getCount()):
                      indexes.getByIndex(i).update()
  
          ### Export phase
          phase = "export"
  
          outputprops = UnoProps(FilterName=outputfilter, OutputStream=OutputStream(stream=outstream), Overwrite=True)
          outputurl = "private:stream"
  
          try:
              document.storeToURL(outputurl, tuple(outputprops) )
          except IOException as e:
              raise UnoException("Unable to store document to %s (ErrCode %d)\n\nProperties: %s" % (outputurl, e.ErrCode, outputprops), None)
  
          phase = "dispose"
          document.dispose()
          document.close(True)
  
      except SystemError as e:
          logger.error("unoconv: SystemError during %s phase:\n%s" % (phase, e))
          exitcode = 1
  
      except RuntimeException as e:
          logger.error("unoconv: RuntimeException during %s phase:\nOffice probably died. %s" % (phase, e))
          exitcode = 6
  
      except DisposedException as e:
          logger.error("unoconv: DisposedException during %s phase:\nOffice probably died. %s" % (phase, e))
          exitcode = 7
  
      except IllegalArgumentException as e:
          logger.error("UNO IllegalArgument during %s phase:\nSource file cannot be read. %s" % (phase, e))
          exitcode = 8
  
      except IOException as e:
          #            for attr in dir(e): print '%s: %s', (attr, getattr(e, attr))
          logger.error("unoconv: IOException during %s phase:\n%s" % (phase, e.Message))
          exitcode = 3
  
      except CannotConvertException as e:
          #            for attr in dir(e): print '%s: %s', (attr, getattr(e, attr))
          logger.error("unoconv: CannotConvertException during %s phase:\n%s" % (phase, e.Message))
          exitcode = 4
  
      except UnoException as e:
          if hasattr(e, 'ErrCode'):
              logger.error("unoconv: UnoException during %s phase in %s (ErrCode %d)" % (phase, repr(e.__class__), e.ErrCode))
              exitcode = e.ErrCode
              pass
          if hasattr(e, 'Message'):
              logger.error("unoconv: UnoException during %s phase:\n%s" % (phase, e.Message))
              exitcode = 5
          else:
              logger.error("unoconv: UnoException during %s phase in %s" % (phase, repr(e.__class__)))
              exitcode = 2
              pass
  </code></pre>