Merge remote-tracking branch 'upstream/master' into ebean-new

# Conflicts:
#	ebean-core/src/main/java/io/ebeaninternal/server/core/DScriptRunner.java
#	ebean-core/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java
#	ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/DdlPlugin.java
#	ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/DefaultDbMigration.java
#	ebean-test/src/test/java/io/ebean/json/EJsonTests.java
This commit is contained in:
Roland Praml
2022-01-13 13:54:40 +01:00
9 changed files with 216 additions and 46 deletions
@@ -67,7 +67,7 @@ final class DScriptRunner implements ScriptRunner {
}
try (InputStream inputStream = UrlHelper.openNoCache(resource);
Reader reader = IOUtils.newReader(inputStream)) {
Reader reader = IOUtils.newReader(inputStream)) {
return readContent(reader);
} catch (IOException e) {
@@ -200,7 +200,7 @@ public final class DefaultTypeManager implements TypeManager {
List<? extends ScalarType<?>> types = plugin.createTypes(config, objectMapper);
for (ScalarType<?> type : types) {
log.debug("adding ScalarType {}", type.getClass());
addCustomType(type);
add(type);
}
}
}
@@ -218,25 +218,6 @@ public final class DefaultTypeManager implements TypeManager {
logAdd(scalarType);
}
/**
* Register the ScalarType for an enum. This is special in the sense that an Enum
* can have many classes if it uses method overrides and we need to register all
* the variations/classes for the enum.
*/
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public void addEnumType(ScalarType<?> scalarType, Class<? extends Enum> enumClass) {
Set<Class<?>> mappedClasses = new HashSet<>();
mappedClasses.add(enumClass);
for (Object value : EnumSet.allOf(enumClass).toArray()) {
mappedClasses.add(value.getClass());
}
for (Class<?> cls : mappedClasses) {
typeMap.put(cls, scalarType);
}
logAdd(scalarType);
}
private void logAdd(ScalarType<?> scalarType) {
if (log.isTraceEnabled()) {
String msg = "ScalarType register [" + scalarType.getClass().getName() + "]";
@@ -282,19 +263,44 @@ public final class DefaultTypeManager implements TypeManager {
"ScalarType of Joda LocalTime not defined. You need to set DatabaseConfig.jodaLocalTimeMode to"
+ " either 'normal' or 'utc'. UTC is the old mode using UTC timezone but local time zone is now preferred as 'normal' mode.");
}
found = checkInterfaceTypes(type);
found = checkInheritedTypes(type);
}
return found;
return found != ScalarTypeNotFound.INSTANCE ? found : null; // Do not return ScalarTypeNotFound, otherwise checks will fail
}
private ScalarType<?> checkInterfaceTypes(Class<?> type) {
for (Entry<Class<?>, ScalarType<?>> entry : typeMap.entrySet()) {
if (entry.getKey().isAssignableFrom(type)) {
typeMap.put(type, entry.getValue());
return entry.getValue();
/**
* Checks the typeMap for inherited types.
*
* If e.g. <code>type</code> is a <code>GregorianCalendar</code>, then this method
* will check the class hierarchy and will probably return a
* <code>ScalarTypeCalendar</code> To speed up a second lookup, it will write
* back the found scalarType to typeMap.
*
* @param type the for which to search for a <code>ScalarType</code>
* @return either a valid <code>ScalarType</code> if one could be found or {@link ScalarTypeNotFound#INSTANCE} if not
*/
private ScalarType<?> checkInheritedTypes(Class<?> type) {
// first step loop through inheritance chain
Class<?> parent = type;
while (parent != null && parent != Object.class) {
ScalarType<?> found = typeMap.get(parent);
if (found != null && found != ScalarTypeNotFound.INSTANCE) {
typeMap.put(type, found); // store type for next lookup
return found;
}
// second step - loop through interfaces of this type
for (Class<?> iface: parent.getInterfaces()) {
found = checkInheritedTypes(iface);
if (found != null && found != ScalarTypeNotFound.INSTANCE) {
typeMap.put(type, found); // store type for next lookup
return found;
}
}
parent = parent.getSuperclass();
}
return null;
typeMap.put(type, ScalarTypeNotFound.INSTANCE);
return ScalarTypeNotFound.INSTANCE; // no success
}
@Override
@@ -399,7 +405,7 @@ public final class DefaultTypeManager implements TypeManager {
private DocPropertyType getDocType(Type genericType) {
if (genericType instanceof Class<?>) {
ScalarType<?> found = typeMap.get(genericType);
ScalarType<?> found = getScalarType((Class<?>)genericType);
if (found != null) {
return found.getDocType();
}
@@ -457,7 +463,7 @@ public final class DefaultTypeManager implements TypeManager {
return scalarType;
}
scalarType = typeMap.get(type);
scalarType = getScalarType(type);
if (scalarType != null) {
if (jdbcType == 0 || scalarType.getJdbcType() == jdbcType) {
// matching type
@@ -575,7 +581,7 @@ public final class DefaultTypeManager implements TypeManager {
// use JPA normal Enum type (without mapping)
scalarEnum = createEnumScalarTypePerSpec(enumType, type);
}
addEnumType(scalarEnum, enumType);
add(scalarEnum);
return scalarEnum;
}
@@ -665,16 +671,13 @@ public final class DefaultTypeManager implements TypeManager {
scalarType = cls.getDeclaredConstructor().newInstance();
}
}
addCustomType(scalarType);
add(scalarType);
} catch (Exception e) {
log.error("Error loading ScalarType [" + cls.getName() + "]", e);
}
}
}
private void addCustomType(ScalarType<?> scalarType) {
add(scalarType);
}
private Object initObjectMapper(DatabaseConfig config) {
Object objectMapper = config.getObjectMapper();
@@ -0,0 +1,140 @@
package io.ebeaninternal.server.type;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.sql.SQLException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
import io.ebean.core.type.ScalarType;
/**
* Class is required as "null" key in ConcurrentHashMap.
* @author Roland Praml, FOCONIS AG
*
*/
class ScalarTypeNotFound implements ScalarType<Void> {
public static final ScalarTypeNotFound INSTANCE = new ScalarTypeNotFound();
private ScalarTypeNotFound() { }
@Override
public boolean isBinaryType() {
throw new UnsupportedOperationException();
}
@Override
public boolean isMutable() {
throw new UnsupportedOperationException();
}
@Override
public boolean isDirty(Object value) {
throw new UnsupportedOperationException();
}
@Override
public int getLength() {
throw new UnsupportedOperationException();
}
@Override
public boolean isJdbcNative() {
throw new UnsupportedOperationException();
}
@Override
public int getJdbcType() {
throw new UnsupportedOperationException();
}
@Override
public Class<Void> getType() {
throw new UnsupportedOperationException();
}
@Override
public Void read(DataReader reader) throws SQLException {
throw new UnsupportedOperationException();
}
@Override
public void loadIgnore(DataReader reader) {
throw new UnsupportedOperationException();
}
@Override
public void bind(DataBinder binder, Void value) throws SQLException {
throw new UnsupportedOperationException();
}
@Override
public Object toJdbcType(Object value) {
throw new UnsupportedOperationException();
}
@Override
public Void toBeanType(Object value) {
throw new UnsupportedOperationException();
}
@Override
public String formatValue(Void value) {
throw new UnsupportedOperationException();
}
@Override
public String format(Object value) {
throw new UnsupportedOperationException();
}
@Override
public Void parse(String value) {
throw new UnsupportedOperationException();
}
@Override
public DocPropertyType getDocType() {
throw new UnsupportedOperationException();
}
@Override
public boolean isDateTimeCapable() {
throw new UnsupportedOperationException();
}
@Override
public long asVersion(Void value) {
throw new UnsupportedOperationException();
}
@Override
public Void convertFromMillis(long dateTime) {
throw new UnsupportedOperationException();
}
@Override
public Void readData(DataInput dataInput) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void writeData(DataOutput dataOutput, Void v) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public Void jsonRead(JsonParser parser) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void jsonWrite(JsonGenerator writer, Void value) throws IOException {
throw new UnsupportedOperationException();
}
}
@@ -17,12 +17,6 @@ public interface TypeManager {
*/
void add(ScalarType<?> scalarType);
/**
* Register a ScalarType for an Enum with can have multiple classes.
*/
@SuppressWarnings("rawtypes")
void addEnumType(ScalarType<?> type, Class<? extends Enum> myEnumClass);
/**
* Return the scalar type for the given logical type.
*/