ocaml: Document g#close () method for objects.
[libguestfs.git] / generator / generator_java.ml
1 (* libguestfs
2  * Copyright (C) 2009-2010 Red Hat Inc.
3  *
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.
8  *
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.
13  *
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
17  *)
18
19 (* Please read generator/README first. *)
20
21 open Printf
22
23 open Generator_types
24 open Generator_utils
25 open Generator_pr
26 open Generator_docstrings
27 open Generator_optgroups
28 open Generator_actions
29 open Generator_structs
30 open Generator_c
31
32 (* Generate Java bindings GuestFS.java file. *)
33 let rec generate_java_java () =
34   generate_header CStyle LGPLv2plus;
35
36   pr "\
37 package com.redhat.et.libguestfs;
38
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;
48
49 /**
50  * The GuestFS object is a libguestfs handle.
51  *
52  * @author rjones
53  */
54 public class GuestFS {
55   // Load the native code.
56   static {
57     System.loadLibrary (\"guestfs_jni\");
58   }
59
60   /**
61    * The native guestfs_h pointer.
62    */
63   long g;
64
65   /**
66    * Create a libguestfs handle.
67    *
68    * @throws LibGuestFSException
69    */
70   public GuestFS () throws LibGuestFSException
71   {
72     g = _create ();
73   }
74   private native long _create () throws LibGuestFSException;
75
76   /**
77    * Close a libguestfs handle.
78    *
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
83    * exception.
84    *
85    * @throws LibGuestFSException
86    */
87   public void close () throws LibGuestFSException
88   {
89     if (g != 0)
90       _close (g);
91     g = 0;
92   }
93   private native void _close (long g) throws LibGuestFSException;
94
95   public void finalize () throws LibGuestFSException
96   {
97     close ();
98   }
99
100 ";
101
102   List.iter (
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
106         let doc =
107           if List.mem ProtocolLimitWarning flags then
108             doc ^ "\n\n" ^ protocol_limit_warning
109           else doc in
110         let doc =
111           if List.mem DangerWillRobinson flags then
112             doc ^ "\n\n" ^ danger_will_robinson
113           else doc in
114         let doc =
115           match deprecation_notice flags with
116           | None -> doc
117           | Some txt -> doc ^ "\n\n" ^ txt in
118         let doc = pod2text ~width:60 name doc in
119         let doc = List.map (            (* RHBZ#501883 *)
120           function
121           | "" -> "<p>"
122           | nonempty -> nonempty
123         ) doc in
124         let doc = String.concat "\n   * " doc in
125
126         pr "  /**\n";
127         pr "   * %s\n" shortdesc;
128         pr "   * <p>\n";
129         pr "   * %s\n" doc;
130         pr "   * @throws LibGuestFSException\n";
131         pr "   */\n";
132         pr "  ";
133       );
134       generate_java_prototype ~public:true ~semicolon:false name style;
135       pr "\n";
136       pr "  {\n";
137       pr "    if (g == 0)\n";
138       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
139         name;
140       pr "    ";
141       if fst style <> RErr then pr "return ";
142       pr "_%s " name;
143       generate_java_call_args ~handle:"g" (snd style);
144       pr ";\n";
145       pr "  }\n";
146       pr "  ";
147       generate_java_prototype ~privat:true ~native:true name style;
148       pr "\n";
149       pr "\n";
150   ) all_functions;
151
152   pr "}\n"
153
154 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
155 and generate_java_call_args ~handle args =
156   pr "(%s" handle;
157   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
158   pr ")"
159
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 ";
165
166   (* return type *)
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
177        pr "%s " name;
178    | RStructList (_, typ) ->
179        let name = java_name_of_struct typ in
180        pr "%s[] " name;
181    | RHashtable _ -> pr "HashMap<String,String> ";
182   );
183
184   if native then pr "_%s " name else pr "%s " name;
185   pr "(";
186   let needs_comma = ref false in
187   if native then (
188     pr "long g";
189     needs_comma := true
190   );
191
192   (* args *)
193   List.iter (
194     fun arg ->
195       if !needs_comma then pr ", ";
196       needs_comma := true;
197
198       match arg with
199       | Pathname n
200       | Device n | Dev_or_Path n
201       | String n
202       | OptString n
203       | FileIn n
204       | FileOut n
205       | Key n ->
206           pr "String %s" n
207       | BufferIn n ->
208           pr "byte[] %s" n
209       | StringList n | DeviceList n ->
210           pr "String[] %s" n
211       | Bool n ->
212           pr "boolean %s" n
213       | Int n ->
214           pr "int %s" n
215       | Int64 n ->
216           pr "long %s" n
217   ) (snd style);
218
219   pr ")\n";
220   pr "    throws LibGuestFSException";
221   if semicolon then pr ";"
222
223 and generate_java_struct jtyp cols () =
224   generate_header CStyle LGPLv2plus;
225
226   pr "\
227 package com.redhat.et.libguestfs;
228
229 /**
230  * Libguestfs %s structure.
231  *
232  * @author rjones
233  * @see GuestFS
234  */
235 public class %s {
236 " jtyp jtyp;
237
238   List.iter (
239     function
240     | name, FString
241     | name, FUUID
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
249   ) cols;
250
251   pr "}\n"
252
253 and generate_java_c () =
254   generate_header CStyle LGPLv2plus;
255
256   pr "\
257 #include <stdio.h>
258 #include <stdlib.h>
259 #include <string.h>
260
261 #include \"com_redhat_et_libguestfs_GuestFS.h\"
262 #include \"guestfs.h\"
263
264 /* Note that this function returns.  The exception is not thrown
265  * until after the wrapper function returns.
266  */
267 static void
268 throw_exception (JNIEnv *env, const char *msg)
269 {
270   jclass cl;
271   cl = (*env)->FindClass (env,
272                           \"com/redhat/et/libguestfs/LibGuestFSException\");
273   (*env)->ThrowNew (env, cl, msg);
274 }
275
276 JNIEXPORT jlong JNICALL
277 Java_com_redhat_et_libguestfs_GuestFS__1create
278   (JNIEnv *env, jobject obj)
279 {
280   guestfs_h *g;
281
282   g = guestfs_create ();
283   if (g == NULL) {
284     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
285     return 0;
286   }
287   guestfs_set_error_handler (g, NULL, NULL);
288   return (jlong) (long) g;
289 }
290
291 JNIEXPORT void JNICALL
292 Java_com_redhat_et_libguestfs_GuestFS__1close
293   (JNIEnv *env, jobject obj, jlong jg)
294 {
295   guestfs_h *g = (guestfs_h *) (long) jg;
296   guestfs_close (g);
297 }
298
299 ";
300
301   List.iter (
302     fun (name, style, _, _, _, _, _) ->
303       pr "JNIEXPORT ";
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 _ ->
312            pr "jobject ";
313        | RStringList _ | RStructList _ ->
314            pr "jobjectArray ";
315       );
316       pr "JNICALL\n";
317       pr "Java_com_redhat_et_libguestfs_GuestFS_";
318       pr "%s" (replace_str ("_" ^ name) "_" "_1");
319       pr "\n";
320       pr "  (JNIEnv *env, jobject obj, jlong jg";
321       List.iter (
322         function
323         | Pathname n
324         | Device n | Dev_or_Path n
325         | String n
326         | OptString n
327         | FileIn n
328         | FileOut n
329         | Key n ->
330             pr ", jstring j%s" n
331         | BufferIn n ->
332             pr ", jbyteArray j%s" n
333         | StringList n | DeviceList n ->
334             pr ", jobjectArray j%s" n
335         | Bool n ->
336             pr ", jboolean j%s" n
337         | Int n ->
338             pr ", jint j%s" n
339         | Int64 n ->
340             pr ", jlong j%s" n
341       ) (snd style);
342       pr ")\n";
343       pr "{\n";
344       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
345       let error_code, no_ret =
346         match fst style with
347         | RErr -> pr "  int r;\n"; "-1", ""
348         | RBool _
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"
353         | RString _ ->
354             pr "  jstring jr;\n";
355             pr "  char *r;\n"; "NULL", "NULL"
356         | RStringList _ ->
357             pr "  jobjectArray jr;\n";
358             pr "  int r_len;\n";
359             pr "  jclass cl;\n";
360             pr "  jstring jstr;\n";
361             pr "  char **r;\n"; "NULL", "NULL"
362         | RStruct (_, typ) ->
363             pr "  jobject jr;\n";
364             pr "  jclass cl;\n";
365             pr "  jfieldID fl;\n";
366             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
367         | RStructList (_, typ) ->
368             pr "  jobjectArray jr;\n";
369             pr "  jclass cl;\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"
374         | RBufferOut _ ->
375             pr "  jstring jr;\n";
376             pr "  char *r;\n";
377             pr "  size_t size;\n";
378             "NULL", "NULL" in
379       List.iter (
380         function
381         | Pathname n
382         | Device n | Dev_or_Path n
383         | String n
384         | OptString n
385         | FileIn n
386         | FileOut n
387         | Key n ->
388             pr "  const char *%s;\n" n
389         | BufferIn 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
395         | Bool n
396         | Int n ->
397             pr "  int %s;\n" n
398         | Int64 n ->
399             pr "  int64_t %s;\n" n
400       ) (snd style);
401
402       let needs_i =
403         (match fst style with
404          | RStringList _ | RStructList _ -> true
405          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
406          | RConstOptString _
407          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
408           List.exists (function
409                        | StringList _ -> true
410                        | DeviceList _ -> true
411                        | _ -> false) (snd style) in
412       if needs_i then
413         pr "  size_t i;\n";
414
415       pr "\n";
416
417       (* Get the parameters. *)
418       List.iter (
419         function
420         | Pathname n
421         | Device n | Dev_or_Path n
422         | String n
423         | FileIn n
424         | FileOut n
425         | Key n ->
426             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
427         | OptString n ->
428             (* This is completely undocumented, but Java null becomes
429              * a NULL parameter.
430              *)
431             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
432         | BufferIn 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"
440               n;
441             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
442             pr "  }\n";
443             pr "  %s[%s_len] = NULL;\n" n n;
444         | Bool n
445         | Int n
446         | Int64 n ->
447             pr "  %s = j%s;\n" n n
448       ) (snd style);
449
450       (* Make the call. *)
451       pr "  r = guestfs_%s " name;
452       generate_c_call_args ~handle:"g" style;
453       pr ";\n";
454
455       (* Release the parameters. *)
456       List.iter (
457         function
458         | Pathname n
459         | Device n | Dev_or_Path n
460         | String n
461         | FileIn n
462         | FileOut n
463         | Key n ->
464             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
465         | OptString n ->
466             pr "  if (j%s)\n" n;
467             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
468         | BufferIn 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"
473               n;
474             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
475             pr "  }\n";
476             pr "  free (%s);\n" n
477         | Bool n
478         | Int n
479         | Int64 n -> ()
480       ) (snd style);
481
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;
486       pr "  }\n";
487
488       (* Return value. *)
489       (match fst style with
490        | RErr -> ()
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"
497        | RString _ ->
498            pr "  jr = (*env)->NewStringUTF (env, r);\n";
499            pr "  free (r);\n";
500            pr "  return jr;\n"
501        | RStringList _ ->
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";
510            pr "  }\n";
511            pr "  free (r);\n";
512            pr "  return jr;\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
521        | RHashtable _ ->
522            (* XXX *)
523            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
524            pr "  return NULL;\n"
525        | RBufferOut _ ->
526            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
527            pr "  free (r);\n";
528            pr "  return jr;\n"
529       );
530
531       pr "}\n";
532       pr "\n"
533   ) all_functions
534
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";
538   List.iter (
539     function
540     | name, FString ->
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;
543     | name, FUUID ->
544         pr "  {\n";
545         pr "    char s[33];\n";
546         pr "    memcpy (s, r->%s, 32);\n" name;
547         pr "    s[32] = 0;\n";
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";
550         pr "  }\n";
551     | name, FBuffer ->
552         pr "  {\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;
556         pr "    s[len] = 0;\n";
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";
559         pr "  }\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;
569     | name, FChar ->
570         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
571         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
572   ) cols;
573   pr "  free (r);\n";
574   pr "  return jr;\n"
575
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";
581   List.iter (
582     function
583     | name, FString ->
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;
586     | name, FUUID ->
587         pr "    {\n";
588         pr "      char s[33];\n";
589         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
590         pr "      s[32] = 0;\n";
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";
593         pr "    }\n";
594     | name, FBuffer ->
595         pr "    {\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;
599         pr "      s[len] = 0;\n";
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";
602         pr "    }\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;
612     | name, FChar ->
613         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
614         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
615   ) cols;
616   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
617   pr "  }\n";
618   pr "  guestfs_free_%s_list (r);\n" typ;
619   pr "  return jr;\n"
620
621 and generate_java_makefile_inc () =
622   generate_header HashStyle GPLv2plus;
623
624   pr "java_built_sources = \\\n";
625   List.iter (
626     fun (typ, jtyp) ->
627         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
628   ) java_structs;
629   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"