source: trunk/factory/src/backends/oooserver.py @ 335

Last change on this file since 335 was 335, checked in by sander, 10 years ago

Do not crash factory when the oooserver dies mid-conversion

File size: 4.6 KB
Line 
1# Officeshots.org - Test your office documents in different applications
2# Copyright (C) 2009 Stichting Lone Wolves
3# Written by Sander Marechal <s.marechal@jejik.com>
4#
5# Heavily based on PyODConvert, which is
6# Copyright (C) 2007 Mirko Nasato <mirko@artofsolving.com>
7# Licensed under the GNU LGPL v2.1 - http://www.gnu.org/licenses/lgpl.html
8
9"""
10This module is a back-end for the headless OpenOffice.org server
11"""
12
13import os
14import uno
15import logging
16
17from backends import Backend, BackendException
18from com.sun.star.uno import RuntimeException
19from com.sun.star.beans import PropertyValue
20from com.sun.star.connection import NoConnectException
21from com.sun.star.document.UpdateDocMode import QUIET_UPDATE
22
23FAMILY_MASTER = "Master"
24FAMILY_PRESENTATION = "Presentation"
25FAMILY_SPREADSHEET = "Spreadsheet"
26FAMILY_TEXT = "Text"
27
28FAMILY_BY_DOCTYPE = {
29        "odt": FAMILY_TEXT,
30        "sxw": FAMILY_TEXT,
31        "doc": FAMILY_TEXT,
32        "rtf": FAMILY_TEXT,
33        "txt": FAMILY_TEXT,
34        "wpd": FAMILY_TEXT,
35        "html": FAMILY_TEXT,
36        "ods": FAMILY_SPREADSHEET,
37        "sxc": FAMILY_SPREADSHEET,
38        "xls": FAMILY_SPREADSHEET,
39        "odp": FAMILY_PRESENTATION,
40        "sxi": FAMILY_PRESENTATION,
41        "ppt": FAMILY_PRESENTATION
42}
43
44FILTER_BY_FORMAT = {
45        "pdf": {
46                FAMILY_TEXT: "writer_pdf_Export",
47                FAMILY_SPREADSHEET: "calc_pdf_Export",
48                FAMILY_PRESENTATION: "impress_pdf_Export"
49        },
50        "odf": {
51                FAMILY_TEXT: "writer8",
52                FAMILY_SPREADSHEET: "calc8",
53                FAMILY_PRESENTATION: "impress8"
54        }
55}
56
57def _unoProps(**args):
58        props = []
59        for key in args:
60                prop = PropertyValue()
61                prop.Name = key
62                prop.Value = args[key]
63                props.append(prop)
64        return tuple(props)
65
66
67class OOOServerException(BackendException):
68        def __str__(self):
69                return 'OOOServerException: ' + BackendException.__str__(self)
70       
71
72class OOOServer(Backend):
73        """
74        Backend for the headless OpenOffice.org server
75        """
76        def initialize(self):
77                localContext = uno.getComponentContext()
78                resolver = localContext.ServiceManager.createInstanceWithContext('com.sun.star.bridge.UnoUrlResolver', localContext)
79
80                if self.config.has_option(self.section, 'ooo_host') and self.config.has_option(self.section, 'ooo_port'):
81                        self.ooo_host = self.config.get(self.section, 'ooo_host')
82                        self.ooo_port = self.config.get(self.section, 'ooo_port')
83                        try:
84                                context = resolver.resolve('uno:socket,host=%s,port=%s;urp;StarOffice.ComponentContext' % (self.ooo_host, self.ooo_port))
85                        except NoConnectException:
86                                raise OOOServerException('Failed to connect to OpenOffice.org on %s port %s' % (self.ooo_host, self.ooo_port))
87                elif self.config.has_option(self.section, 'ooo_pipe'):
88                        self.ooo_pipe = self.config.get(self.section, 'ooo_pipe')
89                        try:
90                                context = resolver.resolve('uno:pipe,name=%s;urp;StarOffice.ComponentContext' % self.ooo_pipe)
91                        except NoConnectException:
92                                raise OOOServerException('Failed to connect to OpenOffice.org on pipe "%s"' % self.ooo_pipe)
93                else:
94                        raise OOOServerException('Failed to connect to OpenOffice.org. No connection method configured.')
95                               
96                self.desktop = context.ServiceManager.createInstanceWithContext('com.sun.star.frame.Desktop', context)
97       
98        def filter_name(self, doctype, format):
99                try:
100                        family = FAMILY_BY_DOCTYPE[doctype]
101                except KeyError:
102                        raise OOOServerException("Unknown input doctype: '%s'" % doctype, True)
103                try:
104                        filterByFamily = FILTER_BY_FORMAT[format]
105                except KeyError:
106                        raise OOOServerException("Unknown output format: '%s'" % format, True)
107                try:
108                        return filterByFamily[family]
109                except KeyError:
110                        raise OOOServerException("Unsupported conversion: from '%s' to '%s'" % (doctype, format), True)
111
112        def file_url(self, path):
113                return uno.systemPathToFileUrl(os.path.abspath(path))
114
115        def process(self, job):
116                src_file = self.save_document(job)
117                (root, ext) = os.path.splitext(src_file)
118                dst_file = root + '_result' + ext
119
120                if (job['format'] == ''):
121                        job['format'] = 'pdf'
122
123                src_file_url = self.file_url(src_file)
124                filter_name = self.filter_name(job['doctype'], job['format'])
125
126                try:
127                        document = self.desktop.loadComponentFromURL(src_file_url, "_blank", 0, _unoProps(Hidden=True, ReadOnly=True, UpdateDocMode=QUIET_UPDATE))
128
129                        if document is None:
130                                raise OOOServerException("The document '%s' could not be opened." % src_file_url, True)
131
132                        document.storeToURL(self.file_url(dst_file), _unoProps(FilterName=filter_name))
133                        document.close(True)
134                except RuntimeException:
135                        raise OOOServerException("UNO RuntimeException in OOOServer. The server probably died. Unloading backend.", False)
136
137                logging.info('OOOServer converted %s to %s' % (src_file, dst_file))
138                contents = self.load_document(dst_file)
139                os.unlink(src_file)
140                os.unlink(dst_file)
141
142                return (job['format'], contents)
143
Note: See TracBrowser for help on using the repository browser.