Merge pull request #437 from iantabolt/master

Make ValidationProblem implement Serializable
This commit is contained in:
Havoc Pennington 2018-03-29 11:26:37 -04:00 committed by GitHub
commit aea2ac4db8
2 changed files with 46 additions and 10 deletions

View File

@ -58,22 +58,22 @@ public abstract class ConfigException extends RuntimeException implements Serial
ConfigImplUtil.writeOrigin(out, origin);
}
private void readObject(java.io.ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
ConfigOrigin origin = ConfigImplUtil.readOrigin(in);
// For deserialization - uses reflection to set the final origin field on the object
private static <T> void setOriginField(T hasOriginField, Class<T> clazz,
ConfigOrigin origin) throws IOException {
// circumvent "final"
Field f;
try {
f = ConfigException.class.getDeclaredField("origin");
f = clazz.getDeclaredField("origin");
} catch (NoSuchFieldException e) {
throw new IOException("ConfigException has no origin field?", e);
throw new IOException(clazz.getSimpleName() + " has no origin field?", e);
} catch (SecurityException e) {
throw new IOException("unable to fill out origin field in ConfigException", e);
throw new IOException("unable to fill out origin field in " +
clazz.getSimpleName(), e);
}
f.setAccessible(true);
try {
f.set(this, origin);
f.set(hasOriginField, origin);
} catch (IllegalArgumentException e) {
throw new IOException("unable to set origin field", e);
} catch (IllegalAccessException e) {
@ -81,6 +81,13 @@ public abstract class ConfigException extends RuntimeException implements Serial
}
}
private void readObject(java.io.ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
ConfigOrigin origin = ConfigImplUtil.readOrigin(in);
setOriginField(this, ConfigException.class, origin);
}
/**
* Exception indicating that the type of a value does not match the type you
* requested.
@ -310,10 +317,10 @@ public abstract class ConfigException extends RuntimeException implements Serial
* {@link ConfigException.ValidationFailed} exception thrown from
* <code>checkValid()</code> includes a list of problems encountered.
*/
public static class ValidationProblem {
public static class ValidationProblem implements Serializable {
final private String path;
final private ConfigOrigin origin;
final private transient ConfigOrigin origin;
final private String problem;
public ValidationProblem(String path, ConfigOrigin origin, String problem) {
@ -347,6 +354,20 @@ public abstract class ConfigException extends RuntimeException implements Serial
return problem;
}
// We customize serialization because ConfigOrigin isn't
// serializable and we don't want it to be
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
ConfigImplUtil.writeOrigin(out, origin);
}
private void readObject(java.io.ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
ConfigOrigin origin = ConfigImplUtil.readOrigin(in);
setOriginField(this, ValidationProblem.class, origin);
}
@Override
public String toString() {
return "ValidationProblem(" + path + "," + origin + "," + problem + ")";

View File

@ -97,6 +97,21 @@ class ValidationTest extends TestUtils {
checkValidationException(e, expecteds)
}
@Test
def validationFailedSerializable(): Unit = {
// Reusing a previous test case to generate an error
val reference = parseConfig("""{ a : [{},{},{}] }""")
val conf = parseConfig("""{ a : 42 }""")
val e = intercept[ConfigException.ValidationFailed] {
conf.checkValid(reference)
}
val expecteds = Seq(WrongType("a", 1, "list", "number"))
val actual = checkSerializableNoMeaningfulEquals(e)
checkValidationException(actual, expecteds)
}
@Test
def validationAllowsListOverriddenWithSameTypeList() {
val reference = parseConfig("""{ a : [1,2,3] }""")