METAMODEL-241: Fixed 102/head
authorkaspersorensen <i.am.kasper.sorensen@gmail.com>
Mon, 16 May 2016 04:47:27 +0000 (21:47 -0700)
committerkaspersorensen <i.am.kasper.sorensen@gmail.com>
Mon, 16 May 2016 04:47:27 +0000 (21:47 -0700)
This fix is implemented by further diving deep into the depths of
OpenJDK. I'm not really fond of going down that route, but it seems to
be the way to go if we really want to keep deserialization support.

CHANGES.md
core/src/main/java/org/apache/metamodel/util/LegacyDeserializationObjectInputStream.java

index 66d1917..d4d0110 100644 (file)
@@ -8,6 +8,7 @@
  * [METAMODEL-159] - DataContextFactory misses methods to create HBase and POJO data contexts.
  * [METAMODEL-252] - Fixed a bug that caused JDBC updates to unnecessarily refresh schema objects.
  * [METAMODEL-1082] - Improved performance of batch ElasticSearch operations by using bulk API.
+ * [METAMODEL-241] - Fixed deserialization of legacy enum types on OpenJDK after rev. 7c1d34773aa6.
 
 ### Apache MetaModel 4.5.2
 
index c4d4570..95fad92 100644 (file)
@@ -22,6 +22,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.ObjectInputStream;
 import java.io.ObjectStreamClass;
+import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.util.Comparator;
 
@@ -252,6 +253,31 @@ public class LegacyDeserializationObjectInputStream extends ObjectInputStream {
      */
     private boolean isEnumExpected(ObjectStreamClass objectStreamClass) {
         try {
+            final Field initializedField = ObjectStreamClass.class.getDeclaredField("initialized");
+            initializedField.setAccessible(true);
+            final Boolean initialized = (Boolean) initializedField.get(objectStreamClass);
+            if (!initialized) {
+                /*
+                 * Snippet from the JDK source:
+                 * 
+                 * void initNonProxy(ObjectStreamClass model,
+                 * Class<?> cl,
+                 * ClassNotFoundException resolveEx,
+                 * ObjectStreamClass superDesc)
+                 **/
+                final Method initMethod = ObjectStreamClass.class.getDeclaredMethod("initNonProxy", ObjectStreamClass.class,
+                        Class.class, ClassNotFoundException.class, ObjectStreamClass.class);
+                initMethod.setAccessible(true);
+                initMethod.invoke(objectStreamClass, objectStreamClass, null, null, null);
+            }
+        } catch (NoSuchFieldError e) {
+            logger.debug("Failed to access boolean field 'initialized' in {}", objectStreamClass.getName(), e);
+        } catch (Exception e) {
+            logger.debug("Failed to access invoke ObjectStreamClass.initialize() to prepare {}", objectStreamClass
+                    .getName(), e);
+        }
+        
+        try {
             final Method isEnumMethod = ObjectStreamClass.class.getDeclaredMethod("isEnum");
             isEnumMethod.setAccessible(true);
             final Boolean result = (Boolean) isEnumMethod.invoke(objectStreamClass);