Fixes issue 1941. Updates the SerializationPolicyLoader such that it ignores any classes that can't be found during the loading process. I decided to add a new method, SerializationPolicyLoader.loadFromStream(InputStream, List<ClassNotFoundException>), since removing ClassNotFoundException from the throws clause of the existing loadFromStream(InputStream) method would break existing users. (I don't suspect that there are very many at all so maybe this decision was overly conservative.)
The new method returns a SerializationPolicy sans any class that could not be found. If the List argument is not null, any ClassNotFoundException thrown during the loading process is added to the list.
Patch by: mmendez
Review by: BobV
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1716 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java b/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java
index d4d0b2a..652c757 100644
--- a/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java
+++ b/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed 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
@@ -228,17 +228,11 @@
try {
if (is != null) {
try {
- serializationPolicy = SerializationPolicyLoader.loadFromStream(is);
+ serializationPolicy = SerializationPolicyLoader.loadFromStream(is, null);
} catch (ParseException e) {
getServletContext().log(
"ERROR: Failed to parse the policy file '"
+ serializationPolicyFilePath + "'", e);
- } catch (ClassNotFoundException e) {
- getServletContext().log(
- "ERROR: Could not find class '" + e.getMessage()
- + "' listed in the serialization policy file '"
- + serializationPolicyFilePath + "'"
- + "; your server's classpath may be misconfigured", e);
} catch (IOException e) {
getServletContext().log(
"ERROR: Could not read the policy file '"
diff --git a/user/src/com/google/gwt/user/server/rpc/SerializationPolicyLoader.java b/user/src/com/google/gwt/user/server/rpc/SerializationPolicyLoader.java
index a32eecb..7141141 100644
--- a/user/src/com/google/gwt/user/server/rpc/SerializationPolicyLoader.java
+++ b/user/src/com/google/gwt/user/server/rpc/SerializationPolicyLoader.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed 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
@@ -22,7 +22,9 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.ParseException;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
/**
@@ -59,9 +61,40 @@
* @throws ParseException if the input stream is not properly formatted
* @throws ClassNotFoundException if a class specified in the serialization
* policy cannot be loaded
+ *
+ * @deprecated see {@link #loadFromStream(InputStream, List)}
*/
+ @Deprecated
public static SerializationPolicy loadFromStream(InputStream inputStream)
throws IOException, ParseException, ClassNotFoundException {
+ List<ClassNotFoundException> classNotFoundExceptions = new ArrayList<ClassNotFoundException>();
+ SerializationPolicy serializationPolicy = loadFromStream(inputStream,
+ classNotFoundExceptions);
+ if (!classNotFoundExceptions.isEmpty()) {
+ // Just report the first failure.
+ throw classNotFoundExceptions.get(0);
+ }
+
+ return serializationPolicy;
+ }
+
+ /**
+ * Loads a SerializationPolicy from an input stream and optionally record any
+ * {@link ClassNotFoundException}s.
+ *
+ * @param inputStream stream to load the SerializationPolicy from.
+ * @param classNotFoundExceptions if not <code>null</code>, all of the
+ * {@link ClassNotFoundException}s thrown while loading this
+ * serialization policy will be added to this list
+ * @return a {@link SerializationPolicy} loaded from the input stream.
+ *
+ * @throws IOException if an error occurs while reading the stream
+ * @throws ParseException if the input stream is not properly formatted
+ */
+ public static SerializationPolicy loadFromStream(InputStream inputStream,
+ List<ClassNotFoundException> classNotFoundExceptions) throws IOException,
+ ParseException {
+
if (inputStream == null) {
throw new NullPointerException("inputStream");
}
@@ -91,9 +124,19 @@
}
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
- Class<?> clazz = Class.forName(binaryTypeName, false, contextClassLoader);
- // TODO: Validate the instantiable string better.
- whitelist.put(clazz, Boolean.valueOf(instantiable));
+
+ try {
+ Class<?> clazz = Class.forName(binaryTypeName, false,
+ contextClassLoader);
+ // TODO: Validate the instantiable string better.
+ whitelist.put(clazz, Boolean.valueOf(instantiable));
+ } catch (ClassNotFoundException ex) {
+ // Ignore the error, but add it to the list of errors if one was
+ // provided.
+ if (classNotFoundExceptions != null) {
+ classNotFoundExceptions.add(ex);
+ }
+ }
}
line = br.readLine();
diff --git a/user/src/com/google/gwt/user/server/rpc/impl/StandardSerializationPolicy.java b/user/src/com/google/gwt/user/server/rpc/impl/StandardSerializationPolicy.java
index db37365..e7373bf 100644
--- a/user/src/com/google/gwt/user/server/rpc/impl/StandardSerializationPolicy.java
+++ b/user/src/com/google/gwt/user/server/rpc/impl/StandardSerializationPolicy.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed 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
@@ -68,7 +68,7 @@
throw new SerializationException(
"Type '"
+ clazz.getName()
- + "' was not included in the set of types which can be deserialized by this SerializationPolicy. For security purposes, this type will not be deserialized.");
+ + "' was not included in the set of types which can be deserialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be deserialized.");
}
}
@@ -83,7 +83,7 @@
throw new SerializationException(
"Type '"
+ clazz.getName()
- + "' was not included in the set of types which can be serialized by this SerializationPolicy. For security purposes, this type will not be serialized.");
+ + "' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.");
}
}
diff --git a/user/test/com/google/gwt/user/server/rpc/SerializationPolicyLoaderTest.java b/user/test/com/google/gwt/user/server/rpc/SerializationPolicyLoaderTest.java
index b90dba9..5ced7cf 100644
--- a/user/test/com/google/gwt/user/server/rpc/SerializationPolicyLoaderTest.java
+++ b/user/test/com/google/gwt/user/server/rpc/SerializationPolicyLoaderTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed 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
@@ -24,6 +24,8 @@
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.List;
/**
* Test the {@link SerializationPolicyLoader} class.
@@ -71,6 +73,17 @@
} catch (ClassNotFoundException e) {
// expected to get here
}
+
+ // Test loading without collecting ClassNotFoundExceptions.
+ is.reset();
+ SerializationPolicyLoader.loadFromStream(is, null);
+
+ // Test loading and collecting ClassNotFoundExceptions.
+ List<ClassNotFoundException> classNotFoundExceptions = new ArrayList<ClassNotFoundException>();
+ is.reset();
+ SerializationPolicyLoader.loadFromStream(is, classNotFoundExceptions);
+ assertEquals(1, classNotFoundExceptions.size());
+ assertNotNull(classNotFoundExceptions.get(0));
}
/**