2 * Copyright (C) 2009-2010 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 (* Please read generator/README first. *)
26 open Generator_docstrings
27 open Generator_optgroups
28 open Generator_actions
29 open Generator_structs
32 (* Generate Java bindings GuestFS.java file. *)
33 let rec generate_java_java () =
34 generate_header CStyle LGPLv2plus;
37 package com.redhat.et.libguestfs;
39 import java.util.HashMap;
40 import com.redhat.et.libguestfs.LibGuestFSException;
41 import com.redhat.et.libguestfs.PV;
42 import com.redhat.et.libguestfs.VG;
43 import com.redhat.et.libguestfs.LV;
44 import com.redhat.et.libguestfs.Stat;
45 import com.redhat.et.libguestfs.StatVFS;
46 import com.redhat.et.libguestfs.IntBool;
47 import com.redhat.et.libguestfs.Dirent;
50 * The GuestFS object is a libguestfs handle.
54 public class GuestFS {
55 // Load the native code.
57 System.loadLibrary (\"guestfs_jni\");
61 * The native guestfs_h pointer.
66 * Create a libguestfs handle.
68 * @throws LibGuestFSException
70 public GuestFS () throws LibGuestFSException
74 private native long _create () throws LibGuestFSException;
77 * Close a libguestfs handle.
79 * You can also leave handles to be collected by the garbage
80 * collector, but this method ensures that the resources used
81 * by the handle are freed up immediately. If you call any
82 * other methods after closing the handle, you will get an
85 * @throws LibGuestFSException
87 public void close () throws LibGuestFSException
93 private native void _close (long g) throws LibGuestFSException;
95 public void finalize () throws LibGuestFSException
103 fun (name, style, _, flags, _, shortdesc, longdesc) ->
104 if not (List.mem NotInDocs flags); then (
105 let doc = replace_str longdesc "C<guestfs_" "C<g." in
107 if List.mem ProtocolLimitWarning flags then
108 doc ^ "\n\n" ^ protocol_limit_warning
111 if List.mem DangerWillRobinson flags then
112 doc ^ "\n\n" ^ danger_will_robinson
115 match deprecation_notice flags with
117 | Some txt -> doc ^ "\n\n" ^ txt in
118 let doc = pod2text ~width:60 name doc in
119 let doc = List.map ( (* RHBZ#501883 *)
122 | nonempty -> nonempty
124 let doc = String.concat "\n * " doc in
127 pr " * %s\n" shortdesc;
130 pr " * @throws LibGuestFSException\n";
134 generate_java_prototype ~public:true ~semicolon:false name style;
138 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
141 if fst style <> RErr then pr "return ";
143 generate_java_call_args ~handle:"g" (snd style);
147 generate_java_prototype ~privat:true ~native:true name style;
154 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
155 and generate_java_call_args ~handle args =
157 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
160 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
161 ?(semicolon=true) name style =
162 if privat then pr "private ";
163 if public then pr "public ";
164 if native then pr "native ";
167 (match fst style with
168 | RErr -> pr "void ";
169 | RInt _ -> pr "int ";
170 | RInt64 _ -> pr "long ";
171 | RBool _ -> pr "boolean ";
172 | RConstString _ | RConstOptString _ | RString _
173 | RBufferOut _ -> pr "String ";
174 | RStringList _ -> pr "String[] ";
175 | RStruct (_, typ) ->
176 let name = java_name_of_struct typ in
178 | RStructList (_, typ) ->
179 let name = java_name_of_struct typ in
181 | RHashtable _ -> pr "HashMap<String,String> ";
184 if native then pr "_%s " name else pr "%s " name;
186 let needs_comma = ref false in
195 if !needs_comma then pr ", ";
200 | Device n | Dev_or_Path n
209 | StringList n | DeviceList n ->
220 pr " throws LibGuestFSException";
221 if semicolon then pr ";"
223 and generate_java_struct jtyp cols () =
224 generate_header CStyle LGPLv2plus;
227 package com.redhat.et.libguestfs;
230 * Libguestfs %s structure.
242 | name, FBuffer -> pr " public String %s;\n" name
243 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
244 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
245 | name, FChar -> pr " public char %s;\n" name
246 | name, FOptPercent ->
247 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
248 pr " public float %s;\n" name
253 and generate_java_c () =
254 generate_header CStyle LGPLv2plus;
261 #include \"com_redhat_et_libguestfs_GuestFS.h\"
262 #include \"guestfs.h\"
264 /* Note that this function returns. The exception is not thrown
265 * until after the wrapper function returns.
268 throw_exception (JNIEnv *env, const char *msg)
271 cl = (*env)->FindClass (env,
272 \"com/redhat/et/libguestfs/LibGuestFSException\");
273 (*env)->ThrowNew (env, cl, msg);
276 JNIEXPORT jlong JNICALL
277 Java_com_redhat_et_libguestfs_GuestFS__1create
278 (JNIEnv *env, jobject obj)
282 g = guestfs_create ();
284 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
287 guestfs_set_error_handler (g, NULL, NULL);
288 return (jlong) (long) g;
291 JNIEXPORT void JNICALL
292 Java_com_redhat_et_libguestfs_GuestFS__1close
293 (JNIEnv *env, jobject obj, jlong jg)
295 guestfs_h *g = (guestfs_h *) (long) jg;
302 fun (name, style, _, _, _, _, _) ->
304 (match fst style with
305 | RErr -> pr "void ";
306 | RInt _ -> pr "jint ";
307 | RInt64 _ -> pr "jlong ";
308 | RBool _ -> pr "jboolean ";
309 | RConstString _ | RConstOptString _ | RString _
310 | RBufferOut _ -> pr "jstring ";
311 | RStruct _ | RHashtable _ ->
313 | RStringList _ | RStructList _ ->
317 pr "Java_com_redhat_et_libguestfs_GuestFS_";
318 pr "%s" (replace_str ("_" ^ name) "_" "_1");
320 pr " (JNIEnv *env, jobject obj, jlong jg";
324 | Device n | Dev_or_Path n
332 pr ", jbyteArray j%s" n
333 | StringList n | DeviceList n ->
334 pr ", jobjectArray j%s" n
336 pr ", jboolean j%s" n
344 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
345 let error_code, no_ret =
347 | RErr -> pr " int r;\n"; "-1", ""
349 | RInt _ -> pr " int r;\n"; "-1", "0"
350 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
351 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
352 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
355 pr " char *r;\n"; "NULL", "NULL"
357 pr " jobjectArray jr;\n";
360 pr " jstring jstr;\n";
361 pr " char **r;\n"; "NULL", "NULL"
362 | RStruct (_, typ) ->
365 pr " jfieldID fl;\n";
366 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
367 | RStructList (_, typ) ->
368 pr " jobjectArray jr;\n";
370 pr " jfieldID fl;\n";
371 pr " jobject jfl;\n";
372 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
373 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
377 pr " size_t size;\n";
382 | Device n | Dev_or_Path n
388 pr " const char *%s;\n" n
390 pr " jbyte *%s;\n" n;
391 pr " size_t %s_size;\n" n
392 | StringList n | DeviceList n ->
393 pr " int %s_len;\n" n;
394 pr " const char **%s;\n" n
399 pr " int64_t %s;\n" n
403 (match fst style with
404 | RStringList _ | RStructList _ -> true
405 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
407 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
408 List.exists (function
409 | StringList _ -> true
410 | DeviceList _ -> true
411 | _ -> false) (snd style) in
417 (* Get the parameters. *)
421 | Device n | Dev_or_Path n
426 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
428 (* This is completely undocumented, but Java null becomes
431 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
433 pr " %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
434 pr " %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
435 | StringList n | DeviceList n ->
436 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
437 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
438 pr " for (i = 0; i < %s_len; ++i) {\n" n;
439 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
441 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
443 pr " %s[%s_len] = NULL;\n" n n;
447 pr " %s = j%s;\n" n n
451 pr " r = guestfs_%s " name;
452 generate_c_call_args ~handle:"g" style;
455 (* Release the parameters. *)
459 | Device n | Dev_or_Path n
464 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
467 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
469 pr " (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
470 | StringList n | DeviceList n ->
471 pr " for (i = 0; i < %s_len; ++i) {\n" n;
472 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
474 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
482 (* Check for errors. *)
483 pr " if (r == %s) {\n" error_code;
484 pr " throw_exception (env, guestfs_last_error (g));\n";
485 pr " return %s;\n" no_ret;
489 (match fst style with
491 | RInt _ -> pr " return (jint) r;\n"
492 | RBool _ -> pr " return (jboolean) r;\n"
493 | RInt64 _ -> pr " return (jlong) r;\n"
494 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
495 | RConstOptString _ ->
496 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
498 pr " jr = (*env)->NewStringUTF (env, r);\n";
502 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
503 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
504 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
505 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
506 pr " for (i = 0; i < r_len; ++i) {\n";
507 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
508 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
509 pr " free (r[i]);\n";
513 | RStruct (_, typ) ->
514 let jtyp = java_name_of_struct typ in
515 let cols = cols_of_struct typ in
516 generate_java_struct_return typ jtyp cols
517 | RStructList (_, typ) ->
518 let jtyp = java_name_of_struct typ in
519 let cols = cols_of_struct typ in
520 generate_java_struct_list_return typ jtyp cols
523 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
526 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
535 and generate_java_struct_return typ jtyp cols =
536 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
537 pr " jr = (*env)->AllocObject (env, cl);\n";
541 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
542 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
546 pr " memcpy (s, r->%s, 32);\n" name;
548 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
549 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
553 pr " int len = r->%s_len;\n" name;
554 pr " char s[len+1];\n";
555 pr " memcpy (s, r->%s, len);\n" name;
557 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
558 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
560 | name, (FBytes|FUInt64|FInt64) ->
561 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
562 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
563 | name, (FUInt32|FInt32) ->
564 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
565 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
566 | name, FOptPercent ->
567 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
568 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
570 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
571 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
576 and generate_java_struct_list_return typ jtyp cols =
577 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
578 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
579 pr " for (i = 0; i < r->len; ++i) {\n";
580 pr " jfl = (*env)->AllocObject (env, cl);\n";
584 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
585 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
589 pr " memcpy (s, r->val[i].%s, 32);\n" name;
591 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
592 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
596 pr " int len = r->val[i].%s_len;\n" name;
597 pr " char s[len+1];\n";
598 pr " memcpy (s, r->val[i].%s, len);\n" name;
600 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
601 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
603 | name, (FBytes|FUInt64|FInt64) ->
604 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
605 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
606 | name, (FUInt32|FInt32) ->
607 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
608 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
609 | name, FOptPercent ->
610 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
611 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
613 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
614 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
616 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
618 pr " guestfs_free_%s_list (r);\n" typ;
621 and generate_java_makefile_inc () =
622 generate_header HashStyle GPLv2plus;
624 pr "java_built_sources = \\\n";
627 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
629 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"