You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by go...@apache.org on 2017/11/15 18:57:37 UTC

[geode] 02/02: Whitelist: Work with older versions of Java 8

This is an automated email from the ASF dual-hosted git repository.

gosullivan pushed a commit to branch whitelist_wip
in repository https://gitbox.apache.org/repos/asf/geode.git

commit 731ac2b4206615fb6bdaa54db371c7f8b7956fd4
Author: Galen O'Sullivan <go...@pivotal.io>
AuthorDate: Wed Nov 15 10:55:23 2017 -0800

    Whitelist: Work with older versions of Java 8
    
    and achieve this by moving references to ObjectInputFilter out of
    InternalDataSerializer.
    
    Signed-off-by: Dan Smith <ds...@pivotal.io>
---
 .../geode/internal/EmptyInputStreamFilter.java     |  24 +++
 .../apache/geode/internal/InputStreamFilter.java   |  21 +++
 .../geode/internal/InternalDataSerializer.java     | 176 ++++++++-------------
 .../internal/ObjectInputStreamFilterWrapper.java   |  92 +++++++++++
 ...alDataSerializerSerializationWhitelistTest.java |  12 ++
 5 files changed, 211 insertions(+), 114 deletions(-)

diff --git a/geode-core/src/main/java/org/apache/geode/internal/EmptyInputStreamFilter.java b/geode-core/src/main/java/org/apache/geode/internal/EmptyInputStreamFilter.java
new file mode 100644
index 0000000..82369a0
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/EmptyInputStreamFilter.java
@@ -0,0 +1,24 @@
+/*
+ * 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.geode.internal;
+
+import java.io.ObjectInputStream;
+
+public class EmptyInputStreamFilter implements InputStreamFilter {
+  @Override
+  public void setFilterOn(ObjectInputStream ois) {
+    // Do nothing, this is the case where we don't filter.
+  }
+}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/InputStreamFilter.java b/geode-core/src/main/java/org/apache/geode/internal/InputStreamFilter.java
new file mode 100644
index 0000000..19d4102
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/InputStreamFilter.java
@@ -0,0 +1,21 @@
+/*
+ * 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.geode.internal;
+
+import java.io.ObjectInputStream;
+
+public interface InputStreamFilter {
+  void setFilterOn(ObjectInputStream ois);
+}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/InternalDataSerializer.java b/geode-core/src/main/java/org/apache/geode/internal/InternalDataSerializer.java
index 71a802a..969ece4 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/InternalDataSerializer.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/InternalDataSerializer.java
@@ -14,7 +14,60 @@
  */
 package org.apache.geode.internal;
 
+import java.io.BufferedReader;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.EOFException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.NotSerializableException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.io.UTFDataFormatException;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.URL;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Stack;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.UUID;
+import java.util.Vector;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
+
 import org.apache.commons.lang.StringUtils;
+import org.apache.logging.log4j.Logger;
+
 import org.apache.geode.CancelException;
 import org.apache.geode.CanonicalInstantiator;
 import org.apache.geode.DataSerializable;
@@ -24,7 +77,6 @@ import org.apache.geode.GemFireIOException;
 import org.apache.geode.GemFireRethrowable;
 import org.apache.geode.Instantiator;
 import org.apache.geode.InternalGemFireError;
-import org.apache.geode.InternalGemFireException;
 import org.apache.geode.SerializationException;
 import org.apache.geode.SystemFailure;
 import org.apache.geode.ToDataException;
@@ -70,59 +122,6 @@ import org.apache.geode.pdx.internal.PdxReaderImpl;
 import org.apache.geode.pdx.internal.PdxType;
 import org.apache.geode.pdx.internal.PdxWriterImpl;
 import org.apache.geode.pdx.internal.TypeRegistry;
-import org.apache.logging.log4j.Logger;
-import sun.misc.ObjectInputFilter;
-
-import java.io.BufferedReader;
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.EOFException;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.NotSerializableException;
-import java.io.ObjectInput;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutput;
-import java.io.ObjectOutputStream;
-import java.io.ObjectStreamClass;
-import java.io.OutputStream;
-import java.io.Serializable;
-import java.io.UTFDataFormatException;
-import java.lang.ref.WeakReference;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Proxy;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.net.InetAddress;
-import java.net.URL;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Properties;
-import java.util.Set;
-import java.util.Stack;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.UUID;
-import java.util.Vector;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.TimeUnit;
 
 /**
  * Contains static methods for data serializing instances of internal GemFire classes. It also
@@ -151,13 +150,12 @@ public abstract class InternalDataSerializer extends DataSerializer implements D
           + ";";
 
 
-  private static ObjectInputFilter defaultSerializationFilter =
-      ObjectInputFilter.Config.createFilter("**");
+  private static InputStreamFilter defaultSerializationFilter = new EmptyInputStreamFilter();
 
   /**
    * A deserialization filter for ObjectInputStreams
    */
-  private static ObjectInputFilter serializationFilter = defaultSerializationFilter;
+  private static InputStreamFilter serializationFilter = defaultSerializationFilter;
 
   private static final String serializationVersionTxt =
       System.getProperty(DistributionConfig.GEMFIRE_PREFIX + "serializationVersion");
@@ -226,8 +224,9 @@ public abstract class InternalDataSerializer extends DataSerializer implements D
         throw new GemFireConfigException(
             "A serialization filter has been specified but this version of Java does not support serialization filters - sun.misc.ObjectInputFilter is not available");
       }
-      createSerializationFilter(SANCTIONED_SERIALIZABLES_DEPENDENCIES_PATTERN
-          + distributionConfig.getSerializableObjectFilter() + ";!*", services);
+      serializationFilter =
+          new ObjectInputStreamFilterWrapper(SANCTIONED_SERIALIZABLES_DEPENDENCIES_PATTERN
+              + distributionConfig.getSerializableObjectFilter() + ";!*", services);
     } else {
       clearSerializationFilter();
     }
@@ -237,59 +236,11 @@ public abstract class InternalDataSerializer extends DataSerializer implements D
     serializationFilter = defaultSerializationFilter;
   }
 
-  private static void createSerializationFilter(String serializationFilterSpec,
-      Collection<DistributedSystemService> services) {
-
-    Set<String> sanctionedClasses = new HashSet<>(500);
-    for (DistributedSystemService service : services) {
-      try {
-        sanctionedClasses.addAll(service.getSerializationWhitelist());
-      } catch (IOException e) {
-        e.printStackTrace();
-      }
-    }
-    try {
-      URL sanctionedSerializables = ClassPathLoader.getLatest()
-          .getResource(InternalDataSerializer.class, "sanctionedSerializables.txt");
-      Collection<String> coreClassNames = loadClassNames(sanctionedSerializables);
-      sanctionedClasses.addAll(coreClassNames);
-    } catch (IOException e) {
-      throw new InternalGemFireException(
-          "unable to read sanctionedSerializables.txt to form a serialization white-list", e);
-    }
-
-    logger.debug("setting a serialization filter containing {}", serializationFilterSpec);
-
-    final ObjectInputFilter userFilter =
-        ObjectInputFilter.Config.createFilter(serializationFilterSpec);
-    serializationFilter = filterInfo -> {
-      if (filterInfo.serialClass() == null) {
-        return userFilter.checkInput(filterInfo);
-      }
-
-      String className = filterInfo.serialClass().getName();
-      if (filterInfo.serialClass().isArray()) {
-        className = filterInfo.serialClass().getComponentType().getName();
-      }
-      if (sanctionedClasses.contains(className)) {
-        return ObjectInputFilter.Status.ALLOWED;
-        // return ObjectInputFilter.Status.UNDECIDED;
-      } else {
-        ObjectInputFilter.Status status = userFilter.checkInput(filterInfo);
-        if (status == ObjectInputFilter.Status.REJECTED) {
-          logger.warn("Serialization filter is rejecting class {}", className);
-        }
-        return status;
-      }
-    };
-
-    // global filter - if we enable this it will affect all ObjectInputStreams
-    // ObjectInputFilter.Config.setSerialFilter(serializationFilter);
-  }
 
   /**
-   * Loads the class names from sanctionedSerializables.txt, a file that is also maintained for
-   * backward-compatibility testing with AnalyzeSerializablesJUnitTest
+   * {@link DistributedSystemService}s that need to whitelist Serializable objects can use this to
+   * read them from a file and then return them via
+   * {@link DistributedSystemService#getSerializationWhitelist}
    */
   public static Collection<String> loadClassNames(URL sanctionedSerializables) throws IOException {
     Collection<String> result = new ArrayList(1000);
@@ -2966,10 +2917,7 @@ public abstract class InternalDataSerializer extends DataSerializer implements D
           }
 
           ObjectInput ois = new DSObjectInputStream(stream);
-          if (serializationFilter != null) {
-            ObjectInputFilter.Config.setObjectInputFilter((ObjectInputStream) ois,
-                serializationFilter);
-          }
+          serializationFilter.setFilterOn((ObjectInputStream) ois);
           if (stream instanceof VersionedDataStream) {
             Version v = ((VersionedDataStream) stream).getVersion();
             if (v != null && v != Version.CURRENT) {
diff --git a/geode-core/src/main/java/org/apache/geode/internal/ObjectInputStreamFilterWrapper.java b/geode-core/src/main/java/org/apache/geode/internal/ObjectInputStreamFilterWrapper.java
new file mode 100644
index 0000000..841d052
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/ObjectInputStreamFilterWrapper.java
@@ -0,0 +1,92 @@
+/*
+ * 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.geode.internal;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.logging.log4j.Logger;
+
+import org.apache.geode.InternalGemFireException;
+import org.apache.geode.distributed.internal.DistributedSystemService;
+import org.apache.geode.internal.logging.LogService;
+
+import sun.misc.ObjectInputFilter;
+
+
+public class ObjectInputStreamFilterWrapper implements InputStreamFilter {
+  private static final Logger logger = LogService.getLogger();
+  private final ObjectInputFilter serializationFilter;
+
+  public ObjectInputStreamFilterWrapper(String serializationFilterSpec,
+      Collection<DistributedSystemService> services) {
+
+    Set<String> sanctionedClasses = new HashSet<>(500);
+    for (DistributedSystemService service : services) {
+      try {
+        sanctionedClasses.addAll(service.getSerializationWhitelist());
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
+    }
+    try {
+      URL sanctionedSerializables = ClassPathLoader.getLatest()
+          .getResource(InternalDataSerializer.class, "sanctionedSerializables.txt");
+      Collection<String> coreClassNames =
+          InternalDataSerializer.loadClassNames(sanctionedSerializables);
+      sanctionedClasses.addAll(coreClassNames);
+    } catch (IOException e) {
+      throw new InternalGemFireException(
+          "unable to read sanctionedSerializables.txt to form a serialization white-list", e);
+    }
+
+    logger.debug("setting a serialization filter containing {}", serializationFilterSpec);
+
+    final ObjectInputFilter userFilter =
+        ObjectInputFilter.Config.createFilter(serializationFilterSpec);
+    serializationFilter = filterInfo -> {
+      if (filterInfo.serialClass() == null) {
+        return userFilter.checkInput(filterInfo);
+      }
+
+      String className = filterInfo.serialClass().getName();
+      if (filterInfo.serialClass().isArray()) {
+        className = filterInfo.serialClass().getComponentType().getName();
+      }
+      if (sanctionedClasses.contains(className)) {
+        return ObjectInputFilter.Status.ALLOWED;
+        // return ObjectInputFilter.Status.UNDECIDED;
+      } else {
+        ObjectInputFilter.Status status = userFilter.checkInput(filterInfo);
+        if (status == ObjectInputFilter.Status.REJECTED) {
+          logger.warn("Serialization filter is rejecting class {}", className);
+        }
+        return status;
+      }
+    };
+
+    // global filter - if we enable this it will affect all ObjectInputStreams
+    // ObjectInputFilter.Config.setSerialFilter(serializationFilter);
+  }
+
+  @Override
+  public void setFilterOn(ObjectInputStream objectInputStream) {
+    ObjectInputFilter.Config.setObjectInputFilter(objectInputStream, serializationFilter);
+  }
+}
diff --git a/geode-core/src/test/java/org/apache/geode/internal/InternalDataSerializerSerializationWhitelistTest.java b/geode-core/src/test/java/org/apache/geode/internal/InternalDataSerializerSerializationWhitelistTest.java
index 1064e2f..73690d9 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/InternalDataSerializerSerializationWhitelistTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/InternalDataSerializerSerializationWhitelistTest.java
@@ -12,6 +12,7 @@ import java.util.ArrayList;
 import java.util.Properties;
 
 import org.junit.AfterClass;
+import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
@@ -43,11 +44,22 @@ public class InternalDataSerializerSerializationWhitelistTest {
 
   @Before
   public void setUp() {
+    Assume.assumeTrue("ObjectInputFilter is present in this JVM (post- 8.111)",
+        hasObjectInputFilter());
     outputStream = new HeapDataOutputStream(Version.CURRENT);
     testSerializable = new TestSerializable();
     properties = new Properties();
   }
 
+  private boolean hasObjectInputFilter() {
+    try {
+      Class.forName("sun.misc.ObjectInputFilter");
+      return true;
+    } catch (ClassNotFoundException e) {
+      return false;
+    }
+  }
+
   @AfterClass
   public static void clearDataSerializerFilter() {
     InternalDataSerializer.initialize(new DistributionConfigImpl(new Properties()),

-- 
To stop receiving notification emails like this one, please contact
"commits@geode.apache.org" <co...@geode.apache.org>.