changeset 27876:76373f5113db

javaddpath.m: Allow cellstr inputs (bug #57487) * NEWS: Announce new feature. * javaaddpath.m: Add new function calling form to docstring. Add description of cellstr input to docstring. Redo input validation to check for strings or cell array of strings. Add new inner for loop to unpack each potential cell array of strings. Add BIST tests for functionality and input validation.
author Rik <rik@octave.org>
date Fri, 27 Dec 2019 10:13:17 -0800
parents 1ebfa73565fe
children 0850f7c37970
files NEWS scripts/java/javaaddpath.m
diffstat 2 files changed, 125 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Fri Dec 27 10:18:06 2019 -0500
+++ b/NEWS	Fri Dec 27 10:13:17 2019 -0800
@@ -152,7 +152,10 @@
   "Superclasslist" for Matlab compatibility.  The original name will
   exist as an alias until Octave version 8.1.
 
-- The function `javaaddpath` now prepends new directories to the existing dynamic classpath by default.  To append them instead, use the new `"-end"` argument.
+- The function `javaaddpath` now prepends new directories to the
+  existing dynamic classpath by default.  To append them instead, use
+  the new `"-end"` argument.  Multiple directories may now be specified
+  in a cell array of strings.
 
 - An undocumented function `gui_mainfcn` has been added, for compatibility
   with figures created with Matlab's Guide.
--- a/scripts/java/javaaddpath.m	Fri Dec 27 10:18:06 2019 -0500
+++ b/scripts/java/javaaddpath.m	Fri Dec 27 10:13:17 2019 -0800
@@ -20,16 +20,19 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {} javaaddpath (@var{clspath})
 ## @deftypefnx {} {} javaaddpath (@var{clspath1}, @dots{})
+## @deftypefnx {} {} javaaddpath (@{@var{clspath1}, @dots{}@})
 ## @deftypefnx {} {} javaaddpath (@dots{}, "-end")
-## Add @var{clspath} to the dynamic class path of the Java virtual machine.
+## Add @var{clspath} to the beginning of the dynamic class path of the
+## Java virtual machine.
 ##
 ## @var{clspath} may either be a directory where @file{.class} files are
 ## found, or a @file{.jar} file containing Java classes.  Multiple paths may
-## be added at once by specifying additional arguments.
+## be added at once by specifying additional arguments, or by using a cell
+## array of strings.
 ##
-## If the final argument is @code{"-end"}, append the new element to the
-## end of the current classpath.  Otherwise, new elements are added at
-## the beginning of the path.
+## If the final argument is @qcode{"-end"}, append the new element to the
+## end of the current classpath.
+##
 ## @seealso{javarmpath, javaclasspath}
 ## @end deftypefn
 
@@ -39,14 +42,13 @@
     print_usage ();
   endif
 
-  if (! iscellstr (varargin))
-    error ("javaaddpath: arguments must all be character strings");
+  if (! all (cellfun (@(c) ischar (c) || iscellstr (c), varargin)))
+    error ("javaaddpath: arguments must be strings or cell array of strings");
   endif
 
   if (strcmp (varargin{end}, "-end"))
     at_end = true;
-    nel = nargin - 1;
-    rng = 1:nel;
+    varargin(end) = [];
   else
     ## Note that when prepending, we iterate over the arguments in
     ## reverse so that a call like
@@ -54,28 +56,123 @@
     ##   javaaddpath ("/foo", "/bar")
     ##
     ## results in "/foo" first in the path followed by "/bar".
-    nel = nargin;
     at_end = false;
-    rng = nel:-1:1;
+    varargin = fliplr (varargin);
   endif
 
-  for i = rng
-    clspath = varargin{i};
-    new_path = canonicalize_file_name (tilde_expand (clspath));
-    if (isfolder (new_path))
-      if (new_path(end) != filesep ())
-        new_path = [new_path, filesep()];
+  for arg = varargin
+    if (iscellstr (arg{1}))
+      if (at_end)
+        ## Guarantee cellstr array is a row vector
+        arg = arg{1}(:).';
+      else
+        ## Iterate in reverse over cell arrays
+        arg = fliplr (arg{1}(:).');
       endif
-    elseif (! exist (new_path, "file"))
-      error ("javaaddpath: CLSPATH does not exist: %s", clspath);
     endif
 
-    success = javaMethod ("addClassPath", "org.octave.ClassHelper",
-                          new_path, at_end);
+    for clspath = arg
+      clspath = clspath{1};
 
-    if (! success)
-      warning ("javaaddpath: failed to add '%s' to Java classpath", new_path);
-    endif
+      new_path = canonicalize_file_name (tilde_expand (clspath));
+      if (isfolder (new_path))
+        if (new_path(end) != filesep ())
+          new_path = [new_path, filesep()];
+        endif
+      elseif (! exist (new_path, "file"))
+        error ("javaaddpath: CLSPATH does not exist: %s", clspath);
+      endif
+
+      success = javaMethod ("addClassPath", "org.octave.ClassHelper",
+                            new_path, at_end);
+
+      if (! success)
+        warning ("javaaddpath: failed to add '%s' to Java classpath", new_path);
+      endif
+    endfor
   endfor
 
 endfunction
+
+
+## FIXME: These tests may fail if either TEMPDIR or HOME have already
+##        been added to the Java class path.
+
+## Basic prepend test with single string
+%!test
+%! pth = tempdir ();
+%! unwind_protect
+%!   clspth1 = javaclasspath ("-dynamic");
+%!   javaaddpath (pth);
+%!   clspth2 = javaclasspath ("-dynamic");
+%!   assert (clspth2{1}, canonicalize_file_name (pth));
+%!   assert (clspth2(2:end), clspth1(1:end));
+%! unwind_protect_cleanup
+%!   javarmpath (pth);
+%! end_unwind_protect
+
+## Prepend test with two strings
+%!test
+%! pth1 = tempdir ();
+%! pth2 = tilde_expand ("~");
+%! unwind_protect
+%!   clspth1 = javaclasspath ("-dynamic");
+%!   javaaddpath (pth1, pth2);
+%!   clspth2 = javaclasspath ("-dynamic");
+%!   assert (clspth2([1, 2]),
+%!           {canonicalize_file_name(pth1), canonicalize_file_name(pth2)});
+%!   assert (clspth2(3:end), clspth1(1:end));
+%! unwind_protect_cleanup
+%!   javarmpath (pth1, pth2);
+%! end_unwind_protect
+
+## Prepend test with cell array of two strings
+%!test
+%! pth1 = tempdir ();
+%! pth2 = tilde_expand ("~");
+%! unwind_protect
+%!   clspth1 = javaclasspath ("-dynamic");
+%!   javaaddpath ({pth1, pth2});
+%!   clspth2 = javaclasspath ("-dynamic");
+%!   assert (clspth2([1, 2]),
+%!           {canonicalize_file_name(pth1), canonicalize_file_name(pth2)});
+%!   assert (clspth2(3:end), clspth1(1:end));
+%! unwind_protect_cleanup
+%!   javarmpath (pth1, pth2);
+%! end_unwind_protect
+
+## Append test with two strings
+%!test
+%! pth1 = tempdir ();
+%! pth2 = tilde_expand ("~");
+%! unwind_protect
+%!   clspth1 = javaclasspath ("-dynamic");
+%!   javaaddpath (pth1, pth2, "-end");
+%!   clspth2 = javaclasspath ("-dynamic");
+%!   assert (clspth2([end-1, end]),
+%!           {canonicalize_file_name(pth1), canonicalize_file_name(pth2)});
+%!   assert (clspth2(1:end-2), clspth1(1:end));
+%! unwind_protect_cleanup
+%!   javarmpath (pth1, pth2);
+%! end_unwind_protect
+
+## Append test with cell array of two strings
+%!test
+%! pth1 = tempdir ();
+%! pth2 = tilde_expand ("~");
+%! unwind_protect
+%!   clspth1 = javaclasspath ("-dynamic");
+%!   javaaddpath ({pth1, pth2}, "-end");
+%!   clspth2 = javaclasspath ("-dynamic");
+%!   assert (clspth2([end-1, end]),
+%!           {canonicalize_file_name(pth1), canonicalize_file_name(pth2)});
+%!   assert (clspth2(1:end-2), clspth1(1:end));
+%! unwind_protect_cleanup
+%!   javarmpath (pth1, pth2);
+%! end_unwind_protect
+
+## Test input validation
+%!error <Invalid call> javaaddpath ()
+%!error <arguments must be strings> javaaddpath (5)
+%!error <arguments must be .* cell array of strings> javaaddpath ({5})
+%!error <CLSPATH does not exist> javaaddpath ("%_A_Very_Unlikely_Name_%")