diff --git a/oap-application/oap-application-test/src/main/java/oap/application/testng/AbstractKernelFixture.java b/oap-application/oap-application-test/src/main/java/oap/application/testng/AbstractKernelFixture.java index 6e7c7ecead..488bbeca84 100644 --- a/oap-application/oap-application-test/src/main/java/oap/application/testng/AbstractKernelFixture.java +++ b/oap-application/oap-application-test/src/main/java/oap/application/testng/AbstractKernelFixture.java @@ -25,11 +25,13 @@ package oap.application.testng; import com.google.common.base.Preconditions; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import oap.application.ApplicationConfiguration; import oap.application.Kernel; import oap.application.module.Module; import oap.http.test.HttpAsserts; +import oap.io.IoStreams; import oap.io.Resources; import oap.json.Binder; import oap.json.JsonException; @@ -40,6 +42,8 @@ import org.apache.commons.io.FilenameUtils; import javax.annotation.Nonnull; +import java.io.FileNotFoundException; +import java.io.IOException; import java.io.UncheckedIOException; import java.net.URI; import java.net.URL; @@ -77,6 +81,7 @@ public abstract class AbstractKernelFixture, String>> confd = new ArrayList<>(); private final ArrayList, String>> conf = new ArrayList<>(); private final LinkedHashMap> dependencies = new LinkedHashMap<>(); + private final LinkedHashSet bootMain = new LinkedHashSet<>(); public Kernel kernel; protected Path confdPath; private int testHttpPort; @@ -167,6 +172,17 @@ public Self withLocalConfResource( Class clazz, String confdResource ) throws return withConfResource( clazz, cr ); } + public Self withAllowActiveByDefault( boolean allowActiveByDefault ) { + return define( "main.allowActiveByDefault", allowActiveByDefault ); + } + + @SuppressWarnings( "unchecked" ) + public Self withBootMain( String... modules ) { + this.bootMain.addAll( List.of( modules ) ); + + return ( Self ) this; + } + private void initConfd() { if( this.confdPath == null ) this.confdPath = testDirectoryFixture.testPath( "/application.test.confd" ); @@ -198,6 +214,7 @@ public List ofClass( String moduleName, Class clazz ) { return kernel.ofClass( moduleName, clazz ); } + @SneakyThrows @Override protected void before() { Preconditions.checkArgument( this.kernel == null ); @@ -217,12 +234,18 @@ protected void before() { } for( var cd : conf ) { - var p = Resources.filePath( cd._1, cd._2 ); - p.ifPresentOrElse( path -> { - Path destPath = confdPath.resolve( path.getFileName() ); - log.info( "Copying file " + path + " -> " + destPath ); - oap.io.Files.copy( path, PLAIN, destPath, PLAIN ); - }, () -> log.warn( "Configuration file " + cd + " is not found" ) ); + var url = Resources.url( cd._1, cd._2 ).orElse( null ); + if( url == null ) { + throw new FileNotFoundException( "Configuration file " + cd + " is not found" ); + } + Path destPath = confdPath.resolve( FilenameUtils.getName( url.toString() ) ); + log.info( "Copying file " + url + " -> " + destPath ); + + try( var is = IoStreams.in( url ) ) { + IoStreams.write( destPath, PLAIN, is ); + } catch( IOException e ) { + throw new UncheckedIOException( e ); + } } var moduleConfigurations = Module.CONFIGURATION.urlsFromClassPath(); @@ -233,6 +256,10 @@ protected void before() { var kernelProperties = new LinkedHashMap<>( properties ); + if( !bootMain.isEmpty() ) { + profiles.add( "boot.main = ${boot.main} [" + String.join( ",", bootMain ) + "]" ); + } + dependencies.forEach( ( name, fixture ) -> { kernelProperties.put( name, fixture.getProperties() ); } ); diff --git a/oap-application/oap-application-test/src/test/java/oap/application/KernelTest.java b/oap-application/oap-application-test/src/test/java/oap/application/KernelTest.java index d6176ee540..e4fd11c50b 100644 --- a/oap-application/oap-application-test/src/test/java/oap/application/KernelTest.java +++ b/oap-application/oap-application-test/src/test/java/oap/application/KernelTest.java @@ -281,20 +281,31 @@ public void testServiceWithoutImplementation() { @Test public void testLoadModules() { var modules = List.of( - url( "deps/m1.yaml" ), - url( "deps/m2.yaml" ), - url( "deps/m3.yaml" ), - url( "deps/m4.yaml" ) + url( "deps/m1.conf" ), + url( "deps/m2.conf" ), + url( "deps/m3.conf" ), + url( "deps/m4.conf" ), + url( "deps/activeByDefault.conf" ), + url( "deps/m5.conf" ) ); try( var kernel = new Kernel( modules ) ) { - kernel.start( Map.of( "boot.main", "m1" ) ); + kernel.start( Map.of( "boot", Map.of( "main", "m1", "allowActiveByDefault", true ) ) ); assertThat( kernel.service( "m1.s11" ) ).isPresent(); assertThat( kernel.service( "m2.s21" ) ).isNotPresent(); assertThat( kernel.service( "m1.s31" ) ).isNotPresent(); assertThat( kernel.service( "m3.s31" ) ).isPresent(); assertThat( kernel.service( "m4.s41" ) ).isPresent(); + assertThat( kernel.service( "activeByDefault.sa" ) ).isPresent(); + assertThat( kernel.service( "m5.s5" ) ).isPresent(); + } + + try( var kernel = new Kernel( modules ) ) { + kernel.start( Map.of( "boot.main", "m1" ) ); + + assertThat( kernel.service( "activeByDefault.sa" ) ).isNotPresent(); + assertThat( kernel.service( "m5.s5" ) ).isNotPresent(); } } diff --git a/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/activeByDefault.conf b/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/activeByDefault.conf new file mode 100644 index 0000000000..55f5005ee6 --- /dev/null +++ b/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/activeByDefault.conf @@ -0,0 +1,6 @@ +name = activeByDefault +activation.activeByDefault = true + +dependsOn = m5 + +services.sa.implementation = oap.application.KernelTest.Service1 diff --git a/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m1.conf b/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m1.conf new file mode 100644 index 0000000000..aaf77ce4ab --- /dev/null +++ b/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m1.conf @@ -0,0 +1,3 @@ +name = m1 +dependsOn = m3 +services.s11.implementation = oap.application.KernelTest.Service1 diff --git a/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m1.yaml b/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m1.yaml deleted file mode 100644 index 484325601b..0000000000 --- a/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m1.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: m1 -dependsOn: - - m3 -services: - s11: - implementation: oap.application.KernelTest$Service1 diff --git a/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m2.conf b/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m2.conf new file mode 100644 index 0000000000..60b5544898 --- /dev/null +++ b/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m2.conf @@ -0,0 +1,2 @@ +name = m2 +services.s21.implementation = oap.application.KernelTest.Service1 diff --git a/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m2.yaml b/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m2.yaml deleted file mode 100644 index 29971afbe4..0000000000 --- a/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m2.yaml +++ /dev/null @@ -1,4 +0,0 @@ -name: m2 -services: - s21: - implementation: oap.application.KernelTest$Service1 diff --git a/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m3.conf b/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m3.conf new file mode 100644 index 0000000000..8907136968 --- /dev/null +++ b/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m3.conf @@ -0,0 +1,3 @@ +name = m3 +dependsOn = m4 +services.s31.implementation = oap.application.KernelTest.Service1 diff --git a/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m3.yaml b/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m3.yaml deleted file mode 100644 index 45d726f1c3..0000000000 --- a/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m3.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: m3 -dependsOn: - - m4 -services: - s31: - implementation: oap.application.KernelTest$Service1 diff --git a/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m4.conf b/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m4.conf new file mode 100644 index 0000000000..f566da50d0 --- /dev/null +++ b/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m4.conf @@ -0,0 +1,2 @@ +name = m4 +services.s41.implementation = oap.application.KernelTest.Service1 diff --git a/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m4.yaml b/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m4.yaml deleted file mode 100644 index b3ae898017..0000000000 --- a/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m4.yaml +++ /dev/null @@ -1,4 +0,0 @@ -name: m4 -services: - s41: - implementation: oap.application.KernelTest$Service1 diff --git a/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m5.conf b/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m5.conf new file mode 100644 index 0000000000..e44d2db1a5 --- /dev/null +++ b/oap-application/oap-application-test/src/test/resources/oap/application/KernelTest/deps/m5.conf @@ -0,0 +1,2 @@ +name = m5 +services.s5.implementation = oap.application.KernelTest.Service1 diff --git a/oap-application/oap-application-test/src/test/resources/oap/application/remote/RemoteTest/application-remote.conf b/oap-application/oap-application-test/src/test/resources/oap/application/remote/RemoteTest/application-remote.conf index 9ea26bf7b9..a06a34d0a2 100644 --- a/oap-application/oap-application-test/src/test/resources/oap/application/remote/RemoteTest/application-remote.conf +++ b/oap-application/oap-application-test/src/test/resources/oap/application/remote/RemoteTest/application-remote.conf @@ -1,10 +1,5 @@ boot.main = oap-module-with-remoting -profiles = [ - http - remoting -] - services { oap-http { oap-http-server.parameters { diff --git a/oap-application/oap-application/src/main/java/oap/application/ApplicationConfiguration.java b/oap-application/oap-application/src/main/java/oap/application/ApplicationConfiguration.java index 69c5db9964..e65133ec57 100644 --- a/oap-application/oap-application/src/main/java/oap/application/ApplicationConfiguration.java +++ b/oap-application/oap-application/src/main/java/oap/application/ApplicationConfiguration.java @@ -121,9 +121,9 @@ static ApplicationConfiguration load( Map properties ) { public static List getConfdUrls( Path confd ) { return confd != null ? Stream - .of( wildcard( confd, "*.conf", "*.yaml" ) ) - .map( Files::toUrl ) - .toList() + .of( wildcard( confd, "*.conf", "*.yaml" ) ) + .map( Files::toUrl ) + .toList() : List.of(); } @@ -233,6 +233,7 @@ public boolean isEnabled() { @ToString public static class ModuleBoot { public final LinkedHashSet main = new LinkedHashSet<>(); + public boolean allowActiveByDefault = false; } public static class ProfileMap { diff --git a/oap-application/oap-application/src/main/java/oap/application/Kernel.java b/oap-application/oap-application/src/main/java/oap/application/Kernel.java index 5869e3db09..03d239410a 100644 --- a/oap-application/oap-application/src/main/java/oap/application/Kernel.java +++ b/oap-application/oap-application/src/main/java/oap/application/Kernel.java @@ -175,7 +175,7 @@ public void start( ApplicationConfiguration config ) throws ApplicationException checkForUnknownServices( config.services ); log.debug( "init modules from main: {}", config.boot.main ); - var map = ModuleHelper.init( this.modules, this.profiles, config.boot.main, this ); + var map = ModuleHelper.init( this.modules, this.profiles, config.boot.main, config.boot.allowActiveByDefault, this ); var servicesMap = instantiateServices( map ); registerServices( servicesMap ); diff --git a/oap-application/oap-application/src/main/java/oap/application/ModuleHelper.java b/oap-application/oap-application/src/main/java/oap/application/ModuleHelper.java index a9f42c28f1..84f6871111 100644 --- a/oap-application/oap-application/src/main/java/oap/application/ModuleHelper.java +++ b/oap-application/oap-application/src/main/java/oap/application/ModuleHelper.java @@ -59,10 +59,11 @@ private static ModuleItemTree init( LinkedHashSet mod public static ModuleItemTree init( LinkedHashSet modules, LinkedHashSet profiles, LinkedHashSet main, + boolean allowActiveByDefault, Kernel kernel ) throws ApplicationException { - log.trace( "Init modules: {}, profiles: {}, main: {}", modules, profiles, main ); + log.trace( "Init modules {} profiles {} main {} allowActiveByDefault {}", modules, profiles, main, allowActiveByDefault ); var map = init( modules, profiles ); - loadOnlyMainModuleAndDependsOn( map, main, profiles ); + loadOnlyMainModuleAndDependsOn( map, main, allowActiveByDefault, profiles ); validateModuleName( map ); validateServiceName( map ); @@ -217,10 +218,11 @@ else if( value instanceof Map ) { } } - private static void loadOnlyMainModuleAndDependsOn( ModuleItemTree map, LinkedHashSet main, LinkedHashSet profiles ) { + private static void loadOnlyMainModuleAndDependsOn( ModuleItemTree map, LinkedHashSet main, + boolean allowActiveByDefault, LinkedHashSet profiles ) { var modules = map.clone(); - log.info( "loading main modules: {} with profiles: {}", main, profiles ); - loadOnlyMainModuleAndDependsOn( modules, main, profiles, new LinkedHashSet<>() ); + log.info( "loading main modules {} with profiles {}", main, profiles ); + loadOnlyMainModuleAndDependsOn( modules, main, allowActiveByDefault, profiles, new LinkedHashSet<>() ); for( var moduleItem : modules.values() ) { log.debug( "unload module {}", moduleItem.getName() ); @@ -230,13 +232,26 @@ private static void loadOnlyMainModuleAndDependsOn( ModuleItemTree map, LinkedHa private static void loadOnlyMainModuleAndDependsOn( ModuleItemTree modules, final LinkedHashSet main, + boolean allowActiveByDefault, final LinkedHashSet profiles, final LinkedHashSet loaded ) { - for( var module : main ) { + + var mainWithAllowActiveByDefault = new LinkedHashSet<>( main ); + if( allowActiveByDefault ) { + for( var moduleName : modules.keySet() ) { + var moduleItem = modules.get( moduleName ); + if( moduleItem.module.activation.activeByDefault ) { + mainWithAllowActiveByDefault.add( moduleName ); + } + } + } + + for( var module : mainWithAllowActiveByDefault ) { var moduleItem = modules.get( module ); - if( moduleItem == null && !loaded.contains( module ) ) + if( moduleItem == null && !loaded.contains( module ) ) { throw new ApplicationException( "main.boot: unknown module name '" + module + "', already loaded: " + loaded ); + } if( moduleItem != null ) { log.trace( "Loading module: {}, already loaded: {}", moduleItem.getName(), loaded ); @@ -254,7 +269,7 @@ private static void loadOnlyMainModuleAndDependsOn( ModuleItemTree modules, log.trace( "dependant module {} disabled for module {}", depends.name, module ); } } - loadOnlyMainModuleAndDependsOn( modules, dependsOn, profiles, loaded ); + loadOnlyMainModuleAndDependsOn( modules, dependsOn, allowActiveByDefault, profiles, loaded ); } } } diff --git a/oap-application/oap-application/src/main/java/oap/application/module/Module.java b/oap-application/oap-application/src/main/java/oap/application/module/Module.java index e2d34a60b4..ed662e502c 100644 --- a/oap-application/oap-application/src/main/java/oap/application/module/Module.java +++ b/oap-application/oap-application/src/main/java/oap/application/module/Module.java @@ -55,6 +55,8 @@ public class Module { @JsonIgnore public LinkedHashMap ext = new LinkedHashMap<>(); + public final ModuleActivation activation = new ModuleActivation(); + @JsonCreator public Module( String name ) { this.name = name; @@ -70,4 +72,8 @@ public Map getUnknown() { return ext; } + @ToString + public static class ModuleActivation { + public boolean activeByDefault = false; + } } diff --git a/oap-application/oap-application/src/main/resources/META-INF/oap-module.conf b/oap-application/oap-application/src/main/resources/META-INF/oap-module.conf index 86f177674c..23b3b82477 100644 --- a/oap-application/oap-application/src/main/resources/META-INF/oap-module.conf +++ b/oap-application/oap-application/src/main/resources/META-INF/oap-module.conf @@ -3,10 +3,6 @@ dependsOn = oap-http services { remoting { implementation = oap.application.remote.Remote - profiles = [ - http - remoting - ] parameters { server = context = /remote/ diff --git a/oap-http/oap-http/src/main/resources/META-INF/oap-module.conf b/oap-http/oap-http/src/main/resources/META-INF/oap-module.conf index 4807b1b582..dfc1970cba 100644 --- a/oap-http/oap-http/src/main/resources/META-INF/oap-module.conf +++ b/oap-http/oap-http/src/main/resources/META-INF/oap-module.conf @@ -27,7 +27,6 @@ services { } oap-http-server { - profile = http implementation = oap.http.server.nio.NioHttpServer parameters { defaultPort { @@ -65,7 +64,6 @@ services { } oap-http-health-handler { - profile = http implementation = oap.http.server.nio.health.HealthHttpHandler parameters { server = diff --git a/oap-mail/oap-mail/src/main/resources/META-INF/oap-module.conf b/oap-mail/oap-mail/src/main/resources/META-INF/oap-module.conf index 59eb470e61..4092457296 100644 --- a/oap-mail/oap-mail/src/main/resources/META-INF/oap-module.conf +++ b/oap-mail/oap-mail/src/main/resources/META-INF/oap-module.conf @@ -2,24 +2,13 @@ name = oap-mail services { oap-mail-password-authenticator.implementation = oap.mail.PasswordAuthenticator - oap-mail-transport-smtp { - profile = oap-mail-javamail - name = oap-mail-transport + oap-mail-transport { implementation = oap.mail.SmtpTransport parameters { authenticator = } } - oap-mail-transport-mock { - profile = -oap-mail-javamail - name = oap-mail-transport - implementation = oap.mail.TransportMock - parameters { - authenticator = - } - } - oap-mail-queue.implementation: oap.mail.MailQueue oap-mail-mailman { diff --git a/oap-message/src/main/resources/META-INF/oap-module.conf b/oap-message/src/main/resources/META-INF/oap-module.conf index 9612172680..bd65dd3c37 100644 --- a/oap-message/src/main/resources/META-INF/oap-module.conf +++ b/oap-message/src/main/resources/META-INF/oap-module.conf @@ -3,7 +3,6 @@ dependsOn = oap-http services { oap-http-message-handler { profiles = [ - http oap-message-server ] implementation = oap.message.MessageHttpHandler diff --git a/oap-message/src/test/resources/oap/message/MessageServerTest/application-message.test.conf b/oap-message/src/test/resources/oap/message/MessageServerTest/application-message.test.conf index 3ce3eb033a..f977c82a43 100644 --- a/oap-message/src/test/resources/oap/message/MessageServerTest/application-message.test.conf +++ b/oap-message/src/test/resources/oap/message/MessageServerTest/application-message.test.conf @@ -5,7 +5,6 @@ boot.main = [ ] profiles = [ - http oap-message-sender oap-message-server ] diff --git a/oap-message/src/test/resources/oap/message/MessageServerTest/oap-module.conf b/oap-message/src/test/resources/oap/message/MessageServerTest/oap-module.conf index ba7b0b9660..4e0449eecb 100644 --- a/oap-message/src/test/resources/oap/message/MessageServerTest/oap-module.conf +++ b/oap-message/src/test/resources/oap/message/MessageServerTest/oap-module.conf @@ -8,7 +8,6 @@ dependsOn = [ services { message-listener-mock { profiles = [ - http oap-message-server ] implementation = oap.message.MessageListenerMock diff --git a/oap-statsdb/oap-statsdb-master/src/test/resources/META-INF/json-mapping.properties b/oap-statsdb/oap-statsdb-master/src/test/resources/META-INF/json-mapping.properties deleted file mode 100644 index cfdbabdd35..0000000000 --- a/oap-statsdb/oap-statsdb-master/src/test/resources/META-INF/json-mapping.properties +++ /dev/null @@ -1,3 +0,0 @@ -mock-value=oap.statsdb.StatsDBTest$MockValue -mock-child2=oap.statsdb.StatsDBTest$MockChild2 -mock-child1=oap.statsdb.StatsDBTest$MockChild1 diff --git a/oap-statsdb/oap-statsdb-master/src/test/resources/META-INF/oap-module.conf b/oap-statsdb/oap-statsdb-master/src/test/resources/META-INF/oap-module.conf new file mode 100644 index 0000000000..7c01667838 --- /dev/null +++ b/oap-statsdb/oap-statsdb-master/src/test/resources/META-INF/oap-module.conf @@ -0,0 +1,12 @@ +name = oap-statsdb-master + +configurations = [ + { + loader = oap.json.TypeIdFactory + config = { + mock-value = oap.statsdb.StatsDBTest.MockValue + mock-child2 = oap.statsdb.StatsDBTest.MockChild2 + mock-child1 = oap.statsdb.StatsDBTest.MockChild1 + } + } +] diff --git a/oap-statsdb/oap-statsdb/src/main/resources/META-INF/json-mapping.properties b/oap-statsdb/oap-statsdb/src/main/resources/META-INF/json-mapping.properties deleted file mode 100644 index 0f9bb65369..0000000000 --- a/oap-statsdb/oap-statsdb/src/main/resources/META-INF/json-mapping.properties +++ /dev/null @@ -1,2 +0,0 @@ -node=oap.statsdb.Node -nid=oap.statsdb.NodeId diff --git a/oap-statsdb/oap-statsdb/src/main/resources/META-INF/oap-module.conf b/oap-statsdb/oap-statsdb/src/main/resources/META-INF/oap-module.conf new file mode 100644 index 0000000000..60a9376f1d --- /dev/null +++ b/oap-statsdb/oap-statsdb/src/main/resources/META-INF/oap-module.conf @@ -0,0 +1,11 @@ +name = oap-statsdb + +configurations = [ + { + loader = oap.json.TypeIdFactory + config = { + node = oap.statsdb.Node + nid = oap.statsdb.NodeId + } + } +] diff --git a/oap-stdlib-test/src/main/java/oap/testng/AbstractFixture.java b/oap-stdlib-test/src/main/java/oap/testng/AbstractFixture.java index d86c081ee4..f1e42c7ff1 100644 --- a/oap-stdlib-test/src/main/java/oap/testng/AbstractFixture.java +++ b/oap-stdlib-test/src/main/java/oap/testng/AbstractFixture.java @@ -32,15 +32,13 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import static oap.testng.Asserts.locationOfTestResource; @Slf4j public abstract class AbstractFixture> { - protected static ConcurrentHashMap, AbstractFixture> suiteScope = new ConcurrentHashMap<>(); protected final LinkedHashMap properties = new LinkedHashMap<>(); - private final ArrayList> children = new ArrayList<>(); + protected final ArrayList> children = new ArrayList<>(); protected Scope scope = Scope.METHOD; protected AbstractFixture() { @@ -55,9 +53,11 @@ public Self withScope( Scope scope ) { this.scope = scope; if( scope == Scope.SUITE ) { - return ( Self ) suiteScope.computeIfAbsent( getClass(), c -> this ); + throw new IllegalArgumentException( "use Fixtures#suiteFixture" ); } + children.forEach( f -> f.withScope( scope ) ); + return ( Self ) this; } diff --git a/oap-stdlib-test/src/main/java/oap/testng/Fixtures.java b/oap-stdlib-test/src/main/java/oap/testng/Fixtures.java index 0ac36fc830..762618dc82 100644 --- a/oap-stdlib-test/src/main/java/oap/testng/Fixtures.java +++ b/oap-stdlib-test/src/main/java/oap/testng/Fixtures.java @@ -46,7 +46,8 @@ public abstract class Fixtures { private final ArrayList> fixtures = new ArrayList<>(); public static > F suiteFixture( F fixture ) throws IllegalArgumentException { - fixture.withScope( SUITE ); + fixture.scope = SUITE; + fixture.children.forEach( f -> f.scope = SUITE ); suiteFixtures.add( fixture ); @@ -77,7 +78,10 @@ public void fixBeforeSuite() { @AfterSuite( alwaysRun = true ) public void fixAfterSuite() { SilentRun silentRun = new SilentRun(); - Lists.reverse( suiteFixtures ).forEach( f -> Threads.withThreadName( f.toThreadName(), () -> silentRun.run( f::afterSuite ) ) ); + Lists.reverse( suiteFixtures ).forEach( f -> Threads.withThreadName( f.toThreadName(), () -> { + log.info( "afterSuite {}", f.getClass() ); + silentRun.run( f::afterSuite ); + } ) ); silentRun.done(); } @@ -90,10 +94,8 @@ public void fixBeforeClass() { @AfterClass( alwaysRun = true ) public void fixAfterClass() { SilentRun silentRun = new SilentRun(); - Lists.reverse( fixtures ).forEach( f -> Threads.withThreadName( f.toThreadName(), () -> silentRun.run( f::afterClass ) ) ); Lists.reverse( suiteFixtures ).forEach( f -> Threads.withThreadName( f.toThreadName(), () -> silentRun.run( f::afterClass ) ) ); - silentRun.done(); } @@ -106,10 +108,8 @@ public void fixBeforeMethod() { @AfterMethod( alwaysRun = true ) public void fixAfterMethod() { SilentRun silentRun = new SilentRun(); - Lists.reverse( fixtures ).forEach( f -> Threads.withThreadName( f.toThreadName(), () -> silentRun.run( f::afterMethod ) ) ); Lists.reverse( suiteFixtures ).forEach( f -> Threads.withThreadName( f.toThreadName(), () -> silentRun.run( f::afterMethod ) ) ); - silentRun.done(); } diff --git a/oap-stdlib-test/src/main/java/oap/testng/SystemTimerFixture.java b/oap-stdlib-test/src/main/java/oap/testng/SystemTimerFixture.java index 6b9614dd28..d656930686 100644 --- a/oap-stdlib-test/src/main/java/oap/testng/SystemTimerFixture.java +++ b/oap-stdlib-test/src/main/java/oap/testng/SystemTimerFixture.java @@ -24,19 +24,16 @@ package oap.testng; -import oap.time.JavaTimeService; -import oap.time.JodaTimeService; +import org.joda.time.DateTimeUtils; public class SystemTimerFixture extends AbstractFixture { @Override protected void before() { - JodaTimeService.INSTANCE.setCurrentMillisSystem(); - JavaTimeService.INSTANCE.setCurrentMillisSystem(); + DateTimeUtils.setCurrentMillisSystem(); } @Override public void after() { - JodaTimeService.INSTANCE.setCurrentMillisSystem(); - JavaTimeService.INSTANCE.setCurrentMillisSystem(); + DateTimeUtils.setCurrentMillisSystem(); } } diff --git a/oap-stdlib-test/src/test/java/oap/json/ext/ClassLocalExtDeserializerTest.java b/oap-stdlib-test/src/test/java/oap/json/ext/ClassLocalExtDeserializerTest.java deleted file mode 100644 index ee1d562cd4..0000000000 --- a/oap-stdlib-test/src/test/java/oap/json/ext/ClassLocalExtDeserializerTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) Open Application Platform Authors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package oap.json.ext; - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import oap.json.Binder; -import org.testng.annotations.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @apiNote json-ext.properties - */ -@SuppressWarnings( "unused" ) -public class ClassLocalExtDeserializerTest { - @Test - public void ext() { - Bean aaa = new Bean( new TestExt( "aaa" ) ); - String json = "{\"ext\":{\"value\":\"aaa\"}}"; - assertThat( Binder.json.marshal( aaa ) ).isEqualTo( json ); - assertThat( Binder.json.unmarshal( Bean.class, json ) ) - .isEqualTo( aaa ); - } - - @EqualsAndHashCode - @ToString - public static class Bean { - @JsonDeserialize( using = BeanExtDeserializer.class ) - BeanExt ext; - - @JsonDeserialize( using = BeanNoExtDeserializer.class ) - BeanExt noext; - - public Bean() { - } - - public Bean( BeanExt ext ) { - this.ext = ext; - } - - interface BeanExt {} - - interface BeanNoExt {} - - public static class BeanExtDeserializer extends ClassLocalExtDeserializer { - public BeanExtDeserializer() { - super( BeanExt.class ); - } - } - - public static class BeanNoExtDeserializer extends ClassLocalExtDeserializer { - public BeanNoExtDeserializer() { - super( BeanNoExt.class ); - } - } - } - - @EqualsAndHashCode - @ToString - public static class TestExt implements Bean.BeanExt { - String value; - - public TestExt() { - } - - public TestExt( String value ) { - this.value = value; - } - } -} diff --git a/oap-stdlib-test/src/test/java/oap/testng/FixturesTest.java b/oap-stdlib-test/src/test/java/oap/testng/FixturesTest.java index 7b0805b657..cfe3ef8063 100644 --- a/oap-stdlib-test/src/test/java/oap/testng/FixturesTest.java +++ b/oap-stdlib-test/src/test/java/oap/testng/FixturesTest.java @@ -31,7 +31,6 @@ import static org.assertj.core.api.Assertions.assertThat; public class FixturesTest extends Fixtures { - private F fixture; { @@ -45,7 +44,7 @@ public void test() { } @AfterTest - public void assertFixture() { + public void testAfterTest() { assertThat( fixture.result ).isEqualTo( "BCBMAMAC" ); } diff --git a/oap-stdlib-test/src/test/resources/META-INF/json-ext.conf b/oap-stdlib-test/src/test/resources/META-INF/json-ext.conf deleted file mode 100644 index 9a684eb072..0000000000 --- a/oap-stdlib-test/src/test/resources/META-INF/json-ext.conf +++ /dev/null @@ -1,29 +0,0 @@ -ext = [ - { - class = oap.json.ext.ExtDeserializerTest.Bean - field = ext - implementation = oap.json.ext.ExtDeserializerTest.TestExt - disableOverwrite = true - } - { - class = oap.json.ext.ExtDeserializerTest.Bean - field = ext - implementation = oap.json.ext.ExtDeserializerTest.TestExtOverwritten - } - { - class = oap.json.ext.ExtDeserializerTest.Bean - field = ext2 - abstract = oap.json.ext.ExtDeserializerTest.Ext2 - implementation = oap.json.ext.ExtDeserializerTest.TestExt - } - { - class = oap.json.ext.Npe - field = ext - implementation = oap.json.ext.NpeExt - } - { - class = oap.json.TestTemplateBean - field = ext - implementation = oap.json.TestTemplateBeanExt - } -] diff --git a/oap-stdlib-test/src/test/resources/META-INF/json-ext.properties b/oap-stdlib-test/src/test/resources/META-INF/json-ext.properties deleted file mode 100644 index fc2eb0345b..0000000000 --- a/oap-stdlib-test/src/test/resources/META-INF/json-ext.properties +++ /dev/null @@ -1,24 +0,0 @@ -# -# The MIT License (MIT) -# -# Copyright (c) Open Application Platform Authors -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -oap.json.ext.ClassLocalExtDeserializerTest$Bean$BeanExt=oap.json.ext.ClassLocalExtDeserializerTest$TestExt diff --git a/oap-stdlib-test/src/test/resources/META-INF/json-mapping.properties b/oap-stdlib-test/src/test/resources/META-INF/json-mapping.properties deleted file mode 100644 index ba3cdd2e9f..0000000000 --- a/oap-stdlib-test/src/test/resources/META-INF/json-mapping.properties +++ /dev/null @@ -1 +0,0 @@ -b=oap.json.TypeIdAccessorFactoryTest$TestBean diff --git a/oap-stdlib-test/src/test/resources/META-INF/oap-module.conf b/oap-stdlib-test/src/test/resources/META-INF/oap-module.conf new file mode 100644 index 0000000000..d5fd06fe22 --- /dev/null +++ b/oap-stdlib-test/src/test/resources/META-INF/oap-module.conf @@ -0,0 +1,42 @@ +name = oap-stdlib-app-test + +configurations = [ + { + loader = oap.json.TypeIdFactory + config = { + b = oap.json.TypeIdAccessorFactoryTest.TestBean + } + } + { + loader = oap.json.ext.ExtDeserializer + config = [ + { + class = oap.json.ext.ExtDeserializerTest.Bean + field = ext + implementation = oap.json.ext.ExtDeserializerTest.TestExt + disableOverwrite = true + } + { + class = oap.json.ext.ExtDeserializerTest.Bean + field = ext + implementation = oap.json.ext.ExtDeserializerTest.TestExtOverwritten + } + { + class = oap.json.ext.ExtDeserializerTest.Bean + field = ext2 + abstract = oap.json.ext.ExtDeserializerTest.Ext2 + implementation = oap.json.ext.ExtDeserializerTest.TestExt + } + { + class = oap.json.ext.Npe + field = ext + implementation = oap.json.ext.NpeExt + } + { + class = oap.json.TestTemplateBean + field = ext + implementation = oap.json.TestTemplateBeanExt + } + ] + } +] diff --git a/oap-stdlib/README.md b/oap-stdlib/README.md index 64f9ff777d..ce0f6e90c6 100644 --- a/oap-stdlib/README.md +++ b/oap-stdlib/README.md @@ -11,8 +11,6 @@ and [KernelTest](oap-stdlib/src/test/java/oap/application/KernelTest.java) and [ ## Kernel services See main Kernel services in [oap-module.conf](oap-stdlib/src/main/resources/META-INF/oap-module.conf): -* oap-time-java -* oap-time-joda * oap-http-server * oap-prometheus-metrics * oap-http-health-handler diff --git a/oap-stdlib/src/main/java/oap/configuration/ConfigurationLoader.java b/oap-stdlib/src/main/java/oap/configuration/ConfigurationLoader.java new file mode 100644 index 0000000000..d8dffa3d0f --- /dev/null +++ b/oap-stdlib/src/main/java/oap/configuration/ConfigurationLoader.java @@ -0,0 +1,110 @@ +package oap.configuration; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; +import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; +import oap.io.Resources; +import oap.json.HoconFactoryWithSystemProperties; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Slf4j +public class ConfigurationLoader { + private static volatile HashMap, ArrayList>> configurations; + + private static void init() { + if( configurations == null ) { + synchronized( ConfigurationLoader.class ) { + if( configurations == null ) { + configurations = new HashMap<>(); + try { + List urls = Resources.urls( "META-INF/oap-module.conf" ); + log.trace( "urls {}", urls ); + + var objectMapper = new ObjectMapper( new HoconFactoryWithSystemProperties( log ) ); + objectMapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false ); + objectMapper.getDeserializationConfig().with( new JacksonAnnotationIntrospector() ); + objectMapper.registerModule( new ParameterNamesModule( JsonCreator.Mode.DEFAULT ) ); + + for( var url : urls ) { + var conf = objectMapper.readValue( url, Configurations.class ); + log.trace( "conf {}", conf ); + + for( var c : conf.configurations ) { + ArrayList> list = configurations.computeIfAbsent( c.loader, l -> new ArrayList<>() ); + list.add( c ); + } + } + + log.trace( "configurations {}", configurations ); + } catch( IOException e ) { + throw new RuntimeException( e ); + } + } + } + } + } + + public static > List read( Class loader, TypeReference>> typeReference ) { + init(); + + ArrayList> conf = configurations.get( loader ); + + if( conf == null ) { + return List.of(); + } + + var objectMapper = new ObjectMapper( new JsonFactory() ); + objectMapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false ); + objectMapper.getDeserializationConfig().with( new JacksonAnnotationIntrospector() ); + objectMapper.registerModule( new ParameterNamesModule( JsonCreator.Mode.DEFAULT ) ); + + try { + String data = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString( Map.of( "map", conf ) ); + + Map> config = objectMapper.readValue( data, typeReference ); + return config.get( "map" ); + } catch( JsonProcessingException e ) { + throw new RuntimeException( e ); + } + } + + @SuppressWarnings( "unchecked" ) + public T get( Class clazz ) { + init(); + + return ( T ) configurations.get( clazz ); + } + + @ToString + public static class Configurations { + public final ArrayList> configurations = new ArrayList<>(); + } + + @ToString + public static class Configuration { + public T config; + } + + @ToString + public static class ClassConfiguration extends Configuration { + public final Class loader; + + @JsonCreator + public ClassConfiguration( Class loader ) { + this.loader = loader; + } + } +} diff --git a/oap-stdlib/src/main/java/oap/json/HoconFactoryWithFallback.java b/oap-stdlib/src/main/java/oap/json/HoconFactoryWithFallback.java index eb2dc6f2fb..773801d834 100644 --- a/oap-stdlib/src/main/java/oap/json/HoconFactoryWithFallback.java +++ b/oap-stdlib/src/main/java/oap/json/HoconFactoryWithFallback.java @@ -25,12 +25,12 @@ package oap.json; import com.fasterxml.jackson.core.io.IOContext; -import com.jasonclawson.jackson.dataformat.hocon.HoconFactory; import com.jasonclawson.jackson.dataformat.hocon.HoconTreeTraversingParser; import com.typesafe.config.Config; import com.typesafe.config.ConfigException; import com.typesafe.config.ConfigFactory; import com.typesafe.config.ConfigParseOptions; +import lombok.SneakyThrows; import oap.util.Stream; import org.slf4j.Logger; @@ -38,7 +38,7 @@ import java.util.List; import java.util.Map; -public class HoconFactoryWithFallback extends HoconFactory { +public class HoconFactoryWithFallback extends OapHoconFactory { private final Config additinal; private final boolean withSystemProperties; private final Logger log; @@ -65,9 +65,15 @@ private static Config init( List configs ) { ( config, value ) -> config.withFallback( ConfigFactory.parseString( value ) ) ); } + @SneakyThrows @Override protected HoconTreeTraversingParser _createParser( Reader r, IOContext ctxt ) { var options = ConfigParseOptions.defaults(); + + Object rawContent = ctxt.contentReference().getRawContent(); + + options = fixClassLoader( log, rawContent, options ); + var config = ConfigFactory.parseReader( r, options ); var unresolvedConfig = additinal.withFallback( config ); diff --git a/oap-stdlib/src/main/java/oap/json/HoconFactoryWithSystemProperties.java b/oap-stdlib/src/main/java/oap/json/HoconFactoryWithSystemProperties.java index eac0d65d29..fd2ef2d9f9 100644 --- a/oap-stdlib/src/main/java/oap/json/HoconFactoryWithSystemProperties.java +++ b/oap-stdlib/src/main/java/oap/json/HoconFactoryWithSystemProperties.java @@ -25,7 +25,6 @@ package oap.json; import com.fasterxml.jackson.core.io.IOContext; -import com.jasonclawson.jackson.dataformat.hocon.HoconFactory; import com.jasonclawson.jackson.dataformat.hocon.HoconTreeTraversingParser; import com.typesafe.config.Config; import com.typesafe.config.ConfigException; @@ -34,15 +33,9 @@ import lombok.SneakyThrows; import org.slf4j.Logger; -import java.io.File; -import java.io.IOException; import java.io.Reader; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.URLClassLoader; -public class HoconFactoryWithSystemProperties extends HoconFactory { +public class HoconFactoryWithSystemProperties extends OapHoconFactory { private final Logger log; public HoconFactoryWithSystemProperties( Logger log ) { @@ -50,44 +43,15 @@ public HoconFactoryWithSystemProperties( Logger log ) { // if( log.isTraceEnabled() ) System.setProperty( "config.trace", "loads" ); } - static URI getParent( URI uri ) throws URISyntaxException { - String strUri = uri.toString(); - - int index = strUri.lastIndexOf( "/" ); - - String strParentUri = strUri.substring( 0, index + 1 ); - - return new URI( strParentUri ); - } - @SneakyThrows @Override - protected HoconTreeTraversingParser _createParser( Reader r, IOContext ctxt ) throws IOException { + protected HoconTreeTraversingParser _createParser( Reader r, IOContext ctxt ) { var options = ConfigParseOptions.defaults(); Object rawContent = ctxt.contentReference().getRawContent(); log.trace( "rawContent {} rawContentClazz {}", rawContent, rawContent.getClass() ); - switch( rawContent ) { - case URL urlContext -> { - URL parentURL = getParent( urlContext.toURI() ).toURL(); - log.trace( "parentURL {}", parentURL ); - options = options.setClassLoader( new URLClassLoader( new URL[] { parentURL } ) ); - } - case File fileContext -> { - URL parentURL = getParent( fileContext.toURI() ).toURL(); - log.trace( "parentURL {}", parentURL ); - options = options.setClassLoader( new URLClassLoader( new URL[] { parentURL } ) ); - } - case URI uriContext -> { - URL parentURL = getParent( uriContext ).toURL(); - log.trace( "parentURL {}", parentURL ); - options = options.setClassLoader( new URLClassLoader( new URL[] { parentURL } ) ); - } - default -> { - } - } - + options = fixClassLoader( log, rawContent, options ); var config = ConfigFactory.parseReader( r, options ); @@ -101,4 +65,5 @@ protected HoconTreeTraversingParser _createParser( Reader r, IOContext ctxt ) th throw e; } } + } diff --git a/oap-stdlib/src/main/java/oap/json/OapHoconFactory.java b/oap-stdlib/src/main/java/oap/json/OapHoconFactory.java new file mode 100644 index 0000000000..ce3f2fff03 --- /dev/null +++ b/oap-stdlib/src/main/java/oap/json/OapHoconFactory.java @@ -0,0 +1,48 @@ +package oap.json; + +import com.jasonclawson.jackson.dataformat.hocon.HoconFactory; +import com.typesafe.config.ConfigParseOptions; +import org.slf4j.Logger; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLClassLoader; + +public class OapHoconFactory extends HoconFactory { + static URI getParent( URI uri ) throws URISyntaxException { + String strUri = uri.toString(); + + int index = strUri.lastIndexOf( "/" ); + + String strParentUri = strUri.substring( 0, index + 1 ); + + return new URI( strParentUri ); + } + + @SuppressWarnings( "checkstyle:ParameterAssignment" ) + protected ConfigParseOptions fixClassLoader( Logger log, Object rawContent, ConfigParseOptions options ) throws MalformedURLException, URISyntaxException { + switch( rawContent ) { + case URL urlContext -> { + URL parentURL = getParent( urlContext.toURI() ).toURL(); + log.trace( "parentURL {}", parentURL ); + options = options.setClassLoader( new URLClassLoader( new URL[] { parentURL } ) ); + } + case File fileContext -> { + URL parentURL = getParent( fileContext.toURI() ).toURL(); + log.trace( "parentURL {}", parentURL ); + options = options.setClassLoader( new URLClassLoader( new URL[] { parentURL } ) ); + } + case URI uriContext -> { + URL parentURL = getParent( uriContext ).toURL(); + log.trace( "parentURL {}", parentURL ); + options = options.setClassLoader( new URLClassLoader( new URL[] { parentURL } ) ); + } + default -> { + } + } + return options; + } +} diff --git a/oap-stdlib/src/main/java/oap/json/TypeIdFactory.java b/oap-stdlib/src/main/java/oap/json/TypeIdFactory.java index f6118d3390..34ff548625 100644 --- a/oap-stdlib/src/main/java/oap/json/TypeIdFactory.java +++ b/oap-stdlib/src/main/java/oap/json/TypeIdFactory.java @@ -25,80 +25,97 @@ package oap.json; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DatabindContext; import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.type.TypeFactory; +import lombok.ToString; import lombok.extern.slf4j.Slf4j; -import oap.io.Resources; -import oap.util.Throwables; +import oap.configuration.ConfigurationLoader; -import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; -import java.util.Properties; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; @Slf4j public class TypeIdFactory implements TypeIdResolver { - private static final ConcurrentHashMap> idToClass = new ConcurrentHashMap<>(); - private static final ConcurrentHashMap, String> classToId = new ConcurrentHashMap<>(); - - static { - Resources.urls( "META-INF/json-mapping.properties" ) - .forEach( url -> { - log.info( "loading {}...", url ); - try( InputStream is = url.openStream() ) { - final Properties properties = new Properties(); - properties.load( is ); - for( String key : properties.stringPropertyNames() ) - register( Class.forName( properties.getProperty( key ) ), key ); - } catch( IOException e ) { - throw new UncheckedIOException( e ); - } catch( ClassNotFoundException e ) { - throw Throwables.propagate( e ); - } - } ); - } - + private static ConcurrentHashMap, String> classToId; + private static volatile LinkedHashMap> idToClass; private JavaType baseType; public static boolean containsId( String id ) { + init(); + return idToClass.containsKey( id ); } public static boolean containsClass( Class clazz ) { + init(); + return classToId.containsKey( clazz ); } public static Class get( String id ) { + init(); + return idToClass.get( id ); } - public static String get( Class clazz ) { + public static String get( Class clazz ) { + init(); + return classToId.get( clazz ); } public static void register( Class bean, String id ) { + init(); + + log.trace( "{} -> {}", id, bean ); + idToClass.put( id, bean ); classToId.put( bean, id ); } public static Set keys() { + init(); + return idToClass.keySet(); } public static Set> values() { + init(); + return classToId.keySet(); } public static void clear() { + init(); + idToClass.clear(); classToId.clear(); } + private static void init() { + if( idToClass == null ) { + synchronized( TypeIdFactory.class ) { + if( idToClass == null ) { + idToClass = new LinkedHashMap<>(); + classToId = new ConcurrentHashMap<>(); + + List conf = ConfigurationLoader.read( TypeIdFactory.class, new TypeReference<>() {} ); + for( var c : conf ) { + c.config.forEach( ( k, v ) -> { + register( v, k ); + } ); + } + } + } + } + } + @Override public void init( JavaType baseType ) { this.baseType = baseType; @@ -111,6 +128,8 @@ public String idFromValue( Object value ) { @Override public String idFromValueAndType( Object value, Class suggestedType ) { + init(); + return classToId.computeIfAbsent( suggestedType, k -> { throw new IllegalStateException( "cannot find class '" + k + "'" ); } ); @@ -123,6 +142,8 @@ public String idFromBaseType() { @Override public JavaType typeFromId( DatabindContext context, String id ) { + init(); + final Class clazz = idToClass.computeIfAbsent( id, k -> { throw new IllegalStateException( "cannot find id '" + k + "'" ); } ); @@ -131,11 +152,23 @@ public JavaType typeFromId( DatabindContext context, String id ) { @Override public String getDescForKnownTypeIds() { - return idToClass.keySet().stream().collect( Collectors.joining( "," ) ); + init(); + + return String.join( ",", idToClass.keySet() ); } @Override public JsonTypeInfo.Id getMechanism() { return JsonTypeInfo.Id.CLASS; } + + @ToString + public static class Configuration extends ConfigurationLoader.Configuration { + @ToString + @JsonDeserialize( contentUsing = ClassDeserializer.class ) + public static class ClassConfiguration extends LinkedHashMap> { + + } + + } } diff --git a/oap-stdlib/src/main/java/oap/json/ext/ClassLocalExtDeserializer.java b/oap-stdlib/src/main/java/oap/json/ext/ClassLocalExtDeserializer.java deleted file mode 100644 index ac3cf86386..0000000000 --- a/oap-stdlib/src/main/java/oap/json/ext/ClassLocalExtDeserializer.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) Open Application Platform Authors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package oap.json.ext; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.deser.std.StdDeserializer; -import lombok.extern.slf4j.Slf4j; -import oap.io.Resources; -import oap.util.Pair; -import oap.util.Strings; -import org.apache.commons.lang3.StringUtils; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -@Slf4j -public class ClassLocalExtDeserializer extends StdDeserializer { - private static Map, Class> extmap = new HashMap<>(); - - static { - for( var p : Resources.readLines( "META-INF/json-ext.properties" ) ) - try { - if( p.startsWith( "#" ) || StringUtils.isBlank( p ) ) continue; - log.trace( "mapping ext {}", p ); - Pair split = Strings.split( p, "=" ); - extmap.put( Class.forName( split._1.trim() ), Class.forName( split._2.trim() ) ); - } catch( ClassNotFoundException e ) { - throw new ExceptionInInitializerError( e ); - } - log.trace( "mapped extensions: {}", extmap ); - } - - private Class clazz; - - public ClassLocalExtDeserializer( Class clazz ) { - super( clazz ); - this.clazz = clazz; - } - - @Override - @SuppressWarnings( "unchecked" ) - public T deserialize( JsonParser jsonParser, DeserializationContext deserializationContext ) throws IOException { - return ( T ) jsonParser.readValueAs( Objects.requireNonNull( extmap.get( clazz ), "extension class lookup failed for " + clazz ) ); - } -} diff --git a/oap-stdlib/src/main/java/oap/json/ext/ExtDeserializer.java b/oap-stdlib/src/main/java/oap/json/ext/ExtDeserializer.java index d5c41853b2..9f4eb486d1 100644 --- a/oap-stdlib/src/main/java/oap/json/ext/ExtDeserializer.java +++ b/oap-stdlib/src/main/java/oap/json/ext/ExtDeserializer.java @@ -24,62 +24,27 @@ package oap.json.ext; -import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; -import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; -import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; -import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; -import com.jasonclawson.jackson.dataformat.hocon.HoconFactory; import lombok.ToString; import lombok.extern.slf4j.Slf4j; -import oap.io.Resources; +import oap.configuration.ConfigurationLoader; import oap.json.ClassDeserializer; -import oap.json.JsonException; import oap.json.ext.ExtDeserializer.Configuration.ClassConfiguration; -import oap.util.Lists; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; @Slf4j public class ExtDeserializer extends StdDeserializer { - private static final HashMap extmap = new HashMap<>(); - - static { - try { - var list = Lists.concat( - Resources.urls( "META-INF/json-ext.conf" ), - Resources.urls( "META-INF/json-ext.yaml" ) ); - - for( var p : list ) { - log.trace( "mapping ext {}", p ); - - var mapper = new ObjectMapper( p.toString().endsWith( "yaml" ) ? new YAMLFactory() : new HoconFactory() ); - mapper.getDeserializationConfig().with( new JacksonAnnotationIntrospector() ); - mapper.registerModule( new ParameterNamesModule( JsonCreator.Mode.DEFAULT ) ); - - var conf = mapper.readValue( p, Configuration.class ); - - for( var cc : conf.ext ) { - String key = extensionKey( cc.clazz, cc.field ); - var oldConf = extmap.get( key ); - if ( oldConf != null && oldConf.disableOverwrite ) continue; - extmap.put( key, cc ); - log.debug( "add ext rule: {} = {}", key, cc.implementation ); - } - } - } catch( IOException e ) { - throw new JsonException( e ); - } - log.trace( "mapped extensions: {}", extmap ); - } + private static volatile HashMap extmap; protected ExtDeserializer() { this( Ext.class ); @@ -89,11 +54,34 @@ public ExtDeserializer( Class clazz ) { super( clazz ); } + private static void init() { + if( extmap == null ) { + synchronized( ExtDeserializer.class ) { + if( extmap == null ) { + extmap = new HashMap<>(); + List conf = ConfigurationLoader.read( ExtDeserializer.class, new TypeReference<>() {} ); + for( Configuration c : conf ) { + for( ClassConfiguration cc : c.config ) { + String key = extensionKey( cc.clazz, cc.field ); + var oldConf = extmap.get( key ); + if( oldConf != null && oldConf.disableOverwrite ) continue; + extmap.put( key, cc ); + log.debug( "add ext rule: {} = {}", key, cc.implementation ); + } + } + log.trace( "mapped extensions: {}", extmap ); + } + } + } + } + private static String extensionKey( Class clazz, String field ) { return clazz.getName() + "#" + field; } public static Class extensionOf( Class clazz, String field ) { + init(); + var classConfiguration = extmap.get( extensionKey( clazz, field ) ); if( classConfiguration != null ) return classConfiguration.implementation; return null; @@ -101,6 +89,8 @@ public static Class extensionOf( Class clazz, String field ) { @SuppressWarnings( "rawtypes" ) public static Map getDeserializers() { + init(); + var ret = new HashMap(); ret.put( Ext.class, new ExtDeserializer() ); @@ -130,9 +120,7 @@ public Ext deserialize( JsonParser jsonParser, DeserializationContext ctxt ) thr } @ToString - public static class Configuration { - public final ArrayList ext = new ArrayList<>(); - + public static class Configuration extends ConfigurationLoader.Configuration> { @ToString public static class ClassConfiguration { @JsonProperty( "class" ) diff --git a/oap-stdlib/src/main/java/oap/json/properties/PropertiesDeserializer.java b/oap-stdlib/src/main/java/oap/json/properties/PropertiesDeserializer.java new file mode 100644 index 0000000000..af09cf23e4 --- /dev/null +++ b/oap-stdlib/src/main/java/oap/json/properties/PropertiesDeserializer.java @@ -0,0 +1,82 @@ +package oap.json.properties; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonStreamContext; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; +import oap.configuration.ConfigurationLoader; +import oap.json.ClassDeserializer; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; + +@Slf4j +public class PropertiesDeserializer extends JsonDeserializer { + private static volatile HashMap, Configuration.ClassConfiguration> propertiesMap; + + private static void init() { + if( propertiesMap == null ) { + synchronized( PropertiesDeserializer.class ) { + if( propertiesMap == null ) { + propertiesMap = new HashMap<>(); + List conf = ConfigurationLoader.read( PropertiesDeserializer.class, new TypeReference<>() {} ); + for( Configuration c : conf ) { + for( Configuration.ClassConfiguration cc : c.config ) { + var clazz = cc.clazz; + + Configuration.ClassConfiguration classConfiguration = propertiesMap.computeIfAbsent( clazz, + v -> new Configuration.ClassConfiguration() ); + classConfiguration.clazz = clazz; + classConfiguration.properties.putAll( cc.properties ); + } + } + log.trace( "mapped extensions: {}", propertiesMap ); + } + } + } + } + + @Override + public Object deserialize( JsonParser jsonParser, DeserializationContext deserializationContext ) throws IOException { + init(); + + String currentName = jsonParser.getCurrentName(); + JsonStreamContext parsingContext = jsonParser.getParsingContext(); + JsonStreamContext parent = parsingContext.getParent(); + Object currentValue = parent.getCurrentValue(); + + if( currentValue == null ) { // not list/map + currentValue = parsingContext.getCurrentValue(); + } + + Configuration.ClassConfiguration classConfiguration = propertiesMap.get( currentValue.getClass() ); + + Class aClass = classConfiguration != null + ? classConfiguration.properties.getOrDefault( currentName, Object.class ) + : Object.class; + + log.trace( "currentName {} aClass {} currentValue {}", currentName, aClass, currentValue ); + + return deserializationContext.readValue( jsonParser, aClass ); + } + + @ToString + public static class Configuration extends ConfigurationLoader.Configuration> { + @ToString + public static class ClassConfiguration { + @JsonDeserialize( contentUsing = ClassDeserializer.class ) + public final LinkedHashMap> properties = new LinkedHashMap<>(); + @JsonProperty( "class" ) + @JsonDeserialize( using = ClassDeserializer.class ) + public Class clazz; + } + } +} diff --git a/oap-stdlib/src/main/java/oap/net/Inet.java b/oap-stdlib/src/main/java/oap/net/Inet.java index 58410f3a6d..23fe0d4056 100644 --- a/oap-stdlib/src/main/java/oap/net/Inet.java +++ b/oap-stdlib/src/main/java/oap/net/Inet.java @@ -42,7 +42,7 @@ public class Inet { @SneakyThrows private static String resolveLocalhost() { - return InetAddress.getByName( "127.0.0.1" ).getCanonicalHostName(); + return InetAddress.getByName( "localhost" ).getCanonicalHostName(); } @SneakyThrows diff --git a/oap-stdlib/src/main/java/oap/time/JavaTimeService.java b/oap-stdlib/src/main/java/oap/time/JavaTimeService.java deleted file mode 100644 index 3e6ddac6e7..0000000000 --- a/oap-stdlib/src/main/java/oap/time/JavaTimeService.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) Open Application Platform Authors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package oap.time; - -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneOffset; - -public class JavaTimeService implements TimeService { - public static final JavaTimeService INSTANCE = new JavaTimeService(); - - private Clock clock = Clock.system( ZoneOffset.UTC ); - - @Override - public Instant now() { - return Instant.now( clock ); - } - - @Override - public long currentTimeMillis() { - return clock.millis(); - } - - public void useFixedClockAt( Instant date ) { - clock = Clock.fixed( date, ZoneOffset.UTC ); - } - - public void setCurrentMillisFixed( long fixedMillis ) { - clock = Clock.fixed( Instant.ofEpochMilli( fixedMillis ), ZoneOffset.UTC ); - } - - public void setCurrentMillisSystem() { - clock = Clock.system( ZoneOffset.UTC ); - } -} diff --git a/oap-stdlib/src/main/java/oap/time/JodaTimeService.java b/oap-stdlib/src/main/java/oap/time/JodaTimeService.java deleted file mode 100644 index 8f0ec78209..0000000000 --- a/oap-stdlib/src/main/java/oap/time/JodaTimeService.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) Open Application Platform Authors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package oap.time; - -import org.joda.time.DateTimeUtils; - -import java.time.Instant; - -public class JodaTimeService implements TimeService { - public static final JodaTimeService INSTANCE = new JodaTimeService(); - - @Override - public Instant now() { - return Instant.ofEpochMilli( DateTimeUtils.currentTimeMillis() ); - } - - @Override - public long currentTimeMillis() { - return DateTimeUtils.currentTimeMillis(); - } - - public void setCurrentMillisSystem() { - DateTimeUtils.setCurrentMillisSystem(); - } -} diff --git a/oap-stdlib/src/main/java/oap/time/TimeService.java b/oap-stdlib/src/main/java/oap/time/TimeService.java deleted file mode 100644 index 74798175f1..0000000000 --- a/oap-stdlib/src/main/java/oap/time/TimeService.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) Open Application Platform Authors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package oap.time; - -import java.time.Instant; - -public interface TimeService { - Instant now(); - - long currentTimeMillis(); -} diff --git a/oap-stdlib/src/main/resources/META-INF/json-mapping.properties b/oap-stdlib/src/main/resources/META-INF/json-mapping.properties deleted file mode 100644 index dac8010095..0000000000 --- a/oap-stdlib/src/main/resources/META-INF/json-mapping.properties +++ /dev/null @@ -1 +0,0 @@ -oap-pair=oap.util.Pair diff --git a/oap-stdlib/src/main/resources/META-INF/oap-module.conf b/oap-stdlib/src/main/resources/META-INF/oap-module.conf index 2b7eaf19dd..bd64c88260 100644 --- a/oap-stdlib/src/main/resources/META-INF/oap-module.conf +++ b/oap-stdlib/src/main/resources/META-INF/oap-module.conf @@ -1,14 +1,12 @@ name = oap services { - oap-time-java { - name = oap-time - profile = java-time - implementation = oap.time.JavaTimeService - } +} - oap-time-joda { - name = oap-time - profile = -java-time - implementation = oap.time.JodaTimeService +configurations = [ + { + loader = oap.json.TypeIdFactory + config = { + oap-pair = oap.util.Pair + } } -} +] diff --git a/oap-stdlib/src/test/java/oap/json/properties/PropertiesDeserializerTest.java b/oap-stdlib/src/test/java/oap/json/properties/PropertiesDeserializerTest.java new file mode 100644 index 0000000000..03c17d1623 --- /dev/null +++ b/oap-stdlib/src/test/java/oap/json/properties/PropertiesDeserializerTest.java @@ -0,0 +1,57 @@ +package oap.json.properties; + +import oap.json.Binder; +import org.testng.annotations.Test; + +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.entry; + +public class PropertiesDeserializerTest { + @Test + public void testDeserialize() { + var json = """ + { + "property1": { + "name1": "n1", + "name2": "n2" + }, + "property2": { + "name1": 1, + "name2": 2 + }, + "property3": "str", + "property4": 5, + "property5": [ + "list" + ], + "property6": { + "k": "v" + } + } + """; + + TestJsonProperties tp = Binder.json.unmarshal( TestJsonProperties.class, json ); + assertThat( tp.getProperties() ).contains( + entry( "property1", new TestJsonProperties.TestProperty1( "n1", "n2" ) ), + entry( "property2", new TestJsonProperties.TestProperty2( 1, 2 ) ), + entry( "property3", "str" ), + entry( "property4", 5L ), + entry( "property5", List.of( "list" ) ), + entry( "property6", Map.of( "k", "v" ) ) + ); + } + + @Test + public void testUnknownClass() { + var json = """ + { + "a": "b" + } + """; + TestJsonProperties2 tp = Binder.json.unmarshal( TestJsonProperties2.class, json ); + assertThat( tp.getProperties() ).contains( entry( "a", "b" ) ); + } +} diff --git a/oap-stdlib/src/test/java/oap/json/properties/TestJsonProperties.java b/oap-stdlib/src/test/java/oap/json/properties/TestJsonProperties.java new file mode 100644 index 0000000000..01992187dd --- /dev/null +++ b/oap-stdlib/src/test/java/oap/json/properties/TestJsonProperties.java @@ -0,0 +1,55 @@ +package oap.json.properties; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class TestJsonProperties { + private final LinkedHashMap properties = new LinkedHashMap<>(); + + @JsonAnySetter + @JsonDeserialize( contentUsing = PropertiesDeserializer.class ) + public void putProperty( String name, Object value ) { + properties.put( name, value ); + } + + @JsonAnyGetter + public Map getProperties() { + return properties; + } + + @ToString + @EqualsAndHashCode + public static class TestProperty1 { + public String name1; + public String name2; + + public TestProperty1() { + } + + public TestProperty1( String name1, String name2 ) { + this.name1 = name1; + this.name2 = name2; + } + } + + @ToString + @EqualsAndHashCode + public static class TestProperty2 { + public int name1; + public int name2; + + public TestProperty2() { + } + + public TestProperty2( int name1, int name2 ) { + this.name1 = name1; + this.name2 = name2; + } + } +} diff --git a/oap-stdlib/src/test/java/oap/json/properties/TestJsonProperties2.java b/oap-stdlib/src/test/java/oap/json/properties/TestJsonProperties2.java new file mode 100644 index 0000000000..a92fdb3eeb --- /dev/null +++ b/oap-stdlib/src/test/java/oap/json/properties/TestJsonProperties2.java @@ -0,0 +1,23 @@ +package oap.json.properties; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class TestJsonProperties2 { + private final LinkedHashMap properties = new LinkedHashMap<>(); + + @JsonAnySetter + @JsonDeserialize( contentUsing = PropertiesDeserializer.class ) + public void putProperty( String name, Object value ) { + properties.put( name, value ); + } + + @JsonAnyGetter + public Map getProperties() { + return properties; + } +} diff --git a/oap-stdlib/src/test/resources/META-INF/oap-module-include.conf b/oap-stdlib/src/test/resources/META-INF/oap-module-include.conf new file mode 100644 index 0000000000..315579212f --- /dev/null +++ b/oap-stdlib/src/test/resources/META-INF/oap-module-include.conf @@ -0,0 +1 @@ +property2 = oap.json.properties.TestJsonProperties.TestProperty2 diff --git a/oap-stdlib/src/test/resources/META-INF/oap-module.conf b/oap-stdlib/src/test/resources/META-INF/oap-module.conf new file mode 100644 index 0000000000..5607e7981a --- /dev/null +++ b/oap-stdlib/src/test/resources/META-INF/oap-module.conf @@ -0,0 +1,16 @@ +name = oap-stdlib-test + +configurations = [ + { + loader = oap.json.properties.PropertiesDeserializer + config = [ + { + class = oap.json.properties.TestJsonProperties + properties { + property1 = oap.json.properties.TestJsonProperties.TestProperty1 + include required("oap-module-include.conf") + } + } + ] + } +] diff --git a/oap-stdlib/src/test/resources/logback-test.xml b/oap-stdlib/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..c3b11f18e5 --- /dev/null +++ b/oap-stdlib/src/test/resources/logback-test.xml @@ -0,0 +1,19 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + diff --git a/oap-storage/oap-storage-cloud-test/src/main/java/oap/storage/cloud/S3MockFixture.java b/oap-storage/oap-storage-cloud-test/src/main/java/oap/storage/cloud/S3MockFixture.java index 74648e65a6..cad6364ca0 100644 --- a/oap-storage/oap-storage-cloud-test/src/main/java/oap/storage/cloud/S3MockFixture.java +++ b/oap-storage/oap-storage-cloud-test/src/main/java/oap/storage/cloud/S3MockFixture.java @@ -25,6 +25,8 @@ import java.net.URLDecoder; import java.nio.file.Path; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import static java.nio.charset.StandardCharsets.UTF_8; @@ -41,7 +43,7 @@ public class S3MockFixture extends AbstractFixture { private final int port; private final TestDirectoryFixture testDirectoryFixture; private boolean debug = false; - private String initialBuckets = ""; + private final LinkedHashSet initialBuckets = new LinkedHashSet<>(); private S3MockApplication s3MockApplication; public S3MockFixture() { @@ -58,7 +60,7 @@ protected void before() { s3MockApplication = S3MockApplication.start( new LinkedHashMap<>( Map.of( S3MockApplication.PROP_HTTP_PORT, port, - S3MockApplication.PROP_INITIAL_BUCKETS, initialBuckets, + S3MockApplication.PROP_INITIAL_BUCKETS, String.join( ",", initialBuckets ), S3MockApplication.PROP_SILENT, !debug, S3MockApplication.PROP_ROOT_DIRECTORY, testDirectoryFixture.testPath( "s3" ).toString() ) ) ); @@ -71,7 +73,7 @@ public S3MockFixture withDebug( boolean debug ) { } public S3MockFixture withInitialBuckets( String... bucketNames ) { - initialBuckets = String.join( ",", bucketNames ); + initialBuckets.addAll( List.of( bucketNames ) ); return this; } diff --git a/oap-storage/oap-storage-mongo-test/src/test/resources/META-INF/json-mapping.properties b/oap-storage/oap-storage-mongo-test/src/test/resources/META-INF/json-mapping.properties deleted file mode 100644 index 1cb3058a6c..0000000000 --- a/oap-storage/oap-storage-mongo-test/src/test/resources/META-INF/json-mapping.properties +++ /dev/null @@ -1,3 +0,0 @@ -bean=oap.storage.Bean -a=oap.storage.MongoPersistenceTest$PolyBeanA -b=oap.storage.MongoPersistenceTest$PolyBeanB diff --git a/oap-storage/oap-storage-mongo-test/src/test/resources/META-INF/oap-module.conf b/oap-storage/oap-storage-mongo-test/src/test/resources/META-INF/oap-module.conf new file mode 100644 index 0000000000..d833dd16b4 --- /dev/null +++ b/oap-storage/oap-storage-mongo-test/src/test/resources/META-INF/oap-module.conf @@ -0,0 +1,12 @@ +name = oap-storage-mongo-test + +configurations = [ + { + loader = oap.json.TypeIdFactory + config = { + bean = oap.storage.Bean + a = oap.storage.MongoPersistenceTest.PolyBeanA + b = oap.storage.MongoPersistenceTest.PolyBeanB + } + } +] diff --git a/oap-storage/oap-storage-mongo-test/src/test/resources/META-INF/oap-mongo-migration.yaml b/oap-storage/oap-storage-mongo-test/src/test/resources/META-INF/oap-mongo-migration.yaml deleted file mode 100644 index f77376fad2..0000000000 --- a/oap-storage/oap-storage-mongo-test/src/test/resources/META-INF/oap-mongo-migration.yaml +++ /dev/null @@ -1,5 +0,0 @@ -migrations: - beans: - - version: - main: 2 - script: /oap/storage/MongoPersistenceTest/migration/2.migration.js diff --git a/oap-template/src/test/resources/META-INF/json-ext.conf b/oap-template/src/test/resources/META-INF/json-ext.conf deleted file mode 100644 index e2af8352fd..0000000000 --- a/oap-template/src/test/resources/META-INF/json-ext.conf +++ /dev/null @@ -1,24 +0,0 @@ -ext = [ - { - class = oap.template.TestTemplateClass - field = ext - implementation = oap.template.TestTemplateClassExt - } - { - class = oap.template.TestTemplateClass - field = ext2 - abstract = oap.template.TestTemplateClass.ITestTemplateClassExt - implementation = oap.template.TestTemplateClassExt - } - { - class = oap.template.TestTemplateClass2 - field = ext - implementation = oap.template.TestTemplateClassExt2 - } - { - class: oap.template.TestTemplateClass2 - field: ext22 - abstract: oap.template.TestTemplateClass2.ITestTemplateClassExt2 - implementation: oap.template.TestTemplateClassExt2 - } -] diff --git a/oap-template/src/test/resources/META-INF/oap-module.conf b/oap-template/src/test/resources/META-INF/oap-module.conf new file mode 100644 index 0000000000..a655673c52 --- /dev/null +++ b/oap-template/src/test/resources/META-INF/oap-module.conf @@ -0,0 +1,31 @@ +name = oap-template-test + +configurations = [ + { + loader = oap.json.ext.ExtDeserializer + config = [ + { + class = oap.template.TestTemplateClass + field = ext + implementation = oap.template.TestTemplateClassExt + } + { + class = oap.template.TestTemplateClass + field = ext2 + abstract = oap.template.TestTemplateClass.ITestTemplateClassExt + implementation = oap.template.TestTemplateClassExt + } + { + class = oap.template.TestTemplateClass2 + field = ext + implementation = oap.template.TestTemplateClassExt2 + } + { + class: oap.template.TestTemplateClass2 + field: ext22 + abstract: oap.template.TestTemplateClass2.ITestTemplateClassExt2 + implementation: oap.template.TestTemplateClassExt2 + } + ] + } +] \ No newline at end of file diff --git a/oap-ws/oap-ws-admin-ws/src/test/resources/application.test.conf b/oap-ws/oap-ws-admin-ws/src/test/resources/application.test.conf index 4683dd69ac..b794478f8a 100644 --- a/oap-ws/oap-ws-admin-ws/src/test/resources/application.test.conf +++ b/oap-ws/oap-ws-admin-ws/src/test/resources/application.test.conf @@ -1,7 +1,5 @@ boot.main = oap-ws-admin-ws-test -profile = http - services { oap.oap-http-server.parameters.port = ${TEST_HTTP_PORT} diff --git a/oap-ws/oap-ws-api-ws/src/test/resources/META-INF/json-ext.yaml b/oap-ws/oap-ws-api-ws/src/test/resources/META-INF/json-ext.yaml deleted file mode 100644 index 88df776645..0000000000 --- a/oap-ws/oap-ws-api-ws/src/test/resources/META-INF/json-ext.yaml +++ /dev/null @@ -1,4 +0,0 @@ -ext: - - class: oap.ws.api.ExampleWS$Bean - field: ext - implementation: oap.ws.api.ExampleWS$Bean$BeanExt diff --git a/oap-ws/oap-ws-api-ws/src/test/resources/META-INF/oap-module.conf b/oap-ws/oap-ws-api-ws/src/test/resources/META-INF/oap-module.conf index d7e157d306..5aae101bd5 100644 --- a/oap-ws/oap-ws-api-ws/src/test/resources/META-INF/oap-module.conf +++ b/oap-ws/oap-ws-api-ws/src/test/resources/META-INF/oap-module.conf @@ -11,3 +11,16 @@ services { ws-service.path = recursion } } + +configurations = [ + { + loader = oap.json.ext.ExtDeserializer + config = [ + { + class = oap.ws.api.ExampleWS.Bean + field = ext + implementation = "oap.ws.api.ExampleWS$Bean$BeanExt" + } + ] + } +] diff --git a/oap-ws/oap-ws-api-ws/src/test/resources/application.test.conf b/oap-ws/oap-ws-api-ws/src/test/resources/application.test.conf index dee77cf2ac..cd1b5c9085 100644 --- a/oap-ws/oap-ws-api-ws/src/test/resources/application.test.conf +++ b/oap-ws/oap-ws-api-ws/src/test/resources/application.test.conf @@ -1,7 +1,5 @@ boot.main = oap-ws-api-ws-test -profile = http - services { oap-http { oap-http-server.parameters { diff --git a/oap-ws/oap-ws-file-ws/src/test/resources/oap/ws/file/FileWSTest/application.test.conf b/oap-ws/oap-ws-file-ws/src/test/resources/oap/ws/file/FileWSTest/application.test.conf index e14f7f68e9..1eadad8f16 100644 --- a/oap-ws/oap-ws-file-ws/src/test/resources/oap/ws/file/FileWSTest/application.test.conf +++ b/oap-ws/oap-ws-file-ws/src/test/resources/oap/ws/file/FileWSTest/application.test.conf @@ -1,7 +1,5 @@ boot.main = oap-ws-file-ws -profile = http - services { oap.oap-http-server.parameters.port = ${TEST_HTTP_PORT} diff --git a/oap-ws/oap-ws-openapi-ws/src/test/resources/META-INF/json-ext.conf b/oap-ws/oap-ws-openapi-ws/src/test/resources/META-INF/json-ext.conf deleted file mode 100644 index e6441921bd..0000000000 --- a/oap-ws/oap-ws-openapi-ws/src/test/resources/META-INF/json-ext.conf +++ /dev/null @@ -1,12 +0,0 @@ -ext = [ - { - class = oap.ws.openapi.ExampleNewWS.NewWsBean - field = ext - implementation = oap.ws.openapi.DynamicBeanExt - } - { - class = oap.ws.openapi.CreativeUniversal - field = settings - implementation = oap.ws.openapi.AcmeCreativeSettings - } -] \ No newline at end of file diff --git a/oap-ws/oap-ws-openapi-ws/src/test/resources/META-INF/oap-module.conf b/oap-ws/oap-ws-openapi-ws/src/test/resources/META-INF/oap-module.conf index 43361877b8..e7273a0cf1 100644 --- a/oap-ws/oap-ws-openapi-ws/src/test/resources/META-INF/oap-module.conf +++ b/oap-ws/oap-ws-openapi-ws/src/test/resources/META-INF/oap-module.conf @@ -18,3 +18,21 @@ services { ws-service.path = example } } + +configurations = [ + { + loader = oap.json.ext.ExtDeserializer + config = [ + { + class = oap.ws.openapi.ExampleNewWS.NewWsBean + field = ext + implementation = oap.ws.openapi.DynamicBeanExt + } + { + class = oap.ws.openapi.CreativeUniversal + field = settings + implementation = oap.ws.openapi.AcmeCreativeSettings + } + ] + } +] diff --git a/oap-ws/oap-ws-openapi-ws/src/test/resources/application-ws-openapi.test.conf b/oap-ws/oap-ws-openapi-ws/src/test/resources/application-ws-openapi.test.conf index 53109fe5bc..65c50fcbf6 100644 --- a/oap-ws/oap-ws-openapi-ws/src/test/resources/application-ws-openapi.test.conf +++ b/oap-ws/oap-ws-openapi-ws/src/test/resources/application-ws-openapi.test.conf @@ -1,7 +1,5 @@ boot.main = oap-ws-openapi-ws-test -profile = http - services { oap-http { oap-http-server.parameters { diff --git a/oap-ws/oap-ws-test/src/test/resources/application-ws.test.conf b/oap-ws/oap-ws-test/src/test/resources/application-ws.test.conf index 26a112efe8..9fc0f7cbe8 100644 --- a/oap-ws/oap-ws-test/src/test/resources/application-ws.test.conf +++ b/oap-ws/oap-ws-test/src/test/resources/application-ws.test.conf @@ -1,5 +1,4 @@ profiles = [ - http test-profile ] diff --git a/pom.xml b/pom.xml index cc12dba31e..1fcf7c2bc2 100644 --- a/pom.xml +++ b/pom.xml @@ -72,7 +72,7 @@ - 21.18.2 + 21.19.0 21.0.0 21.0.1