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