source: gs2-extensions/open-office/trunk/src/perllib/plugins/OpenOfficeConverter.pm@ 24569

Last change on this file since 24569 was 24569, checked in by ak19, 13 years ago
  1. Thanks to Diego, a bug was identified which prevented the openoffice extension from working on Ubuntu: there was reference to the Win32 package even when we're not on Windows. 2. The code now does a better job of working out the default location for SOFFICE_HOME if this is not set. 3. The code changes allow the extension to work successfully with LibreOffice, since that is also launched with soffice and because jodjar is able to work with it in the same way as it works with openoffice.
  • Property svn:executable set to *
File size: 11.2 KB
Line 
1###########################################################################
2#
3# OpenOfficeConverter - helper plugin that does office document conversion
4# using jodconverter combined with OpenOffice
5#
6# A component of the Greenstone digital library software
7# from the New Zealand Digital Library Project at the
8# University of Waikato, New Zealand.
9#
10# Copyright (C) 2010 New Zealand Digital Library Project
11#
12# This program is free software; you can redistribute it and/or modify
13# it under the terms of the GNU General Public License as published by
14# the Free Software Foundation; either version 2 of the License, or
15# (at your option) any later version.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License
23# along with this program; if not, write to the Free Software
24# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25#
26###########################################################################
27package OpenOfficeConverter;
28
29use ConvertBinaryFile;
30use BaseMediaConverter;
31
32use strict;
33no strict 'refs'; # allow filehandles to be variables and viceversa
34
35use gsprintf 'gsprintf';
36
37# these two variables mustn't be initialised here or they will get stuck
38# at those values.
39our $openoffice_conversion_available;
40our $no_openoffice_conversion_reason;
41
42BEGIN {
43 @OpenOfficeConverter::ISA = ('BaseMediaConverter');
44
45 # Check that OpenOffice and jodconverter are installed and available on
46 # the path
47 $openoffice_conversion_available = 1;
48 $no_openoffice_conversion_reason = "";
49
50 if (! defined $ENV{'GEXT_OPENOFFICE'}) {
51 $openoffice_conversion_available = 0;
52 $no_openoffice_conversion_reason = "gextopenofficenotinstalled";
53 }
54 else {
55 my $gextoo_home = $ENV{'GEXT_OPENOFFICE'};
56 my $jodjar = &util::filename_cat($gextoo_home,"lib","java","jodconverter.jar");
57
58 if (!-e $jodjar) {
59 #print STDERR "Failed to find $jodjar\n";
60 $openoffice_conversion_available = 0;
61 $no_openoffice_conversion_reason = "gextjodconverternotinstalled";
62 }
63 else {
64 # test to see if soffice is in path
65 my $cmd = "soffice -headless 2>&1"; # for linux and mac
66
67 # The port that jodconverter uses to connect to soffice.
68 # We set this to 8100 (else jodconverter would have used
69 # 2002 as the port number, which can clash with some programs
70 # such as LogMeIn. Users can specify another port by setting
71 # the environment variable in setup.bat or <ext>-setup.pl.
72 if(!defined $ENV{'JODCONVERTER_PORT'}) {
73 $ENV{'JODCONVERTER_PORT'} = "8100";
74 }
75
76 if ($ENV{'GSDLOS'} =~ m/^windows$/) {
77 if(!defined $ENV{'SOFFICE_HOST'}) {
78 $ENV{'SOFFICE_HOST'} = "localhost";
79 }
80 if(!defined $ENV{'SOFFICE_PORT'}) {
81 $ENV{'SOFFICE_PORT'} = "8200";
82 }
83 # important to have this set when the Greenstone server
84 # and open office is on a remote windows machine
85 if(!defined $ENV{'SOFFICE_HOME'}) {
86 $ENV{'SOFFICE_HOME'} = &util::filename_cat($ENV{'ProgramFiles'},"OpenOffice.org 3");
87 }
88 my $ooffice_dir_guess =
89 &util::filename_cat($ENV{'SOFFICE_HOME'},"program");
90 if (-d $ooffice_dir_guess) {
91 &util::envvar_append("PATH",$ooffice_dir_guess);
92 }
93
94 # for windows, when working on a remote system, want to be able to start OO if
95 # not already running. We'll use the uno socket method to do so. Else client-gli
96 # tends to hang, waiting for the prompt to return after OO has been started up
97 # (which doesn't happen, so need to Ctrl-C GLI and run it again for it to work).
98 $cmd = "start \"soffice process\" soffice \"-accept=socket,host=$ENV{'SOFFICE_HOST'},port=$ENV{'SOFFICE_PORT'};urp;StarOffice.ServiceManager\" -headless 2>&1";
99 $cmd .= " >nul";
100 #print STDERR "***** Tried to start-up OpenOffice with:\n$cmd\n";
101 }
102 else {
103 # Windows seems to launch OpenOffice as a service (i.e.
104 # automatically puts it in the background).
105 # For Unix putting it in the background needs to be done
106 # explicitly
107
108 $cmd .= " >/dev/null &";
109 }
110
111 my $status = system($cmd);
112 if ($status != 0) {
113 #print STDERR "Failed to run: $cmd\n";
114 #print STDERR "$!\n";
115 $openoffice_conversion_available = 0;
116 $no_openoffice_conversion_reason = "openofficenotinstalled";
117 }
118 }
119 }
120}
121
122my $arguments = [
123 { 'name' => "openoffice_port",
124 'desc' => "{OpenOfficeConverter.openoffice_port}",
125 'type' => "int",
126 'deft' => "8100",
127 'range' => "81,",
128 'reqd' => "no" },
129 ];
130
131
132my $options = { 'name' => "OpenOfficeConverter",
133 'desc' => "{OpenOfficeConverter.desc}",
134 'abstract' => "yes",
135 'inherits' => "yes",
136 'args' => $arguments };
137
138sub new {
139 my ($class) = shift (@_);
140 my ($pluginlist,$inputargs,$hashArgOptLists,$auxilary) = @_;
141 push(@$pluginlist, $class);
142
143 push(@{$hashArgOptLists->{"ArgList"}},@{$arguments});
144 push(@{$hashArgOptLists->{"OptList"}},$options);
145
146 my $self = new BaseMediaConverter($pluginlist, $inputargs,
147 $hashArgOptLists, $auxilary);
148
149 if ($self->{'info_only'}) {
150 # don't worry about any options etc
151 return bless $self, $class;
152 }
153 if (!$openoffice_conversion_available) {
154 $self->{'no_openoffice_conversion_reason'} = $no_openoffice_conversion_reason;
155
156 my $outhandle = $self->{'outhandle'};
157 &gsprintf($outhandle, "OpenOfficeConverter: {OpenOfficeConverter.noconversionavailable} ({OpenOfficeConverter.$no_openoffice_conversion_reason})\n");
158 }
159
160 $self->{'openoffice_conversion_available'} = $openoffice_conversion_available;
161
162 return bless $self, $class;
163
164}
165
166sub init {
167 my $self = shift(@_);
168 my ($verbosity, $outhandle, $failhandle) = @_;
169
170 if ($openoffice_conversion_available) {
171 my $oo_port = $self->{'openoffice_port'};
172
173 my $launch_cmd = "soffice";
174 $launch_cmd .= " \"-accept=socket,host=localhost,port=$oo_port;urp;StarOffice.ServiceManager\"";
175 $launch_cmd .= " -headless";
176 $self->{'openoffice_launch_cmd'} = $launch_cmd;
177 }
178
179 $self->{'ootmp_file_paths'} = ();
180}
181
182sub deinit {
183 my $self = shift(@_);
184
185 $self->clean_up_temporary_files();
186}
187
188
189sub convert {
190 my $self = shift(@_);
191 my $source_file_full_path = shift(@_);
192 my $target_file_type = shift(@_);
193 my $convert_options = shift(@_) || "";
194 my $convert_id = shift(@_) || "";
195 my $cache_mode = shift(@_) || "";
196
197 return (0,undef,undef) unless $openoffice_conversion_available;
198 # check the filename
199 return (0,undef,undef) if ( !-f $source_file_full_path);
200
201 my $outhandle = $self->{'outhandle'};
202 my $verbosity = $self->{'verbosity'};
203
204 my $source_file_no_path = &File::Basename::basename($source_file_full_path);
205 # Determine the full name and path of the output file
206 my $target_file_path;
207 if ($self->{'enable_cache'}) {
208 $self->init_cache_for_file($source_file_full_path);
209 my $cache_dir = $self->{'cached_dir'};
210 my $file_root = $self->{'cached_file_root'};
211 $file_root .= "_$convert_id" if ($convert_id ne "");
212 my $target_file = "$file_root.$target_file_type";
213 $target_file_path = &util::filename_cat($cache_dir,$target_file);
214 }
215 else {
216 $target_file_path = &util::get_timestamped_tmp_filename_in_collection($source_file_full_path, $target_file_type);
217 push(@{$self->{'ootmp_file_paths'}}, $target_file_path);
218 }
219
220 # Generate and run the convert command
221
222 my $gextoo_home = $ENV{'GEXT_OPENOFFICE'};
223 my $jodjar = &util::filename_cat($gextoo_home,"lib","java","jodconverter.jar");
224
225 # debugging: print out all the env vars, when import's verbosity is high
226 #foreach my $key (sort(keys %ENV)) {
227 # print $outhandle "$key = $ENV{$key}\n";
228 #}
229
230# *If* SOFFICE_HOME\program was not added to the PATH, *another* way is to insert:
231# -Doffice.home=C:\\PROGRA~1\\OPENOF~1.ORG
232# into the command to launch jodconverter so that, when using the remote GS server
233# on Windows, jodconverter can find the openoffice installation:
234
235 my $office_short_path;
236 if(defined $ENV{'SOFFICE_HOME'}) { # points to libreoffice or openoffice, since soffice launches both
237 if ($ENV{'GSDLOS'} =~ m/^windows$/) {
238 $office_short_path = Win32::GetShortPathName($ENV{'SOFFICE_HOME'});
239 } else {
240 $office_short_path = $ENV{'SOFFICE_HOME'};
241 }
242 }
243 else { # SOFFICE_HOME not user-defined, try defaults
244 if ($ENV{'GSDLOS'} =~ m/^windows$/) {
245 $office_short_path = "C:\\PROGRA~1\\OPENOF~1.ORG";
246 } else {
247 if (-d "/usr/lib/libreoffice") { # try libreoffice first
248 $office_short_path = "/usr/lib/libreoffice";
249 } elsif (-d "/usr/lib/openoffice") { # perhaps it's more likely that openoffice exists (fallback)
250 $office_short_path = "/usr/lib/openoffice";
251 } else { # set to default linux officeHome which jodconverter tries for
252 $office_short_path = "/opt/openoffice.org3";
253 }
254 }
255 }
256
257 # jodjar always assumes that soffice (officeHome) is in "C:\Prog Files\OpenOffice org 3"
258 # or "/opt/openoffice.org3" rather than checking for any user-defined SOFFICE_HOME var.
259 # Therefore, we run jodjar with the -Doffice.home flag explicitly set, instead of without.
260 # my $convert_cmd = "java -jar \"$jodjar\" --port $ENV{'JODCONVERTER_PORT'}";
261 my $convert_cmd = "java -Doffice.home=\"".$office_short_path."\" -jar \"$jodjar\" --port $ENV{'JODCONVERTER_PORT'}";
262 $convert_cmd .= " \"$source_file_full_path\" \"$target_file_path\"";
263
264 if ($verbosity>2) {
265 print $outhandle "Convert command: $convert_cmd\n";
266 }
267
268 my $print_info = { 'message_prefix' => "OpenOffice Conversion",
269 'message' => "Converting $source_file_no_path to: $target_file_type" };
270 $print_info->{'cache_mode'} = $cache_mode if ($cache_mode ne "");
271
272 my ($regenerated,$result,$had_error)
273 = $self->autorun_general_cmd($convert_cmd,$source_file_full_path, $target_file_path,$print_info);
274 if ($had_error) {
275 return (0, $result,$target_file_path);
276 }
277 return (1, $result,$target_file_path);
278}
279
280
281sub convert_without_result {
282 my $self = shift(@_);
283
284 my $source_file_path = shift(@_);
285 my $target_file_type = shift(@_);
286 my $convert_options = shift(@_) || "";
287 my $convert_id = shift(@_) || "";
288
289 return $self->convert($source_file_path,$target_file_type,
290 $convert_options,$convert_id,"without_result");
291}
292
293
294sub tmp_area_convert_fileXX {
295 my $self = shift (@_);
296 my ($output_ext, $input_filename, $textref) = @_;
297
298 my $outhandle = $self->{'outhandle'};
299 my $convert_to = $self->{'convert_to'};
300 my $failhandle = $self->{'failhandle'};
301 my $convert_to_ext = $self->{'convert_to_ext'};
302
303 # derive tmp filename from input filename
304 my ($tailname, $dirname, $suffix)
305 = &File::Basename::fileparse($input_filename, "\\.[^\\.]+\$");
306}
307
308
309sub clean_up_temporary_files {
310 my $self = shift(@_);
311
312 foreach my $ootmp_file_path (@{$self->{'ootmp_file_paths'}}) {
313 if (-e $ootmp_file_path) {
314 &util::rm($ootmp_file_path);
315 }
316 }
317
318 $self->{'ootmp_file_paths'} = ();
319}
320
321
322
3231;
Note: See TracBrowser for help on using the repository browser.