You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by at...@apache.org on 2016/01/02 23:20:53 UTC

commons-scxml git commit: SCXML-247: dedicated SCInstanceObjectInputStream to support proper dynamic class resolution in GroovyContext - see https://issues.apache.org/jira/browse/SCXML-247 for details - GroovyContext now can use the 'root' (SCInstance)Ob

Repository: commons-scxml
Updated Branches:
  refs/heads/master 29402ee97 -> 5faba6798


SCXML-247: dedicated SCInstanceObjectInputStream to support proper dynamic class resolution in GroovyContext
- see https://issues.apache.org/jira/browse/SCXML-247 for details
- GroovyContext now can use the 'root' (SCInstance)ObjectInputStream for dynamic Groovy class resolving
- tested through SerializableInitialBaseScriptTest (unmodified, but again validates new implementation works too)


Project: http://git-wip-us.apache.org/repos/asf/commons-scxml/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-scxml/commit/5faba679
Tree: http://git-wip-us.apache.org/repos/asf/commons-scxml/tree/5faba679
Diff: http://git-wip-us.apache.org/repos/asf/commons-scxml/diff/5faba679

Branch: refs/heads/master
Commit: 5faba67982689543f69fd316c38f16b7ce39225b
Parents: 29402ee
Author: Ate Douma <at...@apache.org>
Authored: Sat Jan 2 23:20:46 2016 +0100
Committer: Ate Douma <at...@apache.org>
Committed: Sat Jan 2 23:20:46 2016 +0100

----------------------------------------------------------------------
 .../scxml2/SCInstanceObjectInputStream.java     | 96 ++++++++++++++++++++
 .../scxml2/env/groovy/GroovyContext.java        | 28 +++---
 .../apache/commons/scxml2/SCXMLTestHelper.java  |  2 +-
 3 files changed, 109 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/5faba679/src/main/java/org/apache/commons/scxml2/SCInstanceObjectInputStream.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/SCInstanceObjectInputStream.java b/src/main/java/org/apache/commons/scxml2/SCInstanceObjectInputStream.java
new file mode 100644
index 0000000..3c0659c
--- /dev/null
+++ b/src/main/java/org/apache/commons/scxml2/SCInstanceObjectInputStream.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.scxml2;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
+
+/**
+ * Extended ObjectInputStream to be used for de-serializing SCInstance.
+ * <p>
+ * This class allows configuring a custom {@link ClassResolver} callback to dynamically resolve a deserialization class,
+ * which is needed for SCXML languages like Groovy which need to dynamically lookup custom Groovy classes.
+ * </p>
+ */
+public class SCInstanceObjectInputStream extends ObjectInputStream {
+
+    /** ClassResolver Callback interface */
+    public interface ClassResolver {
+
+        /**
+         * Callback method invoked from {@link SCInstanceObjectInputStream#resolveClass(ObjectStreamClass)}
+         * @param osc an instance of class ObjectStreamClass
+         * @return a Class object corresponding to osc
+         * @throws IOException
+         * @throws ClassNotFoundException
+         */
+        Class resolveClass(ObjectStreamClass osc) throws IOException, ClassNotFoundException;
+    }
+
+    /**
+     * current classresolver callback
+     */
+    private ClassResolver classResolver;
+
+    /**
+     * Default constructor
+     * @param in Inputstream to use
+     * @throws IOException
+     */
+    public SCInstanceObjectInputStream(final InputStream in) throws IOException {
+        super(in);
+    }
+
+    /**
+     * Set custom class resolver callback, or null when no longer needed.
+     * <p>
+     * Typically usage:
+     * <pre><code>
+     * private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException {
+     *     ClassResolver currentClassResolver = null;
+     *     try {
+     *         if (in instanceof SCInstanceObjectInputStream) {
+     *             currentClassResolver = ((SCInstanceObjectInputStream)in).setClassResolver(customClassResolver);
+     *         }
+     *         ... // read Object(s)
+     *     }
+     *     finally {
+     *         if (in instanceof SCInstanceObjectInputStream) {
+     *             ((SCInstanceObjectInputStream)in).setClassResolver(currentClassResolver);
+     *         }
+     *     }
+     * }
+     * </code></pre>
+     * </p>
+     * @see org.apache.commons.scxml2.env.groovy.GroovyContext#readObject(ObjectInputStream)
+     * @param classResolver custom class resolver
+     */
+    public ClassResolver setClassResolver(ClassResolver classResolver) {
+        ClassResolver old = this.classResolver;
+        this.classResolver = classResolver;
+        return old;
+    }
+
+    protected Class resolveClass(ObjectStreamClass osc) throws IOException, ClassNotFoundException {
+        if (classResolver != null) {
+            return classResolver.resolveClass(osc);
+        }
+        return super.resolveClass(osc);
+    }
+}

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/5faba679/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyContext.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyContext.java b/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyContext.java
index 9799216..d2526f6 100644
--- a/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyContext.java
+++ b/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyContext.java
@@ -18,18 +18,16 @@ package org.apache.commons.scxml2.env.groovy;
 
 import groovy.lang.Closure;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
-import java.io.ObjectStreamClass;
 import java.util.Iterator;
 import java.util.Map;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.commons.scxml2.Context;
+import org.apache.commons.scxml2.SCInstanceObjectInputStream;
 import org.apache.commons.scxml2.env.SimpleContext;
 
 /**
@@ -133,9 +131,7 @@ public class GroovyContext extends SimpleContext {
         out.writeObject(this.scriptBaseClass);
         out.writeObject(this.evaluator);
         out.writeObject(this.binding);
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        new ObjectOutputStream(bout).writeObject(this.vars);
-        out.writeObject(bout.toByteArray());
+        out.writeObject(this.vars);
     }
 
     @SuppressWarnings("unchecked")
@@ -143,17 +139,17 @@ public class GroovyContext extends SimpleContext {
         this.scriptBaseClass = (String)in.readObject();
         this.evaluator = (GroovyEvaluator)in.readObject();
         this.binding = (GroovyContextBinding)in.readObject();
-        byte[] bytes  = (byte[])in.readObject();
-        if (evaluator != null) {
-            this.vars = (Map<String, Object>)
-                    new ObjectInputStream(new ByteArrayInputStream(bytes)) {
-                        protected Class resolveClass(ObjectStreamClass osc) throws IOException, ClassNotFoundException {
-                            return Class.forName(osc.getName(), true, evaluator.getGroovyClassLoader());
-                        }
-                    }.readObject();
+        SCInstanceObjectInputStream.ClassResolver currentResolver = null;
+        try {
+            if (evaluator != null && in instanceof SCInstanceObjectInputStream) {
+                currentResolver = ((SCInstanceObjectInputStream)in).setClassResolver(osc -> Class.forName(osc.getName(), true, evaluator.getGroovyClassLoader()));
+            }
+            this.vars = (Map<String, Object>)in.readObject();
         }
-        else {
-            this.vars = (Map<String, Object>)new ObjectInputStream(new ByteArrayInputStream(bytes)).readObject();
+        finally {
+            if (in instanceof SCInstanceObjectInputStream) {
+                ((SCInstanceObjectInputStream)in).setClassResolver(currentResolver);
+            }
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/5faba679/src/test/java/org/apache/commons/scxml2/SCXMLTestHelper.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/SCXMLTestHelper.java b/src/test/java/org/apache/commons/scxml2/SCXMLTestHelper.java
index 3330cce..983bc7c 100644
--- a/src/test/java/org/apache/commons/scxml2/SCXMLTestHelper.java
+++ b/src/test/java/org/apache/commons/scxml2/SCXMLTestHelper.java
@@ -254,7 +254,7 @@ public class SCXMLTestHelper {
         out.writeObject(exec.detachInstance());
         out.close();
         ObjectInputStream in =
-            new ObjectInputStream(new FileInputStream(filename));
+            new SCInstanceObjectInputStream(new FileInputStream(filename));
         exec.attachInstance((SCInstance) in.readObject());
         in.close();
         return exec;