diff --git a/engine-tests/src/main/java/org/terasology/HeadlessEnvironment.java b/engine-tests/src/main/java/org/terasology/HeadlessEnvironment.java index 4e9bc1fe529..f83220a2118 100644 --- a/engine-tests/src/main/java/org/terasology/HeadlessEnvironment.java +++ b/engine-tests/src/main/java/org/terasology/HeadlessEnvironment.java @@ -64,6 +64,8 @@ import org.terasology.recording.RecordAndReplayCurrentStatus; import org.terasology.recording.RecordAndReplaySerializer; import org.terasology.recording.RecordAndReplayUtils; +import org.terasology.reflection.TypeRegistry; +import org.terasology.reflection.internal.TypeRegistryImpl; import org.terasology.rendering.assets.animation.MeshAnimation; import org.terasology.rendering.assets.animation.MeshAnimationImpl; import org.terasology.rendering.assets.atlas.Atlas; @@ -267,7 +269,10 @@ protected void setupConfig() { @Override protected void setupModuleManager(Set moduleNames) throws Exception { - ModuleManager moduleManager = ModuleManagerFactory.create(); + TypeRegistryImpl typeRegistry = new TypeRegistryImpl(); + context.put(TypeRegistry.class, typeRegistry); + + ModuleManager moduleManager = ModuleManagerFactory.create(typeRegistry); ModuleRegistry registry = moduleManager.getRegistry(); DependencyResolver resolver = new DependencyResolver(registry); diff --git a/engine-tests/src/main/java/org/terasology/ModuleEnvironmentTest.java b/engine-tests/src/main/java/org/terasology/ModuleEnvironmentTest.java index af92ca7eacc..cf746d0e7cc 100644 --- a/engine-tests/src/main/java/org/terasology/ModuleEnvironmentTest.java +++ b/engine-tests/src/main/java/org/terasology/ModuleEnvironmentTest.java @@ -24,6 +24,7 @@ import org.terasology.engine.paths.PathManager; import org.terasology.module.DependencyResolver; import org.terasology.module.ResolutionResult; +import org.terasology.reflection.TypeRegistry; import org.terasology.reflection.internal.TypeRegistryImpl; import org.terasology.testUtil.ModuleManagerFactory; @@ -33,14 +34,16 @@ public abstract class ModuleEnvironmentTest { protected ModuleManager moduleManager; + protected TypeRegistry typeRegistry; @Before - public void setup() throws Exception { + public void before() throws Exception { final JavaArchive homeArchive = ShrinkWrap.create(JavaArchive.class); final FileSystem vfs = ShrinkWrapFileSystems.newFileSystem(homeArchive); PathManager.getInstance().useOverrideHomePath(vfs.getPath("")); - moduleManager = ModuleManagerFactory.create(getTypeRegistry()); + typeRegistry = new TypeRegistryImpl(); + moduleManager = ModuleManagerFactory.create((TypeRegistryImpl) typeRegistry); DependencyResolver resolver = new DependencyResolver(moduleManager.getRegistry()); ResolutionResult result = resolver.resolve(moduleManager.getRegistry().getModuleIds()); @@ -48,9 +51,11 @@ public void setup() throws Exception { assumeTrue(result.isSuccess()); moduleManager.loadEnvironment(result.getModules(), true); + + setup(); } - protected TypeRegistryImpl getTypeRegistry() { - return Mockito.mock(TypeRegistryImpl.class); + protected void setup() { + } } diff --git a/engine-tests/src/main/java/org/terasology/TerasologyTestingEnvironment.java b/engine-tests/src/main/java/org/terasology/TerasologyTestingEnvironment.java index 56698402563..b9f57c196ba 100644 --- a/engine-tests/src/main/java/org/terasology/TerasologyTestingEnvironment.java +++ b/engine-tests/src/main/java/org/terasology/TerasologyTestingEnvironment.java @@ -45,6 +45,7 @@ import org.terasology.recording.RecordAndReplaySerializer; import org.terasology.recording.RecordAndReplayUtils; import org.terasology.recording.RecordedEventStore; +import org.terasology.reflection.TypeRegistry; import org.terasology.world.block.BlockManager; import org.terasology.world.chunks.blockdata.ExtraBlockDataManager; @@ -104,7 +105,7 @@ public void setup() throws Exception { context.put(CharacterStateEventPositionMap.class, characterStateEventPositionMap); DirectionAndOriginPosRecorderList directionAndOriginPosRecorderList = new DirectionAndOriginPosRecorderList(); context.put(DirectionAndOriginPosRecorderList.class, directionAndOriginPosRecorderList); - RecordAndReplaySerializer recordAndReplaySerializer = new RecordAndReplaySerializer(engineEntityManager, recordedEventStore, recordAndReplayUtils, characterStateEventPositionMap, directionAndOriginPosRecorderList, moduleManager); + RecordAndReplaySerializer recordAndReplaySerializer = new RecordAndReplaySerializer(engineEntityManager, recordedEventStore, recordAndReplayUtils, characterStateEventPositionMap, directionAndOriginPosRecorderList, moduleManager, context.get(TypeRegistry.class)); context.put(RecordAndReplaySerializer.class, recordAndReplaySerializer); Path savePath = PathManager.getInstance().getSavePath("world1"); diff --git a/engine-tests/src/test/java/org/terasology/persistence/internal/StorageManagerTest.java b/engine-tests/src/test/java/org/terasology/persistence/internal/StorageManagerTest.java index fc5a27855a4..9405ccfbe41 100644 --- a/engine-tests/src/test/java/org/terasology/persistence/internal/StorageManagerTest.java +++ b/engine-tests/src/test/java/org/terasology/persistence/internal/StorageManagerTest.java @@ -51,6 +51,7 @@ import org.terasology.recording.RecordAndReplaySerializer; import org.terasology.recording.RecordAndReplayUtils; import org.terasology.recording.RecordedEventStore; +import org.terasology.reflection.TypeRegistry; import org.terasology.registry.CoreRegistry; import org.terasology.world.WorldProvider; import org.terasology.world.block.Block; @@ -121,7 +122,7 @@ public void setup() throws Exception { recordAndReplayUtils = new RecordAndReplayUtils(); CharacterStateEventPositionMap characterStateEventPositionMap = new CharacterStateEventPositionMap(); DirectionAndOriginPosRecorderList directionAndOriginPosRecorderList = new DirectionAndOriginPosRecorderList(); - recordAndReplaySerializer = new RecordAndReplaySerializer(entityManager, recordedEventStore, recordAndReplayUtils, characterStateEventPositionMap, directionAndOriginPosRecorderList, moduleManager); + recordAndReplaySerializer = new RecordAndReplaySerializer(entityManager, recordedEventStore, recordAndReplayUtils, characterStateEventPositionMap, directionAndOriginPosRecorderList, moduleManager, mock(TypeRegistry.class)); recordAndReplayCurrentStatus = context.get(RecordAndReplayCurrentStatus.class); diff --git a/engine-tests/src/test/java/org/terasology/persistence/serializers/TypeSerializerTest.java b/engine-tests/src/test/java/org/terasology/persistence/serializers/TypeSerializerTest.java index 4d7ea8a068c..23e3c4bf661 100644 --- a/engine-tests/src/test/java/org/terasology/persistence/serializers/TypeSerializerTest.java +++ b/engine-tests/src/test/java/org/terasology/persistence/serializers/TypeSerializerTest.java @@ -17,27 +17,18 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; -import org.jboss.shrinkwrap.api.ShrinkWrap; -import org.jboss.shrinkwrap.api.nio.file.ShrinkWrapFileSystems; -import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.junit.Before; import org.junit.Test; -import org.terasology.engine.module.ModuleManager; -import org.terasology.engine.paths.PathManager; +import org.terasology.ModuleEnvironmentTest; import org.terasology.math.geom.Vector3f; -import org.terasology.module.DependencyResolver; -import org.terasology.module.ModuleEnvironment; -import org.terasology.module.ResolutionResult; import org.terasology.naming.Name; import org.terasology.persistence.ModuleContext; import org.terasology.persistence.typeHandling.TypeHandlerLibrary; import org.terasology.persistence.typeHandling.annotations.SerializedName; import org.terasology.reflection.TypeInfo; import org.terasology.rendering.nui.Color; -import org.terasology.testUtil.ModuleManagerFactory; import java.io.IOException; -import java.nio.file.FileSystem; import java.util.List; import java.util.Objects; import java.util.Set; @@ -45,9 +36,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assume.assumeTrue; -public class TypeSerializerTest { +public class TypeSerializerTest extends ModuleEnvironmentTest { private static final SomeClass INSTANCE = new SomeClass<>(0xdeadbeef); - private static final String INSTANCE_JSON = "{\"generic-t\":-559038737,\"list\":[50,51,-52,-53],\"animals\":[{\"class\":\"org.terasology.persistence.serializers.TypeSerializerTest$Dog\",\"tailPosition\":[3.15,54.51,-0.001],\"data\":1},{\"class\":\"org.terasology.persistence.serializers.TypeSerializerTest$Cheetah\",\"spotColor\":[255,0,255,255],\"data\":2}]}"; + private static final String INSTANCE_JSON = "{\"generic-t\":-559038737,\"list\":[50,51,-52,-53],\"animals\":[{\"class\":\"org.terasology.persistence.serializers.TypeSerializerTest$Dog\",\"tailPosition\":[3.15,54.51,-0.001],\"data\":{\"class\":\"java.lang.Integer\",\"content\":1}},{\"class\":\"org.terasology.persistence.serializers.TypeSerializerTest$Cheetah\",\"spotColor\":[255,0,255,255],\"data\":{\"class\":\"java.lang.Integer\",\"content\":2}}]}"; static { INSTANCE.list.addAll(Lists.newArrayList(50, 51, -52, -53)); @@ -61,23 +52,11 @@ public class TypeSerializerTest { private ProtobufSerializer protobufSerializer; private GsonSerializer gsonSerializer; - @Before - public void setup() throws Exception { - final JavaArchive homeArchive = ShrinkWrap.create(JavaArchive.class); - final FileSystem vfs = ShrinkWrapFileSystems.newFileSystem(homeArchive); - PathManager.getInstance().useOverrideHomePath(vfs.getPath("")); + @Override + public void setup() { + ModuleContext.setContext(moduleManager.getEnvironment().get(new Name("unittest"))); - ModuleManager moduleManager = ModuleManagerFactory.create(); - - DependencyResolver resolver = new DependencyResolver(moduleManager.getRegistry()); - ResolutionResult result = resolver.resolve(moduleManager.getRegistry().getModuleIds()); - - assumeTrue(result.isSuccess()); - - ModuleEnvironment environment = moduleManager.loadEnvironment(result.getModules(), true); - ModuleContext.setContext(environment.get(new Name("unittest"))); - - typeHandlerLibrary = TypeHandlerLibrary.forModuleEnvironment(moduleManager); + typeHandlerLibrary = TypeHandlerLibrary.forModuleEnvironment(moduleManager, typeRegistry); protobufSerializer = new ProtobufSerializer(typeHandlerLibrary); gsonSerializer = new GsonSerializer(typeHandlerLibrary); diff --git a/engine-tests/src/test/java/org/terasology/recording/EventSystemReplayImplTest.java b/engine-tests/src/test/java/org/terasology/recording/EventSystemReplayImplTest.java index 7a6b41459ad..7b86025035a 100644 --- a/engine-tests/src/test/java/org/terasology/recording/EventSystemReplayImplTest.java +++ b/engine-tests/src/test/java/org/terasology/recording/EventSystemReplayImplTest.java @@ -37,6 +37,7 @@ import org.terasology.network.NetworkMode; import org.terasology.network.NetworkSystem; import org.terasology.persistence.typeHandling.TypeHandlerLibrary; +import org.terasology.reflection.TypeRegistry; import org.terasology.registry.CoreRegistry; import java.util.ArrayList; @@ -77,7 +78,7 @@ public void setup() { ModuleManager moduleManager = mock(ModuleManager.class); when(moduleManager.getEnvironment()).thenReturn(mock(ModuleEnvironment.class)); RecordAndReplaySerializer recordAndReplaySerializer = new RecordAndReplaySerializer(entityManager, eventStore, - recordAndReplayUtils, characterStateEventPositionMap, directionAndOriginPosRecorderList, moduleManager); + recordAndReplayUtils, characterStateEventPositionMap, directionAndOriginPosRecorderList, moduleManager, mock(TypeRegistry.class)); recordAndReplayCurrentStatus.setStatus(RecordAndReplayStatus.REPLAYING); entity = entityManager.create(); Long id = entity.getId(); diff --git a/engine-tests/src/test/java/org/terasology/reflection/internal/TypeRegistryImplTest.java b/engine-tests/src/test/java/org/terasology/reflection/internal/TypeRegistryImplTest.java index f6a2d3a6cdb..370d199ce93 100644 --- a/engine-tests/src/test/java/org/terasology/reflection/internal/TypeRegistryImplTest.java +++ b/engine-tests/src/test/java/org/terasology/reflection/internal/TypeRegistryImplTest.java @@ -33,13 +33,6 @@ public class TypeRegistryImplTest extends ModuleEnvironmentTest { Reflections.log = null; } - private TypeRegistryImpl typeRegistry = new TypeRegistryImpl(); - - @Override - protected TypeRegistryImpl getTypeRegistry() { - return typeRegistry; - } - @Test public void testRegistry() { assertTrue(typeRegistry.getSubtypesOf(Collection.class).contains(TreeSet.class)); diff --git a/engine/src/main/java/org/terasology/engine/TerasologyEngine.java b/engine/src/main/java/org/terasology/engine/TerasologyEngine.java index ee79fda938c..8da21ae3dd6 100644 --- a/engine/src/main/java/org/terasology/engine/TerasologyEngine.java +++ b/engine/src/main/java/org/terasology/engine/TerasologyEngine.java @@ -321,7 +321,7 @@ private void initManagers() { CopyStrategyLibrary copyStrategyLibrary = new CopyStrategyLibrary(reflectFactory); rootContext.put(CopyStrategyLibrary.class, copyStrategyLibrary); - rootContext.put(TypeHandlerLibrary.class, TypeHandlerLibrary.forModuleEnvironment(moduleManager)); + rootContext.put(TypeHandlerLibrary.class, TypeHandlerLibrary.forModuleEnvironment(moduleManager, typeRegistry)); changeStatus(TerasologyEngineStatus.INITIALIZING_ASSET_TYPES); assetTypeManager = new ModuleAwareAssetTypeManager(); diff --git a/engine/src/main/java/org/terasology/engine/bootstrap/EntitySystemSetupUtil.java b/engine/src/main/java/org/terasology/engine/bootstrap/EntitySystemSetupUtil.java index 77ba5011923..f30800a5998 100644 --- a/engine/src/main/java/org/terasology/engine/bootstrap/EntitySystemSetupUtil.java +++ b/engine/src/main/java/org/terasology/engine/bootstrap/EntitySystemSetupUtil.java @@ -51,6 +51,7 @@ import org.terasology.recording.RecordAndReplayStatus; import org.terasology.recording.RecordAndReplayUtils; import org.terasology.recording.RecordedEventStore; +import org.terasology.reflection.TypeRegistry; import org.terasology.reflection.copy.CopyStrategyLibrary; import org.terasology.reflection.reflect.ReflectFactory; import org.terasology.reflection.reflect.ReflectionReflectFactory; @@ -76,7 +77,8 @@ public static void addReflectionBasedLibraries(Context context) { context.put(CopyStrategyLibrary.class, copyStrategyLibrary); ModuleManager moduleManager = context.get(ModuleManager.class); - TypeHandlerLibrary typeHandlerLibrary = TypeHandlerLibrary.forModuleEnvironment(moduleManager); + TypeRegistry typeRegistry = context.get(TypeRegistry.class); + TypeHandlerLibrary typeHandlerLibrary = TypeHandlerLibrary.forModuleEnvironment(moduleManager, typeRegistry); context.put(TypeHandlerLibrary.class, typeHandlerLibrary); EntitySystemLibrary library = new EntitySystemLibrary(context, typeHandlerLibrary); @@ -134,7 +136,7 @@ public static void addEntityManagementRelatedClasses(Context context) { CharacterStateEventPositionMap characterStateEventPositionMap = context.get(CharacterStateEventPositionMap.class); DirectionAndOriginPosRecorderList directionAndOriginPosRecorderList = context.get(DirectionAndOriginPosRecorderList.class); RecordedEventStore recordedEventStore = new RecordedEventStore(); - RecordAndReplaySerializer recordAndReplaySerializer = new RecordAndReplaySerializer(entityManager, recordedEventStore, recordAndReplayUtils, characterStateEventPositionMap, directionAndOriginPosRecorderList, moduleManager); + RecordAndReplaySerializer recordAndReplaySerializer = new RecordAndReplaySerializer(entityManager, recordedEventStore, recordAndReplayUtils, characterStateEventPositionMap, directionAndOriginPosRecorderList, moduleManager, context.get(TypeRegistry.class)); context.put(RecordAndReplaySerializer.class, recordAndReplaySerializer); diff --git a/engine/src/main/java/org/terasology/persistence/typeHandling/TypeHandlerLibrary.java b/engine/src/main/java/org/terasology/persistence/typeHandling/TypeHandlerLibrary.java index 962b463090b..f74f65787af 100644 --- a/engine/src/main/java/org/terasology/persistence/typeHandling/TypeHandlerLibrary.java +++ b/engine/src/main/java/org/terasology/persistence/typeHandling/TypeHandlerLibrary.java @@ -30,7 +30,6 @@ import org.terasology.math.geom.Vector3f; import org.terasology.math.geom.Vector3i; import org.terasology.math.geom.Vector4f; -import org.terasology.module.ModuleEnvironment; import org.terasology.naming.Name; import org.terasology.persistence.typeHandling.coreTypes.BooleanTypeHandler; import org.terasology.persistence.typeHandling.coreTypes.ByteArrayTypeHandler; @@ -67,12 +66,12 @@ import org.terasology.persistence.typeHandling.reflection.ReflectionsSandbox; import org.terasology.persistence.typeHandling.reflection.SerializationSandbox; import org.terasology.reflection.TypeInfo; +import org.terasology.reflection.TypeRegistry; import org.terasology.reflection.metadata.ClassMetadata; import org.terasology.reflection.metadata.FieldMetadata; import org.terasology.reflection.reflect.ConstructorLibrary; import org.terasology.rendering.assets.texture.TextureRegion; import org.terasology.rendering.nui.Color; -import org.terasology.utilities.ReflectionUtil; import java.lang.reflect.Type; import java.util.HashMap; @@ -148,8 +147,8 @@ public TypeHandlerLibrary(Reflections reflections) { this(new ReflectionsSandbox(reflections)); } - public TypeHandlerLibrary(ModuleManager moduleManager) { - this(new ModuleEnvironmentSandbox(moduleManager)); + public TypeHandlerLibrary(ModuleManager moduleManager, TypeRegistry typeRegistry) { + this(new ModuleEnvironmentSandbox(moduleManager, typeRegistry)); } /** @@ -172,8 +171,8 @@ public static TypeHandlerLibrary withReflections(Reflections reflections) { return library; } - public static TypeHandlerLibrary forModuleEnvironment(ModuleManager moduleManager) { - TypeHandlerLibrary library = new TypeHandlerLibrary(moduleManager); + public static TypeHandlerLibrary forModuleEnvironment(ModuleManager moduleManager, TypeRegistry typeRegistry) { + TypeHandlerLibrary library = new TypeHandlerLibrary(moduleManager, typeRegistry); populateWithDefaultHandlers(library); diff --git a/engine/src/main/java/org/terasology/persistence/typeHandling/reflection/ModuleEnvironmentSandbox.java b/engine/src/main/java/org/terasology/persistence/typeHandling/reflection/ModuleEnvironmentSandbox.java index 6088953e30a..a1ef521706a 100644 --- a/engine/src/main/java/org/terasology/persistence/typeHandling/reflection/ModuleEnvironmentSandbox.java +++ b/engine/src/main/java/org/terasology/persistence/typeHandling/reflection/ModuleEnvironmentSandbox.java @@ -16,7 +16,6 @@ package org.terasology.persistence.typeHandling.reflection; import com.google.common.base.Preconditions; -import com.google.common.collect.Streams; import org.terasology.engine.SimpleUri; import org.terasology.engine.module.ModuleManager; import org.terasology.module.ModuleEnvironment; @@ -24,32 +23,40 @@ import org.terasology.persistence.ModuleContext; import org.terasology.persistence.typeHandling.TypeHandler; import org.terasology.reflection.TypeInfo; +import org.terasology.reflection.TypeRegistry; import java.util.Iterator; import java.util.Objects; import java.util.Optional; -import static com.google.common.collect.Streams.stream; - public class ModuleEnvironmentSandbox implements SerializationSandbox { - // TODO: Use TypeRegistry - + private final TypeRegistry typeRegistry; private final ModuleManager moduleManager; - public ModuleEnvironmentSandbox(ModuleManager moduleManager) { + public ModuleEnvironmentSandbox(ModuleManager moduleManager, TypeRegistry typeRegistry) { this.moduleManager = moduleManager; + this.typeRegistry = typeRegistry; } - private ModuleEnvironment getModuleEnvironment() { + private ModuleEnvironment getEnvironment() { return moduleManager.getEnvironment(); } @Override public Optional> findSubTypeOf(String subTypeIdentifier, Class clazz) { + if (getModuleProviding(clazz) == null) { + // Assume that subTypeIdentifier is full name + return typeRegistry.load(subTypeIdentifier) + // If loaded class is not a subtype, return empty + .filter(clazz::isAssignableFrom) + .map(sub -> (Class) sub); + } Iterator> possibilities = - getModuleEnvironment() - .getSubtypesOf(clazz, subclass -> doesSubclassMatch(subclass, subTypeIdentifier)) + typeRegistry + .getSubtypesOf(clazz) + .stream() + .filter(subclass -> doesSubclassMatch(subclass, subTypeIdentifier)) .iterator(); if (possibilities.hasNext()) { @@ -83,7 +90,7 @@ private boolean doesSubclassMatch(Class subclass, String subTypeIdentifier) { } // Now check through module and simple name - Name providingModule = getModuleEnvironment().getModuleProviding(subclass); + Name providingModule = getModuleProviding(subclass); Name givenModuleName; if (subTypeUri.isValid()) { @@ -100,7 +107,11 @@ private boolean doesSubclassMatch(Class subclass, String subTypeIdentifier) { public String getSubTypeIdentifier(Class subType, Class baseType) { String subTypeUri = getTypeUri(subType); - long subTypesWithSameUri = Streams.stream(getModuleEnvironment().getSubtypesOf(baseType)) + if (getModuleProviding(baseType) == null) { + return subType.getName(); + } + + long subTypesWithSameUri = typeRegistry.getSubtypesOf(baseType).stream() .map(this::getTypeUri) .filter(subTypeUri::equals) .count(); @@ -118,7 +129,7 @@ public String getSubTypeIdentifier(Class subType, Class base @Override public boolean isValidTypeHandlerDeclaration(TypeInfo type, TypeHandler typeHandler) { - Name moduleDeclaringHandler = getModuleEnvironment().getModuleProviding(typeHandler.getClass()); + Name moduleDeclaringHandler = getModuleProviding(typeHandler.getClass()); // If handler was declared outside of a module (engine or somewhere else), we allow it // TODO: Possibly find better way to refer to engine module @@ -133,18 +144,14 @@ public boolean isValidTypeHandlerDeclaration(TypeInfo type, TypeHandler type) { - if (type.getClassLoader() == null) { - return type.getName(); - } - - Name moduleProvidingType = getModuleEnvironment().getModuleProviding(type); + Name moduleProvidingType = getModuleProviding(type); if (moduleProvidingType == null || moduleProvidingType.isEmpty()) { return type.getName(); @@ -154,4 +161,12 @@ private String getTypeUri(Class type) { return new SimpleUri(moduleProvidingType, typeSimpleName).toString(); } + + private Name getModuleProviding(Class type) { + if (type.getClassLoader() == null) { + return null; + } + + return getEnvironment().getModuleProviding(type); + } } diff --git a/engine/src/main/java/org/terasology/recording/RecordAndReplaySerializer.java b/engine/src/main/java/org/terasology/recording/RecordAndReplaySerializer.java index 806dc42d6a1..fe88443df8a 100644 --- a/engine/src/main/java/org/terasology/recording/RecordAndReplaySerializer.java +++ b/engine/src/main/java/org/terasology/recording/RecordAndReplaySerializer.java @@ -27,7 +27,7 @@ import org.terasology.engine.paths.PathManager; import org.terasology.entitySystem.entity.EntityManager; import org.terasology.math.geom.Vector3f; -import org.terasology.module.ModuleEnvironment; +import org.terasology.reflection.TypeRegistry; import java.io.FileWriter; import java.io.FileReader; @@ -55,13 +55,15 @@ public final class RecordAndReplaySerializer { private RecordedEventSerializer recordedEventSerializer; public RecordAndReplaySerializer(EntityManager manager, RecordedEventStore store, - RecordAndReplayUtils recordAndReplayUtils, CharacterStateEventPositionMap characterStateEventPositionMap, - DirectionAndOriginPosRecorderList directionAndOriginPosRecorderList, ModuleManager moduleManager) { + RecordAndReplayUtils recordAndReplayUtils, + CharacterStateEventPositionMap characterStateEventPositionMap, + DirectionAndOriginPosRecorderList directionAndOriginPosRecorderList, + ModuleManager moduleManager, TypeRegistry typeRegistry) { this.recordedEventStore = store; this.recordAndReplayUtils = recordAndReplayUtils; this.characterStateEventPositionMap = characterStateEventPositionMap; this.directionAndOriginPosRecorderList = directionAndOriginPosRecorderList; - this.recordedEventSerializer = new RecordedEventSerializer(manager, moduleManager); + this.recordedEventSerializer = new RecordedEventSerializer(manager, moduleManager, typeRegistry); } /** diff --git a/engine/src/main/java/org/terasology/recording/RecordedEventSerializer.java b/engine/src/main/java/org/terasology/recording/RecordedEventSerializer.java index 14fe420e4db..92fe46da2ca 100644 --- a/engine/src/main/java/org/terasology/recording/RecordedEventSerializer.java +++ b/engine/src/main/java/org/terasology/recording/RecordedEventSerializer.java @@ -21,20 +21,17 @@ import org.terasology.entitySystem.entity.EntityManager; import org.terasology.entitySystem.entity.EntityRef; import org.terasology.entitySystem.entity.internal.EngineEntityManager; -import org.terasology.module.ModuleEnvironment; import org.terasology.persistence.serializers.GsonSerializer; -import org.terasology.persistence.typeHandling.PersistedData; import org.terasology.persistence.typeHandling.SerializationException; -import org.terasology.persistence.typeHandling.TypeHandler; import org.terasology.persistence.typeHandling.TypeHandlerLibrary; import org.terasology.persistence.typeHandling.extensionTypes.EntityRefTypeHandler; import org.terasology.reflection.TypeInfo; +import org.terasology.reflection.TypeRegistry; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.Optional; /** * Serializes and deserializes RecordedEvents. @@ -45,8 +42,8 @@ class RecordedEventSerializer { private GsonSerializer gsonSerializer; - public RecordedEventSerializer(EntityManager entityManager, ModuleManager moduleManager) { - TypeHandlerLibrary typeHandlerLibrary = TypeHandlerLibrary.forModuleEnvironment(moduleManager); + public RecordedEventSerializer(EntityManager entityManager, ModuleManager moduleManager, TypeRegistry typeRegistry) { + TypeHandlerLibrary typeHandlerLibrary = TypeHandlerLibrary.forModuleEnvironment(moduleManager, typeRegistry); typeHandlerLibrary.addTypeHandler(EntityRef.class, new EntityRefTypeHandler((EngineEntityManager) entityManager)); gsonSerializer = new GsonSerializer(typeHandlerLibrary); diff --git a/engine/src/main/java/org/terasology/reflection/TypeRegistry.java b/engine/src/main/java/org/terasology/reflection/TypeRegistry.java index 7a2fa30851d..e20e957da01 100644 --- a/engine/src/main/java/org/terasology/reflection/TypeRegistry.java +++ b/engine/src/main/java/org/terasology/reflection/TypeRegistry.java @@ -16,10 +16,13 @@ package org.terasology.reflection; import java.lang.annotation.Annotation; +import java.util.Optional; import java.util.Set; public interface TypeRegistry { Set> getSubtypesOf(Class type); Set> getTypesAnnotatedWith(Class annotationType); + + Optional> load(String name); } diff --git a/engine/src/main/java/org/terasology/reflection/internal/TypeRegistryImpl.java b/engine/src/main/java/org/terasology/reflection/internal/TypeRegistryImpl.java index 9f55a765f08..5e93b530f44 100644 --- a/engine/src/main/java/org/terasology/reflection/internal/TypeRegistryImpl.java +++ b/engine/src/main/java/org/terasology/reflection/internal/TypeRegistryImpl.java @@ -15,7 +15,9 @@ */ package org.terasology.reflection.internal; +import com.google.common.base.Preconditions; import com.google.common.collect.Lists; +import org.reflections.ReflectionUtils; import org.reflections.Reflections; import org.reflections.scanners.SubTypesScanner; import org.reflections.scanners.TypeAnnotationsScanner; @@ -24,11 +26,14 @@ import org.terasology.utilities.ReflectionUtil; import java.lang.annotation.Annotation; +import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.Set; public class TypeRegistryImpl implements TypeRegistry { private Reflections reflections; + private ClassLoader[] classLoaders; /** * Creates an empty {@link TypeRegistryImpl}. No types are loaded when this constructor @@ -53,18 +58,24 @@ private void initializeReflections(ClassLoader classLoader) { classLoader = classLoader.getParent(); } + // Here allClassLoaders contains child class loaders followed by their parent. The list is + // reversed so that classes are loaded using the originally declaring/loading class loader, + // not a child class loader (like a ModuleClassLoader, for example) + Collections.reverse(allClassLoaders); + + classLoaders = allClassLoaders.toArray(new ClassLoader[0]); + reflections = new Reflections( - // Reversed so that classes are loaded using the originally declaring/loading class loader, - // not a child class loader (like a ModuleClassLoader, for example) - Lists.reverse(allClassLoaders), - new SubTypesScanner(), - // TODO: Add string-based scanner that scans all objects (== getSubtypesOf(Object.class)) + allClassLoaders, + new SubTypesScanner(false), new TypeAnnotationsScanner() ); } @Override public Set> getSubtypesOf(Class type) { + Preconditions.checkArgument(!Object.class.equals(type)); + return reflections.getSubTypesOf(type); } @@ -72,4 +83,9 @@ public Set> getSubtypesOf(Class type) { public Set> getTypesAnnotatedWith(Class annotationType) { return reflections.getTypesAnnotatedWith(annotationType); } + + @Override + public Optional> load(String name) { + return Optional.ofNullable(ReflectionUtils.forName(name, classLoaders)); + } }