[Libguestfs] Misc Java patches
Richard W.M. Jones
rjones at redhat.com
Thu Jan 10 09:19:35 UTC 2013
Only tested on ARM (!) so far, but if someone can test them on
x86{,64} that'd be great.
Rich.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming blog: http://rwmj.wordpress.com
Fedora now supports 80 OCaml packages (the OPEN alternative to F#)
-------------- next part --------------
From 387616241206c2b6e3a1bbaedd84cb3b586975d9 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones at redhat.com>
Date: Fri, 4 Jan 2013 12:33:48 +0900
Subject: [PATCH 1/7] Update copyright dates for 2013.
On generated files in git and README.
---
README | 2 +-
gobject/Makefile.inc | 2 +-
java/Makefile.inc | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/README b/README
index 1196e0f..6a5692f 100644
--- a/README
+++ b/README
@@ -346,7 +346,7 @@ attention to the qemu command line and kernel output.
Copyright and license information
----------------------------------------------------------------------
-Copyright (C) 2009-2012 Red Hat Inc.
+Copyright (C) 2009-2013 Red Hat Inc.
The library is distributed under the LGPLv2+. The programs are
distributed under the GPLv2+. Please see the files COPYING and
diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc
index 8708994..25c383e 100644
--- a/gobject/Makefile.inc
+++ b/gobject/Makefile.inc
@@ -3,7 +3,7 @@
# generator/ *.ml
# ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
#
-# Copyright (C) 2009-2012 Red Hat Inc.
+# Copyright (C) 2009-2013 Red Hat Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/java/Makefile.inc b/java/Makefile.inc
index 9dd39de..985be59 100644
--- a/java/Makefile.inc
+++ b/java/Makefile.inc
@@ -3,7 +3,7 @@
# generator/ *.ml
# ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
#
-# Copyright (C) 2009-2012 Red Hat Inc.
+# Copyright (C) 2009-2013 Red Hat Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
--
1.7.11.7
-------------- next part --------------
From 33f9dd68b244d3d8c6afb9032413626ff62beda9 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones at redhat.com>
Date: Wed, 9 Jan 2013 12:28:23 +0900
Subject: [PATCH 2/7] Refresh README file.
---
README | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/README b/README
index 6a5692f..28db6c5 100644
--- a/README
+++ b/README
@@ -166,12 +166,12 @@ To build the Perl tools:
Building
----------------------------------------------------------------------
-Then make the daemon, library and root filesystem:
+Build the daemon, library and root filesystem:
./configure
make
-Finally run the tests:
+Run the tests:
make check
@@ -189,6 +189,10 @@ some libvirt guests installed, that these guests' disks are accessible
by the current user, and these tests may fail for other reasons which
are not necessarily because of real problems.
+ make help
+
+lists all 'make' targets.
+
If everything works, you can install the library and tools by running
this command as root:
@@ -292,7 +296,7 @@ distributions. Non-Linux ports are trickier, but we will accept
patches if they aren't too invasive.
The main porting issues are with the dependencies needed to build the
-appliance. You will need to port the febootstrap first
+appliance. You will need to port febootstrap first
(http://people.redhat.com/~rjones/febootstrap/).
--
1.7.11.7
-------------- next part --------------
From da00e6e1b0645e69431a2161aeebb4f18a01f3a0 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones at redhat.com>
Date: Mon, 7 Jan 2013 06:46:09 +0900
Subject: [PATCH 3/7] java: Tidy up javadoc.
---
generator/java.ml | 16 ++++++++++++++--
java/com/redhat/et/libguestfs/LibGuestFSException.java | 4 +++-
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/generator/java.ml b/generator/java.ml
index c83bf80..270ad44 100644
--- a/generator/java.ml
+++ b/generator/java.ml
@@ -40,7 +40,19 @@ import java.util.HashMap;
import java.util.Map;
/**
- * The GuestFS object is a libguestfs handle.
+ * Libguestfs handle.
+ * <p>
+ * The <code>GuestFS</code> object corresponds to a libguestfs handle.
+ * <p>
+ * Note that the main documentation for the libguestfs API is in
+ * the following man pages:
+ * <p>
+ * <ol>
+ * <li> <a href=\"http://libguestfs.org/guestfs-java.3.html\"><code>guestfs-java(3)</code></a> and </li>
+ * <li> <a href=\"http://libguestfs.org/guestfs.3.html\"><code>guestfs(3)</code></a>. </li>
+ * </ol>
+ * <p>
+ * This javadoc is <b>not</b> a good introduction to using libguestfs.
*
* @author rjones
*/
@@ -384,7 +396,7 @@ and generate_java_struct jtyp cols () =
package com.redhat.et.libguestfs;
/**
- * Libguestfs %s structure.
+ * %s structure.
*
* @author rjones
* @see GuestFS
diff --git a/java/com/redhat/et/libguestfs/LibGuestFSException.java b/java/com/redhat/et/libguestfs/LibGuestFSException.java
index c7bcc05..7b5a27f 100644
--- a/java/com/redhat/et/libguestfs/LibGuestFSException.java
+++ b/java/com/redhat/et/libguestfs/LibGuestFSException.java
@@ -1,5 +1,5 @@
/* libguestfs Java bindings
- * Copyright (C) 2009 Red Hat Inc.
+ * Copyright (C) 2009-2013 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -19,6 +19,8 @@
package com.redhat.et.libguestfs;
/**
+ * Libguestfs error class.
+ * <p>
* This exception is thrown when some error occurs when using the
* libguestfs library. The error message is always a simple
* printable string.
--
1.7.11.7
-------------- next part --------------
From f3eabd6c849f39380f698433e1cac95fd0627189 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones at redhat.com>
Date: Mon, 7 Jan 2013 23:41:46 +0900
Subject: [PATCH 4/7] java: Change synopsis in man page to show use of
add_drive.
---
java/examples/guestfs-java.pod | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/java/examples/guestfs-java.pod b/java/examples/guestfs-java.pod
index 0795c86..6e032b4 100644
--- a/java/examples/guestfs-java.pod
+++ b/java/examples/guestfs-java.pod
@@ -9,7 +9,13 @@ guestfs-java - How to use libguestfs from Java
import com.redhat.et.libguestfs.*;
GuestFS g = new GuestFS ();
- g.add_drive_opts ("disk.img");
+ g.add_drive ("disk.img",
+ new HashMap<String,Object>() {
+ {
+ put ("readonly", Boolean.TRUE);
+ put ("format", "raw");
+ }
+ });
g.launch ();
=head1 DESCRIPTION
--
1.7.11.7
-------------- next part --------------
From e18e3674b53dce63a88f58387ad5109c6b780716 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones at redhat.com>
Date: Tue, 8 Jan 2013 11:29:31 +0900
Subject: [PATCH 5/7] java: Use defined constants for flags in call to
guestfs_create_flags.
---
generator/java.ml | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/generator/java.ml b/generator/java.ml
index 270ad44..1879f50 100644
--- a/generator/java.ml
+++ b/generator/java.ml
@@ -67,6 +67,10 @@ public class GuestFS {
*/
long g;
+ /* guestfs_create_flags values defined in <guestfs.h> */
+ private static int CREATE_NO_ENVIRONMENT = 1;
+ private static int CREATE_NO_CLOSE_ON_EXIT = 2;
+
/**
* Create a libguestfs handle, setting flags.
*
@@ -82,11 +86,11 @@ public class GuestFS {
if (optargs != null)
_optobj = optargs.get (\"environment\");
if (_optobj != null && !((Boolean) _optobj).booleanValue())
- flags |= 1;
+ flags |= CREATE_NO_ENVIRONMENT;
if (optargs != null)
_optobj = optargs.get (\"close_on_exit\");
if (_optobj != null && !((Boolean) _optobj).booleanValue())
- flags |= 2;
+ flags |= CREATE_NO_CLOSE_ON_EXIT;
g = _create (flags);
}
@@ -100,6 +104,7 @@ public class GuestFS {
{
g = _create (0);
}
+
private native long _create (int flags) throws LibGuestFSException;
/**
--
1.7.11.7
-------------- next part --------------
From 4b9c9401aac30054333af891f9630a59b63d474a Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones at redhat.com>
Date: Fri, 4 Jan 2013 05:07:16 +0900
Subject: [PATCH 6/7] java: Implement the event API.
---
generator/java.ml | 302 ++++++++++++++++++++++-
generator/main.ml | 3 +-
java/Makefile.am | 6 +-
java/com/redhat/et/libguestfs/EventCallback.java | 33 +++
java/examples/guestfs-java.pod | 30 +++
java/t/GuestFS400Events.java | 95 +++++++
6 files changed, 465 insertions(+), 4 deletions(-)
create mode 100644 java/com/redhat/et/libguestfs/EventCallback.java
create mode 100644 java/t/GuestFS400Events.java
diff --git a/generator/java.ml b/generator/java.ml
index 1879f50..9ef09ad 100644
--- a/generator/java.ml
+++ b/generator/java.ml
@@ -1,5 +1,5 @@
(* libguestfs
- * Copyright (C) 2009-2012 Red Hat Inc.
+ * Copyright (C) 2009-2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@ open Docstrings
open Optgroups
open Actions
open Structs
+open Events
open C
(* Generate Java bindings GuestFS.java file. *)
@@ -133,6 +134,117 @@ public class GuestFS {
";
+ (* Events. *)
+ pr " // Event bitmasks.\n\n";
+ List.iter (
+ fun (name, bitmask) ->
+ pr " /**\n";
+ pr " * Event '%s'.\n" name;
+ pr " *\n";
+ pr " * @see #set_event_callback\n";
+ pr " */\n";
+ pr " public static final long EVENT_%s = 0x%x;\n" (String.uppercase name) bitmask;
+ pr "\n";
+ ) events;
+
+ pr " /** Bitmask of all events. */\n";
+ pr " public static final long EVENT_ALL = 0x%x;\n" ((1 lsl List.length events) - 1);
+ pr "\n";
+
+ pr " /** Utility function to turn an event number or bitmask into a string. */\n";
+ pr " public static String eventToString (long events)\n";
+ pr " {\n";
+ pr " if (events == 0)\n";
+ pr " return \"\";\n";
+ pr "\n";
+ pr " String ret = \"\";\n";
+ pr "\n";
+ List.iter (
+ fun (name, bitmask) ->
+ pr " if ((events & EVENT_%s) != 0) {\n" (String.uppercase name);
+ pr " ret = ret + \"|EVENT_%s\";\n" (String.uppercase name);
+ pr " events &= ~0x%x;\n" bitmask;
+ pr " }\n";
+ ) events;
+ pr "\n";
+ pr " if (events != 0)\n";
+ pr " ret = events + ret;\n";
+ pr " else\n";
+ pr " ret = ret.substring (1);\n";
+ pr "\n";
+ pr " return ret;\n";
+ pr " }\n";
+
+ pr "
+ /**
+ * Set an event handler.
+ * <p>
+ * Set an event handler (<code>callback</code>) which is called when any
+ * event from the set (<code>events</code>) is raised by the API.
+ * <code>events</code> is one or more <code>EVENT_*</code> constants,
+ * bitwise ORed together.
+ * <p>
+ * When an event happens, the callback object's <code>event</code> method
+ * is invoked like this:
+ * <pre>
+ * callback.event (event, // the specific event which fired (long)
+ * eh, // the event handle (int)
+ * buffer, // event data (String)
+ * array // event data (long[])
+ * );
+ * </pre>
+ * Note that you can pass arbitrary data from the main program to the
+ * callback by putting it into your {@link EventCallback callback object},
+ * then accessing it in the callback via <code>this</code>.
+ * <p>
+ * This function returns an event handle which may be used to delete
+ * the event. Note that event handlers are deleted automatically when
+ * the libguestfs handle is closed.
+ *
+ * @throws LibGuestFSException
+ * @see The section \"EVENTS\" in the guestfs(3) manual
+ * @see #delete_event_callback
+ */
+ public int set_event_callback (EventCallback callback, long events)
+ throws LibGuestFSException
+ {
+ if (g == 0)
+ throw new LibGuestFSException (\"set_event_callback: handle is closed\");
+
+ return _set_event_callback (g, callback, events);
+ }
+
+ private native int _set_event_callback (long g, EventCallback callback,
+ long events)
+ throws LibGuestFSException;
+
+ /**
+ * Delete an event handler.
+ * <p>
+ * Delete a previously registered event handler. The 'eh' parameter is
+ * the event handle returned from a previous call to
+ * {@link #set_event_callback set_event_callback}.
+ * <p>
+ * Note that event handlers are deleted automatically when the
+ * libguestfs handle is closed.
+ *
+ * @throws LibGuestFSException
+ * @see #set_event_callback
+ */
+ public void delete_event_callback (int eh)
+ throws LibGuestFSException
+ {
+ if (g == 0)
+ throw new LibGuestFSException (\"delete_event_callback: handle is closed\");
+
+ _delete_event_callback (g, eh);
+ }
+
+ private native void _delete_event_callback (long g, int eh);
+
+";
+
+ (* Methods. *)
List.iter (
fun ({ name = name; style = (ret, args, optargs as style);
in_docs = in_docs; shortdesc = shortdesc;
@@ -433,10 +545,25 @@ and generate_java_c () =
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <inttypes.h>
#include \"com_redhat_et_libguestfs_GuestFS.h\"
#include \"guestfs.h\"
+/* This is the opaque data passed between _set_event_callback and
+ * the C wrapper which calls the Java event callback.
+ *
+ * NB: The 'callback' in the following struct is registered as a global
+ * reference. It must be freed along with the struct.
+ */
+struct callback_data {
+ JavaVM *jvm; // JVM
+ jobject callback; // object supporting EventCallback interface
+ jmethodID method; // callback.event method
+};
+
+static struct callback_data **get_all_event_callbacks (guestfs_h *g, size_t *len_rtn);
+
/* Note that this function returns. The exception is not thrown
* until after the wrapper function returns.
*/
@@ -469,7 +596,180 @@ Java_com_redhat_et_libguestfs_GuestFS__1close
(JNIEnv *env, jobject obj, jlong jg)
{
guestfs_h *g = (guestfs_h *) (long) jg;
+ size_t len, i;
+ struct callback_data **data;
+
+ /* There is a nasty, difficult to solve case here where the
+ * user deletes events in one of the callbacks that we are
+ * about to invoke, resulting in a double-free. XXX
+ */
+ data = get_all_event_callbacks (g, &len);
+
guestfs_close (g);
+
+ for (i = 0; i < len; ++i) {
+ (*env)->DeleteGlobalRef (env, data[i]->callback);
+ free (data[i]);
+ }
+ free (data);
+}
+
+/* See EventCallback interface. */
+#define METHOD_NAME \"event\"
+#define METHOD_SIGNATURE \"(JILjava/lang/String;[J)V\"
+
+static void
+guestfs_java_callback (guestfs_h *g,
+ void *opaque,
+ uint64_t event,
+ int event_handle,
+ int flags,
+ const char *buf, size_t buf_len,
+ const uint64_t *array, size_t array_len)
+{
+ struct callback_data *data = opaque;
+ JavaVM *jvm = data->jvm;
+ JNIEnv *env;
+ int r;
+ jstring jbuf;
+ jlongArray jarray;
+ size_t i;
+ jlong jl;
+
+ /* Get the Java environment. See:
+ * http://stackoverflow.com/questions/12900695/how-to-obtain-jni-interface-pointer-jnienv-for-asynchronous-calls
+ */
+ r = (*jvm)->GetEnv (jvm, (void **) &env, JNI_VERSION_1_6);
+ if (r != JNI_OK) {
+ switch (r) {
+ case JNI_EDETACHED:
+ /* This can happen when the close event is generated during an atexit
+ * cleanup. The JVM has probably been destroyed so I doubt it is
+ * safe to run Java code at this point.
+ */
+ fprintf (stderr, \"%%s: event %%\" PRIu64 \" (eh %%d) ignored because the thread is not attached to the JVM. This can happen when libguestfs handles are cleaned up at program exit after the JVM has been destroyed.\\n\",
+ __func__, event, event_handle);
+ return;
+
+ default:
+ fprintf (stderr, \"%%s: jvm->GetEnv failed! (JNI_* error code = %%d)\\n\",
+ __func__, r);
+ return;
+ }
+ }
+
+ /* Convert the buffer and array to Java objects. */
+ jbuf = (*env)->NewStringUTF (env, buf); // XXX size
+
+ jarray = (*env)->NewLongArray (env, array_len);
+ for (i = 0; i < array_len; ++i) {
+ jl = array[i];
+ (*env)->SetLongArrayRegion (env, jarray, i, 1, &jl);
+ }
+
+ /* Call the event method. If it throws an exception, all we can do is
+ * print it on stderr.
+ */
+ (*env)->ExceptionClear (env);
+ (*env)->CallVoidMethod (env, data->callback, data->method,
+ (jlong) event, (jint) event_handle,
+ jbuf, jarray);
+ if ((*env)->ExceptionOccurred (env)) {
+ (*env)->ExceptionDescribe (env);
+ (*env)->ExceptionClear (env);
+ }
+}
+
+JNIEXPORT jint JNICALL
+Java_com_redhat_et_libguestfs_GuestFS__1set_1event_1callback
+ (JNIEnv *env, jobject obj, jlong jg, jobject jcallback, jlong jevents)
+{
+ guestfs_h *g = (guestfs_h *) (long) jg;
+ int r;
+ struct callback_data *data;
+ jclass callback_class;
+ jmethodID method;
+ char key[64];
+
+ callback_class = (*env)->GetObjectClass (env, jcallback);
+ method = (*env)->GetMethodID (env, callback_class, METHOD_NAME, METHOD_SIGNATURE);
+ if (method == 0) {
+ throw_exception (env, \"GuestFS.set_event_callback: callback class does not implement the EventCallback interface\");
+ return -1;
+ }
+
+ data = guestfs___safe_malloc (g, sizeof *data);
+ (*env)->GetJavaVM (env, &data->jvm);
+ data->method = method;
+
+ r = guestfs_set_event_callback (g, guestfs_java_callback,
+ (uint64_t) jevents, 0, data);
+ if (r == -1) {
+ free (data);
+ throw_exception (env, guestfs_last_error (g));
+ return -1;
+ }
+
+ /* Register jcallback as a global reference so the GC won't free it. */
+ data->callback = (*env)->NewGlobalRef (env, jcallback);
+
+ /* Store 'data' in the handle, so we can free it at some point. */
+ snprintf (key, sizeof key, \"_java_event_%%d\", r);
+ guestfs_set_private (g, key, data);
+
+ return (jint) r;
+}
+
+JNIEXPORT void JNICALL
+Java_com_redhat_et_libguestfs_GuestFS__1delete_1event_1callback
+ (JNIEnv *env, jobject obj, jlong jg, jint eh)
+{
+ guestfs_h *g = (guestfs_h *) (long) jg;
+ char key[64];
+ struct callback_data *data;
+
+ snprintf (key, sizeof key, \"_java_event_%%d\", eh);
+
+ data = guestfs_get_private (g, key);
+ if (data) {
+ (*env)->DeleteGlobalRef (env, data->callback);
+ free (data);
+ guestfs_set_private (g, key, NULL);
+ guestfs_delete_event_callback (g, eh);
+ }
+}
+
+static struct callback_data **
+get_all_event_callbacks (guestfs_h *g, size_t *len_rtn)
+{
+ struct callback_data **r;
+ size_t i;
+ const char *key;
+ struct callback_data *data;
+
+ /* Count the length of the array that will be needed. */
+ *len_rtn = 0;
+ data = guestfs_first_private (g, &key);
+ while (data != NULL) {
+ if (strncmp (key, \"_java_event_\", strlen (\"_java_event_\")) == 0)
+ (*len_rtn)++;
+ data = guestfs_next_private (g, &key);
+ }
+
+ /* Copy them into the return array. */
+ r = guestfs___safe_malloc (g, sizeof (struct callback_data *) * (*len_rtn));
+
+ i = 0;
+ data = guestfs_first_private (g, &key);
+ while (data != NULL) {
+ if (strncmp (key, \"_java_event_\", strlen (\"_java_event_\")) == 0) {
+ r[i] = data;
+ i++;
+ }
+ data = guestfs_next_private (g, &key);
+ }
+
+ return r;
}
";
diff --git a/generator/main.ml b/generator/main.ml
index 618052b..69ebe05 100644
--- a/generator/main.ml
+++ b/generator/main.ml
@@ -138,7 +138,8 @@ Run it from the top source directory using the command
output_to filename (generate_java_struct jtyp cols)
) structs;
delete_except_generated
- ~skip:["java/com/redhat/et/libguestfs/LibGuestFSException.java"]
+ ~skip:["java/com/redhat/et/libguestfs/LibGuestFSException.java";
+ "java/com/redhat/et/libguestfs/EventCallback.java"]
"java/com/redhat/et/libguestfs/*.java";
output_to "java/Makefile.inc" generate_java_makefile_inc;
diff --git a/java/Makefile.am b/java/Makefile.am
index b655ae9..449f40b 100644
--- a/java/Makefile.am
+++ b/java/Makefile.am
@@ -1,5 +1,5 @@
# libguestfs Java bindings
-# Copyright (C) 2009-2012 Red Hat Inc.
+# Copyright (C) 2009-2013 Red Hat Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -33,13 +33,15 @@ include $(srcdir)/Makefile.inc
java_sources = \
$(java_built_sources) \
+ com/redhat/et/libguestfs/EventCallback.java \
com/redhat/et/libguestfs/LibGuestFSException.java
java_tests = \
Bindtests.java \
t/GuestFS005Load.java \
t/GuestFS010Basic.java \
- t/GuestFS080OptArgs.java
+ t/GuestFS080OptArgs.java \
+ t/GuestFS400Events.java
EXTRA_DIST = \
$(java_sources) \
diff --git a/java/com/redhat/et/libguestfs/EventCallback.java b/java/com/redhat/et/libguestfs/EventCallback.java
new file mode 100644
index 0000000..a5e84e1
--- /dev/null
+++ b/java/com/redhat/et/libguestfs/EventCallback.java
@@ -0,0 +1,33 @@
+/* libguestfs Java bindings
+ * Copyright (C) 2009-2013 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package com.redhat.et.libguestfs;
+
+/**
+ * Event callback interface.
+ * <p>
+ * This is the interface for event callbacks. See the
+ * {@link GuestFS#set_event_callback set_event_callback method}
+ * for details.
+ *
+ * @author rjones
+ * @see GuestFS
+ */
+public interface EventCallback {
+ public void event (long event, int eh, String buffer, long[] array);
+}
diff --git a/java/examples/guestfs-java.pod b/java/examples/guestfs-java.pod
index 6e032b4..c777e05 100644
--- a/java/examples/guestfs-java.pod
+++ b/java/examples/guestfs-java.pod
@@ -40,6 +40,36 @@ is the error message (a C<String>).
Calling any method on a closed handle raises the same exception.
+=head2 EVENTS
+
+The L<libguestfs event API|guestfs(3)/EVENTS> is fully supported from
+Java. Create a class which implements the C<EventCallback> interface,
+create an instance of this class, and then call the C<GuestFS#set_event_callback>
+method to register this instance. The C<event> method of the class is
+called when libguestfs generates an event.
+
+For example, this will print all trace events:
+
+ GuestFS g = new GuestFS ();
+ g.set_trace (true);
+ g.set_event_callback (
+ new EventCallback () {
+ public void event (long event, int eh,
+ String buffer, long[] array) {
+ System.out.println (GuestFS.eventToString (event) +
+ ": " + buffer);
+ }
+ },
+ GuestFS.EVENT_TRACE);
+ g.add_drive_ro ("disk.img");
+ // etc.
+
+The output looks similar to this:
+
+ EVENT_TRACE: add_drive_ro "disk.img"
+ EVENT_TRACE: add_drive_ro = 0
+ // etc.
+
=head1 EXAMPLE 1: CREATE A DISK IMAGE
@EXAMPLE1@
diff --git a/java/t/GuestFS400Events.java b/java/t/GuestFS400Events.java
new file mode 100644
index 0000000..98236d8
--- /dev/null
+++ b/java/t/GuestFS400Events.java
@@ -0,0 +1,95 @@
+/* libguestfs Java bindings
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+import java.io.*;
+import java.util.HashMap;
+import com.redhat.et.libguestfs.*;
+
+public class GuestFS400Events
+{
+ static class PrintEvent implements EventCallback
+ {
+ public void event (long event, int eh, String buffer, long[] array)
+ {
+ String msg = "event=" + GuestFS.eventToString (event) + " " +
+ "eh=" + eh + " ";
+
+ if (buffer != null)
+ msg += "buffer='" + buffer + "' ";
+
+ if (array.length > 0) {
+ msg += "array[" + array.length + "]={";
+ for (int i = 0; i < array.length; ++i)
+ msg += " " + array[i];
+ msg += " }";
+ }
+
+ System.out.println ("java event logged: " + msg);
+ }
+ }
+
+ static class CloseInvoked extends PrintEvent
+ {
+ private int close_invoked = 0;
+
+ public void event (long event, int eh, String buffer, long[] array)
+ {
+ super.event (event, eh, buffer, array);
+ close_invoked++;
+ }
+
+ public int getCloseInvoked ()
+ {
+ return close_invoked;
+ }
+ }
+
+ public static void main (String[] argv)
+ {
+ try {
+ GuestFS g = new GuestFS ();
+
+ // Grab all messages into an event handler that just
+ // prints each event.
+ g.set_event_callback (new PrintEvent (),
+ GuestFS.EVENT_APPLIANCE|GuestFS.EVENT_LIBRARY|
+ GuestFS.EVENT_TRACE);
+
+ // Check that the close event is invoked.
+ CloseInvoked ci = new CloseInvoked ();
+ g.set_event_callback (ci, GuestFS.EVENT_CLOSE);
+
+ // Now make sure we see some messages.
+ g.set_trace (true);
+ g.set_verbose (true);
+
+ // Do some stuff.
+ g.add_drive_ro ("/dev/null");
+ g.set_autosync (true);
+
+ // Close the handle.
+ assert ci.getCloseInvoked() == 0;
+ g.close ();
+ assert ci.getCloseInvoked() == 1;
+ }
+ catch (Exception exn) {
+ System.err.println (exn);
+ System.exit (1);
+ }
+ }
+}
--
1.7.11.7
-------------- next part --------------
From 9586488a34d5d99f7d98b597d4d5aeda61943c1d Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones at redhat.com>
Date: Thu, 10 Jan 2013 06:25:30 +0900
Subject: [PATCH 7/7] podwrapper: Refresh podwrapper man page.
This also adds a rule so you can do:
make podwrapper.1
if you want to read the documentation as a man page.
---
.gitignore | 1 +
Makefile.am | 11 ++++++++++
podwrapper.pl.in | 63 ++++++++++++++++++++++++++++++++++++--------------------
3 files changed, 53 insertions(+), 22 deletions(-)
diff --git a/.gitignore b/.gitignore
index 7f8c892..394e20a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -320,6 +320,7 @@ Makefile.in
/po-docs/po4a.conf
/po-docs/*/*.pod
/po-docs/*/stamp-update-po
+/podwrapper.1
/podwrapper.pl
/po/*.gmo
/python/bindtests.py
diff --git a/Makefile.am b/Makefile.am
index d8b6590..42052c0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -288,11 +288,22 @@ stamp-guestfs-release-notes.pod: guestfs-release-notes.pod
$<
touch $@
+# NB. podwrapper is an internal tool, so the man page mustn't be installed.
+noinst_MANS = podwrapper.1
+podwrapper.1: podwrapper.pl
+ $(PODWRAPPER) \
+ --section 1 \
+ --man $@-t \
+ --license GPLv2+ \
+ $<
+ mv $@-t $@
+
# Make clean.
CLEANFILES = \
html/*.html \
pod2htm?.tmp \
+ podwrapper.1 \
qemu-wrapper.sh \
stamp-guestfs-release-notes.pod
diff --git a/podwrapper.pl.in b/podwrapper.pl.in
index 46c71f2..3998782 100755
--- a/podwrapper.pl.in
+++ b/podwrapper.pl.in
@@ -32,27 +32,37 @@ use File::Basename;
=head1 NAME
-podwrapper.pl - Generate various output formats from POD input files
+podwrapper.pl - Generate libguestfs documentation from POD input files
=head1 SYNOPSIS
+ man_MANS = virt-foo.1
+
virt-foo.1 $(top_builddir)/html/virt-foo.1.html: stamp-virt-foo.pod
+
stamp-virt-foo.pod: virt-foo.pod
- $(PODWRAPPER) --man virt-foo.1 --html virt-foo.1.html $<
- touch $@
+ $(PODWRAPPER) \
+ --section 1 \
+ --man virt-foo.1 \
+ --html $(top_builddir)/html/virt-foo.1.html \
+ --license GPLv2+ \
+ $<
+ touch $@
+
+ CLEANFILES += stamp-virt-foo.pod
=head1 DESCRIPTION
-podwrapper is a Perl script that generates various output formats
+podwrapper.pl is a Perl script that generates various output formats
from POD input files that libguestfs uses for most documentation.
-You should specify an input file, and one or more output formats.
-For example:
+You must specify one input file, and one or more output formats. The
+output options are I<--man>, I<--html> and I<--text> (see below).
- podwrapper.pl virt-foo.pod --man virt-foo.1
+In C<Makefile.am> files, use a variation of the boilerplate shown in
+the L</SYNOPSIS> section above.
-will turn C<virt-foo.pod> into a man page C<virt-foo.1>. The output
-options are I<--man>, I<--html> and I<--text> (see below).
+For information about the POD format, see L<perlpod(1)>.
=head1 OPTIONS
@@ -70,7 +80,7 @@ Display brief help.
my $html;
-=item B<--html=output.html>
+=item B<--html output.html>
Write a web page to C<output.html>. If this option is not
given, then no web page output is produced.
@@ -79,7 +89,7 @@ given, then no web page output is produced.
my @inserts;
-=item B<--insert=filename:__PATTERN__>
+=item B<--insert filename:__PATTERN__>
In the input file, replace the literal text C<__PATTERN__> with the
replacement file C<filename>. You can give this option multiple
@@ -95,7 +105,11 @@ patterns, in fact you can use any string as the pattern.
my @licenses;
-=item B<--license=GPLv2+|LGPLv2+|examples>
+=item B<--license GPLv2+>
+
+=item B<--license LGPLv2+>
+
+=item B<--license examples>
Add the given license to the end of the man page. This parameter
is required. The parameter may be given multiple times (eg. for
@@ -105,16 +119,16 @@ mixed content).
my $man;
-=item B<--man=output.n>
+=item B<--man output.n>
-Write a man page to C<output.n>. If this option is not
-given, then no man page output is produced.
+Write a man page to C<output.n> (C<n> is the manual section number).
+If this option is not given, then no man page output is produced.
=cut
my $name;
-=item B<--name=name>
+=item B<--name name>
Set the name of the man page. If not set, defaults to the basename
of the input file.
@@ -123,7 +137,7 @@ of the input file.
my $section;
-=item B<--section=N>
+=item B<--section N>
Set the section of the man page (a number such as C<1> for
command line utilities or C<3> for C API documentation). If
@@ -143,7 +157,7 @@ subdirectory.
my $text;
-=item B<--text=output.txt>
+=item B<--text output.txt>
Write a text file to C<output.txt>. If this option is not
given, then no text output is produced.
@@ -152,7 +166,7 @@ given, then no text output is produced.
my @verbatims;
-=item B<--verbatim=filename:@PATTERN@>
+=item B<--verbatim filename:__PATTERN__>
In the input file, replace the literal text C<__PATTERN__> with the
replacement file C<filename>. You can give this option multiple
@@ -529,11 +543,16 @@ sub read_verbatim_file
$r;
}
+=head1 SEE ALSO
+
+L<perlpod(1)>,
+L<Pod::Simple(3pm)>,
+libguestfs.git/README.
+
=head1 AUTHOR
Richard W.M. Jones.
-=head1 SEE ALSO
+=head1 COPYRIGHT
-libguestfs.git/README,
-L<Pod::Simple>
+Copyright (C) 2012-2013 Red Hat Inc.
--
1.7.11.7
More information about the Libguestfs
mailing list