Skip to content

Commit

Permalink
Merge branch 'master' into tatu/3.0/4891-rm-moditect-add-module-info
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Jan 11, 2025
2 parents 1f8a02d + c37d0f8 commit e4647e6
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 87 deletions.
Original file line number Diff line number Diff line change
@@ -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.
*<p>
* 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
Expand All @@ -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<String, String> _sqlDeserializers;
private final Map<String, Object> _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");
}

/*
Expand All @@ -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;
Expand All @@ -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)
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String, String> _sqlDeserializers;
private final Map<String, Object> _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());
}
}
}

0 comments on commit e4647e6

Please sign in to comment.