
At Wed, 01 Aug 2012 16:57:33 -0600, Eric Blake wrote:
On 08/01/2012 08:11 AM, Claudio Bley wrote:
At Mon, 23 Jul 2012 14:56:55 -0600,
the old version crashed, and your version leaves code as null (which is a strict improvement, but might cause its own NullPointer issue later on). Having an else branch that sticks in a placeholder would be nicer to end clients to at least recognize that they are talking to a newer server, without crashing.
Please have look at the following patch.
-- >8 -- Subject: [PATCH] Fix IndexOutOfBoundsException for unknown error number/domain/level codes.
Remove default constructor because it does not init the object properly.
Add a special *_UNKNOWN enum value to each enum which is used when the given enum code is out of bounds.
+ /** + * Map an integer to an enum value. + * + * @return when {@code n < values.length} return n-th item of + * {@code values}, otherwise the last item of array + * {@code values}. + */ + private static final <T extends Enum<T>> T wrapToEnum(final int n, final T[] values) {
Wow, Java has changed since I last programmed in it (I haven't programmed Java since 1.4 when 'assert' was added, although I was at least following the development of Java 1.5 at the time enough to understand this syntax - I guess that would be 8 or so years ago?).
Indeed, they try to shoehorn every kind of feature into the language, nowadays. ;) But, as I'm looking at the code now, I notice that it is unnecessarily complex (originally I was trying to make it more succinct, but Java wouldn't let me). I simplified the code, renaming the method / fixing the documentation and made v3 of the patch.
@@ -71,7 +90,13 @@ public class Error implements Serializable { /** * An error */ - VIR_ERR_ERROR + VIR_ERR_ERROR, + + VIR_ERR_UNKNOWN; /* must be the last entry! */
Is this...
+ + protected static final ErrorLevel wrap(int value) { + return wrapToEnum(value, values()); + } }
public static enum ErrorNumber { @@ -161,6 +186,11 @@ public class Error implements Serializable { VIR_ERR_MIGRATE_UNSAFE, /* Migration is not safe */ VIR_ERR_OVERFLOW, /* integer overflow */ VIR_ERR_BLOCK_COPY_ACTIVE, /* action prevented by block copy job */ + VIR_ERR_UNKNOWN; /* unknown error (must be the last entry!) */
...and this common use of a name among two different enums going to bite us?
No, not at all. Enums are type-safe in Java and enums have their own namespace; one always has to specify the enum name when referring to an enum constant. (except in case statements where the compiler can infer the type of the enum constant) Rather, I would /very/ much like these superfluous prefixes of all enum constants to be removed from the libvirt-java interface. They're of no use really, despite adding to the code bloat.
When using 'git send-email', it helps to use '--subject-prefix="libvirt-java PATCHv2" ' for the repost to make it obvious that it is a revision of an earlier post.
OK, thanks for the tip. -- >8 -- Subject: [libvirt-java PATCHv3] Fix IndexOutOfBoundsException for unknown error number/domain/level codes. Remove default constructor because it does not init the object properly. Add a special *_UNKNOWN enum value to each enum which is used when the given enum code is out of bounds. --- src/main/java/org/libvirt/Error.java | 43 +++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/libvirt/Error.java b/src/main/java/org/libvirt/Error.java index f185ce0..e3c3246 100644 --- a/src/main/java/org/libvirt/Error.java +++ b/src/main/java/org/libvirt/Error.java @@ -12,6 +12,21 @@ import org.libvirt.jna.virError; */ public class Error implements Serializable { + /** + * Returns the element of the given array at the specified index, + * or the last element of the array if the index is not less than + * {@code values.length}. + * + * @return n-th item of {@code values} when {@code n < + * values.length}, otherwise the last item of {@code values}. + */ + private static final <T> T safeElementAt(final int n, final T[] values) { + assert(n >= 0 && values.length > 0); + + int idx = Math.min(n, values.length - 1); + return values[idx]; + } + public static enum ErrorDomain { VIR_FROM_NONE, VIR_FROM_XEN, /* Error at Xen hypervisor layer */ VIR_FROM_XEND, /* Error at connection with xend daemon */ @@ -60,6 +75,11 @@ public class Error implements Serializable { VIR_FROM_URI, /* Error from URI handling */ VIR_FROM_AUTH, /* Error from auth handling */ VIR_FROM_DBUS, /* Error from DBus */ + VIR_FROM_UNKNOWN; /* unknown error domain (must be the last entry!) */ + + protected static final ErrorDomain wrap(int value) { + return safeElementAt(value, values()); + } } public static enum ErrorLevel { @@ -71,7 +91,13 @@ public class Error implements Serializable { /** * An error */ - VIR_ERR_ERROR + VIR_ERR_ERROR, + + VIR_ERR_UNKNOWN; /* must be the last entry! */ + + protected static final ErrorLevel wrap(int value) { + return safeElementAt(value, values()); + } } public static enum ErrorNumber { @@ -161,6 +187,11 @@ public class Error implements Serializable { VIR_ERR_MIGRATE_UNSAFE, /* Migration is not safe */ VIR_ERR_OVERFLOW, /* integer overflow */ VIR_ERR_BLOCK_COPY_ACTIVE, /* action prevented by block copy job */ + VIR_ERR_UNKNOWN; /* unknown error (must be the last entry!) */ + + protected static final ErrorNumber wrap(int value) { + return safeElementAt(value, values()); + } } /** @@ -181,14 +212,10 @@ public class Error implements Serializable { int int2; NetworkPointer VNP; /* Deprecated */ - public Error() { - - } - public Error(virError vError) { - code = ErrorNumber.values()[vError.code]; - domain = ErrorDomain.values()[vError.domain]; - level = ErrorLevel.values()[vError.level]; + code = code.wrap(vError.code); + domain = domain.wrap(vError.domain); + level = level.wrap(vError.level); message = vError.message; str1 = vError.str1; str2 = vError.str2; -- 1.7.11.msysgit.0 -- AV-Test GmbH, Henricistraße 20, 04155 Leipzig, Germany Phone: +49 341 265 310 19 Web:<http://www.av-test.org> Eingetragen am / Registered at: Amtsgericht Stendal (HRB 114076) Geschaeftsfuehrer (CEO): Andreas Marx, Guido Habicht, Maik Morgenstern