diff --git a/src/main/java/tools/jackson/databind/ext/OptionalHandlerFactory.java b/src/main/java/tools/jackson/databind/ext/OptionalHandlerFactory.java
index b125ae3425..fb956703e6 100644
--- a/src/main/java/tools/jackson/databind/ext/OptionalHandlerFactory.java
+++ b/src/main/java/tools/jackson/databind/ext/OptionalHandlerFactory.java
@@ -1,30 +1,22 @@
package tools.jackson.databind.ext;
-import java.util.HashMap;
-import java.util.Map;
-
import javax.xml.datatype.Duration;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import tools.jackson.databind.*;
-import tools.jackson.databind.ser.jdk.JavaUtilDateSerializer;
+import tools.jackson.databind.ext.sql.JavaSqlTypeHandlerFactory;
import tools.jackson.databind.ser.std.ToStringSerializer;
-import tools.jackson.databind.util.ClassUtil;
/**
* Helper class used for isolating details of handling optional+external types
* (javax.xml classes) from standard factories that offer them.
- *
- * Note that with 3.0 need for separate class has been reduced somewhat
- * and this class may be eliminated.
*/
public class OptionalHandlerFactory
{
- /* To make 2 main "optional" handler groups (javax.xml.stream)
- * more dynamic, we better only figure out handlers completely dynamically, if and
- * when they are needed. To do this we need to assume package prefixes.
- */
+ // To make 2 main "optional" handler groups (javax.xml.stream)
+ // more dynamic, we better only figure out handlers completely dynamically, if and
+ // when they are needed. To do this we need to assume package prefixes.
private final static String PACKAGE_PREFIX_JAVAX_XML = "javax.xml.";
// // Since 2.7, we will assume DOM classes are always found, both due to JDK 1.6 minimum
@@ -35,41 +27,7 @@ public class OptionalHandlerFactory
public final static OptionalHandlerFactory instance = new OptionalHandlerFactory();
- // classes from java.sql module, this module may or may not be present at runtime
- // (is included on Java 8, but not part of JDK core for Java 9 and beyond)
- private final Map _sqlDeserializers;
- private final Map _sqlSerializers;
-
- private final static String CLS_NAME_JAVA_SQL_TIMESTAMP = "java.sql.Timestamp";
- private final static String CLS_NAME_JAVA_SQL_DATE = "java.sql.Date";
- private final static String CLS_NAME_JAVA_SQL_TIME = "java.sql.Time";
- private final static String CLS_NAME_JAVA_SQL_BLOB = "java.sql.Blob";
- private final static String CLS_NAME_JAVA_SQL_SERIALBLOB = "javax.sql.rowset.serial.SerialBlob";
-
protected OptionalHandlerFactory() {
- _sqlDeserializers = new HashMap<>();
- _sqlDeserializers.put(CLS_NAME_JAVA_SQL_DATE,
- "tools.jackson.databind.ext.sql.JavaSqlDateDeserializer");
- _sqlDeserializers.put(CLS_NAME_JAVA_SQL_TIMESTAMP,
- "tools.jackson.databind.ext.sql.JavaSqlTimestampDeserializer");
- // 09-Nov-2020, tatu: No deserializer for `java.sql.Blob` yet; would require additional
- // dependency and not yet requested by anyone. Add if requested
-
- _sqlSerializers = new HashMap<>();
- // 09-Jan-2015, tatu: As per [databind#1073], let's try to guard against possibility
- // of some environments missing `java.sql.` types
-
- // note: timestamps are very similar to java.util.Date, thus serialized as such
- _sqlSerializers.put(CLS_NAME_JAVA_SQL_TIMESTAMP, JavaUtilDateSerializer.instance);
- _sqlSerializers.put(CLS_NAME_JAVA_SQL_DATE, "tools.jackson.databind.ext.sql.JavaSqlDateSerializer");
- _sqlSerializers.put(CLS_NAME_JAVA_SQL_TIME, "tools.jackson.databind.ext.sql.JavaSqlTimeSerializer");
-
- // 09-Nov-2020, tatu: Not really optimal way to deal with these, problem being that
- // Blob is interface and actual instance we get is usually different. So may
- // need to improve if we reported bugs. But for now, do this
-
- _sqlSerializers.put(CLS_NAME_JAVA_SQL_BLOB, "tools.jackson.databind.ext.sql.JavaSqlBlobSerializer");
- _sqlSerializers.put(CLS_NAME_JAVA_SQL_SERIALBLOB, "tools.jackson.databind.ext.sql.JavaSqlBlobSerializer");
}
/*
@@ -86,15 +44,6 @@ public ValueSerializer> findSerializer(SerializationConfig config, JavaType ty
}
String className = rawType.getName();
- Object sqlHandler = _sqlSerializers.get(className);
-
- if (sqlHandler != null) {
- if (sqlHandler instanceof ValueSerializer>) {
- return (ValueSerializer>) sqlHandler;
- }
- // must be class name otherwise
- return (ValueSerializer>) instantiate((String) sqlHandler, type);
- }
if (className.startsWith(PACKAGE_PREFIX_JAVAX_XML) || hasSuperClassStartingWith(rawType, PACKAGE_PREFIX_JAVAX_XML)) {
if (Duration.class.isAssignableFrom(rawType) || QName.class.isAssignableFrom(rawType)) {
return ToStringSerializer.instance;
@@ -103,7 +52,7 @@ public ValueSerializer> findSerializer(SerializationConfig config, JavaType ty
return XMLGregorianCalendarSerializer.instance;
}
}
- return null;
+ return JavaSqlTypeHandlerFactory.instance.findSerializer(config, type);
}
public ValueDeserializer> findDeserializer(DeserializationConfig config, JavaType type)
@@ -116,15 +65,11 @@ public ValueDeserializer> findDeserializer(DeserializationConfig config, JavaT
return new DOMDeserializer.DocumentDeserializer();
}
String className = rawType.getName();
- final String deserName = _sqlDeserializers.get(className);
- if (deserName != null) {
- return (ValueDeserializer>) instantiate(deserName, type);
- }
if (className.startsWith(PACKAGE_PREFIX_JAVAX_XML)
|| hasSuperClassStartingWith(rawType, PACKAGE_PREFIX_JAVAX_XML)) {
return CoreXMLDeserializers.findBeanDeserializer(config, type);
}
- return null;
+ return JavaSqlTypeHandlerFactory.instance.findDeserializer(config, type);
}
public boolean hasDeserializerFor(Class> valueType) {
@@ -140,8 +85,7 @@ public boolean hasDeserializerFor(Class> valueType) {
|| hasSuperClassStartingWith(valueType, PACKAGE_PREFIX_JAVAX_XML)) {
return CoreXMLDeserializers.hasDeserializerFor(valueType);
}
- // 06-Nov-2020, tatu: One of "java.sql" types?
- return _sqlDeserializers.containsKey(className);
+ return JavaSqlTypeHandlerFactory.instance.hasDeserializerFor(valueType);
}
private boolean _IsXOfY(Class> valueType, Class> expType) {
@@ -154,28 +98,6 @@ private boolean _IsXOfY(Class> valueType, Class> expType) {
/**********************************************************************
*/
- private Object instantiate(String className, JavaType valueType)
- {
- try {
- return instantiate(Class.forName(className), valueType);
- } catch (Exception e) {
- throw new IllegalStateException("Failed to find class `"
-+className+"` for handling values of type "+ClassUtil.getTypeDescription(valueType)
-+", problem: ("+e.getClass().getName()+") "+e.getMessage());
- }
- }
-
- private Object instantiate(Class> handlerClass, JavaType valueType)
- {
- try {
- return ClassUtil.createInstance(handlerClass, false);
- } catch (Exception e) {
- throw new IllegalStateException("Failed to create instance of `"
-+handlerClass.getName()+"` for handling values of type "+ClassUtil.getTypeDescription(valueType)
-+", problem: ("+e.getClass().getName()+") "+e.getMessage());
- }
- }
-
/**
* Since 2.7 we only need to check for class extension, as all implemented
* types are classes, not interfaces. This has performance implications for
diff --git a/src/main/java/tools/jackson/databind/ext/beans/JavaBeansAnnotations.java b/src/main/java/tools/jackson/databind/ext/beans/JavaBeansAnnotations.java
index a990230451..5f55468b01 100644
--- a/src/main/java/tools/jackson/databind/ext/beans/JavaBeansAnnotations.java
+++ b/src/main/java/tools/jackson/databind/ext/beans/JavaBeansAnnotations.java
@@ -8,8 +8,8 @@
/**
* Since 2 JDK7-added annotations were left out of JDK 9+ core modules,
- * moved into "java.beans", support for them will be left as dynamic
- * for Jackson 3.x, and handled via this class
+ * moved into "java.beans" (module {@code java.desktop}), support for them
+ * will be left as dynamic for Jackson 3.x, and handled via this class
*/
public abstract class JavaBeansAnnotations
{
diff --git a/src/main/java/tools/jackson/databind/ext/sql/JavaSqlTypeHandlerFactory.java b/src/main/java/tools/jackson/databind/ext/sql/JavaSqlTypeHandlerFactory.java
new file mode 100644
index 0000000000..0796ba6a19
--- /dev/null
+++ b/src/main/java/tools/jackson/databind/ext/sql/JavaSqlTypeHandlerFactory.java
@@ -0,0 +1,123 @@
+package tools.jackson.databind.ext.sql;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import tools.jackson.databind.*;
+import tools.jackson.databind.ser.jdk.JavaUtilDateSerializer;
+import tools.jackson.databind.util.ClassUtil;
+
+/**
+ * Helper class used for isolating details of handling optional+external types
+ * (java.sql classes) from standard factories that offer them.
+ */
+public class JavaSqlTypeHandlerFactory
+{
+ public final static JavaSqlTypeHandlerFactory instance = new JavaSqlTypeHandlerFactory();
+
+ // classes from java.sql module, this module may or may not be present at runtime
+ // (is included on Java 8, but not part of JDK core for Java 9 and beyond)
+ private final Map _sqlDeserializers;
+ private final Map _sqlSerializers;
+
+ private final static String CLS_NAME_JAVA_SQL_TIMESTAMP = "java.sql.Timestamp";
+ private final static String CLS_NAME_JAVA_SQL_DATE = "java.sql.Date";
+ private final static String CLS_NAME_JAVA_SQL_TIME = "java.sql.Time";
+ private final static String CLS_NAME_JAVA_SQL_BLOB = "java.sql.Blob";
+ private final static String CLS_NAME_JAVA_SQL_SERIALBLOB = "javax.sql.rowset.serial.SerialBlob";
+
+ protected JavaSqlTypeHandlerFactory() {
+ _sqlDeserializers = new HashMap<>();
+ _sqlDeserializers.put(CLS_NAME_JAVA_SQL_DATE,
+ "tools.jackson.databind.ext.sql.JavaSqlDateDeserializer");
+ _sqlDeserializers.put(CLS_NAME_JAVA_SQL_TIMESTAMP,
+ "tools.jackson.databind.ext.sql.JavaSqlTimestampDeserializer");
+ // 09-Nov-2020, tatu: No deserializer for `java.sql.Blob` yet; would require additional
+ // dependency and not yet requested by anyone. Add if requested
+
+ _sqlSerializers = new HashMap<>();
+ // 09-Jan-2015, tatu: As per [databind#1073], let's try to guard against possibility
+ // of some environments missing `java.sql.` types
+
+ // note: timestamps are very similar to java.util.Date, thus serialized as such
+ _sqlSerializers.put(CLS_NAME_JAVA_SQL_TIMESTAMP, JavaUtilDateSerializer.instance);
+ _sqlSerializers.put(CLS_NAME_JAVA_SQL_DATE, "tools.jackson.databind.ext.sql.JavaSqlDateSerializer");
+ _sqlSerializers.put(CLS_NAME_JAVA_SQL_TIME, "tools.jackson.databind.ext.sql.JavaSqlTimeSerializer");
+
+ // 09-Nov-2020, tatu: Not really optimal way to deal with these, problem being that
+ // Blob is interface and actual instance we get is usually different. So may
+ // need to improve if we reported bugs. But for now, do this
+
+ _sqlSerializers.put(CLS_NAME_JAVA_SQL_BLOB, "tools.jackson.databind.ext.sql.JavaSqlBlobSerializer");
+ _sqlSerializers.put(CLS_NAME_JAVA_SQL_SERIALBLOB, "tools.jackson.databind.ext.sql.JavaSqlBlobSerializer");
+ }
+
+ /*
+ /**********************************************************************
+ /* Public API
+ /**********************************************************************
+ */
+
+ public ValueSerializer> findSerializer(SerializationConfig config, JavaType type)
+ {
+ final Class> rawType = type.getRawClass();
+
+ String className = rawType.getName();
+ Object sqlHandler = _sqlSerializers.get(className);
+
+ if (sqlHandler != null) {
+ if (sqlHandler instanceof ValueSerializer>) {
+ return (ValueSerializer>) sqlHandler;
+ }
+ // must be class name otherwise
+ return (ValueSerializer>) instantiate((String) sqlHandler, type);
+ }
+ return null;
+ }
+
+ public ValueDeserializer> findDeserializer(DeserializationConfig config, JavaType type)
+ {
+ final Class> rawType = type.getRawClass();
+ String className = rawType.getName();
+ final String deserName = _sqlDeserializers.get(className);
+ if (deserName != null) {
+ return (ValueDeserializer>) instantiate(deserName, type);
+ }
+ return null;
+ }
+
+ public boolean hasDeserializerFor(Class> valueType) {
+ String className = valueType.getName();
+
+ // 06-Nov-2020, tatu: One of "java.sql" types?
+ return _sqlDeserializers.containsKey(className);
+ }
+
+ /*
+ /**********************************************************************
+ /* Internal helper methods
+ /**********************************************************************
+ */
+
+ private Object instantiate(String className, JavaType valueType)
+ {
+ try {
+ return instantiate(Class.forName(className), valueType);
+ } catch (Exception e) {
+ throw new IllegalStateException("Failed to find class `"
++className+"` for handling values of type "+ClassUtil.getTypeDescription(valueType)
++", problem: ("+e.getClass().getName()+") "+e.getMessage());
+ }
+ }
+
+ private Object instantiate(Class> handlerClass, JavaType valueType)
+ {
+ try {
+ return ClassUtil.createInstance(handlerClass, false);
+ } catch (Exception e) {
+ throw new IllegalStateException("Failed to create instance of `"
++handlerClass.getName()+"` for handling values of type "+ClassUtil.getTypeDescription(valueType)
++", problem: ("+e.getClass().getName()+") "+e.getMessage());
+ }
+ }
+}