GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ov-java.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2007-2017 Michael Goffioul
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include "defun.h"
28 #include "error.h"
29 #include "errwarn.h"
30 #include "fpucw-wrappers.h"
31 
32 #if defined (HAVE_WINDOWS_H)
33 # include <windows.h>
34 #endif
35 
36 #include <algorithm>
37 #include <map>
38 #include <iostream>
39 #include <fstream>
40 #include <string>
41 
42 #include <clocale>
43 
44 #include "Cell.h"
45 #include "cmd-edit.h"
46 #include "defaults.h"
47 #include "file-ops.h"
48 #include "file-stat.h"
49 #include "load-path.h"
50 #include "oct-env.h"
51 #include "oct-shlib.h"
52 #include "ov-java.h"
53 #include "parse.h"
54 #include "variables.h"
55 
56 #if defined (HAVE_JAVA)
57 #include <jni.h>
58 #endif
59 
60 #if defined (HAVE_JAVA)
61 
62 #define TO_JOBJECT(obj) reinterpret_cast<jobject> (obj)
63 #define TO_JCLASS(obj) reinterpret_cast<jclass> (obj)
64 
65 #define TO_JNIENV(env) reinterpret_cast<JNIEnv *> (env)
66 
67 typedef jint (JNICALL *JNI_CreateJavaVM_t) (JavaVM **pvm, JNIEnv **penv,
68  void *args);
69 
70 typedef jint (JNICALL *JNI_GetCreatedJavaVMs_t) (JavaVM **pvm, jsize bufLen,
71  jsize *nVMs);
72 
73 template <typename T>
75 {
76 public:
77 
78  java_local_ref (JNIEnv *_env)
79  : jobj (0), detached (false), env (_env) { }
80 
81  java_local_ref (JNIEnv *_env, T obj)
82  : jobj (obj), detached (false), env (_env) { }
83 
84  ~java_local_ref (void) { release (); }
85 
86  T& operator = (T obj)
87  {
88  release ();
89 
90  jobj = obj;
91  detached = false;
92 
93  return jobj;
94  }
95 
96  operator bool () const { return (jobj != 0); }
97  operator T () { return jobj; }
98 
99  void detach (void) { detached = true; }
100 
101 private:
102 
103  void release (void)
104  {
105  if (env && jobj && ! detached)
106  env->DeleteLocalRef (jobj);
107 
108  jobj = 0;
109  }
110 
112  : jobj (0), detached (false), env (0)
113  { }
114 
115 protected:
116 
117  T jobj;
118  bool detached;
119  JNIEnv *env;
120 };
121 
130 
131 static std::string
132 jstring_to_string (JNIEnv* jni_env, jstring s);
133 
134 static std::string
135 jstring_to_string (JNIEnv* jni_env, jobject obj);
136 
137 static octave_value
138 box (JNIEnv* jni_env, void *jobj, void *jcls_arg = 0);
139 
140 static octave_value
141 box_more (JNIEnv* jni_env, void *jobj_arg, void *jcls_arg = 0);
142 
143 static bool
144 unbox (JNIEnv* jni_env, const octave_value& val, jobject_ref& jobj,
145  jclass_ref& jcls);
146 
147 static bool
148 unbox (JNIEnv* jni_env, const octave_value_list& args,
149  jobjectArray_ref& jobjs, jobjectArray_ref& jclss);
150 
151 extern "C"
152 {
153  JNIEXPORT jboolean JNICALL
154  Java_org_octave_Octave_call (JNIEnv *, jclass, jstring, jobjectArray,
155  jobjectArray);
156 
157  JNIEXPORT void JNICALL
159 
160  JNIEXPORT void JNICALL
161  Java_org_octave_Octave_doInvoke (JNIEnv *, jclass, jint, jobjectArray);
162 
163  JNIEXPORT void JNICALL
164  Java_org_octave_Octave_doEvalString (JNIEnv *, jclass, jstring);
165 
166  JNIEXPORT jboolean JNICALL
168 }
169 
170 static JavaVM *jvm = 0;
171 static bool jvm_attached = false;
172 
173 // Need to keep hold of the shared library handle until exit.
175 
176 static std::map<int,octave_value> listener_map;
177 static std::map<int,octave_value> octave_ref_map;
178 static int octave_java_refcount = 0;
179 static long octave_thread_ID = -1;
180 
183 bool Vdebug_java = false;
184 
185 namespace octave
186 {
187  class JVMArgs
188  {
189  public:
190 
191  JVMArgs (void)
192  {
193  vm_args.version = JNI_VERSION_1_2;
194  vm_args.nOptions = 0;
195  vm_args.options = 0;
196  vm_args.ignoreUnrecognized = false;
197  }
198 
199  ~JVMArgs (void)
200  {
201  clean ();
202  }
203 
204  JavaVMInitArgs *to_args ()
205  {
206  update ();
207  return &vm_args;
208  }
209 
210  void add (const std::string& opt)
211  {
212  java_opts.push_back (opt);
213  }
214 
216  {
217  std::ifstream js (filename.c_str ());
218 
219  if (! js.bad () && ! js.fail ())
220  {
222 
223  while (! js.eof () && ! js.fail ())
224  {
225  std::getline (js, line);
226 
227  if (line.find ("-") == 0)
228  java_opts.push_back (line);
229  else if (line.length () > 0 && Vdebug_java)
230  std::cerr << "invalid JVM option, skipping: " << line << std::endl;
231  }
232  }
233  }
234 
235  private:
236 
237  void clean (void)
238  {
239  if (vm_args.options != 0)
240  {
241  for (int i = 0; i < vm_args.nOptions; i++)
242  delete [] vm_args.options[i].optionString;
243 
244  delete [] vm_args.options;
245 
246  vm_args.options = 0;
247  vm_args.nOptions = 0;
248  }
249  }
250 
251  void update (void)
252  {
253  clean ();
254 
255  if (java_opts.size () > 0)
256  {
257  int index = 0;
258 
259  vm_args.nOptions = java_opts.size ();
260  vm_args.options = new JavaVMOption [vm_args.nOptions];
261 
262  for (std::list<std::string>::const_iterator it = java_opts.begin ();
263  it != java_opts.end (); ++it)
264  {
265  if (Vdebug_java)
266  std::cout << *it << std::endl;
267  vm_args.options[index++].optionString = strsave ((*it).c_str ());
268  }
269 
270  java_opts.clear ();
271  }
272  }
273 
274  private:
275 
276  JavaVMInitArgs vm_args;
277 
278  std::list<std::string> java_opts;
279  };
280 }
281 
282 #if defined (OCTAVE_USE_WINDOWS_API)
283 
284 static std::string
285 read_registry_string (const std::string& key, const std::string& value)
286 {
287  HKEY hkey;
288  DWORD len;
289 
291 
292  if (! RegOpenKeyEx (HKEY_LOCAL_MACHINE, key.c_str (), 0, KEY_READ, &hkey))
293  {
294  if (! RegQueryValueEx (hkey, value.c_str (), 0, 0, 0, &len))
295  {
296  retval.resize (len);
297  if (RegQueryValueEx (hkey, value.c_str (), 0, 0,
298  (LPBYTE)&retval[0], &len))
299  retval = "";
300  else if (retval[len-1] == '\0')
301  retval.resize (--len);
302  }
303  RegCloseKey (hkey);
304  }
305 
306  return retval;
307 }
308 
309 static std::string
310 get_module_filename (HMODULE hMod)
311 {
312  int n = 1024;
313  std::string retval (n, '\0');
314  bool found = false;
315 
316  while (n < 65536)
317  {
318  int status = GetModuleFileName (hMod, &retval[0], n);
319 
320  if (status < n)
321  {
322  retval.resize (n);
323  found = true;
324  break;
325  }
326  else
327  {
328  n *= 2;
329  retval.resize (n);
330  }
331  }
332 
333  return (found ? retval : "");
334 }
335 
336 #endif
337 
338 static std::string
340 {
341  static std::string java_dir;
342 
343  if (java_dir.empty ())
344  {
345  java_dir = octave::sys::env::getenv ("OCTAVE_JAVA_DIR");
346 
347  if (java_dir.empty ())
348  java_dir = Vfcn_file_dir + octave::sys::file_ops::dir_sep_str () + "java";
349  }
350 
351  return java_dir;
352 }
353 
354 // Read the content of a file filename (usually "classpath.txt")
355 //
356 // Returns a string with all lines concatenated and separated
357 // by the path separator character.
358 // The return string also starts with a path separator so that
359 // it can be appended easily to a base classpath.
360 //
361 // The file "classpath.txt" must contain single lines, each
362 // with a classpath.
363 // Comment lines starting with a '#' or a '%' in column 1 are allowed.
364 
365 static std::string
367 {
368  std::string classpath;
369 
370  std::ifstream fs (filepath.c_str ());
371 
372  if (! fs.bad () && ! fs.fail ())
373  {
375 
376  while (! fs.eof () && ! fs.fail ())
377  {
378  std::getline (fs, line);
379 
380  if (line.length () > 0)
381  {
382  if (line[0] == '#' || line[0] == '%')
383  ; // skip comments
384  else
385  {
386  // prepend separator character
387  classpath.append (octave::directory_path::path_sep_str ());
388 
389  // append content of line without whitespace
390  int last = line.find_last_not_of (" \t\f\v\r\n");
391 
392  classpath.append (octave::sys::file_ops::tilde_expand (line.substr (0, last+1)));
393  }
394  }
395  }
396  }
397 
398  return (classpath);
399 }
400 
401 static std::string
403 {
404  std::string java_dir = initial_java_dir ();
405 
406  std::string retval = java_dir;
407 
408  // find octave.jar file
409  if (! retval.empty ())
410  {
412 
413  std::string jar_file = java_dir + sep + "octave.jar";
414 
415  octave::sys::file_stat jar_exists (jar_file);
416 
417  if (jar_exists)
418  {
419  // initialize static classpath to octave.jar
420  retval = jar_file;
421 
422  // The base classpath has been set.
423  // Try to find an optional file specifying classpaths in 3 places.
424  // 1) Current directory
425  // 2) User's home directory
426  // 3) Octave installation directory where octave.jar resides
427 
430 
431  // The filename is "javaclasspath.txt", but historically
432  // has been "classpath.txt" so both are supported.
433  std::string cp_list[] = {"javaclasspath.txt", "classpath.txt"};
434 
435  for (int i=0; i<2; i++)
436  {
437  std::string filename = cp_list[i];
438  std::string cp_file = filename;
439  octave::sys::file_stat cp_exists;
440 
441  // Try to find classpath file in the current directory.
442 
443  cp_exists = octave::sys::file_stat (cp_file);
444  if (cp_exists)
445  {
446  // File found. Add its contents to the static classpath.
447  std::string classpath = read_classpath_txt (cp_file);
448  retval.append (classpath);
449  }
450 
451  // Try to find classpath file in the user's home directory.
452 
453  if (cwd != home_dir)
454  {
455  cp_file = "~" + sep + filename;
456  cp_file = octave::sys::file_ops::tilde_expand (cp_file);
457  cp_exists = octave::sys::file_stat (cp_file);
458  if (cp_exists)
459  {
460  // File found. Add its contents to the static classpath.
461  std::string classpath = read_classpath_txt (cp_file);
462  retval.append (classpath);
463  }
464  }
465 
466  // Try to find classpath file in the Octave install directory.
467 
468  if (cwd != java_dir)
469  {
470  cp_file = java_dir + sep + filename;
471  cp_exists = octave::sys::file_stat (cp_file);
472  if (cp_exists)
473  {
474  // File found. Add its contents to the static classpath.
475  std::string classpath = read_classpath_txt (cp_file);
476  retval.append (classpath);
477  }
478  }
479  }
480  }
481  else
482  error ("octave.jar does not exist: %s", jar_file.c_str ());
483  }
484  else
485  error ("initial java dir is empty");
486 
487  return retval;
488 }
489 
490 static void
492 {
493  // Most of the time JVM already exists and has been initialized.
494  if (jvm)
495  return;
496 
497  JNIEnv *current_env;
498  const char *static_locale = setlocale (LC_ALL, 0);
499  const std::string locale (static_locale);
500 
501 #if defined (OCTAVE_USE_WINDOWS_API)
502 
503  HMODULE hMod = GetModuleHandle ("jvm.dll");
504  std::string jvm_lib_path;
505 
506  if (hMod)
507  {
508  // JVM seems to be already loaded, better to use that DLL instead
509  // of looking in the registry, to avoid opening a different JVM.
510  jvm_lib_path = get_module_filename (hMod);
511 
512  if (jvm_lib_path.empty ())
513  error ("unable to find Java Runtime Environment");
514  }
515  else
516  {
517  // In windows, find the location of the JRE from the registry
518  // and load the symbol from the dll.
519  std::string key, value;
520 
521  key = "software\\javasoft\\java runtime environment";
522 
523  value = octave::sys::env::getenv ("JAVA_VERSION");
524  if (value.empty ())
525  {
526  value = "Currentversion";
527  std::string regval = read_registry_string (key,value);
528 
529  if (regval.empty ())
530  error ("unable to find Java Runtime Environment: %s::%s",
531  key.c_str (), value.c_str ());
532 
533  value = regval;
534  }
535 
536  key = key + "\\" + value;
537  value = "RuntimeLib";
538  jvm_lib_path = read_registry_string (key, value);
539 
540  if (jvm_lib_path.empty ())
541  error ("unable to find Java Runtime Environment: %s::%s",
542  key.c_str (), value.c_str ());
543  }
544 
545 #else
546 
547  // JAVA_LDPATH determined by configure and set in config.h
548 # if defined (__APPLE__)
549  std::string jvm_lib_path = JAVA_LDPATH + std::string ("/libjvm.dylib");
550 # else
551  std::string jvm_lib_path = JAVA_LDPATH + std::string ("/libjvm.so");
552 # endif
553 
554 #endif
555 
556  jsize nVMs = 0;
557 
558 #if ! defined (__APPLE__) && ! defined (__MACH__)
559 
560  octave::dynamic_library lib (jvm_lib_path);
561 
562  if (! lib)
563  error ("unable to load Java Runtime Environment from %s",
564  jvm_lib_path.c_str ());
565 
566  JNI_CreateJavaVM_t create_vm =
567  reinterpret_cast<JNI_CreateJavaVM_t> (lib.search ("JNI_CreateJavaVM"));
568  JNI_GetCreatedJavaVMs_t get_vm =
569  reinterpret_cast<JNI_GetCreatedJavaVMs_t> (lib.search ("JNI_GetCreatedJavaVMs"));
570 
571  if (! create_vm)
572  error ("unable to find JNI_CreateJavaVM in %s", jvm_lib_path.c_str ());
573 
574  if (! get_vm)
575  error ("unable to find JNI_GetCreatedJavaVMs in %s", jvm_lib_path.c_str ());
576 
577  if (get_vm (&jvm, 1, &nVMs) == 0 && nVMs > 0)
578 
579 #else
580 
581  // FIXME: There exists a problem on the Mac platform that
582  // octave::dynamic_library lib (jvm_lib_path)
583  // doesn't work with 'not-bundled' *.oct files.
584 
585  if (JNI_GetCreatedJavaVMs (&jvm, 1, &nVMs) == 0 && nVMs > 0)
586 
587 #endif
588 
589  {
590  // At least one JVM exists, try to attach to it
591 
592  switch (jvm->GetEnv (reinterpret_cast<void **> (&current_env),
593  JNI_VERSION_1_2))
594  {
595  case JNI_EDETACHED:
596  // Attach the current thread
597  JavaVMAttachArgs vm_args;
598  vm_args.version = JNI_VERSION_1_2;
599  vm_args.name = const_cast<char *> ("octave");
600  vm_args.group = 0;
601  if (jvm->AttachCurrentThread (reinterpret_cast<void **> (&current_env),
602  &vm_args) < 0)
603  error ("JVM internal error, unable to attach octave to existing JVM");
604  break;
605 
606  case JNI_EVERSION:
607  error ("JVM internal error, the required JNI version is not supported");
608  break;
609 
610  case JNI_OK:
611  // Don't do anything, the current thread is already attached to JVM
612  break;
613  }
614 
615  jvm_attached = true;
616  //printf ("JVM attached\n");
617  }
618  else
619  {
620  // No JVM exists, create one
621 
622  octave::JVMArgs vm_args;
623 
624  vm_args.add ("-Djava.class.path=" + initial_class_path ());
625  vm_args.add ("-Xrs");
626  vm_args.add ("-Djava.system.class.loader=org.octave.OctClassLoader");
627  vm_args.read_java_opts (initial_java_dir () +
629  "java.opts");
630 
631 #if ! defined (__APPLE__) && ! defined (__MACH__)
632 
633  if (create_vm (&jvm, &current_env, vm_args.to_args ()) != JNI_OK)
634  error ("unable to start Java VM in %s", jvm_lib_path.c_str ());
635  }
636 
637  jvm_lib = lib;
638 
639 #else
640 
641  if (JNI_CreateJavaVM (&jvm, reinterpret_cast<void **> (&current_env),
642  vm_args.to_args ()) != JNI_OK)
643  error ("unable to start Java VM in %s", jvm_lib_path.c_str ());
644 
645  }
646 
647 #endif
648 
649  setlocale (LC_ALL, locale.c_str ());
650 }
651 
652 static void
654 {
655  if (jvm)
656  {
657  if (jvm_attached)
658  jvm->DetachCurrentThread ();
659  else
660  jvm->DestroyJavaVM ();
661 
662  jvm = 0;
663  jvm_attached = false;
664 
665  if (jvm_lib)
666  jvm_lib.close ();
667 
669  }
670 }
671 
672 static std::string
673 jstring_to_string (JNIEnv *jni_env, jstring s)
674 {
676 
677  if (jni_env)
678  {
679  const char *cstr = jni_env->GetStringUTFChars (s, 0);
680  retval = cstr;
681  jni_env->ReleaseStringUTFChars (s, cstr);
682  }
683 
684  return retval;
685 }
686 
687 static std::string
688 jstring_to_string (JNIEnv *jni_env, jobject obj)
689 {
691 
692  if (jni_env && obj)
693  {
694  jclass_ref cls (jni_env, jni_env->FindClass ("java/lang/String"));
695  if (cls)
696  {
697  if (jni_env->IsInstanceOf (obj, cls))
698  retval = jstring_to_string (jni_env,
699  reinterpret_cast<jstring> (obj));
700  }
701  }
702 
703  return retval;
704 }
705 
706 static inline JNIEnv *
708 {
709  JNIEnv *env = 0;
710 
711  if (jvm)
712  jvm->GetEnv (reinterpret_cast<void **> (&env), JNI_VERSION_1_2);
713 
714  return env;
715 }
716 
717 #endif
718 
719 bool
721 {
722 #if defined (HAVE_JAVA)
723 
724  JNIEnv *current_env = thread_jni_env ();
725 
726  if (current_env && java_object)
727  {
728  jclass_ref cls (current_env, current_env->FindClass ("java/lang/String"));
729  return current_env->IsInstanceOf (TO_JOBJECT (java_object), cls);
730  }
731 
732  return false;
733 
734 #else
735 
736  // This shouldn't happen because construction of octave_java
737  // objects is supposed to be impossible if Java is not available.
738 
739  panic_impossible ();
740 
741 #endif
742 }
743 
744 bool
746 {
747 #if defined (HAVE_JAVA)
748 
749  JNIEnv *current_env = thread_jni_env ();
750 
751  std::string cls_cpp = cls_name;
752  std::replace (cls_cpp.begin (), cls_cpp.end (), '.', '/');
753 
754  if (current_env && java_object)
755  {
756  jclass_ref cls (current_env, current_env->FindClass (cls_cpp.c_str ()));
757  if (current_env->ExceptionCheck ())
758  current_env->ExceptionClear ();
759  else
760  return current_env->IsInstanceOf (TO_JOBJECT (java_object), cls);
761  }
762  return false;
763 
764 #else
765 
766  octave_unused_parameter (cls_name);
767 
768  // This shouldn't happen because construction of octave_java
769  // objects is supposed to be impossible if Java is not available.
770 
771  panic_impossible ();
772 
773 #endif
774 }
775 
776 #if defined (HAVE_JAVA)
777 
778 static octave_value
779 check_exception (JNIEnv *jni_env)
780 {
782 
783  jthrowable_ref ex (jni_env, jni_env->ExceptionOccurred ());
784 
785  if (ex)
786  {
787  if (Vdebug_java)
788  jni_env->ExceptionDescribe ();
789 
790  jni_env->ExceptionClear ();
791 
792  jclass_ref jcls (jni_env, jni_env->GetObjectClass (ex));
793  jmethodID mID = jni_env->GetMethodID (jcls, "toString",
794  "()Ljava/lang/String;");
795  jstring_ref js (jni_env,
796  reinterpret_cast<jstring> (jni_env->CallObjectMethod (ex, mID)));
797  std::string msg = jstring_to_string (jni_env, js);
798 
799  error ("[java] %s", msg.c_str ());
800  }
801  else
802  retval = Matrix ();
803 
804  return retval;
805 }
806 
807 static jclass
808 find_octave_class (JNIEnv *jni_env, const char *name)
809 {
810  static std::string class_loader;
811  static jclass uiClass = 0;
812 
813  jclass jcls = jni_env->FindClass (name);
814 
815  if (jcls == 0)
816  {
817  jni_env->ExceptionClear ();
818 
819  if (! uiClass)
820  {
821  if (class_loader.empty ())
822  {
823  jclass_ref syscls (jni_env,
824  jni_env->FindClass ("java/lang/System"));
825  jmethodID mID = jni_env->GetStaticMethodID
826  (syscls,
827  "getProperty",
828  "(Ljava/lang/String;)Ljava/lang/String;");
829  jstring_ref js (jni_env,
830  jni_env->NewStringUTF ("octave.class.loader"));
831  js = reinterpret_cast<jstring> (jni_env->CallStaticObjectMethod
832  (syscls, mID, jstring (js)));
833  class_loader = jstring_to_string (jni_env, jstring (js));
834  std::replace (class_loader.begin (), class_loader.end (),
835  '.', '/');
836  }
837 
838  jclass_ref uicls (jni_env,
839  jni_env->FindClass (class_loader.c_str ()));
840 
841  if (! uicls)
842  {
843  jni_env->ExceptionClear ();
844 
845  // Try the netbeans way
846  std::replace (class_loader.begin (), class_loader.end (),
847  '/', '.');
848  jclass_ref jcls2 (jni_env,
849  jni_env->FindClass ("org/openide/util/Lookup"));
850  jmethodID mID = jni_env->GetStaticMethodID
851  (jcls2, "getDefault", "()Lorg/openide/util/Lookup;");
852  jobject_ref lObj (jni_env,
853  jni_env->CallStaticObjectMethod (jcls2, mID));
854  mID = jni_env->GetMethodID (jcls2, "lookup",
855  "(Ljava/lang/Class;)Ljava/lang/Object;");
856  jclass_ref cLoaderCls (jni_env,
857  jni_env->FindClass ("java/lang/ClassLoader"));
858  jobject_ref cLoader (jni_env,
859  jni_env->CallObjectMethod
860  (lObj, mID, jclass (cLoaderCls)));
861  mID = jni_env->GetMethodID (cLoaderCls, "loadClass",
862  "(Ljava/lang/String;)Ljava/lang/Class;");
863  jstring_ref js (jni_env,
864  jni_env->NewStringUTF (class_loader.c_str ()));
865  uicls = reinterpret_cast<jclass>
866  (jni_env->CallObjectMethod (cLoader, mID, jstring (js)));
867  }
868 
869  if (uicls)
870  uiClass = reinterpret_cast<jclass>
871  (jni_env->NewGlobalRef (jclass (uicls)));
872  }
873 
874  if (uiClass)
875  {
876  jmethodID mID = jni_env->GetStaticMethodID
877  (uiClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
878  jstring_ref js (jni_env, jni_env->NewStringUTF (name));
879  jcls = reinterpret_cast<jclass>
880  (jni_env->CallStaticObjectMethod (uiClass, mID, jstring (js)));
881  }
882  }
883 
884  return jcls;
885 }
886 
887 static dim_vector
888 compute_array_dimensions (JNIEnv *jni_env, jobject obj)
889 {
890  jobjectArray_ref jobj (jni_env, reinterpret_cast<jobjectArray> (obj));
891  jclass_ref jcls (jni_env, jni_env->GetObjectClass (obj));
892  jclass_ref ccls (jni_env, jni_env->GetObjectClass (jcls));
893  jmethodID isArray_ID = jni_env->GetMethodID (ccls, "isArray", "()Z");
894  jmethodID getComponentType_ID = jni_env->GetMethodID (ccls,
895  "getComponentType",
896  "()Ljava/lang/Class;");
897 
898  dim_vector dv (1, 1);
899  int idx = 0;
900 
901  jobj.detach ();
902  while (jcls && jni_env->CallBooleanMethod (jcls, isArray_ID))
903  {
904  int len = (jobj ? jni_env->GetArrayLength (jobj) : 0);
905  if (idx >= dv.ndims ())
906  dv.resize (idx+1);
907  dv(idx) = len;
908  jcls = reinterpret_cast<jclass>
909  (jni_env->CallObjectMethod (jcls, getComponentType_ID));
910  jobj = len > 0
911  ? reinterpret_cast<jobjectArray> (jni_env->GetObjectArrayElement (jobj,
912  0))
913  : 0;
914  idx++;
915  }
916 
918 
919  return dv;
920 }
921 
922 static jobject
923 make_java_index (JNIEnv *jni_env, const octave_value_list& idx)
924 {
925  jclass_ref ocls (jni_env, jni_env->FindClass ("[I"));
926  jobjectArray retval = jni_env->NewObjectArray (idx.length (), ocls, 0);
927  // Here retval has the same length as idx
928 
929  // Fill in entries of idx into retval
930  for (int i = 0; i < idx.length (); i++)
931  try
932  {
933  idx_vector v = idx(i).index_vector ();
934 
935  jintArray_ref i_array (jni_env, jni_env->NewIntArray (v.length ()));
936  jint *buf = jni_env->GetIntArrayElements (i_array, 0);
937  // Here, buf points to the beginning of i_array
938 
939  // Copy v to buf
940  for (int k = 0; k < v.length (); k++)
941  buf[k] = v(k);
942 
943  // set retval[i]=i_array
944  jni_env->ReleaseIntArrayElements (i_array, buf, 0);
945  jni_env->SetObjectArrayElement (retval, i, i_array);
946 
947  check_exception (jni_env);
948  }
949  catch (octave::index_exception& e)
950  {
951  // Rethrow to allow more info to be reported later.
952  e.set_pos_if_unset (idx.length (), i+1);
953  throw;
954  }
955 
956  return retval;
957 }
958 
959 static octave_value
960 get_array_elements (JNIEnv *jni_env, jobject jobj,
961  const octave_value_list& idx)
962 {
964  jobject_ref resObj (jni_env);
965  jobject_ref java_idx (jni_env, make_java_index (jni_env, idx));
966 
967  jclass_ref helperClass (jni_env,
968  find_octave_class (jni_env,
969  "org/octave/ClassHelper"));
970  jmethodID mID = jni_env
971  ->GetStaticMethodID (helperClass, "arraySubsref",
972  "(Ljava/lang/Object;[[I)Ljava/lang/Object;");
973  resObj = jni_env->CallStaticObjectMethod
974  (helperClass, mID, jobj, jobject (java_idx));
975 
976  if (resObj)
977  retval = box (jni_env, resObj);
978  else
979  retval = check_exception (jni_env);
980 
982 
983  return retval;
984 }
985 
986 static octave_value
987 set_array_elements (JNIEnv *jni_env, jobject jobj,
988  const octave_value_list& idx, const octave_value& rhs)
989 {
991 
992  jclass_ref rhsCls (jni_env);
993  jobject_ref resObj (jni_env);
994  jobject_ref rhsObj (jni_env);
995  jobject_ref java_idx (jni_env, make_java_index (jni_env, idx));
996 
997  if (unbox (jni_env, rhs, rhsObj, rhsCls))
998  {
999  jclass_ref helperClass (jni_env,
1000  find_octave_class (jni_env,
1001  "org/octave/ClassHelper"));
1002  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "arraySubsasgn",
1003  "(Ljava/lang/Object;[[ILjava/lang/Object;)" "Ljava/lang/Object;");
1004  resObj = jni_env->CallStaticObjectMethod
1005  (helperClass, mID, jobj, jobject (java_idx), jobject (rhsObj));
1006  }
1007 
1008  if (resObj)
1009  retval = box (jni_env, resObj);
1010  else
1011  retval = check_exception (jni_env);
1012 
1014 
1015  return retval;
1016 }
1017 
1018 static string_vector
1019 get_invoke_list (JNIEnv *jni_env, void *jobj_arg)
1020 {
1021  jobject jobj = TO_JOBJECT (jobj_arg);
1022 
1023  std::list<std::string> name_list;
1024 
1025  if (jni_env)
1026  {
1027  jclass_ref cls (jni_env, jni_env->GetObjectClass (jobj));
1028  jclass_ref ccls (jni_env, jni_env->GetObjectClass (cls));
1029  jmethodID getMethods_ID = jni_env->GetMethodID
1030  (ccls, "getMethods", "()[Ljava/lang/reflect/Method;");
1031  jmethodID getFields_ID = jni_env->GetMethodID
1032  (ccls, "getFields", "()[Ljava/lang/reflect/Field;");
1033  jobjectArray_ref mList (jni_env,
1034  reinterpret_cast<jobjectArray>
1035  (jni_env->CallObjectMethod (cls, getMethods_ID)));
1036  jobjectArray_ref fList (jni_env,
1037  reinterpret_cast<jobjectArray>
1038  (jni_env->CallObjectMethod (cls, getFields_ID)));
1039  int mLen = jni_env->GetArrayLength (mList);
1040  int fLen = jni_env->GetArrayLength (fList);
1041  jclass_ref mCls (jni_env,
1042  jni_env->FindClass ("java/lang/reflect/Method"));
1043  jclass_ref fCls (jni_env,
1044  jni_env->FindClass ("java/lang/reflect/Field"));
1045  jmethodID m_getName_ID = jni_env->GetMethodID (mCls, "getName",
1046  "()Ljava/lang/String;");
1047  jmethodID f_getName_ID = jni_env->GetMethodID (fCls, "getName",
1048  "()Ljava/lang/String;");
1049 
1050  for (int i = 0; i < mLen; i++)
1051  {
1052  jobject_ref meth (jni_env, jni_env->GetObjectArrayElement (mList, i));
1053  jstring_ref methName (jni_env, reinterpret_cast<jstring>
1054  (jni_env->CallObjectMethod (meth, m_getName_ID)));
1055  name_list.push_back (jstring_to_string (jni_env, methName));
1056  }
1057 
1058  for (int i = 0; i < fLen; i++)
1059  {
1060  jobject_ref field (jni_env,
1061  jni_env->GetObjectArrayElement (fList, i));
1062  jstring_ref fieldName (jni_env,
1063  reinterpret_cast<jstring>
1064  (jni_env->CallObjectMethod
1065  (field, f_getName_ID)));
1066  name_list.push_back (jstring_to_string (jni_env, fieldName));
1067  }
1068 
1070  }
1071 
1072  string_vector v (name_list);
1073 
1074  return v.sort (true);
1075 }
1076 
1077 static octave_value
1078 convert_to_string (JNIEnv *jni_env, jobject java_object, bool force, char type)
1079 {
1081 
1082  if (jni_env && java_object)
1083  {
1084  jclass_ref cls (jni_env, jni_env->FindClass ("java/lang/String"));
1085 
1086  if (jni_env->IsInstanceOf (java_object, cls))
1087  retval = octave_value (jstring_to_string (jni_env, java_object), type);
1088  else if (force)
1089  {
1090  cls = jni_env->FindClass ("[Ljava/lang/String;");
1091 
1092  if (jni_env->IsInstanceOf (java_object, cls))
1093  {
1094  jobjectArray array = reinterpret_cast<jobjectArray> (java_object);
1095  int len = jni_env->GetArrayLength (array);
1096  Cell c (len, 1);
1097 
1098  for (int i = 0; i < len; i++)
1099  {
1100  jstring_ref js (jni_env,
1101  reinterpret_cast<jstring>
1102  (jni_env->GetObjectArrayElement (array, i)));
1103 
1104  if (js)
1105  c(i) = octave_value (jstring_to_string (jni_env, js), type);
1106  else
1107  c(i) = check_exception (jni_env);
1108  }
1109 
1110  retval = octave_value (c);
1111  }
1112  else
1113  {
1114  cls = jni_env->FindClass ("java/lang/Object");
1115  jmethodID mID = jni_env->GetMethodID (cls, "toString",
1116  "()Ljava/lang/String;");
1117  jstring_ref js (jni_env,
1118  reinterpret_cast<jstring>
1119  (jni_env->CallObjectMethod (java_object, mID)));
1120 
1121  if (js)
1122  retval = octave_value (jstring_to_string (jni_env, js), type);
1123  else
1124  retval = check_exception (jni_env);
1125  }
1126  }
1127  else
1128  error ("unable to convert Java object to string");
1129 
1131  }
1132 
1133  return retval;
1134 }
1135 
1136 #define TO_JAVA(obj) dynamic_cast<octave_java*> ((obj).internal_rep ())
1137 
1138 //! Return whether @c jobj shall be automatically converted to an Octave
1139 //! numeric value.
1140 //!
1141 //! If @c jobj is an instance of any of the numeric wrapper classes @c Byte,
1142 //! @c Integer, @c Long, @c Short, @c Float, or @c Double, then it will be
1143 //! converted using the @c java.lang.Number.doubleValue() method.
1144 //!
1145 //! @param jobj Java object being returned to Octave
1146 //! @return @c true if @c jobj shall be converted into a numeric value
1147 //! automatically, @c false otherwise
1148 static bool
1149 is_auto_convertible_number (JNIEnv *jni_env, jobject jobj)
1150 {
1151  jclass_ref cls (jni_env);
1152  cls = jni_env->FindClass ("java/lang/Double");
1153  if (jni_env->IsInstanceOf (jobj, cls))
1154  return true;
1155  cls = jni_env->FindClass ("java/lang/Float");
1156  if (jni_env->IsInstanceOf (jobj, cls))
1157  return true;
1158  cls = jni_env->FindClass ("java/lang/Byte");
1159  if (jni_env->IsInstanceOf (jobj, cls))
1160  return true;
1161  cls = jni_env->FindClass ("java/lang/Short");
1162  if (jni_env->IsInstanceOf (jobj, cls))
1163  return true;
1164  cls = jni_env->FindClass ("java/lang/Integer");
1165  if (jni_env->IsInstanceOf (jobj, cls))
1166  return true;
1167  cls = jni_env->FindClass ("java/lang/Long");
1168  if (jni_env->IsInstanceOf (jobj, cls))
1169  return true;
1170 
1171  return false;
1172 }
1173 
1174 //! Convert the Java object pointed to by @c jobj_arg with class @c jcls_arg
1175 //! to an Octave value.
1176 //!
1177 //! @param jni_env JNI environment pointer
1178 //! @param jobj_arg pointer to a Java object
1179 //! @param jcls_arg optional pointer to the Java class of @c jobj_arg
1180 //! @return
1181 //! @arg numeric value as a @c double if @c jobj_arg is of type @c Byte,
1182 //! @c Short, @c Integer, @c Long, @c Float or @c Double
1183 //! @arg logical value if @c jobj_arg is of type @c Boolean
1184 //! @arg string value if @c jobj_arg is of type @c Character or @c String
1185 //! @arg Octave array of numeric, logical, or char type if @c jobj_arg is
1186 //! a Java array of primitive types
1187 //! @arg Octave matrix if @c jobj_arg is of type @c org.octave.Matrix and
1188 //! #Vjava_matrix_autoconversion is enabled
1189 //! @arg Octave object if @c jobj_arg is of type @c org.octave.OctaveReference
1190 //! @arg @c octave_java object wrapping the Java object otherwise
1191 static octave_value
1192 box (JNIEnv *jni_env, void *jobj_arg, void *jcls_arg)
1193 {
1195 
1196  jobject jobj = TO_JOBJECT (jobj_arg);
1197  jclass jcls = TO_JCLASS (jcls_arg);
1198 
1199  jclass_ref cls (jni_env);
1200 
1201  if (! jobj)
1202  retval = Matrix ();
1203 
1204  while (retval.is_undefined ())
1205  {
1206  // Convert a scalar of any numeric class wrapping a primitive class
1207  // (byte, short, integer, long, float, double) to a double value.
1208  // Test whether java.lang.Number before testing for each type.
1209  cls = jni_env->FindClass ("java/lang/Number");
1210  if (jni_env->IsInstanceOf (jobj, cls)
1211  && is_auto_convertible_number (jni_env, jobj))
1212  {
1213  jmethodID m = jni_env->GetMethodID (cls, "doubleValue", "()D");
1214  retval = jni_env->CallDoubleMethod (jobj, m);
1215  break;
1216  }
1217 
1218  cls = jni_env->FindClass ("java/lang/Boolean");
1219  if (jni_env->IsInstanceOf (jobj, cls))
1220  {
1221  jmethodID m = jni_env->GetMethodID (cls, "booleanValue", "()Z");
1222  retval = (jni_env->CallBooleanMethod (jobj, m) ? true : false);
1223  break;
1224  }
1225 
1226  cls = jni_env->FindClass ("java/lang/String");
1227  if (jni_env->IsInstanceOf (jobj, cls))
1228  {
1229  retval = jstring_to_string (jni_env, jobj);
1230  break;
1231  }
1232 
1233  cls = jni_env->FindClass ("java/lang/Character");
1234  if (jni_env->IsInstanceOf (jobj, cls))
1235  {
1236  jmethodID m = jni_env->GetMethodID (cls, "charValue", "()C");
1237  retval = jni_env->CallCharMethod (jobj, m);
1238  retval = retval.convert_to_str (false, true);
1239  break;
1240  }
1241 
1242 #define BOX_PRIMITIVE_ARRAY(JAVA_TYPE, JAVA_ID, JAVA_TYPE_CAP, OCTAVE_ID) \
1243  cls = jni_env->FindClass (JAVA_ID); \
1244  if (jni_env->IsInstanceOf (jobj, cls)) \
1245  { \
1246  const JAVA_TYPE ## Array jarr = reinterpret_cast<JAVA_TYPE ## Array> (jobj); \
1247  const jsize len = jni_env->GetArrayLength (jarr); \
1248  OCTAVE_ID ## NDArray d (dim_vector (len, 1)); \
1249  JAVA_TYPE *buffer = reinterpret_cast<JAVA_TYPE *> (d.fortran_vec ()); \
1250  jni_env->Get ## JAVA_TYPE_CAP ## ArrayRegion (jarr, 0, len, buffer); \
1251  retval = d; \
1252  break; \
1253  }
1254 
1255  BOX_PRIMITIVE_ARRAY (jdouble, "[D", Double, )
1256  BOX_PRIMITIVE_ARRAY (jboolean, "[Z", Boolean, bool)
1257  BOX_PRIMITIVE_ARRAY (jfloat, "[F", Float, Float)
1258  BOX_PRIMITIVE_ARRAY (jchar, "[C", Char, char)
1259  BOX_PRIMITIVE_ARRAY (jbyte, "[B", Byte, int8)
1260  BOX_PRIMITIVE_ARRAY (jshort, "[S", Short, int16)
1261  BOX_PRIMITIVE_ARRAY (jint, "[I", Int, int32)
1262  BOX_PRIMITIVE_ARRAY (jlong, "[J", Long, int64)
1263 
1264 #undef BOX_PRIMITIVE_ARRAY
1265 
1266  if (Vjava_matrix_autoconversion)
1267  {
1268  cls = find_octave_class (jni_env, "org/octave/Matrix");
1269 
1270  if (jni_env->IsInstanceOf (jobj, cls))
1271  {
1272  jmethodID mID = jni_env->GetMethodID (cls, "getDims", "()[I");
1273  jintArray_ref iv (jni_env,
1274  reinterpret_cast<jintArray>
1275  (jni_env->CallObjectMethod (jobj, mID)));
1276  jint *iv_data = jni_env->GetIntArrayElements (jintArray (iv), 0);
1277  dim_vector dims;
1278  dims.resize (jni_env->GetArrayLength (jintArray (iv)));
1279 
1280  for (int i = 0; i < dims.ndims (); i++)
1281  dims(i) = iv_data[i];
1282 
1283  jni_env->ReleaseIntArrayElements (jintArray (iv), iv_data, 0);
1284  mID = jni_env->GetMethodID (cls, "getClassName",
1285  "()Ljava/lang/String;");
1286  jstring_ref js (jni_env,
1287  reinterpret_cast<jstring>
1288  (jni_env->CallObjectMethod (jobj, mID)));
1289 
1290  std::string s = jstring_to_string (jni_env, js);
1291 
1292  if (s == "double")
1293  {
1294  NDArray m (dims);
1295  mID = jni_env->GetMethodID (cls, "toDouble", "()[D");
1296  jdoubleArray_ref dv (jni_env,
1297  reinterpret_cast<jdoubleArray>
1298  (jni_env->CallObjectMethod (jobj, mID)));
1299  jni_env->GetDoubleArrayRegion (dv, 0,
1300  m.numel (),
1301  m.fortran_vec ());
1302  retval = m;
1303  break;
1304  }
1305  else if (s == "byte")
1306  {
1307  if (Vjava_unsigned_autoconversion)
1308  {
1309  uint8NDArray m (dims);
1310  mID = jni_env->GetMethodID (cls, "toByte", "()[B");
1311  jbyteArray_ref dv (jni_env,
1312  reinterpret_cast<jbyteArray>
1313  (jni_env->CallObjectMethod (jobj,
1314  mID)));
1315  jni_env->GetByteArrayRegion (dv, 0, m.numel (),
1316  reinterpret_cast<jbyte *>
1317  (m.fortran_vec ()));
1318  retval = m;
1319  break;
1320  }
1321  else
1322  {
1323  int8NDArray m (dims);
1324  mID = jni_env->GetMethodID (cls, "toByte", "()[B");
1325  jbyteArray_ref dv (jni_env,
1326  reinterpret_cast<jbyteArray>
1327  (jni_env->CallObjectMethod (jobj,
1328  mID)));
1329  jni_env->GetByteArrayRegion (dv, 0, m.numel (),
1330  reinterpret_cast<jbyte *>
1331  (m.fortran_vec ()));
1332  retval = m;
1333  break;
1334  }
1335  }
1336  else if (s == "integer")
1337  {
1338  if (Vjava_unsigned_autoconversion)
1339  {
1340  uint32NDArray m (dims);
1341  mID = jni_env->GetMethodID (cls, "toInt", "()[I");
1342  jintArray_ref dv (jni_env, reinterpret_cast<jintArray> (jni_env->CallObjectMethod (jobj, mID)));
1343  jni_env->GetIntArrayRegion (dv, 0, m.numel (), reinterpret_cast<jint *> (m.fortran_vec ()));
1344  retval = m;
1345  break;
1346  }
1347  else
1348  {
1349  int32NDArray m (dims);
1350  mID = jni_env->GetMethodID (cls, "toInt", "()[I");
1351  jintArray_ref dv (jni_env,
1352  reinterpret_cast<jintArray>
1353  (jni_env->CallObjectMethod (jobj,
1354  mID)));
1355  jni_env->GetIntArrayRegion (dv, 0, m.numel (),
1356  reinterpret_cast<jint *>
1357  (m.fortran_vec ()));
1358  retval = m;
1359  break;
1360  }
1361  }
1362  }
1363  }
1364 
1365  cls = find_octave_class (jni_env, "org/octave/OctaveReference");
1366  if (jni_env->IsInstanceOf (jobj, cls))
1367  {
1368  jmethodID mID = jni_env->GetMethodID (cls, "getID", "()I");
1369  int ID = jni_env->CallIntMethod (jobj, mID);
1370  std::map<int,octave_value>::iterator it = octave_ref_map.find (ID);
1371 
1372  if (it != octave_ref_map.end ())
1373  retval = it->second;
1374  break;
1375  }
1376 
1377  // No suitable class found. Return a generic octave_java object
1378  retval = octave_value (new octave_java (jobj, jcls));
1379  break;
1380  }
1381 
1382  return retval;
1383 }
1384 
1385 static octave_value
1386 box_more (JNIEnv *jni_env, void *jobj_arg, void *jcls_arg)
1387 {
1388  jobject jobj = TO_JOBJECT (jobj_arg);
1389  jclass jcls = TO_JCLASS (jcls_arg);
1390 
1391  octave_value retval = box (jni_env, jobj, jcls);
1392 
1393  if (retval.is_java ())
1394  {
1395  retval = octave_value ();
1396 
1397  jclass_ref cls (jni_env);
1398 
1399  if (retval.is_undefined ())
1400  {
1401  cls = jni_env->FindClass ("[D");
1402 
1403  if (jni_env->IsInstanceOf (jobj, cls))
1404  {
1405  jdoubleArray jarr = reinterpret_cast<jdoubleArray> (jobj);
1406  int len = jni_env->GetArrayLength (jarr);
1407 
1408  if (len > 0)
1409  {
1410  Matrix m (1, len);
1411  jni_env->GetDoubleArrayRegion (jarr, 0, len, m.fortran_vec ());
1412  retval = m;
1413  }
1414  else
1415  retval = Matrix ();
1416  }
1417  }
1418 
1419  if (retval.is_undefined ())
1420  {
1421  cls = jni_env->FindClass ("[[D");
1422 
1423  if (jni_env->IsInstanceOf (jobj, cls))
1424  {
1425  jobjectArray jarr = reinterpret_cast<jobjectArray> (jobj);
1426  int rows = jni_env->GetArrayLength (jarr);
1427  int cols = 0;
1428 
1429  if (rows > 0)
1430  {
1431  Matrix m;
1432 
1433  for (int r = 0; r < rows; r++)
1434  {
1435  jdoubleArray_ref row (jni_env,
1436  reinterpret_cast<jdoubleArray>
1437  (jni_env->GetObjectArrayElement
1438  (jarr, r)));
1439 
1440  if (m.is_empty ())
1441  {
1442  cols = jni_env->GetArrayLength (row);
1443  m.resize (cols, rows);
1444  }
1445  jni_env->GetDoubleArrayRegion
1446  (row, 0, cols, m.fortran_vec () + r * cols);
1447  }
1448  retval = m.transpose ();
1449  }
1450  else
1451  retval = Matrix ();
1452  }
1453  }
1454 
1455  if (retval.is_undefined ())
1456  {
1457  cls = jni_env->FindClass ("[Ljava/lang/String;");
1458 
1459  if (jni_env->IsInstanceOf (jobj, cls))
1460  {
1461  jobjectArray jarr = reinterpret_cast<jobjectArray> (jobj);
1462  int len = jni_env->GetArrayLength (jarr);
1463  Cell m (len, 1);
1464 
1465  for (int i = 0; i < len; i++)
1466  {
1467  jstring_ref js (jni_env,
1468  reinterpret_cast<jstring>
1469  (jni_env->GetObjectArrayElement (jarr, i)));
1470  m(i) = jstring_to_string (jni_env, js);
1471  }
1472 
1473  retval = m;
1474  }
1475  }
1476  }
1477 
1478  if (retval.is_undefined ())
1479  retval = octave_value (new octave_java (jobj, jcls));
1480 
1482 
1483  return retval;
1484 }
1485 
1486 static bool
1487 unbox (JNIEnv *jni_env, const octave_value& val, jobject_ref& jobj,
1488  jclass_ref& jcls)
1489 {
1490  bool found = true;
1491 
1492  if (val.is_java ())
1493  {
1494  octave_java *ovj = TO_JAVA (val);
1495  jobj = TO_JOBJECT (ovj->to_java ());
1496  jobj.detach ();
1497  jcls = jni_env->GetObjectClass (jobj);
1498  }
1499  else if (val.is_string ())
1500  {
1501  std::string s = val.string_value ();
1502 
1503  jobj = jni_env->NewStringUTF (s.c_str ());
1504  jcls = jni_env->GetObjectClass (jobj);
1505  }
1506  else if (val.is_cellstr ())
1507  {
1508  const Array<std::string> str_arr = val.cellstr_value ();
1509  const octave_idx_type n = str_arr.numel ();
1510 
1511  jclass_ref scls (jni_env, jni_env->FindClass ("java/lang/String"));
1512  jobjectArray array = jni_env->NewObjectArray (n, scls, NULL);
1513 
1514  for (octave_idx_type i = 0; i < n; i++)
1515  {
1516  jstring_ref jstr (jni_env, jni_env->NewStringUTF
1517  (str_arr(i).c_str ()));
1518  jni_env->SetObjectArrayElement (array, i, jstr);
1519  }
1520 
1521  jobj = array;
1522  jcls = jni_env->GetObjectClass (jobj);
1523  }
1524  else if (val.numel () > 1 && val.dims ().is_vector ())
1525  {
1526  // FIXME: Is there any way to avoid code duplication here without
1527  // using a macro?
1528 
1529 #define UNBOX_PRIMITIVE_ARRAY(METHOD_T, OCTAVE_T, JAVA_T, JAVA_T_CAP) \
1530  do \
1531  { \
1532  const OCTAVE_T ## NDArray v = val.METHOD_T ## array_value (); \
1533  JAVA_T ## Array jarr = jni_env->New ## JAVA_T_CAP ## Array (v.numel ()); \
1534  const JAVA_T *jv = reinterpret_cast<const JAVA_T*> (v.data ()); \
1535  jni_env->Set ## JAVA_T_CAP ## ArrayRegion (jarr, 0, v.numel (), jv); \
1536  jobj = reinterpret_cast<jobject> (jarr); \
1537  jcls = jni_env->GetObjectClass (jobj); \
1538  } \
1539  while (0)
1540 
1541  // Note that we do NOT handle char here because they are unboxed
1542  // into a String[], not into a char array
1543 
1544  if (val.is_double_type ())
1545  UNBOX_PRIMITIVE_ARRAY ( , , jdouble, Double);
1546  else if (val.is_bool_type ())
1547  UNBOX_PRIMITIVE_ARRAY (bool_, bool, jboolean, Boolean);
1548  else if (val.is_float_type ())
1549  UNBOX_PRIMITIVE_ARRAY (float_, Float, jfloat, Float);
1550  else if (val.is_int8_type ())
1551  UNBOX_PRIMITIVE_ARRAY (int8_, int8, jbyte, Byte);
1552  else if (val.is_uint8_type ())
1553  UNBOX_PRIMITIVE_ARRAY (uint8_, uint8, jbyte, Byte);
1554  else if (val.is_int16_type ())
1555  UNBOX_PRIMITIVE_ARRAY (int16_, int16, jshort, Short);
1556  else if (val.is_uint16_type ())
1557  UNBOX_PRIMITIVE_ARRAY (uint16_, uint16, jshort, Short);
1558  else if (val.is_int32_type ())
1559  UNBOX_PRIMITIVE_ARRAY (int32_, int32, jint, Int);
1560  else if (val.is_uint32_type ())
1561  UNBOX_PRIMITIVE_ARRAY (uint32_, uint32, jint, Int);
1562  else if (val.is_int64_type ())
1563  UNBOX_PRIMITIVE_ARRAY (int64_, int64, jlong, Long);
1564  else if (val.is_uint64_type ())
1565  UNBOX_PRIMITIVE_ARRAY (uint64_, uint64, jlong, Long);
1566 
1567 #undef UNBOX_PRIMITIVE_ARRAY
1568  }
1569  else if (val.is_real_scalar () || val.is_bool_scalar ())
1570  {
1571  // FIXME: Is there any way to avoid code duplication here without
1572  // using a macro?
1573 
1574 #define UNBOX_PRIMITIVE_SCALAR(OCTAVE_T, METHOD_T, JAVA_T, JAVA_CON) \
1575  do \
1576  { \
1577  const OCTAVE_T ov = val.METHOD_T ## _value (); \
1578  jclass_ref dcls (jni_env, jni_env->FindClass (JAVA_T)); \
1579  const jfieldID fid = jni_env->GetStaticFieldID (dcls, "TYPE", "Ljava/lang/Class;"); \
1580  const jmethodID mid = jni_env->GetMethodID (dcls, "<init>", JAVA_CON); \
1581  jcls = reinterpret_cast<jclass> (jni_env->GetStaticObjectField (dcls, fid)); \
1582  jobj = jni_env->NewObject (dcls, mid, ov); \
1583  } \
1584  while (0)
1585 
1586  if (val.is_double_type ())
1587  UNBOX_PRIMITIVE_SCALAR (double, double, "java/lang/Double", "(D)V");
1588  else if (val.is_bool_type ())
1589  UNBOX_PRIMITIVE_SCALAR (bool, bool, "java/lang/Boolean", "(Z)V");
1590  else if (val.is_float_type ())
1591  UNBOX_PRIMITIVE_SCALAR (float, float, "java/lang/Float", "(F)V");
1592  else if (val.is_int8_type ())
1593  UNBOX_PRIMITIVE_SCALAR (int8_t, int8_scalar, "java/lang/Byte", "(B)V");
1594  else if (val.is_uint8_type ())
1595  UNBOX_PRIMITIVE_SCALAR (uint8_t, uint8_scalar, "java/lang/Byte", "(B)V");
1596  else if (val.is_int16_type ())
1597  UNBOX_PRIMITIVE_SCALAR (int16_t, int16_scalar, "java/lang/Short", "(S)V");
1598  else if (val.is_uint16_type ())
1599  UNBOX_PRIMITIVE_SCALAR (uint16_t, uint16_scalar, "java/lang/Short", "(S)V");
1600  else if (val.is_int32_type ())
1601  UNBOX_PRIMITIVE_SCALAR (int32_t, int32_scalar, "java/lang/Integer", "(I)V");
1602  else if (val.is_uint32_type ())
1603  UNBOX_PRIMITIVE_SCALAR (uint32_t, uint32_scalar, "java/lang/Integer", "(I)V");
1604  else if (val.is_int64_type ())
1605  UNBOX_PRIMITIVE_SCALAR (int64_t, int64_scalar, "java/lang/Long", "(J)V");
1606  else if (val.is_uint64_type ())
1607  UNBOX_PRIMITIVE_SCALAR (uint64_t, uint64_scalar, "java/lang/Long", "(J)V");
1608 
1609 #undef UNBOX_PRIMITIVE_SCALAR
1610  }
1611  else if (val.is_empty ())
1612  {
1613  jobj = 0;
1614  jcls = 0;
1615  //jcls = jni_env->FindClass ("java/lang/Object");
1616  }
1617  else if (! Vjava_matrix_autoconversion
1618  && ((val.is_real_matrix ()
1619  && (val.rows () == 1 || val.columns () == 1))
1620  || val.is_range ()))
1621  {
1622  Matrix m = val.matrix_value ();
1623  jdoubleArray dv = jni_env->NewDoubleArray (m.numel ());
1624  jni_env->SetDoubleArrayRegion (dv, 0, m.numel (), m.fortran_vec ());
1625  jobj = dv;
1626  jcls = jni_env->GetObjectClass (jobj);
1627  }
1628  else if (Vjava_matrix_autoconversion
1629  && (val.is_matrix_type () || val.is_range ())
1630  && val.is_real_type ())
1631  {
1632  jclass_ref mcls (jni_env, find_octave_class (jni_env,
1633  "org/octave/Matrix"));
1634  dim_vector dims = val.dims ();
1635  jintArray_ref iv (jni_env, jni_env->NewIntArray (dims.ndims ()));
1636  jint *iv_data = jni_env->GetIntArrayElements (jintArray (iv), 0);
1637 
1638  for (int i = 0; i < dims.ndims (); i++)
1639  iv_data[i] = dims(i);
1640 
1641  jni_env->ReleaseIntArrayElements (jintArray (iv), iv_data, 0);
1642 
1643  if (val.is_double_type ())
1644  {
1645  NDArray m = val.array_value ();
1646  jdoubleArray_ref dv (jni_env, jni_env->NewDoubleArray (m.numel ()));
1647  jni_env->SetDoubleArrayRegion (jdoubleArray (dv), 0, m.numel (),
1648  m.fortran_vec ());
1649  jmethodID mID = jni_env->GetMethodID (mcls, "<init>", "([D[I)V");
1650  jobj = jni_env->NewObject (jclass (mcls), mID, jdoubleArray (dv),
1651  jintArray (iv));
1652  jcls = jni_env->GetObjectClass (jobj);
1653  }
1654  else if (val.is_int8_type ())
1655  {
1656  int8NDArray m = val.int8_array_value ();
1657  jbyteArray_ref bv (jni_env, jni_env->NewByteArray (m.numel ()));
1658  jni_env->SetByteArrayRegion (jbyteArray (bv), 0, m.numel (),
1659  reinterpret_cast<jbyte *>
1660  (m.fortran_vec ()));
1661  jmethodID mID = jni_env->GetMethodID (mcls, "<init>", "([B[I)V");
1662  jobj = jni_env->NewObject
1663  (jclass (mcls), mID, jbyteArray (bv), jintArray (iv));
1664  jcls = jni_env->GetObjectClass (jobj);
1665  }
1666  else if (val.is_uint8_type ())
1667  {
1668  uint8NDArray m = val.uint8_array_value ();
1669  jbyteArray_ref bv (jni_env, jni_env->NewByteArray (m.numel ()));
1670  jni_env->SetByteArrayRegion (jbyteArray (bv), 0, m.numel (),
1671  reinterpret_cast<jbyte *>
1672  (m.fortran_vec ()));
1673  jmethodID mID = jni_env->GetMethodID (mcls, "<init>", "([B[I)V");
1674  jobj = jni_env->NewObject
1675  (jclass (mcls), mID, jbyteArray (bv), jintArray (iv));
1676  jcls = jni_env->GetObjectClass (jobj);
1677  }
1678  else if (val.is_int32_type ())
1679  {
1680  int32NDArray m = val.int32_array_value ();
1681  jintArray_ref v (jni_env, jni_env->NewIntArray (m.numel ()));
1682  jni_env->SetIntArrayRegion (jintArray (v), 0, m.numel (),
1683  reinterpret_cast<jint *>
1684  (m.fortran_vec ()));
1685  jmethodID mID = jni_env->GetMethodID (mcls, "<init>", "([I[I)V");
1686  jobj = jni_env->NewObject
1687  (jclass (mcls), mID, jintArray (v), jintArray (iv));
1688  jcls = jni_env->GetObjectClass (jobj);
1689  }
1690  else
1691  {
1692  found = false;
1693  error ("cannot convert matrix of type '%s'",
1694  val.class_name ().c_str ());
1695  }
1696  }
1697  else
1698  {
1699  jclass rcls = find_octave_class (jni_env, "org/octave/OctaveReference");
1700  jmethodID mID = jni_env->GetMethodID (rcls, "<init>", "(I)V");
1701  int ID = octave_java_refcount++;
1702 
1703  jobj = jni_env->NewObject (rcls, mID, ID);
1704  jcls = rcls;
1705  octave_ref_map[ID] = val;
1706  }
1707 
1708  return found;
1709 }
1710 
1711 static bool
1712 unbox (JNIEnv *jni_env, const octave_value_list& args,
1713  jobjectArray_ref& jobjs, jobjectArray_ref& jclss)
1714 {
1715  bool found = true;
1716 
1717  jclass_ref ocls (jni_env, jni_env->FindClass ("java/lang/Object"));
1718  jclass_ref ccls (jni_env, jni_env->FindClass ("java/lang/Class"));
1719 
1720  if (! jobjs)
1721  jobjs = jni_env->NewObjectArray (args.length (), ocls, 0);
1722 
1723  if (! jclss)
1724  jclss = jni_env->NewObjectArray (args.length (), ccls, 0);
1725 
1726  for (int i = 0; i < args.length (); i++)
1727  {
1728  jobject_ref jobj (jni_env);
1729  jclass_ref jcls (jni_env);
1730 
1731  found = unbox (jni_env, args(i), jobj, jcls);
1732  if (! found)
1733  break;
1734 
1735  jni_env->SetObjectArrayElement (jobjs, i, jobj);
1736  jni_env->SetObjectArrayElement (jclss, i, jcls);
1737  }
1738 
1739  return found;
1740 }
1741 
1742 static long
1743 get_current_thread_ID (JNIEnv *jni_env)
1744 {
1745  if (jni_env)
1746  {
1747  jclass_ref cls (jni_env, jni_env->FindClass ("java/lang/Thread"));
1748  jmethodID mID = jni_env->GetStaticMethodID (cls, "currentThread",
1749  "()Ljava/lang/Thread;");
1750  jobject_ref jthread (jni_env, jni_env->CallStaticObjectMethod (cls, mID));
1751 
1752  if (jthread)
1753  {
1754  jclass_ref jth_cls (jni_env, jni_env->GetObjectClass (jthread));
1755  mID = jni_env->GetMethodID (jth_cls, "getId", "()J");
1756  long result = jni_env->CallLongMethod (jthread, mID);
1757  //printf ("current java thread ID = %ld\n", result);
1758  return result;
1759  }
1760  }
1761 
1762  return -1;
1763 }
1764 
1765 static int
1767 {
1768  JNIEnv *current_env = thread_jni_env ();
1769 
1770  if (current_env)
1771  {
1772  jclass_ref cls (current_env, find_octave_class (current_env,
1773  "org/octave/Octave"));
1774  jmethodID mID = current_env->GetStaticMethodID
1775  (cls, "checkPendingAction", "()V");
1776  current_env->CallStaticVoidMethod (cls, mID);
1777 
1779  }
1780 
1781  return 0;
1782 }
1783 
1784 static void
1786 {
1787  if (! jvm)
1788  {
1789  try
1790  {
1791  initialize_jvm ();
1792 
1793  JNIEnv *current_env = thread_jni_env ();
1794 
1796 
1797  octave_thread_ID = get_current_thread_ID (current_env);
1798  //printf ("octave thread ID=%ld\n", octave_thread_ID);
1799  }
1800  catch (std::string msg)
1801  {
1802  error (msg.c_str ());
1803  }
1804 
1806  }
1807 }
1808 
1809 JNIEXPORT jboolean JNICALL
1810 Java_org_octave_Octave_call (JNIEnv *env, jclass, jstring funcName,
1811  jobjectArray argin, jobjectArray argout)
1812 {
1813  std::string fname = jstring_to_string (env, funcName);
1814 
1815  int nargout = env->GetArrayLength (argout);
1816  int nargin = env->GetArrayLength (argin);
1817 
1818  octave_value_list varargin, varargout;
1819 
1820  for (int i = 0; i < nargin; i++)
1821  varargin(i) = box (env, env->GetObjectArrayElement (argin, i), 0);
1822 
1823  varargout = feval (fname, varargin, nargout);
1824 
1825  jobjectArray_ref out_objs (env, argout), out_clss (env);
1826  out_objs.detach ();
1827  return unbox (env, varargout, out_objs, out_clss);
1828 }
1829 
1830 JNIEXPORT void JNICALL
1832 {
1833  octave_ref_map.erase (ID);
1834 }
1835 
1836 JNIEXPORT void JNICALL
1837 Java_org_octave_Octave_doInvoke (JNIEnv *env, jclass, jint ID,
1838  jobjectArray args)
1839 {
1840  std::map<int,octave_value>::iterator it = octave_ref_map.find (ID);
1841 
1842  if (it != octave_ref_map.end ())
1843  {
1844  octave_value val = it->second;
1845  int len = env->GetArrayLength (args);
1846  octave_value_list oct_args;
1847 
1848  for (int i = 0; i < len; i++)
1849  {
1850  jobject_ref jobj (env, env->GetObjectArrayElement (args, i));
1851  oct_args(i) = box (env, jobj, 0);
1852  }
1853 
1854  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
1855 
1856  if (val.is_function_handle ())
1857  {
1859  feval (fcn, oct_args);
1860  }
1861  else if (val.is_cell () && val.length () > 0
1862  && (val.rows () == 1 || val.columns () == 1)
1863  && val.cell_value()(0).is_function_handle ())
1864  {
1865  Cell c = val.cell_value ();
1866  octave_function *fcn = c(0).function_value ();
1867 
1868  for (int i=1; i<c.numel (); i++)
1869  oct_args(len+i-1) = c(i);
1870 
1871  feval (fcn, oct_args);
1872  }
1873  else
1874  error ("trying to invoke non-invocable object");
1875 
1876  END_INTERRUPT_WITH_EXCEPTIONS;
1877  }
1878 }
1879 
1880 JNIEXPORT void JNICALL
1881 Java_org_octave_Octave_doEvalString (JNIEnv *env, jclass, jstring cmd)
1882 {
1883  std::string s = jstring_to_string (env, cmd);
1884  int pstatus;
1885  eval_string (s, false, pstatus, 0);
1886 }
1887 
1888 JNIEXPORT jboolean JNICALL
1890 {
1891  return (get_current_thread_ID (env) != octave_thread_ID);
1892 }
1893 
1894 #endif
1895 
1896 // octave_java class definition
1897 
1899  : octave_base_value (), java_object (0), java_class (0)
1900 {
1901 #if ! defined (HAVE_JAVA)
1902 
1903  err_disabled_feature ("Java Objects", "Java");
1904 
1905 #endif
1906 }
1907 
1908 octave_java::octave_java (const voidptr& jobj, void *jcls)
1909  : octave_base_value (), java_object (0), java_class (0)
1910 {
1911 #if defined (HAVE_JAVA)
1912 
1913  init (jobj, jcls);
1914 
1915 #else
1916 
1917  octave_unused_parameter (jobj);
1918  octave_unused_parameter (jcls);
1919 
1920  err_disabled_feature ("Java Objects", "Java");
1921 
1922 #endif
1923 }
1924 
1925 int octave_java::t_id (-1);
1926 
1927 const std::string octave_java::t_name ("octave_java");
1928 
1929 void
1931 {
1932 #if defined (HAVE_JAVA)
1933 
1935  (octave_java::t_name, "<unknown>", octave_value (new octave_java ()));
1936 
1937 #endif
1938 }
1939 
1940 dim_vector
1941 octave_java::dims (void) const
1942 {
1943 #if defined (HAVE_JAVA)
1944 
1945  JNIEnv *current_env = thread_jni_env ();
1946 
1947  if (current_env && java_object)
1948  return compute_array_dimensions (current_env, TO_JOBJECT (java_object));
1949  else
1950  return dim_vector (1, 1);
1951 
1952 #else
1953 
1954  // This shouldn't happen because construction of octave_java
1955  // objects is supposed to be impossible if Java is not available.
1956 
1957  panic_impossible ();
1958 
1959 #endif
1960 }
1961 
1964  const std::list<octave_value_list>& idx, int nargout)
1965 {
1966 #if defined (HAVE_JAVA)
1967 
1969  int skip = 1;
1970 
1971  JNIEnv *current_env = thread_jni_env ();
1972 
1973  switch (type[0])
1974  {
1975  case '.':
1976  if (type.length () > 1 && type[1] == '(')
1977  {
1979  count++;
1980  ovl(1) = octave_value (this);
1981  ovl(0) = (idx.front ())(0);
1982  std::list<octave_value_list>::const_iterator it = idx.begin ();
1983  ovl.append (*++it);
1984  retval = feval (std::string ("javaMethod"), ovl, 1);
1985  skip++;
1986  }
1987  else
1988  {
1990  count++;
1991  ovl(0) = octave_value (this);
1992  ovl(1) = (idx.front ())(0);
1993  retval = feval (std::string ("__java_get__"), ovl, 1);
1994  }
1995  break;
1996 
1997  case '(':
1998  if (current_env)
1999  retval = get_array_elements
2000  (current_env, TO_JOBJECT (to_java ()), idx.front ());
2001  break;
2002 
2003  default:
2004  error ("subsref: Java object cannot be indexed with %c", type[0]);
2005  break;
2006  }
2007 
2008  if (idx.size () > 1 && type.length () > 1)
2009  retval = retval(0).next_subsref (nargout, type, idx, skip);
2010 
2011  return retval;
2012 
2013 #else
2014 
2015  octave_unused_parameter (type);
2016  octave_unused_parameter (idx);
2017  octave_unused_parameter (nargout);
2018 
2019  // This shouldn't happen because construction of octave_java
2020  // objects is supposed to be impossible if Java is not available.
2021 
2022  panic_impossible ();
2023 
2024 #endif
2025 }
2026 
2029  const std::list<octave_value_list>& idx,
2030  const octave_value& rhs)
2031 {
2032 #if defined (HAVE_JAVA)
2033 
2035 
2036  JNIEnv *current_env = thread_jni_env ();
2037 
2038  switch (type[0])
2039  {
2040  case '.':
2041  if (type.length () == 1)
2042  {
2043  // field assignment
2045  count++;
2046  ovl(0) = octave_value (this);
2047  ovl(1) = (idx.front ())(0);
2048  ovl(2) = rhs;
2049  feval ("__java_set__", ovl, 0);
2050 
2051  count++;
2052  retval = octave_value (this);
2053  }
2054  else if (type.length () > 2 && type[1] == '(')
2055  {
2056  std::list<octave_value_list> new_idx;
2057  std::list<octave_value_list>::const_iterator it = idx.begin ();
2058  new_idx.push_back (*it++);
2059  new_idx.push_back (*it++);
2060  octave_value_list u = subsref (type.substr (0, 2), new_idx, 1);
2061 
2062  std::list<octave_value_list> next_idx (idx);
2063  next_idx.erase (next_idx.begin ());
2064  next_idx.erase (next_idx.begin ());
2065  u(0).subsasgn (type.substr (2), next_idx, rhs);
2066 
2067  count++;
2068  retval = octave_value (this);
2069  }
2070  else if (type[1] == '.')
2071  {
2072  octave_value_list u = subsref (type.substr (0, 1), idx, 1);
2073 
2074  std::list<octave_value_list> next_idx (idx);
2075  next_idx.erase (next_idx.begin ());
2076  u(0).subsasgn (type.substr (1), next_idx, rhs);
2077 
2078  count++;
2079  retval = octave_value (this);
2080  }
2081  else
2082  error ("invalid indexing/assignment on Java object");
2083  break;
2084 
2085  case '(':
2086  if (current_env)
2087  {
2088  set_array_elements (current_env, TO_JOBJECT (to_java ()),
2089  idx.front (), rhs);
2090 
2091  count++;
2092  retval = octave_value (this);
2093  }
2094  break;
2095 
2096  default:
2097  error ("Java object cannot be indexed with %c", type[0]);
2098  break;
2099  }
2100 
2101  return retval;
2102 
2103 #else
2104 
2105  octave_unused_parameter (type);
2106  octave_unused_parameter (idx);
2107  octave_unused_parameter (rhs);
2108 
2109  // This shouldn't happen because construction of octave_java
2110  // objects is supposed to be impossible if Java is not available.
2111 
2112  panic_impossible ();
2113 
2114 #endif
2115 }
2116 
2119 {
2120 #if defined (HAVE_JAVA)
2121 
2122  JNIEnv *current_env = thread_jni_env ();
2123 
2124  if (current_env)
2125  return get_invoke_list (current_env, to_java ());
2126  else
2127  return string_vector ();
2128 
2129 #else
2130 
2131  // This shouldn't happen because construction of octave_java
2132  // objects is supposed to be impossible if Java is not available.
2133 
2134  panic_impossible ();
2135 
2136 #endif
2137 }
2138 
2140 octave_java::convert_to_str_internal (bool, bool force, char type) const
2141 {
2142 #if defined (HAVE_JAVA)
2143 
2144  JNIEnv *current_env = thread_jni_env ();
2145 
2146  if (current_env)
2147  return convert_to_string (current_env, TO_JOBJECT (to_java ()), force, type);
2148  else
2149  return octave_value ("");
2150 
2151 #else
2152 
2153  octave_unused_parameter (force);
2154  octave_unused_parameter (type);
2155 
2156  // This shouldn't happen because construction of octave_java
2157  // objects is supposed to be impossible if Java is not available.
2158 
2159  panic_impossible ();
2160 
2161 #endif
2162 }
2163 
2164 void
2165 octave_java::print (std::ostream& os, bool)
2166 {
2167  print_raw (os);
2168  newline (os);
2169 }
2170 
2171 void
2172 octave_java::print_raw (std::ostream& os, bool) const
2173 {
2174  os << "<Java object: " << java_classname << ">";
2175 }
2176 
2177 // FIXME: Need routines to actually save/load java objects through Serialize.
2178 // See bug #42112.
2179 
2180 bool
2181 octave_java::save_ascii (std::ostream& /* os */)
2182 {
2183  warning ("save: unable to save java objects, skipping");
2184 
2185  return true;
2186 }
2187 
2188 bool
2189 octave_java::load_ascii (std::istream& /* is */)
2190 {
2191  // Silently skip over java object that was not saved
2192  return true;
2193 }
2194 
2195 bool
2196 octave_java::save_binary (std::ostream& /* os */, bool& /* save_as_floats */)
2197 {
2198  warning ("save: unable to save java objects, skipping");
2199 
2200  return true;
2201 }
2202 
2203 bool
2204 octave_java::load_binary (std::istream& /* is */, bool /* swap*/,
2206 {
2207  // Silently skip over java object that was not saved
2208  return true;
2209 }
2210 
2211 bool
2212 octave_java::save_hdf5 (octave_hdf5_id /* loc_id */, const char * /* name */,
2213  bool /* save_as_floats */)
2214 {
2215  warning ("save: unable to save java objects, skipping");
2216 
2217  return true;
2218 }
2219 
2220 bool
2221 octave_java::load_hdf5 (octave_hdf5_id /* loc_id */, const char * /* name */)
2222 {
2223  // Silently skip object that was not saved
2224  return true;
2225 }
2226 
2228 octave_java::do_javaMethod (void *jni_env_arg, const std::string& name,
2229  const octave_value_list& args)
2230 {
2231 #if defined (HAVE_JAVA)
2232 
2234 
2235  JNIEnv *jni_env = TO_JNIENV (jni_env_arg);
2236 
2237  if (jni_env)
2238  {
2239  jobjectArray_ref arg_objs (jni_env), arg_types (jni_env);
2240  if (unbox (jni_env, args, arg_objs, arg_types))
2241  {
2242  jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
2243  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "invokeMethod",
2244  "(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;");
2245  jstring_ref methName (jni_env, jni_env->NewStringUTF (name.c_str ()));
2246  jobjectArray_ref resObj (jni_env, reinterpret_cast<jobjectArray> (jni_env->CallStaticObjectMethod (helperClass, mID,
2247  to_java (), jstring (methName), jobjectArray (arg_objs), jobjectArray (arg_types))));
2248  if (resObj)
2249  retval = box (jni_env, resObj);
2250  else
2251  retval = check_exception (jni_env);
2252  }
2253 
2255  }
2256 
2257  return retval;
2258 
2259 #else
2260 
2261  octave_unused_parameter (jni_env_arg);
2262  octave_unused_parameter (name);
2263  octave_unused_parameter (args);
2264 
2265  // This shouldn't happen because construction of octave_java
2266  // objects is supposed to be impossible if Java is not available.
2267 
2268  panic_impossible ();
2269 
2270 #endif
2271 }
2272 
2275  const octave_value_list& args)
2276 {
2277 #if defined (HAVE_JAVA)
2278 
2279  return do_javaMethod (thread_jni_env (), name, args);
2280 
2281 #else
2282 
2283  octave_unused_parameter (name);
2284  octave_unused_parameter (args);
2285 
2286  // This shouldn't happen because construction of octave_java
2287  // objects is supposed to be impossible if Java is not available.
2288 
2289  panic_impossible ();
2290 
2291 #endif
2292 }
2293 
2295 octave_java:: do_javaMethod (void *jni_env_arg,
2296  const std::string& class_name,
2297  const std::string& name,
2298  const octave_value_list& args)
2299 {
2300 #if defined (HAVE_JAVA)
2301 
2303 
2304  JNIEnv *jni_env = TO_JNIENV (jni_env_arg);
2305 
2306  if (jni_env)
2307  {
2308  jobjectArray_ref arg_objs (jni_env), arg_types (jni_env);
2309  if (unbox (jni_env, args, arg_objs, arg_types))
2310  {
2311  jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
2312  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "invokeStaticMethod",
2313  "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;");
2314  jstring_ref methName (jni_env, jni_env->NewStringUTF (name.c_str ()));
2315  jstring_ref clsName (jni_env, jni_env->NewStringUTF (class_name.c_str ()));
2316  jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod (helperClass, mID,
2317  jstring (clsName), jstring (methName), jobjectArray (arg_objs), jobjectArray (arg_types)));
2318  if (resObj)
2319  retval = box (jni_env, resObj);
2320  else
2321  retval = check_exception (jni_env);
2322  }
2323 
2325  }
2326 
2327  return retval;
2328 
2329 #else
2330 
2331  octave_unused_parameter (jni_env_arg);
2332  octave_unused_parameter (class_name);
2333  octave_unused_parameter (name);
2334  octave_unused_parameter (args);
2335 
2336  // This shouldn't happen because construction of octave_java
2337  // objects is supposed to be impossible if Java is not available.
2338 
2339  panic_impossible ();
2340 
2341 #endif
2342 }
2343 
2346  const std::string& name,
2347  const octave_value_list& args)
2348 {
2349 #if defined (HAVE_JAVA)
2350 
2351  return do_javaMethod (thread_jni_env (), class_name, name, args);
2352 
2353 #else
2354 
2355  octave_unused_parameter (class_name);
2356  octave_unused_parameter (name);
2357  octave_unused_parameter (args);
2358 
2359  // This shouldn't happen because construction of octave_java
2360  // objects is supposed to be impossible if Java is not available.
2361 
2362  panic_impossible ();
2363 
2364 #endif
2365 }
2366 
2368 octave_java::do_javaObject (void *jni_env_arg, const std::string& name,
2369  const octave_value_list& args)
2370 {
2371 #if defined (HAVE_JAVA)
2372 
2374 
2375  JNIEnv *jni_env = TO_JNIENV (jni_env_arg);
2376 
2377  if (jni_env)
2378  {
2379  jobjectArray_ref arg_objs (jni_env), arg_types (jni_env);
2380 
2381  if (unbox (jni_env, args, arg_objs, arg_types))
2382  {
2383  jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
2384  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "invokeConstructor",
2385  "(Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;");
2386  jstring_ref clsName (jni_env, jni_env->NewStringUTF (name.c_str ()));
2387  jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod (helperClass, mID,
2388  jstring (clsName), jobjectArray (arg_objs), jobjectArray (arg_types)));
2389 
2390  if (resObj)
2391  retval = octave_value (new octave_java (resObj, 0));
2392  else
2393  check_exception (jni_env);
2394  }
2395 
2397  }
2398 
2399  return retval;
2400 
2401 #else
2402 
2403  octave_unused_parameter (jni_env_arg);
2404  octave_unused_parameter (name);
2405  octave_unused_parameter (args);
2406 
2407  // This shouldn't happen because construction of octave_java
2408  // objects is supposed to be impossible if Java is not available.
2409 
2410  panic_impossible ();
2411 
2412 #endif
2413 }
2414 
2417  const octave_value_list& args)
2418 {
2419 #if defined (HAVE_JAVA)
2420 
2421  return do_javaObject (thread_jni_env (), name, args);
2422 
2423 #else
2424 
2425  octave_unused_parameter (name);
2426  octave_unused_parameter (args);
2427 
2428  // This shouldn't happen because construction of octave_java
2429  // objects is supposed to be impossible if Java is not available.
2430 
2431  panic_impossible ();
2432 
2433 #endif
2434 }
2435 
2437 octave_java::do_java_get (void *jni_env_arg, const std::string& name)
2438 {
2439 #if defined (HAVE_JAVA)
2440 
2442 
2443  JNIEnv *jni_env = TO_JNIENV (jni_env_arg);
2444 
2445  if (jni_env)
2446  {
2447  jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
2448  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "getField",
2449  "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;");
2450  jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ()));
2451  jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod (helperClass, mID,
2452  to_java (), jstring (fName)));
2453 
2454  if (resObj)
2455  retval = box (jni_env, resObj);
2456  else
2457  retval = check_exception (jni_env);
2458 
2460  }
2461 
2462  return retval;
2463 
2464 #else
2465 
2466  octave_unused_parameter (jni_env_arg);
2467  octave_unused_parameter (name);
2468 
2469  // This shouldn't happen because construction of octave_java
2470  // objects is supposed to be impossible if Java is not available.
2471 
2472  panic_impossible ();
2473 
2474 #endif
2475 }
2476 
2479 {
2480 #if defined (HAVE_JAVA)
2481 
2482  return do_java_get (thread_jni_env (), name);
2483 
2484 #else
2485 
2486  octave_unused_parameter (name);
2487 
2488  // This shouldn't happen because construction of octave_java
2489  // objects is supposed to be impossible if Java is not available.
2490 
2491  panic_impossible ();
2492 
2493 #endif
2494 }
2495 
2497 octave_java::do_java_get (void *jni_env_arg, const std::string& class_name,
2498  const std::string& name)
2499 {
2500 #if defined (HAVE_JAVA)
2501 
2503 
2504  JNIEnv *jni_env = TO_JNIENV (jni_env_arg);
2505 
2506  if (jni_env)
2507  {
2508  jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
2509  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "getStaticField",
2510  "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
2511  jstring_ref cName (jni_env, jni_env->NewStringUTF (class_name.c_str ()));
2512  jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ()));
2513  jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod (helperClass, mID,
2514  jstring (cName), jstring (fName)));
2515  if (resObj)
2516  retval = box (jni_env, resObj);
2517  else
2518  retval = check_exception (jni_env);
2519 
2521  }
2522 
2523  return retval;
2524 
2525 #else
2526 
2527  octave_unused_parameter (jni_env_arg);
2528  octave_unused_parameter (class_name);
2529  octave_unused_parameter (name);
2530 
2531  // This shouldn't happen because construction of octave_java
2532  // objects is supposed to be impossible if Java is not available.
2533 
2534  panic_impossible ();
2535 
2536 #endif
2537 }
2538 
2541  const std::string& name)
2542 {
2543 #if defined (HAVE_JAVA)
2544 
2545  return do_java_get (thread_jni_env (), class_name, name);
2546 
2547 #else
2548 
2549  octave_unused_parameter (class_name);
2550  octave_unused_parameter (name);
2551 
2552  // This shouldn't happen because construction of octave_java
2553  // objects is supposed to be impossible if Java is not available.
2554 
2555  panic_impossible ();
2556 
2557 #endif
2558 }
2559 
2561 octave_java::do_java_set (void *jni_env_arg, const std::string& name,
2562  const octave_value& val)
2563 {
2564 #if defined (HAVE_JAVA)
2565 
2567 
2568  JNIEnv *jni_env = TO_JNIENV (jni_env_arg);
2569 
2570  if (jni_env)
2571  {
2572  jobject_ref jobj (jni_env);
2573  jclass_ref jcls (jni_env);
2574 
2575  if (unbox (jni_env, val, jobj, jcls))
2576  {
2577  jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
2578  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "setField",
2579  "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V");
2580  jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ()));
2581  jni_env->CallStaticObjectMethod (helperClass, mID, to_java (), jstring (fName), jobject (jobj));
2582  check_exception (jni_env);
2583  }
2584 
2586  }
2587 
2588  return retval;
2589 
2590 #else
2591 
2592  octave_unused_parameter (jni_env_arg);
2593  octave_unused_parameter (name);
2594  octave_unused_parameter (val);
2595 
2596  // This shouldn't happen because construction of octave_java
2597  // objects is supposed to be impossible if Java is not available.
2598 
2599  panic_impossible ();
2600 
2601 #endif
2602 }
2603 
2606 {
2607 #if defined (HAVE_JAVA)
2608 
2609  return do_java_set (thread_jni_env (), name, val);
2610 
2611 #else
2612 
2613  octave_unused_parameter (name);
2614  octave_unused_parameter (val);
2615 
2616  // This shouldn't happen because construction of octave_java
2617  // objects is supposed to be impossible if Java is not available.
2618 
2619  panic_impossible ();
2620 
2621 #endif
2622 }
2623 
2625 octave_java::do_java_set (void *jni_env_arg, const std::string& class_name,
2626  const std::string& name, const octave_value& val)
2627 {
2628 #if defined (HAVE_JAVA)
2629 
2631 
2632  JNIEnv *jni_env = TO_JNIENV (jni_env_arg);
2633 
2634  if (jni_env)
2635  {
2636  jobject_ref jobj (jni_env);
2637  jclass_ref jcls (jni_env);
2638 
2639  if (unbox (jni_env, val, jobj, jcls))
2640  {
2641  jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
2642  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "setStaticField",
2643  "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V");
2644  jstring_ref cName (jni_env, jni_env->NewStringUTF (class_name.c_str ()));
2645  jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ()));
2646  jni_env->CallStaticObjectMethod (helperClass, mID, jstring (cName), jstring (fName), jobject (jobj));
2647  check_exception (jni_env);
2648  }
2649 
2651  }
2652 
2653  return retval;
2654 
2655 #else
2656 
2657  octave_unused_parameter (jni_env_arg);
2658  octave_unused_parameter (class_name);
2659  octave_unused_parameter (name);
2660  octave_unused_parameter (val);
2661 
2662  // This shouldn't happen because construction of octave_java
2663  // objects is supposed to be impossible if Java is not available.
2664 
2665  panic_impossible ();
2666 
2667 #endif
2668 }
2669 
2672  const std::string& name,
2673  const octave_value& val)
2674 {
2675 #if defined (HAVE_JAVA)
2676 
2677  return do_java_set (thread_jni_env (), class_name, name, val);
2678 
2679 #else
2680 
2681  octave_unused_parameter (class_name);
2682  octave_unused_parameter (name);
2683  octave_unused_parameter (val);
2684 
2685  // This shouldn't happen because construction of octave_java
2686  // objects is supposed to be impossible if Java is not available.
2687 
2688  panic_impossible ();
2689 
2690 #endif
2691 }
2692 
2693 void
2694 octave_java::init (void *jobj_arg, void *jcls_arg)
2695 {
2696 #if defined (HAVE_JAVA)
2697 
2698  jobject jobj = TO_JOBJECT (jobj_arg);
2699  jclass jcls = TO_JCLASS (jcls_arg);
2700 
2701  JNIEnv *current_env = thread_jni_env ();
2702 
2703  if (current_env)
2704  {
2705  if (jobj)
2706  java_object = current_env->NewGlobalRef (jobj);
2707 
2708  if (jcls)
2709  java_class = current_env->NewGlobalRef (jcls);
2710  else if (java_object)
2711  {
2712  jclass_ref ocls (current_env, current_env->GetObjectClass (TO_JOBJECT (java_object)));
2713  java_class = current_env->NewGlobalRef (jclass (ocls));
2714  }
2715 
2716  if (java_class)
2717  {
2718  jclass_ref clsCls (current_env, current_env->GetObjectClass (TO_JCLASS (java_class)));
2719  jmethodID mID = current_env->GetMethodID (clsCls, "getCanonicalName", "()Ljava/lang/String;");
2720  jobject_ref resObj (current_env, current_env->CallObjectMethod (TO_JCLASS (java_class), mID));
2721  java_classname = jstring_to_string (current_env, resObj);
2722  }
2723  }
2724 
2725 #else
2726 
2727  octave_unused_parameter (jobj_arg);
2728  octave_unused_parameter (jcls_arg);
2729 
2730  // This shouldn't happen because construction of octave_java
2731  // objects is supposed to be impossible if Java is not available.
2732 
2733  panic_impossible ();
2734 
2735 #endif
2736 }
2737 
2738 void
2740 {
2741 #if defined (HAVE_JAVA)
2742 
2743  JNIEnv *current_env = thread_jni_env ();
2744 
2745  if (current_env)
2746  {
2747  if (java_object)
2748  current_env->DeleteGlobalRef (TO_JOBJECT (java_object));
2749 
2750  if (java_class)
2751  current_env->DeleteGlobalRef (TO_JCLASS (java_class));
2752 
2753  java_object = 0;
2754  java_class = 0;
2755  }
2756 
2757 #else
2758 
2759  // This shouldn't happen because construction of octave_java
2760  // objects is supposed to be impossible if Java is not available.
2761 
2762  panic_impossible ();
2763 
2764 #endif
2765 }
2766 
2767 // DEFUN blocks below must be outside of HAVE_JAVA block so that
2768 // documentation strings are always available, even when functions are not.
2769 
2770 DEFUN (__java_init__, , ,
2771  doc: /* -*- texinfo -*-
2772 @deftypefn {} {} __java_init__ ()
2773 Internal function used @strong{only} when debugging Java interface.
2774 
2775 Function will directly call initialize_java to create an instance of a JVM.
2776 @end deftypefn */)
2777 {
2778 #if defined (HAVE_JAVA)
2779 
2781 
2782  retval = 0;
2783 
2784  initialize_java ();
2785 
2786  retval = 1;
2787 
2788  return retval;
2789 
2790 #else
2791 
2792  err_disabled_feature ("__java_init__", "Java");
2793 
2794 #endif
2795 }
2796 
2797 DEFUN (__java_exit__, , ,
2798  doc: /* -*- texinfo -*-
2799 @deftypefn {} {} __java_exit__ ()
2800 Internal function used @strong{only} when debugging Java interface.
2801 
2802 Function will directly call terminate_jvm to destroy the current JVM
2803 instance.
2804 @end deftypefn */)
2805 {
2806 #if defined (HAVE_JAVA)
2807 
2808  terminate_jvm ();
2809 
2810  return ovl ();
2811 
2812 #else
2813 
2814  err_disabled_feature ("__java_exit__", "Java");
2815 
2816 #endif
2817 }
2818 
2819 DEFUN (javaObject, args, ,
2820  doc: /* -*- texinfo -*-
2821 @deftypefn {} {@var{jobj} =} javaObject (@var{classname})
2822 @deftypefnx {} {@var{jobj} =} javaObject (@var{classname}, @var{arg1}, @dots{})
2823 Create a Java object of class @var{classsname}, by calling the class
2824 constructor with the arguments @var{arg1}, @dots{}
2825 
2826 The first example below creates an uninitialized object, while the second
2827 example supplies an initial argument to the constructor.
2828 
2829 @example
2830 @group
2831 x = javaObject ("java.lang.StringBuffer")
2832 x = javaObject ("java.lang.StringBuffer", "Initial string")
2833 @end group
2834 @end example
2835 
2836 @seealso{javaMethod, javaArray}
2837 @end deftypefn */)
2838 {
2839 #if defined (HAVE_JAVA)
2840 
2841  if (args.length () == 0)
2842  print_usage ();
2843 
2844  std::string classname = args(0).xstring_value ("javaObject: CLASSNAME must be a string");
2845 
2846  initialize_java ();
2847 
2848  JNIEnv *current_env = thread_jni_env ();
2849 
2851  for (int i=1; i<args.length (); i++)
2852  tmp(i-1) = args(i);
2853 
2854  return ovl (octave_java::do_javaObject (current_env, classname, tmp));
2855 
2856 #else
2857 
2858  octave_unused_parameter (args);
2859 
2860  err_disabled_feature ("javaObject", "Java");
2861 
2862 #endif
2863 }
2864 
2865 /*
2866 ## The tests below merely check if javaObject works at all. Whether
2867 ## it works properly, i.e., creates the right values, is a matter of
2868 ## Java itself. Create a Short and check if it really is a short, i.e.,
2869 ## whether it overflows.
2870 %!testif HAVE_JAVA
2871 %! if (! usejava ("jvm"))
2872 %! return;
2873 %! endif
2874 %! assert (javaObject ("java.lang.Short", 40000).doubleValue < 0);
2875 */
2876 
2877 DEFUN (javaMethod, args, ,
2878  doc: /* -*- texinfo -*-
2879 @deftypefn {} {@var{ret} =} javaMethod (@var{methodname}, @var{obj})
2880 @deftypefnx {} {@var{ret} =} javaMethod (@var{methodname}, @var{obj}, @var{arg1}, @dots{})
2881 Invoke the method @var{methodname} on the Java object @var{obj} with the
2882 arguments @var{arg1}, @dots{}.
2883 
2884 For static methods, @var{obj} can be a string representing the fully
2885 qualified name of the corresponding class.
2886 
2887 When @var{obj} is a regular Java object, structure-like indexing can be
2888 used as a shortcut syntax. For instance, the two following statements are
2889 equivalent
2890 
2891 @example
2892 @group
2893  ret = javaMethod ("method1", x, 1.0, "a string")
2894  ret = x.method1 (1.0, "a string")
2895 @end group
2896 @end example
2897 
2898 @code{javaMethod} returns the result of the method invocation.
2899 
2900 @seealso{methods, javaObject}
2901 @end deftypefn */)
2902 {
2903 #if defined (HAVE_JAVA)
2904 
2905  if (args.length () < 2)
2906  print_usage ();
2907 
2908  std::string methodname = args(0).xstring_value ("javaMethod: METHODNAME must be a string");
2909 
2910  initialize_java ();
2911 
2912  JNIEnv *current_env = thread_jni_env ();
2913 
2915 
2917  for (int i=2; i<args.length (); i++)
2918  tmp(i-2) = args(i);
2919 
2920  if (args(1).is_java ())
2921  {
2922  octave_java *jobj = TO_JAVA (args(1));
2923  retval = jobj->do_javaMethod (current_env, methodname, tmp);
2924  }
2925  else if (args(1).is_string ())
2926  {
2927  std::string cls = args(1).string_value ();
2928  retval = octave_java::do_javaMethod (current_env, cls, methodname, tmp);
2929  }
2930  else
2931  error ("javaMethod: OBJ must be a Java object or a string");
2932 
2933  return retval;
2934 
2935 #else
2936 
2937  octave_unused_parameter (args);
2938 
2939  err_disabled_feature ("javaMethod", "Java");
2940 
2941 #endif
2942 }
2943 
2944 /*
2945 %!testif HAVE_JAVA
2946 %! if (! usejava ("jvm"))
2947 %! return;
2948 %! endif
2949 %! ## Check for valid first two Java version numbers
2950 %! jver = strsplit (javaMethod ("getProperty", "java.lang.System", "java.version"), ".");
2951 %! assert (isfinite (str2double (jver{1})) && isfinite (str2double (jver{2})));
2952 */
2953 
2954 DEFUN (__java_get__, args, ,
2955  doc: /* -*- texinfo -*-
2956 @deftypefn {} {@var{val} =} __java_get__ (@var{obj}, @var{name})
2957 Get the value of the field @var{name} of the Java object @var{obj}.
2958 
2959 For static fields, @var{obj} can be a string representing the fully
2960 qualified name of the corresponding class.
2961 
2962 When @var{obj} is a regular Java object, structure-like indexing can be used
2963 as a shortcut syntax. For instance, the two following statements are
2964 equivalent
2965 
2966 @example
2967 @group
2968  __java_get__ (x, "field1")
2969  x.field1
2970 @end group
2971 @end example
2972 
2973 @seealso{__java_set__, javaMethod, javaObject}
2974 @end deftypefn */)
2975 {
2976 #if defined (HAVE_JAVA)
2977 
2978  if (args.length () != 2)
2979  print_usage ();
2980 
2981  std::string name = args(1).string_value ("__java_get__: NAME must be a string");
2982 
2983  initialize_java ();
2984 
2985  JNIEnv *current_env = thread_jni_env ();
2986 
2988 
2989  if (args(0).is_java ())
2990  {
2991  octave_java *jobj = TO_JAVA (args(0));
2992  retval = jobj->do_java_get (current_env, name);
2993  }
2994  else if (args(0).is_string ())
2995  {
2996  std::string cls = args(0).string_value ();
2997  retval = octave_java::do_java_get (current_env, cls, name);
2998  }
2999  else
3000  error ("__java_get__: OBJ must be a Java object or a string");
3001 
3002  return retval;
3003 
3004 #else
3005 
3006  octave_unused_parameter (args);
3007 
3008  err_disabled_feature ("__java_get__", "Java");
3009 
3010 #endif
3011 }
3012 
3013 DEFUN (__java_set__, args, ,
3014  doc: /* -*- texinfo -*-
3015 @deftypefn {} {@var{obj} =} __java_set__ (@var{obj}, @var{name}, @var{val})
3016 Set the value of the field @var{name} of the Java object @var{obj} to
3017 @var{val}.
3018 
3019 For static fields, @var{obj} can be a string representing the fully
3020 qualified named of the corresponding Java class.
3021 
3022 When @var{obj} is a regular Java object, structure-like indexing can be
3023 used as a shortcut syntax. For instance, the two following statements are
3024 equivalent
3025 
3026 @example
3027 @group
3028  __java_set__ (x, "field1", val)
3029  x.field1 = val
3030 @end group
3031 @end example
3032 
3033 @seealso{__java_get__, javaMethod, javaObject}
3034 @end deftypefn */)
3035 {
3036 #if defined (HAVE_JAVA)
3037 
3038  if (args.length () != 3)
3039  print_usage ();
3040 
3041  std::string name = args(1).xstring_value ("__java_set__: NAME must be a string");
3042 
3043  initialize_java ();
3044 
3045  JNIEnv *current_env = thread_jni_env ();
3046 
3048 
3049  if (args(0).is_java ())
3050  {
3051  octave_java *jobj = TO_JAVA (args(0));
3052  retval = jobj->do_java_set (current_env, name, args(2));
3053  }
3054  else if (args(0).is_string ())
3055  {
3056  std::string cls = args(0).string_value ();
3057  retval = octave_java::do_java_set (current_env, cls, name, args(2));
3058  }
3059  else
3060  error ("__java_set__: OBJ must be a Java object or a string");
3061 
3062  return retval;
3063 
3064 #else
3065 
3066  octave_unused_parameter (args);
3067 
3068  err_disabled_feature ("__java_set__", "Java");
3069 
3070 #endif
3071 }
3072 
3073 DEFUN (java2mat, args, ,
3074  doc: /* -*- texinfo -*-
3075 @deftypefn {} {} java2mat (@var{javaobj})
3076 Undocumented internal function.
3077 @end deftypefn */)
3078 {
3079 #if defined (HAVE_JAVA)
3080 
3081  if (args.length () != 1)
3082  print_usage ();
3083 
3084  initialize_java ();
3085 
3086  JNIEnv *current_env = thread_jni_env ();
3087 
3089 
3090  if (args(0).is_java ())
3091  {
3092  octave_java *jobj = TO_JAVA (args(0));
3093  retval = ovl (box_more (current_env, jobj->to_java (), 0));
3094  }
3095  else
3096  retval = ovl (args(0));
3097 
3098  return retval;
3099 
3100 #else
3101 
3102  octave_unused_parameter (args);
3103 
3104  err_disabled_feature ("java2mat", "Java");
3105 
3106 #endif
3107 }
3108 
3109 DEFUN (java_matrix_autoconversion, args, nargout,
3110  doc: /* -*- texinfo -*-
3111 @deftypefn {} {@var{val} =} java_matrix_autoconversion ()
3112 @deftypefnx {} {@var{old_val} =} java_matrix_autoconversion (@var{new_val})
3113 @deftypefnx {} {} java_matrix_autoconversion (@var{new_val}, "local")
3114 Query or set the internal variable that controls whether Java arrays are
3115 automatically converted to Octave matrices.
3116 
3117 The default value is false.
3118 
3119 When called from inside a function with the @qcode{"local"} option, the
3120 variable is changed locally for the function and any subroutines it calls.
3121 The original variable value is restored when exiting the function.
3122 @seealso{java_unsigned_autoconversion, debug_java}
3123 @end deftypefn */)
3124 {
3125 #if defined (HAVE_JAVA)
3126 
3127  return SET_INTERNAL_VARIABLE (java_matrix_autoconversion);
3128 
3129 #else
3130 
3131  octave_unused_parameter (args);
3132  octave_unused_parameter (nargout);
3133 
3134  err_disabled_feature ("java_matrix_autoconversion", "Java");
3135 
3136 #endif
3137 }
3138 
3139 DEFUN (java_unsigned_autoconversion, args, nargout,
3140  doc: /* -*- texinfo -*-
3141 @deftypefn {} {@var{val} =} java_unsigned_autoconversion ()
3142 @deftypefnx {} {@var{old_val} =} java_unsigned_autoconversion (@var{new_val})
3143 @deftypefnx {} {} java_unsigned_autoconversion (@var{new_val}, "local")
3144 Query or set the internal variable that controls how integer classes are
3145 converted when @code{java_matrix_autoconversion} is enabled.
3146 
3147 When enabled, Java arrays of class Byte or Integer are converted to matrices
3148 of class uint8 or uint32 respectively. The default value is true.
3149 
3150 When called from inside a function with the @qcode{"local"} option, the
3151 variable is changed locally for the function and any subroutines it calls.
3152 The original variable value is restored when exiting the function.
3153 @seealso{java_matrix_autoconversion, debug_java}
3154 @end deftypefn */)
3155 {
3156 #if defined (HAVE_JAVA)
3157 
3158  return SET_INTERNAL_VARIABLE (java_unsigned_autoconversion);
3159 
3160 #else
3161 
3162  octave_unused_parameter (args);
3163  octave_unused_parameter (nargout);
3164 
3165  err_disabled_feature ("java_unsigned_autoconversion", "Java");
3166 
3167 #endif
3168 }
3169 
3170 DEFUN (debug_java, args, nargout,
3171  doc: /* -*- texinfo -*-
3172 @deftypefn {} {@var{val} =} debug_java ()
3173 @deftypefnx {} {@var{old_val} =} debug_java (@var{new_val})
3174 @deftypefnx {} {} debug_java (@var{new_val}, "local")
3175 Query or set the internal variable that determines whether extra debugging
3176 information regarding the initialization of the JVM and any Java exceptions
3177 is printed.
3178 
3179 When called from inside a function with the @qcode{"local"} option, the
3180 variable is changed locally for the function and any subroutines it calls.
3181 The original variable value is restored when exiting the function.
3182 @seealso{java_matrix_autoconversion, java_unsigned_autoconversion}
3183 @end deftypefn */)
3184 {
3185 #if defined (HAVE_JAVA)
3186 
3187  return SET_INTERNAL_VARIABLE (debug_java);
3188 
3189 #else
3190 
3191  octave_unused_parameter (args);
3192  octave_unused_parameter (nargout);
3193 
3194  err_disabled_feature ("debug_java", "Java");
3195 
3196 #endif
3197 }
3198 
3199 // Outside of #if defined (HAVE_JAVA) because it is desirable to be able
3200 // to test for the presence of a Java object without having Java
3201 // installed.
3202 
3203 DEFUN (isjava, args, ,
3204  doc: /* -*- texinfo -*-
3205 @deftypefn {} {} isjava (@var{x})
3206 Return true if @var{x} is a Java object.
3207 @seealso{class, typeinfo, isa, javaObject}
3208 @end deftypefn */)
3209 {
3210  if (args.length () != 1)
3211  print_usage ();
3212 
3213  return ovl (args(0).is_java ());
3214 }
3215 
3216 /*
3217 ## Check automatic conversion of java primitive arrays into octave types.
3218 %!testif HAVE_JAVA
3219 %! if (! usejava ("jvm"))
3220 %! return;
3221 %! endif
3222 %! assert (javaObject ("java.lang.String", "hello").getBytes (),
3223 %! int8 ([104 101 108 108 111]'));
3224 
3225 ## Check automatic conversion of octave types into java primitive arrays.
3226 ## Note that uint8 is casted to int8.
3227 %!testif HAVE_JAVA
3228 %! if (! usejava ("jvm"))
3229 %! return;
3230 %! endif
3231 %! assert (javaMethod ("binarySearch", "java.util.Arrays", [90 100 255], 255), 2);
3232 %! assert (javaMethod ("binarySearch", "java.util.Arrays", uint8 ([90 100 255]), uint8 (255)) < 0);
3233 %! assert (javaMethod ("binarySearch", "java.util.Arrays", uint8 ([90 100 128]), uint8 (128)) < 0);
3234 %! assert (javaMethod ("binarySearch", "java.util.Arrays", uint8 ([90 100 127]), uint8 (127)), 2);
3235 %! assert (javaMethod ("binarySearch", "java.util.Arrays", uint16 ([90 100 128]), uint16 (128)), 2);
3236 
3237 ## Check we can create objects that wrap java literals
3238 %!testif HAVE_JAVA <38821>
3239 %! if (! usejava ("jvm"))
3240 %! return;
3241 %! endif
3242 %! assert (class (javaObject ("java.lang.Byte", uint8 (1))), "java.lang.Byte");
3243 %! assert (class (javaObject ("java.lang.Byte", int8 (1))), "java.lang.Byte");
3244 %! assert (class (javaObject ("java.lang.Short", uint16 (1))), "java.lang.Short");
3245 %! assert (class (javaObject ("java.lang.Short", int16 (1))), "java.lang.Short");
3246 %! assert (class (javaObject ("java.lang.Integer", uint32 (1))), "java.lang.Integer");
3247 %! assert (class (javaObject ("java.lang.Integer", int32 (1))), "java.lang.Integer");
3248 %! assert (class (javaObject ("java.lang.Long", uint64 (1))), "java.lang.Long");
3249 %! assert (class (javaObject ("java.lang.Long", int64 (1))), "java.lang.Long");
3250 
3251 ## Test for automatic conversion of specific numeric classes
3252 %!testif HAVE_JAVA <48013>
3253 %! if (! usejava ("jvm"))
3254 %! return;
3255 %! endif
3256 %! assert (javaMethod ("valueOf", "java.lang.Byte", int8 (1)), 1)
3257 %! assert (javaMethod ("valueOf", "java.lang.Short", int16 (1)), 1)
3258 %! assert (javaMethod ("valueOf", "java.lang.Integer", int32 (1)), 1)
3259 %! assert (javaMethod ("valueOf", "java.lang.Long", int64 (1)), 1)
3260 %! assert (javaMethod ("valueOf", "java.lang.Float", single (1)), 1)
3261 %! assert (javaMethod ("valueOf", "java.lang.Double", double (1)), 1)
3262 %! assert (class (javaMethod ("valueOf", "java.math.BigDecimal", double (1))), "java.math.BigDecimal")
3263 %! assert (class (javaMethod ("valueOf", "java.math.BigInteger", int64 (1))), "java.math.BigInteger")
3264 
3265 ## Automatic conversion from string cell array into String[]
3266 %!testif HAVE_JAVA <45290>
3267 %! if (! usejava ("jvm"))
3268 %! return;
3269 %! endif
3270 %! assert (javaMethod ("binarySearch", "java.util.Arrays", {"aaa", "bbb", "ccc", "zzz"}, "aaa"), 0);
3271 %! assert (javaMethod ("binarySearch", "java.util.Arrays", {"aaa", "bbb", "ccc", "zzz"}, "zzz"), 3);
3272 %! assert (javaMethod ("binarySearch", "java.util.Arrays", {"aaa", "bbb", "ccc", "zzz"}, "hhh") < 0);
3273 */
uint8NDArray uint8_array_value(void) const
Definition: ov.h:896
JNIEnv * env
Definition: ov-java.cc:119
static std::string dir_sep_str(void)
Definition: file-ops.h:80
java_local_ref(JNIEnv *_env, T obj)
Definition: ov-java.cc:81
bool is_empty(void) const
Definition: Array.h:575
bool is_range(void) const
Definition: ov.h:587
static std::string get_current_directory(void)
Definition: oct-env.cc:136
Octave interface to the compression and uncompression libraries.
Definition: aepbalance.cc:47
JNIEXPORT void JNICALL Java_org_octave_Octave_doEvalString(JNIEnv *, jclass, jstring)
Definition: ov-java.cc:1881
Definition: Cell.h:37
static octave_value get_array_elements(JNIEnv *jni_env, jobject jobj, const octave_value_list &idx)
Definition: ov-java.cc:960
bool save_hdf5(octave_hdf5_id loc_id, const char *name, bool save_as_floats)
Definition: ov-java.cc:2212
octave_idx_type length(octave_idx_type n=0) const
Definition: idx-vector.h:541
octave_refcount< octave_idx_type > count
Definition: ov-base.h:843
bool is_real_type(void) const
Definition: ov.h:667
fname
Definition: load-save.cc:754
java_local_ref(void)
Definition: ov-java.cc:111
octave_idx_type rows(void) const
Definition: ov.h:489
void * search(const std::string &nm, name_mangler mangler=0) const
Definition: oct-shlib.h:164
void octave_set_default_fpucw(void)
static octave_value do_javaObject(void *jni_env, const std::string &name, const octave_value_list &args)
Definition: ov-java.cc:2368
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
Definition: dMatrix.h:145
int8NDArray int8_array_value(void) const
Definition: ov.h:884
bool load_ascii(std::istream &is)
Definition: ov-java.cc:2189
bool is_vector(void) const
Definition: dim-vector.h:458
#define UNBOX_PRIMITIVE_SCALAR(OCTAVE_T, METHOD_T, JAVA_T, JAVA_CON)
OCTAVE_EXPORT octave_value_list isa nd deftypefn *return ovl(args(0).is_integer_type())
bool is_uint16_type(void) const
Definition: ov.h:650
java_local_ref< jclass > jclass_ref
Definition: ov-java.cc:123
OCTINTERP_API void print_usage(void)
Definition: defun.cc:52
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:363
java_local_ref< jstring > jstring_ref
Definition: ov-java.cc:124
OCTAVE_EXPORT octave_value_list uint16
Definition: ov.cc:1258
static dim_vector compute_array_dimensions(JNIEnv *jni_env, jobject obj)
Definition: ov-java.cc:888
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:5068
void set_pos_if_unset(octave_idx_type nd_arg, octave_idx_type dim_arg)
static octave_value set_array_elements(JNIEnv *jni_env, jobject jobj, const octave_value_list &idx, const octave_value &rhs)
Definition: ov-java.cc:987
octave_idx_type length(void) const
Definition: ovl.h:96
octave_value_list & append(const octave_value &val)
Definition: ovl.cc:85
static char * strsave(const char *s)
Definition: main.cc:183
jsize bufLen
Definition: ov-java.cc:70
for large enough k
Definition: lu.cc:606
java_local_ref< jbyteArray > jbyteArray_ref
Definition: ov-java.cc:127
void resize(int n, int fill_value=0)
Definition: dim-vector.h:316
octave_value do_java_set(void *jni_env, const std::string &name, const octave_value &val)
Definition: ov-java.cc:2561
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:46
octave_java(void)
Definition: ov-java.cc:1898
void error(const char *fmt,...)
Definition: error.cc:570
int32NDArray int32_array_value(void) const
Definition: ov.h:890
#define SET_INTERNAL_VARIABLE(NM)
Definition: variables.h:126
bool is_int8_type(void) const
Definition: ov.h:635
JNIEXPORT jboolean JNICALL Java_org_octave_Octave_call(JNIEnv *, jclass, jstring, jobjectArray, jobjectArray)
Definition: ov-java.cc:1810
std::string Vfcn_file_dir
Definition: defaults.cc:79
static void initialize_java(void)
Definition: ov-java.cc:1785
static std::string initial_java_dir(void)
Definition: ov-java.cc:339
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov-java.cc:2028
void detach(void)
Definition: ov-java.cc:99
static std::string jstring_to_string(JNIEnv *jni_env, jstring s)
Definition: ov-java.cc:673
std::string filename
Definition: urlwrite.cc:340
octave_value resize(const dim_vector &dv, bool fill=false) const
Definition: ov.h:524
void init(void *jobj, void *jcls)
Definition: ov-java.cc:2694
bool is_cell(void) const
Definition: ov.h:545
u
Definition: lu.cc:138
#define BOX_PRIMITIVE_ARRAY(JAVA_TYPE, JAVA_ID, JAVA_TYPE_CAP, OCTAVE_ID)
bool is_int32_type(void) const
Definition: ov.h:641
s
Definition: file-io.cc:2682
static std::string initial_class_path(void)
Definition: ov-java.cc:402
void update(void)
Definition: ov-java.cc:251
static jobject make_java_index(JNIEnv *jni_env, const octave_value_list &idx)
Definition: ov-java.cc:923
i e
Definition: data.cc:2724
void newline(std::ostream &os) const
Definition: ov-base.cc:1381
static std::string tilde_expand(const std::string &)
Definition: file-ops.cc:301
static bool jvm_attached
Definition: ov-java.cc:171
static void initialize_jvm(void)
Definition: ov-java.cc:491
void read_java_opts(const std::string &filename)
Definition: ov-java.cc:215
bool is_function_handle(void) const
Definition: ov.h:702
octave_function * fcn
Definition: ov-class.cc:1743
static std::string getenv(const std::string &name)
Definition: oct-env.cc:235
bool load_hdf5(octave_hdf5_id loc_id, const char *name)
Definition: ov-java.cc:2221
static string_vector get_invoke_list(JNIEnv *jni_env, void *jobj_arg)
Definition: ov-java.cc:1019
void clean(void)
Definition: ov-java.cc:237
#define TO_JCLASS(obj)
Definition: ov-java.cc:63
OCTAVE_EXPORT octave_value_list search each directory of the loadpath for element of the cell array and return the first that matches If the second optional argument return a cell array containing the list of all files that have the same name in the path If no files are found
Definition: utils.cc:302
JNIEXPORT jboolean JNICALL Java_org_octave_Octave_needThreadedInvokation(JNIEnv *, jclass)
Definition: ov-java.cc:1889
JNIEnv ** penv
Definition: ov-java.cc:67
Cell cell_value(void) const
Definition: ov.cc:1687
bool is_float_type(void) const
Definition: ov.h:630
JNIEnv void * args
Definition: ov-java.cc:67
static std::map< int, octave_value > listener_map
Definition: ov-java.cc:176
Array< std::string > cellstr_value(void) const
Definition: ov.h:920
static int java_event_hook(void)
Definition: ov-java.cc:1766
octave_idx_type columns(void) const
Definition: ov.h:491
OCTAVE_EXPORT octave_value_list any number nd example oindent prints the prompt xample Pick a any number!nd example oindent and waits for the user to enter a value The string entered by the user is evaluated as an so it may be a literal a variable name
Definition: input.cc:871
void release(void)
Definition: ov-java.cc:103
typedef jint(JNICALL *JNI_CreateJavaVM_t)(JavaVM **pvm
bool Vjava_matrix_autoconversion
Definition: ov-java.cc:181
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function xample nargout(@histc)
Definition: ov-usr-fcn.cc:935
static void replace(QString &text, const QRegExp &re, const QString &after)
Definition: parser.cc:561
octave_value convert_to_str(bool pad=false, bool force=false, char type= '\'') const
Definition: ov.h:1202
static std::string get_home_directory(void)
Definition: oct-env.cc:143
~java_local_ref(void)
Definition: ov-java.cc:84
octave_idx_type numel(const octave_value_list &idx)
Definition: ov.h:411
static JNIEnv * thread_jni_env(void)
Definition: ov-java.cc:707
bool is_bool_type(void) const
Definition: ov.h:661
bool is_real_scalar(void) const
Definition: ov.h:551
std::string string_value(bool force=false) const
Definition: ov.h:908
OCTAVE_EXPORT octave_value_list uint32
Definition: ov.cc:1258
nd deftypefn *octave_map m
Definition: ov-struct.cc:2058
octave_value do_java_get(void *jni_env, const std::string &name)
Definition: ov-java.cc:2437
bool save_ascii(std::ostream &os)
Definition: ov-java.cc:2181
then the function must return scalars which will be concatenated into the return array(s).If code
Definition: cellfun.cc:398
void * java_object
Definition: ov-java.h:161
bool is_matrix_type(void) const
Definition: ov.h:676
int nargin
Definition: graphics.cc:10115
static long octave_thread_ID
Definition: ov-java.cc:179
bool is_string(void) const
Definition: ov.h:578
OCTAVE_EXPORT octave_value_list int16
Definition: ov.cc:1302
bool is_double_type(void) const
Definition: ov.h:624
~JVMArgs(void)
Definition: ov-java.cc:199
static bool unbox(JNIEnv *jni_env, const octave_value &val, jobject_ref &jobj, jclass_ref &jcls)
Definition: ov-java.cc:1487
double tmp
Definition: data.cc:6300
is false
Definition: cellfun.cc:398
octave_value do_javaMethod(void *jni_env, const std::string &name, const octave_value_list &args)
Definition: ov-java.cc:2228
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition: ov-java.cc:2172
bool is_int64_type(void) const
Definition: ov.h:644
octave_value retval
Definition: data.cc:6294
bool is_cellstr(void) const
Definition: ov.h:548
#define panic_impossible()
Definition: error.h:40
Matrix transpose(void) const
Definition: dMatrix.h:129
OCTAVE_EXPORT octave_value_list int32
Definition: ov.cc:1258
JNIEXPORT void JNICALL Java_org_octave_OctaveReference_doFinalize(JNIEnv *, jclass, jint)
Definition: ov-java.cc:1831
int64_t octave_hdf5_id
string_vector & sort(bool make_uniq=false)
Definition: str-vec.cc:74
dim_vector dims(void) const
Definition: ov-java.cc:1941
static octave_value check_exception(JNIEnv *jni_env)
Definition: ov-java.cc:779
octave_idx_type length(void) const
Definition: ov.cc:1623
idx type
Definition: ov.cc:3129
static int octave_java_refcount
Definition: ov-java.cc:178
Definition: dMatrix.h:37
static jclass find_octave_class(JNIEnv *jni_env, const char *name)
Definition: ov-java.cc:808
void release(void)
Definition: ov-java.cc:2739
the sparsity preserving column transformation such that that defines the pivoting threshold can be given in which case it defines the c
Definition: lu.cc:138
static std::string read_classpath_txt(const std::string &filepath)
Definition: ov-java.cc:366
java_local_ref(JNIEnv *_env)
Definition: ov-java.cc:78
the exceeded dimensions are set to if fewer subscripts than dimensions are the exceeding dimensions are merged into the final requested dimension For consider the following dims
Definition: sub2ind.cc:255
dim_vector dims(void) const
Definition: ov.h:486
java_local_ref< jobjectArray > jobjectArray_ref
Definition: ov-java.cc:125
#define TO_JNIENV(env)
Definition: ov-java.cc:65
Matrix matrix_value(bool frc_str_conv=false) const
Definition: ov.h:787
java_local_ref< jdoubleArray > jdoubleArray_ref
Definition: ov-java.cc:128
With real return the complex result
Definition: data.cc:3375
feval(ar{f}, 1) esult
Definition: oct-parse.cc:8829
bool Vjava_unsigned_autoconversion
Definition: ov-java.cc:182
friend class octave_value
Definition: ov-base.h:211
T & operator=(T obj)
Definition: ov-java.cc:86
octave_function * function_value(bool silent=false) const
Definition: ov.cc:1705
bool is_int16_type(void) const
Definition: ov.h:638
bool Vdebug_java
Definition: ov-java.cc:183
OCTAVE_EXPORT octave_value_list int64
Definition: ov.cc:1258
static octave_value convert_to_string(JNIEnv *jni_env, jobject java_object, bool force, char type)
Definition: ov-java.cc:1078
static const std::string t_name
Definition: ov-java.h:181
void warning(const char *fmt,...)
Definition: error.cc:788
static std::string path_sep_str(void)
Definition: pathsearch.h:109
bool is_empty(void) const
Definition: ov.h:542
bool is_bool_scalar(void) const
Definition: ov.h:563
void * voidptr
Definition: ov-java.h:31
std::list< std::string > java_opts
Definition: ov-java.cc:278
NDArray array_value(bool frc_str_conv=false) const
Definition: ov.h:793
JavaVMInitArgs * to_args()
Definition: ov-java.cc:204
void print(std::ostream &os, bool pr_as_read_syntax=false)
Definition: ov-java.cc:2165
bool is_java_string(void) const
Definition: ov-java.cc:720
static bool is_auto_convertible_number(JNIEnv *jni_env, jobject jobj)
Return whether jobj shall be automatically converted to an Octave numeric value.
Definition: ov-java.cc:1149
static void register_type(void)
Definition: ov-java.cc:1930
octave_value convert_to_str_internal(bool pad, bool force, char type) const
Definition: ov-java.cc:2140
static octave_value box(JNIEnv *jni_env, void *jobj, void *jcls_arg=0)
Convert the Java object pointed to by jobj_arg with class jcls_arg to an Octave value.
Definition: ov-java.cc:1192
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
std::string java_classname
Definition: ov-java.h:165
bool is_uint8_type(void) const
Definition: ov.h:647
string_vector map_keys(void) const
Definition: ov-java.cc:2118
static int register_type(const std::string &, const std::string &, const octave_value &)
Definition: ov-typeinfo.cc:60
OCTAVE_EXPORT octave_value_list or N dimensional array whose elements are all equal to the IEEE symbol zero divided by nd tex zero divided by nd ifnottex and any operation involving another NaN value(5+NaN).Note that NaN always compares not equal to NaN(NaN!
#define UNBOX_PRIMITIVE_ARRAY(METHOD_T, OCTAVE_T, JAVA_T, JAVA_T_CAP)
#define TO_JAVA(obj)
Definition: ov-java.cc:1136
JNIEXPORT void JNICALL Java_org_octave_Octave_doInvoke(JNIEnv *, jclass, jint, jobjectArray)
Definition: ov-java.cc:1837
java_local_ref< jobject > jobject_ref
Definition: ov-java.cc:122
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:301
static int t_id
Definition: ov-java.h:180
std::string class_name(void) const
Definition: ov.h:1234
java_local_ref< jintArray > jintArray_ref
Definition: ov-java.cc:126
bool is_instance_of(const std::string &) const
Definition: ov-java.cc:745
bool is_undefined(void) const
Definition: ov.h:539
bool is_uint64_type(void) const
Definition: ov.h:656
octave::sys::file_stat fs(filename)
static long get_current_thread_ID(JNIEnv *jni_env)
Definition: ov-java.cc:1743
octave_value_list subsref(const std::string &type, const std::list< octave_value_list > &idx, int nargout)
Definition: ov-java.cc:1963
void * java_class
Definition: ov-java.h:163
static void add_event_hook(event_hook_fcn f)
Definition: cmd-edit.cc:1545
static std::map< int, octave_value > octave_ref_map
Definition: ov-java.cc:177
jsize jsize * nVMs
Definition: ov-java.cc:70
static octave_value box_more(JNIEnv *jni_env, void *jobj_arg, void *jcls_arg=0)
Definition: ov-java.cc:1386
OCTINTERP_API octave_value_list eval_string(const std::string &, bool silent, int &parse_status, int nargout)
static void terminate_jvm(void)
Definition: ov-java.cc:653
void close(close_hook cl_hook=0)
Definition: oct-shlib.h:156
const T * fortran_vec(void) const
Definition: Array.h:584
void add(const std::string &opt)
Definition: ov-java.cc:210
bool is_java(void) const
Definition: ov.h:599
bool is_uint32_type(void) const
Definition: ov.h:653
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
#define TO_JOBJECT(obj)
Definition: ov-java.cc:62
void err_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
Definition: errwarn.cc:50
JavaVMInitArgs vm_args
Definition: ov-java.cc:276
static JavaVM * jvm
Definition: ov-java.cc:170
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:854
dim_vector dv
Definition: sub2ind.cc:263
static octave::dynamic_library jvm_lib
Definition: ov-java.cc:174
java_local_ref< jthrowable > jthrowable_ref
Definition: ov-java.cc:129
octave_value next_subsref(const std::string &type, const std::list< octave_value_list > &idx, size_t skip=1)
Definition: ov.cc:1462
where the brackets indicate optional arguments and and character or cell array For character arrays the conversion is repeated for every row
Definition: str2double.cc:342
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))
bool save_binary(std::ostream &os, bool &save_as_floats)
Definition: ov-java.cc:2196
bool is_real_matrix(void) const
Definition: ov.h:554
void * to_java(void) const
Definition: ov-java.h:49
bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
Definition: ov-java.cc:2204