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

Last change on this file since 25218 was 25218, checked in by ak19, 12 years ago
  1. Cleaning up refs to the JODCONVERTER_PORT env var which has been phased out since it ought to be the same as SOFFICE_PORT to which it should connect. 2. The GLI OpenOffice extension plugin provides the option of changing the listening port. If changed, this change was previously not being transmitted to the actual command being run. This should now be the case, still requires testing.
  • Property svn:executable set to *
File size: 11.8 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 my $jodjar = &util::filename_cat($gextoo_home,"jodconverter-2.2.2","lib","jodconverter-cli-2.2.2.jar");
58
59 if (!-e $jodjar) {
60 #print STDERR "Failed to find $jodjar\n";
61 $openoffice_conversion_available = 0;
62 $no_openoffice_conversion_reason = "gextjodconverternotinstalled";
63 }
64 else {
65 # test to see if soffice is in path
66 my $cmd = "soffice -headless 2>&1"; # for linux and mac
67 my $status = 0;
68
69 # No more JODCONVERTER_PORT env var: the port that jodconverter uses is now the
70 # same as SOFFICE_PORT, because the 2 are meant to communicate on the same port.
71 # The default port that jodconverter expects OO to listen on is 8100, so we try that.
72 if ($ENV{'GSDLOS'} =~ m/^windows$/) {
73 if(!defined $ENV{'SOFFICE_HOST'}) {
74 $ENV{'SOFFICE_HOST'} = "localhost";
75 }
76 if(!defined $ENV{'SOFFICE_PORT'}) {
77 $ENV{'SOFFICE_PORT'} = "8100";
78 }
79 # important to have this set when the Greenstone server
80 # and open office is on a remote windows machine
81 if(!defined $ENV{'SOFFICE_HOME'}) {
82 $ENV{'SOFFICE_HOME'} = &util::filename_cat($ENV{'ProgramFiles'},"OpenOffice.org 3");
83 }
84 my $ooffice_dir_guess =
85 &util::filename_cat($ENV{'SOFFICE_HOME'},"program");
86 if (-d $ooffice_dir_guess) {
87 &util::envvar_append("PATH",$ooffice_dir_guess);
88 }
89
90 # for windows, when working on a remote system, want to be able to start OO if
91 # not already running. We'll use the uno socket method to do so. Else client-gli
92 # tends to hang, waiting for the prompt to return after OO has been started up
93 # (which doesn't happen, so need to Ctrl-C GLI and run it again for it to work).
94
95 # first need to silently check soffice exists else windows will display a popup
96 $status = system("which soffice >nul 2>&1"); # which.exe should be in bin/windows
97 if ($status == 0) {
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 cmd is still undefined
103 }
104 else {
105 # Windows seems to launch OpenOffice as a service (i.e.
106 # automatically puts it in the background).
107 # For Unix putting it in the background needs to be done
108 # explicitly
109
110 $cmd .= " >/dev/null &";
111 }
112
113 $status = system($cmd) if ($status == 0);
114 if ($status != 0) {
115 #print STDERR "Failed to run: $cmd\n";
116 #print STDERR "$!\n";
117 $openoffice_conversion_available = 0;
118 $no_openoffice_conversion_reason = "openofficenotinstalled";
119 }
120 }
121 }
122}
123
124my $arguments = [
125 { 'name' => "openoffice_port",
126 'desc' => "{OpenOfficeConverter.openoffice_port}",
127 'type' => "int",
128 'deft' => "8100",
129 'range' => "81,",
130 'reqd' => "no" },
131 ];
132
133
134my $options = { 'name' => "OpenOfficeConverter",
135 'desc' => "{OpenOfficeConverter.desc}",
136 'abstract' => "yes",
137 'inherits' => "yes",
138 'args' => $arguments };
139
140sub new {
141 my ($class) = shift (@_);
142 my ($pluginlist,$inputargs,$hashArgOptLists,$auxilary) = @_;
143 push(@$pluginlist, $class);
144
145 push(@{$hashArgOptLists->{"ArgList"}},@{$arguments});
146 push(@{$hashArgOptLists->{"OptList"}},$options);
147
148 my $self = new BaseMediaConverter($pluginlist, $inputargs,
149 $hashArgOptLists, $auxilary);
150
151 if ($self->{'info_only'}) {
152 # don't worry about any options etc
153 return bless $self, $class;
154 }
155 if (!$openoffice_conversion_available) {
156 $self->{'no_openoffice_conversion_reason'} = $no_openoffice_conversion_reason;
157
158 my $outhandle = $self->{'outhandle'};
159 &gsprintf($outhandle, "OpenOfficeConverter: {OpenOfficeConverter.noconversionavailable} ({OpenOfficeConverter.$no_openoffice_conversion_reason})\n");
160 }
161
162 $self->{'openoffice_conversion_available'} = $openoffice_conversion_available;
163
164 return bless $self, $class;
165
166}
167
168sub init {
169 my $self = shift(@_);
170 my ($verbosity, $outhandle, $failhandle) = @_;
171
172 if ($openoffice_conversion_available) {
173 my $oo_port = $self->{'openoffice_port'};
174
175 my $launch_cmd = "soffice";
176 $launch_cmd .= " \"-accept=socket,host=localhost,port=$oo_port;urp;StarOffice.ServiceManager\"";
177 $launch_cmd .= " -headless";
178 $self->{'openoffice_launch_cmd'} = $launch_cmd;
179 }
180
181 $self->{'ootmp_file_paths'} = ();
182}
183
184sub deinit {
185 my $self = shift(@_);
186
187 $self->clean_up_temporary_files();
188}
189
190
191sub convert {
192 my $self = shift(@_);
193 my $source_file_full_path = shift(@_);
194 my $target_file_type = shift(@_);
195 my $convert_options = shift(@_) || "";
196 my $convert_id = shift(@_) || "";
197 my $cache_mode = shift(@_) || "";
198
199 return (0,undef,undef) unless $openoffice_conversion_available;
200 # check the filename
201 return (0,undef,undef) if ( !-f $source_file_full_path);
202
203 my $outhandle = $self->{'outhandle'};
204 my $verbosity = $self->{'verbosity'};
205
206 my $source_file_no_path = &File::Basename::basename($source_file_full_path);
207 # Determine the full name and path of the output file
208 my $target_file_path;
209 if ($self->{'enable_cache'}) {
210 $self->init_cache_for_file($source_file_full_path);
211 my $cache_dir = $self->{'cached_dir'};
212 my $file_root = $self->{'cached_file_root'};
213 $file_root .= "_$convert_id" if ($convert_id ne "");
214 my $target_file = "$file_root.$target_file_type";
215 $target_file_path = &util::filename_cat($cache_dir,$target_file);
216 }
217 else {
218 $target_file_path = &util::get_timestamped_tmp_filename_in_collection($source_file_full_path, $target_file_type);
219 push(@{$self->{'ootmp_file_paths'}}, $target_file_path);
220 }
221
222 # Generate and run the convert command
223
224 my $gextoo_home = $ENV{'GEXT_OPENOFFICE'};
225 #my $jodjar = &util::filename_cat($gextoo_home,"lib","java","jodconverter.jar");
226 my $jodjar = &util::filename_cat($gextoo_home,"jodconverter-2.2.2","lib","jodconverter-cli-2.2.2.jar");
227
228 # debugging: print out all the env vars, when import's verbosity is high
229 #foreach my $key (sort(keys %ENV)) {
230 # print $outhandle "$key = $ENV{$key}\n";
231 #}
232
233# *If* SOFFICE_HOME\program was not added to the PATH, *another* way is to insert:
234# -Doffice.home=C:\\PROGRA~1\\OPENOF~1.ORG
235# into the command to launch jodconverter so that, when using the remote GS server
236# on Windows, jodconverter can find the openoffice installation:
237
238 my $office_short_path;
239 if(defined $ENV{'SOFFICE_HOME'}) { # points to libreoffice or openoffice, since soffice launches both
240 if ($ENV{'GSDLOS'} =~ m/^windows$/) {
241 $office_short_path = Win32::GetShortPathName($ENV{'SOFFICE_HOME'});
242 } else {
243 $office_short_path = $ENV{'SOFFICE_HOME'};
244 }
245 }
246 else { # SOFFICE_HOME not user-defined, try defaults
247 if ($ENV{'GSDLOS'} =~ m/^windows$/) {
248 $office_short_path = "C:\\PROGRA~1\\OPENOF~1.ORG";
249 } else {
250 if (-d "/usr/lib/libreoffice") { # try libreoffice first
251 $office_short_path = "/usr/lib/libreoffice";
252 } elsif (-d "/usr/lib/openoffice") { # perhaps it's more likely that openoffice exists (fallback)
253 $office_short_path = "/usr/lib/openoffice";
254 } else { # set to default linux officeHome which jodconverter tries for
255 $office_short_path = "/opt/openoffice.org3";
256 }
257 }
258 }
259
260 #if($self->{'openoffice_port'} != $ENV{'SOFFICE_PORT'}) { # if the user changed it
261 #$ENV{'SOFFICE_PORT'} = $self->{'openoffice_port'};
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{'SOFFICE_PORT'}";
268 my $convert_cmd = "java -Doffice.home=\"".$office_short_path."\" -jar \"$jodjar\" --port $self->{'openoffice_port'}"; # --port $ENV{'SOFFICE_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.