mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
Add unsafe-deserialization support for Jabsorb
This is partly extracted from https://github.com/github/codeql/pull/5954
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
lgtm,codescanning
|
||||||
|
* The "Deserialization of user-controlled data" (`java/unsafe-deserialization`) query now recognizes deserialization using the `Jabsorb` library.
|
||||||
@@ -15,7 +15,8 @@ may have unforeseen effects, such as the execution of arbitrary code.
|
|||||||
<p>
|
<p>
|
||||||
There are many different serialization frameworks. This query currently
|
There are many different serialization frameworks. This query currently
|
||||||
supports Kryo, XmlDecoder, XStream, SnakeYaml, JYaml, JsonIO, YAMLBeans, HessianBurlap, Castor, Burlap,
|
supports Kryo, XmlDecoder, XStream, SnakeYaml, JYaml, JsonIO, YAMLBeans, HessianBurlap, Castor, Burlap,
|
||||||
Jackson and Java IO serialization through <code>ObjectInputStream</code>/<code>ObjectOutputStream</code>.
|
Jackson, Jabsorb and Java IO serialization through
|
||||||
|
<code>ObjectInputStream</code>/<code>ObjectOutputStream</code>.
|
||||||
</p>
|
</p>
|
||||||
</overview>
|
</overview>
|
||||||
|
|
||||||
@@ -100,6 +101,10 @@ Blog posts by the developer of Jackson libraries:
|
|||||||
<a href="https://cowtowncoder.medium.com/on-jackson-cves-dont-panic-here-is-what-you-need-to-know-54cd0d6e8062">On Jackson CVEs: Don’t Panic — Here is what you need to know</a>
|
<a href="https://cowtowncoder.medium.com/on-jackson-cves-dont-panic-here-is-what-you-need-to-know-54cd0d6e8062">On Jackson CVEs: Don’t Panic — Here is what you need to know</a>
|
||||||
<a href="https://cowtowncoder.medium.com/jackson-2-10-safe-default-typing-2d018f0ce2ba">Jackson 2.10: Safe Default Typing</a>
|
<a href="https://cowtowncoder.medium.com/jackson-2-10-safe-default-typing-2d018f0ce2ba">Jackson 2.10: Safe Default Typing</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
Jabsorb documentation on deserialization:
|
||||||
|
<a href="https://github.com/Servoy/jabsorb/blob/master/src/org/jabsorb/">Jabsorb JSON Serializer</a>.
|
||||||
|
</li>
|
||||||
</references>
|
</references>
|
||||||
|
|
||||||
</qhelp>
|
</qhelp>
|
||||||
|
|||||||
26
java/ql/src/semmle/code/java/frameworks/Jabsorb.qll
Normal file
26
java/ql/src/semmle/code/java/frameworks/Jabsorb.qll
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* Provides classes for working with the Jabsorb JSON-RPC ORB framework.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
/** The class `org.jabsorb.JSONSerializer`. */
|
||||||
|
class JabsorbSerializer extends RefType {
|
||||||
|
JabsorbSerializer() { this.hasQualifiedName("org.jabsorb", "JSONSerializer") }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The deserialization method `unmarshall`. */
|
||||||
|
class JabsorbUnmarshallMethod extends Method {
|
||||||
|
JabsorbUnmarshallMethod() {
|
||||||
|
this.getDeclaringType().getASupertype*() instanceof JabsorbSerializer and
|
||||||
|
this.getName() = "unmarshall"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The deserialization method `fromJSON`. */
|
||||||
|
class JabsorbFromJsonMethod extends Method {
|
||||||
|
JabsorbFromJsonMethod() {
|
||||||
|
this.getDeclaringType().getASupertype*() instanceof JabsorbSerializer and
|
||||||
|
this.getName() = "fromJSON"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -77,14 +77,6 @@ class SetPolymorphicTypeValidatorSource extends DataFlow::ExprNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `fromNode` to `toNode` is a dataflow step that resolves a class. */
|
|
||||||
predicate resolveClassStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
|
|
||||||
exists(ReflectiveClassIdentifierMethodAccess ma |
|
|
||||||
ma.getArgument(0) = fromNode.asExpr() and
|
|
||||||
ma = toNode.asExpr()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `fromNode` to `toNode` is a dataflow step that creates a Jackson parser.
|
* Holds if `fromNode` to `toNode` is a dataflow step that creates a Jackson parser.
|
||||||
*
|
*
|
||||||
@@ -153,22 +145,3 @@ predicate hasArgumentWithUnsafeJacksonAnnotation(MethodAccess call) {
|
|||||||
hasJsonTypeInfoAnnotation(argType.(ParameterizedType).getATypeArgument())
|
hasJsonTypeInfoAnnotation(argType.(ParameterizedType).getATypeArgument())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `fromNode` to `toNode` is a dataflow step that looks like resolving a class.
|
|
||||||
* A method probably resolves a class if it takes a string, returns a type descriptor,
|
|
||||||
* and its name contains "resolve", "load", etc.
|
|
||||||
*
|
|
||||||
* Any method call that satisfies the rule above is assumed to propagate taint from its string arguments,
|
|
||||||
* so methods that accept user-controlled data but sanitize it or use it for some
|
|
||||||
* completely different purpose before returning a type descriptor could result in false positives.
|
|
||||||
*/
|
|
||||||
predicate looksLikeResolveClassStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
|
|
||||||
exists(MethodAccess ma, Method m, Expr arg | m = ma.getMethod() and arg = ma.getAnArgument() |
|
|
||||||
m.getReturnType() instanceof JacksonTypeDescriptorType and
|
|
||||||
m.getName().toLowerCase().regexpMatch("(.*)(resolve|load|class|type)(.*)") and
|
|
||||||
arg.getType() instanceof TypeString and
|
|
||||||
arg = fromNode.asExpr() and
|
|
||||||
ma = toNode.asExpr()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ private import semmle.code.java.frameworks.YamlBeans
|
|||||||
private import semmle.code.java.frameworks.HessianBurlap
|
private import semmle.code.java.frameworks.HessianBurlap
|
||||||
private import semmle.code.java.frameworks.Castor
|
private import semmle.code.java.frameworks.Castor
|
||||||
private import semmle.code.java.frameworks.Jackson
|
private import semmle.code.java.frameworks.Jackson
|
||||||
|
private import semmle.code.java.frameworks.Jabsorb
|
||||||
private import semmle.code.java.frameworks.apache.Lang
|
private import semmle.code.java.frameworks.apache.Lang
|
||||||
private import semmle.code.java.Reflection
|
private import semmle.code.java.Reflection
|
||||||
|
|
||||||
@@ -184,6 +185,13 @@ predicate unsafeDeserialization(MethodAccess ma, Expr sink) {
|
|||||||
hasArgumentWithUnsafeJacksonAnnotation(ma)
|
hasArgumentWithUnsafeJacksonAnnotation(ma)
|
||||||
) and
|
) and
|
||||||
not exists(SafeObjectMapperConfig config | config.hasFlowToExpr(ma.getQualifier()))
|
not exists(SafeObjectMapperConfig config | config.hasFlowToExpr(ma.getQualifier()))
|
||||||
|
or
|
||||||
|
m instanceof JabsorbUnmarshallMethod and
|
||||||
|
sink = ma.getArgument(2) and
|
||||||
|
any(UnsafeTypeConfig config).hasFlowToExpr(ma.getArgument(1))
|
||||||
|
or
|
||||||
|
m instanceof JabsorbFromJsonMethod and
|
||||||
|
sink = ma.getArgument(0)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,9 +251,36 @@ class UnsafeDeserializationConfig extends TaintTracking::Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Holds if `fromNode` to `toNode` is a dataflow step that resolves a class. */
|
||||||
|
predicate resolveClassStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
|
||||||
|
exists(ReflectiveClassIdentifierMethodAccess ma |
|
||||||
|
ma.getArgument(0) = fromNode.asExpr() and
|
||||||
|
ma = toNode.asExpr()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `fromNode` to `toNode` is a dataflow step that looks like resolving a class.
|
||||||
|
* A method probably resolves a class if it takes a string, returns a type descriptor,
|
||||||
|
* and its name contains "resolve", "load", etc.
|
||||||
|
*
|
||||||
|
* Any method call that satisfies the rule above is assumed to propagate taint from its string arguments,
|
||||||
|
* so methods that accept user-controlled data but sanitize it or use it for some
|
||||||
|
* completely different purpose before returning a type descriptor could result in false positives.
|
||||||
|
*/
|
||||||
|
predicate looksLikeResolveClassStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
|
||||||
|
exists(MethodAccess ma, Method m, Expr arg | m = ma.getMethod() and arg = ma.getAnArgument() |
|
||||||
|
m.getReturnType() instanceof JacksonTypeDescriptorType and
|
||||||
|
m.getName().toLowerCase().regexpMatch("(?i).*(resolve|load|class|type).*") and
|
||||||
|
arg.getType() instanceof TypeString and
|
||||||
|
arg = fromNode.asExpr() and
|
||||||
|
ma = toNode.asExpr()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tracks flow from a remote source to a type descriptor (e.g. a `java.lang.Class` instance)
|
* Tracks flow from a remote source to a type descriptor (e.g. a `java.lang.Class` instance)
|
||||||
* passed to a Jackson deserialization method.
|
* passed to a deserialization method.
|
||||||
*
|
*
|
||||||
* If this is user-controlled, arbitrary code could be executed while instantiating the user-specified type.
|
* If this is user-controlled, arbitrary code could be executed while instantiating the user-specified type.
|
||||||
*/
|
*/
|
||||||
@@ -256,7 +291,12 @@ class UnsafeTypeConfig extends TaintTracking2::Configuration {
|
|||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
override predicate isSink(DataFlow::Node sink) {
|
||||||
exists(MethodAccess ma, int i, Expr arg | i > 0 and ma.getArgument(i) = arg |
|
exists(MethodAccess ma, int i, Expr arg | i > 0 and ma.getArgument(i) = arg |
|
||||||
ma.getMethod() instanceof ObjectMapperReadMethod and
|
(
|
||||||
|
ma.getMethod() instanceof ObjectMapperReadMethod
|
||||||
|
or
|
||||||
|
ma.getMethod() instanceof JabsorbUnmarshallMethod
|
||||||
|
) and
|
||||||
|
// Note `JacksonTypeDescriptorType` includes plain old `java.lang.Class`
|
||||||
arg.getType() instanceof JacksonTypeDescriptorType and
|
arg.getType() instanceof JacksonTypeDescriptorType and
|
||||||
arg = sink.asExpr()
|
arg = sink.asExpr()
|
||||||
)
|
)
|
||||||
|
|||||||
121
java/ql/test/query-tests/security/CWE-502/JabsorbServlet.java
Normal file
121
java/ql/test/query-tests/security/CWE-502/JabsorbServlet.java
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.jabsorb.JSONSerializer;
|
||||||
|
import org.jabsorb.serializer.SerializerState;
|
||||||
|
import org.jabsorb.serializer.ObjectMatch;
|
||||||
|
|
||||||
|
import com.example.User;
|
||||||
|
import com.thirdparty.Person;
|
||||||
|
|
||||||
|
public class JabsorbServlet extends HttpServlet {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
// GOOD: final class type specified
|
||||||
|
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||||
|
String json = req.getParameter("json");
|
||||||
|
String clazz = req.getParameter("class");
|
||||||
|
|
||||||
|
try {
|
||||||
|
Object jsonObject = new JSONObject(json);
|
||||||
|
|
||||||
|
JSONSerializer serializer = new JSONSerializer();
|
||||||
|
serializer.registerDefaultSerializers();
|
||||||
|
|
||||||
|
serializer.setMarshallClassHints(true);
|
||||||
|
serializer.setMarshallNullAttributes(true);
|
||||||
|
|
||||||
|
SerializerState state = new SerializerState();
|
||||||
|
User user = (User) serializer.unmarshall(state, User.class, jsonObject);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IOException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GOOD: concrete class type specified even if it has vulnerable subclasses
|
||||||
|
public void doHead(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||||
|
String json = req.getParameter("json");
|
||||||
|
String clazz = req.getParameter("class");
|
||||||
|
|
||||||
|
try {
|
||||||
|
Object jsonObject = new JSONObject(json);
|
||||||
|
|
||||||
|
JSONSerializer serializer = new JSONSerializer();
|
||||||
|
serializer.registerDefaultSerializers();
|
||||||
|
|
||||||
|
serializer.setMarshallClassHints(true);
|
||||||
|
serializer.setMarshallNullAttributes(true);
|
||||||
|
|
||||||
|
SerializerState state = new SerializerState();
|
||||||
|
Person person = (Person) serializer.unmarshall(state, Person.class, jsonObject);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IOException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
// GOOD: try unmarshall but doesn't actually marshall the object
|
||||||
|
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||||
|
String json = req.getParameter("json");
|
||||||
|
String clazz = req.getParameter("class");
|
||||||
|
|
||||||
|
try {
|
||||||
|
Object jsonObject = new JSONObject(json);
|
||||||
|
|
||||||
|
JSONSerializer serializer = new JSONSerializer();
|
||||||
|
serializer.registerDefaultSerializers();
|
||||||
|
|
||||||
|
serializer.setMarshallClassHints(true);
|
||||||
|
serializer.setMarshallNullAttributes(true);
|
||||||
|
|
||||||
|
SerializerState state = new SerializerState();
|
||||||
|
ObjectMatch objMatch = serializer.tryUnmarshall(state, Class.forName(clazz), jsonObject);
|
||||||
|
User obj = new User();
|
||||||
|
boolean result = objMatch.equals(obj);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IOException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
// BAD: allow class name to be controlled by remote source
|
||||||
|
public void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||||
|
String json = req.getParameter("json");
|
||||||
|
String clazz = req.getParameter("class");
|
||||||
|
|
||||||
|
try {
|
||||||
|
Object jsonObject = new JSONObject(json);
|
||||||
|
|
||||||
|
JSONSerializer serializer = new JSONSerializer();
|
||||||
|
serializer.registerDefaultSerializers();
|
||||||
|
|
||||||
|
serializer.setMarshallClassHints(true);
|
||||||
|
serializer.setMarshallNullAttributes(true);
|
||||||
|
|
||||||
|
SerializerState state = new SerializerState();
|
||||||
|
User user = (User) serializer.unmarshall(state, Class.forName(clazz), jsonObject); // $unsafeDeserialization
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IOException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BAD: allow explicit class type controlled by remote source in the format of "json={\"javaClass\":\"com.thirdparty.Attacker\", ...}"
|
||||||
|
public void doPut2(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||||
|
String json = req.getParameter("json");
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONSerializer serializer = new JSONSerializer();
|
||||||
|
serializer.registerDefaultSerializers();
|
||||||
|
|
||||||
|
User user = (User) serializer.fromJSON(json); // $unsafeDeserialization
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IOException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
java/ql/test/query-tests/security/CWE-502/Person.java
Normal file
29
java/ql/test/query-tests/security/CWE-502/Person.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package com.thirdparty;
|
||||||
|
|
||||||
|
public class Person {
|
||||||
|
private int snum;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Person() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSnum() {
|
||||||
|
return snum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSnum(int snum) {
|
||||||
|
this.snum = snum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "Person[ name = "+name+", snum: "+snum+ "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
29
java/ql/test/query-tests/security/CWE-502/User.java
Normal file
29
java/ql/test/query-tests/security/CWE-502/User.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package com.example;
|
||||||
|
|
||||||
|
public final class User {
|
||||||
|
private String uid;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public User() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUid() {
|
||||||
|
return uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUid(String uid) {
|
||||||
|
this.uid = uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "User[ name = "+name+", uid: "+uid+ "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1 @@
|
|||||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1:${testdir}/../../../stubs/jackson-databind-2.12:${testdir}/../../../stubs/jackson-core-2.12
|
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1:${testdir}/../../../stubs/jackson-databind-2.12:${testdir}/../../../stubs/jackson-core-2.12:${testdir}/../../../stubs/jabsorb-1.3.2:${testdir}/../../../stubs/json-java-20210307
|
||||||
|
|||||||
319
java/ql/test/stubs/jabsorb-1.3.2/org/jabsorb/JSONSerializer.java
Normal file
319
java/ql/test/stubs/jabsorb-1.3.2/org/jabsorb/JSONSerializer.java
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
/*
|
||||||
|
* jabsorb - a Java to JavaScript Advanced Object Request Broker
|
||||||
|
* http://www.jabsorb.org
|
||||||
|
*
|
||||||
|
* Copyright 2007-2009 The jabsorb team
|
||||||
|
*
|
||||||
|
* based on original code from
|
||||||
|
* JSON-RPC-Java - a JSON-RPC to Java Bridge with dynamic invocation
|
||||||
|
*
|
||||||
|
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||||
|
* Michael Clark <michael@metaparadigm.com>
|
||||||
|
*
|
||||||
|
* 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 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.jabsorb;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.jabsorb.serializer.MarshallException;
|
||||||
|
import org.jabsorb.serializer.ObjectMatch;
|
||||||
|
import org.jabsorb.serializer.Serializer;
|
||||||
|
import org.jabsorb.serializer.SerializerState;
|
||||||
|
import org.jabsorb.serializer.UnmarshallException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is the public entry point to the serialization code and provides
|
||||||
|
* methods for marshalling Java objects into JSON objects and unmarshalling JSON
|
||||||
|
* objects into Java objects.
|
||||||
|
*/
|
||||||
|
public class JSONSerializer implements Serializable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if this serializer considers the given Object to be a primitive
|
||||||
|
* wrapper type Object. This is used to determine which types of Objects
|
||||||
|
* should be fixed up as duplicates if the fixupDuplicatePrimitives flag
|
||||||
|
* is false.
|
||||||
|
*
|
||||||
|
* @param o Object to test for primitive.
|
||||||
|
*/
|
||||||
|
public boolean isPrimitive(Object o)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the fixupCircRefs flag. If true, FixUps are generated to handle circular
|
||||||
|
* references found during marshalling. If false, an exception is thrown if a
|
||||||
|
* circular reference is found during serialization.
|
||||||
|
*
|
||||||
|
* @return the fixupCircRefs flag.
|
||||||
|
*/
|
||||||
|
public boolean getFixupCircRefs()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the fixupCircRefs flag. If true, FixUps are generated to handle circular
|
||||||
|
* references found during marshalling. If false, an exception is thrown if a
|
||||||
|
* circular reference is found during serialization.
|
||||||
|
*
|
||||||
|
* @param fixupCircRefs the fixupCircRefs flag.
|
||||||
|
*/
|
||||||
|
public void setFixupCircRefs(boolean fixupCircRefs)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the fixupDuplicates flag. If true, FixUps are generated for duplicate
|
||||||
|
* objects found during marshalling. If false, the duplicates are re-serialized.
|
||||||
|
*
|
||||||
|
* @return the fixupDuplicates flag.
|
||||||
|
*/
|
||||||
|
public boolean getFixupDuplicates()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the fixupDuplicates flag. If true, FixUps are generated for duplicate
|
||||||
|
* objects found during marshalling. If false, the duplicates are re-serialized.
|
||||||
|
*
|
||||||
|
* @param fixupDuplicates the fixupDuplicates flag.
|
||||||
|
*/
|
||||||
|
public void setFixupDuplicates(boolean fixupDuplicates)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the fixupDuplicatePrimitives flag. If true (and fixupDuplicates is
|
||||||
|
* also true), FixUps are generated for duplicate primitive objects found
|
||||||
|
* during marshalling. If false, the duplicates are re-serialized.
|
||||||
|
*
|
||||||
|
* @return the fixupDuplicatePrimitives flag.
|
||||||
|
*/
|
||||||
|
public boolean getFixupDuplicatePrimitives()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the fixupDuplicatePrimitives flag. If true (and fixupDuplicates is
|
||||||
|
* also true), FixUps are generated for duplicate primitive objects found
|
||||||
|
* during marshalling. If false, the duplicates are re-serialized.
|
||||||
|
*
|
||||||
|
* @param fixupDuplicatePrimitives the fixupDuplicatePrimitives flag.
|
||||||
|
*/
|
||||||
|
public void setFixupDuplicatePrimitives(boolean fixupDuplicatePrimitives)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a string in JSON format into Java objects.
|
||||||
|
*
|
||||||
|
* @param jsonString The JSON format string.
|
||||||
|
* @return An object (or tree of objects) representing the data in the JSON
|
||||||
|
* format string.
|
||||||
|
* @throws UnmarshallException If unmarshalling fails
|
||||||
|
*/
|
||||||
|
public Object fromJSON(String jsonString) throws UnmarshallException
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should serializers defined in this object include the fully qualified class
|
||||||
|
* name of objects being serialized? This can be helpful when unmarshalling,
|
||||||
|
* though if not needed can be left out in favor of increased performance and
|
||||||
|
* smaller size of marshalled String. Default is true.
|
||||||
|
*
|
||||||
|
* @return whether Java Class hints are included in the serialised JSON
|
||||||
|
* objects
|
||||||
|
*/
|
||||||
|
public boolean getMarshallClassHints()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if attributes will null values should still be included in the
|
||||||
|
* serialized JSON object. Defaults to true. Set to false for performance
|
||||||
|
* gains and small JSON serialized size. Useful because null and undefined for
|
||||||
|
* JSON object attributes is virtually the same thing.
|
||||||
|
*
|
||||||
|
* @return boolean value as to whether null attributes will be in the
|
||||||
|
* serialized JSON objects
|
||||||
|
*/
|
||||||
|
public boolean getMarshallNullAttributes()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marshall java into an equivalent json representation (JSONObject or
|
||||||
|
* JSONArray.) <p/> This involves finding the correct Serializer for the class
|
||||||
|
* of the given java object and then invoking it to marshall the java object
|
||||||
|
* into json. <p/> The Serializer will invoke this method recursively while
|
||||||
|
* marshalling complex object graphs.
|
||||||
|
*
|
||||||
|
* @param state can be used by the underlying Serializer objects to hold state
|
||||||
|
* while marshalling.
|
||||||
|
*
|
||||||
|
* @param parent parent object of the object being converted. this can be null if
|
||||||
|
* it's the root object being converted.
|
||||||
|
* @param java java object to convert into json.
|
||||||
|
*
|
||||||
|
* @param ref reference within the parent's point of view of the object being serialized.
|
||||||
|
* this will be a String for JSONObjects and an Integer for JSONArrays.
|
||||||
|
*
|
||||||
|
* @return the JSONObject or JSONArray (or primitive object) containing the json
|
||||||
|
* for the marshalled java object or the special token Object,
|
||||||
|
* JSONSerializer.CIRC_REF_OR_DUP to indicate to the caller that the
|
||||||
|
* given Object has already been serialized and so therefore the result
|
||||||
|
* should be ignored.
|
||||||
|
*
|
||||||
|
* @throws MarshallException if there is a problem marshalling java to json.
|
||||||
|
*/
|
||||||
|
public Object marshall(SerializerState state, Object parent, Object java, Object ref)
|
||||||
|
throws MarshallException
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register all of the provided standard serializers.
|
||||||
|
*
|
||||||
|
* @throws Exception If a serialiser has already been registered for a class.
|
||||||
|
*
|
||||||
|
* TODO: Should this be thrown: This can only happen if there is an internal
|
||||||
|
* problem with the code
|
||||||
|
*/
|
||||||
|
public void registerDefaultSerializers() throws Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new type specific serializer. The order of registration is
|
||||||
|
* important. More specific serializers should be added after less specific
|
||||||
|
* serializers. This is because when the JSONSerializer is trying to find a
|
||||||
|
* serializer, if it can't find the serializer by a direct match, it will
|
||||||
|
* search for a serializer in the reverse order that they were registered.
|
||||||
|
*
|
||||||
|
* @param s A class implementing the Serializer interface (usually derived
|
||||||
|
* from AbstractSerializer).
|
||||||
|
*/
|
||||||
|
public void registerSerializer(Serializer s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should serializers defined in this object include the fully qualified class
|
||||||
|
* name of objects being serialized? This can be helpful when unmarshalling,
|
||||||
|
* though if not needed can be left out in favor of increased performance and
|
||||||
|
* smaller size of marshalled String. Default is true.
|
||||||
|
*
|
||||||
|
* @param marshallClassHints flag to enable/disable inclusion of Java class
|
||||||
|
* hints in the serialized JSON objects
|
||||||
|
*/
|
||||||
|
public void setMarshallClassHints(boolean marshallClassHints)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if attributes will null values should still be included in the
|
||||||
|
* serialized JSON object. Defaults to true. Set to false for performance
|
||||||
|
* gains and small JSON serialized size. Useful because null and undefined for
|
||||||
|
* JSON object attributes is virtually the same thing.
|
||||||
|
*
|
||||||
|
* @param marshallNullAttributes flag to enable/disable marshalling of null
|
||||||
|
* attributes in the serialized JSON objects
|
||||||
|
*/
|
||||||
|
public void setMarshallNullAttributes(boolean marshallNullAttributes)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a Java objects (or tree of Java objects) into a string in JSON
|
||||||
|
* format. Note that this method will remove any circular references / duplicates
|
||||||
|
* and not handle the potential fixups that could be generated. (unless duplicates/circular
|
||||||
|
* references are turned off.
|
||||||
|
*
|
||||||
|
* todo: have some way to transmit the fixups back to the caller of this method.
|
||||||
|
*
|
||||||
|
* @param obj the object to be converted to JSON.
|
||||||
|
* @return the JSON format string representing the data in the the Java
|
||||||
|
* object.
|
||||||
|
* @throws MarshallException If marshalling fails.
|
||||||
|
*/
|
||||||
|
public String toJSON(Object obj) throws MarshallException
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Determine if a given JSON object matches a given class type, and to what
|
||||||
|
* degree it matches. An ObjectMatch instance is returned which contains a
|
||||||
|
* number indicating the number of fields that did not match. Therefore when a given
|
||||||
|
* parameter could potentially match in more that one way, this is a metric
|
||||||
|
* to compare these ObjectMatches to determine which one matches more closely.
|
||||||
|
* </p><p>
|
||||||
|
* This is only used when there are overloaded method names that are being called
|
||||||
|
* from JSON-RPC to determine which call signature the method call matches most
|
||||||
|
* closely and therefore which method is the intended target method to call.
|
||||||
|
* </p>
|
||||||
|
* @param state used by the underlying Serializer objects to hold state
|
||||||
|
* while unmarshalling for detecting circular references and duplicates.
|
||||||
|
*
|
||||||
|
* @param clazz optional java class to unmarshall to- if set to null then it
|
||||||
|
* will be looked for via the javaClass hinting mechanism.
|
||||||
|
*
|
||||||
|
* @param json JSONObject or JSONArray or primitive Object wrapper that contains the json to unmarshall.
|
||||||
|
*
|
||||||
|
* @return an ObjectMatch indicating the degree to which the object matched the class,
|
||||||
|
* @throws UnmarshallException if getClassFromHint() fails
|
||||||
|
*/
|
||||||
|
public ObjectMatch tryUnmarshall(SerializerState state, Class clazz,
|
||||||
|
Object json) throws UnmarshallException
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unmarshall json into an equivalent java object. <p/> This involves finding
|
||||||
|
* the correct Serializer to use and then delegating to that Serializer to
|
||||||
|
* unmarshall for us. This method will be invoked recursively as Serializers
|
||||||
|
* unmarshall complex object graphs.
|
||||||
|
*
|
||||||
|
* @param state used by the underlying Serializer objects to hold state
|
||||||
|
* while unmarshalling for detecting circular references and duplicates.
|
||||||
|
*
|
||||||
|
* @param clazz optional java class to unmarshall to- if set to null then it
|
||||||
|
* will be looked for via the javaClass hinting mechanism.
|
||||||
|
*
|
||||||
|
* @param json JSONObject or JSONArray or primitive Object wrapper that contains the json to unmarshall.
|
||||||
|
*
|
||||||
|
* @return the java object representing the json that was unmarshalled.
|
||||||
|
*
|
||||||
|
* @throws UnmarshallException if there is a problem unmarshalling json to
|
||||||
|
* java.
|
||||||
|
*/
|
||||||
|
public Object unmarshall(SerializerState state, Class clazz, Object json)
|
||||||
|
throws UnmarshallException
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package org.jabsorb.serializer;
|
||||||
|
|
||||||
|
public class MarshallException extends Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* jabsorb - a Java to JavaScript Advanced Object Request Broker
|
||||||
|
* http://www.jabsorb.org
|
||||||
|
*
|
||||||
|
* Copyright 2007-2009 The jabsorb team
|
||||||
|
*
|
||||||
|
* based on original code from
|
||||||
|
* JSON-RPC-Java - a JSON-RPC to Java Bridge with dynamic invocation
|
||||||
|
*
|
||||||
|
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||||
|
* Michael Clark <michael@metaparadigm.com>
|
||||||
|
*
|
||||||
|
* 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 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.jabsorb.serializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* This class is returned from the Serializer tryUnmarshall method to indicate
|
||||||
|
* number of mismatched fields. This is used to handle ambiguities with
|
||||||
|
* JavaScript's typeless objects combined with and Java's operator overloading.
|
||||||
|
* </p>
|
||||||
|
* TODO: wouldn't a better name for this class be ObjectMismatch as it's would
|
||||||
|
* be more descriptive. The name ObjectMatch is a little confusing because it
|
||||||
|
* implies the opposite of what the class actually stores (ObjectMismatch)
|
||||||
|
* either that, or I'm not understanding something correctly... [WB: I agree!]
|
||||||
|
*/
|
||||||
|
public class ObjectMatch
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a new ObjectMatch object with the given number of mismatches.
|
||||||
|
*
|
||||||
|
* @param mismatch the number of mismatched fields that occured on a
|
||||||
|
* tryUnmarshall call.
|
||||||
|
*/
|
||||||
|
public ObjectMatch(int mismatch)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of mismatched fields that occured on a tryUnmarshall call.
|
||||||
|
*
|
||||||
|
* @return the number of mismatched fields that occured on a tryUnmarshall
|
||||||
|
* call.
|
||||||
|
*/
|
||||||
|
public int getMismatch()
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the mismatch on this ObjectMatch.
|
||||||
|
* The ObjectMatch cannot be immutable anymore (at least in the current design--
|
||||||
|
* because the same mismatch object must be maintained through recursive processing
|
||||||
|
* to properly handle circular references detection)
|
||||||
|
*
|
||||||
|
* @param mismatch the mismatch value to set for this ObjectMatch.
|
||||||
|
*/
|
||||||
|
public void setMismatch(int mismatch)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare another ObjectMatch with this ObjectMatch and return the one that
|
||||||
|
* has the most mismatches.
|
||||||
|
*
|
||||||
|
* @param m ObjectMatch to compare this ObjectMatch to.
|
||||||
|
*
|
||||||
|
* @return this ObjectMatch if it has more mismatches, else the passed in
|
||||||
|
* ObjectMatch.
|
||||||
|
*/
|
||||||
|
public ObjectMatch max(ObjectMatch m)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* jabsorb - a Java to JavaScript Advanced Object Request Broker
|
||||||
|
* http://www.jabsorb.org
|
||||||
|
*
|
||||||
|
* Copyright 2007-2009 The jabsorb team
|
||||||
|
*
|
||||||
|
* based on original code from
|
||||||
|
* JSON-RPC-Java - a JSON-RPC to Java Bridge with dynamic invocation
|
||||||
|
*
|
||||||
|
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||||
|
* Michael Clark <michael@metaparadigm.com>
|
||||||
|
*
|
||||||
|
* 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 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.jabsorb.serializer;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.jabsorb.JSONSerializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to be implemented by custom serializer objects that convert to and
|
||||||
|
* from Java objects and JSON objects.
|
||||||
|
*/
|
||||||
|
public interface Serializer extends Serializable
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the given java,json class pair can be handled by this
|
||||||
|
* serializer. Both for serialzing from java => json and deserializing from
|
||||||
|
* json => java.
|
||||||
|
*
|
||||||
|
* @param clazz java Class type.
|
||||||
|
* @param jsonClazz json Class wrapper type.
|
||||||
|
* @return true if this serializer can serialize/deserialize the given pair.
|
||||||
|
*/
|
||||||
|
public boolean canSerialize(Class clazz, Class jsonClazz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the json java classes that this Serializer is able to serialize from
|
||||||
|
* json into java and deserialize into json from java. <p/> These will
|
||||||
|
* typically be primitive class type wrappers or JSONObject, JSONArray.
|
||||||
|
*
|
||||||
|
* @return json side java classes that can be serialized/deserialized by this
|
||||||
|
* serializer.
|
||||||
|
*/
|
||||||
|
public Class[] getJSONClasses();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the java classes that this Serializer is able to serialize from java
|
||||||
|
* into json and deserialize into java from json.
|
||||||
|
*
|
||||||
|
* @return java side classes that can be serialized/deserialized by this
|
||||||
|
* serializer.
|
||||||
|
*/
|
||||||
|
public Class[] getSerializableClasses();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marshall a java object into an equivalent json object.
|
||||||
|
*
|
||||||
|
* @param state can be used to hold state while unmarshalling through
|
||||||
|
* recursive levels.
|
||||||
|
* @param p parent of java object being marshalled into json (can be null if the object is the root object being marshalled.
|
||||||
|
* @param o java object to marhsall into json.
|
||||||
|
* @return that JSONObject or JSONArray that contains the json representation
|
||||||
|
* of the java object that was marshalled.
|
||||||
|
* @throws MarshallException if there is a problem marshalling java to json.
|
||||||
|
*/
|
||||||
|
public Object marshall(SerializerState state, Object p, Object o)
|
||||||
|
throws MarshallException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the owning JSONSerializer of this Serializer instance.
|
||||||
|
*
|
||||||
|
* @param ser the owning JSONSerializer of this Serializer instance.
|
||||||
|
*/
|
||||||
|
public void setOwner(JSONSerializer ser);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to unmarshal a javascript object
|
||||||
|
*
|
||||||
|
* @param state The state of the serialiser
|
||||||
|
* @param clazz The class to unmarhall to
|
||||||
|
* @param json The object to unmarshal
|
||||||
|
* @return An ObjectMatch denoting whether the object matches the class (?)
|
||||||
|
* @throws UnmarshallException
|
||||||
|
*/
|
||||||
|
public ObjectMatch tryUnmarshall(SerializerState state, Class clazz,
|
||||||
|
Object json) throws UnmarshallException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unmarshall json into an equivalent java object.
|
||||||
|
*
|
||||||
|
* @param state can be used to hold state while unmarshalling through
|
||||||
|
* recursive levels.
|
||||||
|
* @param clazz optional java class to unmarshall to.
|
||||||
|
* @param json JSONObject or JSONArray that contains the json to unmarshall.
|
||||||
|
* @return the java object representing the json that was unmarshalled.
|
||||||
|
* @throws UnmarshallException if there is a problem unmarshalling json to
|
||||||
|
* java.
|
||||||
|
*/
|
||||||
|
public Object unmarshall(SerializerState state, Class clazz, Object json)
|
||||||
|
throws UnmarshallException;
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* jabsorb - a Java to JavaScript Advanced Object Request Broker
|
||||||
|
* http://www.jabsorb.org
|
||||||
|
*
|
||||||
|
* Copyright 2007-2009 The jabsorb team
|
||||||
|
*
|
||||||
|
* based on original code from
|
||||||
|
* JSON-RPC-Java - a JSON-RPC to Java Bridge with dynamic invocation
|
||||||
|
*
|
||||||
|
* Copyright Metaparadigm Pte. Ltd. 2004.
|
||||||
|
* Michael Clark <michael@metaparadigm.com>
|
||||||
|
*
|
||||||
|
* 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 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.jabsorb.serializer;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by Serializers to hold state during marshalling and
|
||||||
|
* unmarshalling. It keeps track of all Objects encountered
|
||||||
|
* during processing for the purpose of detecting circular
|
||||||
|
* references and/or duplicates.
|
||||||
|
*/
|
||||||
|
public class SerializerState
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Add a fixup entry. Assumes that the SerializerState is in the correct scope for the
|
||||||
|
* fix up location.
|
||||||
|
*
|
||||||
|
* @param originalLocation original json path location where the object was first encountered.
|
||||||
|
* @param ref additional reference (String|Integer) to add on to the scope's current location.
|
||||||
|
* @throws MarshallException if a scope error occurs (this won't normally occur.
|
||||||
|
*/
|
||||||
|
public void addFixUp(List originalLocation, Object ref) throws MarshallException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the List of all FixUp objects created during processing.
|
||||||
|
* @return List of FixUps to circular references and duplicates found during processing.
|
||||||
|
*/
|
||||||
|
public List getFixUps()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pop off one level from the scope stack of the current location during processing.
|
||||||
|
* If we are already at the lowest level of scope, then this has no action.
|
||||||
|
* @throws MarshallException If called when currentLocation is empty
|
||||||
|
*/
|
||||||
|
public void pop() throws MarshallException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record the given object as a ProcessedObject and push into onto the scope stack. This is only
|
||||||
|
* used for marshalling. The store method should be used for unmarshalling.
|
||||||
|
*
|
||||||
|
* @param parent parent of object to process. Can be null if it's the root object being processed.
|
||||||
|
* it should be an object that was already processed via a previous call to processObject.
|
||||||
|
*
|
||||||
|
* @param obj object being processed
|
||||||
|
* @param ref reference to object within parent-- should be a String if parent is an object, and Integer
|
||||||
|
* if parent is an array. Can be null if this is the root object that is being pushed/processed.
|
||||||
|
*/
|
||||||
|
public void push(Object parent, Object obj, Object ref)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associate the incoming source object being serialized to it's serialized representation.
|
||||||
|
* Currently only used within tryUnmarshall and unmarshall. This MUST be called before a given unmarshall
|
||||||
|
* or tryUnmarshall recurses into child objects to unmarshall them.
|
||||||
|
* The purpose is to stop the recursion that can take place when circular references/duplicates are in the
|
||||||
|
* input json being unmarshalled.
|
||||||
|
*
|
||||||
|
* @param source source object being unmarshalled.
|
||||||
|
* @param target target serialized representation of the object that the source object is being unmarshalled to.
|
||||||
|
* @throws UnmarshallException if the source object is null, or is not already stored within a ProcessedObject.
|
||||||
|
*/
|
||||||
|
public void setSerialized(Object source, Object target) throws UnmarshallException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package org.jabsorb.serializer;
|
||||||
|
|
||||||
|
public class UnmarshallException extends Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user