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

ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git


The following commit(s) were added to refs/heads/master by this push:
     new 63a3918  Use whitelist for Hessian serialization
     new 1f7e3ad  Merge remote-tracking branch 'parent/pr/414' into asf-master
63a3918 is described below

commit 63a3918153563753d3b8b9febe41748b680e8660
Author: Nikita Timofeev <stari...@gmail.com>
AuthorDate: Tue Feb 11 17:40:24 2020 +0300

    Use whitelist for Hessian serialization
---
 .../remote/hessian/ClientSerializerFactory.java    | 10 ++--
 .../cayenne/rop/HttpClientConnectionProvider.java  |  4 +-
 .../rop/http/HessianROPSerializationServiceIT.java |  3 +-
 .../configuration/rop/server/ROPServerModule.java  | 13 ++++-
 .../cayenne/remote/hessian/HessianConfig.java      | 56 ++++++++++++++++++----
 .../java/org/apache/cayenne/rop/ROPConstants.java  |  5 ++
 .../ServerHessianSerializationServiceProvider.java | 24 +++++++++-
 pom.xml                                            |  2 +-
 8 files changed, 97 insertions(+), 20 deletions(-)

diff --git 
a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java
 
b/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java
index 0f81bc8..02212e8 100644
--- 
a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java
+++ 
b/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java
@@ -19,13 +19,13 @@
 
 package org.apache.cayenne.remote.hessian;
 
+import com.caucho.hessian.io.FieldDeserializer2Factory;
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.util.PersistentObjectList;
 import org.apache.cayenne.util.PersistentObjectMap;
 
 import com.caucho.hessian.io.AbstractSerializerFactory;
 import com.caucho.hessian.io.Deserializer;
-import com.caucho.hessian.io.HessianProtocolException;
 import com.caucho.hessian.io.JavaDeserializer;
 import com.caucho.hessian.io.Serializer;
 
@@ -41,23 +41,23 @@ public class ClientSerializerFactory extends 
AbstractSerializerFactory {
     private Deserializer mapDeserializer;
 
     @Override
-    public Serializer getSerializer(Class cl) throws HessianProtocolException {
+    public Serializer getSerializer(Class cl) {
         return null;
     }
 
     @Override
-    public Deserializer getDeserializer(Class cl) throws 
HessianProtocolException {
+    public Deserializer getDeserializer(Class cl) {
         //turns out Hessian uses its own (incorrect) serialization mechanism 
for maps
         if (PersistentObjectMap.class.isAssignableFrom(cl)) {
             if (mapDeserializer == null) {
-                mapDeserializer = new JavaDeserializer(cl);
+                mapDeserializer = new JavaDeserializer(cl, 
FieldDeserializer2Factory.create());
             }
             return mapDeserializer;
         }
         
         if (PersistentObjectList.class.isAssignableFrom(cl)) {
             if (listDeserializer == null) {
-                listDeserializer = new JavaDeserializer(cl);
+                listDeserializer = new JavaDeserializer(cl, 
FieldDeserializer2Factory.create());
             }
             return listDeserializer;
         }
diff --git 
a/cayenne-client/src/main/java/org/apache/cayenne/rop/HttpClientConnectionProvider.java
 
b/cayenne-client/src/main/java/org/apache/cayenne/rop/HttpClientConnectionProvider.java
index 3093c34..3138c43 100644
--- 
a/cayenne-client/src/main/java/org/apache/cayenne/rop/HttpClientConnectionProvider.java
+++ 
b/cayenne-client/src/main/java/org/apache/cayenne/rop/HttpClientConnectionProvider.java
@@ -33,7 +33,7 @@ public class HttpClientConnectionProvider implements 
Provider<ClientConnection>
     protected RuntimeProperties runtimeProperties;
     
     @Inject
-    protected ROPSerializationService serializationService;
+    protected Provider<ROPSerializationService> serializationServiceProvider;
 
     @Override
     public ClientConnection get() throws DIRuntimeException {
@@ -41,7 +41,7 @@ public class HttpClientConnectionProvider implements 
Provider<ClientConnection>
                 .get(ClientConstants.ROP_SERVICE_SHARED_SESSION_PROPERTY);
 
         HttpROPConnector ropConnector = createHttpRopConnector();
-        ProxyRemoteService remoteService = new 
ProxyRemoteService(serializationService, ropConnector);
+        ProxyRemoteService remoteService = new 
ProxyRemoteService(serializationServiceProvider.get(), ropConnector);
 
         HttpClientConnection clientConnection = new 
HttpClientConnection(remoteService, sharedSession);
         ropConnector.setClientConnection(clientConnection);
diff --git 
a/cayenne-client/src/test/java/org/apache/cayenne/rop/http/HessianROPSerializationServiceIT.java
 
b/cayenne-client/src/test/java/org/apache/cayenne/rop/http/HessianROPSerializationServiceIT.java
index 97d35e7..9f86a1c 100644
--- 
a/cayenne-client/src/test/java/org/apache/cayenne/rop/http/HessianROPSerializationServiceIT.java
+++ 
b/cayenne-client/src/test/java/org/apache/cayenne/rop/http/HessianROPSerializationServiceIT.java
@@ -32,6 +32,7 @@ import org.junit.Test;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.util.Collections;
 
 import static org.junit.Assert.*;
 
@@ -107,7 +108,7 @@ public class HessianROPSerializationServiceIT extends 
ClientCase {
        }
 
        private ROPSerializationService createServerSerializationService() {
-               return new ServerHessianSerializationServiceProvider().get();
+               return new ServerHessianSerializationServiceProvider(() -> 
context.getChannel(), Collections.emptyList()).get();
        }
        
 }
diff --git 
a/cayenne-rop-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPServerModule.java
 
b/cayenne-rop-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPServerModule.java
index 20938d7..896ff89 100644
--- 
a/cayenne-rop-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPServerModule.java
+++ 
b/cayenne-rop-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPServerModule.java
@@ -22,9 +22,11 @@ import java.util.Map;
 
 import org.apache.cayenne.configuration.Constants;
 import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.ListBuilder;
 import org.apache.cayenne.di.MapBuilder;
 import org.apache.cayenne.di.Module;
 import org.apache.cayenne.remote.RemoteService;
+import org.apache.cayenne.rop.ROPConstants;
 import org.apache.cayenne.rop.ROPSerializationService;
 import org.apache.cayenne.rop.ServerHessianSerializationServiceProvider;
 import org.apache.cayenne.rop.ServerHttpRemoteService;
@@ -46,6 +48,14 @@ public class ROPServerModule implements Module {
         return binder.bindMap(String.class, 
Constants.SERVER_ROP_EVENT_BRIDGE_PROPERTIES_MAP);
     }
 
+    /**
+     * @since 4.2
+     */
+    public static ListBuilder<String> contributeSerializationWhitelist(Binder 
binder) {
+        return binder.bindList(String.class, 
ROPConstants.SERIALIZATION_WHITELIST);
+    }
+
+
     public ROPServerModule() {}
 
     /**
@@ -60,8 +70,9 @@ public class ROPServerModule implements Module {
     }
 
     public void configure(Binder binder) {
+        contributeSerializationWhitelist(binder);
+        MapBuilder<String> mapBuilder = contributeROPBridgeProperties(binder);
         if(eventBridgeProperties != null) {
-            MapBuilder<String> mapBuilder = 
contributeROPBridgeProperties(binder);
             mapBuilder.putAll(eventBridgeProperties);
         }
         binder.bind(RemoteService.class).to(ServerHttpRemoteService.class);
diff --git 
a/cayenne-rop-server/src/main/java/org/apache/cayenne/remote/hessian/HessianConfig.java
 
b/cayenne-rop-server/src/main/java/org/apache/cayenne/remote/hessian/HessianConfig.java
index 8c4a9c2..615474d 100644
--- 
a/cayenne-rop-server/src/main/java/org/apache/cayenne/remote/hessian/HessianConfig.java
+++ 
b/cayenne-rop-server/src/main/java/org/apache/cayenne/remote/hessian/HessianConfig.java
@@ -21,8 +21,13 @@ package org.apache.cayenne.remote.hessian;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
 
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.EntityResolver;
 import org.apache.cayenne.util.Util;
 
@@ -47,21 +52,57 @@ public class HessianConfig {
      *            and have a default constructor.
      * @param resolver if not null, EntityResolver will be injected into all 
factories
      *            that implement <em>setEntityResolver(EntityResolver)</em> 
method.
+     * @see #createFactory(String[], EntityResolver, Collection)
      */
     public static SerializerFactory createFactory(
             String[] factoryNames,
             EntityResolver resolver) {
+        return createFactory(factoryNames, resolver, Collections.emptyList());
+    }
+
+    /**
+     * Creates a Hessian SerializerFactory configured with zero or more
+     * AbstractSerializerFactory extensions. Extensions are specified as class 
names. This
+     * method can inject EntityResolver if an extension factory class defines
+     * <em>setEntityResolver(EntityResolver)</em> method.
+     *
+     * @param factoryNames an array of factory class names. Each class must be 
a concrete
+     *            subclass of 
<em>com.caucho.hessian.io.AbstractSerializerFactory</em>
+     *            and have a default constructor.
+     * @param resolver if not null, EntityResolver will be injected into all 
factories
+     *            that implement <em>setEntityResolver(EntityResolver)</em> 
method.
+     * @param additionalWhitelist serialization whitelist, examples: 
"java.util.*", "com.foo.io.Bean"
+     * @see #createFactory(String[], EntityResolver)
+     *
+     * @since 4.2
+     */
+    public static SerializerFactory createFactory(
+            String[] factoryNames,
+            EntityResolver resolver,
+            Collection<String> additionalWhitelist) {
 
         SerializerFactory factory = new CayenneSerializerFactory();
 
-        if (factoryNames != null && factoryNames.length > 0) {
+        List<String> whitelist = new ArrayList<>(additionalWhitelist);
+        if(resolver != null) {
+            whitelist.add("org.apache.cayenne.*");
+            for (DataMap dataMap : resolver.getDataMaps()) {
+                whitelist.add(dataMap.getDefaultPackage() + ".*");
+            }
+        }
 
-            for (String factoryName : factoryNames) {
+        if(!whitelist.isEmpty()) {
+            for (String pattern : whitelist) {
+                factory.getClassFactory().allow(pattern);
+            }
+            factory.getClassFactory().setWhitelist(true);
+        }
 
+        if (factoryNames != null && factoryNames.length > 0) {
+            for (String factoryName : factoryNames) {
                 try {
                     factory.addFactory(loadFactory(factoryName, resolver));
-                }
-                catch (Exception e) {
+                } catch (Exception e) {
                     throw new CayenneRuntimeException("Error configuring 
factory class "
                             + factoryName, e);
                 }
@@ -83,16 +124,14 @@ public class HessianConfig {
                     + " is not a AbstractSerializerFactory");
         }
 
-        Constructor c = factoryClass.getDeclaredConstructor();
+        Constructor<?> c = factoryClass.getDeclaredConstructor();
         if (!Util.isAccessible(c)) {
             c.setAccessible(true);
         }
 
         AbstractSerializerFactory object = (AbstractSerializerFactory) 
c.newInstance();
-
         if (resolver != null) {
             try {
-
                 Method setter = factoryClass.getDeclaredMethod(
                         "setEntityResolver",
                         EntityResolver.class);
@@ -102,8 +141,7 @@ public class HessianConfig {
                 }
 
                 setter.invoke(object, resolver);
-            }
-            catch (Exception e) {
+            } catch (Exception ignore) {
                 // ignore injection exception
             }
         }
diff --git 
a/cayenne-rop-server/src/main/java/org/apache/cayenne/rop/ROPConstants.java 
b/cayenne-rop-server/src/main/java/org/apache/cayenne/rop/ROPConstants.java
index b8e234a..7bf9267 100644
--- a/cayenne-rop-server/src/main/java/org/apache/cayenne/rop/ROPConstants.java
+++ b/cayenne-rop-server/src/main/java/org/apache/cayenne/rop/ROPConstants.java
@@ -25,4 +25,9 @@ public class ROPConstants {
 
     public static final String ESTABLISH_SESSION_OPERATION = 
"establish_session";
     public static final String ESTABLISH_SHARED_SESSION_OPERATION = 
"establish_shared_session";
+
+    /**
+     * @since 4.2
+     */
+    public static final String SERIALIZATION_WHITELIST = 
"serialization_whitelist";
 }
diff --git 
a/cayenne-rop-server/src/main/java/org/apache/cayenne/rop/ServerHessianSerializationServiceProvider.java
 
b/cayenne-rop-server/src/main/java/org/apache/cayenne/rop/ServerHessianSerializationServiceProvider.java
index dccb0c4..5d683fe 100644
--- 
a/cayenne-rop-server/src/main/java/org/apache/cayenne/rop/ServerHessianSerializationServiceProvider.java
+++ 
b/cayenne-rop-server/src/main/java/org/apache/cayenne/rop/ServerHessianSerializationServiceProvider.java
@@ -18,20 +18,42 @@
  ****************************************************************/
 package org.apache.cayenne.rop;
 
+import java.util.List;
+
+import org.apache.cayenne.DataChannel;
 import org.apache.cayenne.di.DIRuntimeException;
+import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.di.Provider;
 import org.apache.cayenne.remote.hessian.HessianConfig;
 import org.apache.cayenne.remote.hessian.service.ServerSerializerFactory;
 
 public class ServerHessianSerializationServiceProvider implements 
Provider<ROPSerializationService> {
 
+    private final Provider<DataChannel> dataChannelProvider;
+
+    private final List<String> serializationWhitelist;
+
     public static final String[] SERVER_SERIALIZER_FACTORIES = new String[] {
             ServerSerializerFactory.class.getName()
     };
 
+    /**
+     * @since 4.2
+     */
+    public ServerHessianSerializationServiceProvider(@Inject 
Provider<DataChannel> dataChannelProvider,
+                                                     
@Inject(ROPConstants.SERIALIZATION_WHITELIST) List<String> 
serializationWhitelist) {
+        this.dataChannelProvider = dataChannelProvider;
+        this.serializationWhitelist = serializationWhitelist;
+    }
+
     @Override
     public ROPSerializationService get() throws DIRuntimeException {
         return new HessianROPSerializationService(
-                HessianConfig.createFactory(SERVER_SERIALIZER_FACTORIES, 
null));
+                HessianConfig.createFactory(
+                        SERVER_SERIALIZER_FACTORIES,
+                        dataChannelProvider.get().getEntityResolver(),
+                        serializationWhitelist
+                )
+        );
     }
 }
diff --git a/pom.xml b/pom.xml
index 649f987..3e86ca8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -342,7 +342,7 @@
             <dependency>
                 <groupId>com.caucho</groupId>
                 <artifactId>hessian</artifactId>
-                <version>4.0.51</version>
+                <version>4.0.63</version>
                 <scope>provided</scope>
             </dependency>
                        <dependency>

Reply via email to