]> Creatis software - CreaPhase.git/blob - octave_packages/io-1.0.19/odsopen.m
Add a useful package (from Source forge) for octave
[CreaPhase.git] / octave_packages / io-1.0.19 / odsopen.m
1 ## Copyright (C) 2009,2010,2011,2012 Philip Nienhuis <prnienhuis at users.sf.net>
2 ## 
3 ## This program is free software; you can redistribute it and/or modify
4 ## it under the terms of the GNU General Public License as published by
5 ## the Free Software Foundation; either version 2 of the License, or
6 ## (at your option) any later version.
7 ## 
8 ## This program is distributed in the hope that it will be useful,
9 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
10 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 ## GNU General Public License for more details.
12 ## 
13 ## You should have received a copy of the GNU General Public License
14 ## along with Octave; see the file COPYING.  If not, see
15 ## <http://www.gnu.org/licenses/>.
16
17 ## -*- texinfo -*-
18 ## @deftypefn {Function File} @var{ods} = odsopen (@var{filename})
19 ## @deftypefnx {Function File} @var{ods} = odsopen (@var{filename}, @var{readwrite})
20 ## @deftypefnx {Function File} @var{ods} = odsopen (@var{filename}, @var{readwrite}, @var{reqintf})
21 ## Get a pointer to an OpenOffice_org spreadsheet in the form of return
22 ## argument @var{ods}.
23 ##
24 ## Calling odsopen without specifying a return argument is fairly useless!
25 ##
26 ## To make this function work at all, you need the Java package >= 1.2.5 plus
27 ## ODFtoolkit (version 0.7.5 or 0.8.6+) & xercesImpl, and/or jOpenDocument, and/or
28 ## OpenOffice.org (or clones) installed on your computer + proper javaclasspath
29 ## set. These interfaces are referred to as OTK, JOD, and UNO resp., and are
30 ## preferred in that order by default (depending on their presence).
31 ## For (currently experimental) UNO support, Octave-Java package 1.2.8 + latest
32 ## fixes is imperative; furthermore the relevant classes had best be added to
33 ## the javaclasspath by utility function chk_spreadsheet_support().
34 ##
35 ## @var{filename} must be a valid .ods OpenOffice.org file name including
36 ## .ods suffix. If @var{filename} does not contain any directory path,
37 ## the file is saved in the current directory.
38 ## For UNO bridge, filenames need to be in the form "file:///<path_to_file>/filename";
39 ## a URL will also work. If a plain file name is given (absolute or relative),
40 ## odsopen() will transform it into proper form.
41 ##
42 ## @var{readwrite} must be set to true or numerical 1 if writing to spreadsheet
43 ## is desired immediately after calling odsopen(). It merely serves proper
44 ## handling of file errors (e.g., "file not found" or "new file created").
45 ##
46 ## Optional input argument @var{reqintf} can be used to override the ODS
47 ## interface automatically selected by odsopen. Currently implemented interfaces
48 ## are 'OTK' (Java/ODF Toolkit), 'JOD' (Java/jOpenDocument) and 'UNO'
49 ## (Java/OpenOffice.org UNO bridge).
50 ##
51 ## Examples:
52 ##
53 ## @example
54 ##   ods = odsopen ('test1.ods');
55 ##   (get a pointer for reading from spreadsheet test1.ods)
56 ##
57 ##   ods = odsopen ('test2.ods', [], 'JOD');
58 ##   (as above, indicate test2.ods will be read from; in this case using
59 ##    the jOpenDocument interface is requested)
60 ## @end example
61 ##
62 ## @seealso {odsclose, odsread, oct2ods, ods2oct, odsfinfo, chk_spreadsheet_support}
63 ##
64 ## @end deftypefn
65
66 ## Author: Philip Nienhuis
67 ## Created: 2009-12-13
68 ## Updates: 
69 ## 2009-12-30 ....<forgot what is was >
70 ## 2010-01-17 Make sure proper dimensions are checked in parsed javaclasspath
71 ## 2010-01-24 Added warning when trying to create a new spreadsheet using jOpenDocument
72 ## 2010-03-01 Removed check for rt.jar in javaclasspath
73 ## 2010-03-04 Slight texinfo adaptation (reqd. odfdom version = 0.7.5)
74 ## 2010-03-14 Updated help text (section on readwrite)
75 ## 2010-06-01 Added check for jOpenDocument version + suitable warning
76 ## 2010-06-02 Added ";" to supress debug stuff around lines 115
77 ##     ''      Moved JOD version check to subfunc getodsinterfaces
78 ##     ''      Fiddled ods.changed flag when creating a spreadsheet to avoid unnamed 1st sheets
79 ## 2010-08-23 Added version field "odfvsn" to ods file ptr, set in getodsinterfaces() (odfdom)
80 ##     ''     Moved JOD version check to this func from subfunc getodsinterfaces()
81 ##     ''     Full support for odfdom 0.8.6 (in subfunc)
82 ## 2010-08-27 Improved help text
83 ## 2010-10-27 Improved tracking of file changes tru ods.changed
84 ## 2010-11-12 Small changes to help text
85 ##     ''     Added try-catch to file open sections to create fallback to other intf
86 ## 2011-05-06 Experimental UNO support
87 ## 2011-05-18 Creating new spreadsheet docs in UNO now works
88 ## 2011-06-06 Tamed down interface verbosity on first startup
89 ##     ''     Multiple requested interfaces now possible 
90 ## 2011-09-03 Reset chkintf if no ods support was found to allow full interface rediscovery
91 ##            (otherwise javaclasspath additions will never be picked up)
92 ## 2012-01-26 Fixed "seealso" help string
93 ## 2012-02-26 Added ";" to suppress echo of filename f UNO
94 ## 2012-06-06 Made interface checking routine less verbose when same requested interface
95 ##            was used consecutively
96 ##
97 ## Latest change on subfunctions below: 2012-06-08
98
99 function [ ods ] = odsopen (filename, rw=0, reqinterface=[])
100
101   persistent odsinterfaces; persistent chkintf; persistent lastintf;
102   if (isempty (chkintf))
103     odsinterfaces = struct ( "OTK", [], "JOD", [], "UNO", [] );
104     chkintf = 1;
105   endif
106   if (isempty (lastintf)); lastintf = '---'; endif 
107   
108   if (nargout < 1) usage ("ODS = odsopen (ODSfile, [Rw]). But no return argument specified!"); endif
109
110   if (~isempty (reqinterface))
111     if ~(ischar (reqinterface) || iscell (reqinterface)), usage ("Arg # 3 not recognized"); endif
112     # Turn arg3 into cell array if needed
113     if (~iscell (reqinterface)), reqinterface = {reqinterface}; endif
114     ## Check if previously used interface matches a requested interface
115     if (isempty (regexpi (reqinterface, lastintf, 'once'){1}))
116       ## New interface requested
117       odsinterfaces.OTK = 0; odsinterfaces.JOD = 0; odsinterfaces.UNO = 0;
118       for ii=1:numel (reqinterface)
119         reqintf = toupper (reqinterface {ii});
120         # Try to invoke requested interface(s) for this call. Check if it
121         # is supported anyway by emptying the corresponding var.
122         if     (strcmp (reqintf, 'OTK'))
123           odsinterfaces.OTK = [];
124         elseif (strcmp (reqintf, 'JOD'))
125           odsinterfaces.JOD = [];
126         elseif (strcmp (reqintf, 'UNO'))
127           odsinterfaces.UNO = [];
128         else 
129           usage (sprintf ("Unknown .ods interface \"%s\" requested. Only OTK, JOD or UNO supported\n", reqinterface{}));
130         endif
131       endfor
132       printf ("Checking requested interface(s):\n");
133       odsinterfaces = getodsinterfaces (odsinterfaces);
134       # Well, is/are the requested interface(s) supported on the system?
135       # FIXME check for multiple interfaces
136       odsintf_cnt = 0;
137       for ii=1:numel (reqinterface)
138         if (~odsinterfaces.(toupper (reqinterface{ii})))
139           # No it aint
140           printf ("%s is not supported.\n", toupper (reqinterface{ii}));
141         else
142           ++odsintf_cnt;
143         endif
144       endfor
145       # Reset interface check indicator if no requested support found
146       if (~odsintf_cnt)
147         chkintf = [];
148         ods = [];
149         return
150       endif
151     endif
152   endif
153   
154   # Var rw is really used to avoid creating files when wanting to read, or
155   # not finding not-yet-existing files when wanting to write.
156
157   if (rw), rw = 1; endif    # Be sure it's either 0 or 1 initially
158
159   # Check if ODS file exists. Set open mode based on rw argument
160   if (rw), fmode = 'r+b'; else fmode = 'rb'; endif
161   fid = fopen (filename, fmode);
162   if (fid < 0)
163     if (~rw)      # Read mode requested but file doesn't exist
164       err_str = sprintf ("File %s not found\n", filename);
165       error (err_str)
166     else        # For writing we need more info:
167       fid = fopen (filename, 'rb');  # Check if it can be opened for reading
168       if (fid < 0)  # Not found => create it
169         printf ("Creating file %s\n", filename);
170         rw = 3;
171       else      # Found but not writable = error
172         fclose (fid);  # Do not forget to close the handle neatly
173         error (sprintf ("Write mode requested but file %s is not writable\n", filename))
174       endif
175     endif
176   else
177     # close file anyway to avoid Java errors
178     fclose (fid);
179   endif
180
181 # Check for the various ODS interfaces. No problem if they've already
182 # been checked, getodsinterfaces (far below) just returns immediately then.
183
184   [odsinterfaces] = getodsinterfaces (odsinterfaces);
185
186 # Supported interfaces determined; now check ODS file type.
187
188   chk1 = strcmp (tolower (filename(end-3:end)), '.ods');
189   # Only jOpenDocument (JOD) can read from .sxc files, but only if odfvsn = 2
190   chk2 = strcmp (tolower (filename(end-3:end)), '.sxc');
191 #  if (~chk1)
192 #    error ("Currently ods2oct can only read reliably from .ods files")
193 #  endif
194
195   ods = struct ("xtype", [], "app", [], "filename", [], "workbook", [], "changed", 0, "limits", [], "odfvsn", []);
196
197   # Preferred interface = OTK (ODS toolkit & xerces), so it comes first. 
198   # Keep track of which interface is selected. Can be used for fallback to other intf
199   odssupport = 0;
200
201   if (odsinterfaces.OTK && ~odssupport)
202     # Parts after user gfterry in
203     # http://www.oooforum.org/forum/viewtopic.phtml?t=69060
204     odftk = 'org.odftoolkit.odfdom.doc';
205     try
206       if (rw > 2)
207         # New spreadsheet
208         wb = java_invoke ([odftk '.OdfSpreadsheetDocument'], 'newSpreadsheetDocument');
209       else
210         # Existing spreadsheet
211         wb = java_invoke ([odftk '.OdfDocument'], 'loadDocument', filename);
212       endif
213       ods.workbook = wb.getContentDom ();    # Reads the entire spreadsheet
214       ods.xtype = 'OTK';
215       ods.app = wb;
216       ods.filename = filename;
217       ods.odfvsn = odsinterfaces.odfvsn;
218       odssupport += 1;
219       lastintf = 'OTK';
220     catch
221       if (odsinterfaces.JOD && ~rw && chk2)
222         printf ('Couldn''t open file %s using OTK; trying .sxc format with JOD...\n', filename);
223       else
224         error ('Couldn''t open file %s using OTK', filename);
225       endif
226     end_try_catch
227   endif
228
229   if (odsinterfaces.JOD && ~odssupport)
230     file = java_new ('java.io.File', filename);
231     jopendoc = 'org.jopendocument.dom.spreadsheet.SpreadSheet';
232     try
233       if (rw > 2)
234         # Create an empty 2 x 2 default TableModel template
235         tmodel= java_new ('javax.swing.table.DefaultTableModel', 2, 2);
236         wb = java_invoke (jopendoc, 'createEmpty', tmodel);
237       else
238         wb = java_invoke (jopendoc, 'createFromFile', file);
239       endif
240       ods.workbook = wb;
241       ods.filename = filename;
242       ods.xtype = 'JOD';
243       ods.app = 'file';
244       # Check jOpenDocument version. This can only work here when a
245       # workbook has been opened
246       sh = ods.workbook.getSheet (0);
247       cl = sh.getCellAt (0, 0);
248       try
249         # 1.2b3 has public getValueType ()
250         cl.getValueType ();
251         ods.odfvsn = 3;
252       catch
253         # 1.2b2 has not
254         ods.odfvsn = 2;
255         printf ("NOTE: jOpenDocument v. 1.2b2 has limited functionality. Try upgrading to 1.2\n");
256       end_try_catch
257       odssupport += 2;
258       lastintf = 'JOD';
259     catch
260       error ('Couldn''t open file %s using JOD', filename);
261     end_try_catch
262   endif
263
264   if (odsinterfaces.UNO && ~odssupport)
265     # First the file name must be transformed into a URL
266     if (~isempty (strmatch ("file:///", filename)) || ~isempty (strmatch ("http:///", filename))...
267       || ~isempty (strmatch ("ftp:///", filename)) || ~isempty (strmatch ("www:///", filename)))
268       # Seems in proper shape for OOO (at first sight)
269     else
270       # Transform into URL form
271       fname = canonicalize_file_name (strsplit (filename, filesep){end});
272       # On Windows, change backslash file separator into forward slash
273       if (strcmp (filesep, "\\"))
274         tmp = strsplit (fname, filesep);
275         flen = numel (tmp);
276         tmp(2:2:2*flen) = tmp;
277         tmp(1:2:2*flen) = '/';
278         fname = [ tmp{:} ];
279       endif
280       filename = [ 'file://' fname ];
281     endif
282     try
283       xContext = java_invoke ("com.sun.star.comp.helper.Bootstrap", "bootstrap");
284       xMCF = xContext.getServiceManager ();
285       oDesktop = xMCF.createInstanceWithContext ("com.sun.star.frame.Desktop", xContext);
286       # Workaround:
287       unotmp = java_new ('com.sun.star.uno.Type', 'com.sun.star.frame.XComponentLoader');
288       aLoader = oDesktop.queryInterface (unotmp);
289       # Some trickery as Octave Java cannot create non-numeric arrays
290       lProps = javaArray ('com.sun.star.beans.PropertyValue', 1);
291       lProp = java_new ('com.sun.star.beans.PropertyValue', "Hidden", 0, true, []);
292       lProps(1) = lProp;
293       if (rw > 2)
294         xComp = aLoader.loadComponentFromURL ("private:factory/scalc", "_blank", 0, lProps);
295       else
296         xComp = aLoader.loadComponentFromURL (filename, "_blank", 0, lProps);
297       endif
298       # Workaround:
299       unotmp = java_new ('com.sun.star.uno.Type', 'com.sun.star.sheet.XSpreadsheetDocument');
300       # save in ods struct:
301       xSpdoc = xComp.queryInterface (unotmp);
302       ods.workbook = xSpdoc;      # Needed to be able to close soffice in odsclose()
303       ods.filename = filename;
304       ods.xtype = 'UNO';
305       ods.app.xComp = xComp;      # Needed to be able to close soffice in odsclose()
306       ods.app.aLoader = aLoader;  # Needed to be able to close soffice in odsclose()
307       ods.odfvsn = 'UNO';
308       odssupport += 4;
309       lastintf = 'UNO';
310     catch
311       error ('Couldn''t open file %s using UNO', filename);
312     end_try_catch
313   endif
314
315 #  if 
316 #    <other interfaces here>
317
318   if (~odssupport)
319     printf ("None.\n");
320     warning ("No support for OpenOffice.org .ods I/O"); 
321     ods = [];
322     chkintf = [];
323   else
324     # From here on rw is tracked via ods.changed in the various lower
325     # level r/w routines and it is only used to determine if an informative
326     # message is to be given when saving a newly created ods file.
327     ods.changed = rw;
328
329     # Until something was written to existing files we keep status "unchanged".
330     # ods.changed = 0 (existing/only read from), 1 (existing/data added), 2 (new,
331     # data added) or 3 (pristine, no data added).
332     if (ods.changed == 1) ods.changed = 0; endif
333   endif
334
335 endfunction
336
337
338 ## Copyright (C) 2009,2010,2011,2012 Philip Nienhuis <prnienhuis at users.sf.net>
339 ## 
340 ## This program is free software; you can redistribute it and/or modify
341 ## it under the terms of the GNU General Public License as published by
342 ## the Free Software Foundation; either version 2 of the License, or
343 ## (at your option) any later version.
344 ## 
345 ## This program is distributed in the hope that it will be useful,
346 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
347 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
348 ## GNU General Public License for more details.
349 ## 
350 ## You should have received a copy of the GNU General Public License
351 ## along with Octave; see the file COPYING.  If not, see
352 ## <http://www.gnu.org/licenses/>.
353
354 ## -*- texinfo -*-
355 ## @deftypefn {Function File} @var{odsinterfaces} = getodsinterfaces (@var{odsinterfaces})
356 ## Get supported OpenOffice.org .ods file read/write interfaces from
357 ## the system.
358 ## Each interface for which the corresponding field is set to empty
359 ## will be checked. So by manipulating the fields of input argument
360 ## @var{odsinterfaces} it is possible to specify which
361 ## interface(s) should be checked.
362 ##
363 ## Currently implemented interfaces comprise:
364 ## - Java & ODFtoolkit (www.apache.org)
365 ## - Java & jOpenDocument (www.jopendocument.org)
366 ## - Java & UNO bridge (OpenOffice.org)
367 ##
368 ## Examples:
369 ##
370 ## @example
371 ##   odsinterfaces = getodsinterfaces (odsinterfaces);
372 ## @end example
373
374 ## Author: Philip Nienhuis
375 ## Created: 2009-12-27
376 ## Updates:
377 ## 2010-01-14
378 ## 2010-01-17 Make sure proper dimensions are checked in parsed javaclasspath
379 ## 2010-04-11 Introduced check on odfdom.jar version - only 0.7.5 works properly
380 ## 2010-06-02 Moved in check on JOD version
381 ## 2010-06-05 Experimental odfdom 0.8.5 support
382 ## 2010-06-## dropped 0.8.5, too buggy
383 ## 2010-08-22 Experimental odfdom 0.8.6 support
384 ## 2010-08-23 Added odfvsn (odfdom version string) to output struct argument
385 ##     ''     Bugfix: moved JOD version check to main function (it can't work here)
386 ##     ''     Finalized odfdom 0.8.6 support (even prefered version now)
387 ## 2010-09-11 Somewhat clarified messages about missing java classes
388 ##     ''     Rearranged code a bit; fixed typos in OTK detection code (odfdvsn -> odfvsn)
389 ## 2010-09-27 More code cleanup
390 ## 2010-11-12 Warning added about waning support for odfdom v. 0.7.5
391 ## 2011-05-06 Fixed wrong strfind tests
392 ##     ''     Experimental UNO support added
393 ## 2011-05-18 Forgot to initialize odsinterfaces.UNO
394 ## 2011-06-06 Fix for javaclasspath format in *nix w. java-1.2.8 pkg
395 ##     ''     Implemented more rigid Java check
396 ##     ''     Tamed down verbosity
397 ## 2011-09-03 Fixed order of odsinterfaces.<member> statement in Java detection try-catch
398 ##     ''     Reset tmp1 (always allow interface rediscovery) for empty odsinterfaces arg
399 ## 2011-09-18 Added temporary warning about UNO interface
400 ## 2012-03-22 Improved Java checks (analogous to xlsopen)
401 ## 2012-06-06 Again improved & simplified Java-based interface checking support
402 ## 2012-06-08 Support for odfdom-0.8.8 (-incubator)
403
404 function [odsinterfaces] = getodsinterfaces (odsinterfaces)
405
406   # tmp1 = [] (not initialized), 0 (No Java detected), or 1 (Working Java found)
407   persistent tmp1 = []; persistent jcp;  # Java class path
408   persistent uno_1st_time = 0;
409
410   if (isempty (odsinterfaces.OTK) && isempty (odsinterfaces.JOD) && isempty (odsinterfaces.UNO))
411     # Assume no interface detection has happened yet
412     printf ("Detected ODS interfaces: ");
413     tmp1 = [];
414   elseif (isempty (odsinterfaces.OTK) || isempty (odsinterfaces.JOD) || isempty (odsinterfaces.UNO))
415     # Can't be first call. Here one of the Java interfaces is requested
416     if (~tmp1)
417       # Check Java support again
418       tmp1 = [];
419     endif
420   endif
421   deflt = 0;
422
423   if (isempty (tmp1))
424   # Check Java support
425     try
426       jcp = javaclasspath ("-all");          # For java pkg >= 1.2.8
427       if (isempty (jcp)), jcp = javaclasspath; endif  # For java pkg <  1.2.8
428       # If we get here, at least Java works. Now check for proper version (>= 1.6)
429       jver = char (java_invoke ('java.lang.System', 'getProperty', 'java.version'));
430       cjver = strsplit (jver, '.');
431       if (sscanf (cjver{2}, '%d') < 6)
432         warning ("\nJava version too old - you need at least Java 6 (v. 1.6.x.x)\n");
433         return
434       endif
435       # Now check for proper entries in class path. Under *nix the classpath
436       # must first be split up. In java 1.2.8+ javaclasspath is already a cell array
437       if (isunix && ~iscell (jcp)), jcp = strsplit (char (jcp), pathsep ()); endif
438       tmp1 = 1;
439     catch
440       # No Java support
441       tmp1 = 0;
442       if (isempty (odsinterfaces.OTK) || isempty (odsinterfaces.JOD) || isempty (odsinterfaces.UNO))
443         # Some or all Java-based interface explicitly requested; but no Java support
444         warning (' No Java support found (no Java JRE? no Java pkg installed AND loaded?');
445       endif
446       # No specific Java-based interface requested. Just return
447       odsinterfaces.OTK = 0;
448       odsinterfaces.JOD = 0;
449       odsinterfaces.UNO = 0;
450       printf ("\n");
451       return;
452     end_try_catch
453   endif
454
455   # Try Java & ODF toolkit
456   if (isempty (odsinterfaces.OTK))
457     odsinterfaces.OTK = 0;
458     jpchk = 0; entries = {"odfdom", "xercesImpl"};
459     # Only under *nix we might use brute force: e.g., strfind(classpath, classname);
460     # under Windows we need the following more subtle, platform-independent approach:
461     for ii=1:length (jcp)
462       for jj=1:length (entries)
463         if (~isempty (strfind ( jcp{ii}, entries{jj}))), ++jpchk; endif
464       endfor
465     endfor
466     if (jpchk >= numel(entries))    # Apparently all requested classes present.
467       # Only now we can check for proper odfdom version (only 0.7.5 & 0.8.6 work OK).
468       # The odfdom team deemed it necessary to change the version call so we need this:
469       odfvsn = ' ';
470       try
471         # New in 0.8.6
472         odfvsn = java_invoke ('org.odftoolkit.odfdom.JarManifest', 'getOdfdomVersion');
473       catch
474         odfvsn = java_invoke ('org.odftoolkit.odfdom.Version', 'getApplicationVersion');
475       end_try_catch
476       # For odfdom-incubator, strip extra info
477       odfvsn = regexp (odfvsn, '\d\.\d\.\d', "match"){1};
478       if ~(strcmp  (odfvsn, "0.7.5") || strcmp (odfvsn, "0.8.6") || strcmp (odfvsn, "0.8.7")
479         || strfind (odfvsn, "0.8.8"))
480         warning ("\nodfdom version %s is not supported - use v. 0.8.6 or later\n", odfvsn);
481       else
482         if (strcmp (odfvsn, '0.7.5'))
483           warning ("odfdom v. 0.7.5 support won't be maintained - please upgrade to 0.8.6 or higher."); 
484         endif
485         odsinterfaces.OTK = 1;
486         printf ("OTK");
487         if (deflt), printf ("; "); else, printf ("*; "); deflt = 1; endif
488       endif
489       odsinterfaces.odfvsn = odfvsn;
490     else
491       warning ("\nNot all required classes (.jar) in classpath for OTK");
492     endif
493   endif
494
495   # Try Java & jOpenDocument
496   if (isempty (odsinterfaces.JOD))
497     odsinterfaces.JOD = 0;
498     jpchk = 0; entries = {"jOpenDocument"};
499     for ii=1:length (jcp)
500       for jj=1:length (entries)
501         if (~isempty (strfind (jcp{ii}, entries{jj}))), ++jpchk; endif
502       endfor
503     endfor
504     if (jpchk >= numel(entries))
505       odsinterfaces.JOD = 1;
506       printf ("JOD");
507       if (deflt), printf ("; "); else, printf ("*; "); deflt = 1; endif
508     else
509       warning ("\nNot all required classes (.jar) in classpath for JOD");
510     endif
511   endif
512
513   # Try Java & UNO
514   if (isempty (odsinterfaces.UNO))
515     odsinterfaces.UNO = 0;
516     # entries(1) = not a jar but a directory (<000_install_dir/program/>)
517     jpchk = 0; entries = {'program', 'unoil', 'jurt', 'juh', 'unoloader', 'ridl'};
518     for jj=1:numel (entries)
519       for ii=1:numel (jcp)
520         jcplst = strsplit (jcp{ii}, filesep);
521         jcpentry = jcplst {end};
522         if (~isempty (strfind (lower (jcpentry), lower (entries{jj}))))
523           jpchk = jpchk + 1;
524         endif
525       endfor
526     endfor
527     if (jpchk >= numel (entries))
528       odsinterfaces.UNO = 1;
529       printf ("UNO");
530       if (deflt), printf ("; "); else, printf ("*; "); deflt = 1; uno_1st_time = min (++uno_1st_time, 2); endif
531     else
532       warning ("\nOne or more UNO classes (.jar) missing in javaclasspath");
533     endif
534   endif
535   
536   # ---- Other interfaces here, similar to the ones above
537
538   if (deflt), printf ("(* = active interface)\n"); endif
539
540   ## FIXME the below stanza should be dropped once UNO is stable.
541   # Echo a suitable warning about experimental status:
542   if (uno_1st_time == 1)
543     ++uno_1st_time;
544     printf ("\nPLEASE NOTE: UNO (=OpenOffice.org-behind-the-scenes) is EXPERIMENTAL\n");
545     printf ("After you've opened a spreadsheet file using the UNO interface,\n");
546     printf ("odsclose on that file will kill ALL OpenOffice.org invocations,\n");
547     printf ("also those that were started outside and/or before Octave!\n");
548     printf ("Trying to quit Octave w/o invoking odsclose will only hang Octave.\n\n");
549   endif
550   
551 endfunction