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

Last change on this file since 24687 was 24687, checked in by ak19, 13 years ago

If soffice is not installed, then the OpenOfficeConverter's attempt to start soffice in the BEGIN statement fails with a popup generated by Windows that it couldn't find soffice. Before trying to run start soffice on Windows, the code now runs a which soffice command to determine that it is installed.

  • Property svn:executable set to *
File size: 11.5 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 my $status = 0;
67
68 # The port that jodconverter uses to connect to soffice.
69 # We set this to 8100 (else jodconverter would have used
70 # 2002 as the port number, which can clash with some programs
71 # such as LogMeIn. Users can specify another port by setting
72 # the environment variable in setup.bat or <ext>-setup.pl.
73 if(!defined $ENV{'JODCONVERTER_PORT'}) {
74 $ENV{'JODCONVERTER_PORT'} = "8100";
75 }
76
77 if ($ENV{'GSDLOS'} =~ m/^windows$/) {
78 if(!defined $ENV{'SOFFICE_HOST'}) {
79 $ENV{'SOFFICE_HOST'} = "localhost";
80 }
81 if(!defined $ENV{'SOFFICE_PORT'}) {
82 $ENV{'SOFFICE_PORT'} = "8200";
83 }
84 # important to have this set when the Greenstone server
85 # and open office is on a remote windows machine
86 if(!defined $ENV{'SOFFICE_HOME'}) {
87 $ENV{'SOFFICE_HOME'} = &util::filename_cat($ENV{'ProgramFiles'},"OpenOffice.org 3");
88 }
89 my $ooffice_dir_guess =
90 &util::filename_cat($ENV{'SOFFICE_HOME'},"program");
91 if (-d $ooffice_dir_guess) {
92 &util::envvar_append("PATH",$ooffice_dir_guess);
93 }
94
95 # for windows, when working on a remote system, want to be able to start OO if
96 # not already running. We'll use the uno socket method to do so. Else client-gli
97 # tends to hang, waiting for the prompt to return after OO has been started up
98 # (which doesn't happen, so need to Ctrl-C GLI and run it again for it to work).
99
100 # first need to silently check soffice exists else windows will display a popup
101 $status = system("which soffice >nul 2>&1"); # which.exe should be in bin/windows
102 if ($status == 0) {
103 $cmd = "start \"soffice process\" soffice \"-accept=socket,host=$ENV{'SOFFICE_HOST'},port=$ENV{'SOFFICE_PORT'};urp;StarOffice.ServiceManager\" -headless 2>&1";
104 $cmd .= " >nul";
105 #print STDERR "***** Tried to start-up OpenOffice with:\n$cmd\n";
106 }
107 # else cmd is still undefined
108 }
109 else {
110 # Windows seems to launch OpenOffice as a service (i.e.
111 # automatically puts it in the background).
112 # For Unix putting it in the background needs to be done
113 # explicitly
114
115 $cmd .= " >/dev/null &";
116 }
117
118 $status = system($cmd) if ($status == 0);
119 if ($status != 0) {
120 #print STDERR "Failed to run: $cmd\n";
121 #print STDERR "$!\n";
122 $openoffice_conversion_available = 0;
123 $no_openoffice_conversion_reason = "openofficenotinstalled";
124 }
125 }
126 }
127}
128
129my $arguments = [
130 { 'name' => "openoffice_port",
131 'desc' => "{OpenOfficeConverter.openoffice_port}",
132 'type' => "int",
133 'deft' => "8100",
134 'range' => "81,",
135 'reqd' => "no" },
136 ];
137
138
139my $options = { 'name' => "OpenOfficeConverter",
140 'desc' => "{OpenOfficeConverter.desc}",
141 'abstract' => "yes",
142 'inherits' => "yes",
143 'args' => $arguments };
144
145sub new {
146 my ($class) = shift (@_);
147 my ($pluginlist,$inputargs,$hashArgOptLists,$auxilary) = @_;
148 push(@$pluginlist, $class);
149
150 push(@{$hashArgOptLists->{"ArgList"}},@{$arguments});
151 push(@{$hashArgOptLists->{"OptList"}},$options);
152
153 my $self = new BaseMediaConverter($pluginlist, $inputargs,
154 $hashArgOptLists, $auxilary);
155
156 if ($self->{'info_only'}) {
157 # don't worry about any options etc
158 return bless $self, $class;
159 }
160 if (!$openoffice_conversion_available) {
161 $self->{'no_openoffice_conversion_reason'} = $no_openoffice_conversion_reason;
162
163 my $outhandle = $self->{'outhandle'};
164 &gsprintf($outhandle, "OpenOfficeConverter: {OpenOfficeConverter.noconversionavailable} ({OpenOfficeConverter.$no_openoffice_conversion_reason})\n");
165 }
166
167 $self->{'openoffice_conversion_available'} = $openoffice_conversion_available;
168
169 return bless $self, $class;
170
171}
172
173sub init {
174 my $self = shift(@_);
175 my ($verbosity, $outhandle, $failhandle) = @_;
176
177 if ($openoffice_conversion_available) {
178 my $oo_port = $self->{'openoffice_port'};
179
180 my $launch_cmd = "soffice";
181 $launch_cmd .= " \"-accept=socket,host=localhost,port=$oo_port;urp;StarOffice.ServiceManager\"";
182 $launch_cmd .= " -headless";
183 $self->{'openoffice_launch_cmd'} = $launch_cmd;
184 }
185
186 $self->{'ootmp_file_paths'} = ();
187}
188
189sub deinit {
190 my $self = shift(@_);
191
192 $self->clean_up_temporary_files();
193}
194
195
196sub convert {
197 my $self = shift(@_);
198 my $source_file_full_path = shift(@_);
199 my $target_file_type = shift(@_);
200 my $convert_options = shift(@_) || "";
201 my $convert_id = shift(@_) || "";
202 my $cache_mode = shift(@_) || "";
203
204 return (0,undef,undef) unless $openoffice_conversion_available;
205 # check the filename
206 return (0,undef,undef) if ( !-f $source_file_full_path);
207
208 my $outhandle = $self->{'outhandle'};
209 my $verbosity = $self->{'verbosity'};
210
211 my $source_file_no_path = &File::Basename::basename($source_file_full_path);
212 # Determine the full name and path of the output file
213 my $target_file_path;
214 if ($self->{'enable_cache'}) {
215 $self->init_cache_for_file($source_file_full_path);
216 my $cache_dir = $self->{'cached_dir'};
217 my $file_root = $self->{'cached_file_root'};
218 $file_root .= "_$convert_id" if ($convert_id ne "");
219 my $target_file = "$file_root.$target_file_type";
220 $target_file_path = &util::filename_cat($cache_dir,$target_file);
221 }
222 else {
223 $target_file_path = &util::get_timestamped_tmp_filename_in_collection($source_file_full_path, $target_file_type);
224 push(@{$self->{'ootmp_file_paths'}}, $target_file_path);
225 }
226
227 # Generate and run the convert command
228
229 my $gextoo_home = $ENV{'GEXT_OPENOFFICE'};
230 my $jodjar = &util::filename_cat($gextoo_home,"lib","java","jodconverter.jar");
231
232 # debugging: print out all the env vars, when import's verbosity is high
233 #foreach my $key (sort(keys %ENV)) {
234 # print $outhandle "$key = $ENV{$key}\n";
235 #}
236
237# *If* SOFFICE_HOME\program was not added to the PATH, *another* way is to insert:
238# -Doffice.home=C:\\PROGRA~1\\OPENOF~1.ORG
239# into the command to launch jodconverter so that, when using the remote GS server
240# on Windows, jodconverter can find the openoffice installation:
241
242 my $office_short_path;
243 if(defined $ENV{'SOFFICE_HOME'}) { # points to libreoffice or openoffice, since soffice launches both
244 if ($ENV{'GSDLOS'} =~ m/^windows$/) {
245 $office_short_path = Win32::GetShortPathName($ENV{'SOFFICE_HOME'});
246 } else {
247 $office_short_path = $ENV{'SOFFICE_HOME'};
248 }
249 }
250 else { # SOFFICE_HOME not user-defined, try defaults
251 if ($ENV{'GSDLOS'} =~ m/^windows$/) {
252 $office_short_path = "C:\\PROGRA~1\\OPENOF~1.ORG";
253 } else {
254 if (-d "/usr/lib/libreoffice") { # try libreoffice first
255 $office_short_path = "/usr/lib/libreoffice";
256 } elsif (-d "/usr/lib/openoffice") { # perhaps it's more likely that openoffice exists (fallback)
257 $office_short_path = "/usr/lib/openoffice";
258 } else { # set to default linux officeHome which jodconverter tries for
259 $office_short_path = "/opt/openoffice.org3";
260 }
261 }
262 }
263
264 # jodjar always assumes that soffice (officeHome) is in "C:\Prog Files\OpenOffice org 3"
265 # or "/opt/openoffice.org3" rather than checking for any user-defined SOFFICE_HOME var.
266 # Therefore, we run jodjar with the -Doffice.home flag explicitly set, instead of without.
267 # my $convert_cmd = "java -jar \"$jodjar\" --port $ENV{'JODCONVERTER_PORT'}";
268 my $convert_cmd = "java -Doffice.home=\"".$office_short_path."\" -jar \"$jodjar\" --port $ENV{'JODCONVERTER_PORT'}";
269 $convert_cmd .= " \"$source_file_full_path\" \"$target_file_path\"";
270
271 if ($verbosity>2) {
272 print $outhandle "Convert command: $convert_cmd\n";
273 }
274
275 my $print_info = { 'message_prefix' => "OpenOffice Conversion",
276 'message' => "Converting $source_file_no_path to: $target_file_type" };
277 $print_info->{'cache_mode'} = $cache_mode if ($cache_mode ne "");
278
279 my ($regenerated,$result,$had_error)
280 = $self->autorun_general_cmd($convert_cmd,$source_file_full_path, $target_file_path,$print_info);
281 if ($had_error) {
282 return (0, $result,$target_file_path);
283 }
284 return (1, $result,$target_file_path);
285}
286
287
288sub convert_without_result {
289 my $self = shift(@_);
290
291 my $source_file_path = shift(@_);
292 my $target_file_type = shift(@_);
293 my $convert_options = shift(@_) || "";
294 my $convert_id = shift(@_) || "";
295
296 return $self->convert($source_file_path,$target_file_type,
297 $convert_options,$convert_id,"without_result");
298}
299
300
301sub tmp_area_convert_fileXX {
302 my $self = shift (@_);
303 my ($output_ext, $input_filename, $textref) = @_;
304
305 my $outhandle = $self->{'outhandle'};
306 my $convert_to = $self->{'convert_to'};
307 my $failhandle = $self->{'failhandle'};
308 my $convert_to_ext = $self->{'convert_to_ext'};
309
310 # derive tmp filename from input filename
311 my ($tailname, $dirname, $suffix)
312 = &File::Basename::fileparse($input_filename, "\\.[^\\.]+\$");
313}
314
315
316sub clean_up_temporary_files {
317 my $self = shift(@_);
318
319 foreach my $ootmp_file_path (@{$self->{'ootmp_file_paths'}}) {
320 if (-e $ootmp_file_path) {
321 &util::rm($ootmp_file_path);
322 }
323 }
324
325 $self->{'ootmp_file_paths'} = ();
326}
327
328
329
3301;
Note: See TracBrowser for help on using the repository browser.