From 36d97004dc6923b327b5136b240e140467994bf2 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Mon, 6 Nov 2023 17:25:02 +0100 Subject: [PATCH 001/126] fix config service name --- ...ipse.serializer.configuration.types.ConfigurationBasedCreator} | 0 ...ipse.serializer.configuration.types.ConfigurationBasedCreator} | 0 ...ipse.serializer.configuration.types.ConfigurationBasedCreator} | 0 ...ipse.serializer.configuration.types.ConfigurationBasedCreator} | 0 ...ipse.serializer.configuration.types.ConfigurationBasedCreator} | 0 ...ipse.serializer.configuration.types.ConfigurationBasedCreator} | 0 ...ipse.serializer.configuration.types.ConfigurationBasedCreator} | 0 ...ipse.serializer.configuration.types.ConfigurationBasedCreator} | 0 ...ipse.serializer.configuration.types.ConfigurationBasedCreator} | 0 ...ipse.serializer.configuration.types.ConfigurationBasedCreator} | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename afs/aws/dynamodb/src/main/resources/META-INF/services/{org.eclipse.store.configuration.types.ConfigurationBasedCreator => org.eclipse.serializer.configuration.types.ConfigurationBasedCreator} (100%) rename afs/aws/s3/src/main/resources/META-INF/services/{org.eclipse.store.configuration.types.ConfigurationBasedCreator => org.eclipse.serializer.configuration.types.ConfigurationBasedCreator} (100%) rename afs/azure/storage/src/main/resources/META-INF/services/{org.eclipse.store.configuration.types.ConfigurationBasedCreator => org.eclipse.serializer.configuration.types.ConfigurationBasedCreator} (100%) rename afs/googlecloud/firestore/src/main/resources/META-INF/services/{org.eclipse.storage.configuration.types.ConfigurationBasedCreator => org.eclipse.serializer.configuration.types.ConfigurationBasedCreator} (100%) rename afs/hazelcast/src/main/resources/META-INF/services/{org.eclipse.store.configuration.types.ConfigurationBasedCreator => org.eclipse.serializer.configuration.types.ConfigurationBasedCreator} (100%) rename afs/kafka/src/main/resources/META-INF/services/{org.eclipse.store.configuration.types.ConfigurationBasedCreator => org.eclipse.serializer.configuration.types.ConfigurationBasedCreator} (100%) rename afs/oracle/coherence/src/main/resources/META-INF/services/{org.eclipse.store.configuration.types.ConfigurationBasedCreator => org.eclipse.serializer.configuration.types.ConfigurationBasedCreator} (100%) rename afs/oraclecloud/objectstorage/src/main/resources/META-INF/services/{org.eclipse.store.configuration.types.ConfigurationBasedCreator => org.eclipse.serializer.configuration.types.ConfigurationBasedCreator} (100%) rename afs/redis/src/main/resources/META-INF/services/{org.eclipse.store.configuration.types.ConfigurationBasedCreator => org.eclipse.serializer.configuration.types.ConfigurationBasedCreator} (100%) rename afs/sql/src/main/resources/META-INF/services/{org.eclipse.store.configuration.types.ConfigurationBasedCreator => org.eclipse.serializer.configuration.types.ConfigurationBasedCreator} (100%) diff --git a/afs/aws/dynamodb/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator b/afs/aws/dynamodb/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator similarity index 100% rename from afs/aws/dynamodb/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator rename to afs/aws/dynamodb/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator diff --git a/afs/aws/s3/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator b/afs/aws/s3/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator similarity index 100% rename from afs/aws/s3/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator rename to afs/aws/s3/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator diff --git a/afs/azure/storage/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator b/afs/azure/storage/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator similarity index 100% rename from afs/azure/storage/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator rename to afs/azure/storage/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator diff --git a/afs/googlecloud/firestore/src/main/resources/META-INF/services/org.eclipse.storage.configuration.types.ConfigurationBasedCreator b/afs/googlecloud/firestore/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator similarity index 100% rename from afs/googlecloud/firestore/src/main/resources/META-INF/services/org.eclipse.storage.configuration.types.ConfigurationBasedCreator rename to afs/googlecloud/firestore/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator diff --git a/afs/hazelcast/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator b/afs/hazelcast/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator similarity index 100% rename from afs/hazelcast/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator rename to afs/hazelcast/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator diff --git a/afs/kafka/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator b/afs/kafka/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator similarity index 100% rename from afs/kafka/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator rename to afs/kafka/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator diff --git a/afs/oracle/coherence/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator b/afs/oracle/coherence/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator similarity index 100% rename from afs/oracle/coherence/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator rename to afs/oracle/coherence/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator diff --git a/afs/oraclecloud/objectstorage/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator b/afs/oraclecloud/objectstorage/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator similarity index 100% rename from afs/oraclecloud/objectstorage/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator rename to afs/oraclecloud/objectstorage/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator diff --git a/afs/redis/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator b/afs/redis/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator similarity index 100% rename from afs/redis/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator rename to afs/redis/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator diff --git a/afs/sql/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator b/afs/sql/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator similarity index 100% rename from afs/sql/src/main/resources/META-INF/services/org.eclipse.store.configuration.types.ConfigurationBasedCreator rename to afs/sql/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator From 5f67d6ccfa140804c13cd26036d4c2fae4867076 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 7 Nov 2023 10:11:54 +0100 Subject: [PATCH 002/126] update eclipse.serializer version to 1.1.0-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 694168ed..57bed089 100644 --- a/pom.xml +++ b/pom.xml @@ -47,7 +47,7 @@ ${basedir}/LICENSE 1 false - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT 2 2 From d3d81a410a3e52fdeceb1d07b4617f81d51d2961 Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Thu, 9 Nov 2023 07:27:25 +0100 Subject: [PATCH 003/126] Update continuous-backup.adoc --- .../backup/continuous-backup.adoc | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/docs/modules/storage/pages/configuration/backup/continuous-backup.adoc b/docs/modules/storage/pages/configuration/backup/continuous-backup.adoc index 871ebb52..37bd9dd8 100644 --- a/docs/modules/storage/pages/configuration/backup/continuous-backup.adoc +++ b/docs/modules/storage/pages/configuration/backup/continuous-backup.adoc @@ -52,3 +52,55 @@ StorageConfiguration configuration = StorageConfiguration.Builder() ; ---- +== Storage Targets +The continuous backup can be written to all supported xref:storage-targets/index.adoc[storage targets]. + +[source,java,title="foundation classes:"] +---- +SQLiteDataSource dataSource = new SQLiteDataSource(); +dataSource.setUrl("jdbc:sqlite:eclipsestore_bkup_db"); + +SqlFileSystem fileSystem = SqlFileSystem.New( + SqlConnector.Caching( + SqlProviderSqlite.New(dataSource) + ) +); + +StorageBackupSetup backupSetup = StorageBackupSetup.New( + Sorage.BackupFileProviderBuilder(fileSystem) + .setDirectory(fileSystem.ensureDirectoryPath(BACKUPDIR)) + .setTruncationDirectory(fileSystem.ensureDirectoryPath(TRUNCATIONDIR)) + .setDeletionDirectory(fileSystem.ensureDirectoryPath(DELETIONDIR)) + .createFileProvider() +); + +StorageConfiguration configuration = StorageConfiguration.Builder() + .setBackupSetup(backupSetup) + .setStorageFileProvider(StorageLiveFileProvider.New( + fileSystem.ensureDirectoryPath(WORKINGDIR) + )) + .createConfiguration() +; + + +---- + +When using external configuration the specific target configuration must be applied to the `backup-filesystem` property: + +[source,text,title="external configuration:"] +---- +storage-filesystem.sql.sqlite.data-source-provider=com.sample.MyDataSourceProvider +storage-filesystem.sql.sqlite.catalog=mycatalog +storage-filesystem.sql.sqlite.schema=myschema +storage-filesystem.sql.sqlite.url=jdbc:sqlite:eclipsestoredb + +storage-directory=storageDir + +backup-filesystem.sql.sqlite.data-source-provider=com.sample.MyDataSourceProvider +backup-filesystem.sql.sqlite.catalog=mycatalog +backup-filesystem.sql.sqlite.schema=myschema +backup-filesystem.sql.sqlite.url=jdbc:sqlite:eclipsestore_bkup_db + +backup-directory=backupDir +---- + From 56957f0045f88508ab9260f6610b877e735c32b5 Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Fri, 10 Nov 2023 10:15:15 +0100 Subject: [PATCH 004/126] Update continuous-backup.adoc --- .../configuration/backup/continuous-backup.adoc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/docs/modules/storage/pages/configuration/backup/continuous-backup.adoc b/docs/modules/storage/pages/configuration/backup/continuous-backup.adoc index 37bd9dd8..b7369a12 100644 --- a/docs/modules/storage/pages/configuration/backup/continuous-backup.adoc +++ b/docs/modules/storage/pages/configuration/backup/continuous-backup.adoc @@ -58,7 +58,7 @@ The continuous backup can be written to all supported xref:storage-targets/index [source,java,title="foundation classes:"] ---- SQLiteDataSource dataSource = new SQLiteDataSource(); -dataSource.setUrl("jdbc:sqlite:eclipsestore_bkup_db"); +dataSource.setUrl("jdbc:sqlite:microstream_bkup_db"); SqlFileSystem fileSystem = SqlFileSystem.New( SqlConnector.Caching( @@ -89,18 +89,17 @@ When using external configuration the specific target configuration must be appl [source,text,title="external configuration:"] ---- -storage-filesystem.sql.sqlite.data-source-provider=com.sample.MyDataSourceProvider -storage-filesystem.sql.sqlite.catalog=mycatalog -storage-filesystem.sql.sqlite.schema=myschema -storage-filesystem.sql.sqlite.url=jdbc:sqlite:eclipsestoredb +storage-filesystem.aws.s3.credentials.type=static +storage-filesystem.aws.s3.credentials.access-key-id=my-access-key-id +storage-filesystem.aws.s3.credentials.secret-acces-key=my-secret-access-key +storage-filesystem.aws.s3.credentials.region=us-east-1 storage-directory=storageDir backup-filesystem.sql.sqlite.data-source-provider=com.sample.MyDataSourceProvider backup-filesystem.sql.sqlite.catalog=mycatalog backup-filesystem.sql.sqlite.schema=myschema -backup-filesystem.sql.sqlite.url=jdbc:sqlite:eclipsestore_bkup_db +backup-filesystem.sql.sqlite.url=jdbc:sqlite:microstream_bkup_db backup-directory=backupDir ---- - From e9050e26de5ce557beca150cddd1620289b84e75 Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Fri, 10 Nov 2023 10:32:22 +0100 Subject: [PATCH 005/126] changed naming from microstream to eclipse --- .../storage/pages/configuration/backup/continuous-backup.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/modules/storage/pages/configuration/backup/continuous-backup.adoc b/docs/modules/storage/pages/configuration/backup/continuous-backup.adoc index b7369a12..663d2223 100644 --- a/docs/modules/storage/pages/configuration/backup/continuous-backup.adoc +++ b/docs/modules/storage/pages/configuration/backup/continuous-backup.adoc @@ -58,7 +58,7 @@ The continuous backup can be written to all supported xref:storage-targets/index [source,java,title="foundation classes:"] ---- SQLiteDataSource dataSource = new SQLiteDataSource(); -dataSource.setUrl("jdbc:sqlite:microstream_bkup_db"); +dataSource.setUrl("jdbc:sqlite:eclipsestore_bkup_db"); SqlFileSystem fileSystem = SqlFileSystem.New( SqlConnector.Caching( @@ -99,7 +99,7 @@ storage-directory=storageDir backup-filesystem.sql.sqlite.data-source-provider=com.sample.MyDataSourceProvider backup-filesystem.sql.sqlite.catalog=mycatalog backup-filesystem.sql.sqlite.schema=myschema -backup-filesystem.sql.sqlite.url=jdbc:sqlite:microstream_bkup_db +backup-filesystem.sql.sqlite.url=jdbc:sqlite:eclipsestore_bkup_db_bkup_db backup-directory=backupDir ---- From ab6c985c4fbd7e4a0b314e0d794588ff495effdd Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Fri, 10 Nov 2023 14:30:50 +0100 Subject: [PATCH 006/126] Add examples (#55) * Add examples * add maven profile + script --------- Co-authored-by: Zdenek Jonas --- .github/workflows/maven_build.yml | 5 +- examples/LICENSE | 277 ++++++++++++++++++ examples/blobs/LICENSE | 277 ++++++++++++++++++ examples/blobs/pom.xml | 28 ++ .../store/examples/blobs/FileAsset.java | 49 ++++ .../store/examples/blobs/FileAssets.java | 77 +++++ .../eclipse/store/examples/blobs/Main.java | 86 ++++++ .../eclipse/store/examples/blobs/MyRoot.java | 33 +++ examples/custom-legacy-type-handler/LICENSE | 277 ++++++++++++++++++ examples/custom-legacy-type-handler/pom.xml | 34 +++ .../LegacyTypeHandlerNicePlace.java | 95 ++++++ .../customlegacytypehandler/Location.java | 37 +++ .../customlegacytypehandler/Main.java | 124 ++++++++ .../customlegacytypehandler/NicePlace.java | 93 ++++++ examples/custom-type-handler/LICENSE | 277 ++++++++++++++++++ examples/custom-type-handler/pom.xml | 35 +++ .../CustomBufferedImageHandler.java | 118 ++++++++ .../examples/customtypehandler/Employee.java | 104 +++++++ .../examples/customtypehandler/Order.java | 92 ++++++ .../customtypehandler/OrderBinaryHandler.java | 160 ++++++++++ examples/deleting/LICENSE | 277 ++++++++++++++++++ examples/deleting/pom.xml | 30 ++ .../eclipse/store/examples/deleting/Main.java | 92 ++++++ .../store/examples/deleting/MyData.java | 56 ++++ .../store/examples/deleting/MyRoot.java | 23 ++ examples/eager-storing/LICENSE | 277 ++++++++++++++++++ examples/eager-storing/pom.xml | 31 ++ .../store/examples/eagerstoring/Main.java | 70 +++++ .../store/examples/eagerstoring/MyRoot.java | 27 ++ .../examples/eagerstoring/StoreEager.java | 30 ++ .../eagerstoring/StoreEagerEvaluator.java | 37 +++ examples/extension-wrapper/LICENSE | 277 ++++++++++++++++++ examples/extension-wrapper/pom.xml | 28 ++ .../store/examples/extensionwrapper/Main.java | 55 ++++ .../PersistenceStorerExtension.java | 114 +++++++ .../PersistenceStorerWrapper.java | 126 ++++++++ .../PersistenceTargetExtension.java | 44 +++ .../PersistenceTargetWrapper.java | 48 +++ .../extensionwrapper/StorageExtender.java | 43 +++ examples/filesystems/LICENSE | 277 ++++++++++++++++++ examples/filesystems/pom.xml | 34 +++ .../filesystems/nio/NioFilesystemJimfs.java | 49 ++++ examples/helloworld-ini/LICENSE | 277 ++++++++++++++++++ examples/helloworld-ini/pom.xml | 35 +++ .../store/examples/helloworld/DataRoot.java | 42 +++ .../store/examples/helloworld/HelloWorld.java | 56 ++++ .../META-INF/eclipsestore/storage.ini | 2 + examples/helloworld/LICENSE | 277 ++++++++++++++++++ examples/helloworld/pom.xml | 30 ++ .../store/examples/helloworld/DataRoot.java | 42 +++ .../store/examples/helloworld/HelloWorld.java | 48 +++ examples/items/LICENSE | 277 ++++++++++++++++++ examples/items/pom.xml | 43 +++ .../store/examples/items/Commands.java | 209 +++++++++++++ .../store/examples/items/DataRoot.java | 35 +++ .../eclipse/store/examples/items/Item.java | 51 ++++ .../eclipse/store/examples/items/Main.java | 170 +++++++++++ examples/layered-entities/LICENSE | 277 ++++++++++++++++++ examples/layered-entities/pom.xml | 86 ++++++ .../examples/layeredentities/Address.java | 26 ++ .../examples/layeredentities/Animal.java | 22 ++ .../examples/layeredentities/Beeing.java | 20 ++ .../layeredentities/EntityFactory.java | 62 ++++ .../store/examples/layeredentities/Human.java | 22 ++ .../examples/layeredentities/JulLogger.java | 46 +++ .../layeredentities/LayeredEntities.java | 56 ++++ .../store/examples/layeredentities/Named.java | 20 ++ .../store/examples/layeredentities/Pet.java | 20 ++ examples/lazy-loading/LICENSE | 277 ++++++++++++++++++ examples/lazy-loading/pom.xml | 35 +++ .../examples/lazyLoading/BusinessYear.java | 54 ++++ .../store/examples/lazyLoading/Main.java | 121 ++++++++ .../examples/lazyLoading/MyBusinessApp.java | 34 +++ .../store/examples/lazyLoading/Turnover.java | 41 +++ examples/loading/LICENSE | 277 ++++++++++++++++++ examples/loading/pom.xml | 35 +++ .../eclipse/store/examples/loading/Main.java | 58 ++++ .../store/examples/loading/MyData.java | 56 ++++ .../store/examples/loading/MyRoot.java | 23 ++ examples/pom.xml | 80 +++++ examples/reloader/LICENSE | 277 ++++++++++++++++++ examples/reloader/pom.xml | 30 ++ .../store/examples/reloader/DataRoot.java | 34 +++ .../examples/reloader/ExampleProgram.java | 65 ++++ .../examples/reloader/StorageProvider.java | 33 +++ examples/storing/LICENSE | 277 ++++++++++++++++++ examples/storing/pom.xml | 36 +++ .../microstream/examples/storing/Main.java | 56 ++++ .../microstream/examples/storing/MyData.java | 55 ++++ .../microstream/examples/storing/MyRoot.java | 23 ++ pom.xml | 6 + 91 files changed, 8555 insertions(+), 2 deletions(-) create mode 100644 examples/LICENSE create mode 100644 examples/blobs/LICENSE create mode 100644 examples/blobs/pom.xml create mode 100644 examples/blobs/src/main/java/org/eclipse/store/examples/blobs/FileAsset.java create mode 100644 examples/blobs/src/main/java/org/eclipse/store/examples/blobs/FileAssets.java create mode 100644 examples/blobs/src/main/java/org/eclipse/store/examples/blobs/Main.java create mode 100644 examples/blobs/src/main/java/org/eclipse/store/examples/blobs/MyRoot.java create mode 100644 examples/custom-legacy-type-handler/LICENSE create mode 100644 examples/custom-legacy-type-handler/pom.xml create mode 100644 examples/custom-legacy-type-handler/src/main/java/org/eclipse/store/examples/customlegacytypehandler/LegacyTypeHandlerNicePlace.java create mode 100644 examples/custom-legacy-type-handler/src/main/java/org/eclipse/store/examples/customlegacytypehandler/Location.java create mode 100644 examples/custom-legacy-type-handler/src/main/java/org/eclipse/store/examples/customlegacytypehandler/Main.java create mode 100644 examples/custom-legacy-type-handler/src/main/java/org/eclipse/store/examples/customlegacytypehandler/NicePlace.java create mode 100644 examples/custom-type-handler/LICENSE create mode 100644 examples/custom-type-handler/pom.xml create mode 100644 examples/custom-type-handler/src/main/java/org/eclipse/store/examples/customtypehandler/CustomBufferedImageHandler.java create mode 100644 examples/custom-type-handler/src/main/java/org/eclipse/store/examples/customtypehandler/Employee.java create mode 100644 examples/custom-type-handler/src/main/java/org/eclipse/store/examples/customtypehandler/Order.java create mode 100644 examples/custom-type-handler/src/main/java/org/eclipse/store/examples/customtypehandler/OrderBinaryHandler.java create mode 100644 examples/deleting/LICENSE create mode 100644 examples/deleting/pom.xml create mode 100644 examples/deleting/src/main/java/org/eclipse/store/examples/deleting/Main.java create mode 100644 examples/deleting/src/main/java/org/eclipse/store/examples/deleting/MyData.java create mode 100644 examples/deleting/src/main/java/org/eclipse/store/examples/deleting/MyRoot.java create mode 100644 examples/eager-storing/LICENSE create mode 100644 examples/eager-storing/pom.xml create mode 100644 examples/eager-storing/src/main/java/org/eclipse/store/examples/eagerstoring/Main.java create mode 100644 examples/eager-storing/src/main/java/org/eclipse/store/examples/eagerstoring/MyRoot.java create mode 100644 examples/eager-storing/src/main/java/org/eclipse/store/examples/eagerstoring/StoreEager.java create mode 100644 examples/eager-storing/src/main/java/org/eclipse/store/examples/eagerstoring/StoreEagerEvaluator.java create mode 100644 examples/extension-wrapper/LICENSE create mode 100644 examples/extension-wrapper/pom.xml create mode 100644 examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/Main.java create mode 100644 examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceStorerExtension.java create mode 100644 examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceStorerWrapper.java create mode 100644 examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceTargetExtension.java create mode 100644 examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceTargetWrapper.java create mode 100644 examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/StorageExtender.java create mode 100644 examples/filesystems/LICENSE create mode 100644 examples/filesystems/pom.xml create mode 100644 examples/filesystems/src/main/java/org/eclipse/store/examples/filesystems/nio/NioFilesystemJimfs.java create mode 100644 examples/helloworld-ini/LICENSE create mode 100644 examples/helloworld-ini/pom.xml create mode 100644 examples/helloworld-ini/src/main/java/org/eclipse/store/examples/helloworld/DataRoot.java create mode 100644 examples/helloworld-ini/src/main/java/org/eclipse/store/examples/helloworld/HelloWorld.java create mode 100644 examples/helloworld-ini/src/main/resources/META-INF/eclipsestore/storage.ini create mode 100644 examples/helloworld/LICENSE create mode 100644 examples/helloworld/pom.xml create mode 100644 examples/helloworld/src/main/java/org/eclipse/store/examples/helloworld/DataRoot.java create mode 100644 examples/helloworld/src/main/java/org/eclipse/store/examples/helloworld/HelloWorld.java create mode 100644 examples/items/LICENSE create mode 100644 examples/items/pom.xml create mode 100644 examples/items/src/main/java/org/eclipse/store/examples/items/Commands.java create mode 100644 examples/items/src/main/java/org/eclipse/store/examples/items/DataRoot.java create mode 100644 examples/items/src/main/java/org/eclipse/store/examples/items/Item.java create mode 100644 examples/items/src/main/java/org/eclipse/store/examples/items/Main.java create mode 100644 examples/layered-entities/LICENSE create mode 100644 examples/layered-entities/pom.xml create mode 100644 examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Address.java create mode 100644 examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Animal.java create mode 100644 examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Beeing.java create mode 100644 examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/EntityFactory.java create mode 100644 examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Human.java create mode 100644 examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/JulLogger.java create mode 100644 examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/LayeredEntities.java create mode 100644 examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Named.java create mode 100644 examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Pet.java create mode 100644 examples/lazy-loading/LICENSE create mode 100644 examples/lazy-loading/pom.xml create mode 100644 examples/lazy-loading/src/main/java/org/eclipse/store/examples/lazyLoading/BusinessYear.java create mode 100644 examples/lazy-loading/src/main/java/org/eclipse/store/examples/lazyLoading/Main.java create mode 100644 examples/lazy-loading/src/main/java/org/eclipse/store/examples/lazyLoading/MyBusinessApp.java create mode 100644 examples/lazy-loading/src/main/java/org/eclipse/store/examples/lazyLoading/Turnover.java create mode 100644 examples/loading/LICENSE create mode 100644 examples/loading/pom.xml create mode 100644 examples/loading/src/main/java/org/eclipse/store/examples/loading/Main.java create mode 100644 examples/loading/src/main/java/org/eclipse/store/examples/loading/MyData.java create mode 100644 examples/loading/src/main/java/org/eclipse/store/examples/loading/MyRoot.java create mode 100644 examples/pom.xml create mode 100644 examples/reloader/LICENSE create mode 100644 examples/reloader/pom.xml create mode 100644 examples/reloader/src/main/java/org/eclipse/store/examples/reloader/DataRoot.java create mode 100644 examples/reloader/src/main/java/org/eclipse/store/examples/reloader/ExampleProgram.java create mode 100644 examples/reloader/src/main/java/org/eclipse/store/examples/reloader/StorageProvider.java create mode 100644 examples/storing/LICENSE create mode 100644 examples/storing/pom.xml create mode 100644 examples/storing/src/main/java/one/microstream/examples/storing/Main.java create mode 100644 examples/storing/src/main/java/one/microstream/examples/storing/MyData.java create mode 100644 examples/storing/src/main/java/one/microstream/examples/storing/MyRoot.java diff --git a/.github/workflows/maven_build.yml b/.github/workflows/maven_build.yml index 51f6c1d3..23436f2d 100644 --- a/.github/workflows/maven_build.yml +++ b/.github/workflows/maven_build.yml @@ -5,7 +5,8 @@ name: Java CI with Maven on: push: - branches: [ main] + branches: + - '*' pull_request: branches: [ main ] @@ -24,4 +25,4 @@ jobs: distribution: 'temurin' cache: 'maven' - name: Build with Maven - run: mvn -B package --file pom.xml -U + run: mvn -P examples -B package --file pom.xml -U diff --git a/examples/LICENSE b/examples/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/examples/blobs/LICENSE b/examples/blobs/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/blobs/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/examples/blobs/pom.xml b/examples/blobs/pom.xml new file mode 100644 index 00000000..c7c277bc --- /dev/null +++ b/examples/blobs/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + + org.eclipse.store + examples-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + examples-blobs + + EclipseStore Example Blobs + EclipseStore Blobs Example + https://projects.eclipse.org/projects/technology.store + + + + org.eclipse.store + storage-embedded + 1.0.0-SNAPSHOT + + + + diff --git a/examples/blobs/src/main/java/org/eclipse/store/examples/blobs/FileAsset.java b/examples/blobs/src/main/java/org/eclipse/store/examples/blobs/FileAsset.java new file mode 100644 index 00000000..a5b2f23b --- /dev/null +++ b/examples/blobs/src/main/java/org/eclipse/store/examples/blobs/FileAsset.java @@ -0,0 +1,49 @@ + +package org.eclipse.store.examples.blobs; + +/*- + * #%L + * EclipseStore Example Blobs + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.UUID; + +public class FileAsset +{ + private final String path; + private final String name; + private final String uuid; + + public FileAsset(final String path, final String name) + { + super(); + + this.path = path; + this.name = name; + this.uuid = UUID.randomUUID().toString(); + } + + public String getPath() + { + return this.path; + } + + public String getName() + { + return this.name; + } + + public String getUUID() + { + return this.uuid; + } +} diff --git a/examples/blobs/src/main/java/org/eclipse/store/examples/blobs/FileAssets.java b/examples/blobs/src/main/java/org/eclipse/store/examples/blobs/FileAssets.java new file mode 100644 index 00000000..15323a40 --- /dev/null +++ b/examples/blobs/src/main/java/org/eclipse/store/examples/blobs/FileAssets.java @@ -0,0 +1,77 @@ + +package org.eclipse.store.examples.blobs; + +/*- + * #%L + * EclipseStore Example Blobs + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.io.File; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.serializer.persistence.types.Storer; + + +public class FileAssets implements Iterable +{ + private final File root; + private final Map registry; + + public FileAssets(final File root) + { + super(); + + this.root = root; + this.registry = new HashMap<>(); + } + + public FileAssets registerFileAsset(final FileAsset fileAsset) + { + this.registry.put(fileAsset.getUUID(), fileAsset); + return this; + } + + public FileAsset getFileAssetById(final String uuid) + { + return this.registry.get(uuid); + } + + public FileAsset getFileAssetByName(final String name) + { + return this.registry.values().stream() + .filter(fileAsset -> fileAsset.getName().equals(name)) + .findFirst() + .orElse(null); + } + + public File getAssetFile(final FileAsset asset) + { + final File file = new File(this.root, asset.getPath()); + file.getParentFile().mkdirs(); + return file; + } + + @Override + public Iterator iterator() + { + return this.registry.values().iterator(); + } + + public S store(final S storer) + { + storer.store(this.registry); + storer.store(this); + return storer; + } +} diff --git a/examples/blobs/src/main/java/org/eclipse/store/examples/blobs/Main.java b/examples/blobs/src/main/java/org/eclipse/store/examples/blobs/Main.java new file mode 100644 index 00000000..9d78d0af --- /dev/null +++ b/examples/blobs/src/main/java/org/eclipse/store/examples/blobs/Main.java @@ -0,0 +1,86 @@ + +package org.eclipse.store.examples.blobs; + +/*- + * #%L + * EclipseStore Example Blobs + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import org.eclipse.serializer.exceptions.IORuntimeException; +import org.eclipse.store.storage.embedded.types.EmbeddedStorage; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + + +/** + * + * A simple example how to handle blobs (or large binary data). + * Best practice is to just have a metadata object ({@link FileAsset}) in the persistent object graph, + * and the actual file data outside in a dedicated directory. + * + */ +public class Main +{ + public static void main(final String[] args) + { + // Init storage manager + final EmbeddedStorageManager storage = EmbeddedStorage.start(); + + // if storage.root() returns null no data have been loaded + // since there is no existing database, let's create a new one. + if(storage.root() == null) + { + System.out.println("No existing Database found, creating a new one:"); + + final MyRoot root = new MyRoot(); + + createSampleAsset(root, "testfiles/sample.xml", "sample.xml", + "\n\n"); + createSampleAsset(root, "testfiles/sample.json", "sample.json", "{\n\t\"number\":1,\n\t\"text\":\"string\"\n}"); + + storage.setRoot(root); + storage.storeRoot(); + } + // storage.root() is not null so we have loaded data + else + { + System.out.println("Existing Database found:"); + } + + final MyRoot root = (MyRoot)storage.root(); + for(final FileAsset fileAsset : root.getFileAssets()) + { + System.out.println("File asset '" + fileAsset.getName() + "' file = " + + root.getFileAssets().getAssetFile(fileAsset).getAbsolutePath()); + } + + storage.shutdown(); + } + + private static void createSampleAsset(final MyRoot root, final String path, final String name, final String contents) + { + final FileAsset asset = new FileAsset(path, name); + final FileAssets fileAssets = root.getFileAssets(); + final File file = fileAssets.registerFileAsset(asset).getAssetFile(asset); + try(FileWriter writer = new FileWriter(file)) + { + writer.write(contents); + } + catch(final IOException e) + { + throw new IORuntimeException(e); + } + } +} diff --git a/examples/blobs/src/main/java/org/eclipse/store/examples/blobs/MyRoot.java b/examples/blobs/src/main/java/org/eclipse/store/examples/blobs/MyRoot.java new file mode 100644 index 00000000..8ffcca8e --- /dev/null +++ b/examples/blobs/src/main/java/org/eclipse/store/examples/blobs/MyRoot.java @@ -0,0 +1,33 @@ + +package org.eclipse.store.examples.blobs; + +/*- + * #%L + * EclipseStore Example Blobs + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.io.File; + +public class MyRoot +{ + private final FileAssets fileAssets = new FileAssets(new File("assets")); + + public MyRoot() + { + super(); + } + + public FileAssets getFileAssets() + { + return this.fileAssets; + } +} diff --git a/examples/custom-legacy-type-handler/LICENSE b/examples/custom-legacy-type-handler/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/custom-legacy-type-handler/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/examples/custom-legacy-type-handler/pom.xml b/examples/custom-legacy-type-handler/pom.xml new file mode 100644 index 00000000..7b783402 --- /dev/null +++ b/examples/custom-legacy-type-handler/pom.xml @@ -0,0 +1,34 @@ + + + + + 4.0.0 + + + org.eclipse.store + examples-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + examples-custom-legacy-type-handler + + EclipseStore Example Legacy Type Handler + EclipseStore Legacy Type Handler Example + https://projects.eclipse.org/projects/technology.store + + + + org.eclipse.store + storage-embedded + 1.0.0-SNAPSHOT + + + org.eclipse.serializer + persistence-binary-jdk8 + 1.0.0-SNAPSHOT + + + diff --git a/examples/custom-legacy-type-handler/src/main/java/org/eclipse/store/examples/customlegacytypehandler/LegacyTypeHandlerNicePlace.java b/examples/custom-legacy-type-handler/src/main/java/org/eclipse/store/examples/customlegacytypehandler/LegacyTypeHandlerNicePlace.java new file mode 100644 index 00000000..c16a3a72 --- /dev/null +++ b/examples/custom-legacy-type-handler/src/main/java/org/eclipse/store/examples/customlegacytypehandler/LegacyTypeHandlerNicePlace.java @@ -0,0 +1,95 @@ +package org.eclipse.store.examples.customlegacytypehandler; + +/*- + * #%L + * EclipseStore Example Legacy Type Handler + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.persistence.binary.types.Binary; +import org.eclipse.serializer.persistence.binary.types.BinaryLegacyTypeHandler; +import org.eclipse.serializer.persistence.types.PersistenceLoadHandler; +import org.eclipse.serializer.persistence.types.PersistenceReferenceLoader; +import org.eclipse.serializer.util.X; + +public class LegacyTypeHandlerNicePlace extends BinaryLegacyTypeHandler.AbstractCustom +{ + //need to know the binary layout of the persisted legacy class + private static final long + BINARY_OFFSET_name = 0, + BINARY_OFFSET_directions = BINARY_OFFSET_name + Binary.objectIdByteLength(); + + + public LegacyTypeHandlerNicePlace() + { + //introduce the field names of the legacy class + super(NicePlace.class, + X.List(CustomField(String.class,"name"), + CustomField(String.class,"directions"))); + } + + @Override + public boolean hasPersistedReferences() + { + // persisted data records have references to other persisted data records + return true; + } + + @Override + public boolean hasVaryingPersistedLengthInstances() + { + /*the same instance can never have a varying persisted length, since the NicePlace class + *only has to references as member. + * + * Collections are an example for variable length instances. + * The same collection instance can contain 2 elements at one store and 3 at another store. + */ + + return false; + } + + + @Override + public NicePlace create( + final Binary bytes, + final PersistenceLoadHandler loadHandler + ) + { + //required instances may not be available, yet, at creation time. Thus create dummy and fill in #update. + return new NicePlace(); + } + + @Override + public void updateState( + final Binary bytes, + final NicePlace instance, + final PersistenceLoadHandler handler + ) + { + //get the data of the legacy NicePlace fields + final String name = (String)handler.lookupObject(bytes.read_long(BINARY_OFFSET_name)); + final String directions = (String)handler.lookupObject(bytes.read_long(BINARY_OFFSET_directions)); + + //initialize the new version of our NicePlace + instance.name = name; + instance.location = new Location(directions, 0, 0); + } + + @Override + public void iterateLoadableReferences( + final Binary bytes, + final PersistenceReferenceLoader iterator + ) + { + iterator.acceptObjectId(bytes.read_long(BINARY_OFFSET_name)); + iterator.acceptObjectId(bytes.read_long(BINARY_OFFSET_directions)); + } +} diff --git a/examples/custom-legacy-type-handler/src/main/java/org/eclipse/store/examples/customlegacytypehandler/Location.java b/examples/custom-legacy-type-handler/src/main/java/org/eclipse/store/examples/customlegacytypehandler/Location.java new file mode 100644 index 00000000..ecb1b448 --- /dev/null +++ b/examples/custom-legacy-type-handler/src/main/java/org/eclipse/store/examples/customlegacytypehandler/Location.java @@ -0,0 +1,37 @@ + +package org.eclipse.store.examples.customlegacytypehandler; + +/*- + * #%L + * EclipseStore Example Legacy Type Handler + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class Location +{ + String directions; + double latitude; + double longitude; + + public Location(final String directions, final double latitude, final double longitude) + { + super(); + this.directions = directions; + this.latitude = latitude; + this.longitude = longitude; + } + + @Override + public String toString() + { + return "Latitude: " + this.latitude + "\nLogitude: " + this.longitude + "\ndirections: " + this.directions; + } +} diff --git a/examples/custom-legacy-type-handler/src/main/java/org/eclipse/store/examples/customlegacytypehandler/Main.java b/examples/custom-legacy-type-handler/src/main/java/org/eclipse/store/examples/customlegacytypehandler/Main.java new file mode 100644 index 00000000..fdeb92e9 --- /dev/null +++ b/examples/custom-legacy-type-handler/src/main/java/org/eclipse/store/examples/customlegacytypehandler/Main.java @@ -0,0 +1,124 @@ +package org.eclipse.store.examples.customlegacytypehandler; + +/*- + * #%L + * EclipseStore Example Legacy Type Handler + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.io.File; +import java.lang.reflect.Field; +import java.nio.file.Files; +import java.nio.file.Paths; + +import org.eclipse.store.storage.embedded.types.EmbeddedStorage; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + +/** + * + * This example shows how custom legacy type mapping is done. + * + * USAGE: + * + * Run this sample twice. For the first run use the upper first generation "NicePlace" Object to setup the initial storage. + * Before the second run switch to the modified, second generation version of the "NicePlace" object by + * commenting out the initial version and using the modified one in NicePlace.java. + * + * the custom type mapping is done by the LegacyTypeHandlerNicePlace. + * + */ +public class Main +{ + static final File workingdir = GetTempWorkDirectory("e008-LegacyTypeMappingExample"); + static final String storageChannelFileName = "channel_0\\channel_0_1.dat"; + + @SuppressWarnings("resource") + public static void main(final String[] args) + { + final EmbeddedStorageManager storage; + + //if no channel storage files are found a new storage is created + if(!Files.exists(Paths.get(workingdir.getPath(), storageChannelFileName))) + { + storage = EmbeddedStorage.Foundation(workingdir.toPath()).start(); + final NicePlace myPlace = new NicePlace("Campground", "not far away"); + storage.setRoot(myPlace); + storage.storeRoot(); + + System.out.println("created storage with legacy object:"); + System.out.println(ObjectToString(myPlace)); + System.out.println(myPlace + "\n"); + } + else + { + //a channel storage file is found, try to load the storage and use + //the custom legacy type handler "NicePlaceLegacyHandler" + + storage = EmbeddedStorage.Foundation(workingdir.toPath()) + .onConnectionFoundation(f -> + f.getCustomTypeHandlerRegistry() + .registerLegacyTypeHandler(new LegacyTypeHandlerNicePlace())) + .start(); + + final NicePlace myPlace = (NicePlace)storage.root(); + + System.out.println("loaded legacy storage:"); + System.out.println(ObjectToString(myPlace)); + System.out.println(myPlace + "\n"); + } + + storage.shutdown(); + } + + /** + * Object class and field to String + * + * @param o Object + * @return String + */ + public static String ObjectToString(final Object o) + { + final StringBuilder str = new StringBuilder(); + + final Class T = o.getClass(); + + str.append(T.getName() + "\n"); + + for (final Field field : T.getDeclaredFields()) + { + str.append(field + "\n"); + } + + return str.toString(); + } + + /** + * create a working directory with constant name in system's temporary directory + */ + public static File GetTempWorkDirectory(final String name) + { + final File tmpPath = new File(System.getProperty("java.io.tmpdir")); + if(tmpPath.canWrite() && tmpPath.isDirectory()) + { + final File p = Paths.get(tmpPath.toString(), name).toFile(); + if(p.exists()) + { + return p; + } + if(p.mkdir()) + { + return p; + } + } + + throw new RuntimeException("Faild to get or create working directory!"); + } +} diff --git a/examples/custom-legacy-type-handler/src/main/java/org/eclipse/store/examples/customlegacytypehandler/NicePlace.java b/examples/custom-legacy-type-handler/src/main/java/org/eclipse/store/examples/customlegacytypehandler/NicePlace.java new file mode 100644 index 00000000..7c03a46b --- /dev/null +++ b/examples/custom-legacy-type-handler/src/main/java/org/eclipse/store/examples/customlegacytypehandler/NicePlace.java @@ -0,0 +1,93 @@ +package org.eclipse.store.examples.customlegacytypehandler; + +/*- + * #%L + * EclipseStore Example Legacy Type Handler + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +/** + * + * This file contains to variants of the "NicePlace" class. + * Both variants of that class contain some code that is only + * required to avoid source code modifications outside this file to + * run the legacy type handler example. + * + * It is necessary to do the code switching since java does not like + * identical named classes in one project. + * + * + * This is the first generation of the "NicePlace" class, + * use this one first to setup a storage with a legacy type + * + */ +public class NicePlace +{ + public String name; + public String directions; + + //This field just exists to avoid compiler issues in the LegacyTypeHandler, don't persist it + public transient Location location; + + public NicePlace() + { + super(); + } + + public NicePlace(final String name, final String directions) + { + super(); + this.name = name; + this.directions = directions; + } + + @Override + public String toString() + { + return "Nice Place: " + this.name + "\ndirections: " + this.directions; + } +} + +///** +// * +// * This is the second generation of the "NicePlace" class, +// * use this one to apply the LegacyTypeHandler +// * +// */ +//public class NicePlace +//{ +// String name; +// Location location; +// +// public NicePlace() +// { +// super(); +// } +// +// public NicePlace(String name, Location location) +// { +// super(); +// this.name = name; +// this.location = location; +// } +// +// //This constructor just exists to avoid compiler issues in the LegacyTypeHandler +// public NicePlace(String name, String locationDescrption) +// { +// super(); +// this.name = name; +// } +// +// public String toString() +// { +// return "Nice Place: " + name + "\n" + location; +// } +//} diff --git a/examples/custom-type-handler/LICENSE b/examples/custom-type-handler/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/custom-type-handler/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/examples/custom-type-handler/pom.xml b/examples/custom-type-handler/pom.xml new file mode 100644 index 00000000..836d0d28 --- /dev/null +++ b/examples/custom-type-handler/pom.xml @@ -0,0 +1,35 @@ + + + + + 4.0.0 + + + org.eclipse.store + examples-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + examples-custom-type-handler + + EclipseStore Example Custom Type Handler + EclipseStore Custom Type Handler Example + https://projects.eclipse.org/projects/technology.store + + + + org.eclipse.store + storage-embedded + 1.0.0-SNAPSHOT + + + org.eclipse.serializer + persistence-binary-jdk8 + 1.0.0-SNAPSHOT + + + + diff --git a/examples/custom-type-handler/src/main/java/org/eclipse/store/examples/customtypehandler/CustomBufferedImageHandler.java b/examples/custom-type-handler/src/main/java/org/eclipse/store/examples/customtypehandler/CustomBufferedImageHandler.java new file mode 100644 index 00000000..eb51a86b --- /dev/null +++ b/examples/custom-type-handler/src/main/java/org/eclipse/store/examples/customtypehandler/CustomBufferedImageHandler.java @@ -0,0 +1,118 @@ +package org.eclipse.store.examples.customtypehandler; + +/*- + * #%L + * EclipseStore Example Custom Type Handler + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.imageio.stream.ImageOutputStream; +import javax.imageio.stream.MemoryCacheImageOutputStream; + +import org.eclipse.serializer.persistence.binary.types.AbstractBinaryHandlerCustomValue; +import org.eclipse.serializer.persistence.binary.types.Binary; +import org.eclipse.serializer.persistence.types.PersistenceLoadHandler; +import org.eclipse.serializer.persistence.types.PersistenceStoreHandler; + +public class CustomBufferedImageHandler extends AbstractBinaryHandlerCustomValue +{ + private static byte[] instanceState(final BufferedImage instance) + { + final ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try ( ImageOutputStream ios = new MemoryCacheImageOutputStream(bos)) + { + ImageIO.write(instance, "png", ios); + } + catch (final IOException e) + { + throw new RuntimeException(e); + } + return bos.toByteArray(); + } + + private static byte[] binaryState(final Binary data) + { + return data.build_bytes(); + } + + + public CustomBufferedImageHandler() + { + super( + BufferedImage.class, + CustomFields( + bytes("imageData") + ) + ); + } + + @Override + public void store( + final Binary bytes, + final BufferedImage instance, + final long objectId, + final PersistenceStoreHandler handler + ) + { + bytes.store_bytes( + this.typeId(), + objectId, + instanceState(instance) + ); + } + + @Override + public BufferedImage create( + final Binary data, + final PersistenceLoadHandler handler + ) + { + final byte[] imageData = binaryState(data); + + BufferedImage image = null; + + try(ByteArrayInputStream bis = new ByteArrayInputStream(imageData)) + { + image = ImageIO.read(bis); + } + catch (final IOException e) + { + throw new RuntimeException(e); + } + + return image; + } + + @Override + public byte[] getValidationStateFromInstance(BufferedImage instance) + { + return instanceState(instance); + } + + @Override + public byte[] getValidationStateFromBinary(Binary data) + { + return binaryState(data); + } + + @Override + public boolean hasVaryingPersistedLengthInstances() + { + return true; + } + +} diff --git a/examples/custom-type-handler/src/main/java/org/eclipse/store/examples/customtypehandler/Employee.java b/examples/custom-type-handler/src/main/java/org/eclipse/store/examples/customtypehandler/Employee.java new file mode 100644 index 00000000..84a21d31 --- /dev/null +++ b/examples/custom-type-handler/src/main/java/org/eclipse/store/examples/customtypehandler/Employee.java @@ -0,0 +1,104 @@ +package org.eclipse.store.examples.customtypehandler; + +/*- + * #%L + * EclipseStore Example Custom Type Handler + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.Date; + +import org.eclipse.serializer.persistence.binary.types.Binary; +import org.eclipse.serializer.persistence.binary.types.BinaryTypeHandler; + +public class Employee +{ + /* + * The entity class must just contain "any" method returning a suitable type handler + * and MicroStream will recognize it and use the returned handler automatically. + * + * Type type handler just needs to specify the entity class and define a list of fields + * comprised of (name, getter, setter) in arbitrary order. + */ + static BinaryTypeHandler provideTypeHandler() + { + return Binary.TypeHandler( + Employee.class, + Binary.Field_long("id", + e -> Long.parseLong(e.id), + (e, value) -> e.id = String.valueOf(value) + ), + Binary.Field_long("dateOfBirth", + e -> e.dateOfBirth.getTime(), + (e, value) -> e.dateOfBirth = new Date(value) + ), + Binary.Field_double("salary", + e -> e.salary.longValue(), + (e, value) -> e.salary = Double.valueOf(value) + ) + ); + } + + /* + * Fields with primitive data are (for whatever reason, e.g. project design rules) all object types, + * but records should be stored as efficient as possible, i.e. without overhead of references and value objects. + * + * MicroStream's generic type analysis does not know of this and hence cannot do it. + * But defining a custom type handler can + */ + + private String id ; + private Double salary ; + private Date dateOfBirth; + + public Employee() + { + super(); + } + + public Employee(String id, Double salary, Date dateOfBirth) + { + super(); + this.id = id; + this.salary = salary; + this.dateOfBirth = dateOfBirth; + } + + public String getId() + { + return this.id; + } + + public void setId(String id) + { + this.id = id; + } + + public Double getSalary() + { + return this.salary; + } + + public void setSalary(Double salary) + { + this.salary = salary; + } + + public Date getDateOfBirth() + { + return this.dateOfBirth; + } + + public void setDateOfBirth(Date dateOfBirth) + { + this.dateOfBirth = dateOfBirth; + } +} diff --git a/examples/custom-type-handler/src/main/java/org/eclipse/store/examples/customtypehandler/Order.java b/examples/custom-type-handler/src/main/java/org/eclipse/store/examples/customtypehandler/Order.java new file mode 100644 index 00000000..95cc4ee1 --- /dev/null +++ b/examples/custom-type-handler/src/main/java/org/eclipse/store/examples/customtypehandler/Order.java @@ -0,0 +1,92 @@ + +package org.eclipse.store.examples.customtypehandler; + +/*- + * #%L + * EclipseStore Example Custom Type Handler + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.Date; + + +public class Order +{ + public static class Item + { + private final int productNumber; + private final int amount; + + public Item(final int productNumber, final int amount) + { + super(); + this.productNumber = productNumber; + this.amount = amount; + } + + public int getProductNumber() + { + return this.productNumber; + } + + public int getAmount() + { + return this.amount; + } + } + + private Date timestamp; + private String customerNumber; + private Item[] items; + + public Order() + { + } + + public Order(final Date timestamp, final String customerNumber, final Item... items) + { + super(); + this.timestamp = timestamp; + this.customerNumber = customerNumber; + this.items = items; + } + + public Date getTimestamp() + { + return this.timestamp; + } + + public void setTimestamp(final Date timestamp) + { + this.timestamp = timestamp; + } + + public String getCustomerNumber() + { + return this.customerNumber; + } + + public void setCustomerNumber(final String customerNumber) + { + this.customerNumber = customerNumber; + } + + public Item[] getItems() + { + return this.items; + } + + public void setItems(final Item[] items) + { + this.items = items; + } + +} diff --git a/examples/custom-type-handler/src/main/java/org/eclipse/store/examples/customtypehandler/OrderBinaryHandler.java b/examples/custom-type-handler/src/main/java/org/eclipse/store/examples/customtypehandler/OrderBinaryHandler.java new file mode 100644 index 00000000..114c66ab --- /dev/null +++ b/examples/custom-type-handler/src/main/java/org/eclipse/store/examples/customtypehandler/OrderBinaryHandler.java @@ -0,0 +1,160 @@ +package org.eclipse.store.examples.customtypehandler; + +/*- + * #%L + * EclipseStore Example Custom Type Handler + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.eclipse.serializer.memory.XMemory; +import org.eclipse.serializer.persistence.binary.types.AbstractBinaryHandlerCustom; +import org.eclipse.serializer.persistence.binary.types.Binary; +import org.eclipse.serializer.persistence.types.PersistenceLoadHandler; +import org.eclipse.serializer.persistence.types.PersistenceReferenceLoader; +import org.eclipse.serializer.persistence.types.PersistenceStoreHandler; +import org.eclipse.serializer.util.X; +import org.eclipse.store.examples.customtypehandler.Order.Item; + +public class OrderBinaryHandler extends AbstractBinaryHandlerCustom +{ + static final int + BINARY_OFFSET_timestamp = 0 , + BINARY_OFFSET_customerNumber = BINARY_OFFSET_timestamp + XMemory.byteSize_long() , + BINARY_OFFSET_ITEMS = BINARY_OFFSET_customerNumber + Binary.objectIdByteLength() + ; + static final int + BINARY_ITEM_OFFSET_productNumber = 0 , + BINARY_ITEM_OFFSET_amount = BINARY_ITEM_OFFSET_productNumber + XMemory.byteSize_int() , + BINARY_ITEM_LENGTH = BINARY_ITEM_OFFSET_amount + XMemory.byteSize_int() + ; + + static int getBuildItemElementCount(final Binary bytes) + { + return X.checkArrayRange(bytes.getListElementCount(BINARY_OFFSET_ITEMS, BINARY_ITEM_LENGTH)); + } + + + public OrderBinaryHandler() + { + super( + Order.class, + CustomFields( + CustomField(long .class, "timestamp" ), + CustomField(String.class, "customerNumber"), + Complex("items", + CustomField(int.class, "productNumber"), + CustomField(int.class, "amount" ) + ) + ) + ); + } + + @Override + public final void store( + final Binary bytes , + final Order instance, + final long oid , + final PersistenceStoreHandler linker + ) + { + final Item[] items = instance.getItems(); + + // calculate length and write header + final long listElementCount = items.length; + final long listContentBinaryLength = listElementCount * BINARY_ITEM_LENGTH; + final long entityContentBinaryLength = BINARY_OFFSET_ITEMS + + Binary.toBinaryListTotalByteLength(listContentBinaryLength) + ; + bytes.storeEntityHeader(entityContentBinaryLength, this.typeId(), oid); + + // write order values + bytes.store_long(BINARY_OFFSET_timestamp , instance.getTimestamp().getTime() ); + bytes.store_long(BINARY_OFFSET_customerNumber, linker.apply(instance.getCustomerNumber())); + + // set element list header + bytes.storeListHeader( + BINARY_OFFSET_ITEMS , + listContentBinaryLength, + listElementCount + ); + + // write items + long offset = Binary.toBinaryListTotalByteLength(BINARY_OFFSET_ITEMS); + for(final Item item : items) + { + bytes.store_int(offset + BINARY_ITEM_OFFSET_productNumber, item.getProductNumber()); + bytes.store_int(offset + BINARY_ITEM_OFFSET_amount , item.getAmount() ); + + // add item length to offset + offset += BINARY_ITEM_LENGTH; + } + } + + @Override + public Order create(final Binary data, final PersistenceLoadHandler handler) + { + return new Order(); + } + + @Override + public final void updateState( + final Binary bytes , + final Order instance, + final PersistenceLoadHandler builder + ) + { + final long elementCount = getBuildItemElementCount(bytes); + final long addressBound = elementCount * BINARY_ITEM_LENGTH; + + instance.setTimestamp( + new Date(bytes.read_long(BINARY_OFFSET_timestamp)) + ); + instance.setCustomerNumber( + (String)builder.lookupObject(bytes.read_long(BINARY_OFFSET_customerNumber)) + ); + + final List items = new ArrayList<>(); + + for(long adr = Binary.toBinaryListTotalByteLength(BINARY_OFFSET_ITEMS); adr < addressBound; adr += BINARY_ITEM_LENGTH) + { + final Item item = new Item( + bytes.read_int(adr + BINARY_ITEM_OFFSET_productNumber), + bytes.read_int(adr + BINARY_ITEM_OFFSET_amount ) + ); + items.add(item); + } + + instance.setItems(items.toArray(new Item[items.size()])); + } + + @Override + public void iterateLoadableReferences(final Binary data, final PersistenceReferenceLoader iterator) + { + // no-op + } + + @Override + public boolean hasPersistedReferences() + { + return false; + } + + @Override + public boolean hasVaryingPersistedLengthInstances() + { + return false; + } + +} diff --git a/examples/deleting/LICENSE b/examples/deleting/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/deleting/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/examples/deleting/pom.xml b/examples/deleting/pom.xml new file mode 100644 index 00000000..eaca3dd5 --- /dev/null +++ b/examples/deleting/pom.xml @@ -0,0 +1,30 @@ + + + + + 4.0.0 + + + org.eclipse.store + examples-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + examples-deleting + + EclipseStore Example Deleting + EclipseStore Deleting Example + https://projects.eclipse.org/projects/technology.store + + + + org.eclipse.store + storage-embedded + 1.0.0-SNAPSHOT + + + + diff --git a/examples/deleting/src/main/java/org/eclipse/store/examples/deleting/Main.java b/examples/deleting/src/main/java/org/eclipse/store/examples/deleting/Main.java new file mode 100644 index 00000000..abefb048 --- /dev/null +++ b/examples/deleting/src/main/java/org/eclipse/store/examples/deleting/Main.java @@ -0,0 +1,92 @@ +package org.eclipse.store.examples.deleting; + +/*- + * #%L + * EclipseStore Example Deleting + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.storage.embedded.types.EmbeddedStorage; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + +/** + * + * Microstream deleting data example + * + * Deleting an (data)object means to remove all references to the object: + * In this example all data objects are referenced from the myObjects list of the + * MyRoot class. Thus deleting an object is done by removing it's reference from the + * myObjects list and storing the myObject list again. + * + * Objects that are no more reachable in the stored object graph + * will be removed from the storage files a a later time. + * + */ +public class Main +{ + public static void main(final String[] args) + { + //Init storage manager + final EmbeddedStorageManager storage = EmbeddedStorage.start(); + + //if storage.root() returns null no data has been loaded + //since there is no existing database, let's create a new one. + if(storage.root() == null) + { + System.out.println("No existing Database found, creating a new one:"); + + final MyRoot root = new MyRoot(); + storage.setRoot(root); + root.myObjects.add(new MyData("Alice", 20)); + root.myObjects.add(new MyData("Bob" , 25)); + root.myObjects.add(new MyData("Claire", 18)); + storage.storeRoot(); + + root.myObjects.forEach(System.out::println); + System.out.println("\n"); + } + //storage.root() is not null so we have loaded data + else + { + System.out.println("Existing Database found:"); + + final MyRoot root = (MyRoot) storage.root(); + root.myObjects.forEach(System.out::println); + + if(!root.myObjects.isEmpty()) + { + System.out.println("\nDeleting first object:"); + + //delete the first object from our object graph + root.myObjects.remove(0); + + //store the changed list to apply the deletion of it's second element + storage.store(root.myObjects); + + if(!root.myObjects.isEmpty()) + { + root.myObjects.forEach(System.out::println); + } + else + { + System.out.println("myObjects is empty!"); + } + } + else + { + System.out.println("myObjects is empty!"); + } + } + + storage.shutdown(); + } + +} diff --git a/examples/deleting/src/main/java/org/eclipse/store/examples/deleting/MyData.java b/examples/deleting/src/main/java/org/eclipse/store/examples/deleting/MyData.java new file mode 100644 index 00000000..135d7b47 --- /dev/null +++ b/examples/deleting/src/main/java/org/eclipse/store/examples/deleting/MyData.java @@ -0,0 +1,56 @@ + +package org.eclipse.store.examples.deleting; + +/*- + * #%L + * microstream-examples-deleting + * %% + * Copyright (C) 2019 - 2022 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class MyData +{ + private String name; + private int intValue; + + public MyData(final String name, final int value) + { + super(); + this.name = name; + this.intValue = value; + } + + public String getName() + { + return this.name; + } + + public void setName(final String name) + { + this.name = name; + } + + public int getIntegerValue() + { + return this.intValue; + } + + public void setIntValue(final int integerValue) + { + this.intValue = integerValue; + } + + @Override + public String toString() + { + return this.name + " value: " + this.intValue; + } + +} diff --git a/examples/deleting/src/main/java/org/eclipse/store/examples/deleting/MyRoot.java b/examples/deleting/src/main/java/org/eclipse/store/examples/deleting/MyRoot.java new file mode 100644 index 00000000..0f98b332 --- /dev/null +++ b/examples/deleting/src/main/java/org/eclipse/store/examples/deleting/MyRoot.java @@ -0,0 +1,23 @@ +package org.eclipse.store.examples.deleting; + +/*- + * #%L + * microstream-examples-deleting + * %% + * Copyright (C) 2019 - 2022 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.ArrayList; +import java.util.List; + +public class MyRoot +{ + public List myObjects = new ArrayList<>(); +} diff --git a/examples/eager-storing/LICENSE b/examples/eager-storing/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/eager-storing/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/examples/eager-storing/pom.xml b/examples/eager-storing/pom.xml new file mode 100644 index 00000000..ffbb4e26 --- /dev/null +++ b/examples/eager-storing/pom.xml @@ -0,0 +1,31 @@ + + + + + 4.0.0 + + + org.eclipse.store + examples-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + examples-eager-storing + + EclipseStore Example Eager Storing + EclipseStore Eager Storing Example + https://projects.eclipse.org/projects/technology.store + + + + org.eclipse.store + storage-embedded + 1.0.0-SNAPSHOT + + + + diff --git a/examples/eager-storing/src/main/java/org/eclipse/store/examples/eagerstoring/Main.java b/examples/eager-storing/src/main/java/org/eclipse/store/examples/eagerstoring/Main.java new file mode 100644 index 00000000..d8a579a5 --- /dev/null +++ b/examples/eager-storing/src/main/java/org/eclipse/store/examples/eagerstoring/Main.java @@ -0,0 +1,70 @@ +package org.eclipse.store.examples.eagerstoring; + +/*- + * #%L + * EclipseStore Example Eager Storing + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.time.LocalDateTime; + +import org.eclipse.store.storage.embedded.types.EmbeddedStorage; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + +/** + * Excample which shows how to implement a custom eager storing behavior, + * based on an annotation ({@link StoreEager}) + * and a field evaluator ({@link StoreEagerEvaluator}). + * + * + */ +public class Main +{ + public static void main( + final String[] args + ) + { + for(int i = 0; i < 5; i++) + { + final EmbeddedStorageManager storage = EmbeddedStorage.Foundation() + // register custom field evaluator + .onConnectionFoundation(cf -> cf.setReferenceFieldEagerEvaluator(new StoreEagerEvaluator())) + .createEmbeddedStorageManager() + .start() + ; + if(storage.root() == null) + { + final MyRoot root = new MyRoot(); + root.numbers.add(1); + root.dates.add(LocalDateTime.now()); + storage.setRoot(root); + storage.storeRoot(); + } + else + { + final MyRoot root = (MyRoot)storage.root(); + + /* + * At each iteration you can see that the eager field (root#numbers) gets stored, + * whereas root#dates is not, because it is not marked as eager. + */ + System.out.println(root.numbers + ", " + root.dates); + + root.numbers.add(root.numbers.size() + 1); + root.dates.add(LocalDateTime.now()); + storage.storeRoot(); + } + + storage.shutdown(); + } + } + +} diff --git a/examples/eager-storing/src/main/java/org/eclipse/store/examples/eagerstoring/MyRoot.java b/examples/eager-storing/src/main/java/org/eclipse/store/examples/eagerstoring/MyRoot.java new file mode 100644 index 00000000..91682262 --- /dev/null +++ b/examples/eager-storing/src/main/java/org/eclipse/store/examples/eagerstoring/MyRoot.java @@ -0,0 +1,27 @@ +package org.eclipse.store.examples.eagerstoring; + +/*- + * #%L + * microstream-examples-eager-storing + * %% + * Copyright (C) 2019 - 2022 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +public class MyRoot +{ + @StoreEager + final List numbers = new ArrayList<>(); + + final List dates = new ArrayList<>(); +} diff --git a/examples/eager-storing/src/main/java/org/eclipse/store/examples/eagerstoring/StoreEager.java b/examples/eager-storing/src/main/java/org/eclipse/store/examples/eagerstoring/StoreEager.java new file mode 100644 index 00000000..daea86e7 --- /dev/null +++ b/examples/eager-storing/src/main/java/org/eclipse/store/examples/eagerstoring/StoreEager.java @@ -0,0 +1,30 @@ +package org.eclipse.store.examples.eagerstoring; + +/*- + * #%L + * microstream-examples-eager-storing + * %% + * Copyright (C) 2019 - 2022 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to mark fields for eager storing + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface StoreEager +{ + // simple marker annotation +} diff --git a/examples/eager-storing/src/main/java/org/eclipse/store/examples/eagerstoring/StoreEagerEvaluator.java b/examples/eager-storing/src/main/java/org/eclipse/store/examples/eagerstoring/StoreEagerEvaluator.java new file mode 100644 index 00000000..7d67d5a8 --- /dev/null +++ b/examples/eager-storing/src/main/java/org/eclipse/store/examples/eagerstoring/StoreEagerEvaluator.java @@ -0,0 +1,37 @@ +package org.eclipse.store.examples.eagerstoring; + +/*- + * #%L + * EclipseStore Example Eager Storing + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.lang.reflect.Field; + +import org.eclipse.serializer.persistence.types.PersistenceEagerStoringFieldEvaluator; + +/** + * Custom field evaluator which looks for the {@link StoreEager} annotation. + * + */ +public class StoreEagerEvaluator implements PersistenceEagerStoringFieldEvaluator +{ + + @Override + public boolean isEagerStoring( + final Class clazz, + final Field field + ) + { + return field.isAnnotationPresent(StoreEager.class); + } + +} diff --git a/examples/extension-wrapper/LICENSE b/examples/extension-wrapper/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/extension-wrapper/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/examples/extension-wrapper/pom.xml b/examples/extension-wrapper/pom.xml new file mode 100644 index 00000000..ca5bc338 --- /dev/null +++ b/examples/extension-wrapper/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + + org.eclipse.store + examples-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + examples-extension-wrapper + + EclipseStore Example Extension Wrapper + EclipseStore Extension Wrapper Example + https://projects.eclipse.org/projects/technology.store + + + + org.eclipse.store + storage-embedded + 1.0.0-SNAPSHOT + + + + diff --git a/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/Main.java b/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/Main.java new file mode 100644 index 00000000..551dfd4f --- /dev/null +++ b/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/Main.java @@ -0,0 +1,55 @@ + +package org.eclipse.store.examples.extensionwrapper; + +/*- + * #%L + * EclipseStore Example Extension Wrapper + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.store.storage.embedded.types.EmbeddedStorage; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + +/** + * Example which shows how to use the instance dispatching in foundations, + * in order to extend certain parts of the storage engine. + * + */ +public class Main +{ + private static List ROOT = new ArrayList<>(); + + + public static void main(final String[] args) + { + // Create default storage foundation + final EmbeddedStorageFoundation foundation = EmbeddedStorage.Foundation(); + + // Add extender as dispatcher + foundation.getConnectionFoundation().setInstanceDispatcher(new StorageExtender()); + + // Start storage + final EmbeddedStorageManager storage = foundation.start(ROOT); + + // See extensions in action + ROOT.add(LocalDateTime.now()); + storage.storeRoot(); + + storage.shutdown(); + System.exit(0); + } + +} diff --git a/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceStorerExtension.java b/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceStorerExtension.java new file mode 100644 index 00000000..41a3aa2d --- /dev/null +++ b/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceStorerExtension.java @@ -0,0 +1,114 @@ + +package org.eclipse.store.examples.extensionwrapper; + +/*- + * #%L + * EclipseStore Example Extension Wrapper + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.persistence.binary.types.Binary; +import org.eclipse.serializer.persistence.types.PersistenceObjectManager; +import org.eclipse.serializer.persistence.types.PersistenceStorer; +import org.eclipse.serializer.persistence.types.PersistenceTarget; +import org.eclipse.serializer.persistence.types.PersistenceTypeHandlerManager; +import org.eclipse.serializer.reference.ObjectSwizzling; +import org.eclipse.serializer.util.BufferSizeProviderIncremental; + + +/** + * Extension for {@link PersistenceStorer} which adds logic to store operations + * + */ +public class PersistenceStorerExtension extends PersistenceStorerWrapper +{ + public PersistenceStorerExtension(final PersistenceStorer delegate) + { + super(delegate); + } + + private void beforeStoreObject(final Object instance) + { + System.out.println("Storing " + instance.getClass().getName() + "@" + System.identityHashCode(instance)); + } + + @Override + public long store(final Object instance) + { + this.beforeStoreObject(instance); + + return super.store(instance); + } + + @Override + public void storeAll(final Iterable instances) + { + instances.forEach(this::beforeStoreObject); + + super.storeAll(instances); + } + + @Override + public long[] storeAll(final Object... instances) + { + for(final Object instance : instances) + { + this.beforeStoreObject(instance); + } + + return super.storeAll(instances); + } + + + + + public static class Creator implements PersistenceStorer.Creator + { + private final PersistenceStorer.Creator delegate; + + public Creator(PersistenceStorer.Creator delegate) + { + super(); + this.delegate = delegate; + } + + @Override + public PersistenceStorer createLazyStorer( + final PersistenceTypeHandlerManager typeManager , + final PersistenceObjectManager objectManager , + final ObjectSwizzling objectRetriever , + final PersistenceTarget target , + final BufferSizeProviderIncremental bufferSizeProvider + ) + { + return new PersistenceStorerExtension( + this.delegate.createLazyStorer(typeManager, objectManager, objectRetriever, target, bufferSizeProvider) + ); + } + + @Override + public PersistenceStorer createEagerStorer( + final PersistenceTypeHandlerManager typeManager , + final PersistenceObjectManager objectManager , + final ObjectSwizzling objectRetriever , + final PersistenceTarget target , + final BufferSizeProviderIncremental bufferSizeProvider + ) + { + return new PersistenceStorerExtension( + this.delegate.createEagerStorer(typeManager, objectManager, objectRetriever, target, bufferSizeProvider) + ); + } + + + } + +} diff --git a/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceStorerWrapper.java b/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceStorerWrapper.java new file mode 100644 index 00000000..53bb3e32 --- /dev/null +++ b/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceStorerWrapper.java @@ -0,0 +1,126 @@ +package org.eclipse.store.examples.extensionwrapper; + +/*- + * #%L + * EclipseStore Example Extension Wrapper + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.persistence.types.PersistenceStorer; + +/** + * Wrapper for {@link PersistenceStorer}, used as base for extensions + * + */ +public class PersistenceStorerWrapper implements PersistenceStorer +{ + private final PersistenceStorer delegate; + + public PersistenceStorerWrapper(final PersistenceStorer delegate) + { + super(); + this.delegate = delegate; + } + + @Override + public PersistenceStorer reinitialize() + { + return this.delegate.reinitialize(); + } + + @Override + public long store(final Object instance) + { + return this.delegate.store(instance); + } + + @Override + public PersistenceStorer reinitialize(final long initialCapacity) + { + return this.delegate.reinitialize(initialCapacity); + } + + @Override + public Object commit() + { + return this.delegate.commit(); + } + + @Override + public PersistenceStorer ensureCapacity(final long desiredCapacity) + { + return this.delegate.ensureCapacity(desiredCapacity); + } + + @Override + public void clear() + { + this.delegate.clear(); + } + + @Override + public long[] storeAll(final Object... instances) + { + return this.delegate.storeAll(instances); + } + + @Override + public boolean skipMapped(final Object instance, final long objectId) + { + return this.delegate.skipMapped(instance, objectId); + } + + @Override + public void storeAll(final Iterable instances) + { + this.delegate.storeAll(instances); + } + + @Override + public boolean skip(final Object instance) + { + return this.delegate.skip(instance); + } + + @Override + public boolean skipNulled(final Object instance) + { + return this.delegate.skipNulled(instance); + } + + @Override + public long size() + { + return this.delegate.size(); + } + + @Override + public boolean isEmpty() + { + return this.delegate.isEmpty(); + } + + @Override + public long currentCapacity() + { + return this.delegate.currentCapacity(); + } + + @Override + public long maximumCapacity() + { + return this.delegate.maximumCapacity(); + } + + + + +} diff --git a/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceTargetExtension.java b/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceTargetExtension.java new file mode 100644 index 00000000..787bf166 --- /dev/null +++ b/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceTargetExtension.java @@ -0,0 +1,44 @@ +package org.eclipse.store.examples.extensionwrapper; + +/*- + * #%L + * EclipseStore Example Extension Wrapper + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.persistence.binary.types.Binary; +import org.eclipse.serializer.persistence.exceptions.PersistenceExceptionTransfer; +import org.eclipse.serializer.persistence.types.PersistenceTarget; + +/** + * Extension for {@link PersistenceTarget} which adds logic to write operations + * + */ +public class PersistenceTargetExtension extends PersistenceTargetWrapper +{ + public PersistenceTargetExtension(final PersistenceTarget delegate) + { + super(delegate); + } + + + @Override + public void write(final Binary data) throws PersistenceExceptionTransfer + { + // Original write + super.write(data); + + // Add extension code + System.out.println("Data written"); + } + + +} diff --git a/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceTargetWrapper.java b/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceTargetWrapper.java new file mode 100644 index 00000000..be3cfe07 --- /dev/null +++ b/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceTargetWrapper.java @@ -0,0 +1,48 @@ +package org.eclipse.store.examples.extensionwrapper; + +/*- + * #%L + * EclipseStore Example Extension Wrapper + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.persistence.binary.types.Binary; +import org.eclipse.serializer.persistence.exceptions.PersistenceExceptionTransfer; +import org.eclipse.serializer.persistence.types.PersistenceTarget; + +/** + * Wrapper for {@link PersistenceTarget}, used as base for extensions + * + */ +public class PersistenceTargetWrapper implements PersistenceTarget +{ + private final PersistenceTarget delegate; + + public PersistenceTargetWrapper(final PersistenceTarget delegate) + { + super(); + this.delegate = delegate; + } + + @Override + public boolean isWritable() + { + return this.delegate.isWritable(); + } + + @Override + public void write(final Binary data) throws PersistenceExceptionTransfer + { + this.delegate.write(data); + } + + +} diff --git a/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/StorageExtender.java b/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/StorageExtender.java new file mode 100644 index 00000000..afae3d34 --- /dev/null +++ b/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/StorageExtender.java @@ -0,0 +1,43 @@ +package org.eclipse.store.examples.extensionwrapper; + +/*- + * #%L + * EclipseStore Example Extension Wrapper + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.functional.InstanceDispatcherLogic; +import org.eclipse.serializer.persistence.binary.types.Binary; +import org.eclipse.serializer.persistence.types.PersistenceStorer; +import org.eclipse.serializer.persistence.types.PersistenceTarget; + +/** + * Dispatcher logic which is used to extend certain parts + */ +public class StorageExtender implements InstanceDispatcherLogic +{ + @SuppressWarnings("unchecked") + @Override + public T apply(final T subject) + { + if(subject instanceof PersistenceTarget) + { + return (T)new PersistenceTargetExtension((PersistenceTarget)subject); + } + + if(subject instanceof PersistenceStorer.Creator) + { + return (T)new PersistenceStorerExtension.Creator((PersistenceStorer.Creator)subject); + } + + return subject; + } +} diff --git a/examples/filesystems/LICENSE b/examples/filesystems/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/filesystems/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/examples/filesystems/pom.xml b/examples/filesystems/pom.xml new file mode 100644 index 00000000..1691b9b4 --- /dev/null +++ b/examples/filesystems/pom.xml @@ -0,0 +1,34 @@ + + + + + 4.0.0 + + + org.eclipse.store + examples-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + examples-filesystems + + EclipseStore Example File Systems + EclipseStore File Systems Example + https://projects.eclipse.org/projects/technology.store + + + + org.eclipse.store + storage-embedded + 1.0.0-SNAPSHOT + + + com.google.jimfs + jimfs + + + + diff --git a/examples/filesystems/src/main/java/org/eclipse/store/examples/filesystems/nio/NioFilesystemJimfs.java b/examples/filesystems/src/main/java/org/eclipse/store/examples/filesystems/nio/NioFilesystemJimfs.java new file mode 100644 index 00000000..50c62cb6 --- /dev/null +++ b/examples/filesystems/src/main/java/org/eclipse/store/examples/filesystems/nio/NioFilesystemJimfs.java @@ -0,0 +1,49 @@ + +package org.eclipse.store.examples.filesystems.nio; + +/*- + * #%L + * EclipseStore Example File Systems + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.nio.file.FileSystem; + +import org.eclipse.store.afs.nio.types.NioFileSystem; +import org.eclipse.store.storage.embedded.types.EmbeddedStorage; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.eclipse.store.storage.types.StorageLiveFileProvider; + +import com.google.common.jimfs.Jimfs; + + +public class NioFilesystemJimfs +{ + @SuppressWarnings("unused") + public static void main( + final String[] args + ) + { + // create jimfs filesystem + final FileSystem jimfs = Jimfs.newFileSystem(); + + // start storage with jimfs path + final EmbeddedStorageManager storage = EmbeddedStorage.start(jimfs.getPath("storage")); + storage.shutdown(); + + // or create file provider with jimsfs filesytem for further configuration + final NioFileSystem fileSystem = NioFileSystem.New(jimfs); + final StorageLiveFileProvider fileProvider = StorageLiveFileProvider.Builder(fileSystem) + .setDirectory(fileSystem.ensureDirectoryPath("storage")) + .createFileProvider() + ; + } +} diff --git a/examples/helloworld-ini/LICENSE b/examples/helloworld-ini/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/helloworld-ini/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/examples/helloworld-ini/pom.xml b/examples/helloworld-ini/pom.xml new file mode 100644 index 00000000..cd5ddacc --- /dev/null +++ b/examples/helloworld-ini/pom.xml @@ -0,0 +1,35 @@ + + + + + 4.0.0 + + + org.eclipse.store + examples-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + examples-helloworld-ini + + EclipseStore Example Hello World INI + EclipseStore Hello World INI Example + https://projects.eclipse.org/projects/technology.store + + + + org.eclipse.store + storage-embedded + 1.0.0-SNAPSHOT + + + org.eclipse.store + storage-embedded-configuration + 1.0.0-SNAPSHOT + + + + diff --git a/examples/helloworld-ini/src/main/java/org/eclipse/store/examples/helloworld/DataRoot.java b/examples/helloworld-ini/src/main/java/org/eclipse/store/examples/helloworld/DataRoot.java new file mode 100644 index 00000000..33cd22a2 --- /dev/null +++ b/examples/helloworld-ini/src/main/java/org/eclipse/store/examples/helloworld/DataRoot.java @@ -0,0 +1,42 @@ + +package org.eclipse.store.examples.helloworld; + +/*- + * #%L + * EclipseStore Example Hello World INI + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class DataRoot +{ + private String content; + + public DataRoot() + { + super(); + } + + public String getContent() + { + return this.content; + } + + public void setContent(final String content) + { + this.content = content; + } + + @Override + public String toString() + { + return "Root: " + this.content; + } +} diff --git a/examples/helloworld-ini/src/main/java/org/eclipse/store/examples/helloworld/HelloWorld.java b/examples/helloworld-ini/src/main/java/org/eclipse/store/examples/helloworld/HelloWorld.java new file mode 100644 index 00000000..6b19d054 --- /dev/null +++ b/examples/helloworld-ini/src/main/java/org/eclipse/store/examples/helloworld/HelloWorld.java @@ -0,0 +1,56 @@ + +package org.eclipse.store.examples.helloworld; + +/*- + * #%L + * EclipseStore Example Hello World INI + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.io.IOException; +import java.util.Date; + +import org.eclipse.store.storage.embedded.configuration.types.EmbeddedStorageConfiguration; +import org.eclipse.store.storage.embedded.configuration.types.EmbeddedStorageConfigurationBuilder; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + + +public class HelloWorld +{ + public static void main(final String[] args) throws IOException + { + // Application-specific root instance + final DataRoot root = new DataRoot(); + + // configuring the database via .ini file instead of API. Here the directory and the thread count. + final EmbeddedStorageConfigurationBuilder configuration = EmbeddedStorageConfiguration.load( + "/META-INF/eclipsestore/storage.ini" + ); + + final EmbeddedStorageManager storageManager = configuration + .createEmbeddedStorageFoundation() + .createEmbeddedStorageManager(root) + .start(); + + // print the root to show its loaded content (stored in the last execution). + System.out.println(root); + + // Set content data to the root element, including the time to visualize changes on the next execution. + root.setContent("Hello World! @ " + new Date()); + + // Store the modified root and its content. + storageManager.storeRoot(); + + // Shutdown is optional as the storage concept is inherently crash-safe +// storageManager.shutdown(); + System.exit(0); + } +} diff --git a/examples/helloworld-ini/src/main/resources/META-INF/eclipsestore/storage.ini b/examples/helloworld-ini/src/main/resources/META-INF/eclipsestore/storage.ini new file mode 100644 index 00000000..59405d27 --- /dev/null +++ b/examples/helloworld-ini/src/main/resources/META-INF/eclipsestore/storage.ini @@ -0,0 +1,2 @@ +storage-directory = data +channel-count = 4 diff --git a/examples/helloworld/LICENSE b/examples/helloworld/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/helloworld/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml new file mode 100644 index 00000000..cb2daa8e --- /dev/null +++ b/examples/helloworld/pom.xml @@ -0,0 +1,30 @@ + + + + + 4.0.0 + + + org.eclipse.store + examples-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + examples-helloworld + + EclipseStore Example Hello World + EclipseStore Hello World Example + https://projects.eclipse.org/projects/technology.store + + + + org.eclipse.store + storage-embedded + 1.0.0-SNAPSHOT + + + + diff --git a/examples/helloworld/src/main/java/org/eclipse/store/examples/helloworld/DataRoot.java b/examples/helloworld/src/main/java/org/eclipse/store/examples/helloworld/DataRoot.java new file mode 100644 index 00000000..2e3cb341 --- /dev/null +++ b/examples/helloworld/src/main/java/org/eclipse/store/examples/helloworld/DataRoot.java @@ -0,0 +1,42 @@ + +package org.eclipse.store.examples.helloworld; + +/*- + * #%L + * EclipseStore Example Hello World + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class DataRoot +{ + private String content; + + public DataRoot() + { + super(); + } + + public String getContent() + { + return this.content; + } + + public void setContent(final String content) + { + this.content = content; + } + + @Override + public String toString() + { + return "Root: " + this.content; + } +} diff --git a/examples/helloworld/src/main/java/org/eclipse/store/examples/helloworld/HelloWorld.java b/examples/helloworld/src/main/java/org/eclipse/store/examples/helloworld/HelloWorld.java new file mode 100644 index 00000000..653fd6a2 --- /dev/null +++ b/examples/helloworld/src/main/java/org/eclipse/store/examples/helloworld/HelloWorld.java @@ -0,0 +1,48 @@ + +package org.eclipse.store.examples.helloworld; + +/*- + * #%L + * EclipseStore Example Hello World + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.nio.file.Paths; +import java.util.Date; + +import org.eclipse.store.storage.embedded.types.EmbeddedStorage; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + + +public class HelloWorld +{ + public static void main(final String[] args) + { + // Application-specific root instance + final DataRoot root = new DataRoot(); + + // Initialize a storage manager ("the database") with the given directory and defaults for everything else. + final EmbeddedStorageManager storageManager = EmbeddedStorage.start(root, Paths.get("data")); + + // print the root to show its loaded content (stored in the last execution). + System.out.println(root); + + // Set content data to the root element, including the time to visualize changes on the next execution. + root.setContent("Hello World! @ " + new Date()); + + // Store the modified root and its content. + storageManager.storeRoot(); + + // Shutdown is optional as the storage concept is inherently crash-safe +// storageManager.shutdown(); + System.exit(0); + } +} diff --git a/examples/items/LICENSE b/examples/items/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/items/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/examples/items/pom.xml b/examples/items/pom.xml new file mode 100644 index 00000000..db00eab2 --- /dev/null +++ b/examples/items/pom.xml @@ -0,0 +1,43 @@ + + + + + 4.0.0 + + + org.eclipse.store + examples-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + examples-items + + EclipseStore Example Items + EclipseStore Items Example + https://projects.eclipse.org/projects/technology.store + + + + org.eclipse.store + storage-embedded + 1.0.0-SNAPSHOT + + + org.eclipse.serializer + persistence-binary-jdk8 + 1.0.0-SNAPSHOT + + + info.picocli + picocli + + + info.picocli + picocli-shell-jline3 + + + + diff --git a/examples/items/src/main/java/org/eclipse/store/examples/items/Commands.java b/examples/items/src/main/java/org/eclipse/store/examples/items/Commands.java new file mode 100644 index 00000000..28c71e3e --- /dev/null +++ b/examples/items/src/main/java/org/eclipse/store/examples/items/Commands.java @@ -0,0 +1,209 @@ +package org.eclipse.store.examples.items; + +/*- + * #%L + * EclipseStore Example Items + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + +import picocli.CommandLine; +import picocli.CommandLine.Command; +import picocli.CommandLine.Parameters; + +@Command(name = "") +public class Commands +{ + public static CommandLine createCommandLine(final EmbeddedStorageManager storageManager) + { + final CommandLine cli = new CommandLine(new Commands()); + cli.addSubcommand(new AddCommand(storageManager)); + cli.addSubcommand(new RemoveCommand(storageManager)); + cli.addSubcommand(new SearchCommand(storageManager)); + cli.addSubcommand(new ListCommand(storageManager)); + cli.addSubcommand(new QuitCommand(storageManager)); + return cli; + } + + static abstract class Abstract implements Runnable + { + final EmbeddedStorageManager storageManager; + + Abstract(final EmbeddedStorageManager storageManager) + { + this.storageManager = storageManager; + } + + DataRoot data() + { + return (DataRoot)this.storageManager.root(); + } + + void print(final List items) + { + if(items.isEmpty()) + { + System.out.println("No items found"); + } + else + { + System.out.println("Found " + items.size() + " item(s):"); + for(int i = 0, c = items.size(); i < c; i++) + { + System.out.println(i + " " + items.get(i)); + } + } + } + } + + @Command( + name = "add", + aliases = {"a"}, + description = "Adds an item", + mixinStandardHelpOptions = true + ) + static class AddCommand extends Abstract + { + @Parameters( + index = "0", + description = "the new item name" + ) + String item; + + AddCommand(final EmbeddedStorageManager storageManager) + { + super(storageManager); + } + + @Override + public void run() + { + final List items = this.data().items(); + items.add(new Item(this.item)); + this.storageManager.store(items); + System.out.println("Item added"); + } + } + + @Command( + name = "remove", + aliases = {"r"}, + description = "Removes an item at the specified index", + mixinStandardHelpOptions = true + ) + static class RemoveCommand extends Abstract + { + @Parameters( + index = "0", + description = "the item's index" + ) + int index; + + RemoveCommand(final EmbeddedStorageManager storageManager) + { + super(storageManager); + } + + @Override + public void run() + { + final List items = this.data().items(); + if(this.index < 0 || this.index >= items.size()) + { + System.out.println("Invalid index"); + } + else + { + items.remove(this.index); + this.storageManager.store(items); + System.out.println("Item removed"); + } + } + } + + @Command( + name = "search", + aliases = {"s"}, + description = "Searches items", + mixinStandardHelpOptions = true + ) + static class SearchCommand extends Abstract + { + @Parameters( + index = "0", + description = "search term" + ) + String term; + + SearchCommand(final EmbeddedStorageManager storageManager) + { + super(storageManager); + } + + @Override + public void run() + { + final List items = this.data().items().stream() + .filter(item -> item.getTitle().toLowerCase().startsWith(this.term)) + .collect(Collectors.toList()); + this.print(items); + } + } + + @Command( + name = "list", + aliases = {"l"}, + description = "List all items", + mixinStandardHelpOptions = true + ) + static class ListCommand extends Abstract + { + ListCommand(final EmbeddedStorageManager storageManager) + { + super(storageManager); + } + + @Override + public void run() + { + this.print(this.data().items()); + } + } + + @Command( + name = "quit", + aliases = {"q"}, + description = "Exits the program", + mixinStandardHelpOptions = true + ) + static class QuitCommand extends Abstract + { + QuitCommand(final EmbeddedStorageManager storageManager) + { + super(storageManager); + } + + @Override + public void run() + { + this.storageManager.shutdown(); + + System.out.println("Bye!"); + + System.exit(0); + } + } + +} diff --git a/examples/items/src/main/java/org/eclipse/store/examples/items/DataRoot.java b/examples/items/src/main/java/org/eclipse/store/examples/items/DataRoot.java new file mode 100644 index 00000000..9cce4b14 --- /dev/null +++ b/examples/items/src/main/java/org/eclipse/store/examples/items/DataRoot.java @@ -0,0 +1,35 @@ + +package org.eclipse.store.examples.items; + +/*- + * #%L + * EclipseStore Example Items + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.ArrayList; +import java.util.List; + + +public class DataRoot +{ + private final List items = new ArrayList<>(); + + public DataRoot() + { + super(); + } + + public List items() + { + return this.items; + } +} diff --git a/examples/items/src/main/java/org/eclipse/store/examples/items/Item.java b/examples/items/src/main/java/org/eclipse/store/examples/items/Item.java new file mode 100644 index 00000000..4fb93fc9 --- /dev/null +++ b/examples/items/src/main/java/org/eclipse/store/examples/items/Item.java @@ -0,0 +1,51 @@ + +package org.eclipse.store.examples.items; + +/*- + * #%L + * EclipseStore Example Items + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.time.LocalDateTime; + + +public class Item +{ + private final String title; + private final LocalDateTime createdAt; + + public Item( + final String title + ) + { + super(); + + this.title = title; + this.createdAt = LocalDateTime.now(); + } + + public String getTitle() + { + return this.title; + } + + public LocalDateTime getCreatedAt() + { + return this.createdAt; + } + + @Override + public String toString() + { + return this.title + " created at " + this.createdAt; + } +} diff --git a/examples/items/src/main/java/org/eclipse/store/examples/items/Main.java b/examples/items/src/main/java/org/eclipse/store/examples/items/Main.java new file mode 100644 index 00000000..52acbdf8 --- /dev/null +++ b/examples/items/src/main/java/org/eclipse/store/examples/items/Main.java @@ -0,0 +1,170 @@ + +package org.eclipse.store.examples.items; + +/*- + * #%L + * EclipseStore Example Items + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; + +import org.eclipse.serializer.exceptions.IORuntimeException; +import org.eclipse.store.storage.embedded.types.EmbeddedStorage; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.jline.builtins.Builtins; +import org.jline.builtins.Completers.SystemCompleter; +import org.jline.builtins.Widgets.CmdDesc; +import org.jline.builtins.Widgets.CmdLine; +import org.jline.builtins.Widgets.TailTipWidgets; +import org.jline.builtins.Widgets.TailTipWidgets.TipType; +import org.jline.reader.LineReader; +import org.jline.reader.LineReaderBuilder; +import org.jline.reader.MaskingCallback; +import org.jline.reader.ParsedLine; +import org.jline.reader.Parser; +import org.jline.reader.impl.DefaultParser; +import org.jline.terminal.Terminal; +import org.jline.terminal.TerminalBuilder; + +import picocli.CommandLine; +import picocli.shell.jline3.PicocliCommands; + + +public class Main +{ + public static void main(final String[] args) + { + new Main().startCli(); + } + + private final EmbeddedStorageManager storageManager; + + private Main() + { + this.storageManager = EmbeddedStorage.start( + new DataRoot(), + Paths.get("data") + ); + } + + /** + * Starts the command line interface, for commands see {@link Commands} + */ + @SuppressWarnings("unused") + private void startCli() + { + final Path workDir = Paths.get(""); + final Builtins builtins = new Builtins(workDir, null, null); + builtins.rename(Builtins.Command.TTOP, "top"); + builtins.alias("zle", "widget"); + builtins.alias("bindkey", "keymap"); + final SystemCompleter systemCompleter = builtins.compileCompleters(); + final CommandLine cli = Commands.createCommandLine(this.storageManager); + final PicocliCommands picocliCommands = new PicocliCommands(workDir, cli); + systemCompleter.add(picocliCommands.compileCompleters()); + systemCompleter.compile(); + Terminal terminal; + try + { + terminal = TerminalBuilder.builder().build(); + } + catch(final IOException e) + { + throw new IORuntimeException(e); + } + final LineReader reader = LineReaderBuilder.builder() + .terminal(terminal) + .completer(systemCompleter) + .parser(new DefaultParser()) + .variable(LineReader.LIST_MAX, 50) + .build(); + builtins.setLineReader(reader); + final DescriptionGenerator descriptionGenerator = new DescriptionGenerator(builtins, picocliCommands); + new TailTipWidgets(reader, descriptionGenerator::commandDescription, 5, TipType.COMPLETER); + + cli.usage(System.out); + + final String prompt = "Items> "; + final String rightPrompt = null; + + while(true) + { + final String line = reader.readLine(prompt, rightPrompt, (MaskingCallback) null, null); + if(line.matches("^\\s*#.*")) + { + continue; + } + final ParsedLine pl = reader.getParser().parse(line, 0); + final String[] arguments = pl.words().toArray(new String[0]); + final String command = Parser.getCommand(pl.word()); + if(builtins.hasCommand(command)) + { + try + { + builtins.execute( + command, + Arrays.copyOfRange(arguments, 1, arguments.length), + System.in, + System.out, + System.err + ); + } + catch(final Exception e) + { + throw new RuntimeException(e); + } + } + else + { + cli.execute(arguments); + } + } + } + + + private static class DescriptionGenerator + { + Builtins builtins; + PicocliCommands picocli; + + public DescriptionGenerator(final Builtins builtins, final PicocliCommands picocli) + { + this.builtins = builtins; + this.picocli = picocli; + } + + CmdDesc commandDescription(final CmdLine line) + { + switch(line.getDescriptionType()) + { + case COMMAND: + final String cmd = Parser.getCommand(line.getArgs().get(0)); + if(this.builtins.hasCommand(cmd)) + { + return this.builtins.commandDescription(cmd); + } + if(this.picocli.hasCommand(cmd)) + { + return this.picocli.commandDescription(cmd); + } + break; + default: + break; + } + return null; + } + } + +} diff --git a/examples/layered-entities/LICENSE b/examples/layered-entities/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/layered-entities/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/examples/layered-entities/pom.xml b/examples/layered-entities/pom.xml new file mode 100644 index 00000000..065c9cb3 --- /dev/null +++ b/examples/layered-entities/pom.xml @@ -0,0 +1,86 @@ + + + + + 4.0.0 + + + org.eclipse.store + examples-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + examples-layered-entities + + EclipseStore Example Layered Entities + EclipseStore Layered Entities Example + https://projects.eclipse.org/projects/technology.store + + + + org.eclipse.serializer + base + 1.0.0-SNAPSHOT + + + org.eclipse.serializer + codegen-entity + 1.0.0-SNAPSHOT + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + javac + + + + process-annotations + generate-sources + + compile + + + + org.eclipse.serializer.codegen.entity.EntityProcessor + + + -proc:only + -Amicrostream.entity.hashequalator=true + -Amicrostream.entity.appendable=true + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.4.0 + + + add-source + generate-sources + + add-source + + + + ${project.build.directory}/generated-sources/annotations + + + + + + + + + diff --git a/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Address.java b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Address.java new file mode 100644 index 00000000..908890e2 --- /dev/null +++ b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Address.java @@ -0,0 +1,26 @@ +package org.eclipse.store.examples.layeredentities; + +/*- + * #%L + * EclipseStore Example Layered Entities + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.entity.Entity; + +public interface Address extends Entity +{ + public String street(); + + public String city(); + + public String zipCode(); +} diff --git a/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Animal.java b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Animal.java new file mode 100644 index 00000000..926f7ac5 --- /dev/null +++ b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Animal.java @@ -0,0 +1,22 @@ +package org.eclipse.store.examples.layeredentities; + +/*- + * #%L + * EclipseStore Example Layered Entities + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.entity.Entity; + +public interface Animal extends Beeing, Entity +{ + public String species(); +} diff --git a/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Beeing.java b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Beeing.java new file mode 100644 index 00000000..0981c9b3 --- /dev/null +++ b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Beeing.java @@ -0,0 +1,20 @@ +package org.eclipse.store.examples.layeredentities; + +/*- + * #%L + * EclipseStore Example Layered Entities + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public interface Beeing +{ + public B partner(); +} diff --git a/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/EntityFactory.java b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/EntityFactory.java new file mode 100644 index 00000000..f30142ad --- /dev/null +++ b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/EntityFactory.java @@ -0,0 +1,62 @@ +package org.eclipse.store.examples.layeredentities; + +/*- + * #%L + * EclipseStore Example Layered Entities + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.entity.Entity; +import org.eclipse.serializer.entity.EntityVersionCleaner; +import org.eclipse.serializer.entity.EntityVersionContext; +import org.eclipse.store.examples.layeredentities._Address.AddressCreator; +import org.eclipse.store.examples.layeredentities._Animal.AnimalCreator; +import org.eclipse.store.examples.layeredentities._Human.HumanCreator; +import org.eclipse.store.examples.layeredentities._Pet.PetCreator; + + +public final class EntityFactory +{ + final static JulLogger logger = new JulLogger(); + final static EntityVersionCleaner cleaner = EntityVersionCleaner.AmountPreserving(10); + + public static AddressCreator AddressCreator() + { + return addLayers(AddressCreator.New()); + } + + public static AnimalCreator AnimalCreator() + { + return addLayers(AnimalCreator.New()); + } + + public static HumanCreator HumanCreator() + { + return addLayers(HumanCreator.New()); + } + + public static PetCreator PetCreator() + { + return addLayers(PetCreator.New()); + } + + private static > C addLayers(final C creator) + { + return creator + .addLayer(logger) + .addLayer(EntityVersionContext.AutoIncrementingInt(cleaner)) + ; + } + + private EntityFactory() + { + } +} diff --git a/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Human.java b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Human.java new file mode 100644 index 00000000..bca19ed0 --- /dev/null +++ b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Human.java @@ -0,0 +1,22 @@ +package org.eclipse.store.examples.layeredentities; + +/*- + * #%L + * EclipseStore Example Layered Entities + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.entity.Entity; + +public interface Human extends Beeing, Named, Entity +{ + public Address address(); +} diff --git a/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/JulLogger.java b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/JulLogger.java new file mode 100644 index 00000000..520aa13c --- /dev/null +++ b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/JulLogger.java @@ -0,0 +1,46 @@ +package org.eclipse.store.examples.layeredentities; + +/*- + * #%L + * EclipseStore Example Layered Entities + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.logging.Logger; + +import org.eclipse.serializer.entity.Entity; +import org.eclipse.serializer.entity.EntityLogger; + +public class JulLogger implements EntityLogger +{ + public JulLogger() + { + super(); + } + + @Override + public void entityCreated(final Entity identity, final Entity data) + { + Logger.getLogger(identity.getClass().getName()) + .info("Entity created: " + data); + } + + @Override + public void afterUpdate( + final Entity identity, + final Entity data, + final boolean successful + ) + { + Logger.getLogger(identity.getClass().getName()) + .info("Entity updated: " + data); + } +} diff --git a/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/LayeredEntities.java b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/LayeredEntities.java new file mode 100644 index 00000000..102d15c7 --- /dev/null +++ b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/LayeredEntities.java @@ -0,0 +1,56 @@ +package org.eclipse.store.examples.layeredentities; + +/*- + * #%L + * EclipseStore Example Layered Entities + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.collections.types.XGettingTable; +import org.eclipse.serializer.entity.Entity; +import org.eclipse.serializer.entity.EntityVersionContext; +import org.eclipse.store.examples.layeredentities._Human.HumanUpdater; + +public class LayeredEntities +{ + public static void main(final String[] args) + { + final Human human = EntityFactory.HumanCreator() + .name("John Doe") + .address( + EntityFactory.AddressCreator() + .street("Main Street") + .city("Springfield") + .create() + ) + .create(); + + HumanUpdater.setAddress( + human, + EntityFactory.AddressCreator() + .street("Rose Boulevard") + .city("Newtown") + .create() + ); + + printVersions(human); + } + + static void printVersions(final Entity entity) + { + final EntityVersionContext context = EntityVersionContext.lookup(entity); + final XGettingTable versions = context.versions(entity); + versions.iterate(v -> + System.out.println("Version " + v.key() + " = " + v.value()) + ); + } + +} diff --git a/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Named.java b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Named.java new file mode 100644 index 00000000..3377ebb7 --- /dev/null +++ b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Named.java @@ -0,0 +1,20 @@ +package org.eclipse.store.examples.layeredentities; + +/*- + * #%L + * EclipseStore Example Layered Entities + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public interface Named +{ + public String name(); +} diff --git a/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Pet.java b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Pet.java new file mode 100644 index 00000000..ae278c73 --- /dev/null +++ b/examples/layered-entities/src/main/java/org/eclipse/store/examples/layeredentities/Pet.java @@ -0,0 +1,20 @@ +package org.eclipse.store.examples.layeredentities; + +/*- + * #%L + * EclipseStore Example Layered Entities + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public interface Pet extends Animal, Named +{ + // plaing typing interface +} diff --git a/examples/lazy-loading/LICENSE b/examples/lazy-loading/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/lazy-loading/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/examples/lazy-loading/pom.xml b/examples/lazy-loading/pom.xml new file mode 100644 index 00000000..47200fe8 --- /dev/null +++ b/examples/lazy-loading/pom.xml @@ -0,0 +1,35 @@ + + + + + 4.0.0 + + + org.eclipse.store + examples-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + examples-lazy-loading + + EclipseStore Example Lazy Loading + EclipseStore Lazy Loading Example + https://projects.eclipse.org/projects/technology.store + + + + org.eclipse.store + storage-embedded + 1.0.0-SNAPSHOT + + + org.eclipse.serializer + persistence-binary-jdk8 + 1.0.0-SNAPSHOT + + + + diff --git a/examples/lazy-loading/src/main/java/org/eclipse/store/examples/lazyLoading/BusinessYear.java b/examples/lazy-loading/src/main/java/org/eclipse/store/examples/lazyLoading/BusinessYear.java new file mode 100644 index 00000000..5621d0fc --- /dev/null +++ b/examples/lazy-loading/src/main/java/org/eclipse/store/examples/lazyLoading/BusinessYear.java @@ -0,0 +1,54 @@ + +package org.eclipse.store.examples.lazyLoading; + +/*- + * #%L + * EclipseStore Example Lazy Loading + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import org.eclipse.serializer.reference.Lazy; + + +public class BusinessYear +{ + private Lazy> turnovers; + + public BusinessYear() + { + super(); + } + + private List getTurnovers() + { + return Lazy.get(this.turnovers); + } + + public void addTurnover(final Turnover turnover) + { + List turnovers = this.getTurnovers(); + if(turnovers == null) + { + this.turnovers = Lazy.Reference(turnovers = new ArrayList<>()); + } + turnovers.add(turnover); + } + + public Stream turnovers() + { + final List turnovers = this.getTurnovers(); + return turnovers != null ? turnovers.stream() : Stream.empty(); + } +} diff --git a/examples/lazy-loading/src/main/java/org/eclipse/store/examples/lazyLoading/Main.java b/examples/lazy-loading/src/main/java/org/eclipse/store/examples/lazyLoading/Main.java new file mode 100644 index 00000000..f3c35ab5 --- /dev/null +++ b/examples/lazy-loading/src/main/java/org/eclipse/store/examples/lazyLoading/Main.java @@ -0,0 +1,121 @@ + +package org.eclipse.store.examples.lazyLoading; + +/*- + * #%L + * EclipseStore Example Lazy Loading + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.nio.file.Paths; +import java.text.NumberFormat; +import java.time.Instant; +import java.time.Year; +import java.util.Map; +import java.util.Random; +import java.util.stream.Collectors; + +import org.eclipse.store.storage.embedded.types.EmbeddedStorage; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + + +/** + * Lazy loading example. Lazy part is in {@link BusinessYear}. + * + * + */ +public class Main +{ + public static void main(final String[] args) + { + final EmbeddedStorageManager storageManager = EmbeddedStorage.start(Paths.get("data")); + if(storageManager.root() == null) + { + storageManager.setRoot(createSampleData()); + storageManager.storeRoot(); + } + + calcRevenue(storageManager); + + System.out.println(); + System.out.println("No going full in memory!"); + + calcRevenue(storageManager); + + storageManager.shutdown(); + } + + private static void calcRevenue(final EmbeddedStorageManager storageManager) + { + final MyBusinessApp root = (MyBusinessApp)storageManager.root(); + + final int startYear = Year.now().getValue() - 3; + final long now = System.currentTimeMillis(); + + final Map yearToRevenue = root.getBusinessYears().entrySet().stream() + .filter(e -> e.getKey() >= startYear) + .collect(Collectors.toMap( + e -> e.getKey(), + e -> e.getValue().turnovers() + .mapToDouble(Turnover::getAmount) + .sum())); + + final double overallRevenue = yearToRevenue.values().stream() + .mapToDouble(Double::doubleValue) + .sum(); + + final NumberFormat numberFormat = NumberFormat.getCurrencyInstance(); + + System.out.println(); + + System.out.println( + "Overall Revenue since " + startYear + ": " + + numberFormat.format(overallRevenue)); + + yearToRevenue.entrySet().stream() + .sorted((e1, e2) -> Integer.compare(e1.getKey(), e2.getKey())) + .forEach(e -> System.out.println( + "Revenue in " + + e.getKey() + + ": " + + numberFormat.format(e.getValue()))); + + final long recordCount = root.getBusinessYears().entrySet().stream() + .filter(e -> e.getKey() >= startYear) + .mapToLong(e -> 2 + 2 * e.getValue().turnovers().count()) + .sum(); + + System.out.println( + "Took " + (System.currentTimeMillis() - now) + + " ms for " + NumberFormat.getIntegerInstance().format(recordCount) + " records"); + } + + private static MyBusinessApp createSampleData() + { + System.out.println("Creating sample data..."); + + final MyBusinessApp app = new MyBusinessApp(); + + final Random random = new Random(); + + for(int year = 2000, thisYear = Year.now().getValue(); year <= thisYear; year++) + { + final BusinessYear businessYear = new BusinessYear(); + for(int i = 0, c = (int)(random.nextDouble() * 100000); i < c; i++) + { + businessYear.addTurnover(new Turnover(random.nextDouble() * 100_000, Instant.now())); + } + app.getBusinessYears().put(year, businessYear); + } + + return app; + } +} diff --git a/examples/lazy-loading/src/main/java/org/eclipse/store/examples/lazyLoading/MyBusinessApp.java b/examples/lazy-loading/src/main/java/org/eclipse/store/examples/lazyLoading/MyBusinessApp.java new file mode 100644 index 00000000..f1720ef5 --- /dev/null +++ b/examples/lazy-loading/src/main/java/org/eclipse/store/examples/lazyLoading/MyBusinessApp.java @@ -0,0 +1,34 @@ + +package org.eclipse.store.examples.lazyLoading; + +/*- + * #%L + * EclipseStore Example Lazy Loading + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.HashMap; + + +public class MyBusinessApp +{ + private final HashMap businessYears = new HashMap<>(); + + public MyBusinessApp() + { + super(); + } + + public HashMap getBusinessYears() + { + return this.businessYears; + } +} diff --git a/examples/lazy-loading/src/main/java/org/eclipse/store/examples/lazyLoading/Turnover.java b/examples/lazy-loading/src/main/java/org/eclipse/store/examples/lazyLoading/Turnover.java new file mode 100644 index 00000000..f69c9a65 --- /dev/null +++ b/examples/lazy-loading/src/main/java/org/eclipse/store/examples/lazyLoading/Turnover.java @@ -0,0 +1,41 @@ +package org.eclipse.store.examples.lazyLoading; + +/*- + * #%L + * EclipseStore Example Lazy Loading + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.time.Instant; + + +public class Turnover +{ + private final double amount; + private final Instant timestamp; + + public Turnover(final double amount, final Instant timestamp) + { + super(); + this.amount = amount; + this.timestamp = timestamp; + } + + public double getAmount() + { + return this.amount; + } + + public Instant getTimestamp() + { + return this.timestamp; + } +} diff --git a/examples/loading/LICENSE b/examples/loading/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/loading/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/examples/loading/pom.xml b/examples/loading/pom.xml new file mode 100644 index 00000000..10208024 --- /dev/null +++ b/examples/loading/pom.xml @@ -0,0 +1,35 @@ + + + + + 4.0.0 + + + org.eclipse.store + examples-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + examples-loading + + EclipseStore Example Loading + EclipseStore Loading Example + https://projects.eclipse.org/projects/technology.store + + + + org.eclipse.store + storage-embedded + 1.0.0-SNAPSHOT + + + org.eclipse.serializer + persistence-binary-jdk8 + 1.0.0-SNAPSHOT + + + + diff --git a/examples/loading/src/main/java/org/eclipse/store/examples/loading/Main.java b/examples/loading/src/main/java/org/eclipse/store/examples/loading/Main.java new file mode 100644 index 00000000..485e34eb --- /dev/null +++ b/examples/loading/src/main/java/org/eclipse/store/examples/loading/Main.java @@ -0,0 +1,58 @@ +package org.eclipse.store.examples.loading; + +/*- + * #%L + * EclipseStore Example Loading + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.storage.embedded.types.EmbeddedStorage; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + + +/** + * + * A very simple example how to load an existing database + * Run twice, the first run creates a database, all further runs + * load it. + * + */ +public class Main +{ + public static void main(final String[] args) + { + // Init storage manager + final EmbeddedStorageManager storage = EmbeddedStorage.start(); + + //if storage.root() returns null no data have been loaded + //since there is no existing database, let's create a new one. + if(storage.root() == null) + { + System.out.println("No existing Database found, creating a new one:"); + + final MyRoot root = new MyRoot(); + storage.setRoot(root); + root.myObjects.add(new MyData("Alice", 20)); + root.myObjects.add(new MyData("Bob" , 25)); + storage.storeRoot(); + } + //storage.root() is not null so we have loaded data + else + { + System.out.println("Existing Database found:"); + + final MyRoot root = (MyRoot) storage.root(); + root.myObjects.forEach(System.out::println); + } + + storage.shutdown(); + } +} diff --git a/examples/loading/src/main/java/org/eclipse/store/examples/loading/MyData.java b/examples/loading/src/main/java/org/eclipse/store/examples/loading/MyData.java new file mode 100644 index 00000000..09c0a8d4 --- /dev/null +++ b/examples/loading/src/main/java/org/eclipse/store/examples/loading/MyData.java @@ -0,0 +1,56 @@ + +package org.eclipse.store.examples.loading; + +/*- + * #%L + * EclipseStore Example Loading + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class MyData +{ + private String name; + private int intValue; + + public MyData(final String name, final int value) + { + super(); + this.name = name; + this.intValue = value; + } + + public String getName() + { + return this.name; + } + + public void setName(final String name) + { + this.name = name; + } + + public int getIntegerValue() + { + return this.intValue; + } + + public void setIntValue(final int integerValue) + { + this.intValue = integerValue; + } + + @Override + public String toString() + { + return this.name + " value: " + this.intValue; + } + +} diff --git a/examples/loading/src/main/java/org/eclipse/store/examples/loading/MyRoot.java b/examples/loading/src/main/java/org/eclipse/store/examples/loading/MyRoot.java new file mode 100644 index 00000000..aba9b150 --- /dev/null +++ b/examples/loading/src/main/java/org/eclipse/store/examples/loading/MyRoot.java @@ -0,0 +1,23 @@ +package org.eclipse.store.examples.loading; + +/*- + * #%L + * EclipseStore Example Loading + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.ArrayList; +import java.util.List; + +public class MyRoot +{ + public List myObjects = new ArrayList<>(); +} diff --git a/examples/pom.xml b/examples/pom.xml new file mode 100644 index 00000000..e6df4c2a --- /dev/null +++ b/examples/pom.xml @@ -0,0 +1,80 @@ + + + + + 4.0.0 + + + org.eclipse.store + store-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + examples-parent + pom + + EclipseStore Examples + Examples for EclipseStore + https://projects.eclipse.org/projects/technology.store + + + blobs + custom-type-handler + custom-legacy-type-handler + deleting + eager-storing + extension-wrapper + filesystems + helloworld + helloworld-ini + items + layered-entities + lazy-loading + loading + reloader + storing + + + + + + com.google.jimfs + jimfs + 1.2 + + + info.picocli + picocli + 4.2.0 + + + info.picocli + picocli-shell-jline3 + 4.2.0 + + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.apache.maven.plugins + maven-enforcer-plugin + + true + + + + + + diff --git a/examples/reloader/LICENSE b/examples/reloader/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/reloader/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/examples/reloader/pom.xml b/examples/reloader/pom.xml new file mode 100644 index 00000000..5268d3c0 --- /dev/null +++ b/examples/reloader/pom.xml @@ -0,0 +1,30 @@ + + + + + 4.0.0 + + + org.eclipse.store + examples-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + examples-reloader + + EclipseStore Example Reloader + EclipseStore Reloader Example + https://projects.eclipse.org/projects/technology.store + + + + org.eclipse.store + storage-embedded-configuration + 1.0.0-SNAPSHOT + + + + diff --git a/examples/reloader/src/main/java/org/eclipse/store/examples/reloader/DataRoot.java b/examples/reloader/src/main/java/org/eclipse/store/examples/reloader/DataRoot.java new file mode 100644 index 00000000..6061a4d4 --- /dev/null +++ b/examples/reloader/src/main/java/org/eclipse/store/examples/reloader/DataRoot.java @@ -0,0 +1,34 @@ +package org.eclipse.store.examples.reloader; + +/*- + * #%L + * EclipseStore Example Reloader + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.ArrayList; +import java.util.List; + +public class DataRoot +{ + + private final List data = new ArrayList<>(); + + public List getData() + { + return this.data; + } + + public void addItem(final String value) { + this.data.add(value); + } + +} diff --git a/examples/reloader/src/main/java/org/eclipse/store/examples/reloader/ExampleProgram.java b/examples/reloader/src/main/java/org/eclipse/store/examples/reloader/ExampleProgram.java new file mode 100644 index 00000000..7302dbf0 --- /dev/null +++ b/examples/reloader/src/main/java/org/eclipse/store/examples/reloader/ExampleProgram.java @@ -0,0 +1,65 @@ +package org.eclipse.store.examples.reloader; + +/*- + * #%L + * EclipseStore Example Reloader + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.stream.Collectors; + +import org.eclipse.serializer.persistence.binary.types.Binary; +import org.eclipse.serializer.persistence.types.PersistenceManager; +import org.eclipse.serializer.persistence.util.Reloader; +import org.eclipse.store.storage.types.StorageManager; + +public class ExampleProgram +{ + + public static void main(final String[] args) + { + final DataRoot root = new DataRoot(); + try (StorageManager storageManager = StorageProvider.createStorageManager("target/data", root) + .start()) + { + root.addItem("value 1"); + root.addItem("value 2"); + + storageManager.store(root.getData()); + + System.out.printf("Number of items in list: %s%n", root.getData() + .size()); + + root.getData() + .clear(); + System.out.printf("Number of items in list after clear: %s (surprise :) )%n", root.getData() + .size()); + + reload(storageManager.persistenceManager(), root); + System.out.printf("Number of items in list after reload: %s%n", root.getData() + .size()); + + System.out.println(root.getData() + .stream() + .collect(Collectors.joining(", ", "[", "]"))); + } + } + + private static void reload(final PersistenceManager persistenceManager, final DataRoot root) + { + final Reloader reloader = Reloader.New(persistenceManager); + reloader.reloadFlat(root.getData()); + // reloadFlat is enough here as we just changed the List object. + // You can also use .reloadFlat() to reload the object and all objects within the object if you have changed data + // at multiple levels. + } +} + diff --git a/examples/reloader/src/main/java/org/eclipse/store/examples/reloader/StorageProvider.java b/examples/reloader/src/main/java/org/eclipse/store/examples/reloader/StorageProvider.java new file mode 100644 index 00000000..dabb67d7 --- /dev/null +++ b/examples/reloader/src/main/java/org/eclipse/store/examples/reloader/StorageProvider.java @@ -0,0 +1,33 @@ +package org.eclipse.store.examples.reloader; + +/*- + * #%L + * EclipseStore Example Reloader + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.storage.embedded.configuration.types.EmbeddedStorageConfiguration; +import org.eclipse.store.storage.types.StorageManager; + +public class StorageProvider +{ + + public static StorageManager createStorageManager(final String storageDirectory, final Object root) { + + return EmbeddedStorageConfiguration.Builder() + .setStorageDirectory(storageDirectory) + + .createEmbeddedStorageFoundation() + .setRoot(root) + + .createEmbeddedStorageManager(); + } +} diff --git a/examples/storing/LICENSE b/examples/storing/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/storing/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/examples/storing/pom.xml b/examples/storing/pom.xml new file mode 100644 index 00000000..ed1caf11 --- /dev/null +++ b/examples/storing/pom.xml @@ -0,0 +1,36 @@ + + + + + 4.0.0 + + + org.eclipse.store + examples-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + examples-storing + + EclipseStore Example Storing + EclipseStore Storing Example + https://projects.eclipse.org/projects/technology.store + + + + org.eclipse.store + storage-embedded + 1.0.0-SNAPSHOT + + + org.eclipse.serializer + persistence-binary-jdk8 + 1.0.0-SNAPSHOT + + + + diff --git a/examples/storing/src/main/java/one/microstream/examples/storing/Main.java b/examples/storing/src/main/java/one/microstream/examples/storing/Main.java new file mode 100644 index 00000000..76a98717 --- /dev/null +++ b/examples/storing/src/main/java/one/microstream/examples/storing/Main.java @@ -0,0 +1,56 @@ +package one.microstream.examples.storing; + +/*- + * #%L + * EclipseStore Example Storing + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.storage.embedded.types.EmbeddedStorage; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + +/** + * Microstream data storing example + * + */ +public class Main +{ + public static void main( final String[] args ) + { + // Root instance + final MyRoot root = new MyRoot(); + + // Init storage manager + final EmbeddedStorageManager storageManager = EmbeddedStorage.start(root); + + //store the root object + storageManager.storeRoot(); + + //add a new data object to the list in root + final MyData dataItem = new MyData("Alice"); + root.myObjects.add(dataItem); + + //store the modified list + storageManager.store(root.myObjects); + + //modify a value type member and store it + dataItem .setIntValue(100); + storageManager.store(dataItem); + + //modify a string object and store it + dataItem .setName("Bob"); + storageManager.store(dataItem); + + + //shutdown + storageManager.shutdown(); + } +} diff --git a/examples/storing/src/main/java/one/microstream/examples/storing/MyData.java b/examples/storing/src/main/java/one/microstream/examples/storing/MyData.java new file mode 100644 index 00000000..2a092aed --- /dev/null +++ b/examples/storing/src/main/java/one/microstream/examples/storing/MyData.java @@ -0,0 +1,55 @@ + +package one.microstream.examples.storing; + +/*- + * #%L + * EclipseStore Example Storing + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class MyData +{ + private String name; + private int intValue; + + public MyData(final String content) + { + super(); + this.name = content; + } + + public String getName() + { + return this.name; + } + + public void setName(final String name) + { + this.name = name; + } + + public int getIntegerValue() + { + return this.intValue; + } + + public void setIntValue(final int integerValue) + { + this.intValue = integerValue; + } + + @Override + public String toString() + { + return this.name + " value: " + this.intValue; + } + +} diff --git a/examples/storing/src/main/java/one/microstream/examples/storing/MyRoot.java b/examples/storing/src/main/java/one/microstream/examples/storing/MyRoot.java new file mode 100644 index 00000000..789ec661 --- /dev/null +++ b/examples/storing/src/main/java/one/microstream/examples/storing/MyRoot.java @@ -0,0 +1,23 @@ +package one.microstream.examples.storing; + +/*- + * #%L + * EclipseStore Example Storing + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.ArrayList; +import java.util.List; + +public class MyRoot +{ + public List myObjects = new ArrayList<>(); +} diff --git a/pom.xml b/pom.xml index 57bed089..57639a3b 100644 --- a/pom.xml +++ b/pom.xml @@ -378,6 +378,12 @@ + + examples + + examples + + production From ad5ce858742aa2058f01bea0224f987d02920081 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Mon, 13 Nov 2023 14:00:50 +0100 Subject: [PATCH 007/126] remove modules with incompatible license --- afs/hazelcast/LICENSE | 277 ------------- afs/hazelcast/pom.xml | 40 -- afs/hazelcast/src/main/java/module-info.java | 25 -- .../afs/hazelcast/types/BlobMetadata.java | 68 --- .../hazelcast/types/HazelcastConnector.java | 311 -------------- .../types/HazelcastFileSystemCreator.java | 114 ------ ...figuration.types.ConfigurationBasedCreator | 1 - afs/oracle/LICENSE | 277 ------------- afs/oracle/coherence/LICENSE | 277 ------------- afs/oracle/coherence/pom.xml | 52 --- .../coherence/src/main/java/module-info.java | 25 -- .../oracle/coherence/types/BlobMetadata.java | 68 --- .../types/OracleCoherenceConnector.java | 387 ------------------ .../OracleCoherenceFileSystemCreator.java | 67 --- ...figuration.types.ConfigurationBasedCreator | 1 - afs/oracle/pom.xml | 27 -- afs/pom.xml | 2 - docs/modules/ROOT/nav.adoc | 2 - .../blob-stores/hazelcast.adoc | 50 --- .../blob-stores/oracle-coherence.adoc | 42 -- 20 files changed, 2113 deletions(-) delete mode 100644 afs/hazelcast/LICENSE delete mode 100644 afs/hazelcast/pom.xml delete mode 100644 afs/hazelcast/src/main/java/module-info.java delete mode 100644 afs/hazelcast/src/main/java/org/eclipse/store/afs/hazelcast/types/BlobMetadata.java delete mode 100644 afs/hazelcast/src/main/java/org/eclipse/store/afs/hazelcast/types/HazelcastConnector.java delete mode 100644 afs/hazelcast/src/main/java/org/eclipse/store/afs/hazelcast/types/HazelcastFileSystemCreator.java delete mode 100644 afs/hazelcast/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator delete mode 100644 afs/oracle/LICENSE delete mode 100644 afs/oracle/coherence/LICENSE delete mode 100644 afs/oracle/coherence/pom.xml delete mode 100644 afs/oracle/coherence/src/main/java/module-info.java delete mode 100644 afs/oracle/coherence/src/main/java/org/eclipse/store/afs/oracle/coherence/types/BlobMetadata.java delete mode 100644 afs/oracle/coherence/src/main/java/org/eclipse/store/afs/oracle/coherence/types/OracleCoherenceConnector.java delete mode 100644 afs/oracle/coherence/src/main/java/org/eclipse/store/afs/oracle/coherence/types/OracleCoherenceFileSystemCreator.java delete mode 100644 afs/oracle/coherence/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator delete mode 100644 afs/oracle/pom.xml delete mode 100644 docs/modules/storage/pages/storage-targets/blob-stores/hazelcast.adoc delete mode 100644 docs/modules/storage/pages/storage-targets/blob-stores/oracle-coherence.adoc diff --git a/afs/hazelcast/LICENSE b/afs/hazelcast/LICENSE deleted file mode 100644 index d3087e4c..00000000 --- a/afs/hazelcast/LICENSE +++ /dev/null @@ -1,277 +0,0 @@ -Eclipse Public License - v 2.0 - - THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE - PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION - OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. - -1. DEFINITIONS - -"Contribution" means: - - a) in the case of the initial Contributor, the initial content - Distributed under this Agreement, and - - b) in the case of each subsequent Contributor: - i) changes to the Program, and - ii) additions to the Program; - where such changes and/or additions to the Program originate from - and are Distributed by that particular Contributor. A Contribution - "originates" from a Contributor if it was added to the Program by - such Contributor itself or anyone acting on such Contributor's behalf. - Contributions do not include changes or additions to the Program that - are not Modified Works. - -"Contributor" means any person or entity that Distributes the Program. - -"Licensed Patents" mean patent claims licensable by a Contributor which -are necessarily infringed by the use or sale of its Contribution alone -or when combined with the Program. - -"Program" means the Contributions Distributed in accordance with this -Agreement. - -"Recipient" means anyone who receives the Program under this Agreement -or any Secondary License (as applicable), including Contributors. - -"Derivative Works" shall mean any work, whether in Source Code or other -form, that is based on (or derived from) the Program and for which the -editorial revisions, annotations, elaborations, or other modifications -represent, as a whole, an original work of authorship. - -"Modified Works" shall mean any work in Source Code or other form that -results from an addition to, deletion from, or modification of the -contents of the Program, including, for purposes of clarity any new file -in Source Code form that contains any contents of the Program. Modified -Works shall not include works that contain only declarations, -interfaces, types, classes, structures, or files of the Program solely -in each case in order to link to, bind by name, or subclass the Program -or Modified Works thereof. - -"Distribute" means the acts of a) distributing or b) making available -in any manner that enables the transfer of a copy. - -"Source Code" means the form of a Program preferred for making -modifications, including but not limited to software source code, -documentation source, and configuration files. - -"Secondary License" means either the GNU General Public License, -Version 2.0, or any later versions of that license, including any -exceptions or additional permissions as identified by the initial -Contributor. - -2. GRANT OF RIGHTS - - a) Subject to the terms of this Agreement, each Contributor hereby - grants Recipient a non-exclusive, worldwide, royalty-free copyright - license to reproduce, prepare Derivative Works of, publicly display, - publicly perform, Distribute and sublicense the Contribution of such - Contributor, if any, and such Derivative Works. - - b) Subject to the terms of this Agreement, each Contributor hereby - grants Recipient a non-exclusive, worldwide, royalty-free patent - license under Licensed Patents to make, use, sell, offer to sell, - import and otherwise transfer the Contribution of such Contributor, - if any, in Source Code or other form. This patent license shall - apply to the combination of the Contribution and the Program if, at - the time the Contribution is added by the Contributor, such addition - of the Contribution causes such combination to be covered by the - Licensed Patents. The patent license shall not apply to any other - combinations which include the Contribution. No hardware per se is - licensed hereunder. - - c) Recipient understands that although each Contributor grants the - licenses to its Contributions set forth herein, no assurances are - provided by any Contributor that the Program does not infringe the - patent or other intellectual property rights of any other entity. - Each Contributor disclaims any liability to Recipient for claims - brought by any other entity based on infringement of intellectual - property rights or otherwise. As a condition to exercising the - rights and licenses granted hereunder, each Recipient hereby - assumes sole responsibility to secure any other intellectual - property rights needed, if any. For example, if a third party - patent license is required to allow Recipient to Distribute the - Program, it is Recipient's responsibility to acquire that license - before distributing the Program. - - d) Each Contributor represents that to its knowledge it has - sufficient copyright rights in its Contribution, if any, to grant - the copyright license set forth in this Agreement. - - e) Notwithstanding the terms of any Secondary License, no - Contributor makes additional grants to any Recipient (other than - those set forth in this Agreement) as a result of such Recipient's - receipt of the Program under the terms of a Secondary License - (if permitted under the terms of Section 3). - -3. REQUIREMENTS - -3.1 If a Contributor Distributes the Program in any form, then: - - a) the Program must also be made available as Source Code, in - accordance with section 3.2, and the Contributor must accompany - the Program with a statement that the Source Code for the Program - is available under this Agreement, and informs Recipients how to - obtain it in a reasonable manner on or through a medium customarily - used for software exchange; and - - b) the Contributor may Distribute the Program under a license - different than this Agreement, provided that such license: - i) effectively disclaims on behalf of all other Contributors all - warranties and conditions, express and implied, including - warranties or conditions of title and non-infringement, and - implied warranties or conditions of merchantability and fitness - for a particular purpose; - - ii) effectively excludes on behalf of all other Contributors all - liability for damages, including direct, indirect, special, - incidental and consequential damages, such as lost profits; - - iii) does not attempt to limit or alter the recipients' rights - in the Source Code under section 3.2; and - - iv) requires any subsequent distribution of the Program by any - party to be under a license that satisfies the requirements - of this section 3. - -3.2 When the Program is Distributed as Source Code: - - a) it must be made available under this Agreement, or if the - Program (i) is combined with other material in a separate file or - files made available under a Secondary License, and (ii) the initial - Contributor attached to the Source Code the notice described in - Exhibit A of this Agreement, then the Program may be made available - under the terms of such Secondary Licenses, and - - b) a copy of this Agreement must be included with each copy of - the Program. - -3.3 Contributors may not remove or alter any copyright, patent, -trademark, attribution notices, disclaimers of warranty, or limitations -of liability ("notices") contained within the Program from any copy of -the Program which they Distribute, provided that Contributors may add -their own appropriate notices. - -4. COMMERCIAL DISTRIBUTION - -Commercial distributors of software may accept certain responsibilities -with respect to end users, business partners and the like. While this -license is intended to facilitate the commercial use of the Program, -the Contributor who includes the Program in a commercial product -offering should do so in a manner which does not create potential -liability for other Contributors. Therefore, if a Contributor includes -the Program in a commercial product offering, such Contributor -("Commercial Contributor") hereby agrees to defend and indemnify every -other Contributor ("Indemnified Contributor") against any losses, -damages and costs (collectively "Losses") arising from claims, lawsuits -and other legal actions brought by a third party against the Indemnified -Contributor to the extent caused by the acts or omissions of such -Commercial Contributor in connection with its distribution of the Program -in a commercial product offering. The obligations in this section do not -apply to any claims or Losses relating to any actual or alleged -intellectual property infringement. In order to qualify, an Indemnified -Contributor must: a) promptly notify the Commercial Contributor in -writing of such claim, and b) allow the Commercial Contributor to control, -and cooperate with the Commercial Contributor in, the defense and any -related settlement negotiations. The Indemnified Contributor may -participate in any such claim at its own expense. - -For example, a Contributor might include the Program in a commercial -product offering, Product X. That Contributor is then a Commercial -Contributor. If that Commercial Contributor then makes performance -claims, or offers warranties related to Product X, those performance -claims and warranties are such Commercial Contributor's responsibility -alone. Under this section, the Commercial Contributor would have to -defend claims against the other Contributors related to those performance -claims and warranties, and if a court requires any other Contributor to -pay any damages as a result, the Commercial Contributor must pay -those damages. - -5. NO WARRANTY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT -PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" -BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR -IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF -TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR -PURPOSE. Each Recipient is solely responsible for determining the -appropriateness of using and distributing the Program and assumes all -risks associated with its exercise of rights under this Agreement, -including but not limited to the risks and costs of program errors, -compliance with applicable laws, damage to or loss of data, programs -or equipment, and unavailability or interruption of operations. - -6. DISCLAIMER OF LIABILITY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT -PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS -SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST -PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE -EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - -7. GENERAL - -If any provision of this Agreement is invalid or unenforceable under -applicable law, it shall not affect the validity or enforceability of -the remainder of the terms of this Agreement, and without further -action by the parties hereto, such provision shall be reformed to the -minimum extent necessary to make such provision valid and enforceable. - -If Recipient institutes patent litigation against any entity -(including a cross-claim or counterclaim in a lawsuit) alleging that the -Program itself (excluding combinations of the Program with other software -or hardware) infringes such Recipient's patent(s), then such Recipient's -rights granted under Section 2(b) shall terminate as of the date such -litigation is filed. - -All Recipient's rights under this Agreement shall terminate if it -fails to comply with any of the material terms or conditions of this -Agreement and does not cure such failure in a reasonable period of -time after becoming aware of such noncompliance. If all Recipient's -rights under this Agreement terminate, Recipient agrees to cease use -and distribution of the Program as soon as reasonably practicable. -However, Recipient's obligations under this Agreement and any licenses -granted by Recipient relating to the Program shall continue and survive. - -Everyone is permitted to copy and distribute copies of this Agreement, -but in order to avoid inconsistency the Agreement is copyrighted and -may only be modified in the following manner. The Agreement Steward -reserves the right to publish new versions (including revisions) of -this Agreement from time to time. No one other than the Agreement -Steward has the right to modify this Agreement. The Eclipse Foundation -is the initial Agreement Steward. The Eclipse Foundation may assign the -responsibility to serve as the Agreement Steward to a suitable separate -entity. Each new version of the Agreement will be given a distinguishing -version number. The Program (including Contributions) may always be -Distributed subject to the version of the Agreement under which it was -received. In addition, after a new version of the Agreement is published, -Contributor may elect to Distribute the Program (including its -Contributions) under the new version. - -Except as expressly stated in Sections 2(a) and 2(b) above, Recipient -receives no rights or licenses to the intellectual property of any -Contributor under this Agreement, whether expressly, by implication, -estoppel or otherwise. All rights in the Program not expressly granted -under this Agreement are reserved. Nothing in this Agreement is intended -to be enforceable by any entity that is not a Contributor or Recipient. -No third-party beneficiary rights are created under this Agreement. - -Exhibit A - Form of Secondary Licenses Notice - -"This Source Code may also be made available under the following -Secondary Licenses when the conditions for such availability set forth -in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), -version(s), and exceptions or additional permissions here}." - - Simply including a copy of this Agreement, including this Exhibit A - is not sufficient to license the Source Code under Secondary Licenses. - - If it is not possible or desirable to put the notice in a particular - file, then You may include the notice in a location (such as a LICENSE - file in a relevant directory) where a recipient would be likely to - look for such a notice. - - You may add additional accurate notices of copyright ownership. diff --git a/afs/hazelcast/pom.xml b/afs/hazelcast/pom.xml deleted file mode 100644 index 867afecf..00000000 --- a/afs/hazelcast/pom.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - 4.0.0 - - - org.eclipse.store - afs-parent - 1.0.0-SNAPSHOT - ../pom.xml - - - afs-hazelcast - - EclipseStore Abstract File System Hazelcast - EclipseStore File System Abstraction for Hazelcast - https://projects.eclipse.org/projects/technology.store - - - - org.eclipse.store - afs-blobstore - 1.0.0-SNAPSHOT - - - org.eclipse.serializer - configuration - ${eclipse.serializer.version} - - - com.hazelcast - hazelcast - 5.1.7 - - - - diff --git a/afs/hazelcast/src/main/java/module-info.java b/afs/hazelcast/src/main/java/module-info.java deleted file mode 100644 index 4f12b79b..00000000 --- a/afs/hazelcast/src/main/java/module-info.java +++ /dev/null @@ -1,25 +0,0 @@ -/*- - * #%L - * EclipseStore Abstract File System Hazelcast - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.afs.hazelcast -{ - exports org.eclipse.store.afs.hazelcast.types; - - provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator - with org.eclipse.store.afs.hazelcast.types.HazelcastFileSystemCreator - ; - - requires transitive org.eclipse.serializer.configuration; - requires transitive org.eclipse.store.afs.blobstore; - requires transitive com.hazelcast.core; -} diff --git a/afs/hazelcast/src/main/java/org/eclipse/store/afs/hazelcast/types/BlobMetadata.java b/afs/hazelcast/src/main/java/org/eclipse/store/afs/hazelcast/types/BlobMetadata.java deleted file mode 100644 index b963aba2..00000000 --- a/afs/hazelcast/src/main/java/org/eclipse/store/afs/hazelcast/types/BlobMetadata.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.eclipse.store.afs.hazelcast.types; - -/*- - * #%L - * EclipseStore Abstract File System Hazelcast - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ - -import static org.eclipse.serializer.chars.XChars.notEmpty; -import static org.eclipse.serializer.math.XMath.notNegative; - -public interface BlobMetadata -{ - public String key(); - - public long size(); - - - public static BlobMetadata New( - final String key , - final long size - ) - { - return new BlobMetadata.Default( - notEmpty (key ), - notNegative(size) - ); - } - - - public static class Default implements BlobMetadata - { - private final String key ; - private final long size; - - Default( - final String key , - final long size - ) - { - super(); - this.key = key ; - this.size = size; - } - - @Override - public String key() - { - return this.key; - } - - @Override - public long size() - { - return this.size; - } - - } - -} diff --git a/afs/hazelcast/src/main/java/org/eclipse/store/afs/hazelcast/types/HazelcastConnector.java b/afs/hazelcast/src/main/java/org/eclipse/store/afs/hazelcast/types/HazelcastConnector.java deleted file mode 100644 index 3017365d..00000000 --- a/afs/hazelcast/src/main/java/org/eclipse/store/afs/hazelcast/types/HazelcastConnector.java +++ /dev/null @@ -1,311 +0,0 @@ -package org.eclipse.store.afs.hazelcast.types; - -/*- - * #%L - * EclipseStore Abstract File System Hazelcast - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ - -import static org.eclipse.serializer.util.X.checkArrayRange; -import static org.eclipse.serializer.util.X.notNull; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Map.Entry; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Stream; - -import com.hazelcast.core.HazelcastInstance; -import com.hazelcast.map.IMap; -import com.hazelcast.projection.Projections; -import com.hazelcast.query.Predicates; -import com.hazelcast.query.QueryConstants; - -import org.eclipse.store.afs.blobstore.types.BlobStoreConnector; -import org.eclipse.store.afs.blobstore.types.BlobStorePath; -import org.eclipse.serializer.exceptions.IORuntimeException; -import org.eclipse.serializer.io.ByteBufferInputStream; -import org.eclipse.serializer.io.LimitedInputStream; - - -/** - * Connector for the Hazelcast IMDG. - *

- * First create a connection to a Hazelcast instance. - *

- * HazelcastInstance hazelcast = ...
- * BlobStoreFileSystem fileSystem = BlobStoreFileSystem.New(
- * 	HazelcastConnector.New(hazelcast)
- * );
- * 
- * - * - * - */ -public interface HazelcastConnector extends BlobStoreConnector -{ - /** - * Pseudo-constructor method which creates a new {@link HazelcastConnector}. - * - * @param hazelcast connection to the Hazelcast instance - * @return a new {@link HazelcastConnector} - */ - public static HazelcastConnector New( - final HazelcastInstance hazelcast - ) - { - return new Default( - notNull(hazelcast), - false - ); - } - - /** - * Pseudo-constructor method which creates a new {@link HazelcastConnector} with cache. - * - * @param hazelcast connection to the Hazelcast instance - * @return a new {@link HazelcastConnector} - */ - public static HazelcastConnector Caching( - final HazelcastInstance hazelcast - ) - { - return new Default( - notNull(hazelcast), - true - ); - } - - - public static class Default - extends BlobStoreConnector.Abstract - implements HazelcastConnector - { - /* - * Blobs are stored as Lists: - * LinkedList[ // needed to get projection working ("this.getFirst") - * ArrayList[ // metadata - * String key - * Long size - * ], - * byte[] data - * ] - */ - - private static List createBlobList( - final String identifier, - final Long size , - final byte[] data - ) - { - final List metadata = new ArrayList<>(3); - metadata.add(identifier); - metadata.add(size); - - final List blob = new LinkedList<>(); - blob.add(metadata); - blob.add(data); - return blob; - } - - private static byte[] data( - final List blobList - ) - { - return (byte[])blobList.get(1); - } - - private final static long MAX_UPLOAD_BLOB_BYTES = 10_000_000L; - - private final HazelcastInstance hazelcast; - - Default( - final HazelcastInstance hazelcast, - final boolean withCache - ) - { - super( - BlobMetadata::key, - BlobMetadata::size, - withCache - ); - this.hazelcast = hazelcast; - } - - private IMap> map( - final BlobStorePath path - ) - { - return this.hazelcast.getMap(path.container()); - } - - @Override - protected Stream blobs( - final BlobStorePath file - ) - { - return this.map(file).project( - Projections.>, List>singleAttribute( - QueryConstants.THIS_ATTRIBUTE_NAME.value() + ".getFirst" - ), - Predicates.regex( - QueryConstants.KEY_ATTRIBUTE_NAME.value(), - blobKeyRegex(toBlobKeyPrefix(file)) - ) - ) - .stream() - .map(list -> BlobMetadata.New((String)list.get(0), (Long)list.get(1))) - .sorted(this.blobComparator()) - ; - } - - @Override - protected Stream childKeys( - final BlobStorePath directory - ) - { - return this.map(directory).project( - Projections.>, List>singleAttribute( - QueryConstants.THIS_ATTRIBUTE_NAME.value() + ".getFirst" - ), - Predicates.regex( - QueryConstants.KEY_ATTRIBUTE_NAME.value(), - childKeysRegex(directory) - ) - ) - .stream() - .map(list -> (String)list.get(0)) - ; - } - - @Override - protected void internalReadBlobData( - final BlobStorePath file , - final BlobMetadata metadata , - final ByteBuffer targetBuffer, - final long offset , - final long length - ) - { - final byte[] data = data( - this.map(file).get(metadata.key()) - ); - targetBuffer.put( - data, - checkArrayRange(offset), - checkArrayRange(length) - ); - } - - @Override - protected boolean internalDeleteBlobs( - final BlobStorePath file , - final List blobs - ) - { - final IMap> map = this.map(file); - blobs.forEach( - metadata -> map.delete(metadata.key()) - ); - return true; - } - - @Override - protected long internalWriteData( - final BlobStorePath file , - final Iterable sourceBuffers - ) - { - long nextBlobNumber = this.nextBlobNumber(file); - final long totalSize = this.totalSize(sourceBuffers); - final IMap> map = this.map(file); - final ByteBufferInputStream buffersInputStream = ByteBufferInputStream.New(sourceBuffers); - long available = totalSize; - while(available > 0) - { - final long currentBatchSize = Math.min( - available, - MAX_UPLOAD_BLOB_BYTES - ); - - try(LimitedInputStream limitedInputStream = LimitedInputStream.New( - new BufferedInputStream(buffersInputStream), - currentBatchSize - )) - { - final int batchSize = checkArrayRange(currentBatchSize); - final byte[] batch = new byte[batchSize]; - int read = 0; - do - { - read += limitedInputStream.read(batch, read, batch.length - read); - } - while(read < batchSize); - - final String identifier = toBlobKey(file, nextBlobNumber++); - final List blob = createBlobList( - identifier, - currentBatchSize, - batch - ); - map.set(identifier, blob); - } - catch(final IOException e) - { - throw new IORuntimeException(e); - } - - available -= currentBatchSize; - } - - return totalSize; - } - - @Override - protected void internalMoveFile( - final BlobStorePath sourceFile, - final BlobStorePath targetFile - ) - { - final IMap> sourceMap = this.map(sourceFile); - final IMap> targetMap = this.map(targetFile); - final AtomicInteger nr = new AtomicInteger(); - this.blobs(sourceFile).forEach(metadata -> { - this.copyBlob(metadata, targetFile, sourceMap, targetMap, nr); - sourceMap.delete(metadata.key()); - }); - } - - private void copyBlob( - final BlobMetadata metadata , - final BlobStorePath targetFile, - final IMap> sourceMap , - final IMap> targetMap , - final AtomicInteger nr - ) - { - final List blob = sourceMap.get(metadata.key()); - final String targetIdentifier = toBlobKey(targetFile, nr.getAndIncrement()); - final List newBlob = createBlobList( - targetIdentifier, - metadata.size(), - data(blob) - ); - targetMap.put(targetIdentifier, newBlob); - } - - } - -} diff --git a/afs/hazelcast/src/main/java/org/eclipse/store/afs/hazelcast/types/HazelcastFileSystemCreator.java b/afs/hazelcast/src/main/java/org/eclipse/store/afs/hazelcast/types/HazelcastFileSystemCreator.java deleted file mode 100644 index 5d1516c8..00000000 --- a/afs/hazelcast/src/main/java/org/eclipse/store/afs/hazelcast/types/HazelcastFileSystemCreator.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.eclipse.store.afs.hazelcast.types; - -/*- - * #%L - * EclipseStore Abstract File System Hazelcast - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ - -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; - -import org.eclipse.serializer.afs.types.AFileSystem; -import org.eclipse.serializer.chars.XChars; -import org.eclipse.serializer.configuration.exceptions.ConfigurationException; -import org.eclipse.serializer.configuration.types.Configuration; -import org.eclipse.serializer.configuration.types.ConfigurationBasedCreator; -import org.eclipse.store.afs.blobstore.types.BlobStoreFileSystem; - -import com.hazelcast.config.ClasspathXmlConfig; -import com.hazelcast.config.ClasspathYamlConfig; -import com.hazelcast.config.Config; -import com.hazelcast.config.FileSystemXmlConfig; -import com.hazelcast.config.FileSystemYamlConfig; -import com.hazelcast.config.UrlXmlConfig; -import com.hazelcast.config.UrlYamlConfig; -import com.hazelcast.core.Hazelcast; -import com.hazelcast.core.HazelcastInstance; - - -public class HazelcastFileSystemCreator extends ConfigurationBasedCreator.Abstract -{ - private final static String CLASSPATH_PREFIX = "classpath:"; - - public HazelcastFileSystemCreator() - { - super(AFileSystem.class); - } - - @Override - public AFileSystem create( - final Configuration configuration - ) - { - final String hazelcastConfigPath = configuration.get("hazelcast.configuration"); - if(XChars.isEmpty(hazelcastConfigPath)) - { - return null; - } - - final HazelcastInstance hazelcast = Hazelcast.newHazelcastInstance( - this.loadHazelcastConfig(configuration, hazelcastConfigPath) - ); - final boolean cache = configuration.optBoolean("cache").orElse(true); - final HazelcastConnector connector = cache - ? HazelcastConnector.Caching(hazelcast) - : HazelcastConnector.New(hazelcast) - ; - return BlobStoreFileSystem.New(connector); - } - - private Config loadHazelcastConfig( - final Configuration configuration, - final String path - ) - { - if(path.equalsIgnoreCase("default")) - { - return Config.load(); - } - - final boolean xml = path.toLowerCase().endsWith(".xml"); - if(path.toLowerCase().startsWith(CLASSPATH_PREFIX)) - { - return xml - ? new ClasspathXmlConfig(path.substring(CLASSPATH_PREFIX.length())) - : new ClasspathYamlConfig(path.substring(CLASSPATH_PREFIX.length())) - ; - } - - try - { - try - { - final URL url = new URL(path); - return xml - ? new UrlXmlConfig(url) - : new UrlYamlConfig(url) - ; - } - catch(final MalformedURLException e) - { - return xml - ? new FileSystemXmlConfig(new File(path)) - : new FileSystemYamlConfig(new File(path)) - ; - } - } - catch(final IOException ioe) - { - throw new ConfigurationException(configuration, ioe); - } - } - -} diff --git a/afs/hazelcast/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator b/afs/hazelcast/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator deleted file mode 100644 index 3e7544d5..00000000 --- a/afs/hazelcast/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.store.afs.hazelcast.types.HazelcastFileSystemCreator diff --git a/afs/oracle/LICENSE b/afs/oracle/LICENSE deleted file mode 100644 index d3087e4c..00000000 --- a/afs/oracle/LICENSE +++ /dev/null @@ -1,277 +0,0 @@ -Eclipse Public License - v 2.0 - - THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE - PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION - OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. - -1. DEFINITIONS - -"Contribution" means: - - a) in the case of the initial Contributor, the initial content - Distributed under this Agreement, and - - b) in the case of each subsequent Contributor: - i) changes to the Program, and - ii) additions to the Program; - where such changes and/or additions to the Program originate from - and are Distributed by that particular Contributor. A Contribution - "originates" from a Contributor if it was added to the Program by - such Contributor itself or anyone acting on such Contributor's behalf. - Contributions do not include changes or additions to the Program that - are not Modified Works. - -"Contributor" means any person or entity that Distributes the Program. - -"Licensed Patents" mean patent claims licensable by a Contributor which -are necessarily infringed by the use or sale of its Contribution alone -or when combined with the Program. - -"Program" means the Contributions Distributed in accordance with this -Agreement. - -"Recipient" means anyone who receives the Program under this Agreement -or any Secondary License (as applicable), including Contributors. - -"Derivative Works" shall mean any work, whether in Source Code or other -form, that is based on (or derived from) the Program and for which the -editorial revisions, annotations, elaborations, or other modifications -represent, as a whole, an original work of authorship. - -"Modified Works" shall mean any work in Source Code or other form that -results from an addition to, deletion from, or modification of the -contents of the Program, including, for purposes of clarity any new file -in Source Code form that contains any contents of the Program. Modified -Works shall not include works that contain only declarations, -interfaces, types, classes, structures, or files of the Program solely -in each case in order to link to, bind by name, or subclass the Program -or Modified Works thereof. - -"Distribute" means the acts of a) distributing or b) making available -in any manner that enables the transfer of a copy. - -"Source Code" means the form of a Program preferred for making -modifications, including but not limited to software source code, -documentation source, and configuration files. - -"Secondary License" means either the GNU General Public License, -Version 2.0, or any later versions of that license, including any -exceptions or additional permissions as identified by the initial -Contributor. - -2. GRANT OF RIGHTS - - a) Subject to the terms of this Agreement, each Contributor hereby - grants Recipient a non-exclusive, worldwide, royalty-free copyright - license to reproduce, prepare Derivative Works of, publicly display, - publicly perform, Distribute and sublicense the Contribution of such - Contributor, if any, and such Derivative Works. - - b) Subject to the terms of this Agreement, each Contributor hereby - grants Recipient a non-exclusive, worldwide, royalty-free patent - license under Licensed Patents to make, use, sell, offer to sell, - import and otherwise transfer the Contribution of such Contributor, - if any, in Source Code or other form. This patent license shall - apply to the combination of the Contribution and the Program if, at - the time the Contribution is added by the Contributor, such addition - of the Contribution causes such combination to be covered by the - Licensed Patents. The patent license shall not apply to any other - combinations which include the Contribution. No hardware per se is - licensed hereunder. - - c) Recipient understands that although each Contributor grants the - licenses to its Contributions set forth herein, no assurances are - provided by any Contributor that the Program does not infringe the - patent or other intellectual property rights of any other entity. - Each Contributor disclaims any liability to Recipient for claims - brought by any other entity based on infringement of intellectual - property rights or otherwise. As a condition to exercising the - rights and licenses granted hereunder, each Recipient hereby - assumes sole responsibility to secure any other intellectual - property rights needed, if any. For example, if a third party - patent license is required to allow Recipient to Distribute the - Program, it is Recipient's responsibility to acquire that license - before distributing the Program. - - d) Each Contributor represents that to its knowledge it has - sufficient copyright rights in its Contribution, if any, to grant - the copyright license set forth in this Agreement. - - e) Notwithstanding the terms of any Secondary License, no - Contributor makes additional grants to any Recipient (other than - those set forth in this Agreement) as a result of such Recipient's - receipt of the Program under the terms of a Secondary License - (if permitted under the terms of Section 3). - -3. REQUIREMENTS - -3.1 If a Contributor Distributes the Program in any form, then: - - a) the Program must also be made available as Source Code, in - accordance with section 3.2, and the Contributor must accompany - the Program with a statement that the Source Code for the Program - is available under this Agreement, and informs Recipients how to - obtain it in a reasonable manner on or through a medium customarily - used for software exchange; and - - b) the Contributor may Distribute the Program under a license - different than this Agreement, provided that such license: - i) effectively disclaims on behalf of all other Contributors all - warranties and conditions, express and implied, including - warranties or conditions of title and non-infringement, and - implied warranties or conditions of merchantability and fitness - for a particular purpose; - - ii) effectively excludes on behalf of all other Contributors all - liability for damages, including direct, indirect, special, - incidental and consequential damages, such as lost profits; - - iii) does not attempt to limit or alter the recipients' rights - in the Source Code under section 3.2; and - - iv) requires any subsequent distribution of the Program by any - party to be under a license that satisfies the requirements - of this section 3. - -3.2 When the Program is Distributed as Source Code: - - a) it must be made available under this Agreement, or if the - Program (i) is combined with other material in a separate file or - files made available under a Secondary License, and (ii) the initial - Contributor attached to the Source Code the notice described in - Exhibit A of this Agreement, then the Program may be made available - under the terms of such Secondary Licenses, and - - b) a copy of this Agreement must be included with each copy of - the Program. - -3.3 Contributors may not remove or alter any copyright, patent, -trademark, attribution notices, disclaimers of warranty, or limitations -of liability ("notices") contained within the Program from any copy of -the Program which they Distribute, provided that Contributors may add -their own appropriate notices. - -4. COMMERCIAL DISTRIBUTION - -Commercial distributors of software may accept certain responsibilities -with respect to end users, business partners and the like. While this -license is intended to facilitate the commercial use of the Program, -the Contributor who includes the Program in a commercial product -offering should do so in a manner which does not create potential -liability for other Contributors. Therefore, if a Contributor includes -the Program in a commercial product offering, such Contributor -("Commercial Contributor") hereby agrees to defend and indemnify every -other Contributor ("Indemnified Contributor") against any losses, -damages and costs (collectively "Losses") arising from claims, lawsuits -and other legal actions brought by a third party against the Indemnified -Contributor to the extent caused by the acts or omissions of such -Commercial Contributor in connection with its distribution of the Program -in a commercial product offering. The obligations in this section do not -apply to any claims or Losses relating to any actual or alleged -intellectual property infringement. In order to qualify, an Indemnified -Contributor must: a) promptly notify the Commercial Contributor in -writing of such claim, and b) allow the Commercial Contributor to control, -and cooperate with the Commercial Contributor in, the defense and any -related settlement negotiations. The Indemnified Contributor may -participate in any such claim at its own expense. - -For example, a Contributor might include the Program in a commercial -product offering, Product X. That Contributor is then a Commercial -Contributor. If that Commercial Contributor then makes performance -claims, or offers warranties related to Product X, those performance -claims and warranties are such Commercial Contributor's responsibility -alone. Under this section, the Commercial Contributor would have to -defend claims against the other Contributors related to those performance -claims and warranties, and if a court requires any other Contributor to -pay any damages as a result, the Commercial Contributor must pay -those damages. - -5. NO WARRANTY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT -PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" -BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR -IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF -TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR -PURPOSE. Each Recipient is solely responsible for determining the -appropriateness of using and distributing the Program and assumes all -risks associated with its exercise of rights under this Agreement, -including but not limited to the risks and costs of program errors, -compliance with applicable laws, damage to or loss of data, programs -or equipment, and unavailability or interruption of operations. - -6. DISCLAIMER OF LIABILITY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT -PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS -SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST -PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE -EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - -7. GENERAL - -If any provision of this Agreement is invalid or unenforceable under -applicable law, it shall not affect the validity or enforceability of -the remainder of the terms of this Agreement, and without further -action by the parties hereto, such provision shall be reformed to the -minimum extent necessary to make such provision valid and enforceable. - -If Recipient institutes patent litigation against any entity -(including a cross-claim or counterclaim in a lawsuit) alleging that the -Program itself (excluding combinations of the Program with other software -or hardware) infringes such Recipient's patent(s), then such Recipient's -rights granted under Section 2(b) shall terminate as of the date such -litigation is filed. - -All Recipient's rights under this Agreement shall terminate if it -fails to comply with any of the material terms or conditions of this -Agreement and does not cure such failure in a reasonable period of -time after becoming aware of such noncompliance. If all Recipient's -rights under this Agreement terminate, Recipient agrees to cease use -and distribution of the Program as soon as reasonably practicable. -However, Recipient's obligations under this Agreement and any licenses -granted by Recipient relating to the Program shall continue and survive. - -Everyone is permitted to copy and distribute copies of this Agreement, -but in order to avoid inconsistency the Agreement is copyrighted and -may only be modified in the following manner. The Agreement Steward -reserves the right to publish new versions (including revisions) of -this Agreement from time to time. No one other than the Agreement -Steward has the right to modify this Agreement. The Eclipse Foundation -is the initial Agreement Steward. The Eclipse Foundation may assign the -responsibility to serve as the Agreement Steward to a suitable separate -entity. Each new version of the Agreement will be given a distinguishing -version number. The Program (including Contributions) may always be -Distributed subject to the version of the Agreement under which it was -received. In addition, after a new version of the Agreement is published, -Contributor may elect to Distribute the Program (including its -Contributions) under the new version. - -Except as expressly stated in Sections 2(a) and 2(b) above, Recipient -receives no rights or licenses to the intellectual property of any -Contributor under this Agreement, whether expressly, by implication, -estoppel or otherwise. All rights in the Program not expressly granted -under this Agreement are reserved. Nothing in this Agreement is intended -to be enforceable by any entity that is not a Contributor or Recipient. -No third-party beneficiary rights are created under this Agreement. - -Exhibit A - Form of Secondary Licenses Notice - -"This Source Code may also be made available under the following -Secondary Licenses when the conditions for such availability set forth -in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), -version(s), and exceptions or additional permissions here}." - - Simply including a copy of this Agreement, including this Exhibit A - is not sufficient to license the Source Code under Secondary Licenses. - - If it is not possible or desirable to put the notice in a particular - file, then You may include the notice in a location (such as a LICENSE - file in a relevant directory) where a recipient would be likely to - look for such a notice. - - You may add additional accurate notices of copyright ownership. diff --git a/afs/oracle/coherence/LICENSE b/afs/oracle/coherence/LICENSE deleted file mode 100644 index d3087e4c..00000000 --- a/afs/oracle/coherence/LICENSE +++ /dev/null @@ -1,277 +0,0 @@ -Eclipse Public License - v 2.0 - - THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE - PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION - OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. - -1. DEFINITIONS - -"Contribution" means: - - a) in the case of the initial Contributor, the initial content - Distributed under this Agreement, and - - b) in the case of each subsequent Contributor: - i) changes to the Program, and - ii) additions to the Program; - where such changes and/or additions to the Program originate from - and are Distributed by that particular Contributor. A Contribution - "originates" from a Contributor if it was added to the Program by - such Contributor itself or anyone acting on such Contributor's behalf. - Contributions do not include changes or additions to the Program that - are not Modified Works. - -"Contributor" means any person or entity that Distributes the Program. - -"Licensed Patents" mean patent claims licensable by a Contributor which -are necessarily infringed by the use or sale of its Contribution alone -or when combined with the Program. - -"Program" means the Contributions Distributed in accordance with this -Agreement. - -"Recipient" means anyone who receives the Program under this Agreement -or any Secondary License (as applicable), including Contributors. - -"Derivative Works" shall mean any work, whether in Source Code or other -form, that is based on (or derived from) the Program and for which the -editorial revisions, annotations, elaborations, or other modifications -represent, as a whole, an original work of authorship. - -"Modified Works" shall mean any work in Source Code or other form that -results from an addition to, deletion from, or modification of the -contents of the Program, including, for purposes of clarity any new file -in Source Code form that contains any contents of the Program. Modified -Works shall not include works that contain only declarations, -interfaces, types, classes, structures, or files of the Program solely -in each case in order to link to, bind by name, or subclass the Program -or Modified Works thereof. - -"Distribute" means the acts of a) distributing or b) making available -in any manner that enables the transfer of a copy. - -"Source Code" means the form of a Program preferred for making -modifications, including but not limited to software source code, -documentation source, and configuration files. - -"Secondary License" means either the GNU General Public License, -Version 2.0, or any later versions of that license, including any -exceptions or additional permissions as identified by the initial -Contributor. - -2. GRANT OF RIGHTS - - a) Subject to the terms of this Agreement, each Contributor hereby - grants Recipient a non-exclusive, worldwide, royalty-free copyright - license to reproduce, prepare Derivative Works of, publicly display, - publicly perform, Distribute and sublicense the Contribution of such - Contributor, if any, and such Derivative Works. - - b) Subject to the terms of this Agreement, each Contributor hereby - grants Recipient a non-exclusive, worldwide, royalty-free patent - license under Licensed Patents to make, use, sell, offer to sell, - import and otherwise transfer the Contribution of such Contributor, - if any, in Source Code or other form. This patent license shall - apply to the combination of the Contribution and the Program if, at - the time the Contribution is added by the Contributor, such addition - of the Contribution causes such combination to be covered by the - Licensed Patents. The patent license shall not apply to any other - combinations which include the Contribution. No hardware per se is - licensed hereunder. - - c) Recipient understands that although each Contributor grants the - licenses to its Contributions set forth herein, no assurances are - provided by any Contributor that the Program does not infringe the - patent or other intellectual property rights of any other entity. - Each Contributor disclaims any liability to Recipient for claims - brought by any other entity based on infringement of intellectual - property rights or otherwise. As a condition to exercising the - rights and licenses granted hereunder, each Recipient hereby - assumes sole responsibility to secure any other intellectual - property rights needed, if any. For example, if a third party - patent license is required to allow Recipient to Distribute the - Program, it is Recipient's responsibility to acquire that license - before distributing the Program. - - d) Each Contributor represents that to its knowledge it has - sufficient copyright rights in its Contribution, if any, to grant - the copyright license set forth in this Agreement. - - e) Notwithstanding the terms of any Secondary License, no - Contributor makes additional grants to any Recipient (other than - those set forth in this Agreement) as a result of such Recipient's - receipt of the Program under the terms of a Secondary License - (if permitted under the terms of Section 3). - -3. REQUIREMENTS - -3.1 If a Contributor Distributes the Program in any form, then: - - a) the Program must also be made available as Source Code, in - accordance with section 3.2, and the Contributor must accompany - the Program with a statement that the Source Code for the Program - is available under this Agreement, and informs Recipients how to - obtain it in a reasonable manner on or through a medium customarily - used for software exchange; and - - b) the Contributor may Distribute the Program under a license - different than this Agreement, provided that such license: - i) effectively disclaims on behalf of all other Contributors all - warranties and conditions, express and implied, including - warranties or conditions of title and non-infringement, and - implied warranties or conditions of merchantability and fitness - for a particular purpose; - - ii) effectively excludes on behalf of all other Contributors all - liability for damages, including direct, indirect, special, - incidental and consequential damages, such as lost profits; - - iii) does not attempt to limit or alter the recipients' rights - in the Source Code under section 3.2; and - - iv) requires any subsequent distribution of the Program by any - party to be under a license that satisfies the requirements - of this section 3. - -3.2 When the Program is Distributed as Source Code: - - a) it must be made available under this Agreement, or if the - Program (i) is combined with other material in a separate file or - files made available under a Secondary License, and (ii) the initial - Contributor attached to the Source Code the notice described in - Exhibit A of this Agreement, then the Program may be made available - under the terms of such Secondary Licenses, and - - b) a copy of this Agreement must be included with each copy of - the Program. - -3.3 Contributors may not remove or alter any copyright, patent, -trademark, attribution notices, disclaimers of warranty, or limitations -of liability ("notices") contained within the Program from any copy of -the Program which they Distribute, provided that Contributors may add -their own appropriate notices. - -4. COMMERCIAL DISTRIBUTION - -Commercial distributors of software may accept certain responsibilities -with respect to end users, business partners and the like. While this -license is intended to facilitate the commercial use of the Program, -the Contributor who includes the Program in a commercial product -offering should do so in a manner which does not create potential -liability for other Contributors. Therefore, if a Contributor includes -the Program in a commercial product offering, such Contributor -("Commercial Contributor") hereby agrees to defend and indemnify every -other Contributor ("Indemnified Contributor") against any losses, -damages and costs (collectively "Losses") arising from claims, lawsuits -and other legal actions brought by a third party against the Indemnified -Contributor to the extent caused by the acts or omissions of such -Commercial Contributor in connection with its distribution of the Program -in a commercial product offering. The obligations in this section do not -apply to any claims or Losses relating to any actual or alleged -intellectual property infringement. In order to qualify, an Indemnified -Contributor must: a) promptly notify the Commercial Contributor in -writing of such claim, and b) allow the Commercial Contributor to control, -and cooperate with the Commercial Contributor in, the defense and any -related settlement negotiations. The Indemnified Contributor may -participate in any such claim at its own expense. - -For example, a Contributor might include the Program in a commercial -product offering, Product X. That Contributor is then a Commercial -Contributor. If that Commercial Contributor then makes performance -claims, or offers warranties related to Product X, those performance -claims and warranties are such Commercial Contributor's responsibility -alone. Under this section, the Commercial Contributor would have to -defend claims against the other Contributors related to those performance -claims and warranties, and if a court requires any other Contributor to -pay any damages as a result, the Commercial Contributor must pay -those damages. - -5. NO WARRANTY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT -PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" -BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR -IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF -TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR -PURPOSE. Each Recipient is solely responsible for determining the -appropriateness of using and distributing the Program and assumes all -risks associated with its exercise of rights under this Agreement, -including but not limited to the risks and costs of program errors, -compliance with applicable laws, damage to or loss of data, programs -or equipment, and unavailability or interruption of operations. - -6. DISCLAIMER OF LIABILITY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT -PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS -SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST -PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE -EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - -7. GENERAL - -If any provision of this Agreement is invalid or unenforceable under -applicable law, it shall not affect the validity or enforceability of -the remainder of the terms of this Agreement, and without further -action by the parties hereto, such provision shall be reformed to the -minimum extent necessary to make such provision valid and enforceable. - -If Recipient institutes patent litigation against any entity -(including a cross-claim or counterclaim in a lawsuit) alleging that the -Program itself (excluding combinations of the Program with other software -or hardware) infringes such Recipient's patent(s), then such Recipient's -rights granted under Section 2(b) shall terminate as of the date such -litigation is filed. - -All Recipient's rights under this Agreement shall terminate if it -fails to comply with any of the material terms or conditions of this -Agreement and does not cure such failure in a reasonable period of -time after becoming aware of such noncompliance. If all Recipient's -rights under this Agreement terminate, Recipient agrees to cease use -and distribution of the Program as soon as reasonably practicable. -However, Recipient's obligations under this Agreement and any licenses -granted by Recipient relating to the Program shall continue and survive. - -Everyone is permitted to copy and distribute copies of this Agreement, -but in order to avoid inconsistency the Agreement is copyrighted and -may only be modified in the following manner. The Agreement Steward -reserves the right to publish new versions (including revisions) of -this Agreement from time to time. No one other than the Agreement -Steward has the right to modify this Agreement. The Eclipse Foundation -is the initial Agreement Steward. The Eclipse Foundation may assign the -responsibility to serve as the Agreement Steward to a suitable separate -entity. Each new version of the Agreement will be given a distinguishing -version number. The Program (including Contributions) may always be -Distributed subject to the version of the Agreement under which it was -received. In addition, after a new version of the Agreement is published, -Contributor may elect to Distribute the Program (including its -Contributions) under the new version. - -Except as expressly stated in Sections 2(a) and 2(b) above, Recipient -receives no rights or licenses to the intellectual property of any -Contributor under this Agreement, whether expressly, by implication, -estoppel or otherwise. All rights in the Program not expressly granted -under this Agreement are reserved. Nothing in this Agreement is intended -to be enforceable by any entity that is not a Contributor or Recipient. -No third-party beneficiary rights are created under this Agreement. - -Exhibit A - Form of Secondary Licenses Notice - -"This Source Code may also be made available under the following -Secondary Licenses when the conditions for such availability set forth -in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), -version(s), and exceptions or additional permissions here}." - - Simply including a copy of this Agreement, including this Exhibit A - is not sufficient to license the Source Code under Secondary Licenses. - - If it is not possible or desirable to put the notice in a particular - file, then You may include the notice in a location (such as a LICENSE - file in a relevant directory) where a recipient would be likely to - look for such a notice. - - You may add additional accurate notices of copyright ownership. diff --git a/afs/oracle/coherence/pom.xml b/afs/oracle/coherence/pom.xml deleted file mode 100644 index 788a5ebb..00000000 --- a/afs/oracle/coherence/pom.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - 4.0.0 - - - org.eclipse.store - afs-oracle-parent - 1.0.0-SNAPSHOT - ../pom.xml - - - afs-oracle-coherence - - EclipseStore Abstract File System Oracle Coherence - EclipseStore File System Abstraction for Oracle Coherence - https://projects.eclipse.org/projects/technology.store - - - - - com.oracle.coherence.ce - coherence-bom - 21.12.3 - pom - import - - - - - - - org.eclipse.store - afs-blobstore - 1.0.0-SNAPSHOT - - - org.eclipse.serializer - configuration - ${eclipse.serializer.version} - - - com.oracle.coherence.ce - coherence - - - - - diff --git a/afs/oracle/coherence/src/main/java/module-info.java b/afs/oracle/coherence/src/main/java/module-info.java deleted file mode 100644 index a4ceed48..00000000 --- a/afs/oracle/coherence/src/main/java/module-info.java +++ /dev/null @@ -1,25 +0,0 @@ -/*- - * #%L - * EclipseStore Abstract File System Oracle Coherence - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.afs.ocacle.coherence -{ - exports org.eclipse.store.afs.oracle.coherence.types; - - provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator - with org.eclipse.store.afs.oracle.coherence.types.OracleCoherenceFileSystemCreator - ; - - requires transitive org.eclipse.serializer.configuration; - requires transitive org.eclipse.store.afs.blobstore; - requires transitive com.oracle.coherence.ce; -} diff --git a/afs/oracle/coherence/src/main/java/org/eclipse/store/afs/oracle/coherence/types/BlobMetadata.java b/afs/oracle/coherence/src/main/java/org/eclipse/store/afs/oracle/coherence/types/BlobMetadata.java deleted file mode 100644 index b01c8389..00000000 --- a/afs/oracle/coherence/src/main/java/org/eclipse/store/afs/oracle/coherence/types/BlobMetadata.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.eclipse.store.afs.oracle.coherence.types; - -/*- - * #%L - * EclipseStore Abstract File System Oracle Coherence - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ - -import static org.eclipse.serializer.chars.XChars.notEmpty; -import static org.eclipse.serializer.math.XMath.notNegative; - -public interface BlobMetadata -{ - public String key(); - - public long size(); - - - public static BlobMetadata New( - final String key , - final long size - ) - { - return new BlobMetadata.Default( - notEmpty (key ), - notNegative(size) - ); - } - - - public static class Default implements BlobMetadata - { - private final String key ; - private final long size; - - Default( - final String key , - final long size - ) - { - super(); - this.key = key ; - this.size = size; - } - - @Override - public String key() - { - return this.key; - } - - @Override - public long size() - { - return this.size; - } - - } - -} diff --git a/afs/oracle/coherence/src/main/java/org/eclipse/store/afs/oracle/coherence/types/OracleCoherenceConnector.java b/afs/oracle/coherence/src/main/java/org/eclipse/store/afs/oracle/coherence/types/OracleCoherenceConnector.java deleted file mode 100644 index 611ef1de..00000000 --- a/afs/oracle/coherence/src/main/java/org/eclipse/store/afs/oracle/coherence/types/OracleCoherenceConnector.java +++ /dev/null @@ -1,387 +0,0 @@ -package org.eclipse.store.afs.oracle.coherence.types; - -/*- - * #%L - * EclipseStore Abstract File System Oracle Coherence - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ - -import static java.util.stream.Collectors.toSet; -import static org.eclipse.serializer.util.X.checkArrayRange; -import static org.eclipse.serializer.util.X.notNull; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Stream; - -import com.tangosol.coherence.memcached.processor.DeleteProcessor; -import com.tangosol.net.CacheFactory; -import com.tangosol.net.NamedCache; -import com.tangosol.net.cache.CacheMap; -import com.tangosol.util.Filter; -import com.tangosol.util.ValueExtractor; -import com.tangosol.util.aggregator.LongSum; -import com.tangosol.util.extractor.KeyExtractor; -import com.tangosol.util.extractor.ReflectionExtractor; -import com.tangosol.util.filter.InFilter; -import com.tangosol.util.filter.RegexFilter; -import com.tangosol.util.processor.ExtractorProcessor; - -import org.eclipse.store.afs.blobstore.types.BlobStoreConnector; -import org.eclipse.store.afs.blobstore.types.BlobStorePath; -import org.eclipse.serializer.exceptions.IORuntimeException; -import org.eclipse.serializer.io.ByteBufferInputStream; -import org.eclipse.serializer.io.LimitedInputStream; - - -/** - * Connector for the Oracle Coherence data grid. - *

- * First create a connection to a named cache. - *

- * NamedCache cache = ...
- * BlobStoreFileSystem fileSystem = BlobStoreFileSystem.New(
- * 	OracleCoherenceConnector.New(cache)
- * );
- * 
- * - * - * - */ -public interface OracleCoherenceConnector extends BlobStoreConnector -{ - /** - * Pseudo-constructor method which creates a new {@link OracleCoherenceConnector}. - * - * @param cacheName name of the coherence cache - * @return a new {@link OracleCoherenceConnector} - */ - public static OracleCoherenceConnector New(final String cacheName) - { - return New(CacheFactory.getCache(cacheName)); - } - - /** - * Pseudo-constructor method which creates a new {@link OracleCoherenceConnector} with cache. - * - * @param cacheName name of the coherence cache - * @return a new {@link OracleCoherenceConnector} - */ - public static OracleCoherenceConnector Caching(final String cacheName) - { - return Caching(CacheFactory.getCache(cacheName)); - } - - /** - * Pseudo-constructor method which creates a new {@link OracleCoherenceConnector}. - * - * @param cache connection to the coherence caching service - * @return a new {@link OracleCoherenceConnector} - */ - public static OracleCoherenceConnector New( - final NamedCache> cache - ) - { - return new Default( - notNull(cache), - false - ); - } - - /** - * Pseudo-constructor method which creates a new {@link OracleCoherenceConnector} with cache. - * - * @param cache connection to the coherence caching service - * @return a new {@link OracleCoherenceConnector} - */ - public static OracleCoherenceConnector Caching( - final NamedCache> cache - ) - { - return new Default( - notNull(cache), - true - ); - } - - public static class Default - extends BlobStoreConnector.Abstract - implements OracleCoherenceConnector - { - /* - * Blobs are stored as Maps: - * Cache { - * "key" : String - * "value" : Map { - * "size" : Long - * "data" : byte[] - * } - * } - */ - - private final static String SIZE = "size"; - private final static String DATA = "data"; - - private final static long MAX_BLOB_SIZE = 16_777_216; - - private static Map createBlobValue( - final Long size, - final byte[] data - ) - { - final Map blob = new HashMap<>(2); - blob.put(SIZE, size); - blob.put(DATA, data); - return blob; - } - - private static ValueExtractor, T> valueExtractor( - final String key - ) - { - return new ReflectionExtractor<>( - "get", - new Object[] {key} - ); - } - - private static Filter fileFilter( - final BlobStorePath file - ) - { - return new RegexFilter<>( - new KeyExtractor<>(), - blobKeyRegex(toBlobKeyPrefixWithContainer(file)) - ); - } - - private static Filter childKeysFilter( - final BlobStorePath directory - ) - { - return new RegexFilter<>( - new KeyExtractor<>(), - childKeysRegexWithContainer(directory) - ); - } - - private static Filter blobsFilter( - final List blobs - ) - { - return new InFilter<>( - new KeyExtractor<>(), - blobs.stream() - .map(BlobMetadata::key) - .collect(toSet()) - ); - } - - private final NamedCache> cache; - - Default( - final NamedCache> cache , - final boolean withCache - ) - { - super( - BlobMetadata::key, - BlobMetadata::size, - withCache - ); - this.cache = cache; - } - - @Override - protected Stream blobs( - final BlobStorePath file - ) - { - final Map result = this.cache.invokeAll( - fileFilter(file), - new ExtractorProcessor<>(valueExtractor(SIZE)) - ); - return result.entrySet().stream() - .map(entry -> BlobMetadata.New(entry.getKey(), entry.getValue())) - .sorted(this.blobComparator()) - ; - } - - @Override - protected Stream childKeys( - final BlobStorePath directory - ) - { - final Map result = this.cache.invokeAll( - childKeysFilter(directory), - new ExtractorProcessor<>(new KeyExtractor<>()) - ); - return result.keySet().stream(); - } - - @Override - protected long internalFileSize(final BlobStorePath file) - { - final Long size = this.cache.aggregate( - fileFilter(file), - new LongSum<>(valueExtractor(SIZE)) - ); - return size != null - ? size - : 0L - ; - } - - private byte[] data( - final BlobMetadata metadata - ) - { - return (byte[])this.cache.invoke( - metadata.key(), - new ExtractorProcessor<>(valueExtractor(DATA)) - ); - } - - @Override - protected void internalReadBlobData( - final BlobStorePath file , - final BlobMetadata metadata , - final ByteBuffer targetBuffer, - final long offset , - final long length - ) - { - targetBuffer.put( - this.data(metadata), - checkArrayRange(offset), - checkArrayRange(length) - ); - } - - @SuppressWarnings("unchecked") // DeleteProcessor is not typed - @Override - protected boolean internalDeleteFile( - final BlobStorePath file - ) - { - return !this.cache.invokeAll( - fileFilter(file), - new DeleteProcessor() - ) - .isEmpty(); - } - - @SuppressWarnings("unchecked") // DeleteProcessor is not typed - @Override - protected boolean internalDeleteBlobs( - final BlobStorePath file , - final List blobs - ) - { - return !this.cache.invokeAll( - blobsFilter(blobs), - new DeleteProcessor() - ) - .isEmpty(); - } - - @Override - protected long internalWriteData( - final BlobStorePath file , - final Iterable sourceBuffers - ) - { - long nextBlobNumber = this.nextBlobNumber(file); - final long totalSize = this.totalSize(sourceBuffers); - final ByteBufferInputStream buffersInputStream = ByteBufferInputStream.New(sourceBuffers); - long available = totalSize; - while(available > 0) - { - final long currentBatchSize = Math.min( - available, - MAX_BLOB_SIZE - ); - - try(LimitedInputStream limitedInputStream = LimitedInputStream.New( - new BufferedInputStream(buffersInputStream), - currentBatchSize - )) - { - final int batchSize = checkArrayRange(currentBatchSize); - final byte[] batch = new byte[batchSize]; - int read = 0; - do - { - read += limitedInputStream.read(batch, read, batch.length - read); - } - while(read < batchSize); - - final String key = toBlobKeyWithContainer(file, nextBlobNumber++); - final Map blob = createBlobValue( - currentBatchSize, - batch - ); - this.cache.put( - key, - blob, - CacheMap.EXPIRY_NEVER - ); - } - catch(final IOException e) - { - throw new IORuntimeException(e); - } - - available -= currentBatchSize; - } - - return totalSize; - } - - @Override - protected void internalMoveFile( - final BlobStorePath sourceFile, - final BlobStorePath targetFile - ) - { - final AtomicInteger nr = new AtomicInteger(); - this.blobs(sourceFile).forEach(metadata -> { - this.copyBlob(metadata, targetFile, nr); - this.cache.remove(metadata.key()); - }); - } - - private void copyBlob( - final BlobMetadata metadata , - final BlobStorePath targetFile, - final AtomicInteger nr - ) - { - this.cache.put( - toBlobKeyWithContainer( - targetFile, - nr.getAndIncrement() - ), - createBlobValue( - metadata.size(), - this.data(metadata) - ) - ); - } - - } - -} diff --git a/afs/oracle/coherence/src/main/java/org/eclipse/store/afs/oracle/coherence/types/OracleCoherenceFileSystemCreator.java b/afs/oracle/coherence/src/main/java/org/eclipse/store/afs/oracle/coherence/types/OracleCoherenceFileSystemCreator.java deleted file mode 100644 index 1d4e56a6..00000000 --- a/afs/oracle/coherence/src/main/java/org/eclipse/store/afs/oracle/coherence/types/OracleCoherenceFileSystemCreator.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.eclipse.store.afs.oracle.coherence.types; - -/*- - * #%L - * EclipseStore Abstract File System Oracle Coherence - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ - -import java.util.Map; - -import org.eclipse.serializer.afs.types.AFileSystem; -import org.eclipse.serializer.chars.XChars; -import org.eclipse.serializer.configuration.exceptions.ConfigurationException; -import org.eclipse.serializer.configuration.types.Configuration; -import org.eclipse.serializer.configuration.types.ConfigurationBasedCreator; -import org.eclipse.store.afs.blobstore.types.BlobStoreFileSystem; - -import com.tangosol.net.CacheFactory; -import com.tangosol.net.NamedCache; - - -public class OracleCoherenceFileSystemCreator extends ConfigurationBasedCreator.Abstract -{ - public OracleCoherenceFileSystemCreator() - { - super(AFileSystem.class); - } - - @Override - public AFileSystem create( - final Configuration configuration - ) - { - final Configuration coherenceConfiguration = configuration.child("oracle.coherence"); - if(coherenceConfiguration == null) - { - return null; - } - - final String cacheName = coherenceConfiguration.get("cache-name"); - if(XChars.isEmpty(cacheName)) - { - throw new ConfigurationException(coherenceConfiguration, "Coherence cache-name must be defined"); - } - - coherenceConfiguration.opt("cache-config").ifPresent( - value -> System.setProperty("tangosol.coherence.cacheconfig", value) - ); - - final NamedCache> namedCache = CacheFactory.getCache(cacheName); - final boolean useCache = configuration.optBoolean("cache").orElse(true); - final OracleCoherenceConnector connector = useCache - ? OracleCoherenceConnector.Caching(namedCache) - : OracleCoherenceConnector.New(namedCache) - ; - return BlobStoreFileSystem.New(connector); - } - -} diff --git a/afs/oracle/coherence/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator b/afs/oracle/coherence/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator deleted file mode 100644 index 8f697335..00000000 --- a/afs/oracle/coherence/src/main/resources/META-INF/services/org.eclipse.serializer.configuration.types.ConfigurationBasedCreator +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.store.afs.oracle.coherence.types.OracleCoherenceFileSystemCreator \ No newline at end of file diff --git a/afs/oracle/pom.xml b/afs/oracle/pom.xml deleted file mode 100644 index fd3f55c9..00000000 --- a/afs/oracle/pom.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - 4.0.0 - - - org.eclipse.store - afs-parent - 1.0.0-SNAPSHOT - ../pom.xml - - - afs-oracle-parent - pom - - EclipseStore Abstract File System Oracle Parent - EclipseStore File System Abstraction for Oracle - https://projects.eclipse.org/projects/technology.store - - - coherence - - - diff --git a/afs/pom.xml b/afs/pom.xml index 3a782048..5a6a51f0 100644 --- a/afs/pom.xml +++ b/afs/pom.xml @@ -25,10 +25,8 @@ azure blobstore googlecloud - hazelcast kafka nio - oracle oraclecloud redis sql diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 26a9d17d..91220ebd 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -26,10 +26,8 @@ ***** xref:storage:storage-targets/blob-stores/aws-dynamodb.adoc[DynamoDB] ***** xref:storage:storage-targets/blob-stores/aws-s3.adoc[S3] **** xref:storage:storage-targets/blob-stores/azure-storage.adoc[Azure Storage] -**** xref:storage:storage-targets/blob-stores/hazelcast.adoc[Hazelcast] **** xref:storage:storage-targets/blob-stores/kafka.adoc[Kafka] **** xref:storage:storage-targets/blob-stores/oracle-cloud-object-storage.adoc[Oracle Cloud Object Storage] -**** xref:storage:storage-targets/blob-stores/oracle-coherence.adoc[Oracle Coherence] **** xref:storage:storage-targets/blob-stores/redis.adoc[Redis] ** xref:storage:storing-data/index.adoc[Storing Data] *** xref:storage:storing-data/transactions.adoc[Convenience Methods and Explicit Storing (Transactions)] diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/hazelcast.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/hazelcast.adoc deleted file mode 100644 index 5249c355..00000000 --- a/docs/modules/storage/pages/storage-targets/blob-stores/hazelcast.adoc +++ /dev/null @@ -1,50 +0,0 @@ -= Hazelcast - -[source, xml, subs=attributes+] ----- - - org.eclipse.store - afs-hazelcast - {maven-version} - ----- - -[source, java] ----- -HazelcastInstance hazelcast = ...; -BlobStoreFileSystem fileSystem = BlobStoreFileSystem.New( - HazelcastConnector.Caching(cache) -); -EmbeddedStorage.start(fileSystem.ensureDirectoryPath("storage")); ----- - -== Configuration - -When using xref:configuration/index.adoc#external-configuration[external configuration] Hazelcast can be set as follows. - -[source, text, title="eclipsestore.properties"] ----- -storage-filesystem.hazelcast.configuration=path-to-hazelcast-configuration-file ----- - -== Supported properties - -[options="header",cols="1,2a"] -|=== -|Property -|Description -//------------- -|hazelcast.configuration -|Supported values: - -* "default" + -It tries to load Hazelcast configuration from a list of well-known locations, and then applies overrides found in environment variables/system properties. When no location contains Hazelcast configuration then it returns default. -* "classpath:path-to-hazelcast-configuration-file" + -When the "classpath:" prefix is used, the file is loaded from a classpath resource. -* a valid URL + -Creates new Config which is loaded from the given URL and uses the System.properties to replace variables. -* a file path + -Creates a Config based on a Hazelcast file and uses the System.properties to resolve variables. -|=== - -CAUTION: Depending on the amount of data and transactions, charges may apply depending on service usage. Please check with your service provider for details. diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/oracle-coherence.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/oracle-coherence.adoc deleted file mode 100644 index 87645227..00000000 --- a/docs/modules/storage/pages/storage-targets/blob-stores/oracle-coherence.adoc +++ /dev/null @@ -1,42 +0,0 @@ -= Oracle Coherence - -[source, xml, subs=attributes+] ----- - - org.eclipse.store - afs-oracle-coherence - {maven-version} - ----- - -[source, java] ----- -NamedCache cache = CacheFactory.getCache("cache-name"); -BlobStoreFileSystem fileSystem = BlobStoreFileSystem.New( - CoherenceConnector.Caching(cache) -); -EmbeddedStorage.start(fileSystem.ensureDirectoryPath("storage")); ----- - -== Configuration - -When using xref:configuration/index.adoc#external-configuration[external configuration] Coherence can be set as follows. - -[source, text, title="eclipestore.properties"] ----- -storage-filesystem.oracle.coherence.cache-name=my-cache ----- - -[options="header",cols="1,2a"] -|=== -|Property -|Description -//------------- -|cache-name -|The name of the cache which is used to retrieve the named cache from the cache factory. - -|cache-config -|It is used to specify a custom cache configuration deployment descriptor to be used instead of the configured default cache configuration deployment descriptor. -|=== - -CAUTION: Depending on the amount of data and transactions, charges may apply depending on service usage. Please check with your service provider for details. From de8adb2b7b7f1e83a43e5ebd72c813a93724bb74 Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Wed, 15 Nov 2023 15:18:22 +0100 Subject: [PATCH 008/126] Provided dependencies (#61) * Set scope to provided * Add readme * Update docs * Fix format * Update docs --- afs/aws/aws/README.md | 11 +++ afs/aws/aws/pom.xml | 8 +- afs/aws/dynamodb/README.md | 10 +++ afs/aws/dynamodb/pom.xml | 1 + afs/aws/s3/README.md | 10 +++ afs/aws/s3/pom.xml | 1 + afs/azure/storage/README.md | 10 +++ afs/azure/storage/pom.xml | 1 + afs/googlecloud/firestore/README.md | 10 +++ afs/googlecloud/firestore/pom.xml | 1 + afs/kafka/README.md | 10 +++ afs/kafka/pom.xml | 9 ++- afs/oraclecloud/objectstorage/README.md | 10 +++ afs/oraclecloud/objectstorage/pom.xml | 1 + afs/redis/README.md | 10 +++ afs/redis/pom.xml | 1 + docs/modules/ROOT/nav.adoc | 1 + .../blob-stores/aws-dynamodb.adoc | 5 ++ .../storage-targets/blob-stores/aws-s3.adoc | 5 ++ .../blob-stores/azure-storage.adoc | 6 ++ .../blob-stores/google-cloud-firestore.adoc | 77 +++++++++++++++++++ .../storage-targets/blob-stores/kafka.adoc | 5 ++ .../oracle-cloud-object-storage.adoc | 5 ++ .../storage-targets/blob-stores/redis.adoc | 5 ++ 24 files changed, 204 insertions(+), 9 deletions(-) create mode 100644 afs/aws/aws/README.md create mode 100644 afs/aws/dynamodb/README.md create mode 100644 afs/aws/s3/README.md create mode 100644 afs/azure/storage/README.md create mode 100644 afs/googlecloud/firestore/README.md create mode 100644 afs/kafka/README.md create mode 100644 afs/oraclecloud/objectstorage/README.md create mode 100644 afs/redis/README.md create mode 100644 docs/modules/storage/pages/storage-targets/blob-stores/google-cloud-firestore.adoc diff --git a/afs/aws/aws/README.md b/afs/aws/aws/README.md new file mode 100644 index 00000000..b825900b --- /dev/null +++ b/afs/aws/aws/README.md @@ -0,0 +1,11 @@ +# AFS adapter for AWS + +> **_NOTE:_** +> +> This module makes use of external libraries, which have to be provided by the user: +> - `software.amazon.awssdk:auth` +> - `software.amazon.awssdk:aws-core` +> +> Please refer to the [pom](../pom.xml) file for the used versions. +> +> This is done because they might bring licenses potentially incompatible with the EPL. It is the responsibility of the adaptor to acquire them. diff --git a/afs/aws/aws/pom.xml b/afs/aws/aws/pom.xml index 3b0410d9..9583475b 100644 --- a/afs/aws/aws/pom.xml +++ b/afs/aws/aws/pom.xml @@ -33,14 +33,12 @@ software.amazon.awssdk auth + provided software.amazon.awssdk - s3 - - - software.amazon.awssdk - dynamodb + aws-core + provided diff --git a/afs/aws/dynamodb/README.md b/afs/aws/dynamodb/README.md new file mode 100644 index 00000000..36399c64 --- /dev/null +++ b/afs/aws/dynamodb/README.md @@ -0,0 +1,10 @@ +# AFS adapter for AWS DynamoDB + +> **_NOTE:_** +> +> This module makes use of external libraries, which have to be provided by the user: +> - `software.amazon.awssdk:dynamodb` +> +> Please refer to the [pom](../pom.xml) file for the used versions. +> +> This is done because they might bring licenses potentially incompatible with the EPL. It is the responsibility of the adaptor to acquire them. diff --git a/afs/aws/dynamodb/pom.xml b/afs/aws/dynamodb/pom.xml index 1410b957..11773fc8 100644 --- a/afs/aws/dynamodb/pom.xml +++ b/afs/aws/dynamodb/pom.xml @@ -28,6 +28,7 @@ software.amazon.awssdk dynamodb + provided diff --git a/afs/aws/s3/README.md b/afs/aws/s3/README.md new file mode 100644 index 00000000..6e749d51 --- /dev/null +++ b/afs/aws/s3/README.md @@ -0,0 +1,10 @@ +# AFS adapter for AWS S3 + +> **_NOTE:_** +> +> This module makes use of external libraries, which have to be provided by the user: +> - `software.amazon.awssdk:s3` +> +> Please refer to the [pom](../pom.xml) file for the used versions. +> +> This is done because they might bring licenses potentially incompatible with the EPL. It is the responsibility of the adaptor to acquire them. diff --git a/afs/aws/s3/pom.xml b/afs/aws/s3/pom.xml index 2dbfe45e..580879ee 100644 --- a/afs/aws/s3/pom.xml +++ b/afs/aws/s3/pom.xml @@ -28,6 +28,7 @@ software.amazon.awssdk s3 + provided diff --git a/afs/azure/storage/README.md b/afs/azure/storage/README.md new file mode 100644 index 00000000..354776ef --- /dev/null +++ b/afs/azure/storage/README.md @@ -0,0 +1,10 @@ +# AFS adapter for Azure Storage + +> **_NOTE:_** +> +> This module makes use of external libraries, which have to be provided by the user: +> - `com.azure:azure-storage-blob` +> +> Please refer to the [pom](../pom.xml) file for the used versions. +> +> This is done because they might bring licenses potentially incompatible with the EPL. It is the responsibility of the adaptor to acquire them. diff --git a/afs/azure/storage/pom.xml b/afs/azure/storage/pom.xml index 1b822f16..97bfcf13 100644 --- a/afs/azure/storage/pom.xml +++ b/afs/azure/storage/pom.xml @@ -31,6 +31,7 @@ com.azure azure-storage-blob + provided diff --git a/afs/googlecloud/firestore/README.md b/afs/googlecloud/firestore/README.md new file mode 100644 index 00000000..5e36ac56 --- /dev/null +++ b/afs/googlecloud/firestore/README.md @@ -0,0 +1,10 @@ +# AFS adapter for Google Cloud FireStore + +> **_NOTE:_** +> +> This module makes use of external libraries, which have to be provided by the user: +> - `com.google.cloud:google-cloud-firestore` +> +> Please refer to the [pom](../pom.xml) file for the used versions. +> +> This is done because they might bring licenses potentially incompatible with the EPL. It is the responsibility of the adaptor to acquire them. diff --git a/afs/googlecloud/firestore/pom.xml b/afs/googlecloud/firestore/pom.xml index 8244317e..04ae95c2 100644 --- a/afs/googlecloud/firestore/pom.xml +++ b/afs/googlecloud/firestore/pom.xml @@ -23,6 +23,7 @@ com.google.cloud google-cloud-firestore + provided diff --git a/afs/kafka/README.md b/afs/kafka/README.md new file mode 100644 index 00000000..5dfa382d --- /dev/null +++ b/afs/kafka/README.md @@ -0,0 +1,10 @@ +# AFS adapter for Apache Kafka + +> **_NOTE:_** +> +> This module makes use of external libraries, which have to be provided by the user: +> - `org.apache.kafka:kafka-clients` +> +> Please refer to the [pom](./pom.xml) file for the used versions. +> +> This is done because they might bring licenses potentially incompatible with the EPL. It is the responsibility of the adaptor to acquire them. diff --git a/afs/kafka/pom.xml b/afs/kafka/pom.xml index b3f848b8..40b26235 100644 --- a/afs/kafka/pom.xml +++ b/afs/kafka/pom.xml @@ -29,10 +29,11 @@ ${eclipse.serializer.version} - org.apache.kafka - kafka-clients - 3.1.2 - + org.apache.kafka + kafka-clients + 3.1.2 + provided + diff --git a/afs/oraclecloud/objectstorage/README.md b/afs/oraclecloud/objectstorage/README.md new file mode 100644 index 00000000..3c28a2d9 --- /dev/null +++ b/afs/oraclecloud/objectstorage/README.md @@ -0,0 +1,10 @@ +# AFS adapter for Oracle Cloud Object Storage + +> **_NOTE:_** +> +> This module makes use of external libraries, which have to be provided by the user: +> - `com.oracle.oci.sdk:oci-java-sdk-objectstorage` +> +> Please refer to the [pom](../pom.xml) file for the used versions. +> +> This is done because they might bring licenses potentially incompatible with the EPL. It is the responsibility of the adaptor to acquire them. diff --git a/afs/oraclecloud/objectstorage/pom.xml b/afs/oraclecloud/objectstorage/pom.xml index fb291fdc..1b9c9c38 100644 --- a/afs/oraclecloud/objectstorage/pom.xml +++ b/afs/oraclecloud/objectstorage/pom.xml @@ -33,6 +33,7 @@ com.oracle.oci.sdk oci-java-sdk-objectstorage + provided diff --git a/afs/redis/README.md b/afs/redis/README.md new file mode 100644 index 00000000..188675d2 --- /dev/null +++ b/afs/redis/README.md @@ -0,0 +1,10 @@ +# AFS adapter for Redis + +> **_NOTE:_** +> +> This module makes use of external libraries, which have to be provided by the user: +> - `io.lettuce:lettuce-core` +> +> Please refer to the [pom](./pom.xml) file for the used versions. +> +> This is done because they might bring licenses potentially incompatible with the EPL. It is the responsibility of the adaptor to acquire them. diff --git a/afs/redis/pom.xml b/afs/redis/pom.xml index ad1e953a..bdb549c4 100644 --- a/afs/redis/pom.xml +++ b/afs/redis/pom.xml @@ -34,6 +34,7 @@ io.lettuce lettuce-core 6.2.6.RELEASE + provided diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 91220ebd..312c4c01 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -26,6 +26,7 @@ ***** xref:storage:storage-targets/blob-stores/aws-dynamodb.adoc[DynamoDB] ***** xref:storage:storage-targets/blob-stores/aws-s3.adoc[S3] **** xref:storage:storage-targets/blob-stores/azure-storage.adoc[Azure Storage] +**** xref:storage:storage-targets/blob-stores/google-cloud-firestore.adoc[Google Cloud Firestore] **** xref:storage:storage-targets/blob-stores/kafka.adoc[Kafka] **** xref:storage:storage-targets/blob-stores/oracle-cloud-object-storage.adoc[Oracle Cloud Object Storage] **** xref:storage:storage-targets/blob-stores/redis.adoc[Redis] diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/aws-dynamodb.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/aws-dynamodb.adoc index 4ac9929d..58ae34bd 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/aws-dynamodb.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/aws-dynamodb.adoc @@ -7,6 +7,11 @@ afs-aws-dynamodb {maven-version} + + software.amazon.awssdk + dynamodb + 2.17.272 + ---- [source, java] diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/aws-s3.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/aws-s3.adoc index 7d9e4889..85f9de1f 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/aws-s3.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/aws-s3.adoc @@ -7,6 +7,11 @@ afs-aws-s3 {maven-version} + + software.amazon.awssdk + s3 + 2.17.272 + ---- [source, java] diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/azure-storage.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/azure-storage.adoc index 026f9669..729622e2 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/azure-storage.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/azure-storage.adoc @@ -7,6 +7,12 @@ afs-azure-storage {maven-version} + + com.azure + azure-storage-blob + 1.0.2 + + ---- [source, java] diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/google-cloud-firestore.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/google-cloud-firestore.adoc new file mode 100644 index 00000000..2277dd7d --- /dev/null +++ b/docs/modules/storage/pages/storage-targets/blob-stores/google-cloud-firestore.adoc @@ -0,0 +1,77 @@ += Google Cloud Firestore + +[source, xml, subs=attributes+] +---- + + org.eclipse.store + afs-googlecloud-firestore + {maven-version} + + + com.google.cloud + google-cloud-firestore + 25.0.0 + +---- + +[source, java] +---- +Firestore firestore = ... +BlobStoreFileSystem fileSystem = BlobStoreFileSystem.New( + GoogleCloudFirestoreConnector.Caching(client) +); +EmbeddedStorage.start(fileSystem.ensureDirectoryPath("storage")); +---- + +== Configuration + +When using xref:configuration/index.adoc#external-configuration[external configuration] Google Cloud Firestore can be set as follows. + +[source, text, title="eclipsestore.properties"] +---- +storage-filesystem.googlecloud.firestore.credentials.type=default +storage-filesystem.googlecloud.firestore.database-id=my-database-id +storage-filesystem.googlecloud.firestore.project-id=my-project-id +---- + +== Supported properties +[options="header", cols="1,2a"] +|=== +|Property +|Description +//------------- +|database-id +|The database ID to use with this Firestore client. + +|emulator-host +|The emulator host to use with this Firestore client. + +|host +|The service host. + +|project-id +|The project ID. If no project ID is set, the project ID from the environment will be used. + +|quota-project-id +|The project ID that specifies the project used for quota and billing purposes. + +|credentials.type +|The type of the credentials provider. Supported values are: + +* "none" + +No credentials are used. +* "input-stream" + +Path of a JSON file stream. The stream can contain a Service Account key file in JSON format from the Google DevelopersConsole or a stored user credential using the format supported by the Cloud SDK. +* "default" + +Returns the Application Default Credentials which are used to identify and authorize thewhole application. The following are searched (in order) to find the Application DefaultCredentials: +. Credentials file pointed to by the GOOGLE_APPLICATION_CREDENTIALS environment variable +. Credentials provided by the Google Cloud SDK. +.. gcloud auth application-default login for user account credentials. +.. gcloud auth application-default login --impersonate-service-account forimpersonated service account credentials. +. Google App Engine built-in credentials +. Google Cloud Shell built-in credentials +. Google Compute Engine built-in credentials + +|=== + +CAUTION: Depending on the amount of data and transactions, charges may apply depending on service usage. Please check with your service provider for details. \ No newline at end of file diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/kafka.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/kafka.adoc index ae73b4c0..fd3a9afd 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/kafka.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/kafka.adoc @@ -7,6 +7,11 @@ afs-kafka {maven-version} + + org.apache.kafka + kafka-clients + 3.1.2 + ---- [source, java] diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/oracle-cloud-object-storage.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/oracle-cloud-object-storage.adoc index 873c00c3..993c24bc 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/oracle-cloud-object-storage.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/oracle-cloud-object-storage.adoc @@ -7,6 +7,11 @@ afs-oraclecloud-objectstorage {maven-version} + + com.oracle.oci.sdk + oci-java-sdk-objectstorage + 2.21.0 + ---- [source, java] diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/redis.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/redis.adoc index aa5a00f2..733500da 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/redis.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/redis.adoc @@ -7,6 +7,11 @@ afs-redis {maven-version} + + io.lettuce + lettuce-core + 6.2.6.RELEASE + ---- [source, java] From bebf37ff49ad5d8f93ec75a4e896bfdde8677149 Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Mon, 20 Nov 2023 20:51:44 +0100 Subject: [PATCH 009/126] Update README.md --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1a37b87b..5a18818c 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ ![GitHub](https://img.shields.io/github/license/eclipse-store/store?style=for-the-badge) ![GitHub issues](https://img.shields.io/github/issues/eclipse-store/store?style=for-the-badge) +![Maven Central](https://img.shields.io/maven-central/v/org.eclipse.store/storage-embedded?style=for-the-badge) # High-Performance Java-Native-Persistence @@ -15,10 +16,7 @@ EclipseStore is available under [Eclipse Public License - v 2.0](LICENSE). - [Reference manual](https://docs.eclipsestore.io) - [Get started](https://docs.eclipsestore.io/manual/storage/getting-started.html) - +- [Changelog](https://docs.eclipsestore.io/manual/intro/changelog.html) ## Build From 63002ea0adbaa2f437ed4c3f30faa1094b7ee25d Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Fri, 24 Nov 2023 08:26:52 +0100 Subject: [PATCH 010/126] change dev version --- afs/aws/aws/pom.xml | 4 ++-- afs/aws/dynamodb/pom.xml | 4 ++-- afs/aws/pom.xml | 2 +- afs/aws/s3/pom.xml | 4 ++-- afs/azure/pom.xml | 2 +- afs/azure/storage/pom.xml | 4 ++-- afs/blobstore/pom.xml | 2 +- afs/googlecloud/firestore/pom.xml | 2 +- afs/googlecloud/pom.xml | 4 ++-- afs/kafka/pom.xml | 4 ++-- afs/nio/pom.xml | 2 +- afs/oraclecloud/objectstorage/pom.xml | 4 ++-- afs/oraclecloud/pom.xml | 2 +- afs/pom.xml | 2 +- afs/redis/pom.xml | 4 ++-- afs/sql/pom.xml | 2 +- examples/blobs/pom.xml | 4 ++-- examples/custom-legacy-type-handler/pom.xml | 4 ++-- examples/custom-type-handler/pom.xml | 4 ++-- examples/deleting/pom.xml | 4 ++-- examples/eager-storing/pom.xml | 4 ++-- examples/extension-wrapper/pom.xml | 4 ++-- examples/filesystems/pom.xml | 4 ++-- examples/helloworld-ini/pom.xml | 6 +++--- examples/helloworld/pom.xml | 4 ++-- examples/items/pom.xml | 4 ++-- examples/layered-entities/pom.xml | 2 +- examples/lazy-loading/pom.xml | 4 ++-- examples/loading/pom.xml | 4 ++-- examples/pom.xml | 2 +- examples/reloader/pom.xml | 4 ++-- examples/storing/pom.xml | 4 ++-- pom.xml | 2 +- storage/embedded-configuration/pom.xml | 4 ++-- storage/embedded-tools/pom.xml | 2 +- storage/embedded-tools/storage-converter/pom.xml | 4 ++-- storage/embedded-tools/storage-migrator/pom.xml | 2 +- storage/embedded/pom.xml | 4 ++-- storage/pom.xml | 2 +- storage/rest/adapter/pom.xml | 4 ++-- storage/rest/client-app/pom.xml | 4 ++-- storage/rest/client-jersey/pom.xml | 4 ++-- storage/rest/client/pom.xml | 4 ++-- storage/rest/pom.xml | 2 +- storage/rest/service-sparkjava/pom.xml | 4 ++-- storage/rest/service/pom.xml | 4 ++-- storage/storage/pom.xml | 4 ++-- 47 files changed, 80 insertions(+), 80 deletions(-) diff --git a/afs/aws/aws/pom.xml b/afs/aws/aws/pom.xml index 9583475b..ad5e1360 100644 --- a/afs/aws/aws/pom.xml +++ b/afs/aws/aws/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-aws-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-blobstore - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/aws/dynamodb/pom.xml b/afs/aws/dynamodb/pom.xml index 11773fc8..3fb62e7e 100644 --- a/afs/aws/dynamodb/pom.xml +++ b/afs/aws/dynamodb/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-aws-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-aws - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT software.amazon.awssdk diff --git a/afs/aws/pom.xml b/afs/aws/pom.xml index 1f12d29b..97ea6ea3 100644 --- a/afs/aws/pom.xml +++ b/afs/aws/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml diff --git a/afs/aws/s3/pom.xml b/afs/aws/s3/pom.xml index 580879ee..6599b57a 100644 --- a/afs/aws/s3/pom.xml +++ b/afs/aws/s3/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-aws-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-aws - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT software.amazon.awssdk diff --git a/afs/azure/pom.xml b/afs/azure/pom.xml index 89b6dbaf..69e713ea 100644 --- a/afs/azure/pom.xml +++ b/afs/azure/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml diff --git a/afs/azure/storage/pom.xml b/afs/azure/storage/pom.xml index 97bfcf13..24064045 100644 --- a/afs/azure/storage/pom.xml +++ b/afs/azure/storage/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-azure-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ org.eclipse.store afs-blobstore - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/blobstore/pom.xml b/afs/blobstore/pom.xml index 330cb7e7..25382a9e 100644 --- a/afs/blobstore/pom.xml +++ b/afs/blobstore/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml diff --git a/afs/googlecloud/firestore/pom.xml b/afs/googlecloud/firestore/pom.xml index 04ae95c2..ffe53a69 100644 --- a/afs/googlecloud/firestore/pom.xml +++ b/afs/googlecloud/firestore/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-googlecloud-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml diff --git a/afs/googlecloud/pom.xml b/afs/googlecloud/pom.xml index 3ed0fde9..440fdd2c 100644 --- a/afs/googlecloud/pom.xml +++ b/afs/googlecloud/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -40,7 +40,7 @@ org.eclipse.store afs-blobstore - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/kafka/pom.xml b/afs/kafka/pom.xml index 40b26235..93c0f528 100644 --- a/afs/kafka/pom.xml +++ b/afs/kafka/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ org.eclipse.store afs-blobstore - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/nio/pom.xml b/afs/nio/pom.xml index 9a45eae9..cc785c1e 100644 --- a/afs/nio/pom.xml +++ b/afs/nio/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml diff --git a/afs/oraclecloud/objectstorage/pom.xml b/afs/oraclecloud/objectstorage/pom.xml index 1b9c9c38..adbb09ae 100644 --- a/afs/oraclecloud/objectstorage/pom.xml +++ b/afs/oraclecloud/objectstorage/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-oraclecloud-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-blobstore - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/oraclecloud/pom.xml b/afs/oraclecloud/pom.xml index 1e15280b..4a6a45d9 100644 --- a/afs/oraclecloud/pom.xml +++ b/afs/oraclecloud/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml diff --git a/afs/pom.xml b/afs/pom.xml index 5a6a51f0..c94d6e27 100644 --- a/afs/pom.xml +++ b/afs/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store store-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml diff --git a/afs/redis/pom.xml b/afs/redis/pom.xml index bdb549c4..8d085de5 100644 --- a/afs/redis/pom.xml +++ b/afs/redis/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-blobstore - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/sql/pom.xml b/afs/sql/pom.xml index 86bd777c..3efb36d0 100644 --- a/afs/sql/pom.xml +++ b/afs/sql/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml diff --git a/examples/blobs/pom.xml b/examples/blobs/pom.xml index c7c277bc..25330877 100644 --- a/examples/blobs/pom.xml +++ b/examples/blobs/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store examples-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ org.eclipse.store storage-embedded - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT diff --git a/examples/custom-legacy-type-handler/pom.xml b/examples/custom-legacy-type-handler/pom.xml index 7b783402..c7950c14 100644 --- a/examples/custom-legacy-type-handler/pom.xml +++ b/examples/custom-legacy-type-handler/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/custom-type-handler/pom.xml b/examples/custom-type-handler/pom.xml index 836d0d28..f4f0ab9d 100644 --- a/examples/custom-type-handler/pom.xml +++ b/examples/custom-type-handler/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/deleting/pom.xml b/examples/deleting/pom.xml index eaca3dd5..c84b2af6 100644 --- a/examples/deleting/pom.xml +++ b/examples/deleting/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT diff --git a/examples/eager-storing/pom.xml b/examples/eager-storing/pom.xml index ffbb4e26..85dc535b 100644 --- a/examples/eager-storing/pom.xml +++ b/examples/eager-storing/pom.xml @@ -10,7 +10,7 @@ org.eclipse.store examples-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -24,7 +24,7 @@ org.eclipse.store storage-embedded - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT diff --git a/examples/extension-wrapper/pom.xml b/examples/extension-wrapper/pom.xml index ca5bc338..035de4c6 100644 --- a/examples/extension-wrapper/pom.xml +++ b/examples/extension-wrapper/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store examples-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ org.eclipse.store storage-embedded - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT diff --git a/examples/filesystems/pom.xml b/examples/filesystems/pom.xml index 1691b9b4..9bff63d8 100644 --- a/examples/filesystems/pom.xml +++ b/examples/filesystems/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT com.google.jimfs diff --git a/examples/helloworld-ini/pom.xml b/examples/helloworld-ini/pom.xml index cd5ddacc..643dd11a 100644 --- a/examples/helloworld-ini/pom.xml +++ b/examples/helloworld-ini/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,12 +23,12 @@ org.eclipse.store storage-embedded - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.store storage-embedded-configuration - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml index cb2daa8e..3ea555b2 100644 --- a/examples/helloworld/pom.xml +++ b/examples/helloworld/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT diff --git a/examples/items/pom.xml b/examples/items/pom.xml index db00eab2..168f9acd 100644 --- a/examples/items/pom.xml +++ b/examples/items/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/layered-entities/pom.xml b/examples/layered-entities/pom.xml index 065c9cb3..74a15309 100644 --- a/examples/layered-entities/pom.xml +++ b/examples/layered-entities/pom.xml @@ -10,7 +10,7 @@ org.eclipse.store examples-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml diff --git a/examples/lazy-loading/pom.xml b/examples/lazy-loading/pom.xml index 47200fe8..72251a1c 100644 --- a/examples/lazy-loading/pom.xml +++ b/examples/lazy-loading/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/loading/pom.xml b/examples/loading/pom.xml index 10208024..795f23bc 100644 --- a/examples/loading/pom.xml +++ b/examples/loading/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/pom.xml b/examples/pom.xml index e6df4c2a..25e517da 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store store-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml diff --git a/examples/reloader/pom.xml b/examples/reloader/pom.xml index 5268d3c0..2d8a399c 100644 --- a/examples/reloader/pom.xml +++ b/examples/reloader/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded-configuration - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT diff --git a/examples/storing/pom.xml b/examples/storing/pom.xml index ed1caf11..fdf522b7 100644 --- a/examples/storing/pom.xml +++ b/examples/storing/pom.xml @@ -10,7 +10,7 @@ org.eclipse.store examples-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -24,7 +24,7 @@ org.eclipse.store storage-embedded - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.serializer diff --git a/pom.xml b/pom.xml index 57639a3b..81177528 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ org.eclipse.store store-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT pom EclipseStore diff --git a/storage/embedded-configuration/pom.xml b/storage/embedded-configuration/pom.xml index ff15716f..79a4849b 100644 --- a/storage/embedded-configuration/pom.xml +++ b/storage/embedded-configuration/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.serializer diff --git a/storage/embedded-tools/pom.xml b/storage/embedded-tools/pom.xml index 5ceb9c33..51d13177 100644 --- a/storage/embedded-tools/pom.xml +++ b/storage/embedded-tools/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml diff --git a/storage/embedded-tools/storage-converter/pom.xml b/storage/embedded-tools/storage-converter/pom.xml index c314d593..33cd29af 100644 --- a/storage/embedded-tools/storage-converter/pom.xml +++ b/storage/embedded-tools/storage-converter/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-embedded-tools-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded-configuration - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT diff --git a/storage/embedded-tools/storage-migrator/pom.xml b/storage/embedded-tools/storage-migrator/pom.xml index 8be17bd5..ecb13d7d 100644 --- a/storage/embedded-tools/storage-migrator/pom.xml +++ b/storage/embedded-tools/storage-migrator/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-embedded-tools-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml diff --git a/storage/embedded/pom.xml b/storage/embedded/pom.xml index 114338aa..9392bbdd 100644 --- a/storage/embedded/pom.xml +++ b/storage/embedded/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT diff --git a/storage/pom.xml b/storage/pom.xml index e587657b..01cac3b2 100644 --- a/storage/pom.xml +++ b/storage/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store store-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml diff --git a/storage/rest/adapter/pom.xml b/storage/rest/adapter/pom.xml index ba7300ad..c16756a1 100644 --- a/storage/rest/adapter/pom.xml +++ b/storage/rest/adapter/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT diff --git a/storage/rest/client-app/pom.xml b/storage/rest/client-app/pom.xml index 9f348a04..cfbd755f 100644 --- a/storage/rest/client-app/pom.xml +++ b/storage/rest/client-app/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -47,7 +47,7 @@ org.eclipse.store storage-restclient-jersey - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT com.vaadin diff --git a/storage/rest/client-jersey/pom.xml b/storage/rest/client-jersey/pom.xml index 101d2d2b..93c329da 100644 --- a/storage/rest/client-jersey/pom.xml +++ b/storage/rest/client-jersey/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -29,7 +29,7 @@ org.eclipse.store storage-restclient - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.glassfish.jersey.core diff --git a/storage/rest/client/pom.xml b/storage/rest/client/pom.xml index 179fdb26..534185b1 100644 --- a/storage/rest/client/pom.xml +++ b/storage/rest/client/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-restadapter - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT diff --git a/storage/rest/pom.xml b/storage/rest/pom.xml index 830364a2..ee4316e6 100644 --- a/storage/rest/pom.xml +++ b/storage/rest/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml diff --git a/storage/rest/service-sparkjava/pom.xml b/storage/rest/service-sparkjava/pom.xml index ffc6525c..d200b352 100644 --- a/storage/rest/service-sparkjava/pom.xml +++ b/storage/rest/service-sparkjava/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -29,7 +29,7 @@ org.eclipse.store storage-restservice - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT com.sparkjava diff --git a/storage/rest/service/pom.xml b/storage/rest/service/pom.xml index cd4b5cdd..1d3da606 100644 --- a/storage/rest/service/pom.xml +++ b/storage/rest/service/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-restadapter - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT diff --git a/storage/storage/pom.xml b/storage/storage/pom.xml index 57a782cb..aa90f791 100644 --- a/storage/storage/pom.xml +++ b/storage/storage/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-nio - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.serializer From 4c98b874dc89943559f1f936c614ba48921c7eee Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 28 Nov 2023 14:31:19 +0100 Subject: [PATCH 011/126] add release snapshot build --- .github/workflows/maven_deploy_snapshot.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/maven_deploy_snapshot.yml b/.github/workflows/maven_deploy_snapshot.yml index 030a7aeb..e06c0e48 100644 --- a/.github/workflows/maven_deploy_snapshot.yml +++ b/.github/workflows/maven_deploy_snapshot.yml @@ -5,7 +5,9 @@ name: Make snapshot and deploy on: push: - branches: [main] + branches: + - main + - 'release/**' jobs: publish: From 2f6816854fdfaa8e17ad06c2de68a6de2cb4ec6b Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Thu, 30 Nov 2023 08:42:01 +0100 Subject: [PATCH 012/126] fixing docu #74 --- docs/modules/ROOT/nav.adoc | 1 + .../storage/pages/configuration/readonly.adoc | 32 +++++++++++++++++++ .../storage-files-and-directories.adoc | 4 +-- .../pages/configuration/using-channels.adoc | 6 ++-- 4 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 docs/modules/storage/pages/configuration/readonly.adoc diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 312c4c01..a4620d25 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -10,6 +10,7 @@ *** xref:storage:configuration/storage-files-and-directories.adoc[Storage Files and Directories] *** xref:storage:configuration/using-channels.adoc[Using Channels] *** xref:storage:configuration/housekeeping.adoc[Houskeeping] +*** xref:storage:configuration/readonly.adoc[Read-only Manager] *** Backup **** xref:storage:configuration/backup/continuous-backup.adoc[Continous Backup] **** xref:storage:configuration/backup/full-backup.adoc[Full Backup] diff --git a/docs/modules/storage/pages/configuration/readonly.adoc b/docs/modules/storage/pages/configuration/readonly.adoc new file mode 100644 index 00000000..1e83e450 --- /dev/null +++ b/docs/modules/storage/pages/configuration/readonly.adoc @@ -0,0 +1,32 @@ += Read-Only Storage Manager + +It is possible to have a _Storage Manager_ which operates in a read-only mode. Since there is a limitation Eclipse Store that you can have only one manager that is connected to one data storage, you can bypass this restriction with this read-only mode. But there are limitations, such as: + +- In read-only mode, you cannot write to a data storage. This means that calls to `.store()` and other methods which would result in a write, will throw an exception. +- In read-only mode, the housekeeping processes do not run since that would corrupt the data storage because two managers are operating on the same 'files'. +- In read-only mode, your data root is filled on startup of the manager as usual, and lazy references operate as normal. But there is no notification mechanism that the underlying data storage has changed and the Storage Manager only remembers the structure of the data storage as it was when it started. + +The last bullet point is important. It indicates that when another _Storage Manager_ writes some new data, this new data never gets picked up by this read-only manager. And when the house-holding process of the other _Storage Manager_ removes a file or reorganizes a file as cleanup, an exception will be thrown as the structure is changed but still expected by the read-only manager. + +So the read-only manager can only be used to read some data but should be closed 'soon' after starting and a new manager created if you need to read data later on. + +== Configuration + +The following snippet shows how you can make a read-only _Storage Manager_. It actually wraps the `StorageWriteController` configured by the _Foundation_ and can either block or pass through the normal behaviour. + + +[source, java] +---- + EmbeddedStorageFoundation foundation = ... + + final StorageWriteControllerReadOnlyMode storageWriteController = + new StorageWriteControllerReadOnlyMode(foundation.getWriteController()); + foundation.setWriteController(storageWriteController); +---- + +With the `.setReadOnly()` method you can switch the read-only mode of the Storage Manager after it has started. But be careful with the method because you can't have more than one manager that writes to the same data storage as that would corrupt the storage. + +[source, java] +---- + storageWriteController.setReadOnly(false); +---- diff --git a/docs/modules/storage/pages/configuration/storage-files-and-directories.adoc b/docs/modules/storage/pages/configuration/storage-files-and-directories.adoc index f9ed615f..87ab05f1 100644 --- a/docs/modules/storage/pages/configuration/storage-files-and-directories.adoc +++ b/docs/modules/storage/pages/configuration/storage-files-and-directories.adoc @@ -25,9 +25,9 @@ Available properties are: StorageFileNameProvider fileNameProvider = StorageFileNameProvider.Builder() .setChannelDirectoryPrefix("canal_") .setDataFilePrefix ("canal_") - .setDataFileSuffix (".bin") + .setDataFileSuffix ("bin") .setTransactionsFilePrefix("events_") - .setTransactionsFileSuffix(".bin") + .setTransactionsFileSuffix("bin") .setTypeDictionaryFileName("typeDictionary.txt") .createFileNameProvider () ; diff --git a/docs/modules/storage/pages/configuration/using-channels.adoc b/docs/modules/storage/pages/configuration/using-channels.adoc index b6b1f7eb..a2ec3ff3 100644 --- a/docs/modules/storage/pages/configuration/using-channels.adoc +++ b/docs/modules/storage/pages/configuration/using-channels.adoc @@ -25,7 +25,7 @@ For the channel configuration the following configuration xref:configuration/pro |Default is `"channel_"` |data-file-suffix -|Default is `".dat"` +|Default is `"dat"` |=== Channel file size configuration is done by the the xref:configuration/housekeeping.adoc#storage-data-file-evaluator[Storage Data File Evaluator]. @@ -38,7 +38,7 @@ EmbeddedStorageManager storageManager = EmbeddedStorageConfigurationBuilder.New( .setChannelCount(4) .setChannelDirectoryPrefix("channel_") .setDataFilePrefix("channel_") - .setDataFileSuffix(".bin") + .setDataFileSuffix("bin") .createEmbeddedStorageFoundation() .createEmbeddedStorageManager(); ---- @@ -49,7 +49,7 @@ EmbeddedStorageManager storageManager = EmbeddedStorageConfigurationBuilder.New( - + ---- From 4463b57764eefd7abfc98207a25f5bf6d4466dfc Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Thu, 30 Nov 2023 09:01:23 +0100 Subject: [PATCH 013/126] Update readonly.adoc --- .../storage/pages/configuration/readonly.adoc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/modules/storage/pages/configuration/readonly.adoc b/docs/modules/storage/pages/configuration/readonly.adoc index 1e83e450..9019e8be 100644 --- a/docs/modules/storage/pages/configuration/readonly.adoc +++ b/docs/modules/storage/pages/configuration/readonly.adoc @@ -1,14 +1,14 @@ = Read-Only Storage Manager -It is possible to have a _Storage Manager_ which operates in a read-only mode. Since there is a limitation Eclipse Store that you can have only one manager that is connected to one data storage, you can bypass this restriction with this read-only mode. But there are limitations, such as: +It is possible to have a _Storage Manager_ which operates in a read-only mode. Since there is a limitation {product-name} that you can have only one manager that is connected to one data storage, you can bypass this restriction with this read-only mode. But there are limitations, such as: -- In read-only mode, you cannot write to a data storage. This means that calls to `.store()` and other methods which would result in a write, will throw an exception. -- In read-only mode, the housekeeping processes do not run since that would corrupt the data storage because two managers are operating on the same 'files'. -- In read-only mode, your data root is filled on startup of the manager as usual, and lazy references operate as normal. But there is no notification mechanism that the underlying data storage has changed and the Storage Manager only remembers the structure of the data storage as it was when it started. +- In read-only mode, you cannot write to a data storage. This means that calls to `.store()` and other methods that would result in a write, will throw an exception. +- In read-only mode, the housekeeping processes do not run since that would corrupt the data storage because two managers operate on the same 'files'. +- In read-only mode, your data root is filled on startup of the manager as usual, and lazy references operate as normal. But there is no notification mechanism that the underlying data storage has changed, and the Storage Manager only remembers the structure of the data storage as it was when it started. The last bullet point is important. It indicates that when another _Storage Manager_ writes some new data, this new data never gets picked up by this read-only manager. And when the house-holding process of the other _Storage Manager_ removes a file or reorganizes a file as cleanup, an exception will be thrown as the structure is changed but still expected by the read-only manager. -So the read-only manager can only be used to read some data but should be closed 'soon' after starting and a new manager created if you need to read data later on. +So, the read-only manager can only be used to read some data but should be closed 'soon' after starting, and a new manager should be created if you need to read data later on. == Configuration @@ -24,7 +24,7 @@ The following snippet shows how you can make a read-only _Storage Manager_. It foundation.setWriteController(storageWriteController); ---- -With the `.setReadOnly()` method you can switch the read-only mode of the Storage Manager after it has started. But be careful with the method because you can't have more than one manager that writes to the same data storage as that would corrupt the storage. +With the `.setReadOnly()` method, you can switch the read-only mode of the Storage Manager after it has started. But be careful with the method because you can't have more than one manager that writes to the same data storage, as that would corrupt the storage. [source, java] ---- From d21de11a94f64e5f9b6186407940495b8e101588 Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Thu, 30 Nov 2023 09:03:38 +0100 Subject: [PATCH 014/126] Update readonly.adoc --- docs/modules/storage/pages/configuration/readonly.adoc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/modules/storage/pages/configuration/readonly.adoc b/docs/modules/storage/pages/configuration/readonly.adoc index 9019e8be..8a09b803 100644 --- a/docs/modules/storage/pages/configuration/readonly.adoc +++ b/docs/modules/storage/pages/configuration/readonly.adoc @@ -1,18 +1,18 @@ = Read-Only Storage Manager -It is possible to have a _Storage Manager_ which operates in a read-only mode. Since there is a limitation {product-name} that you can have only one manager that is connected to one data storage, you can bypass this restriction with this read-only mode. But there are limitations, such as: +It is possible to have a _Storage Manager_ which operates in a read-only mode. Since there is a limitation in {product-name} that you can have only one manager that is connected to one data storage, you can bypass this restriction with this read-only mode. But there are limitations, such as: -- In read-only mode, you cannot write to a data storage. This means that calls to `.store()` and other methods that would result in a write, will throw an exception. +- In read-only mode, you cannot write to a data storage. This means calls to `.store()` and other methods resulting in a write will throw an exception. - In read-only mode, the housekeeping processes do not run since that would corrupt the data storage because two managers operate on the same 'files'. -- In read-only mode, your data root is filled on startup of the manager as usual, and lazy references operate as normal. But there is no notification mechanism that the underlying data storage has changed, and the Storage Manager only remembers the structure of the data storage as it was when it started. +- In read-only mode, your data root is filled on startup of the manager as usual, and lazy references operate as normal. However, there is no notification mechanism that the underlying data storage has changed, and the Storage Manager only remembers the structure of the data storage as it was when it started. -The last bullet point is important. It indicates that when another _Storage Manager_ writes some new data, this new data never gets picked up by this read-only manager. And when the house-holding process of the other _Storage Manager_ removes a file or reorganizes a file as cleanup, an exception will be thrown as the structure is changed but still expected by the read-only manager. +The last bullet point is important. It indicates that when another _Storage Manager_ writes some new data, this new data never gets picked up by this read-only manager. When the other _Storage Manager_ housekeeping process removes a file or reorganizes a file as cleanup, an exception will be thrown as the structure is changed but still expected by the read-only manager. So, the read-only manager can only be used to read some data but should be closed 'soon' after starting, and a new manager should be created if you need to read data later on. == Configuration -The following snippet shows how you can make a read-only _Storage Manager_. It actually wraps the `StorageWriteController` configured by the _Foundation_ and can either block or pass through the normal behaviour. +The following snippet shows how to make a read-only _Storage Manager_. It actually wraps the `StorageWriteController` configured by the _Foundation_ and can either block or pass through the normal behaviour. [source, java] From 4461eea12ea24bf4924b60d5f861e5fa236cb2d1 Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Thu, 30 Nov 2023 11:06:37 +0100 Subject: [PATCH 015/126] migration: fixed-missing-output-file-error-#640 --- .../store/storage/util/MainUtilTransactionFileConverter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/util/MainUtilTransactionFileConverter.java b/storage/storage/src/main/java/org/eclipse/store/storage/util/MainUtilTransactionFileConverter.java index 9032a057..4351d1ea 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/util/MainUtilTransactionFileConverter.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/util/MainUtilTransactionFileConverter.java @@ -61,6 +61,7 @@ public static void main(final String[] args) System.out.println("Converted String length: " + result.length()); final AFile outputFile = file.parent().ensureFile(file.name(), "txt"); + outputFile.ensureExists(); System.out.println("Writing File " + outputFile); try From 8d937f59939ebe0c9b95ea6a473afbda25dbb8ea Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Thu, 30 Nov 2023 14:46:04 +0100 Subject: [PATCH 016/126] migration of adaptive housekeeping feature migrating https://github.com/microstream-one/microstream/pull/641 --- .../pages/configuration/housekeeping.adoc | 43 ++- .../pages/configuration/properties.adoc | 12 + .../EmbeddedStorageConfigurationBuilder.java | 74 ++++ ...ddedStorageConfigurationPropertyNames.java | 20 ++ ...geFoundationCreatorConfigurationBased.java | 33 +- .../storage/types/StorageEventLogger.java | 93 +++++ .../storage/types/StorageFoundation.java | 23 +- .../types/StorageHousekeepingController.java | 329 ++++++++++++++++++ 8 files changed, 613 insertions(+), 14 deletions(-) diff --git a/docs/modules/storage/pages/configuration/housekeeping.adoc b/docs/modules/storage/pages/configuration/housekeeping.adoc index f949e7b5..bd2d20da 100644 --- a/docs/modules/storage/pages/configuration/housekeeping.adoc +++ b/docs/modules/storage/pages/configuration/housekeeping.adoc @@ -16,15 +16,48 @@ Available properties are: |xref:configuration/properties.adoc#housekeeping-time-budget[housekeeping-time-budget] |Time budget for housekeeping in nanoseconds, default is 0.01 seconds + +|housekeeping-adaptive +|Usage of an adaptive housekeeping controller, which will increase the time budgets on demand, if the garbage collector needs more time to reach the sweeping phase. + +|housekeeping-increase-threshold +|The threshold of the adaption cycle to calculate new budgets for the housekeeping process. Default is 5 seconds. + +|housekeeping-increase-amount +|The amount the housekeeping budgets will be increased each cycle. Default is 50 ms. + +|housekeeping-maximum-time-budget +|The upper limit of the housekeeping time budgets. Default is 0.5 seconds. |=== [source, java] ---- -EmbeddedStorageManager storage = EmbeddedStorage.Foundation( - Storage.ConfigurationBuilder() - .setHousekeepingController(Storage.HousekeepingController(1000, 10_000_000)) - .createConfiguration()) - .start(); +// New foundation +final EmbeddedStorageFoundation foundation = EmbeddedStorage.Foundation(); + +// Housekeeping controller with fixed time budget +final StorageHousekeepingController fixedController = Storage.HousekeepingController( + 1000, // interval in ms + 10_000_000 // time budget in ns +); + +// Wrap in adaptive controller +final StorageHousekeepingController adaptiveController = StorageHousekeepingController + .AdaptiveBuilder(fixedController) + .increaseThresholdMs(100) + .increaseAmountNs(Duration.ofMillis(1).toNanos()) + .maximumTimeBudgetNs(Duration.ofMillis(100).toNanos()) + .buildFor(foundation) +; + +// Use controller in foundation +foundation.setConfiguration(Storage.ConfigurationBuilder() + .setHousekeepingController(adaptiveController) + .createConfiguration() +); + +// Start storage +final EmbeddedStorageManager storage = foundation.start(); ---- [#storage-data-file-evaluator] diff --git a/docs/modules/storage/pages/configuration/properties.adoc b/docs/modules/storage/pages/configuration/properties.adoc index 9b5086b9..1f8053c9 100644 --- a/docs/modules/storage/pages/configuration/properties.adoc +++ b/docs/modules/storage/pages/configuration/properties.adoc @@ -59,6 +59,18 @@ They can be found as constants in `EmbeddedStorageConfigurationPropertyNames`. |xref:#housekeeping-time-budget[housekeeping-time-budget] |Number of nanoseconds used for each housekeeping cycle. Default is 10 milliseconds = 0.01 seconds. +|housekeeping-adaptive +|Usage of an adaptive housekeeping controller, which will increase the time budgets on demand, if the garbage collector needs more time to reach the sweeping phase. + +|housekeeping-increase-threshold +|The threshold of the adaption cycle to calculate new budgets for the housekeeping process. Default is 5 seconds. + +|housekeeping-increase-amount +|The amount the housekeeping budgets will be increased each cycle. Default is 50 ms. + +|housekeeping-maximum-time-budget +|The upper limit of the housekeeping time budgets. Default is 0.5 seconds. + |entity-cache-threshold |Abstract threshold value for the lifetime of entities in the cache. Default is `1000000000`. diff --git a/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageConfigurationBuilder.java b/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageConfigurationBuilder.java index d4b2dcdc..0b8fe92e 100644 --- a/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageConfigurationBuilder.java +++ b/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageConfigurationBuilder.java @@ -202,6 +202,48 @@ public default EmbeddedStorageConfigurationBuilder setBackupDirectoryInUserHome( */ public EmbeddedStorageConfigurationBuilder setHousekeepingTimeBudget(Duration housekeepingTimeBudget); + /** + * Usage of an adaptive housekeeping controller, which will increase the time budgets on demand, + * if the garbage collector needs more time to reach the sweeping phase. + * + * @param adaptive true if an adaptive controller should be used + * @return this + * + * @see #setHousekeepingIncreaseThreshold(Duration) + * @see #setHousekeepingIncreaseAmount(Duration) + * @see #setHousekeepingMaximumTimeBudget(Duration) + */ + public EmbeddedStorageConfigurationBuilder setHousekeepingAdaptive(boolean adaptive); + + /** + * The threshold of the adaption cycle to calculate new budgets for the housekeeping process. + *

+ * Only used when {@link #setHousekeepingAdaptive(boolean)} is true. + * + * @param housekeepingIncreaseThreshold the new increase threshold + * @return this + */ + public EmbeddedStorageConfigurationBuilder setHousekeepingIncreaseThreshold(Duration housekeepingIncreaseThreshold); + + /** + * The amount the housekeeping budgets will be increased each cycle. + *

+ * Only used when {@link #setHousekeepingAdaptive(boolean)} is true. + * + * @param housekeepingIncreaseAmount the new increase amount + * @return this + */ + public EmbeddedStorageConfigurationBuilder setHousekeepingIncreaseAmount(Duration housekeepingIncreaseAmount); + + /** + * The upper limit of the housekeeping time budgets. + *

+ * Only used when {@link #setHousekeepingAdaptive(boolean)} is true. + * + * @param housekeepingMaximumTimeBudget the new maximum time budget + * @return this + */ + public EmbeddedStorageConfigurationBuilder setHousekeepingMaximumTimeBudget(Duration housekeepingMaximumTimeBudget); /** * Abstract threshold value for the lifetime of entities in the cache. See @@ -508,6 +550,38 @@ public EmbeddedStorageConfigurationBuilder setHousekeepingTimeBudget( return this.set(HOUSEKEEPING_TIME_BUDGET, housekeepingTimeBudget.toString()); } + @Override + public EmbeddedStorageConfigurationBuilder setHousekeepingAdaptive( + final boolean adaptive + ) + { + return this.set(HOUSEKEEPING_ADAPTIVE, Boolean.toString(adaptive)); + } + + @Override + public EmbeddedStorageConfigurationBuilder setHousekeepingIncreaseThreshold( + final Duration housekeepingIncreaseThreshold + ) + { + return this.set(HOUSEKEEPING_INCREASE_THRESHOLD, housekeepingIncreaseThreshold.toString()); + } + + @Override + public EmbeddedStorageConfigurationBuilder setHousekeepingIncreaseAmount( + final Duration housekeepingIncreaseAmount + ) + { + return this.set(HOUSEKEEPING_INCREASE_AMOUNT, housekeepingIncreaseAmount.toString()); + } + + @Override + public EmbeddedStorageConfigurationBuilder setHousekeepingMaximumTimeBudget( + final Duration housekeepingMaximumTimeBudget + ) + { + return this.set(HOUSEKEEPING_MAXIMUM_TIME_BUDGET, housekeepingMaximumTimeBudget.toString()); + } + @Override public EmbeddedStorageConfigurationBuilder setEntityCacheThreshold( final long entityCacheThreshold diff --git a/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageConfigurationPropertyNames.java b/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageConfigurationPropertyNames.java index 8c32befa..5003e0c2 100644 --- a/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageConfigurationPropertyNames.java +++ b/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageConfigurationPropertyNames.java @@ -102,6 +102,26 @@ public interface EmbeddedStorageConfigurationPropertyNames */ public final static String HOUSEKEEPING_TIME_BUDGET = "housekeeping-time-budget"; + /** + * @see EmbeddedStorageConfigurationBuilder#setHousekeepingAdaptive(boolean) + */ + public final static String HOUSEKEEPING_ADAPTIVE = "housekeeping-adaptive"; + + /** + * @see EmbeddedStorageConfigurationBuilder#setHousekeepingIncreaseThreshold(java.time.Duration) + */ + public final static String HOUSEKEEPING_INCREASE_THRESHOLD = "housekeeping-increase-threshold"; + + /** + * @see EmbeddedStorageConfigurationBuilder#setHousekeepingIncreaseAmount(java.time.Duration) + */ + public final static String HOUSEKEEPING_INCREASE_AMOUNT = "housekeeping-increase-amount"; + + /** + * @see EmbeddedStorageConfigurationBuilder#setHousekeepingMaximumTimeBudget(java.time.Duration) + */ + public final static String HOUSEKEEPING_MAXIMUM_TIME_BUDGET = "housekeeping-maximum-time-budget"; + /** * @see EmbeddedStorageConfigurationBuilder#setEntityCacheThreshold(long) */ diff --git a/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageFoundationCreatorConfigurationBased.java b/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageFoundationCreatorConfigurationBased.java index 2963f0c1..d638a572 100644 --- a/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageFoundationCreatorConfigurationBased.java +++ b/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageFoundationCreatorConfigurationBased.java @@ -95,6 +95,8 @@ public EmbeddedStorageFoundation createEmbeddedStorageFoundation() private EmbeddedStorageFoundation internalCreateEmbeddedStorageFoundation() { + final EmbeddedStorageFoundation foundation = EmbeddedStorage.Foundation(); + final AFileSystem fileSystem = this.createFileSystem( STORAGE_FILESYSTEM, NioFileSystem::New @@ -103,7 +105,7 @@ private EmbeddedStorageFoundation internalCreateEmbeddedStorageFoundation() final StorageConfiguration.Builder configBuilder = Storage.ConfigurationBuilder() .setStorageFileProvider (this.createFileProvider(fileSystem)) .setChannelCountProvider (this.createChannelCountProvider() ) - .setHousekeepingController(this.createHousekeepingController()) + .setHousekeepingController(this.createHousekeepingController(foundation)) .setDataFileEvaluator (this.createDataFileEvaluator() ) .setEntityCacheEvaluator (this.createEntityCacheEvaluator() ) ; @@ -123,9 +125,9 @@ private EmbeddedStorageFoundation internalCreateEmbeddedStorageFoundation() }) ; - return EmbeddedStorage.Foundation( - configBuilder.createConfiguration() - ); + foundation.setConfiguration(configBuilder.createConfiguration()); + + return foundation; } private AFileSystem createFileSystem( @@ -208,9 +210,9 @@ private StorageChannelCountProvider createChannelCountProvider() ); } - private StorageHousekeepingController createHousekeepingController() + private StorageHousekeepingController createHousekeepingController(final EmbeddedStorageFoundation foundation) { - return Storage.HousekeepingController( + StorageHousekeepingController controller = Storage.HousekeepingController( this.configuration.opt(HOUSEKEEPING_INTERVAL, Duration.class) .map(Duration::toMillis) .orElse(StorageHousekeepingController.Defaults.defaultHousekeepingIntervalMs()), @@ -218,6 +220,25 @@ private StorageHousekeepingController createHousekeepingController() .map(Duration::toNanos) .orElse(StorageHousekeepingController.Defaults.defaultHousekeepingTimeBudgetNs()) ); + + if(this.configuration.optBoolean(HOUSEKEEPING_ADAPTIVE).orElse(false)) + { + controller = StorageHousekeepingController.Adaptive( + controller, + this.configuration.opt(HOUSEKEEPING_INCREASE_THRESHOLD, Duration.class) + .map(Duration::toMillis) + .orElse(StorageHousekeepingController.Adaptive.Defaults.defaultAdaptiveHousekeepingIncreaseThresholdMs()), + this.configuration.opt(HOUSEKEEPING_INCREASE_AMOUNT, Duration.class) + .map(Duration::toNanos) + .orElse(StorageHousekeepingController.Adaptive.Defaults.defaultAdaptiveHousekeepingIncreaseAmountNs()), + this.configuration.opt(HOUSEKEEPING_MAXIMUM_TIME_BUDGET, Duration.class) + .map(Duration::toNanos) + .orElse(StorageHousekeepingController.Adaptive.Defaults.defaultAdaptiveHousekeepingMaximumTimeBudgetNs()), + foundation + ); + } + + return controller; } private StorageDataFileEvaluator createDataFileEvaluator() diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageEventLogger.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageEventLogger.java index 8354600b..faaf3049 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageEventLogger.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageEventLogger.java @@ -300,4 +300,97 @@ public void logGarbageCollectorCompleted(final long gcColdGeneration, final long } + + public static StorageEventLogger Chain( + final StorageEventLogger first , + final StorageEventLogger second + ) + { + return new StorageEventLogger.Chaining( + notNull(first ), + notNull(second) + ); + } + + + public final class Chaining implements StorageEventLogger + { + private final StorageEventLogger first ; + private final StorageEventLogger second; + + Chaining( + final StorageEventLogger first , + final StorageEventLogger second + ) + { + super(); + this.first = first ; + this.second = second; + } + + @Override + public void logChannelProcessingDisabled(final StorageChannel channel) + { + this.first.logChannelProcessingDisabled(channel); + this.second.logChannelProcessingDisabled(channel); + } + + @Override + public void logChannelStoppedWorking(final StorageChannel channel) + { + this.first.logChannelStoppedWorking(channel); + this.second.logChannelStoppedWorking(channel); + } + + @Override + public void logDisruption(final StorageChannel channel, final Throwable t) + { + this.first.logDisruption(channel, t); + this.second.logDisruption(channel, t); + } + + @Override + public void logLiveCheckComplete(final StorageEntityCache entityCache) + { + this.first.logLiveCheckComplete(entityCache); + this.second.logLiveCheckComplete(entityCache); + } + + @Override + public void logGarbageCollectorSweepingComplete(final StorageEntityCache entityCache) + { + this.first.logGarbageCollectorSweepingComplete(entityCache); + this.second.logGarbageCollectorSweepingComplete(entityCache); + } + + @Override + public void logGarbageCollectorNotNeeded() + { + this.first.logGarbageCollectorNotNeeded(); + this.second.logGarbageCollectorNotNeeded(); + } + + @Override + public void logGarbageCollectorCompletedHotPhase(final long gcHotGeneration, final long lastGcHotCompletion) + { + this.first.logGarbageCollectorCompletedHotPhase(gcHotGeneration, lastGcHotCompletion); + this.second.logGarbageCollectorCompletedHotPhase(gcHotGeneration, lastGcHotCompletion); + } + + @Override + public void logGarbageCollectorCompleted(final long gcColdGeneration, final long lastGcColdCompletion) + { + this.first.logGarbageCollectorCompleted(gcColdGeneration, lastGcColdCompletion); + this.second.logGarbageCollectorCompleted(gcColdGeneration, lastGcColdCompletion); + } + + @Override + public void logGarbageCollectorEncounteredZombieObjectId(final long objectId) + { + this.first.logGarbageCollectorEncounteredZombieObjectId(objectId); + this.second.logGarbageCollectorEncounteredZombieObjectId(objectId); + } + + } + } diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFoundation.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFoundation.java index 061ce99e..9556a5ac 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFoundation.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFoundation.java @@ -14,6 +14,8 @@ * #L% */ +import static org.eclipse.serializer.util.X.notNull; + import java.nio.ByteOrder; import org.eclipse.serializer.exceptions.MissingFoundationPartException; @@ -800,8 +802,18 @@ public interface StorageFoundation> extends Insta */ public F setExceptionHandler(StorageExceptionHandler exceptionHandler); + /** + * Use {@link #addEventLogger(StorageEventLogger)} instead, multiple event loggers are supported now + * + * @deprecated replaced by {@link #addEventLogger(StorageEventLogger)} + */ + @Deprecated + public default F setEventLogger(final StorageEventLogger eventLogger) + { + return this.addEventLogger(eventLogger); + } - public F setEventLogger(StorageEventLogger eventLogger); + public F addEventLogger(StorageEventLogger eventLogger); public F setWriteController(StorageWriteController writeController); @@ -1767,9 +1779,14 @@ public F setExceptionHandler(final StorageExceptionHandler exceptionHandler) } @Override - public F setEventLogger(final StorageEventLogger eventLogger) + public F addEventLogger(final StorageEventLogger eventLogger) { - this.eventLogger = eventLogger; + notNull(eventLogger); + + this.eventLogger = this.eventLogger != null + ? StorageEventLogger.Chain(this.eventLogger, eventLogger) + : eventLogger + ; return this.$(); } diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageHousekeepingController.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageHousekeepingController.java index 17bf5045..6f81d875 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageHousekeepingController.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageHousekeepingController.java @@ -14,7 +14,12 @@ * #L% */ +import static org.eclipse.serializer.math.XMath.positive; +import static org.eclipse.serializer.util.X.notNull; + import org.eclipse.serializer.chars.VarString; +import org.eclipse.serializer.util.logging.Logging; +import org.slf4j.Logger; public interface StorageHousekeepingController { @@ -238,4 +243,328 @@ public String toString() } + + /** + * Pseudo-constructor method to create a new adaptive {@link StorageHousekeepingController} instance + * using the passed values. + *

+ * It will wrap a {@link StorageHousekeepingController} with default values and increase the time budgets on demand, + * if the garbage collector needs more time to reach the sweeping phase. + * + * @see #New() + * + * @param increaseThresholdMs the threshold in milliseconds of the adaption cycle to calculate new budgets for the housekeeping process + * @param increaseAmountNs the amount in nanoseconds the budgets will be increased each cycle + * @param maximumTimeBudgetNs the upper limit of the time budgets in nanoseconds + * @param foundation the {@link StorageFoundation} the controller is created for + * @return a new {@link StorageHousekeepingController} instance. + */ + public static StorageHousekeepingController Adaptive( + final long increaseThresholdMs, + final long increaseAmountNs , + final long maximumTimeBudgetNs, + final StorageFoundation foundation + ) + { + return Adaptive( + StorageHousekeepingController.New(), + increaseThresholdMs , + increaseAmountNs , + maximumTimeBudgetNs , + foundation + ); + } + + /** + * Pseudo-constructor method to create a new adaptive {@link StorageHousekeepingController} instance + * using the passed values. + *

+ * It will wrap the given {@link StorageHousekeepingController} and increase the time budgets on demand, + * if the garbage collector needs more time to reach the sweeping phase. + * + * @see #New(long, long) + * + * @param delegate the wrapped controller delivering the original budget values + * @param increaseThresholdMs the threshold in milliseconds of the adaption cycle to calculate new budgets for the housekeeping process + * @param increaseAmountNs the amount in nanoseconds the budgets will be increased each cycle + * @param maximumTimeBudgetNs the upper limit of the time budgets in nanoseconds + * @param foundation the {@link StorageFoundation} the controller is created for + * @return a new {@link StorageHousekeepingController} instance. + */ + public static StorageHousekeepingController Adaptive( + final StorageHousekeepingController delegate , + final long increaseThresholdMs, + final long increaseAmountNs , + final long maximumTimeBudgetNs, + final StorageFoundation foundation + ) + { + final StorageHousekeepingController.Adaptive controller = new StorageHousekeepingController.Adaptive( + notNull (delegate ), + positive(increaseThresholdMs), + positive(increaseAmountNs ), + positive(maximumTimeBudgetNs) + ); + foundation.addEventLogger(controller); + return controller; + } + + /** + * Pseudo-constructor method to create a new adaptive {@link StorageHousekeepingController} builder. + * It will wrap a {@link StorageHousekeepingController} with default values. + * + * @return a new {@link AdaptiveBuilder} instance + */ + public static AdaptiveBuilder AdaptiveBuilder() + { + return AdaptiveBuilder(StorageHousekeepingController.New()); + } + + /** + * Pseudo-constructor method to create a new adaptive {@link StorageHousekeepingController} builder. + * It will wrap the given {@link StorageHousekeepingController}. + * + * @param delegate the wrapped controller delivering the original budget values + * @return a new {@link AdaptiveBuilder} instance + */ + public static AdaptiveBuilder AdaptiveBuilder(final StorageHousekeepingController delegate) + { + return new AdaptiveBuilder.Default( + notNull(delegate) + ); + } + + /** + * Builder type for an adaptive {@link StorageHousekeepingController} + * + */ + public interface AdaptiveBuilder + { + /** + * @param increaseThresholdMs the threshold in milliseconds of the adaption cycle to calculate new budgets for the housekeeping process + * @return this builder instance + */ + public AdaptiveBuilder increaseThresholdMs(long increaseThresholdMs); + + /** + * + * @param increaseAmountNs the amount in nanoseconds the budgets will be increased each cycle + * @return this builder instance + */ + public AdaptiveBuilder increaseAmountNs(long increaseAmountNs); + + /** + * + * @param maximumTimeBudgetNs the upper limit of the time budgets in nanoseconds + * @return this builder instance + */ + public AdaptiveBuilder maximumTimeBudgetNs(long maximumTimeBudgetNs); + + /** + * Builds the {@link StorageHousekeepingController} instance given the provided values. + * + * @param foundation the {@link StorageFoundation} the controller should be created for + * @return a new {@link StorageHousekeepingController} instance + */ + public StorageHousekeepingController buildFor(final StorageFoundation foundation); + + + public static class Default implements AdaptiveBuilder + { + private final StorageHousekeepingController delegate ; + private long increaseThresholdMs = Adaptive.Defaults.defaultAdaptiveHousekeepingIncreaseThresholdMs(); + private long increaseAmountNs = Adaptive.Defaults.defaultAdaptiveHousekeepingIncreaseAmountNs (); + private long maximumTimeBudgetNs = Adaptive.Defaults.defaultAdaptiveHousekeepingMaximumTimeBudgetNs(); + + Default(final StorageHousekeepingController delegate) + { + super(); + this.delegate = delegate; + } + + @Override + public AdaptiveBuilder increaseThresholdMs(final long increaseThresholdMs) + { + this.increaseThresholdMs = increaseThresholdMs; + return this; + } + + @Override + public AdaptiveBuilder increaseAmountNs(final long increaseAmountNs) + { + this.increaseAmountNs = increaseAmountNs; + return this; + } + + @Override + public AdaptiveBuilder maximumTimeBudgetNs(final long maximumTimeBudgetNs) + { + this.maximumTimeBudgetNs = maximumTimeBudgetNs; + return this; + } + + @Override + public StorageHousekeepingController buildFor(final StorageFoundation foundation) + { + final StorageHousekeepingController.Adaptive controller = new StorageHousekeepingController.Adaptive( + this.delegate , + this.increaseThresholdMs, + this.increaseAmountNs , + this.maximumTimeBudgetNs + ); + foundation.addEventLogger(controller); + return controller; + } + + } + + } + + + public final class Adaptive implements StorageHousekeepingController, StorageEventLogger + { + public interface Defaults + { + public static long defaultAdaptiveHousekeepingIncreaseThresholdMs() + { + return 5000; // 5 seconds + } + + public static long defaultAdaptiveHousekeepingIncreaseAmountNs() + { + return 50_000_000; // 50 ms + } + + public static long defaultAdaptiveHousekeepingMaximumTimeBudgetNs() + { + return 500_000_000; // half second + } + } + + + private final static Logger logger = Logging.getLogger(Adaptive.class); + + + /////////////////////////////////////////////////////////////////////////// + // instance fields // + //////////////////// + + private final StorageHousekeepingController delegate ; + private final long increaseThresholdMs; + private final long increaseAmountNs ; + private final long maximumTimeBudgetNs; + + // mutable adaptive state + + private long lastFinishedGCCycle = 0; + private long lastIncrease = 0; + private long currentIncreaseNs = 0; + + /////////////////////////////////////////////////////////////////////////// + // constructors // + ///////////////// + + Adaptive( + final StorageHousekeepingController delegate , + final long increaseThresholdMs, + final long increaseAmountNs , + final long maximumNsTimeBudget + ) + { + super(); + this.delegate = delegate ; + this.increaseThresholdMs = increaseThresholdMs; + this.increaseAmountNs = increaseAmountNs ; + this.maximumTimeBudgetNs = maximumNsTimeBudget; + } + + + /////////////////////////////////////////////////////////////////////////// + // methods // + //////////// + + private synchronized void reset() + { + this.lastFinishedGCCycle = this.lastIncrease = System.currentTimeMillis(); + this.internalSetIncrease(0); + } + + private synchronized long increaseNs() + { + final long now = System.currentTimeMillis(); + if( now - this.increaseThresholdMs > this.lastFinishedGCCycle + && (this.lastIncrease <= 0 || now - this.lastIncrease > this.increaseThresholdMs) + ) + { + this.lastIncrease = now; + this.internalSetIncrease(this.currentIncreaseNs + this.increaseAmountNs); + } + return this.currentIncreaseNs; + } + + private void internalSetIncrease(final long increaseNs) + { + this.currentIncreaseNs = Math.min( + this.maximumTimeBudgetNs, + increaseNs + ); + logger.debug("Housekeeping time budgets increased by {} ns", String.format("%,d", this.currentIncreaseNs)); + } + + @Override + public long housekeepingIntervalMs() + { + return this.delegate.housekeepingIntervalMs(); + } + + @Override + public long housekeepingTimeBudgetNs() + { + return Math.min( + this.maximumTimeBudgetNs, + this.delegate.housekeepingTimeBudgetNs() + this.increaseNs() + ); + } + + @Override + public long garbageCollectionTimeBudgetNs() + { + return Math.min( + this.maximumTimeBudgetNs, + this.delegate.garbageCollectionTimeBudgetNs() + this.increaseNs() + ); + } + + @Override + public long liveCheckTimeBudgetNs() + { + return Math.min( + this.maximumTimeBudgetNs, + this.delegate.liveCheckTimeBudgetNs() + this.increaseNs() + ); + } + + @Override + public long fileCheckTimeBudgetNs() + { + return Math.min( + this.maximumTimeBudgetNs, + this.delegate.fileCheckTimeBudgetNs() + this.increaseNs() + ); + } + + @Override + public void logGarbageCollectorNotNeeded() + { + this.reset(); + } + + @Override + public void logGarbageCollectorSweepingComplete(final StorageEntityCache entityCache) + { + this.reset(); + } + + } + } From 55e7c72e73af5ceb01c17104a13c9abbb776a070 Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Fri, 1 Dec 2023 12:48:26 +0100 Subject: [PATCH 017/126] migration of improved gc #642 feature (#80) see https://github.com/microstream-one/microstream/pull/642 --- .../java/org/eclipse/store/storage/types/StorageConnection.java | 1 + .../org/eclipse/store/storage/types/StorageEntityCache.java | 2 ++ 2 files changed, 3 insertions(+) diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageConnection.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageConnection.java index fcad9268..911474d1 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageConnection.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageConnection.java @@ -502,6 +502,7 @@ public final boolean issueGarbageCollection(final long nanoTimeBudget) try { // a time budget <= 0 will effectively be a cheap query for the completion state. + this.persistenceManager().objectRegistry().consolidate(); return this.connectionRequestAcceptor.issueGarbageCollection(nanoTimeBudget); } catch(final InterruptedException e) diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageEntityCache.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageEntityCache.java index 03e66b58..1612f183 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageEntityCache.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageEntityCache.java @@ -1356,6 +1356,8 @@ public final boolean issuedGarbageCollection( { return true; } + + this.markMonitor.resetCompletion(); // check time budget first for explicitly issued calls. performGC: From 3b18a67c6f59c772ba9ccac2f869040ad81503f1 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Mon, 4 Dec 2023 14:12:37 +0100 Subject: [PATCH 018/126] add javadoc check --- .github/workflows/maven_javadoc.yml | 28 ++++++++++++++++++++++++++++ pom.xml | 22 ++++++++++++++++++---- 2 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/maven_javadoc.yml diff --git a/.github/workflows/maven_javadoc.yml b/.github/workflows/maven_javadoc.yml new file mode 100644 index 00000000..795d623f --- /dev/null +++ b/.github/workflows/maven_javadoc.yml @@ -0,0 +1,28 @@ +# This workflow will build a Java project with Maven +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven + +name: Javadoc check + +on: + push: + branches: + - '*' + pull_request: + branches: [ main ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + #Build with java 11 + - uses: actions/checkout@v3 + - name: Set up JDK 11 + uses: actions/setup-java@v3 + with: + java-version: '11' + distribution: 'temurin' + cache: 'maven' + - name: Build with Maven + run: mvn -P examples -P javadoc-check -B package --file pom.xml -U diff --git a/pom.xml b/pom.xml index 81177528..f8badc4e 100644 --- a/pom.xml +++ b/pom.xml @@ -16,9 +16,9 @@ https://projects.eclipse.org/projects/technology.store - MicroStream Software - https://microstream.one - + MicroStream Software + https://microstream.one + @@ -224,7 +224,7 @@ 3.5.0 none - false + ${javadoc.failed.on.error} true 8 Eclipse Store API @@ -470,6 +470,20 @@ + + javadoc-check + + true + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + + From c46edfac7086aa711015a65c3b2c857c958b9088 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 5 Dec 2023 14:25:43 +0100 Subject: [PATCH 019/126] add transaction-file-converter profile to build transaction-file-converter --- pom.xml | 5 +++++ storage/storage/pom.xml | 46 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/pom.xml b/pom.xml index f8badc4e..8d3b3366 100644 --- a/pom.xml +++ b/pom.xml @@ -162,6 +162,11 @@ maven-dependency-plugin 3.6.0 + + org.apache.maven.plugins + maven-shade-plugin + 3.5.0 + org.apache.felix maven-bundle-plugin diff --git a/storage/storage/pom.xml b/storage/storage/pom.xml index aa90f791..66fe9b11 100644 --- a/storage/storage/pom.xml +++ b/storage/storage/pom.xml @@ -31,5 +31,51 @@ ${eclipse.serializer.version} + + + + + transaction-file-converter + + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + true + transaction-file-converter + + + + org.eclipse.store.storage.util.MainUtilTransactionFileConverter + + + + + + *:* + + META-INF/Microstream-Sbom.json + META-INF/Microstream-Sbom.xml + META-INF/MANIFEST.MF + LICENSE + module-info.class + + + + + + + + + + + From d7f0bb4c3ce053515858b08bb45212b0e3828861 Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Wed, 6 Dec 2023 09:25:06 +0100 Subject: [PATCH 020/126] migration feature time stamp provider monotonic #643 (#81) see https://github.com/microstream-one/microstream/pull/643 --- .../types/StorageChannelTaskInitialize.java | 20 ++++ .../storage/types/StorageFoundation.java | 2 +- .../store/storage/types/StorageSystem.java | 2 + .../types/StorageTimestampProvider.java | 100 ++++++++++++++++++ .../types/StorageTransactionsAnalysis.java | 31 +++++- 5 files changed, 152 insertions(+), 3 deletions(-) diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannelTaskInitialize.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannelTaskInitialize.java index a69abae6..92bdd16f 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannelTaskInitialize.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannelTaskInitialize.java @@ -16,6 +16,9 @@ import static org.eclipse.serializer.util.X.notNull; +import java.util.Objects; +import java.util.stream.Stream; + import org.eclipse.serializer.collections.EqHashEnum; import org.eclipse.serializer.collections.XSort; import org.eclipse.serializer.persistence.types.Persistence; @@ -25,6 +28,7 @@ public interface StorageChannelTaskInitialize extends StorageChannelTask { public StorageIdAnalysis idAnalysis(); + public long latestTimestamp(); public final class Default @@ -40,6 +44,7 @@ public final class Default private Long consistentStoreTimestamp ; private Long commonTaskHeadFileTimestamp; + private Long latestTimestamp ; private long maxEntityObjectOid ; private long maxEntityConstantOid; @@ -200,6 +205,15 @@ protected final void succeed(final StorageChannel channel, final StorageInventor this.updateIdAnalysis(idAnalysis); + //Some storage targets like SQL will create "files" only if there is some data written. + //The transactionsFileAnalysis may be null if a new storage has been created + //and the transactions log is empty. + this.latestTimestamp = Stream.of(result) + .filter( r -> Objects.nonNull(r.transactionsFileAnalysis())) + .mapToLong( r -> r.transactionsFileAnalysis().maxTimestamp()) + .max() + .orElse(0L); + this.operationController.activate(); } @@ -221,6 +235,12 @@ public synchronized StorageIdAnalysis idAnalysis() ); } + @Override + public long latestTimestamp() + { + return this.latestTimestamp; + } + } } diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFoundation.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFoundation.java index 9556a5ac..ccd4aee7 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFoundation.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFoundation.java @@ -1034,7 +1034,7 @@ protected StorageRootTypeIdProvider ensureRootTypeIdProvider() protected StorageTimestampProvider ensureTimestampProvider() { - return new StorageTimestampProvider.Default(); + return new StorageTimestampProvider.MonotonicTime(); } protected StorageObjectIdRangeEvaluator ensureObjectIdRangeEvaluator() diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageSystem.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageSystem.java index b8ba4927..7b944d3b 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageSystem.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageSystem.java @@ -328,6 +328,8 @@ private StorageIdAnalysis startThreads(final StorageChannelTaskInitialize initia } initializingTask.waitOnCompletion(); } + + this.timestampProvider.set(initializingTask.latestTimestamp()); return initializingTask.idAnalysis(); } diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageTimestampProvider.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageTimestampProvider.java index 2070182f..a8dea640 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageTimestampProvider.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageTimestampProvider.java @@ -1,5 +1,7 @@ package org.eclipse.store.storage.types; +import java.util.concurrent.atomic.AtomicLong; + /*- * #%L * EclipseStore Storage @@ -24,6 +26,15 @@ public interface StorageTimestampProvider */ public long currentNanoTimestamp(); + /** + * Set the base value used to create the timestamps + * Implementations are allowed to ignore it. + * + * @param base base value for timestamp creation. + * @return base value for timestamp creation. + */ + public long set(long base); + public final class Default implements StorageTimestampProvider { @@ -45,5 +56,94 @@ public synchronized long currentNanoTimestamp() return Storage.millisecondsToNanoseconds(this.lastTimeMillis = currentTimeMillis); } + + /** + * This implementation ignores the offset. + * + * @param offset ignored by this implementation. + * @return always zero. + */ + @Override + public long set(final long offset) + { + return 0; + } + + } + + /** + * Returns a timestamp based upon the current system time. + * If the current system time is less or equal to the last returned value + * the last returned timestamp plus 1 nanosecond will be returned to archive + * a strictly monotone behavior. + */ + public final class MonotonicTime implements StorageTimestampProvider + { + private long lastTimeNanos; + + /** + * Returns a timestamp based upon the current system time. + * If the current system time is less or equal to the last returned value + * the last returned timestamp plus 1 nanosecond will be returned to archive + * a strictly monotone behavior. + */ + @Override + public synchronized long currentNanoTimestamp() + { + final long currentTimeNanos = Storage.millisecondsToNanoseconds(System.currentTimeMillis()); + + if(currentTimeNanos <= this.lastTimeNanos) + { + return ++this.lastTimeNanos; + } + return this.lastTimeNanos = currentTimeNanos; + } + + /** + * Set to new base value only if the new value is larger then the current one. + */ + @Override + public synchronized long set(final long timeNs) + { + if(timeNs > this.lastTimeNanos) + { + this.lastTimeNanos = timeNs; + } + return this.lastTimeNanos; + } + } + + /** + * An implementation of {@link StorageTimestampProvider} that provides an strictly monotonic increasing + * long value instead of a time value. This implementation does not rely on any time based value + * that might be affected by changes of the system clock. + * + */ + public final class MonotonicCounter implements StorageTimestampProvider + { + private final AtomicLong lastValue = new AtomicLong(); + + /** + * Provides an strictly monotonic increasing + * long value starting from the set base value {@link #set(long)} instead of a time based value. + * + * @return a strictly monotone increasing long value. + */ + @Override + public long currentNanoTimestamp() + { + return this.lastValue.incrementAndGet(); + } + + /** + * Set to new base value only if the new value is larger then the current one. + */ + @Override + public long set(final long base) + { + return this.lastValue.updateAndGet((v) -> (base > v) ? base : v); + } + } + } diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageTransactionsAnalysis.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageTransactionsAnalysis.java index c8758602..92c153cd 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageTransactionsAnalysis.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageTransactionsAnalysis.java @@ -46,6 +46,8 @@ public interface StorageTransactionsAnalysis public long headFileLatestTimestamp(); + public long maxTimestamp(); + public StorageLiveTransactionsFile transactionsFile(); public XGettingTable transactionsFileEntries(); @@ -465,6 +467,7 @@ public static XGettingSequence header() "Type" , "Timestamp" , "Time Delta (ms)" , + "Timestamp(long)" , "Resulting Length" , "Length Change" , "Current Head File", @@ -541,6 +544,7 @@ private void addCommonTimestampPart(final long address) this.vs .add(formateTimeStamp(new Date(Storage.millisecondsToSeconds(timestamp)))).tab() .add(Storage.millisecondsToSeconds(timestamp - this.lastTimestamp)).tab() + .add(timestamp).tab() ; this.lastTimestamp = timestamp; @@ -670,6 +674,7 @@ public final class EntryAggregator implements EntryIterator private long lastConsistentStoreTimestamp; private long currentStoreLength ; private long currentStoreTimestamp ; + private long maxTimeStamp; private long currentFileNumber = -1; @@ -729,6 +734,7 @@ private boolean handleEntryFileCreation(final long address, final long available } // timestamp is intentionally ignored as file creation happens AFTER a store has been issued. + this.updateMaxTimestamp(Logic.getEntryTimestamp(address)); // entry is consistent, register completed file and reset values for new file. this.registerCurrentFile(); @@ -773,6 +779,7 @@ private boolean handleEntryStore(final long address, final long availableItemLen } final long timestamp = Logic.getEntryTimestamp(address); + this.updateMaxTimestamp(timestamp); if(timestamp <= this.currentStoreTimestamp) { throw new StorageExceptionConsistency( @@ -804,6 +811,8 @@ private boolean handleEntryTransfer(final long address, final long availableItem ); } + this.updateMaxTimestamp(Logic.getEntryTimestamp(address)); + /* lastConsistentStoreTimestamp is not updated to associate the new file length with the old timestamp * i.e. when an inter-channel rollback has to occur, the transfer part is not rolled back, as it is * channel-local @@ -848,6 +857,7 @@ private boolean handleEntryFileTruncation(final long address, final long availab ); } + this.updateMaxTimestamp(Logic.getEntryTimestamp(address)); this.lastConsistentStoreLength = this.currentStoreLength = newLength; return true; @@ -868,6 +878,8 @@ private boolean handleEntryFileDeletion(final long address, final long available } file.isDeleted = true; + this.updateMaxTimestamp(Logic.getEntryTimestamp(address)); + return true; } @@ -882,9 +894,15 @@ final StorageTransactionsAnalysis yield(final StorageLiveTransactionsFile transa this.lastConsistentStoreLength , this.lastConsistentStoreTimestamp, this.currentStoreLength , - this.currentStoreTimestamp + this.currentStoreTimestamp , + this.maxTimeStamp ); } + + private void updateMaxTimestamp(final long timestamp) + { + this.maxTimeStamp = Math.max(this.maxTimeStamp, timestamp); + } } @@ -902,6 +920,7 @@ public final class Default implements StorageTransactionsAnalysis private final long headFileLastConsistentStoreTimestamp; private final long headFileLatestLength ; private final long headFileLatestTimestamp ; + private final long maxTimestamp ; @@ -915,7 +934,8 @@ public final class Default implements StorageTransactionsAnalysis final long headFileLastConsistentStoreLength , final long headFileLastConsistentStoreTimestamp, final long headFileLatestLength , - final long headFileLatestTimestamp + final long headFileLatestTimestamp , + final long maxTimestamp ) { super(); @@ -925,6 +945,7 @@ public final class Default implements StorageTransactionsAnalysis this.headFileLastConsistentStoreTimestamp = headFileLastConsistentStoreTimestamp; this.headFileLatestLength = headFileLatestLength ; this.headFileLatestTimestamp = headFileLatestTimestamp ; + this.maxTimestamp = maxTimestamp ; } @@ -968,6 +989,12 @@ public final long headFileLatestTimestamp() { return this.headFileLatestTimestamp; } + + @Override + public final long maxTimestamp() + { + return this.maxTimestamp; + } } From 22f84645eb788fe966680fc0d9d9ef095bd664a9 Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Wed, 6 Dec 2023 09:31:47 +0100 Subject: [PATCH 021/126] Migration of feature "transaction file housekeeping" #645 (#85) see https://github.com/microstream-one/microstream/pull/645 --- .../pages/configuration/properties.adoc | 19 + .../EmbeddedStorageConfigurationBuilder.java | 20 +- ...ddedStorageConfigurationPropertyNames.java | 5 + ...geFoundationCreatorConfigurationBased.java | 5 +- .../types/EmbeddedStorageManager.java | 8 +- .../eclipse/store/storage/types/Storage.java | 57 ++- .../storage/types/StorageBackupItemQueue.java | 123 ++++-- .../store/storage/types/StorageChannel.java | 27 ++ .../storage/types/StorageConnection.java | 24 + .../types/StorageDataFileEvaluator.java | 232 +++++++--- .../storage/types/StorageFileManager.java | 33 +- .../types/StorageHousekeepingBroker.java | 13 + .../types/StorageHousekeepingExecutor.java | 2 + .../storage/types/StorageRequestAcceptor.java | 10 + .../types/StorageRequestTaskCreator.java | 17 + ...rageRequestTaskTransactionsLogCleanup.java | 67 +++ .../storage/types/StorageTaskBroker.java | 15 + .../types/StorageTransactionsFileCleaner.java | 410 ++++++++++++++++++ 18 files changed, 972 insertions(+), 115 deletions(-) create mode 100644 storage/storage/src/main/java/org/eclipse/store/storage/types/StorageRequestTaskTransactionsLogCleanup.java create mode 100644 storage/storage/src/main/java/org/eclipse/store/storage/types/StorageTransactionsFileCleaner.java diff --git a/docs/modules/storage/pages/configuration/properties.adoc b/docs/modules/storage/pages/configuration/properties.adoc index 1f8053c9..bca89a47 100644 --- a/docs/modules/storage/pages/configuration/properties.adoc +++ b/docs/modules/storage/pages/configuration/properties.adoc @@ -88,6 +88,10 @@ They can be found as constants in `EmbeddedStorageConfigurationPropertyNames`. |data-file-cleanup-head-file |A flag defining whether the current head file (the only file actively written to) shall be subjected to file cleanups as well. + +|xref:#transaction-file-maximum-size[transaction-file-maximum-size] +Maximum file size for each channels transactions log file. If this limit is exceeded the file wile be cleaned up during housekeeping. Default is 100 MiB. +Maximum value is 1 GiB. |=== @@ -165,6 +169,18 @@ The ratio (value in ]0.0;1.0]) of non-gap data contained in a storage file to pr "Gap" data is anything that is not the latest version of an entity's data, including older versions of an entity and "comment" bytes (a sequence of bytes beginning with its length as a negative value length header). The closer this value is to 1.0 (100%), the less disk space is occupied by storage files, but the more file dissolving (data transfers to new files) is required and vice versa. +[#transaction-file-maximum-size] +=== transaction-file-maximum-size +Maximum file size for each channels transactions log file. If this limit is exceeded the file wile be cleaned up during housekeeping. + +To shrink the file size all store, transfer, and truncation entries are combined into one single store entry +for each storage files. FileCreation entries are kept, FileDeletion entries are kept +if the storage data file still exists on the file system. Otherwise all entries related +to deleted files are removed if the storage data file does no more exist. + +Default is 100 MB. +Maximum value is 1 GB. + == Involved Types This list shows which property configures which type, used by the foundation types, to create the storage manager. @@ -242,4 +258,7 @@ This list shows which property configures which type, used by the foundation typ | data-file-cleanup-head-file | `StorageDataFileEvaluator` + +| transaction-file-maximum-size +| `StorageDataFileEvaluator` |=== diff --git a/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageConfigurationBuilder.java b/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageConfigurationBuilder.java index 0b8fe92e..2ac3439c 100644 --- a/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageConfigurationBuilder.java +++ b/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageConfigurationBuilder.java @@ -19,13 +19,13 @@ import java.io.File; import java.time.Duration; -import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; -import org.eclipse.store.storage.types.StorageEntityCacheEvaluator; import org.eclipse.serializer.collections.types.XGettingCollection; import org.eclipse.serializer.configuration.types.ByteSize; import org.eclipse.serializer.configuration.types.Configuration; import org.eclipse.serializer.configuration.types.ConfigurationValueMapperProvider; import org.eclipse.serializer.typing.KeyValue; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; +import org.eclipse.store.storage.types.StorageEntityCacheEvaluator; /** @@ -312,6 +312,14 @@ public default EmbeddedStorageConfigurationBuilder setBackupDirectoryInUserHome( */ public EmbeddedStorageConfigurationBuilder setDataFileCleanupHeadFile(boolean dataFileCleanupHeadFile); + /** + * Maximum file size for a transaction file to avoid cleaning it up. Default is 1 GiB. + * + * @param transactionFileMaximumSize the new maximum file size + * @return this + */ + public EmbeddedStorageConfigurationBuilder setTransactionFileMaximumSize(ByteSize transactionFileMaximumSize); + /** * Creates an {@link EmbeddedStorageFoundation} based on the settings of this builder. * @@ -630,6 +638,14 @@ public EmbeddedStorageConfigurationBuilder setDataFileCleanupHeadFile( return this.set(DATA_FILE_CLEANUP_HEAD_FILE, Boolean.toString(dataFileCleanupHeadFile)); } + @Override + public EmbeddedStorageConfigurationBuilder setTransactionFileMaximumSize( + final ByteSize transactionFileMaximumSize + ) + { + return this.set(TRANSACTION_FILE_MAXIMUM_SIZE, transactionFileMaximumSize.toString()); + } + } } diff --git a/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageConfigurationPropertyNames.java b/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageConfigurationPropertyNames.java index 5003e0c2..2d2ba944 100644 --- a/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageConfigurationPropertyNames.java +++ b/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageConfigurationPropertyNames.java @@ -146,6 +146,11 @@ public interface EmbeddedStorageConfigurationPropertyNames * @see EmbeddedStorageConfigurationBuilder#setDataFileMinimumUseRatio(double) */ public final static String DATA_FILE_MINIMUM_USE_RATIO = "data-file-minimum-use-ratio"; + + /** + * @see EmbeddedStorageConfigurationBuilder#setTransactionFileMaximumSize(ByteSize) + */ + public final static String TRANSACTION_FILE_MAXIMUM_SIZE = "transaction-file-maximum-size"; /** * @see EmbeddedStorageConfigurationBuilder#setDataFileCleanupHeadFile(boolean) diff --git a/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageFoundationCreatorConfigurationBased.java b/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageFoundationCreatorConfigurationBased.java index d638a572..99bf0fe9 100644 --- a/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageFoundationCreatorConfigurationBased.java +++ b/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageFoundationCreatorConfigurationBased.java @@ -253,7 +253,10 @@ private StorageDataFileEvaluator createDataFileEvaluator() this.configuration.optDouble(DATA_FILE_MINIMUM_USE_RATIO) .orElse(StorageDataFileEvaluator.Defaults.defaultMinimumUseRatio()), this.configuration.optBoolean(DATA_FILE_CLEANUP_HEAD_FILE) - .orElse(StorageDataFileEvaluator.Defaults.defaultResolveHeadfile()) + .orElse(StorageDataFileEvaluator.Defaults.defaultResolveHeadfile()), + this.configuration.opt(TRANSACTION_FILE_MAXIMUM_SIZE, ByteSize.class) + .map(byteSize -> (int)byteSize.bytes()) + .orElse(StorageDataFileEvaluator.Defaults.defaultTransactionFileMaximumSize()) ); } diff --git a/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageManager.java b/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageManager.java index b6bfbf77..f87da3b1 100644 --- a/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageManager.java +++ b/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageManager.java @@ -326,7 +326,7 @@ private void synchronizeRoots(final PersistenceRoots loadedRoots) private void ensureRequiredTypeHandlers() { - // make sure a functional type handler is present for every occuring type id or throw an exception. + // make sure a functional type handler is present for every occurring type id or throw an exception. final StorageIdAnalysis idAnalysis = this.storageSystem.initializationIdAnalysis(); final XGettingEnum occuringTypeIds = idAnalysis.occuringTypeIds(); this.connectionFoundation.getTypeHandlerManager().ensureTypeHandlersByTypeIds(occuringTypeIds); @@ -517,6 +517,12 @@ public final void issueFullBackup( this.singletonConnection().issueFullBackup(targetFileProvider, typeDictionaryExporter); } + @Override + public void issueTransactionsLogCleanup() + { + this.singletonConnection().issueTransactionsLogCleanup(); + } + @Override public final StorageRawFileStatistics createStorageStatistics() { diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/Storage.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/Storage.java index 1bd26ce5..2d0fa012 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/Storage.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/Storage.java @@ -465,7 +465,7 @@ public static final StorageDataFileEvaluator DataFileEvaluator( * * @param minimumUseRatio the ratio (value in ]0.0;1.0]) of non-gap data contained in a storage file to prevent * the file from being dissolved. "Gap" data is anything that is not the latest version of an entity's data, - * inluding older versions of an entity and "comment" bytes (a sequence of bytes beginning with its length + * Including older versions of an entity and "comment" bytes (a sequence of bytes beginning with its length * as a negative value length header).
* The closer this value is to 1.0 (100%), the less disk space is occupied by storage files, but the more * file dissolving (data transfers to new files) is required and vice versa. @@ -506,7 +506,7 @@ public static final StorageDataFileEvaluator DataFileEvaluator( * The closer this value is to 1.0 (100%), the less disk space is occupied by storage files, but the more * file dissolving (data transfers to new files) is required and vice versa. * - * @param cleanUpHeadFile a flag defining wether the current head file (the only file actively written to) + * @param cleanUpHeadFile a flag defining whether the current head file (the only file actively written to) * shall be subjected to file cleanups as well. * * @return a new {@link StorageDataFileEvaluator} instance. @@ -526,6 +526,59 @@ public static final StorageDataFileEvaluator DataFileEvaluator( return StorageDataFileEvaluator.New(fileMinimumSize, fileMaximumSize, minimumUseRatio, cleanUpHeadFile); } + /** + * Creates a new {@link StorageDataFileEvaluator}. + *

+ * For a detailed explanation see {@link StorageDataFileEvaluator#New(int, int, double, boolean)}. + * + * @param fileMinimumSize the minimum file size in bytes that a single storage file must have. Smaller files + * will be dissolved. + * + * @param fileMaximumSize the maximum file size in bytes that a single storage file may have. Larger files + * will be dissolved.
+ * Note that a file can exceed this limit if it contains a single entity that already exceeds the limit. + * E.g. an int array with 10 million elements would be about 40 MB in size and would exceed a file size + * limit of, for example, 30 MB. + * + * @param minimumUseRatio the ratio (value in ]0.0;1.0]) of non-gap data contained in a storage file to prevent + * the file from being dissolved. "Gap" data is anything that is not the latest version of an entity's data, + * including older versions of an entity and "comment" bytes (a sequence of bytes beginning with its length + * as a negative value length header).
+ * The closer this value is to 1.0 (100%), the less disk space is occupied by storage files, but the more + * file dissolving (data transfers to new files) is required and vice versa. + * + * @param cleanUpHeadFile a flag defining whether the current head file (the only file actively written to) + * shall be subjected to file cleanups as well. + * + * @param transactionFileMaximumSize the maximum file size for transaction files. Lager files will + * be deleted and a new one will be created.
+ * Note that the max file size should be smaller than the technical limit of 2 GB (Integer.MAX_VALUE) + * to allow more appends without exceeding the limit until housekeeping will create a new one. + * + * @return a new {@link StorageDataFileEvaluator} instance. + * + * @see Storage#DataFileEvaluator() + * @see Storage#DataFileEvaluator(int, int) + * @see Storage#DataFileEvaluator(int, int, double) + * @see StorageDataFileEvaluator#New(int, int, double, boolean) + */ + public static final StorageDataFileEvaluator DataFileEvaluator( + final int fileMinimumSize, + final int fileMaximumSize, + final double minimumUseRatio, + final boolean cleanUpHeadFile, + final int transactionFileMaximumSize + ) + { + return StorageDataFileEvaluator.New( + fileMinimumSize, + fileMaximumSize, + minimumUseRatio, + cleanUpHeadFile, + transactionFileMaximumSize + ); + } + /** * Creates a new {@link StorageBackupSetup}. *

diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageBackupItemQueue.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageBackupItemQueue.java index b29cd93e..0fa86cb4 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageBackupItemQueue.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageBackupItemQueue.java @@ -31,7 +31,7 @@ public final class Default implements StorageBackupItemQueue // instance fields // //////////////////// - private final Item head = new Item(null, 0, 0); + private final Item head = new Item(null); private Item tail = this.head; @@ -64,7 +64,7 @@ public final void enqueueCopyingItem( final long length ) { - this.internalEnqueueItem(sourceFile, sourcePosition, length); + this.internalEnqueueItem(new CopyItem(sourceFile, sourcePosition, length)); } @Override @@ -73,8 +73,8 @@ public final void enqueueTruncatingItem( final long newLength ) { - // signalling with a null sourceFile is a hack to avoid the complexity of multiple Item classes - this.internalEnqueueItem(file, newLength, -1); + // Signaling with a null sourceFile is a hack to avoid the complexity of multiple Item classes + this.internalEnqueueItem(new TruncationItem(file, newLength)); } @Override @@ -82,22 +82,20 @@ public void enqueueDeletionItem( final StorageLiveChannelFile file ) { - // signalling with a negative length is a hack to avoid the complexity of multiple Item classes - this.internalEnqueueItem(file, 0, -1); + // Signaling with a negative length is a hack to avoid the complexity of multiple Item classes + this.internalEnqueueItem(new DeletionItem(file)); } private void internalEnqueueItem( - final StorageLiveChannelFile sourceFile , - final long sourcePosition, - final long length + final Item item ) { - sourceFile.registerUsage(this); + item.sourceFile.registerUsage(this); // no try-catch with unregisterUsage required since the following code is too simple to fail. synchronized(this.head) { - this.tail = this.tail.next = new Item(sourceFile, sourcePosition, length); + this.tail = this.tail.next = item; this.head.notifyAll(); } } @@ -146,62 +144,111 @@ public final boolean processNextItem( } } - static final class Item + static class Item { /////////////////////////////////////////////////////////////////////////// // instance fields // //////////////////// final StorageLiveChannelFile sourceFile ; - final long sourcePosition; - final long length ; - Item next; + public Item(final StorageLiveChannelFile sourceFile) + { + super(); + this.sourceFile = sourceFile; + } + + /////////////////////////////////////////////////////////////////////////// + // methods // + //////////// + + public void processBy(final StorageBackupHandler handler) + { + //no-op + return; + } + + } + + static final class CopyItem extends Item + { + /////////////////////////////////////////////////////////////////////////// + // instance fields // + //////////////////// + + final long sourcePosition; + final long length ; /////////////////////////////////////////////////////////////////////////// // constructors // ///////////////// - Item( + CopyItem( final StorageLiveChannelFile sourceFile , final long sourcePosition, final long length ) { - super(); - this.sourceFile = sourceFile ; + super(sourceFile); this.sourcePosition = sourcePosition; this.length = length ; } + @Override + public void processBy(final StorageBackupHandler handler) + { + handler.copyFilePart(this.sourceFile, this.sourcePosition, this.length); + } + } + + static final class TruncationItem extends Item + { + /////////////////////////////////////////////////////////////////////////// + // instance fields // + //////////////////// + + final long length; /////////////////////////////////////////////////////////////////////////// - // methods // - //////////// + // constructors // + ///////////////// + TruncationItem( + final StorageLiveChannelFile sourceFile, + final long length + ) + { + super(sourceFile); + this.length = length; + } + + @Override public void processBy(final StorageBackupHandler handler) { - // negative length used as a hack ("reduce file") to avoid the complexity of multiple Item classes - if(this.length < 0) - { - if(this.sourcePosition == 0) - { - // reduce to 0 means deleting the file. - handler.deleteFile(this.sourceFile); - } - else - { - // reduce to a non-zero position means truncation. - handler.truncateFile(this.sourceFile, this.sourcePosition); - } - } - else - { - handler.copyFilePart(this.sourceFile, this.sourcePosition, this.length); - } + handler.truncateFile(this.sourceFile, this.length); + } + } + + static final class DeletionItem extends Item + { + /////////////////////////////////////////////////////////////////////////// + // constructors // + ///////////////// + + DeletionItem( + final StorageLiveChannelFile sourceFile + ) + { + super(sourceFile); + } + + @Override + public void processBy(final StorageBackupHandler handler) + { + handler.deleteFile(this.sourceFile); } } diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannel.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannel.java index 70f884ca..4ded8b5d 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannel.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannel.java @@ -68,6 +68,8 @@ public void postStoreUpdateEntityCache(ByteBuffer[] chunks, long[] chunksStorage public boolean issuedEntityCacheCheck(long nanoTimeBudget, StorageEntityCacheEvaluator entityEvaluator); + public boolean issuedTransactionsLogCleanup(); + public void exportData(StorageLiveFileProvider fileProvider); // (19.07.2014 TM)TODO: refactor storage typing to avoid classes in public API @@ -192,6 +194,7 @@ private HousekeepingTask[] defineHouseKeepingTasks() tasks.add(this::houseKeepingCheckFileCleanup); tasks.add(this::houseKeepingGarbageCollection); tasks.add(this::houseKeepingEntityCacheCheck); + tasks.add(this::houseKeepingTransactionFile); // (16.06.2020 TM)TODO: priv#49: housekeeping task that closes data files after a timeout. return tasks.toArray(HousekeepingTask.class); @@ -327,6 +330,19 @@ public boolean performEntityCacheCheck( return this.entityCache.incrementalEntityCacheCheck(nanoTimeBudgetBound); } + @Override + public boolean performTransactionFileCheck(final boolean checkSize) + { + if(!this.fileManager.isFileCleanupEnabled()) + { + return true; + } + + logger.trace("StorageChannel#{} performing transaction file check", this.channelIndex); + + return this.fileManager.issuedTransactionFileCheck(checkSize); + } + @Override public final boolean issuedGarbageCollection(final long nanoTimeBudget) { @@ -348,6 +364,12 @@ public boolean issuedEntityCacheCheck( return this.housekeepingBroker.performIssuedEntityCacheCheck(this, nanoTimeBudget, entityEvaluator); } + @Override + public boolean issuedTransactionsLogCleanup() + { + return this.housekeepingBroker.performTransactionFileCheck(this, false); + } + private long calculateSpecificHousekeepingTimeBudget(final long nanoTimeBudget) { return Math.min(nanoTimeBudget, this.housekeepingIntervalBudgetNs); @@ -384,6 +406,11 @@ final boolean houseKeepingEntityCacheCheck() return this.housekeepingBroker.performEntityCacheCheck(this, nanoTimeBudget); } + + final boolean houseKeepingTransactionFile() + { + return this.housekeepingBroker.performTransactionFileCheck(this, true); + } private void work() throws InterruptedException { diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageConnection.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageConnection.java index 911474d1..4976a550 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageConnection.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageConnection.java @@ -237,6 +237,16 @@ public void issueFullBackup( PersistenceTypeDictionaryExporter typeDictionaryExporter ); + /** + * Issue a cleanup of the transaction log to reduce size regardless of its current size. + * + * To shrink the file size all store, transfer, and truncation entries are combined into one single store entry + * for each storage files. FileCreation entries are kept, FileDeletion entries are kept + * if the storage data file still exists on the file system. Otherwise, all entries related + * to deleted files are removed if the storage data file does no more exist. + */ + public void issueTransactionsLogCleanup(); + /** * Creates a {@link StorageRawFileStatistics} instance, (obviously) containing raw file statistics about * every channel in the storage. @@ -554,6 +564,20 @@ public final void issueFullBackup( this.exportChannels(targetFileProvider); typeDictionaryExporter.exportTypeDictionary(this.persistenceManager().typeDictionary()); } + + @Override + public void issueTransactionsLogCleanup() + { + try + { + this.connectionRequestAcceptor.issueTransactionsLogCleanup(); + } + catch(final InterruptedException e) + { + // thread interrupted, task aborted, return + return; + } + } @Override public StorageRawFileStatistics createStorageStatistics() diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageDataFileEvaluator.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageDataFileEvaluator.java index 0ab9d32e..9f7c3bc0 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageDataFileEvaluator.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageDataFileEvaluator.java @@ -38,6 +38,7 @@ public interface StorageDataFileEvaluator extends StorageDataFileDissolvingEvalu public int fileMaximumSize(); + public int transactionFileMaximumSize(); /** * Pseudo-constructor method to create a new {@link StorageDataFileEvaluator} instance @@ -59,10 +60,11 @@ public static StorageDataFileEvaluator New() * good defense against accidentally erroneous changes of the default values. */ return New( - Defaults.defaultFileMinimumSize(), - Defaults.defaultFileMaximumSize(), - Defaults.defaultMinimumUseRatio(), - Defaults.defaultResolveHeadfile() + Defaults.defaultFileMinimumSize() , + Defaults.defaultFileMaximumSize() , + Defaults.defaultMinimumUseRatio() , + Defaults.defaultResolveHeadfile() , + Defaults.defaultTransactionFileMaximumSize() ); } @@ -89,10 +91,11 @@ public static StorageDataFileEvaluator New() public static StorageDataFileEvaluator New(final double minimumUseRatio) { return New( - Defaults.defaultFileMinimumSize(), - Defaults.defaultFileMaximumSize(), - minimumUseRatio , - Defaults.defaultResolveHeadfile() + Defaults.defaultFileMinimumSize() , + Defaults.defaultFileMaximumSize() , + minimumUseRatio , + Defaults.defaultResolveHeadfile() , + Defaults.defaultTransactionFileMaximumSize() ); } @@ -124,10 +127,11 @@ public static StorageDataFileEvaluator New( ) { return New( - fileMinimumSize , - fileMaximumSize , - Defaults.defaultMinimumUseRatio(), - Defaults.defaultResolveHeadfile() + fileMinimumSize , + fileMaximumSize , + Defaults.defaultMinimumUseRatio() , + Defaults.defaultResolveHeadfile() , + Defaults.defaultTransactionFileMaximumSize() ); } @@ -176,13 +180,113 @@ public static StorageDataFileEvaluator New( ) { return New( - fileMinimumSize , - fileMaximumSize , - minimumUseRatio , - Defaults.defaultResolveHeadfile() + fileMinimumSize , + fileMaximumSize , + minimumUseRatio , + Defaults.defaultResolveHeadfile() , + Defaults.defaultTransactionFileMaximumSize() ); } + /** + * Pseudo-constructor method to create a new {@link StorageDataFileEvaluator} instance + * using the passed values and default values specified by {@link StorageDataFileEvaluator.Defaults}. + *

+ * For explanations and customizing values, see {@link StorageDataFileEvaluator#New(int, int, double)}. + * + * @param fileMinimumSize the minimum file size in bytes that a single storage file must have. Smaller files + * will be dissolved. + * + * @param fileMaximumSize the maximum file size in bytes that a single storage file may have. Larger files + * will be dissolved.
+ * Note that a file can exceed this limit if it contains a single entity that already exceeds the limit. + * E.g. an int array with 10 million elements would be about 40 MB in size and would exceed a file size + * limit of, for example, 30 MB. + * + * @param minimumUseRatio the ratio (value in ]0.0;1.0]) of non-gap data contained in a storage file to prevent + * the file from being dissolved. "Gap" data is anything that is not the latest version of an entity's data, + * including older versions of an entity and "comment" bytes (a sequence of bytes beginning with its length + * as a negative value length header).
+ * The closer this value is to 1.0 (100%), the less disk space is occupied by storage files, but the more + * file dissolving (data transfers to new files) is required and vice versa. + * + * @param cleanUpHeadFile a flag defining whether the current head file (the only file actively written to) + * shall be subjected to file cleanups as well. + * + * @return a new {@link StorageDataFileEvaluator} instance. + * + * @see StorageDataFileEvaluator#New() + * @see StorageDataFileEvaluator#New(double) + * @see StorageDataFileEvaluator#New(int, int) + * @see StorageDataFileEvaluator#New(int, int, double) + * @see StorageDataFileEvaluator.Defaults + */ + public static StorageDataFileEvaluator New( + final int fileMinimumSize, + final int fileMaximumSize, + final double minimumUseRatio, + final boolean cleanUpHeadFile + ) + { + return New( + fileMinimumSize , + fileMaximumSize , + minimumUseRatio , + cleanUpHeadFile , + Defaults.defaultTransactionFileMaximumSize() + ); + } + + + /** + * Pseudo-constructor method to create a new {@link StorageDataFileEvaluator} instance + * using the passed values and default values specified by {@link StorageDataFileEvaluator.Defaults}. + *

+ * For explanations and customizing values, see {@link StorageDataFileEvaluator#New(int, int, double)}. + * + * @param fileMinimumSize the minimum file size in bytes that a single storage file must have. Smaller files + * will be dissolved. + * + * @param fileMaximumSize the maximum file size in bytes that a single storage file may have. Larger files + * will be dissolved.
+ * Note that a file can exceed this limit if it contains a single entity that already exceeds the limit. + * E.g. an int array with 10 million elements would be about 40 MB in size and would exceed a file size + * limit of, for example, 30 MB. + * + * @param minimumUseRatio the ratio (value in ]0.0;1.0]) of non-gap data contained in a storage file to prevent + * the file from being dissolved. "Gap" data is anything that is not the latest version of an entity's data, + * including older versions of an entity and "comment" bytes (a sequence of bytes beginning with its length + * as a negative value length header).
+ * The closer this value is to 1.0 (100%), the less disk space is occupied by storage files, but the more + * file dissolving (data transfers to new files) is required and vice versa. + * + * @param cleanUpHeadFile a flag defining whether the current head file (the only file actively written to) + * shall be subjected to file cleanups as well. + * + * @param transactionFileMaximumSize the maximum file size for transaction files. Lager files will + * be deleted and a new one will be created.
+ * Note that the max file size should be smaller than the technical limit of 2 GB (Integer.MAX_VALUE) + * to allow more appends without exceeding the limit until housekeeping will create a new one. + * + * @return a new {@link StorageDataFileEvaluator} instance. + * + * @see StorageDataFileEvaluator#New() + * @see StorageDataFileEvaluator#New(double) + * @see StorageDataFileEvaluator#New(int, int) + * @see StorageDataFileEvaluator#New(int, int, double) + * @see StorageDataFileEvaluator.Defaults + */ + public static StorageDataFileEvaluator New( + final int fileMinimumSize, + final int fileMaximumSize, + final double minimumUseRatio, + final boolean cleanUpHeadFile, + final int transactionFileMaximumSize + ) + { + Validation.validateParameters(fileMinimumSize, fileMaximumSize, minimumUseRatio, transactionFileMaximumSize); + return new Default(fileMinimumSize, fileMaximumSize, minimumUseRatio, cleanUpHeadFile, transactionFileMaximumSize); + } @@ -198,6 +302,16 @@ public static int maximumFileSize() return Integer.MAX_VALUE; } + public static int minimumTransactionLogFileSize() + { + return 1024; + } + + public static int maximumTransactionLogFileSize() + { + return 1024*1024*1024; + } + /** * How much the maximum file size must be above the minimum file size. * @@ -221,7 +335,8 @@ public static double useRatioMaximum() public static void validateParameters( final int fileMinimumSize, final int fileMaximumSize, - final double minimumUseRatio + final double minimumUseRatio, + final int transactionFileMaximumSize ) { // > maximumFileSize() can technically never happen for now, but the max value might change. @@ -262,51 +377,16 @@ public static void validateParameters( + useRatioLowerBound() + ", " + useRatioMaximum() + "]." ); } - } - } - /** - * Pseudo-constructor method to create a new {@link StorageDataFileEvaluator} instance - * using the passed values and default values specified by {@link StorageDataFileEvaluator.Defaults}. - *

- * For explanations and customizing values, see {@link StorageDataFileEvaluator#New(int, int, double)}. - * - * @param fileMinimumSize the minimum file size in bytes that a single storage file must have. Smaller files - * will be dissolved. - * - * @param fileMaximumSize the maximum file size in bytes that a single storage file may have. Larger files - * will be dissolved.
- * Note that a file can exceed this limit if it contains a single entity that already exceeds the limit. - * E.g. an int array with 10 million elements would be about 40 MB in size and would exceed a file size - * limit of, for example, 30 MB. - * - * @param minimumUseRatio the ratio (value in ]0.0;1.0]) of non-gap data contained in a storage file to prevent - * the file from being dissolved. "Gap" data is anything that is not the latest version of an entity's data, - * including older versions of an entity and "comment" bytes (a sequence of bytes beginning with its length - * as a negative value length header).
- * The closer this value is to 1.0 (100%), the less disk space is occupied by storage files, but the more - * file dissolving (data transfers to new files) is required and vice versa. - * - * @param cleanUpHeadFile a flag defining wether the current head file (the only file actively written to) - * shall be subjected to file cleanups as well. - * - * @return a new {@link StorageDataFileEvaluator} instance. - * - * @see StorageDataFileEvaluator#New() - * @see StorageDataFileEvaluator#New(double) - * @see StorageDataFileEvaluator#New(int, int) - * @see StorageDataFileEvaluator#New(int, int, double) - * @see StorageDataFileEvaluator.Defaults - */ - public static StorageDataFileEvaluator New( - final int fileMinimumSize, - final int fileMaximumSize, - final double minimumUseRatio, - final boolean cleanUpHeadFile - ) - { - Validation.validateParameters(fileMinimumSize, fileMaximumSize, minimumUseRatio); - return new Default(fileMinimumSize, fileMaximumSize, minimumUseRatio, cleanUpHeadFile); + if(transactionFileMaximumSize < minimumTransactionLogFileSize() || transactionFileMaximumSize > maximumTransactionLogFileSize()) + { + throw new IllegalArgumentException( + "Specified transaction file maximum size of " + transactionFileMaximumSize + + " is not in the valid range of [" + + minimumTransactionLogFileSize() + ", " + maximumTransactionLogFileSize() + "]." + ); + } + } } public interface Defaults @@ -320,6 +400,16 @@ public static int defaultFileMinimumSize() return 1 * 1024 * 1024; } + /** + * + * @return {@code 100 * 1024 * 1024} (meaning 100 MB maximum transaction log file size). + */ + public static int defaultTransactionFileMaximumSize() + { + // 100 MB as default + return 1024 * 1024 * 100; + } + /** * @return {@code 8 * 1024 * 1024} (meaning 8 MB maximum file size). */ @@ -355,7 +445,7 @@ public final class Default implements StorageDataFileEvaluator private final int fileMaximumSize; private final double minimumUseRatio; private final boolean cleanupHeadFile; - + private final int transactionFileMaximumSize; /////////////////////////////////////////////////////////////////////////// @@ -366,14 +456,16 @@ public final class Default implements StorageDataFileEvaluator final int fileMinimumSize, final int fileMaximumSize, final double minimumUseRatio, - final boolean cleanupHeadFile + final boolean cleanupHeadFile, + final int transactionFileMaximumSize ) { super(); - this.fileMinimumSize = fileMinimumSize; - this.fileMaximumSize = fileMaximumSize; - this.minimumUseRatio = minimumUseRatio; - this.cleanupHeadFile = cleanupHeadFile; + this.fileMinimumSize = fileMinimumSize; + this.fileMaximumSize = fileMaximumSize; + this.minimumUseRatio = minimumUseRatio; + this.cleanupHeadFile = cleanupHeadFile; + this.transactionFileMaximumSize = transactionFileMaximumSize; } @@ -403,6 +495,12 @@ public boolean cleanupHeadFile() { return this.cleanupHeadFile; } + + @Override + public final int transactionFileMaximumSize() + { + return this.transactionFileMaximumSize; + } @Override public final boolean needsDissolving(final StorageLiveDataFile storageFile) diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFileManager.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFileManager.java index d8d830bf..346079d9 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFileManager.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFileManager.java @@ -220,6 +220,8 @@ private static long[] allChunksStoragePositions(final ByteBuffer[] chunks, final // cleared and nulled by clearRegisteredFiles() / reset() private StorageLiveDataFile.Default headFile; + private StorageTransactionsFileCleaner.Default transactionFileCleaner; + /////////////////////////////////////////////////////////////////////////// @@ -879,6 +881,14 @@ public StorageIdAnalysis initializeStorage( this.initializeBackupHandler(effectiveStorageInventory); } + this.transactionFileCleaner = new StorageTransactionsFileCleaner.Default( + this.fileTransactions, + this.channelIndex, + this.dataFileEvaluator.transactionFileMaximumSize(), + this.fileProvider, + this.writer + ); + this.restartFileCleanupCursor(); return idAnalysis; @@ -1249,7 +1259,7 @@ public final void reset() * The deleteBuffers method is used to allow an early deallocation * of the used DirectByteBuffers in order to reduce the off-heap * memory footprint without the need to relay on the GC. - * after calling this method the StorageManager is left in a inoperable state. + * after calling this method the StorageManager is left in an inoperable state. */ public final void deleteBuffers() { @@ -1357,6 +1367,11 @@ public final boolean issuedFileCleanupCheck(final long nanoTimeBudgetBound) return this.internalCheckForCleanup(nanoTimeBudgetBound, this.dataFileEvaluator); } + public boolean issuedTransactionFileCheck(final boolean checkSize) + { + return this.internalTransactionFileCheck(checkSize); + } + private void deletePendingFile(final StorageLiveDataFile.Default file) { if(this.pendingFileDeletes < 1) @@ -1503,7 +1518,7 @@ private void deleteFile(final StorageLiveDataFile.Default file) * The registration logic must be inverted in this case: * First register the file to be deleted (no longer needed), then, after that entry is ensured, * the file can be physically deleted (or left alive because of a killed process). - * This way, the next startup validation know that the file is no longer needed and can react accrodingly + * This way, the next startup validation know that the file is no longer needed and can react accordingly * (keep it alive to re-evaluate it or delete it, etc.) */ this.writeTransactionsEntryFileDeletion(file, this.timestampProvider.currentNanoTimestamp()); @@ -1580,7 +1595,6 @@ final void prepareImport() public void copyData(final StorageImportSource importSource) { -// DEBUGStorage.println(this.channelIndex + " processing import source file " + importFile); importSource.iterateBatches(this.importHelper.setSource(importSource)); } @@ -1628,7 +1642,6 @@ final void importBatch(final StorageImportSource source, final long position, fi } this.checkForNewFile(); -// DEBUGStorage.println(this.channelIndex + " importing batch from source @" + position + "[" + length + "] to file #" + this.headFile.number()); this.writer.writeImport(source, position, length, this.headFile); } @@ -1737,6 +1750,18 @@ static void throwImpossibleStoreLengthException( throw new StorageException(vs.toString()); } + + private boolean internalTransactionFileCheck(final boolean checkSize) + { + if(this.fileTransactions == null) + { + return true; + } + + this.transactionFileCleaner.compactTransactionsFile(checkSize); + + return true; + } } diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageHousekeepingBroker.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageHousekeepingBroker.java index b1389f96..0b4424fd 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageHousekeepingBroker.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageHousekeepingBroker.java @@ -48,6 +48,10 @@ public boolean performEntityCacheCheck( long nanoTimeBudget ); + public boolean performTransactionFileCheck( + StorageHousekeepingExecutor executor , + boolean checkSize + ); public static StorageHousekeepingBroker New() { @@ -127,6 +131,15 @@ public boolean performEntityCacheCheck( return executor.performEntityCacheCheck(nanoTimeBudget); } + @Override + public boolean performTransactionFileCheck( + final StorageHousekeepingExecutor executor , + final boolean checkSize + ) + { + return executor.performTransactionFileCheck(checkSize); + } + } } diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageHousekeepingExecutor.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageHousekeepingExecutor.java index a52b9b7e..316e5e60 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageHousekeepingExecutor.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageHousekeepingExecutor.java @@ -29,5 +29,7 @@ public interface StorageHousekeepingExecutor public boolean performGarbageCollection(long nanoTimeBudget); public boolean performEntityCacheCheck(long nanoTimeBudget); + + public boolean performTransactionFileCheck(boolean checkSize); } diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageRequestAcceptor.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageRequestAcceptor.java index 5af23c1b..21955d57 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageRequestAcceptor.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageRequestAcceptor.java @@ -72,6 +72,9 @@ public interface StorageRequestAcceptor public boolean issueCacheCheck(long nanoTimeBudget, StorageEntityCacheEvaluator entityEvaluator) throws InterruptedException; + public void issueTransactionsLogCleanup() + throws InterruptedException; + // exporting // public default StorageEntityTypeExportStatistics exportTypes(final StorageEntityTypeExportFileProvider exportFileProvider) @@ -220,6 +223,13 @@ public boolean issueFileCheck(final long nanoTimeBudget) return waitOnTask(this.taskBroker.issueFileCheck(nanoTimeBudget)).result(); } + @Override + public void issueTransactionsLogCleanup() + throws InterruptedException + { + waitOnTask(this.taskBroker.issueTransactionsLogCleanup()); + } + @Override public final StorageEntityTypeExportStatistics exportTypes( final StorageEntityTypeExportFileProvider exportFileProvider, diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageRequestTaskCreator.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageRequestTaskCreator.java index c00de630..82cc7d85 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageRequestTaskCreator.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageRequestTaskCreator.java @@ -92,6 +92,11 @@ public StorageRequestTaskCacheCheck createFullCacheCheckTask( StorageOperationController operationController ); + public StorageRequestTaskTransactionsLogCleanup CreateTransactionsLogCleanupTask( + int channelCount , + StorageOperationController operationController + ); + public StorageRequestTaskImportDataFiles createImportFromFilesTask( int channelCount , StorageDataFileEvaluator fileEvaluator , @@ -298,6 +303,18 @@ public StorageRequestTaskCacheCheck createFullCacheCheckTask( ); } + @Override + public StorageRequestTaskTransactionsLogCleanup CreateTransactionsLogCleanupTask( + final int channelCount, + final StorageOperationController operationController) + { + return new StorageRequestTaskTransactionsLogCleanup.Default( + this.timestampProvider.currentNanoTimestamp(), + channelCount, + operationController + ); + } + @Override public StorageRequestTaskImportDataFiles createImportFromFilesTask( final int channelCount , diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageRequestTaskTransactionsLogCleanup.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageRequestTaskTransactionsLogCleanup.java new file mode 100644 index 00000000..90726dea --- /dev/null +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageRequestTaskTransactionsLogCleanup.java @@ -0,0 +1,67 @@ +package org.eclipse.store.storage.types; + +/*- + * #%L + * EclipseStore Storage + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public interface StorageRequestTaskTransactionsLogCleanup extends StorageRequestTask +{ + public boolean result(); + + + public final class Default + extends StorageChannelSynchronizingTask.AbstractCompletingTask + implements StorageRequestTaskTransactionsLogCleanup, StorageChannelTaskStoreEntities + { + /////////////////////////////////////////////////////////////////////////// + // instance fields // + //////////////////// + + boolean completed; + + + /////////////////////////////////////////////////////////////////////////// + // constructors // + ///////////////// + + Default( + final long timestamp , + final int channelCount , + final StorageOperationController controller + ) + { + super(timestamp, channelCount, controller); + } + + + + /////////////////////////////////////////////////////////////////////////// + // methods // + //////////// + + @Override + protected final Void internalProcessBy(final StorageChannel channel) + { + this.completed = channel.issuedTransactionsLogCleanup(); + return null; + } + + @Override + public final boolean result() + { + return this.completed; + } + + } + +} diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageTaskBroker.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageTaskBroker.java index 09f36b42..8c947a5f 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageTaskBroker.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageTaskBroker.java @@ -94,6 +94,9 @@ public StorageRequestTaskCacheCheck issueCacheCheck( ) throws InterruptedException; + public StorageRequestTaskTransactionsLogCleanup issueTransactionsLogCleanup() + throws InterruptedException; + public StorageOperationController operationController(); public final class Default implements StorageTaskBroker @@ -271,6 +274,18 @@ public final synchronized StorageRequestTaskFileCheck issueFileCheck( this.enqueueTaskAndNotifyAll(task); return task; } + + @Override + public final synchronized StorageRequestTaskTransactionsLogCleanup issueTransactionsLogCleanup() + throws InterruptedException + { + final StorageRequestTaskTransactionsLogCleanup task = this.taskCreator.CreateTransactionsLogCleanupTask( + this.channelCount, + this.operationController + ); + this.enqueueTaskAndNotifyAll(task); + return task; + } @Override public final synchronized StorageRequestTask enqueueExportChannelsTask( diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageTransactionsFileCleaner.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageTransactionsFileCleaner.java new file mode 100644 index 00000000..94f9f28f --- /dev/null +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageTransactionsFileCleaner.java @@ -0,0 +1,410 @@ +package org.eclipse.store.storage.types; + +/*- + * #%L + * EclipseStore Storage + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.nio.ByteBuffer; +import java.util.LinkedHashMap; + +import org.eclipse.serializer.memory.XMemory; +import org.eclipse.serializer.util.X; +import org.eclipse.serializer.util.logging.Logging; +import org.eclipse.store.storage.exceptions.StorageException; +import org.eclipse.store.storage.types.StorageTransactionsAnalysis.EntryIterator; +import org.eclipse.store.storage.types.StorageTransactionsAnalysis.Logic; +import org.slf4j.Logger; + +public interface StorageTransactionsFileCleaner +{ + /** + * Reduces the size of the storage transactions log file if it exceeds the configured limit. + *
+ * To shrink the file size all store, transfer, and truncation entries are combined into one single store entry + * for each storage files. FileCreation entries are kept, FileDeletion entries are kept + * if the storage data file still exists on the file system. Otherwise, all entries related + * to deleted files are removed if the storage data file does no more exist. + * + * @param checkSize if false the file is compacted regardless of its current size. + */ + public void compactTransactionsFile(boolean checkSize); + + public final class Default implements StorageTransactionsFileCleaner + { + private static class FileTransactionInfo + { + /////////////////////////////////////////////////////////////////////////// + // instance fields // + //////////////////// + + private long creationFileLength; + private long creationTimeStamp; + private long storeFileLength; + private long storeTimeStamp; + private long deletionFileLength; + private long deletionTimeStamp; + + /////////////////////////////////////////////////////////////////////////// + // constructors // + ///////////////// + + public FileTransactionInfo() + { + super(); + } + + /////////////////////////////////////////////////////////////////////////// + // methods // + //////////// + + public void setCreation(final long fileLength, final long timestamp) + { + this.creationFileLength = fileLength; + this.creationTimeStamp = timestamp; + } + + public void setStore(final long fileLength, final long timestamp) + { + this.storeFileLength = fileLength; + this.storeTimeStamp = timestamp; + } + + public void setDeletion(final long fileLength, final long timestamp) + { + this.deletionFileLength = fileLength; + this.deletionTimeStamp = timestamp; + } + + } + + private static class Collector implements EntryIterator + { + /////////////////////////////////////////////////////////////////////////// + // instance fields // + //////////////////// + + private final LinkedHashMap transactions; + private FileTransactionInfo currentTransactionInfo; + + + /////////////////////////////////////////////////////////////////////////// + // constructors // + ///////////////// + + public Collector() + { + super(); + this.transactions = new LinkedHashMap<>(); + } + + + /////////////////////////////////////////////////////////////////////////// + // methods // + //////////// + + public LinkedHashMap transactions() + { + return this.transactions; + } + + @Override + public boolean accept(final long address, final long availableEntryLength) + { + // check for and skip gaps / comments + if(availableEntryLength < 0) + { + return true; + } + + switch(Logic.getEntryType(address)) + { + case Logic.TYPE_FILE_CREATION : return this.handleEntryFileCreation (address, availableEntryLength); + case Logic.TYPE_STORE : return this.handleEntryStore (address, availableEntryLength); + case Logic.TYPE_TRANSFER : return this.handleEntryTransfer (address, availableEntryLength); + case Logic.TYPE_FILE_TRUNCATION: return this.handleEntryFileTruncation(address, availableEntryLength); + case Logic.TYPE_FILE_DELETION : return this.handleEntryFileDeletion (address, availableEntryLength); + default: + { + throw new StorageException("Unknown transactions entry type: " + Logic.getEntryType(address)); + } + } + } + + private boolean handleEntryFileDeletion(final long address, final long availableEntryLength) + { + if(availableEntryLength < Logic.LENGTH_FILE_DELETION) + { + return false; + } + + final long fileNumber = Logic.getFileNumber(address); + final long fileLength = Logic.getFileLength(address); + final long timestamp = Logic.getEntryTimestamp(address); + + final FileTransactionInfo info = this.transactions.get(fileNumber); + if(info == null) + { + throw new RuntimeException("no FileTransactionInfo for file found, file number: " + fileNumber); + } + + info.setDeletion(fileLength, timestamp); + + return true; + } + + private boolean handleEntryFileTruncation(final long address, final long availableEntryLength) + { + if(availableEntryLength < Logic.LENGTH_FILE_TRUNCATION) + { + return false; + } + + final long FileLength = Logic.getFileLength(address); + + this.currentTransactionInfo.setStore(FileLength, this.currentTransactionInfo.storeTimeStamp); + + return true; + } + + private boolean handleEntryTransfer(final long address, final long availableEntryLength) + { + if(availableEntryLength < Logic.LENGTH_TRANSFER) + { + return false; + } + + final long FileLength = Logic.getFileLength(address); + + this.currentTransactionInfo.setStore(FileLength, this.currentTransactionInfo.storeTimeStamp); + + return true; + } + + private boolean handleEntryStore(final long address, final long availableEntryLength) + { + if(availableEntryLength < Logic.LENGTH_STORE) + { + return false; + } + + final long FileLength = Logic.getFileLength(address); + final long timestamp = Logic.getEntryTimestamp(address); + + this.currentTransactionInfo.setStore(FileLength, timestamp); + + return true; + } + + private boolean handleEntryFileCreation(final long address, final long availableEntryLength) + { + if(availableEntryLength < Logic.LENGTH_FILE_CREATION) + { + return false; + } + + final long fileNumber = Logic.getFileNumber(address); + final long fileLength = Logic.getFileLength(address); + final long timestamp = Logic.getEntryTimestamp(address); + + this.currentTransactionInfo = new FileTransactionInfo(); + this.currentTransactionInfo.setCreation(fileLength, timestamp); + + if(null != this.transactions.putIfAbsent(fileNumber, this.currentTransactionInfo)) + { + throw new RuntimeException("duplicated creation entry!"); + } + + return true; + } + + } + + private final static Logger logger = Logging.getLogger(StorageTransactionsFileCleaner.class); + + /////////////////////////////////////////////////////////////////////////// + // instance fields // + //////////////////// + + private final StorageLiveTransactionsFile storageLiveTransactionsFile; + private final int channelIndex; + private final long transactionFileSizeLimit; + private final StorageFileWriter storageFileWriter; + private final StorageLiveFileProvider fileProvider; + + /** + * The most actual store time stamp in all processed files. + * Required if a file has only transfers but no stores. + */ + private long lastStoreTimestamp; + + + /////////////////////////////////////////////////////////////////////////// + // constructors // + ///////////////// + + public Default( + final StorageLiveTransactionsFile fileTransactions, + final int channelIndex, + final long transactionFileSizeLimit, + final StorageLiveFileProvider fileProvider, + final StorageFileWriter storageFileWriter) + { + super(); + this.channelIndex = channelIndex; + this.transactionFileSizeLimit = transactionFileSizeLimit; + this.storageLiveTransactionsFile = fileTransactions; + this.fileProvider = fileProvider; + this.storageFileWriter = storageFileWriter; + } + + + /////////////////////////////////////////////////////////////////////////// + // methods // + //////////// + + @Override + public void compactTransactionsFile(final boolean checkSize) + { + if(checkSize == true && this.storageLiveTransactionsFile.size() > this.transactionFileSizeLimit) + { + logger.info("Transaction file {} size exceeds limit of {} bytes", this.storageLiveTransactionsFile.identifier(), this.transactionFileSizeLimit); + this.compactTransactionsFileInternal(); + } + else if(!checkSize) + { + this.compactTransactionsFileInternal(); + } + } + + private void compactTransactionsFileInternal() + { + logger.info("Compacting transaction file {}", this.storageLiveTransactionsFile.identifier()); + + final LinkedHashMap transactions = this.collectEntries(); + this.lastStoreTimestamp = this.getLastStoreTimestamp(transactions); + + this.removeDeletedEntries(transactions); + + this.storageFileWriter.truncate(this.storageLiveTransactionsFile, 0, this.fileProvider); + this.writeTransactionLog(transactions); + } + + private LinkedHashMap collectEntries() + { + final Collector collector = new Collector(); + StorageTransactionsAnalysis.Logic.processInputFile(this.storageLiveTransactionsFile.file().tryUseReading(), collector); + return collector.transactions(); + } + + private long getLastStoreTimestamp(final LinkedHashMap transactions) + { + return transactions.values().stream().mapToLong((x)->x.storeTimeStamp).max().orElse(0); + } + + private void removeDeletedEntries(final LinkedHashMap transactions) + { + transactions.entrySet().removeIf( e -> { + logger.debug("channel {} file {} no more existing, removing all entries from transactions log ", this.channelIndex, e.getKey()); + return !this.fileProvider.provideDataFile(this.channelIndex, e.getKey()).exists(); + }); + } + + private void writeTransactionLog(final LinkedHashMap transactions) + { + final ByteBuffer + entryBufferFileCreation = XMemory.allocateDirectNative(StorageTransactionsAnalysis.Logic.entryLengthFileCreation()), + entryBufferStore = XMemory.allocateDirectNative(StorageTransactionsAnalysis.Logic.entryLengthStore()) , + entryBufferFileDeletion = XMemory.allocateDirectNative(StorageTransactionsAnalysis.Logic.entryLengthFileDeletion()); + + final Iterable + entryBufferWrapFileCreation = X.ArrayView(entryBufferFileCreation ), + entryBufferWrapStore = X.ArrayView(entryBufferStore ), + entryBufferWrapFileDeletion = X.ArrayView(entryBufferFileDeletion ); + + final long + entryBufferFileCreationAddress = XMemory.getDirectByteBufferAddress(entryBufferFileCreation) , + entryBufferStoreAddress = XMemory.getDirectByteBufferAddress(entryBufferStore) , + entryBufferFileDeletionAddress = XMemory.getDirectByteBufferAddress(entryBufferFileDeletion) ; + + StorageTransactionsAnalysis.Logic.initializeEntryFileCreation (entryBufferFileCreationAddress ); + StorageTransactionsAnalysis.Logic.initializeEntryStore (entryBufferStoreAddress ); + StorageTransactionsAnalysis.Logic.initializeEntryFileDeletion (entryBufferFileDeletionAddress ); + + transactions.forEach( (k,v) -> { + + entryBufferFileCreation.clear(); + StorageTransactionsAnalysis.Logic.setEntryFileCreation( + entryBufferFileCreationAddress, + v.creationFileLength, + v.creationTimeStamp, + k + ); + this.storageFileWriter.writeTransactionEntryCreate(this.storageLiveTransactionsFile, entryBufferWrapFileCreation, null); + + + if(v.storeTimeStamp > 0) { + + entryBufferStore.clear(); + StorageTransactionsAnalysis.Logic.setEntryStore( + entryBufferStoreAddress, + v.storeFileLength, + v.storeTimeStamp + ); + + this.storageFileWriter.writeTransactionEntryStore( + this.storageLiveTransactionsFile, + entryBufferWrapStore, + null, + 0, + v.storeFileLength); + } + else + { + //special case: there is no real store entry that sets a correct time stamp and file length. + //This may happen if older data file are deleted and the current one has only transfers. + + entryBufferStore.clear(); + StorageTransactionsAnalysis.Logic.setEntryStore( + entryBufferStoreAddress, + v.storeFileLength, + this.lastStoreTimestamp + ); + + this.storageFileWriter.writeTransactionEntryStore( + this.storageLiveTransactionsFile, + entryBufferWrapStore, + null, + 0, + v.storeFileLength); + } + + if(v.deletionTimeStamp > 0) { + entryBufferFileDeletion.clear(); + StorageTransactionsAnalysis.Logic.setEntryFileDeletion( + entryBufferFileDeletionAddress, + v.deletionFileLength, + v.deletionTimeStamp, + k + ); + this.storageFileWriter.writeTransactionEntryDelete(this.storageLiveTransactionsFile, entryBufferWrapFileDeletion, null); + } + }); + + XMemory.deallocateDirectByteBuffer(entryBufferFileCreation); + XMemory.deallocateDirectByteBuffer(entryBufferStore); + XMemory.deallocateDirectByteBuffer(entryBufferFileDeletion); + } + + } + +} From 95825e5bc29bba4b972e2c0b54cc6e4a6f4be159 Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Wed, 6 Dec 2023 10:52:43 +0100 Subject: [PATCH 022/126] Migration of microstream cache to eclipse store (#86) --- cache/LICENSE | 277 ++ cache/cache/LICENSE | 277 ++ cache/cache/pom.xml | 45 + cache/cache/src/main/java/module-info.java | 30 + .../eclipse/store/cache/types/ByteSized.java | 24 + .../org/eclipse/store/cache/types/Cache.java | 2595 +++++++++++++++++ .../store/cache/types/CacheConfiguration.java | 1591 ++++++++++ ...onfigurationBuilderConfigurationBased.java | 233 ++ .../cache/types/CacheConfigurationMXBean.java | 78 + .../CacheConfigurationPropertyNames.java | 97 + .../eclipse/store/cache/types/CacheEntry.java | 73 + .../types/CacheEntryListenerRegistration.java | 155 + .../eclipse/store/cache/types/CacheEvent.java | 120 + .../cache/types/CacheEventDispatcher.java | 192 ++ .../store/cache/types/CacheManager.java | 317 ++ .../cache/types/CacheStatisticsMXBean.java | 248 ++ .../eclipse/store/cache/types/CacheStore.java | 222 ++ .../eclipse/store/cache/types/CacheTable.java | 236 ++ .../cache/types/CacheValueValidator.java | 94 + .../store/cache/types/CachedValue.java | 164 ++ .../store/cache/types/CachingProvider.java | 201 ++ .../cache/types/EntryProcessorResult.java | 37 + .../store/cache/types/EvictionManager.java | 234 ++ .../store/cache/types/EvictionPolicy.java | 382 +++ .../store/cache/types/MBeanServerUtils.java | 115 + .../store/cache/types/MutableCacheEntry.java | 183 ++ .../store/cache/types/ObjectConverter.java | 92 + .../store/cache/types/SerializedObject.java | 74 + .../store/cache/types/Unwrappable.java | 40 + .../services/javax.cache.spi.CachingProvider | 1 + cache/hibernate/LICENSE | 277 ++ cache/hibernate/pom.xml | 36 + .../hibernate/src/main/java/module-info.java | 23 + .../hibernate/types/CacheRegionFactory.java | 455 +++ .../CacheStrategyRegistrationProvider.java | 45 + .../types/ConfigurationPropertyNames.java | 25 + .../hibernate/types/MissingCacheStrategy.java | 73 + .../cache/hibernate/types/StorageAccess.java | 139 + ...stry.selector.StrategyRegistrationProvider | 1 + cache/pom.xml | 28 + pom.xml | 1 + 41 files changed, 9530 insertions(+) create mode 100644 cache/LICENSE create mode 100644 cache/cache/LICENSE create mode 100644 cache/cache/pom.xml create mode 100644 cache/cache/src/main/java/module-info.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/ByteSized.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/Cache.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/CacheConfiguration.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/CacheConfigurationBuilderConfigurationBased.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/CacheConfigurationMXBean.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/CacheConfigurationPropertyNames.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/CacheEntry.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/CacheEntryListenerRegistration.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/CacheEvent.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/CacheEventDispatcher.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/CacheManager.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/CacheStatisticsMXBean.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/CacheStore.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/CacheTable.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/CacheValueValidator.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/CachedValue.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/CachingProvider.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/EntryProcessorResult.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/EvictionManager.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/EvictionPolicy.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/MBeanServerUtils.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/MutableCacheEntry.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/ObjectConverter.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/SerializedObject.java create mode 100644 cache/cache/src/main/java/org/eclipse/store/cache/types/Unwrappable.java create mode 100644 cache/cache/src/main/resources/META-INF/services/javax.cache.spi.CachingProvider create mode 100644 cache/hibernate/LICENSE create mode 100644 cache/hibernate/pom.xml create mode 100644 cache/hibernate/src/main/java/module-info.java create mode 100644 cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/CacheRegionFactory.java create mode 100644 cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/CacheStrategyRegistrationProvider.java create mode 100644 cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/ConfigurationPropertyNames.java create mode 100644 cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/MissingCacheStrategy.java create mode 100644 cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/StorageAccess.java create mode 100644 cache/hibernate/src/main/resources/META-INF/services/org.hibernate.boot.registry.selector.StrategyRegistrationProvider create mode 100644 cache/pom.xml diff --git a/cache/LICENSE b/cache/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/cache/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/cache/cache/LICENSE b/cache/cache/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/cache/cache/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/cache/cache/pom.xml b/cache/cache/pom.xml new file mode 100644 index 00000000..40965983 --- /dev/null +++ b/cache/cache/pom.xml @@ -0,0 +1,45 @@ + + + + + 4.0.0 + + + org.eclipse.store + cache-parent + 1.1.0-SNAPSHOT + ../pom.xml + + + cache + + EclipseStore Cache + JSR-107 (JCache) Implementation + https://projects.eclipse.org/projects/technology.store + + + + org.eclipse.store + storage-embedded + 1.1.0-SNAPSHOT + + + org.eclipse.store + storage-embedded-configuration + 1.1.0-SNAPSHOT + + + javax.cache + cache-api + 1.1.1 + + + org.eclipse.serializer + serializer + 1.1.0-SNAPSHOT + + + + diff --git a/cache/cache/src/main/java/module-info.java b/cache/cache/src/main/java/module-info.java new file mode 100644 index 00000000..6417b7f9 --- /dev/null +++ b/cache/cache/src/main/java/module-info.java @@ -0,0 +1,30 @@ +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.cache +{ + exports org.eclipse.store.cache.types; + + provides javax.cache.spi.CachingProvider + with org.eclipse.store.cache.types.CachingProvider + ; + + requires transitive org.eclipse.serializer.persistence.binary; + requires transitive org.eclipse.store.storage.embedded.configuration; + requires transitive cache.api; + requires transitive java.management; + requires org.eclipse.store.storage.embedded; + requires org.eclipse.serializer.configuration; + requires org.eclipse.serializer; + requires org.eclipse.serializer.base; +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/ByteSized.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/ByteSized.java new file mode 100644 index 00000000..a138db5f --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/ByteSized.java @@ -0,0 +1,24 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public interface ByteSized +{ + /** + * @return the amount of bytes this objects requires in memory. + */ + public long byteSize(); +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/Cache.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/Cache.java new file mode 100644 index 00000000..dcd406d0 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/Cache.java @@ -0,0 +1,2595 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import static org.eclipse.serializer.util.X.coalesce; +import static org.eclipse.serializer.util.X.notNull; + +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; + +import javax.cache.CacheException; +import javax.cache.configuration.CacheEntryListenerConfiguration; +import javax.cache.configuration.Configuration; +import javax.cache.configuration.Factory; +import javax.cache.configuration.MutableConfiguration; +import javax.cache.event.CacheEntryCreatedListener; +import javax.cache.event.CacheEntryExpiredListener; +import javax.cache.event.CacheEntryRemovedListener; +import javax.cache.event.CacheEntryUpdatedListener; +import javax.cache.event.EventType; +import javax.cache.expiry.Duration; +import javax.cache.expiry.ExpiryPolicy; +import javax.cache.integration.CacheLoader; +import javax.cache.integration.CacheLoaderException; +import javax.cache.integration.CacheWriter; +import javax.cache.integration.CacheWriterException; +import javax.cache.integration.CompletionListener; +import javax.cache.processor.EntryProcessor; +import javax.cache.processor.EntryProcessorException; + +import org.eclipse.serializer.Serializer; +import org.eclipse.serializer.collections.BulkList; +import org.eclipse.serializer.collections.types.XList; +import org.eclipse.serializer.exceptions.IORuntimeException; +import org.eclipse.serializer.reference.Reference; +import org.eclipse.serializer.reflect.ClassLoaderProvider; +import org.eclipse.serializer.typing.KeyValue; +import org.eclipse.serializer.util.X; +import org.eclipse.serializer.util.logging.Logging; +import org.eclipse.store.cache.types.MBeanServerUtils.MBeanType; +import org.slf4j.Logger; + + +/** + * JSR-107 compliant {@link javax.cache.Cache}. + * + * @param the key type + * @param the value type + */ +public interface Cache extends javax.cache.Cache, Unwrappable +{ + @Override + public CacheManager getCacheManager(); + + /** + * @return the {@link CacheConfiguration} which was used to create this cache. + */ + public CacheConfiguration getConfiguration(); + + /** + * Returns the amount of entries in this cache. + * + * @return this cache's size + */ + public long size(); + + /** + * Adds all entries to this cache. + *

+ * Short for putAll(map, true) + * + * @see #putAll(Map, boolean) + */ + @Override + public default void putAll(final Map map) + { + this.putAll(map, true); + } + + /** + * Adds all entries to this cache. + *

+ * Short for putAll(map, replaceExistingValues, true) + * + * @param map entries to add + * @param replaceExistingValues if values with same keys should be replaces + * @see #putAll(Map, boolean, boolean) + */ + public default void putAll( + final Map map , + final boolean replaceExistingValues + ) + { + this.putAll(map, replaceExistingValues, true); + } + + /** + * Adds all entries to this cache. + * + * @param map entries to add + * @param replaceExistingValues if values with same keys should be replaces + * @param useWriteThrough enable write through mode for this operation + */ + public void putAll( + Map map , + boolean replaceExistingValues, + boolean useWriteThrough + ); + + /** + * Enables or disables the management bean of this cache. + * @param enabled true if the management bean should be enabled + */ + public void setManagementEnabled(boolean enabled); + + /** + * Enables or disables statistics gathering. + * @param enabled true if the statistics gathering should be enabled + */ + public void setStatisticsEnabled(boolean enabled); + + /** + * Evicts given entries from this cache. + * @param entriesToEvict the entries to evict + */ + public void evict(Iterable> entriesToEvict); + + @Override + public default T unwrap(final Class clazz) + { + return Unwrappable.Static.unwrap(this, clazz); + } + + public static Cache New( + final String name , + final CacheManager manager , + final CacheConfiguration configuration + ) + { + return new Default<>( + name, + manager, + configuration + ); + } + + public static class Default implements Cache + { + private final static Logger logger = Logging.getLogger(Default.class); + + private final String name ; + private final CacheManager manager ; + private final CacheConfiguration configuration ; + private final CacheValueValidator keyValidator ; + private final CacheValueValidator valueValidator ; + private final ObjectConverter objectConverter ; + private final CacheLoader cacheLoader ; + private final CacheWriter cacheWriter ; + private final ExpiryPolicy expiryPolicy ; + private final EvictionManager evictionManager ; + private final CacheTable cacheTable ; + private final XList> listenerRegistrations ; + private final ExecutorService executorService ; + private final CacheConfigurationMXBean cacheConfigurationMXBean; + private final CacheStatisticsMXBean cacheStatisticsMXBean ; + private final AtomicBoolean isStatisticsEnabled = new AtomicBoolean(); + private final AtomicBoolean isClosed = new AtomicBoolean(); + + /* + * According to spec cache and configuration, which may be mutable, + * are hard-wired and overlap partially, so the constructor has to + * execute logic and cannot just take predefined values. + */ + @SuppressWarnings("unchecked") // cache reader typing differs from cache writer typing (?) + Default( + final String name , + final CacheManager manager , + final CacheConfiguration configuration + ) + { + super(); + + this.name = name ; + this.manager = manager ; + this.configuration = configuration; + + this.objectConverter = configuration.isStoreByValue() + ? ObjectConverter.ByValue( + Serializer.Binary( + configuration.getSerializerFoundation() + .setClassLoaderProvider( + ClassLoaderProvider.New(Thread.currentThread().getContextClassLoader()) + ) + ) + ) + : ObjectConverter.ByReference() + ; + + final Factory expiryPolicyFactory = coalesce( + configuration.getExpiryPolicyFactory(), + CacheConfiguration.DefaultExpiryPolicyFactory() + ); + this.expiryPolicy = expiryPolicyFactory != null + ? expiryPolicyFactory.create() + : null + ; + + final Factory> evictionManagerFactory = coalesce( + configuration.getEvictionManagerFactory(), + CacheConfiguration.DefaultEvictionManagerFactory() + ); + this.evictionManager = evictionManagerFactory != null + ? evictionManagerFactory.create() + : null + ; + + final Factory> cacheLoaderFactory; + this.cacheLoader = (cacheLoaderFactory = configuration.getCacheLoaderFactory()) != null + ? cacheLoaderFactory.create() + : null + ; + + final Factory> cacheWriterFactory; + this.cacheWriter = (cacheWriterFactory = configuration.getCacheWriterFactory()) != null + ? (CacheWriter)cacheWriterFactory.create() + : null + ; + + this.keyValidator = CacheValueValidator.New("key", configuration.getKeyType() ); + this.valueValidator = CacheValueValidator.New("value", configuration.getValueType()); + + this.cacheTable = CacheTable.New(); + this.listenerRegistrations = X.synchronize(BulkList.New()); + this.executorService = Executors.newFixedThreadPool(1); + this.cacheConfigurationMXBean = new CacheConfigurationMXBean.Default(this.configuration); + this.cacheStatisticsMXBean = new CacheStatisticsMXBean.Default(this::size); + + configuration.getCacheEntryListenerConfigurations().forEach( + this::createAndRegisterCacheEntryListener + ); + + if(configuration.isManagementEnabled()) + { + this.setManagementEnabled(true); + } + if(configuration.isStatisticsEnabled()) + { + this.setStatisticsEnabled(true); + } + + if(this.evictionManager != null) + { + this.evictionManager.install(this, this.cacheTable); + } + + logger.debug( + "EclipseStore Cache '{}' created with following configuration:\n{}", + name, + configuration + ); + } + + @Override + public String getName() + { + return this.name; + } + + @Override + public CacheManager getCacheManager() + { + return this.manager; + } + + @Override + public CacheConfiguration getConfiguration() + { + return this.configuration; + } + + @Override + public > C getConfiguration(final Class clazz) + { + if(clazz.isInstance(this.configuration)) + { + return clazz.cast(this.configuration); + } + + throw new IllegalArgumentException("Unsupported configuration type: " + clazz.getName()); + } + + @SuppressWarnings("unchecked") + private void updateConfiguration(final Consumer> c) + { + if(this.configuration instanceof MutableConfiguration) + { + c.accept((MutableConfiguration)this.configuration); + } + } + + @Override + public void registerCacheEntryListener(final CacheEntryListenerConfiguration cacheEntryListenerConfiguration) + { + notNull(cacheEntryListenerConfiguration); + + this.updateConfiguration(c -> + c.addCacheEntryListenerConfiguration(cacheEntryListenerConfiguration) + ); + + this.createAndRegisterCacheEntryListener(cacheEntryListenerConfiguration); + } + + private void createAndRegisterCacheEntryListener(final CacheEntryListenerConfiguration cacheEntryListenerConfiguration) + { + synchronized(this.listenerRegistrations) + { + this.listenerRegistrations.add( + CacheEntryListenerRegistration.New(cacheEntryListenerConfiguration) + ); + } + } + + @Override + public void deregisterCacheEntryListener(final CacheEntryListenerConfiguration cacheEntryListenerConfiguration) + { + notNull(cacheEntryListenerConfiguration); + + this.updateConfiguration(c -> + c.removeCacheEntryListenerConfiguration(cacheEntryListenerConfiguration) + ); + + synchronized(this.listenerRegistrations) + { + this.listenerRegistrations.removeBy( + reg -> cacheEntryListenerConfiguration.equals(reg.getConfiguration()) + ); + } + } + + @Override + public boolean isClosed() + { + return this.isClosed.get(); + } + + @Override + public synchronized void close() + { + if(this.isClosed.get()) + { + return; + } + + this.isClosed.set(true); + + this.manager.removeCache(this.name); + + if(this.evictionManager != null) + { + this.evictionManager.uninstall(this, this.cacheTable); + } + + this.setStatisticsEnabled(false); + this.setManagementEnabled(false); + + this.closeIfCloseable(this.cacheLoader); + this.closeIfCloseable(this.cacheWriter); + this.closeIfCloseable(this.expiryPolicy); + this.listenerRegistrations.forEach( + reg -> this.closeIfCloseable(reg.getCacheEntryListener()) + ); + this.listenerRegistrations.clear(); + + this.executorService.shutdown(); + try + { + this.executorService.awaitTermination(10, TimeUnit.SECONDS); + } + catch(final InterruptedException e) + { + throw new CacheException(e); + } + + this.cacheTable.clear(); + + logger.debug("EclipseStore Cache '{}' closed", this.name); + } + + @Override + public long size() + { + synchronized(this.cacheTable) + { + return this.cacheTable.size(); + } + } + + @Override + public V get(final K key) + { + this.ensureOpen(); + + this.keyValidator.validate(key); + + final CacheEventDispatcher eventDispatcher = this.listenerRegistrations.size() > 0L + ? CacheEventDispatcher.New() + : null; + final V value = this.getValue(key, eventDispatcher, null); + + if(eventDispatcher != null) + { + eventDispatcher.dispatch(this.listenerRegistrations); + } + + return value; + } + + @Override + public Map getAll(final Set keys) + { + this.ensureOpen(); + + keys.forEach(this.keyValidator::validate); + + final HashMap result = new HashMap<>(keys.size()); + final CacheEventDispatcher eventDispatcher = this.listenerRegistrations.size() > 0L + ? CacheEventDispatcher.New() + : null; + + for(final K key : keys) + { + V value; + if((value = this.getValue(key, eventDispatcher, null)) != null) + { + result.put(key, value); + } + } + + if(eventDispatcher != null) + { + eventDispatcher.dispatch(this.listenerRegistrations); + } + + return result; + } + + @Override + public boolean containsKey(final K key) + { + this.ensureOpen(); + + this.keyValidator.validate(key); + + final Object internalKey = this.objectConverter.internalize(key); + final long now = System.currentTimeMillis(); + + synchronized(this.cacheTable) + { + final CachedValue cachedValue = this.cacheTable.get(internalKey); + return cachedValue != null && !cachedValue.isExpiredAt(now); + } + } + + @Override + public void loadAll( + final Set keys , + final boolean replaceExistingValues, + final CompletionListener completionListener + ) + { + this.ensureOpen(); + + if(this.cacheLoader != null) + { + keys.forEach(this.keyValidator::validate); + + this.submit(() -> this.loadAllInternal(keys, replaceExistingValues, completionListener)); + } + else if(completionListener != null) + { + completionListener.onCompletion(); + } + } + + private void loadAllInternal( + final Set keys , + final boolean replaceExistingValues, + final CompletionListener completionListener + ) + { + try + { + final ArrayList keysToLoad = new ArrayList<>(); + for(final K key : keys) + { + if(replaceExistingValues || !this.containsKey(key)) + { + keysToLoad.add(key); + } + } + + Map loaded; + try + { + loaded = this.cacheLoader.loadAll(keysToLoad); + } + catch(final CacheLoaderException e) + { + throw e; + } + catch(final Exception e) + { + throw new CacheLoaderException(e); + } + + for(final K key : keysToLoad) + { + if(loaded.get(key) == null) + { + loaded.remove(key); + } + } + + this.putAll(loaded, replaceExistingValues, false); + + if(completionListener != null) + { + completionListener.onCompletion(); + } + } + catch(final Exception e) + { + if(completionListener != null) + { + completionListener.onException(e); + } + } + } + + @Override + public void put(final K key, final V value) + { + this.ensureOpen(); + + this.keyValidator.validate(key); + this.valueValidator.validate(value); + + final AtomicBoolean isStatisticsEnabled = this.isStatisticsEnabled; + final long start = isStatisticsEnabled.get() + ? System.nanoTime() + : 0; + + final CacheEventDispatcher eventDispatcher = this.listenerRegistrations.size() > 0L + ? CacheEventDispatcher.New() + : null; + int putCount = 0; + final long now = System.currentTimeMillis(); + final ObjectConverter objectConverter = this.objectConverter; + final Object internalKey = objectConverter.internalize(key); + final Object internalValue = objectConverter.internalize(value); + + synchronized(this.cacheTable) + { + CachedValue cachedValue = this.cacheTable.get(internalKey); + final boolean isExpired = cachedValue != null && cachedValue.isExpiredAt(now); + + if(isExpired) + { + this.processExpiries( + key, + internalKey, + eventDispatcher, + objectConverter.externalize(cachedValue.value()) + ); + } + + final CacheEntry entry = CacheEntry.New(key, value); + + if(cachedValue == null || isExpired) + { + cachedValue = CachedValue.New( + internalValue, + now, + this.expiryForCreation().getAdjustedTime(now) + ); + + if(cachedValue.isExpiredAt(now)) + { + this.processExpiries( + key, + internalKey, + eventDispatcher, + objectConverter.externalize(cachedValue.value()) + ); + } + else + { + // write before put, because if write fails, put mustn't happen + this.writeCacheEntry(entry); + this.putValue( + key, + value, + internalKey, + cachedValue, + eventDispatcher + ); + putCount++; + } + } + else + { + final V oldValue = objectConverter.externalize(cachedValue.value(now)); + + this.updateExpiryForUpdate(cachedValue, now); + + cachedValue.value(internalValue, now); + this.writeCacheEntry(entry); + putCount++; + + if(eventDispatcher != null) + { + eventDispatcher.addEvent( + CacheEntryUpdatedListener.class, + new CacheEvent<>(this, EventType.UPDATED, key, value, oldValue) + ); + } + } + } + + if(eventDispatcher != null) + { + eventDispatcher.dispatch(this.listenerRegistrations); + } + if(isStatisticsEnabled.get() && putCount > 0) + { + final CacheStatisticsMXBean cacheStatisticsMXBean = this.cacheStatisticsMXBean; + cacheStatisticsMXBean.increaseCachePuts(putCount); + cacheStatisticsMXBean.addPutTimeNano(System.nanoTime() - start); + } + } + + @Override + public V getAndPut(final K key, final V value) + { + this.ensureOpen(); + + this.keyValidator.validate(key); + this.valueValidator.validate(value); + + final AtomicBoolean isStatisticsEnabled = this.isStatisticsEnabled; + final long start = isStatisticsEnabled.get() + ? System.nanoTime() + : 0; + + V result; + final CacheEventDispatcher eventDispatcher = this.listenerRegistrations.size() > 0L + ? CacheEventDispatcher.New() + : null; + int putCount = 0; + final long now = System.currentTimeMillis(); + final Object internalKey = this.objectConverter.internalize(key); + final Object internalValue = this.objectConverter.internalize(value); + + synchronized(this.cacheTable) + { + CachedValue cachedValue = this.cacheTable.get(internalKey); + final boolean isExpired = cachedValue != null && cachedValue.isExpiredAt(now); + + if(isExpired) + { + this.processExpiries( + key, + internalKey, + eventDispatcher, + this.objectConverter.externalize(cachedValue.value()) + ); + } + + final CacheEntry entry = CacheEntry.New(key, value); + + if(cachedValue == null || isExpired) + { + result = null; + + cachedValue = CachedValue.New( + internalValue, + now, + this.expiryForCreation().getAdjustedTime(now) + ); + + if(cachedValue.isExpiredAt(now)) + { + this.processExpiries( + key, + internalKey, + eventDispatcher, + this.objectConverter.externalize(cachedValue.value()) + ); + } + else + { + this.putValue( + key, + value, + internalKey, + cachedValue, + eventDispatcher + ); + this.writeCacheEntry(entry); + putCount++; + } + } + else + { + final V oldValue = result = this.objectConverter.externalize(cachedValue.value(now)); + + this.updateExpiryForUpdate(cachedValue, now); + + cachedValue.value(internalValue, now); + this.writeCacheEntry(entry); + putCount++; + + if(eventDispatcher != null) + { + eventDispatcher.addEvent( + CacheEntryUpdatedListener.class, + new CacheEvent<>(this, EventType.UPDATED, key, value, oldValue) + ); + } + } + } + + if(eventDispatcher != null) + { + eventDispatcher.dispatch(this.listenerRegistrations); + } + if(isStatisticsEnabled.get()) + { + final CacheStatisticsMXBean cacheStatisticsMXBean = this.cacheStatisticsMXBean; + if(result == null) + { + cacheStatisticsMXBean.increaseCacheMisses(1); + } + else + { + cacheStatisticsMXBean.increaseCacheHits(1); + } + + cacheStatisticsMXBean.addGetTimeNano(System.nanoTime() - start); + + if(putCount > 0) + { + cacheStatisticsMXBean.increaseCachePuts(putCount); + cacheStatisticsMXBean.addPutTimeNano(System.nanoTime() - start); + } + } + + return result; + } + + @Override + public void putAll( + final Map map , + final boolean replaceExistingValues, + final boolean useWriteThrough + ) + { + this.ensureOpen(); + + map.keySet().forEach(this.keyValidator::validate); + map.values().forEach(this.valueValidator::validate); + + final boolean isStatisticsEnabled = this.isStatisticsEnabled.get(); + final long start = isStatisticsEnabled + ? System.nanoTime() + : 0; + + final long now = System.currentTimeMillis(); + int putCount = 0; + final CacheEventDispatcher eventDispatcher = this.listenerRegistrations.size() > 0L + ? CacheEventDispatcher.New() + : null; + CacheWriterException exception = null; + + synchronized(this.cacheTable) + { + final boolean isWriteThrough = this.cacheWriter != null + && this.configuration.isWriteThrough() && useWriteThrough; + + final Collection> entriesToWrite = new ArrayList<>(); + final HashSet keysToPut = new HashSet<>(); + for(final Map.Entry entry : map.entrySet()) + { + final K key = entry.getKey(); + final V value = entry.getValue(); + + keysToPut.add(key); + + if(isWriteThrough) + { + entriesToWrite.add(CacheEntry.New(key, value)); + } + } + + if(isWriteThrough) + { + try + { + this.cacheWriter.writeAll(entriesToWrite); + } + catch(final CacheWriterException e) + { + exception = e; + } + catch(final Exception e) + { + exception = new CacheWriterException(e); + } + + for(final Cache.Entry entry : entriesToWrite) + { + keysToPut.remove(entry.getKey()); + } + } + + for(final K key : keysToPut) + { + final V value = map.get(key); + final Object internalKey = this.objectConverter.internalize(key); + final Object internalValue = this.objectConverter.internalize(value); + CachedValue cachedValue = this.cacheTable.get(internalKey); + + final boolean isExpired = cachedValue != null && cachedValue.isExpiredAt(now); + if(cachedValue == null || isExpired) + { + if(isExpired) + { + this.processExpiries( + key, + internalKey, + eventDispatcher, + this.objectConverter.externalize(cachedValue.value()) + ); + } + + cachedValue = CachedValue.New( + internalValue, + now, + this.expiryForCreation().getAdjustedTime(now) + ); + if(cachedValue.isExpiredAt(now)) + { + this.processExpiries( + key, + internalKey, + eventDispatcher, + value + ); + } + else + { + this.putValue( + key, + value, + internalKey, + cachedValue, + eventDispatcher + ); + + /* + * This method called from loadAll when useWriteThrough is false. Do not count loads as puts + * per statistics table in specification. + */ + if(useWriteThrough) + { + putCount++; + } + } + } + else if(replaceExistingValues) + { + final V oldValue = this.objectConverter.externalize(cachedValue.value()); + + this.updateExpiryForUpdate(cachedValue, now); + + cachedValue.value(internalValue, now); + + /* + * Do not count loadAll calls as puts. useWriteThrough is false when called from loadAll. + */ + if(useWriteThrough) + { + putCount++; + } + + if(eventDispatcher != null) + { + eventDispatcher.addEvent( + CacheEntryUpdatedListener.class, + new CacheEvent<>(this, EventType.UPDATED, key, value, oldValue) + ); + } + } + } + } + + if(eventDispatcher != null) + { + eventDispatcher.dispatch(this.listenerRegistrations); + } + if(isStatisticsEnabled && putCount > 0) + { + final CacheStatisticsMXBean cacheStatisticsMXBean = this.cacheStatisticsMXBean; + cacheStatisticsMXBean.increaseCachePuts(putCount); + cacheStatisticsMXBean.addPutTimeNano(System.nanoTime() - start); + } + if(exception != null) + { + throw exception; + } + } + + @Override + public boolean putIfAbsent(final K key, final V value) + { + this.ensureOpen(); + + this.keyValidator.validate(key); + this.valueValidator.validate(value); + + final boolean isStatisticsEnabled = this.isStatisticsEnabled.get(); + final long start = isStatisticsEnabled + ? System.nanoTime() + : 0; + + final long now = System.currentTimeMillis(); + final CacheEventDispatcher eventDispatcher = this.listenerRegistrations.size() > 0L + ? CacheEventDispatcher.New() + : null; + final Object internalKey = this.objectConverter.internalize(key); + final Object internalValue = this.objectConverter.internalize(value); + boolean result; + + synchronized(this.cacheTable) + { + CachedValue cachedValue = this.cacheTable.get(internalKey); + + final boolean isExpired = cachedValue != null && cachedValue.isExpiredAt(now); + if(cachedValue == null || isExpired) + { + final CacheEntry entry = CacheEntry.New(key, value); + this.writeCacheEntry(entry); + + if(isExpired) + { + this.processExpiries( + key, + internalKey, + eventDispatcher, + this.objectConverter.externalize(cachedValue.value()) + ); + } + + cachedValue = CachedValue.New( + internalValue, + now, + this.expiryForCreation().getAdjustedTime(now) + ); + if(cachedValue.isExpiredAt(now)) + { + this.processExpiries( + key, + internalKey, + eventDispatcher, + value + ); + + // no expiry event for created entry that expires before put in cache. + // do not put entry in cache. + result = false; + } + else + { + this.putValue( + key, + value, + internalKey, + cachedValue, + eventDispatcher + ); + result = true; + } + } + else + { + result = false; + } + } + + if(eventDispatcher != null) + { + eventDispatcher.dispatch(this.listenerRegistrations); + } + if(isStatisticsEnabled) + { + final CacheStatisticsMXBean cacheStatisticsMXBean = this.cacheStatisticsMXBean; + if(result) + { + cacheStatisticsMXBean.increaseCachePuts(1); + cacheStatisticsMXBean.increaseCacheMisses(1); + cacheStatisticsMXBean.addPutTimeNano(System.nanoTime() - start); + } + else + { + cacheStatisticsMXBean.increaseCacheHits(1); + } + } + + return result; + } + + @Override + public boolean remove(final K key) + { + this.ensureOpen(); + + this.keyValidator.validate(key); + + final boolean isStatisticsEnabled = this.isStatisticsEnabled.get(); + final long start = isStatisticsEnabled + ? System.nanoTime() + : 0; + + final long now = System.currentTimeMillis(); + final CacheEventDispatcher eventDispatcher = this.listenerRegistrations.size() > 0L + ? CacheEventDispatcher.New() + : null; + final Object internalKey = this.objectConverter.internalize(key); + boolean result; + + synchronized(this.cacheTable) + { + this.deleteCacheEntry(key); + + final CachedValue cachedValue; + if((cachedValue = this.cacheTable.get(internalKey)) == null) + { + return false; + } + + if(cachedValue.isExpiredAt(now)) + { + result = false; + } + else + { + this.cacheTable.remove(internalKey); + final V value = this.objectConverter.externalize(cachedValue.value()); + + if(eventDispatcher != null) + { + eventDispatcher.addEvent( + CacheEntryRemovedListener.class, + new CacheEvent<>(this, EventType.REMOVED, key, value, value) + ); + } + + result = true; + } + } + + if(eventDispatcher != null) + { + eventDispatcher.dispatch(this.listenerRegistrations); + } + if(result && isStatisticsEnabled) + { + final CacheStatisticsMXBean cacheStatisticsMXBean = this.cacheStatisticsMXBean; + cacheStatisticsMXBean.increaseCacheRemovals(1); + cacheStatisticsMXBean.addRemoveTimeNano(System.nanoTime() - start); + } + + return result; + } + + @Override + public boolean remove(final K key, final V oldValue) + { + this.ensureOpen(); + + this.keyValidator.validate(key); + this.valueValidator.validate(oldValue); + + final boolean isStatisticsEnabled = this.isStatisticsEnabled.get(); + final long start = isStatisticsEnabled + ? System.nanoTime() + : 0; + + final long now = System.currentTimeMillis(); + final CacheEventDispatcher eventDispatcher = this.listenerRegistrations.size() > 0L + ? CacheEventDispatcher.New() + : null; + final Object internalKey = this.objectConverter.internalize(key); + boolean hit = false; + boolean result; + + synchronized(this.cacheTable) + { + final CachedValue cachedValue = this.cacheTable.get(internalKey); + if(cachedValue == null || cachedValue.isExpiredAt(now)) + { + result = false; + } + else + { + hit = true; + + final Object internalValue = cachedValue.value(); + final Object oldInternalValue = this.objectConverter.internalize(oldValue); + + if(internalValue.equals(oldInternalValue)) + { + this.deleteCacheEntry(key); + + this.cacheTable.remove(internalKey); + + if(eventDispatcher != null) + { + eventDispatcher.addEvent( + CacheEntryRemovedListener.class, + new CacheEvent<>(this, EventType.REMOVED, key, oldValue, oldValue) + ); + } + + result = true; + } + else + { + this.updateExpiryForAccess(cachedValue, now); + + result = false; + } + } + } + + if(eventDispatcher != null) + { + eventDispatcher.dispatch(this.listenerRegistrations); + } + if(isStatisticsEnabled) + { + final CacheStatisticsMXBean cacheStatisticsMXBean = this.cacheStatisticsMXBean; + final long duration = System.nanoTime() - start; + if(result) + { + cacheStatisticsMXBean.increaseCacheRemovals(1); + cacheStatisticsMXBean.addRemoveTimeNano(duration); + } + cacheStatisticsMXBean.addGetTimeNano(duration); + if(hit) + { + cacheStatisticsMXBean.increaseCacheHits(1); + } + else + { + cacheStatisticsMXBean.increaseCacheMisses(1); + } + } + + return result; + } + + @Override + public V getAndRemove(final K key) + { + this.ensureOpen(); + + this.keyValidator.validate(key); + + final boolean isStatisticsEnabled = this.isStatisticsEnabled.get(); + final long start = isStatisticsEnabled + ? System.nanoTime() + : 0; + + final long now = System.currentTimeMillis(); + final CacheEventDispatcher eventDispatcher = this.listenerRegistrations.size() > 0L + ? CacheEventDispatcher.New() + : null; + final Object internalKey = this.objectConverter.internalize(key); + V result; + + synchronized(this.cacheTable) + { + this.deleteCacheEntry(key); + + final CachedValue cachedValue = this.cacheTable.get(internalKey); + if(cachedValue == null || cachedValue.isExpiredAt(now)) + { + result = null; + } + else + { + this.cacheTable.remove(internalKey); + result = this.objectConverter.externalize(cachedValue.value(now)); + + if(eventDispatcher != null) + { + eventDispatcher.addEvent( + CacheEntryRemovedListener.class, + new CacheEvent<>(this, EventType.REMOVED, key, result, result) + ); + } + } + } + + if(eventDispatcher != null) + { + eventDispatcher.dispatch(this.listenerRegistrations); + } + if(isStatisticsEnabled) + { + final CacheStatisticsMXBean cacheStatisticsMXBean = this.cacheStatisticsMXBean; + final long duration = System.nanoTime() - start; + cacheStatisticsMXBean.addGetTimeNano(duration); + if(result != null) + { + cacheStatisticsMXBean.increaseCacheHits(1); + cacheStatisticsMXBean.increaseCacheRemovals(1); + cacheStatisticsMXBean.addRemoveTimeNano(duration); + } + else + { + cacheStatisticsMXBean.increaseCacheMisses(1); + } + } + + return result; + } + + @Override + public boolean replace(final K key, final V oldValue, final V newValue) + { + this.ensureOpen(); + + this.keyValidator.validate(key); + this.valueValidator.validate(newValue); + this.valueValidator.validate(oldValue); + + final boolean isStatisticsEnabled = this.isStatisticsEnabled.get(); + final long start = isStatisticsEnabled + ? System.nanoTime() + : 0; + + final long now = System.currentTimeMillis(); + final CacheEventDispatcher eventDispatcher = this.listenerRegistrations.size() > 0L + ? CacheEventDispatcher.New() + : null; + final Object internalKey = this.objectConverter.internalize(key); + long hitCount = 0; + boolean result; + + synchronized(this.cacheTable) + { + final CachedValue cachedValue = this.cacheTable.get(internalKey); + if(cachedValue == null || cachedValue.isExpiredAt(now)) + { + result = false; + } + else + { + hitCount++; + + final Object oldInternalValue = this.objectConverter.internalize(oldValue); + + if(cachedValue.value().equals(oldInternalValue)) + { + final CacheEntry entry = CacheEntry.New(key, newValue); + this.writeCacheEntry(entry); + + this.updateExpiryForUpdate(cachedValue, now); + + cachedValue.value( + this.objectConverter.internalize(newValue), + now + ); + + if(eventDispatcher != null) + { + eventDispatcher.addEvent( + CacheEntryUpdatedListener.class, + new CacheEvent<>(this, EventType.UPDATED, key, newValue, oldValue) + ); + } + + result = true; + } + else + { + this.updateExpiryForAccess(cachedValue, now); + + result = false; + } + } + } + + if(eventDispatcher != null) + { + eventDispatcher.dispatch(this.listenerRegistrations); + } + if(isStatisticsEnabled) + { + final CacheStatisticsMXBean cacheStatisticsMXBean = this.cacheStatisticsMXBean; + final long duration = System.nanoTime() - start; + if(result) + { + cacheStatisticsMXBean.increaseCachePuts(1); + cacheStatisticsMXBean.addPutTimeNano(duration); + } + cacheStatisticsMXBean.addGetTimeNano(duration); + if(hitCount == 1) + { + cacheStatisticsMXBean.increaseCacheHits(hitCount); + } + else + { + cacheStatisticsMXBean.increaseCacheMisses(1); + } + } + + return result; + } + + @Override + public boolean replace(final K key, final V value) + { + this.ensureOpen(); + + this.keyValidator.validate(key); + this.valueValidator.validate(value); + + final boolean isStatisticsEnabled = this.isStatisticsEnabled.get(); + final long start = isStatisticsEnabled + ? System.nanoTime() + : 0; + + final long now = System.currentTimeMillis(); + final CacheEventDispatcher eventDispatcher = this.listenerRegistrations.size() > 0L + ? CacheEventDispatcher.New() + : null; + final Object internalKey = this.objectConverter.internalize(key); + boolean result; + + synchronized(this.cacheTable) + { + final CachedValue cachedValue = this.cacheTable.get(internalKey); + if(cachedValue == null || cachedValue.isExpiredAt(now)) + { + result = false; + } + else + { + final V oldValue = this.objectConverter.externalize(cachedValue.value()); + + final CacheEntry entry = CacheEntry.New(key, value); + this.writeCacheEntry(entry); + + this.updateExpiryForUpdate(cachedValue, now); + + final Object newInternalValue = this.objectConverter.internalize(value); + cachedValue.value(newInternalValue, now); + + if(eventDispatcher != null) + { + eventDispatcher.addEvent( + CacheEntryUpdatedListener.class, + new CacheEvent<>(this, EventType.UPDATED, key, value, oldValue) + ); + } + + result = true; + } + } + + if(eventDispatcher != null) + { + eventDispatcher.dispatch(this.listenerRegistrations); + } + if(isStatisticsEnabled) + { + final CacheStatisticsMXBean cacheStatisticsMXBean = this.cacheStatisticsMXBean; + final long duration = System.nanoTime() - start; + cacheStatisticsMXBean.addGetTimeNano(duration); + if(result) + { + cacheStatisticsMXBean.increaseCachePuts(1); + cacheStatisticsMXBean.increaseCacheHits(1); + cacheStatisticsMXBean.addPutTimeNano(duration); + } + else + { + cacheStatisticsMXBean.increaseCacheMisses(1); + } + } + + return result; + } + + @Override + public V getAndReplace(final K key, final V value) + { + this.ensureOpen(); + + this.keyValidator.validate(key); + this.valueValidator.validate(value); + + final boolean isStatisticsEnabled = this.isStatisticsEnabled.get(); + final long start = isStatisticsEnabled + ? System.nanoTime() + : 0; + + final long now = System.currentTimeMillis(); + final CacheEventDispatcher eventDispatcher = this.listenerRegistrations.size() > 0L + ? CacheEventDispatcher.New() + : null; + final Object internalKey = this.objectConverter.internalize(key); + V result; + + synchronized(this.cacheTable) + { + final CachedValue cachedValue = this.cacheTable.get(internalKey); + if(cachedValue == null || cachedValue.isExpiredAt(now)) + { + result = null; + } + else + { + final V oldValue = this.objectConverter.externalize(cachedValue.value()); + + final CacheEntry entry = CacheEntry.New(key, value); + this.writeCacheEntry(entry); + + this.updateExpiryForUpdate(cachedValue, now); + + cachedValue.value( + this.objectConverter.internalize(value), + now + ); + + if(eventDispatcher != null) + { + eventDispatcher.addEvent( + CacheEntryUpdatedListener.class, + new CacheEvent<>(this, EventType.UPDATED, key, value, oldValue) + ); + } + + result = oldValue; + } + } + + if(eventDispatcher != null) + { + eventDispatcher.dispatch(this.listenerRegistrations); + } + if(isStatisticsEnabled) + { + final CacheStatisticsMXBean cacheStatisticsMXBean = this.cacheStatisticsMXBean; + final long duration = System.nanoTime() - start; + cacheStatisticsMXBean.addGetTimeNano(duration); + if(result != null) + { + cacheStatisticsMXBean.increaseCachePuts(1); + cacheStatisticsMXBean.increaseCacheHits(1); + cacheStatisticsMXBean.addPutTimeNano(duration); + } + else + { + cacheStatisticsMXBean.increaseCacheMisses(1); + } + } + + return result; + } + + @Override + public void removeAll(final Set keys) + { + this.ensureOpen(); + + keys.forEach(this.keyValidator::validate); + + final boolean isStatisticsEnabled = this.isStatisticsEnabled.get(); + final long now = System.currentTimeMillis(); + final CacheEventDispatcher eventDispatcher = this.listenerRegistrations.size() > 0L + ? CacheEventDispatcher.New() + : null; + final HashSet cacheWriterKeys = new HashSet<>(); + final HashSet deletedKeys = new HashSet<>(); + cacheWriterKeys.addAll(keys); + CacheException exception = null; + + synchronized(this.cacheTable) + { + if(this.cacheWriter != null && this.configuration.isWriteThrough()) + { + try + { + this.cacheWriter.deleteAll(cacheWriterKeys); + } + catch(final CacheWriterException e) + { + exception = e; + } + catch(final Exception e) + { + exception = new CacheWriterException(e); + } + + // At this point, cacheWriterKeys will contain only those that were _not_ written + // Now delete only those that the writer deleted + for(final K key : keys) + { + // only delete those keys that the writer deleted. per CacheWriter spec. + if(!cacheWriterKeys.contains(key)) + { + final Object internalKey = this.objectConverter.internalize(key); + final CachedValue cachedValue = this.cacheTable.remove(internalKey); + if(cachedValue != null) + { + deletedKeys.add(key); + + final V value = this.objectConverter.externalize(cachedValue.value()); + + if(cachedValue.isExpiredAt(now)) + { + this.processExpiries( + key, + internalKey, + eventDispatcher, + value + ); + } + else if(eventDispatcher != null) + { + eventDispatcher.addEvent( + CacheEntryRemovedListener.class, + new CacheEvent<>(this, EventType.REMOVED, key, value, value) + ); + } + } + } + } + } + else + { + for(final K key : keys) + { + // only delete those keys that the writer deleted. per CacheWriter spec. + final Object internalKey = this.objectConverter.internalize(key); + final CachedValue cachedValue = this.cacheTable.remove(internalKey); + if(cachedValue != null) + { + deletedKeys.add(key); + + final V value = this.objectConverter.externalize(cachedValue.value()); + + if(cachedValue.isExpiredAt(now)) + { + this.processExpiries( + key, + internalKey, + eventDispatcher, + value + ); + } + else if(eventDispatcher != null) + { + eventDispatcher.addEvent( + CacheEntryRemovedListener.class, + new CacheEvent<>(this, EventType.REMOVED, key, value, value) + ); + } + } + } + } + } + + if(eventDispatcher != null) + { + eventDispatcher.dispatch(this.listenerRegistrations); + } + if(isStatisticsEnabled) + { + this.cacheStatisticsMXBean.increaseCacheRemovals(deletedKeys.size()); + } + + if(exception != null) + { + throw exception; + } + } + + @Override + public void removeAll() + { + this.ensureOpen(); + + final boolean isStatisticsEnabled = this.isStatisticsEnabled.get(); + int removed = 0; + final long now = System.currentTimeMillis(); + final CacheEventDispatcher eventDispatcher = this.listenerRegistrations.size() > 0L + ? CacheEventDispatcher.New() + : null; + CacheException exception = null; + + synchronized(this.cacheTable) + { + final HashSet keys = new HashSet<>(); + this.cacheTable.keys().forEach(key -> keys.add(this.objectConverter.externalize(key))); + + final Set keysToDelete; + + if(this.cacheWriter != null && this.configuration.isWriteThrough()) + { + keysToDelete = new HashSet<>(keys); + + if(keysToDelete.size() > 0) + { + try + { + this.cacheWriter.deleteAll(keysToDelete); + } + catch(final CacheWriterException e) + { + exception = e; + } + catch(final Exception e) + { + exception = new CacheWriterException(e); + } + } + } + else + { + keysToDelete = Collections.emptySet(); + } + + // remove the deleted keys that were successfully deleted from the set + for(final K key : keys) + { + if(!keysToDelete.contains(key)) + { + final Object internalKey = this.objectConverter.internalize(key); + final CachedValue cachedValue = this.cacheTable.remove(internalKey); + final V value = this.objectConverter.externalize(cachedValue.value()); + + if(cachedValue.isExpiredAt(now)) + { + this.processExpiries( + key, + internalKey, + eventDispatcher, + value + ); + } + else + { + if(eventDispatcher != null) + { + eventDispatcher.addEvent( + CacheEntryRemovedListener.class, + new CacheEvent<>(this, EventType.REMOVED, key, value, value) + ); + } + removed++; + } + } + } + } + + if(eventDispatcher != null) + { + eventDispatcher.dispatch(this.listenerRegistrations); + } + if(isStatisticsEnabled) + { + this.cacheStatisticsMXBean.increaseCacheRemovals(removed); + } + + if(exception != null) + { + throw exception; + } + } + + @Override + public void clear() + { + this.ensureOpen(); + + synchronized(this.cacheTable) + { + this.cacheTable.clear(); + } + } + + @Override + public Iterator> iterator() + { + this.ensureOpen(); + + if(this.cacheLoader instanceof CacheStore) + { + final Iterator keys = ((CacheStore)this.cacheLoader).keys(); + final CacheEventDispatcher eventDispatcher = this.listenerRegistrations.size() > 0L + ? CacheEventDispatcher.New() + : null; + return new EntryIterator(new KeyToValueIterator(keys, eventDispatcher)); + } + + return new EntryIterator(this.cacheTable.iterator()); + } + + @Override + public void setStatisticsEnabled(final boolean enabled) + { + this.isStatisticsEnabled.set(enabled); + + this.updateConfiguration(c -> c.setStatisticsEnabled(enabled)); + + this.updateCacheObjectRegistration( + enabled, + this.cacheStatisticsMXBean, + MBeanServerUtils.MBeanType.CacheStatistics + ); + } + + @Override + public void setManagementEnabled(final boolean enabled) + { + this.updateConfiguration(c -> c.setManagementEnabled(enabled)); + + this.updateCacheObjectRegistration( + enabled, + this.cacheConfigurationMXBean, + MBeanServerUtils.MBeanType.CacheConfiguration + ); + } + + private void updateCacheObjectRegistration( + final boolean enabled , + final Object bean , + final MBeanType beanType + ) + { + if(enabled) + { + MBeanServerUtils.registerCacheObject(this, bean, beanType); + } + else + { + MBeanServerUtils.unregisterCacheObject(this, bean, beanType); + } + } + + @Override + public Map> invokeAll( + final Set keys , + final EntryProcessor entryProcessor, + final Object... arguments + ) + { + this.ensureOpen(); + + keys.forEach(this.keyValidator::validate); + + notNull(entryProcessor); + + final HashMap> map = new HashMap<>(); + for(final K key : keys) + { + EntryProcessorResult result = null; + try + { + final T t = this.invoke(key, entryProcessor, arguments); + result = t == null + ? null + : EntryProcessorResult.New(t); + } + catch(final Exception e) + { + result = EntryProcessorResult.New(e); + } + if(result != null) + { + map.put(key, result); + } + } + + return map; + } + + @Override + public T invoke( + final K key , + final EntryProcessor entryProcessor, + final Object... arguments + ) + throws EntryProcessorException + { + this.ensureOpen(); + + this.keyValidator.validate(key); + + final boolean isStatisticsEnabled = this.isStatisticsEnabled.get(); + long start = isStatisticsEnabled + ? System.nanoTime() + : 0; + + notNull(entryProcessor); + + final long now = System.currentTimeMillis(); + final CacheEventDispatcher eventDispatcher = this.listenerRegistrations.size() > 0L + ? CacheEventDispatcher.New() + : null; + final Object internalKey = this.objectConverter.internalize(key); + T result = null; + + synchronized(this.cacheTable) + { + final CachedValue cachedValue = this.cacheTable.get(internalKey); + final boolean isExpired = cachedValue != null && cachedValue.isExpiredAt(now); + + if(isExpired) + { + this.processExpiries( + key, + internalKey, + eventDispatcher, + this.objectConverter.externalize(cachedValue.value()) + ); + } + + if(isStatisticsEnabled) + { + final CacheStatisticsMXBean cacheStatisticsMXBean = this.cacheStatisticsMXBean; + if(cachedValue == null || isExpired) + { + cacheStatisticsMXBean.increaseCacheMisses(1); + } + else + { + cacheStatisticsMXBean.increaseCacheHits(1); + } + final long nanoTime = System.nanoTime(); + cacheStatisticsMXBean.addGetTimeNano(nanoTime - start); + // restart + start = nanoTime; + } + + final MutableCacheEntry entry = MutableCacheEntry.New( + this.objectConverter, + key, + cachedValue, + now, + this.configuration.isReadThrough() ? this.cacheLoader : null + ); + try + { + result = entryProcessor.process(entry, arguments); + } + catch(final CacheException e) + { + throw e; + } + catch(final Exception e) + { + throw new EntryProcessorException(e); + } + + this.finishInvocation( + key, + internalKey, + cachedValue, + entry, + start, + now, + eventDispatcher, + isStatisticsEnabled + ); + } + + if(eventDispatcher != null) + { + eventDispatcher.dispatch(this.listenerRegistrations); + } + + return result; + } + + @SuppressWarnings("incomplete-switch") + private void finishInvocation( + final K key , + final Object internalKey , + final CachedValue cachedValue , + final MutableCacheEntry entry , + final long start , + final long now , + final CacheEventDispatcher eventDispatcher , + final boolean isStatisticsEnabled + ) + { + switch(entry.getOperation()) + { + case ACCESS: + + this.updateExpiryForAccess(cachedValue, now); + + break; + + case CREATE: + case LOAD: + + this.finishInvocationCreateLoad( + key, + internalKey, + entry, + start, + now, + eventDispatcher, + isStatisticsEnabled + ); + + break; + + case UPDATE: + + this.finishInvocationUpdate( + key, + entry, + cachedValue, + start, + now, + eventDispatcher, + isStatisticsEnabled + ); + + break; + + case REMOVE: + + this.finishInvocationRemove( + key, + internalKey, + cachedValue, + start, + eventDispatcher, + isStatisticsEnabled + ); + + break; + } + } + + private void finishInvocationCreateLoad( + final K key , + final Object internalKey , + final MutableCacheEntry entry , + final long start , + final long now , + final CacheEventDispatcher eventDispatcher , + final boolean isStatisticsEnabled + ) + { + CachedValue cachedValue; + final CacheEntry e = CacheEntry.New(key, entry.getValue()); + + if(entry.getOperation() == MutableCacheEntry.Operation.CREATE) + { + this.writeCacheEntry(e); + } + + cachedValue = CachedValue.New( + this.objectConverter.internalize(entry.getValue()), + now, + this.expiryForCreation().getAdjustedTime(now) + ); + + if(cachedValue.isExpiredAt(now)) + { + final V previousValue = this.objectConverter.externalize(cachedValue.value()); + this.processExpiries( + key, + internalKey, + eventDispatcher, + previousValue + ); + } + else + { + this.putValue( + key, + entry.getValue(), + internalKey, + cachedValue, + eventDispatcher + ); + + // do not count LOAD as a put for cache statistics. + if(isStatisticsEnabled && entry.getOperation() == MutableCacheEntry.Operation.CREATE) + { + final CacheStatisticsMXBean cacheStatisticsMXBean = this.cacheStatisticsMXBean; + cacheStatisticsMXBean.increaseCachePuts(1); + cacheStatisticsMXBean.addPutTimeNano(System.nanoTime() - start); + } + } + } + + private void finishInvocationUpdate( + final K key , + final MutableCacheEntry entry , + final CachedValue cachedValue , + final long start , + final long now , + final CacheEventDispatcher eventDispatcher , + final boolean isStatisticsEnabled + ) + { + final V oldValue = this.objectConverter.externalize(cachedValue.value()); + + final CacheEntry e = CacheEntry.New(key, entry.getValue()); + this.writeCacheEntry(e); + + this.updateExpiryForUpdate(cachedValue, now); + + cachedValue.value( + this.objectConverter.internalize(entry.getValue()), + now + ); + + if(eventDispatcher != null) + { + eventDispatcher.addEvent( + CacheEntryUpdatedListener.class, + new CacheEvent<>(this, EventType.UPDATED, key, entry.getValue(), oldValue) + ); + } + if(isStatisticsEnabled) + { + final CacheStatisticsMXBean cacheStatisticsMXBean = this.cacheStatisticsMXBean; + cacheStatisticsMXBean.increaseCachePuts(1); + cacheStatisticsMXBean.addPutTimeNano(System.nanoTime() - start); + } + } + + private void finishInvocationRemove( + final K key , + final Object internalKey , + final CachedValue cachedValue , + final long start , + final CacheEventDispatcher eventDispatcher , + final boolean isStatisticsEnabled + ) + { + this.deleteCacheEntry(key); + + final V oldValue = cachedValue == null + ? null + : this.objectConverter.externalize(cachedValue.value()); + this.cacheTable.remove(internalKey); + + if(eventDispatcher != null) + { + eventDispatcher.addEvent( + CacheEntryRemovedListener.class, + new CacheEvent<>(this, EventType.REMOVED, key, oldValue, oldValue) + ); + } + if(isStatisticsEnabled) + { + final CacheStatisticsMXBean cacheStatisticsMXBean = this.cacheStatisticsMXBean; + cacheStatisticsMXBean.increaseCacheRemovals(1); + cacheStatisticsMXBean.addRemoveTimeNano(System.nanoTime() - start); + } + } + + private void ensureOpen() + { + if(this.isClosed.get()) + { + throw new IllegalStateException("Cache is closed"); + } + } + + private V getValue( + final K key , + final CacheEventDispatcher eventDispatcher , + final Reference cachedValueReference + ) + { + final boolean isStatisticsEnabled = this.isStatisticsEnabled.get(); + final long start = isStatisticsEnabled + ? System.nanoTime() + : 0; + + final long now = System.currentTimeMillis(); + final Object internalKey = this.objectConverter.internalize(key); + V value = null; + + synchronized(this.cacheTable) + { + CachedValue cachedValue = this.cacheTable.get(internalKey); + final boolean isExpired = cachedValue != null && cachedValue.isExpiredAt(now); + + if(cachedValue == null || isExpired) + { + if(isExpired) + { + this.processExpiries( + key, + internalKey, + eventDispatcher, + this.objectConverter.externalize(cachedValue.value()) + ); + } + + if(isStatisticsEnabled) + { + this.cacheStatisticsMXBean.increaseCacheMisses(1); + } + + value = this.loadCacheEntry(key, value); + + if(value != null) + { + final long creationTime = cachedValue != null + ? cachedValue.creationTime() + : now + ; + cachedValue = CachedValue.New( + this.objectConverter.internalize(value), + creationTime, + this.expiryForCreation().getAdjustedTime(creationTime) + ); + + if(cachedValue.isExpiredAt(now)) + { + value = null; + } + else + { + this.putValue( + key, + value, + internalKey, + cachedValue, + eventDispatcher + ); + } + } + } + else + { + value = this.objectConverter.externalize(cachedValue.value(now)); + this.updateExpiryForAccess(cachedValue, now); + + if(isStatisticsEnabled) + { + this.cacheStatisticsMXBean.increaseCacheHits(1); + } + } + + if(cachedValueReference != null) + { + cachedValueReference.set(cachedValue); + } + } + + if(isStatisticsEnabled) + { + this.cacheStatisticsMXBean.addGetTimeNano(System.nanoTime() - start); + } + + return value; + } + + private void putValue( + final K key , + final V value , + final Object internalKey , + final CachedValue cachedValue , + final CacheEventDispatcher eventDispatcher + ) + { + this.cacheTable.put(internalKey, cachedValue); + + if(eventDispatcher != null) + { + eventDispatcher.addEvent( + CacheEntryCreatedListener.class, + new CacheEvent<>(this, EventType.CREATED, key, value) + ); + } + } + + + @Override + public void evict(final Iterable> entriesToEvict) + { + long evictionCount = 0; + final CacheEventDispatcher eventDispatcher = this.listenerRegistrations.size() > 0L + ? CacheEventDispatcher.New() + : null; + + synchronized(this.cacheTable) + { + for(final KeyValue entryToEvict : entriesToEvict) + { + this.cacheTable.remove(entryToEvict.key()); + + final K evictedKey = this.objectConverter.externalize(entryToEvict.key()); + final V evictedValue = this.objectConverter.externalize(entryToEvict.value().value()); + + this.deleteCacheEntry(evictedKey); + + if(eventDispatcher != null) + { + eventDispatcher.addEvent( + CacheEntryRemovedListener.class, + new CacheEvent<>(this, EventType.REMOVED, evictedKey, evictedValue, evictedValue) + ); + } + + evictionCount++; + } + } + + if(this.isStatisticsEnabled.get() && evictionCount > 0) + { + if(eventDispatcher != null) + { + eventDispatcher.dispatch(this.listenerRegistrations); + } + this.cacheStatisticsMXBean.increaseCacheEvictions(evictionCount); + } + } + + private void updateExpiryForAccess(final CachedValue cachedValue, final long now ) + { + try + { + final Duration duration; + if((duration = this.expiryPolicy.getExpiryForAccess()) != null) + { + cachedValue.expiryTime(duration.getAdjustedTime(now)); + } + } + catch(final Throwable t) + { + // Spec says leave the expiry time untouched when we can't determine a duration + } + } + + private void updateExpiryForUpdate(final CachedValue cachedValue, final long now) + { + try + { + final Duration duration; + if((duration = this.expiryPolicy.getExpiryForUpdate()) != null) + { + cachedValue.expiryTime(duration.getAdjustedTime(now)); + } + } + catch(final Throwable t) + { + // Spec says leave the expiry time untouched when we can't determine a duration + } + } + + private void processExpiries( + final K key , + final Object internalKey , + final CacheEventDispatcher eventDispatcher, + final V expiredValue + ) + { + this.cacheTable.remove(internalKey); + + if(eventDispatcher != null) + { + eventDispatcher.addEvent( + CacheEntryExpiredListener.class, + new CacheEvent<>(this, EventType.EXPIRED, key, expiredValue, expiredValue) + ); + } + } + + private Duration expiryForCreation() + { + // Spec says if exception happens, a default duration should be used. + try + { + return this.expiryPolicy.getExpiryForCreation(); + } + catch(final Throwable t) + { + return Duration.ETERNAL; + } + } + + private void submit(final Runnable task) + { + this.executorService.submit(task); + } + + private V loadCacheEntry(final K key, final V value) + { + if(this.cacheLoader != null && this.configuration.isReadThrough()) + { + try + { + return this.cacheLoader.load(key); + } + catch(final CacheLoaderException e) + { + throw e; + } + catch(final Exception e) + { + throw new CacheLoaderException(e); + } + } + + return value; + } + + private void writeCacheEntry(final CacheEntry entry) + { + if(this.cacheWriter != null && this.configuration.isWriteThrough()) + { + try + { + this.cacheWriter.write(entry); + } + catch(final CacheWriterException e) + { + throw e; + } + catch(final Exception e) + { + throw new CacheWriterException(e); + } + } + } + + private void deleteCacheEntry(final K key) + { + if(this.cacheWriter != null && this.configuration.isWriteThrough()) + { + try + { + this.cacheWriter.delete(key); + } + catch(final CacheWriterException e) + { + throw e; + } + catch(final Exception e) + { + throw new CacheWriterException(e); + } + } + } + + private void closeIfCloseable(final Object obj) + { + if(obj instanceof Closeable) + { + try + { + ((Closeable)obj).close(); + } + catch(final IOException e) + { + throw new IORuntimeException(e); + } + } + } + + + @SuppressWarnings("synthetic-access") + private final class KeyToValueIterator implements Iterator> + { + private final Iterator keyIterator ; + private final CacheEventDispatcher eventDispatcher ; + private final Reference cachedValueReference; + + KeyToValueIterator(final Iterator keyIterator, final CacheEventDispatcher eventDispatcher) + { + super(); + this.keyIterator = keyIterator ; + this.eventDispatcher = eventDispatcher ; + this.cachedValueReference = X.Reference(null); + } + + @Override + public boolean hasNext() + { + return this.keyIterator.hasNext(); + } + + @Override + public KeyValue next() + { + final K key = this.keyIterator.next(); + Default.this.getValue(key, this.eventDispatcher, this.cachedValueReference); + return KeyValue.New(key, this.cachedValueReference.get()); + } + } + + + @SuppressWarnings("synthetic-access") + private final class EntryIterator implements Iterator> + { + private final Iterator> iterator ; + private CacheEntry nextEntry; + private CacheEntry lastEntry; + private final long now ; + private final boolean isStatisticsEnabled; + + EntryIterator(final Iterator> iterator) + { + super(); + this.iterator = iterator; + this.nextEntry = null; + this.lastEntry = null; + this.now = System.currentTimeMillis(); + this.isStatisticsEnabled = Cache.Default.this.isStatisticsEnabled.get(); + } + + private void fetch() + { + final long start = this.isStatisticsEnabled + ? System.nanoTime() + : 0; + + final ObjectConverter objectConverter = Cache.Default.this.objectConverter; + + while(this.nextEntry == null && this.iterator.hasNext()) + { + final KeyValue entry = this.iterator.next(); + final CachedValue cachedValue = entry.value(); + final K key = objectConverter.externalize(entry.key()); + try + { + if(!cachedValue.isExpiredAt(this.now)) + { + final V value = objectConverter.externalize(cachedValue.value(this.now)); + this.nextEntry = CacheEntry.New(key, value); + + try + { + Cache.Default.this.updateExpiryForAccess(cachedValue, this.now); + } + catch(final Throwable t) + { + // Spec says leave the expiry time untouched when we can't determine a duration + } + } + } + finally + { + if(this.isStatisticsEnabled && this.nextEntry != null) + { + final CacheStatisticsMXBean cacheStatisticsMXBean = Cache.Default.this.cacheStatisticsMXBean; + cacheStatisticsMXBean.increaseCacheHits(1); + cacheStatisticsMXBean.addGetTimeNano(System.nanoTime() - start); + } + } + } + } + + @Override + public boolean hasNext() + { + if(this.nextEntry == null) + { + this.fetch(); + } + return this.nextEntry != null; + } + + @Override + public Entry next() + { + if(this.hasNext()) + { + // remember the lastEntry (so that we call allow for removal) + this.lastEntry = this.nextEntry; + + // reset nextEntry to force fetching the next available entry + this.nextEntry = null; + + return this.lastEntry; + } + + throw new NoSuchElementException(); + } + + @Override + public void remove() + { + if(this.lastEntry == null) + { + throw new IllegalStateException("Must progress to the next entry to remove"); + } + + final long start = this.isStatisticsEnabled + ? System.nanoTime() + : 0; + int cacheRemovals = 0; + try + { + Cache.Default.this.deleteCacheEntry(this.lastEntry.getKey()); + + /* + * NOTE: There is the possibility here that the entry the application retrieved may have been + * replaced / expired or already removed since it retrieved it. We simply don't care here as + * multiple-threads are ok to remove and see such side-effects. + */ + this.iterator.remove(); + cacheRemovals++; + + // raise "remove" event + if(Cache.Default.this.listenerRegistrations.size() > 0L) + { + CacheEventDispatcher.New() + .addEvent( + CacheEntryRemovedListener.class, + new CacheEvent<>( + Cache.Default.this, + EventType.REMOVED, + this.lastEntry.getKey(), + this.lastEntry.getValue(), + this.lastEntry.getValue() + ) + ) + .dispatch(Cache.Default.this.listenerRegistrations); + } + } + finally + { + // reset lastEntry (we can't attempt to remove it again) + this.lastEntry = null; + if(this.isStatisticsEnabled && cacheRemovals > 0) + { + final CacheStatisticsMXBean cacheStatisticsMXBean = Cache.Default.this.cacheStatisticsMXBean; + cacheStatisticsMXBean.increaseCacheRemovals(cacheRemovals); + cacheStatisticsMXBean.addRemoveTimeNano(System.nanoTime() - start); + } + } + } + + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheConfiguration.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheConfiguration.java new file mode 100644 index 00000000..907fa023 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheConfiguration.java @@ -0,0 +1,1591 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import static org.eclipse.serializer.chars.XChars.notEmpty; +import static org.eclipse.serializer.util.X.coalesce; +import static org.eclipse.serializer.util.X.notNull; + +import java.io.File; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.util.Collections; +import java.util.HashSet; + +import javax.cache.CacheManager; +import javax.cache.configuration.CacheEntryListenerConfiguration; +import javax.cache.configuration.CompleteConfiguration; +import javax.cache.configuration.Factory; +import javax.cache.configuration.MutableConfiguration; +import javax.cache.event.CacheEntryListener; +import javax.cache.expiry.EternalExpiryPolicy; +import javax.cache.expiry.ExpiryPolicy; +import javax.cache.integration.CacheLoader; +import javax.cache.integration.CacheWriter; + +import org.eclipse.serializer.SerializerFoundation; +import org.eclipse.serializer.chars.VarString; +import org.eclipse.serializer.chars.XChars; +import org.eclipse.serializer.configuration.types.Configuration; +import org.eclipse.serializer.configuration.types.ConfigurationLoader; +import org.eclipse.serializer.configuration.types.ConfigurationParserIni; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + + +/** + * Extended {@link CompleteConfiguration} used by EclipseStore's {@link Cache}. + *

+ * Added features:
+ * - {@link #getEvictionManagerFactory()}
+ * - {@link #getSerializerFoundation()} + *

+ *

+ * Can be adapted to EclipseStore's generic {@link Configuration} layer. + * + * @param the key type + * @param the value type + */ +public interface CacheConfiguration extends CompleteConfiguration +{ + /** + * The property name which is used to hand the external configuration file path to the application. + *

+ * Either as system property or in the context's configuration, e.g. Spring's application.properties. + * + * @return "eclipsestore.cache.configuration.path" + */ + public static String PathProperty() + { + return "eclipsestore.cache.configuration.path"; + } + + /** + * The default name of the cache configuration resource. + * + * @see #load() + * + * @return "eclipsestore-cache.properties" + */ + public static String DefaultResourceName() + { + return "eclipsestore-cache.properties"; + } + + /** + * Tries to load the default configuration file. + *

+ * The search order is as follows: + *

    + *
  • The path set in the system property "eclipsestore.cache.configuration.path"
  • + *
  • The file named "eclipsestore-cache.properties" in + *
      + *
    • The classpath
    • + *
    • The application's directory
    • + *
    • The user home directory
    • + *
  • + *
+ * + * @see #PathProperty() + * @see #DefaultResourceName() + * + * @return the loaded configuration or null if none was found + */ + public static CacheConfiguration load() + { + return load(ConfigurationLoader.Defaults.defaultCharset()); + } + + /** + * Tries to load the default configuration file. + *

+ * The search order is as follows: + *

    + *
  • The path set in the system property "eclipsestore.cache.configuration.path"
  • + *
  • The file named "eclipsestore-cache.properties" in + *
      + *
    • The classpath
    • + *
    • The application's directory
    • + *
    • The user home directory
    • + *
  • + *
+ * + * @see #PathProperty() + * @see #DefaultResourceName() + * + * @param charset the charset used to load the configuration + * @return the loaded configuration or null if none was found + */ + public static CacheConfiguration load( + final Charset charset + ) + { + final String path = System.getProperty(PathProperty()); + if(!XChars.isEmpty(path)) + { + final CacheConfiguration configuration = load(path, charset); + if(configuration != null) + { + return configuration; + } + } + + final String defaultName = DefaultResourceName(); + final ClassLoader contextClassloader = Thread.currentThread().getContextClassLoader(); + final URL url = contextClassloader != null + ? contextClassloader.getResource(defaultName) + : javax.cache.configuration.Configuration.class.getResource("/" + defaultName); + if(url != null) + { + return load(url, charset); + } + + File file = new File(defaultName); + if(file.exists()) + { + return load(file, charset); + } + file = new File(System.getProperty("user.home"), defaultName); + if(file.exists()) + { + return load(file, charset); + } + + return null; + } + + /** + * Tries to load the default configuration file. + *

+ * The search order is as follows: + *

    + *
  • The path set in the system property "eclipsestore.cache.configuration.path"
  • + *
  • The file named "eclipsestore-cache.properties" in + *
      + *
    • The classpath
    • + *
    • The application's directory
    • + *
    • The user home directory
    • + *
  • + *
+ * + * @see #PathProperty() + * @see #DefaultResourceName() + * + * @param the key type + * @param the value type + * @param keyType the class for the key type + * @param valueType the class for value type + * @return the loaded configuration or null if none was found + */ + public static CacheConfiguration load( + final Class keyType , + final Class valueType + ) + { + return load( + ConfigurationLoader.Defaults.defaultCharset(), + keyType, + valueType + ); + } + + /** + * Tries to load the default configuration file. + *

+ * The search order is as follows: + *

    + *
  • The path set in the system property "eclipsestore.cache.configuration.path"
  • + *
  • The file named "eclipsestore-cache.properties" in + *
      + *
    • The classpath
    • + *
    • The application's directory
    • + *
    • The user home directory
    • + *
  • + *
+ * + * @see #PathProperty() + * @see #DefaultResourceName() + * + * @param the key type + * @param the value type + * @param charset the charset used to load the configuration + * @param keyType the class for the key type + * @param valueType the class for value type + * @return the loaded configuration or null if none was found + */ + public static CacheConfiguration load( + final Charset charset , + final Class keyType , + final Class valueType + ) + { + final String path = System.getProperty(PathProperty()); + if(!XChars.isEmpty(path)) + { + final CacheConfiguration configuration = load(path, charset, keyType, valueType); + if(configuration != null) + { + return configuration; + } + } + + final String defaultName = DefaultResourceName(); + final ClassLoader contextClassloader = Thread.currentThread().getContextClassLoader(); + final URL url = contextClassloader != null + ? contextClassloader.getResource(defaultName) + : javax.cache.configuration.Configuration.class.getResource("/" + defaultName); + if(url != null) + { + return load(url, charset, keyType, valueType); + } + + File file = new File(defaultName); + if(file.exists()) + { + return load(file, charset, keyType, valueType); + } + file = new File(System.getProperty("user.home"), defaultName); + if(file.exists()) + { + return load(file, charset, keyType, valueType); + } + + return null; + } + + /** + * Tries to load the configuration file from path. + *

+ * The load order is as follows: + *

    + *
  • The classpath
  • + *
  • As an URL
  • + *
  • As a file
  • + *
+ * + * @param path a classpath resource, a file path or an URL + * @return the configuration or null if none was found + */ + public static CacheConfiguration load( + final String path + ) + { + return load( + path, + ConfigurationLoader.Defaults.defaultCharset() + ); + } + + /** + * Tries to load the configuration file from path. + *

+ * The load order is as follows: + *

    + *
  • The classpath
  • + *
  • As an URL
  • + *
  • As a file
  • + *
+ * + * @param path a classpath resource, a file path or an URL + * @param charset the charset used to load the configuration + * @return the configuration or null if none was found + */ + public static CacheConfiguration load( + final String path , + final Charset charset + ) + { + final Configuration configuration = Configuration.Load( + ConfigurationLoader.New(path, charset), + ConfigurationParserIni.New() + ); + return Builder(configuration).build(); + } + + /** + * Tries to load the configuration file from path. + *

+ * The load order is as follows: + *

    + *
  • The classpath
  • + *
  • As an URL
  • + *
  • As a file
  • + *
+ * + * @param the key type + * @param the value type + * @param path a classpath resource, a file path or an URL + * @param keyType the class of the key type + * @param valueType the class of the value type + * @return the configuration or null if none was found + */ + public static CacheConfiguration load( + final String path , + final Class keyType , + final Class valueType + ) + { + return load( + path, + ConfigurationLoader.Defaults.defaultCharset(), + keyType, + valueType + ); + } + + /** + * Tries to load the configuration file from path. + *

+ * The load order is as follows: + *

    + *
  • The classpath
  • + *
  • As an URL
  • + *
  • As a file
  • + *
+ * + * @param the key type + * @param the value type + * @param path a classpath resource, a file path or an URL + * @param charset the charset used to load the configuration + * @param keyType the class of the key type + * @param valueType the class of the value type + * @return the configuration or null if none was found + */ + public static CacheConfiguration load( + final String path , + final Charset charset , + final Class keyType , + final Class valueType + ) + { + final ClassLoader contextClassloader = Thread.currentThread().getContextClassLoader(); + URL url = contextClassloader != null + ? contextClassloader.getResource(path) + : javax.cache.configuration.Configuration.class.getResource(path); + if(url != null) + { + return load(url, charset, keyType, valueType); + } + + try + { + url = new URL(path); + return load(url, charset, keyType, valueType); + } + catch(final MalformedURLException e) + { + final File file = new File(path); + if(file.exists()) + { + return load(file, charset, keyType, valueType); + } + } + + return null; + } + + /** + * Tries to load the configuration from path. + * + * @param path file system path + * @return the configuration + * @throws ConfigurationException if the configuration couldn't be loaded + */ + public static CacheConfiguration load( + final Path path + ) + { + return load( + path, + ConfigurationLoader.Defaults.defaultCharset() + ); + } + + /** + * Tries to load the configuration from path. + * + * @param path file system path + * @param charset the charset used to load the configuration + * @return the configuration + * @throws ConfigurationException if the configuration couldn't be loaded + */ + public static CacheConfiguration load( + final Path path , + final Charset charset + ) + { + final Configuration configuration = Configuration.Load( + ConfigurationLoader.New(path, charset), + ConfigurationParserIni.New() + ); + return Builder(configuration).build(); + } + + /** + * Tries to load the configuration from the file file. + * + * @param file file path + * @return the configuration + * @throws ConfigurationException if the configuration couldn't be loaded + */ + public static CacheConfiguration load( + final File file + ) + { + return load( + file, + ConfigurationLoader.Defaults.defaultCharset() + ); + } + + /** + * Tries to load the configuration from the file file. + * + * @param file file path + * @param charset the charset used to load the configuration + * @return the configuration + * @throws ConfigurationException if the configuration couldn't be loaded + */ + public static CacheConfiguration load( + final File file , + final Charset charset + ) + { + final Configuration configuration = Configuration.Load( + ConfigurationLoader.New(file, charset), + ConfigurationParserIni.New() + ); + return Builder(configuration).build(); + } + + /** + * Tries to load the configuration from the URL url. + * + * @param url URL path + * @return the configuration + * @throws ConfigurationException if the configuration couldn't be loaded + */ + public static CacheConfiguration load( + final URL url + ) + { + return load( + url, + ConfigurationLoader.Defaults.defaultCharset() + ); + } + + /** + * Tries to load the configuration from the URL url. + * + * @param url URL path + * @param charset the charset used to load the configuration + * @return the configuration + * @throws ConfigurationException if the configuration couldn't be loaded + */ + public static CacheConfiguration load( + final URL url , + final Charset charset + ) + { + final Configuration configuration = Configuration.Load( + ConfigurationLoader.New(url, charset), + ConfigurationParserIni.New() + ); + return Builder(configuration).build(); + } + + /** + * Tries to load the configuration from the {@link InputStream} inputStream. + * + * @param inputStream the stream to read from + * @return the configuration + * @throws ConfigurationException if the configuration couldn't be loaded + */ + public static CacheConfiguration load( + final InputStream inputStream + ) + { + return load( + inputStream, + ConfigurationLoader.Defaults.defaultCharset() + ); + } + + /** + * Tries to load the configuration from the {@link InputStream} inputStream. + * + * @param inputStream the stream to read from + * @param charset the charset used to load the configuration + * @return the configuration + * @throws ConfigurationException if the configuration couldn't be loaded + */ + public static CacheConfiguration load( + final InputStream inputStream, + final Charset charset + ) + { + final Configuration configuration = Configuration.Load( + ConfigurationLoader.New(inputStream, charset), + ConfigurationParserIni.New() + ); + return Builder(configuration).build(); + } + + /** + * Tries to load the configuration from path. + * + * @param the key type + * @param the value type + * @param path file system path + * @param keyType the class for the key type + * @param valueType the class for value type + * @return the configuration + * @throws ConfigurationException if the configuration couldn't be loaded + */ + public static CacheConfiguration load( + final Path path , + final Class keyType , + final Class valueType + ) + { + return load( + path, + ConfigurationLoader.Defaults.defaultCharset(), + keyType, + valueType + ); + } + + /** + * Tries to load the configuration from path. + * + * @param the key type + * @param the value type + * @param path file system path + * @param charset the charset used to load the configuration + * @param keyType the class for the key type + * @param valueType the class for value type + * @return the configuration + * @throws ConfigurationException if the configuration couldn't be loaded + */ + public static CacheConfiguration load( + final Path path , + final Charset charset , + final Class keyType , + final Class valueType + ) + { + final Configuration configuration = Configuration.Load( + ConfigurationLoader.New(path, charset), + ConfigurationParserIni.New() + ); + return Builder(keyType, valueType, configuration).build(); + } + + /** + * Tries to load the configuration from the file file. + * + * @param the key type + * @param the value type + * @param file file path + * @param keyType the class for the key type + * @param valueType the class for value type + * @return the configuration + * @throws ConfigurationException if the configuration couldn't be loaded + */ + public static CacheConfiguration load( + final File file , + final Class keyType , + final Class valueType + ) + { + return load( + file, + ConfigurationLoader.Defaults.defaultCharset(), + keyType, + valueType + ); + } + + /** + * Tries to load the configuration from the file file. + * + * @param the key type + * @param the value type + * @param file file path + * @param charset the charset used to load the configuration + * @param keyType the class for the key type + * @param valueType the class for value type + * @return the configuration + * @throws ConfigurationException if the configuration couldn't be loaded + */ + public static CacheConfiguration load( + final File file , + final Charset charset , + final Class keyType , + final Class valueType + ) + { + final Configuration configuration = Configuration.Load( + ConfigurationLoader.New(file, charset), + ConfigurationParserIni.New() + ); + return Builder(keyType, valueType, configuration).build(); + } + + /** + * Tries to load the configuration from the URL url. + * + * @param the key type + * @param the value type + * @param url URL path + * @param keyType the class for the key type + * @param valueType the class for value type + * @return the configuration + * @throws ConfigurationException if the configuration couldn't be loaded + */ + public static CacheConfiguration load( + final URL url , + final Class keyType , + final Class valueType + ) + { + return load( + url, + ConfigurationLoader.Defaults.defaultCharset(), + keyType, + valueType + ); + } + + /** + * Tries to load the configuration from the URL url. + * + * @param the key type + * @param the value type + * @param url URL path + * @param charset the charset used to load the configuration + * @param keyType the class for the key type + * @param valueType the class for value type + * @return the configuration + * @throws ConfigurationException if the configuration couldn't be loaded + */ + public static CacheConfiguration load( + final URL url , + final Charset charset , + final Class keyType , + final Class valueType + ) + { + final Configuration configuration = Configuration.Load( + ConfigurationLoader.New(url, charset), + ConfigurationParserIni.New() + ); + return Builder(keyType, valueType, configuration).build(); + } + + /** + * Tries to load the configuration from the {@link InputStream} inputStream. + * + * @param the key type + * @param the value type + * @param inputStream the stream to read from + * @param keyType the class for the key type + * @param valueType the class for value type + * @return the configuration + * @throws ConfigurationException if the configuration couldn't be loaded + */ + public static CacheConfiguration load( + final InputStream inputStream, + final Class keyType , + final Class valueType + ) + { + return load( + inputStream, + ConfigurationLoader.Defaults.defaultCharset(), + keyType, + valueType + ); + } + + /** + * Tries to load the configuration from the {@link InputStream} inputStream. + * + * @param the key type + * @param the value type + * @param inputStream the stream to read from + * @param charset the charset used to load the configuration + * @param keyType the class for the key type + * @param valueType the class for value type + * @return the configuration + * @throws ConfigurationException if the configuration couldn't be loaded + */ + public static CacheConfiguration load( + final InputStream inputStream, + final Charset charset , + final Class keyType , + final Class valueType + ) + { + final Configuration configuration = Configuration.Load( + ConfigurationLoader.New(inputStream, charset), + ConfigurationParserIni.New() + ); + return Builder(keyType, valueType, configuration).build(); + } + + + /** + * Gets the {@link javax.cache.configuration.Factory} for the + * {@link EvictionManager}, if any. + * + * @return the {@link javax.cache.configuration.Factory} for the + * {@link EvictionManager} or null if none has been set. + */ + public Factory> getEvictionManagerFactory(); + + /** + * Gets the serializer foundation. + * + * @return the foundation which the serializer will be based on + */ + public SerializerFoundation getSerializerFoundation(); + + /** + * Creates a new {@link Builder} for a {@link CacheConfiguration}. + * + * @param the key type + * @param the value type + * @param keyType the class for the key type + * @param valueType the class for value type + * @return the newly created builder + */ + public static Builder Builder( + final Class keyType , + final Class valueType + ) + { + return new Builder.Default<>(keyType, valueType); + } + + /** + * Creates a new {@link Builder} for a {@link CacheConfiguration}, which uses + * the storageManager as a backing store. + * + * @param the key type + * @param the value type + * @param keyType the class for the key type + * @param valueType the class for value type + * @param cacheName the slot name for the data in the {@link EmbeddedStorageManager}'s root, + * usually the {@link Cache}'s name + * @param storageManager the {@link EmbeddedStorageManager} to use as a backing store + * @return the newly created builder + */ + public static Builder Builder( + final Class keyType , + final Class valueType , + final String cacheName , + final EmbeddedStorageManager storageManager + ) + { + return Builder( + keyType, + valueType, + CachingProvider.defaultURI(), + cacheName, + storageManager + ); + } + + /** + * Creates a new {@link Builder} for a {@link CacheConfiguration}, which uses + * the storageManager as a backing store. + * + * @param the key type + * @param the value type + * @param keyType the class for the key type + * @param valueType the class for value type + * @param uri prefix of the slot name for the data in the {@link EmbeddedStorageManager}'s root + * @param cacheName suffix of slot name for the data in the {@link EmbeddedStorageManager}'s root + * @param storageManager the {@link EmbeddedStorageManager} to use as a backing store + * @return the newly created builder + */ + public static Builder Builder( + final Class keyType, + final Class valueType, + final URI uri, + final String cacheName, + final EmbeddedStorageManager storageManager + ) + { + notNull(uri); + notEmpty(cacheName); + notNull(storageManager); + + final String cacheKey = uri.toString() + "::" + cacheName; + final CacheStore cacheStore = CacheStore.New(cacheKey, storageManager); + + return Builder(keyType, valueType) + .cacheLoaderFactory(() -> cacheStore) + .cacheWriterFactory(() -> cacheStore) + .readThrough() + .writeThrough(); + } + + /** + * Creates a new {@link Builder} for a {@link CacheConfiguration}, which uses + * the generic EclipseStore configuration's values. + * + * @param configuration the {@link Configuration} to take the initial values from + * @return the newly created builder + */ + public static Builder Builder( + final Configuration configuration + ) + { + return CacheConfigurationBuilderConfigurationBased.New() + .buildCacheConfiguration(configuration) + ; + } + + /** + * Creates a new {@link Builder} for a {@link CacheConfiguration}, which uses + * the generic EclipseStore configuration's values. + * + * @param the key type + * @param the value type + * @param keyType the class for the key type + * @param valueType the class for value type + * @param configuration the {@link Configuration} to take the initial values from + * @return the newly created builder + */ + public static Builder Builder( + final Class keyType , + final Class valueType , + final Configuration configuration + ) + { + return CacheConfigurationBuilderConfigurationBased.New() + .buildCacheConfiguration( + configuration, + Builder(keyType, valueType) + ); + } + + + public static interface Builder + { + /** + * Add a configuration for a {@link CacheEntryListener}. + * + * @param listenerConfiguration the + * {@link CacheEntryListenerConfiguration} + * @return this + */ + public Builder addListenerConfiguration(CacheEntryListenerConfiguration listenerConfiguration); + + /** + * Set the {@link CacheLoader} {@link Factory}. + * + * @param cacheLoaderFactory the {@link CacheLoader} {@link Factory} + * @return this + */ + public Builder cacheLoaderFactory(Factory> cacheLoaderFactory); + + /** + * Set the {@link CacheWriter} {@link Factory}. + * + * @param cacheWriterFactory the {@link CacheWriter} {@link Factory} + * @return this + */ + public Builder cacheWriterFactory(Factory> cacheWriterFactory); + + /** + * Set the {@link Factory} for the {@link ExpiryPolicy}. If null + * is specified the default {@link ExpiryPolicy} is used. + *

+ * Only one expiry policy can be set for a cache. The last policy applied + * before cache construction will be the one used. + * + * @param expiryPolicyFactory + * the {@link ExpiryPolicy} {@link Factory} + * @return this + * + * @see CacheConfiguration#DefaultExpiryPolicyFactory() + */ + public Builder expiryPolicyFactory(Factory expiryPolicyFactory); + + /** + * Set the {@link EvictionManager} {@link Factory}. If null + * is specified the default {@link EvictionManager} is used. + *

+ * Only one eviction manager can be set for a cache. The last manager applied + * before cache construction will be the one used. + * + * @param evictionManagerFactory the {@link EvictionManager} {@link Factory} + * @return this + * + * @see CacheConfiguration#DefaultEvictionManagerFactory() + */ + public Builder evictionManagerFactory(Factory> evictionManagerFactory); + + /** + * Set that read-through caching should be used. + *

+ * It is an invalid configuration to use this without specifying a + * {@link CacheLoader} {@link Factory}. + * @return this + */ + public default Builder readThrough() + { + return this.readThrough(true); + } + + /** + * Set if read-through caching should be used. + *

+ * It is an invalid configuration to set this to true without specifying a + * {@link CacheLoader} {@link Factory}. + * + * @param readThrough + * true if read-through is required + * @return this + */ + public Builder readThrough(boolean readThrough); + + /** + * Set that write-through caching should be used. + *

+ * It is an invalid configuration to use this without specifying a + * {@link CacheWriter} {@link Factory}. + * @return this + */ + public default Builder writeThrough() + { + return this.writeThrough(true); + } + + /** + * Set if write-through caching should be used. + *

+ * It is an invalid configuration to set this to true without specifying a + * {@link CacheWriter} {@link Factory}. + * + * @param writeThrough + * true if write-through is required + * @return this + */ + public Builder writeThrough(boolean writeThrough); + + /** + * Set that store-by-value semantics should be used. + * @return this + */ + public default Builder storeByValue() + { + return this.storeByValue(true); + } + + /** + * Set that store-by-reference semantics should be used. + * @return this + */ + public default Builder storeByReference() + { + return this.storeByValue(false); + } + + /** + * Set if a configured cache should use store-by-value or store-by-reference + * semantics. + * + * @param storeByValue + * true if store-by-value is required, + * false for store-by-reference + * @return this + */ + public Builder storeByValue(boolean storeByValue); + + /** + * Enables statistics gathering. + *

+ * Statistics may be enabled or disabled at runtime via + * {@link CacheManager#enableStatistics(String, boolean)} or + * {@link Cache#setStatisticsEnabled(boolean)}. + * @return this + */ + public default Builder enableStatistics() + { + return this.enableStatistics(true); + } + + /** + * Disables statistics gathering. + *

+ * Statistics may be enabled or disabled at runtime via + * {@link CacheManager#enableStatistics(String, boolean)} or + * {@link Cache#setStatisticsEnabled(boolean)}. + * @return this + */ + public default Builder disableStatistics() + { + return this.enableStatistics(false); + } + + /** + * Sets whether statistics gathering is enabled. + *

+ * Statistics may be enabled or disabled at runtime via + * {@link CacheManager#enableStatistics(String, boolean)} or + * {@link Cache#setStatisticsEnabled(boolean)}. + * + * @param statisticsEnabled + * true to enable statistics, false to disable. + * @return this + */ + public Builder enableStatistics(final boolean statisticsEnabled); + + /** + * Enables the management bean. + *

+ * Management may be enabled or disabled at runtime via + * {@link CacheManager#enableManagement(String, boolean)} or + * {@link Cache#setManagementEnabled(boolean)}. + * @return this + */ + public default Builder enableManagement() + { + return this.enableManagement(true); + } + + /** + * Disables the management bean. + *

+ * Management may be enabled or disabled at runtime via + * {@link CacheManager#enableManagement(String, boolean)} or + * {@link Cache#setManagementEnabled(boolean)}. + * @return this + */ + public default Builder disableManagement() + { + return this.enableManagement(false); + } + + /** + * Sets whether the management bean is enabled. + *

+ * Management may be enabled or disabled at runtime via + * {@link CacheManager#enableManagement(String, boolean)} or + * {@link Cache#setManagementEnabled(boolean)}. + * + * @param managementEnabled + * true to enable statistics, false to disable. + * @return this + */ + public Builder enableManagement(final boolean managementEnabled); + + /** + * Set the serializer foundation. + * + * @param serializerFoundation the foundation which the serializer will be based on + * @return this + */ + public Builder serializerFoundation(SerializerFoundation serializerFoundation); + + /** + * Builds a {@link CacheConfiguration} based on the values of this {@link Builder}. + * + * @return the created configuration + */ + public CacheConfiguration build(); + + public static class Default implements Builder + { + private final Class keyType; + private final Class valueType; + private HashSet> listenerConfigurations; + private Factory> cacheLoaderFactory; + private Factory> cacheWriterFactory; + private Factory expiryPolicyFactory; + private Factory> evictionManagerFactory; + private boolean readThrough; + private boolean writeThrough; + private boolean storeByValue; + private boolean statisticsEnabled; + private boolean managementEnabled; + private SerializerFoundation serializerFoundation; + + Default(final Class keyType, final Class valueType) + { + super(); + + this.keyType = notNull(keyType); + this.valueType = notNull(valueType); + } + + @Override + public Builder + addListenerConfiguration(final CacheEntryListenerConfiguration listenerConfiguration) + { + this.listenerConfigurations.add(listenerConfiguration); + return this; + } + + @Override + public Builder cacheLoaderFactory(final Factory> cacheLoaderFactory) + { + this.cacheLoaderFactory = cacheLoaderFactory; + return this; + } + + @Override + public Builder cacheWriterFactory(final Factory> cacheWriterFactory) + { + this.cacheWriterFactory = cacheWriterFactory; + return this; + } + + @Override + public Builder expiryPolicyFactory(final Factory expiryPolicyFactory) + { + this.expiryPolicyFactory = expiryPolicyFactory; + return this; + } + + @Override + public Builder evictionManagerFactory(final Factory> evictionManagerFactory) + { + this.evictionManagerFactory = evictionManagerFactory; + return this; + } + + @Override + public Builder readThrough(final boolean readThrough) + { + this.readThrough = readThrough; + return this; + } + + @Override + public Builder writeThrough(final boolean writeThrough) + { + this.writeThrough = writeThrough; + return this; + } + + @Override + public Builder storeByValue(final boolean storeByValue) + { + this.storeByValue = storeByValue; + return this; + } + + @Override + public Builder enableStatistics(final boolean statisticsEnabled) + { + this.statisticsEnabled = statisticsEnabled; + return this; + } + + @Override + public Builder enableManagement(final boolean managementEnabled) + { + this.managementEnabled = managementEnabled; + return this; + } + + @Override + public Builder serializerFoundation(final SerializerFoundation serializerFoundation) + { + this.serializerFoundation = serializerFoundation; + return this; + } + + @Override + public CacheConfiguration build() + { + final Factory expiryPolicyFactory = coalesce( + this.expiryPolicyFactory, + DefaultExpiryPolicyFactory() + ); + + final Factory> evictionManagerFactory = coalesce( + this.evictionManagerFactory, + DefaultEvictionManagerFactory() + ); + + final SerializerFoundation serializerFoundation = coalesce( + this.serializerFoundation, + SerializerFoundation.New() + ); + + return new CacheConfiguration.Default<>(this.keyType, + this.valueType, + this.listenerConfigurations, + this.cacheLoaderFactory, + this.cacheWriterFactory, + expiryPolicyFactory, + evictionManagerFactory, + this.readThrough, + this.writeThrough, + this.storeByValue, + this.statisticsEnabled, + this.managementEnabled, + serializerFoundation + ); + } + + } + + } + + /** + * @return the default {@link ExpiryPolicy} {@link Factory}, which is eternal. + */ + public static Factory DefaultExpiryPolicyFactory() + { + return EternalExpiryPolicy.factoryOf(); + } + + /** + * @param the key type + * @param the value type + * @return the default {@link EvictionManager} {@link Factory}, which doesn't evict at all. + */ + public static Factory> DefaultEvictionManagerFactory() + { + return () -> null; + } + + /** + * Creates a new {@link CacheConfiguration} based on a {@link javax.cache.configuration.Configuration}. + * + * @param the key type + * @param the value type + * @param other the configuration to take the values from + * @return the newly created configuration + */ + public static CacheConfiguration New(final javax.cache.configuration.Configuration other) + { + final HashSet> listenerConfigurations = new HashSet<>(); + + if(other instanceof CompleteConfiguration) + { + final CompleteConfiguration complete = (CompleteConfiguration)other; + + for(final CacheEntryListenerConfiguration listenerConfig : complete + .getCacheEntryListenerConfigurations()) + { + listenerConfigurations.add(listenerConfig); + } + + final Factory expiryPolicyFactory = coalesce( + complete.getExpiryPolicyFactory(), + DefaultExpiryPolicyFactory() + ); + + final Factory> evictionManagerFactory; + final SerializerFoundation serializerFoundation; + if(other instanceof CacheConfiguration) + { + final CacheConfiguration msCacheConfig = (CacheConfiguration)other; + evictionManagerFactory = msCacheConfig.getEvictionManagerFactory(); + serializerFoundation = msCacheConfig.getSerializerFoundation(); + } + else + { + evictionManagerFactory = DefaultEvictionManagerFactory(); + serializerFoundation = SerializerFoundation.New(); + } + + return new Default<>( + complete.getKeyType(), + complete.getValueType(), + listenerConfigurations, + complete.getCacheLoaderFactory(), + complete.getCacheWriterFactory(), + expiryPolicyFactory, + evictionManagerFactory, + complete.isReadThrough(), + complete.isWriteThrough(), + complete.isStoreByValue(), + complete.isStatisticsEnabled(), + complete.isManagementEnabled(), + serializerFoundation + ); + } + + return new Default<>( + other.getKeyType(), + other.getValueType(), + listenerConfigurations, + null, + null, + DefaultExpiryPolicyFactory(), + DefaultEvictionManagerFactory(), + false, + false, + other.isStoreByValue(), + false, + false, + SerializerFoundation.New()); + } + + public static class Default extends MutableConfiguration implements CacheConfiguration + { + private final Factory> evictionManagerFactory; + private final SerializerFoundation serializerFoundation; + + Default( + final Class keyType, + final Class valueType, + final HashSet> listenerConfigurations, + final Factory> cacheLoaderFactory, + final Factory> cacheWriterFactory, + final Factory expiryPolicyFactory, + final Factory> evictionManagerFactory, + final boolean isReadThrough, + final boolean isWriteThrough, + final boolean isStoreByValue, + final boolean isStatisticsEnabled, + final boolean isManagementEnabled, + final SerializerFoundation serializerFoundation + ) + { + super(); + + this.keyType = keyType; + this.valueType = valueType; + if(listenerConfigurations != null) + { + this.listenerConfigurations.addAll(listenerConfigurations); + } + this.cacheLoaderFactory = cacheLoaderFactory; + this.cacheWriterFactory = cacheWriterFactory; + this.expiryPolicyFactory = expiryPolicyFactory; + this.evictionManagerFactory = evictionManagerFactory; + this.isReadThrough = isReadThrough; + this.isWriteThrough = isWriteThrough; + this.isStatisticsEnabled = isStatisticsEnabled; + this.isStoreByValue = isStoreByValue; + this.isManagementEnabled = isManagementEnabled; + this.serializerFoundation = serializerFoundation; + } + + @Override + public Class getKeyType() + { + return this.keyType; + } + + @Override + public Class getValueType() + { + return this.valueType; + } + + @Override + public Iterable> getCacheEntryListenerConfigurations() + { + return this.listenerConfigurations != null + ? this.listenerConfigurations + : Collections.emptyList(); + } + + @Override + public Factory> getEvictionManagerFactory() + { + return this.evictionManagerFactory; + } + + @Override + public SerializerFoundation getSerializerFoundation() + { + return this.serializerFoundation; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + (this.cacheLoaderFactory == null ? 0 : this.cacheLoaderFactory.hashCode()); + result = prime * result + (this.cacheWriterFactory == null ? 0 : this.cacheWriterFactory.hashCode()); + result = prime * result + (this.expiryPolicyFactory == null ? 0 : this.expiryPolicyFactory.hashCode()); + result = prime * result + (this.isManagementEnabled ? 1231 : 1237); + result = prime * result + (this.isReadThrough ? 1231 : 1237); + result = prime * result + (this.isStatisticsEnabled ? 1231 : 1237); + result = prime * result + (this.isStoreByValue ? 1231 : 1237); + result = prime * result + (this.isWriteThrough ? 1231 : 1237); + result = prime * result + (this.keyType == null ? 0 : this.keyType.hashCode()); + result = prime * result + (this.listenerConfigurations == null ? 0 : this.listenerConfigurations.hashCode()); + result = prime * result + (this.valueType == null ? 0 : this.valueType.hashCode()); + result = prime * result + (this.evictionManagerFactory == null ? 0 : this.evictionManagerFactory.hashCode()); + result = prime * result + (this.serializerFoundation == null ? 0 : this.serializerFoundation.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) + { + if(this == obj) + { + return true; + } + if(!(obj instanceof CacheConfiguration)) + { + return false; + } + final CacheConfiguration other = (CacheConfiguration)obj; + if(this.cacheLoaderFactory == null) + { + if(other.getCacheLoaderFactory() != null) + { + return false; + } + } + else if(!this.cacheLoaderFactory.equals(other.getCacheLoaderFactory())) + { + return false; + } + if(this.cacheWriterFactory == null) + { + if(other.getCacheWriterFactory() != null) + { + return false; + } + } + else if(!this.cacheWriterFactory.equals(other.getCacheWriterFactory())) + { + return false; + } + if(this.expiryPolicyFactory == null) + { + if(other.getExpiryPolicyFactory() != null) + { + return false; + } + } + else if(!this.expiryPolicyFactory.equals(other.getExpiryPolicyFactory())) + { + return false; + } + if(this.isManagementEnabled != other.isManagementEnabled()) + { + return false; + } + if(this.isReadThrough != other.isReadThrough()) + { + return false; + } + if(this.isStatisticsEnabled != other.isStatisticsEnabled()) + { + return false; + } + if(this.isStoreByValue != other.isStoreByValue()) + { + return false; + } + if(this.isWriteThrough != other.isWriteThrough()) + { + return false; + } + if(this.keyType == null) + { + if(other.getKeyType() != null) + { + return false; + } + } + else if(!this.keyType.equals(other.getKeyType())) + { + return false; + } + if(this.listenerConfigurations == null) + { + if(other.getCacheEntryListenerConfigurations() != null) + { + return false; + } + } + else if(!this.listenerConfigurations.equals(other.getCacheEntryListenerConfigurations())) + { + return false; + } + if(this.valueType == null) + { + if(other.getValueType() != null) + { + return false; + } + } + else if(!this.valueType.equals(other.getValueType())) + { + return false; + } + if(this.evictionManagerFactory == null) + { + if(other.getEvictionManagerFactory() != null) + { + return false; + } + } + else if(!this.evictionManagerFactory.equals(other.getEvictionManagerFactory())) + { + return false; + } + if(this.serializerFoundation == null) + { + if(other.getSerializerFoundation() != null) + { + return false; + } + } + else if(!this.serializerFoundation.equals(other.getSerializerFoundation())) + { + return false; + } + return true; + } + + + @Override + public String toString() + { + return VarString.New() + .add("keyType=").add(this.keyType.toString()).lf() + .add("valueType=").add(this.valueType.toString()).lf() + .add("listenerConfigurations=").add(this.listenerConfigurations).lf() + .add("cacheLoaderFactory=").add(this.cacheLoaderFactory).lf() + .add("cacheWriterFactory=").add(this.cacheWriterFactory).lf() + .add("expiryPolicyFactory=").add(this.expiryPolicyFactory).lf() + .add("isReadThrough=").add(this.isReadThrough).lf() + .add("isWriteThrough=").add(this.isWriteThrough).lf() + .add("isStatisticsEnabled=").add(this.isStatisticsEnabled).lf() + .add("isStoreByValue=").add(this.isStoreByValue).lf() + .add("isManagementEnabled=").add(this.isManagementEnabled) + .toString() + ; + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheConfigurationBuilderConfigurationBased.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheConfigurationBuilderConfigurationBased.java new file mode 100644 index 00000000..798a032a --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheConfigurationBuilderConfigurationBased.java @@ -0,0 +1,233 @@ +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import static org.eclipse.serializer.util.X.notNull; + +import java.lang.reflect.InvocationTargetException; + +import javax.cache.CacheException; +import javax.cache.configuration.Factory; + +import org.eclipse.serializer.chars.XChars; +import org.eclipse.serializer.configuration.types.Configuration; +import org.eclipse.serializer.configuration.types.ConfigurationLoader; +import org.eclipse.serializer.configuration.types.ConfigurationParserIni; +import org.eclipse.serializer.configuration.types.ConfigurationParserXml; +import org.eclipse.store.storage.embedded.configuration.types.EmbeddedStorageFoundationCreatorConfigurationBased; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + + +public interface CacheConfigurationBuilderConfigurationBased +{ + @FunctionalInterface + public static interface ClassResolver + { + public Class loadClass(String name) throws ClassNotFoundException; + + + public static ClassResolver New() + { + return Class::forName; + } + } + + + public CacheConfiguration.Builder buildCacheConfiguration( + Configuration configuration + ); + + public CacheConfiguration.Builder buildCacheConfiguration( + Configuration configuration, CacheConfiguration.Builder builder + ); + + + public static CacheConfigurationBuilderConfigurationBased New() + { + return new CacheConfigurationBuilderConfigurationBased.Default( + ClassResolver.New() + ); + } + + public static CacheConfigurationBuilderConfigurationBased New( + final ClassResolver classResolver + ) + { + return new CacheConfigurationBuilderConfigurationBased.Default( + notNull(classResolver) + ); + } + + + public static class Default implements + CacheConfigurationBuilderConfigurationBased, + CacheConfigurationPropertyNames + { + private final ClassResolver classResolver; + + Default( + final ClassResolver classResolver + ) + { + super(); + this.classResolver = classResolver; + } + + @Override + public CacheConfiguration.Builder buildCacheConfiguration( + final Configuration configuration + ) + { + final CacheConfiguration.Builder builder = CacheConfiguration.Builder( + this.getClass(configuration, KEY_TYPE ), + this.getClass(configuration, VALUE_TYPE) + ); + + return this.buildCacheConfiguration(configuration, builder); + } + + @Override + public CacheConfiguration.Builder buildCacheConfiguration( + final Configuration configuration, + final CacheConfiguration.Builder builder + ) + { + configuration.opt(EXPIRY_POLICY_FACTORY).ifPresent(value -> + builder.expiryPolicyFactory(this.valueAsFactory(value)) + ); + configuration.opt(EVICTION_MANAGER_FACTORY).ifPresent(value -> + builder.evictionManagerFactory(this.valueAsFactory(value)) + ); + configuration.optBoolean(STORE_BY_VALUE).ifPresent(value -> + builder.storeByValue(value) + ); + configuration.optBoolean(STATISTICS_ENABLED).ifPresent(value -> + builder.enableStatistics(value) + ); + configuration.optBoolean(MANAGEMENT_ENABLED).ifPresent(value -> + builder.enableManagement(value) + ); + + final CacheStore cacheStore = this.buildCacheStore(configuration); + if(cacheStore != null) + { + builder + .cacheLoaderFactory(() -> cacheStore) + .cacheWriterFactory(() -> cacheStore) + .readThrough(configuration.optBoolean(READ_THROUGH).orElse(true)) + .writeThrough(configuration.optBoolean(WRITE_THROUGH).orElse(true)) + ; + } + else + { + configuration.opt(CACHE_LOADER_FACTORY).ifPresent(value -> + { + builder + .cacheLoaderFactory(this.valueAsFactory(value)) + .readThrough(configuration.optBoolean(READ_THROUGH).orElse(true)) + ; + }); + configuration.opt(CACHE_WRITER_FACTORY).ifPresent(value -> + { + builder + .cacheWriterFactory(this.valueAsFactory(value)) + .writeThrough(configuration.optBoolean(WRITE_THROUGH).orElse(true)) + ; + }); + } + + return builder; + } + + private CacheStore buildCacheStore( + final Configuration configuration + ) + { + Configuration storageConfiguration = configuration.child(STORAGE); + if(storageConfiguration == null) + { + final String resourceName = configuration.get(STORAGE_CONFIGURATION_RESOURCE_NAME); + if(!XChars.isEmpty(resourceName)) + { + storageConfiguration = Configuration.Load( + ConfigurationLoader.New(resourceName), + resourceName.toLowerCase().endsWith(".xml") + ? ConfigurationParserXml.New() + : ConfigurationParserIni.New() + ); + } + } + if(storageConfiguration != null) + { + final EmbeddedStorageManager storageManager = EmbeddedStorageFoundationCreatorConfigurationBased + .New(storageConfiguration) + .createEmbeddedStorageFoundation() + .createEmbeddedStorageManager() + ; + final String cacheKey = storageConfiguration.opt(STORAGE_KEY) + .orElse(CachingProvider.defaultURI() + "::cache") + ; + return CacheStore.New(cacheKey, storageManager); + } + + return null; + } + + private Class getClass( + final Configuration configuration, + final String key + ) + { + final String name = configuration.opt(key).orElse(null); + + try + { + return XChars.isEmpty(name) + ? Object.class + : this.classResolver.loadClass(name) + ; + } + catch(final ClassNotFoundException e) + { + throw new CacheException(e); + } + } + + @SuppressWarnings("unchecked") + private Factory valueAsFactory( + final String value + ) + { + try + { + return Factory.class.cast( + this.classResolver + .loadClass(value) + .getDeclaredConstructor() + .newInstance() + ); + } + catch(ClassNotFoundException | ClassCastException | + InstantiationException | IllegalAccessException | + NoSuchMethodException | InvocationTargetException e + ) + { + throw new CacheException(e); + } + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheConfigurationMXBean.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheConfigurationMXBean.java new file mode 100644 index 00000000..c133c719 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheConfigurationMXBean.java @@ -0,0 +1,78 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import javax.cache.configuration.CompleteConfiguration; + + +public interface CacheConfigurationMXBean extends javax.cache.management.CacheMXBean +{ + public static class Default implements CacheConfigurationMXBean + { + private final CompleteConfiguration configuration; + + Default(final CompleteConfiguration configuration) + { + super(); + + this.configuration = configuration; + } + + @Override + public String getKeyType() + { + return this.configuration.getKeyType().getName(); + } + + @Override + public String getValueType() + { + return this.configuration.getValueType().getName(); + } + + @Override + public boolean isReadThrough() + { + return this.configuration.isReadThrough(); + } + + @Override + public boolean isWriteThrough() + { + return this.configuration.isWriteThrough(); + } + + @Override + public boolean isStoreByValue() + { + return this.configuration.isStoreByValue(); + } + + @Override + public boolean isStatisticsEnabled() + { + return this.configuration.isStatisticsEnabled(); + } + + @Override + public boolean isManagementEnabled() + { + return this.configuration.isManagementEnabled(); + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheConfigurationPropertyNames.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheConfigurationPropertyNames.java new file mode 100644 index 00000000..6180995a --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheConfigurationPropertyNames.java @@ -0,0 +1,97 @@ +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import javax.cache.configuration.CompleteConfiguration; +import javax.cache.configuration.Configuration; + + +/** + * All supported properties for external configuration files. + * + */ +public interface CacheConfigurationPropertyNames +{ + /** + * @see Configuration#getKeyType() + */ + public static final String KEY_TYPE = "key-type"; + + /** + * @see Configuration#getValueType() + */ + public static final String VALUE_TYPE = "value-type"; + + /** + * Path for the {@link org.eclipse.serializer.configuration.types.Configuration} for the backing store. + */ + public static final String STORAGE_CONFIGURATION_RESOURCE_NAME = "storage-configuration-resource-name"; + + /** + * Sub-configuration name for the backing store. + */ + public static final String STORAGE = "storage"; + + /** + * Storage key of the backing store + */ + public static final String STORAGE_KEY = "key"; + + /** + * @see CompleteConfiguration#getCacheLoaderFactory() + */ + public static final String CACHE_LOADER_FACTORY = "cache-loader-factory"; + + /** + * @see CompleteConfiguration#getCacheWriterFactory() + */ + public static final String CACHE_WRITER_FACTORY = "cache-writer-factory"; + + /** + * @see CompleteConfiguration#getExpiryPolicyFactory() + */ + public static final String EXPIRY_POLICY_FACTORY = "expiry-policy-factory"; + + /** + * @see CacheConfiguration#getEvictionManagerFactory() + */ + public static final String EVICTION_MANAGER_FACTORY = "eviction-manager-factory"; + + /** + * @see CompleteConfiguration#isReadThrough() + */ + public static final String READ_THROUGH = "read-through"; + + /** + * @see CompleteConfiguration#isWriteThrough() + */ + public static final String WRITE_THROUGH = "write-through"; + + /** + * @see CompleteConfiguration#isStoreByValue() + */ + public static final String STORE_BY_VALUE = "store-by-value"; + + /** + * @see CompleteConfiguration#isStatisticsEnabled() + */ + public static final String STATISTICS_ENABLED = "statistics-enabled"; + + /** + * @see CompleteConfiguration#isManagementEnabled() + */ + public static final String MANAGEMENT_ENABLED = "management-enabled"; + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheEntry.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheEntry.java new file mode 100644 index 00000000..2084cc02 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheEntry.java @@ -0,0 +1,73 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.typing.KeyValue; + + +public interface CacheEntry extends javax.cache.Cache.Entry, KeyValue, Unwrappable +{ + @Override + public default K key() + { + return this.getKey(); + } + + @Override + public default V value() + { + return this.getValue(); + } + + @Override + public default T unwrap(final Class clazz) + { + return Unwrappable.Static.unwrap(this, clazz); + } + + static CacheEntry New(final K key, final V value) + { + return new Default<>(key, value); + } + + public static class Default implements CacheEntry + { + private final K key; + private final V value; + + Default(final K key, final V value) + { + super(); + + this.key = key; + this.value = value; + } + + @Override + public K getKey() + { + return this.key; + } + + @Override + public V getValue() + { + return this.value; + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheEntryListenerRegistration.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheEntryListenerRegistration.java new file mode 100644 index 00000000..bebf0530 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheEntryListenerRegistration.java @@ -0,0 +1,155 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import javax.cache.configuration.CacheEntryListenerConfiguration; +import javax.cache.event.CacheEntryEventFilter; +import javax.cache.event.CacheEntryListener; + + +public interface CacheEntryListenerRegistration +{ + public CacheEntryListener getCacheEntryListener(); + + public CacheEntryEventFilter getCacheEntryFilter(); + + public CacheEntryListenerConfiguration getConfiguration(); + + public boolean isOldValueRequired(); + + public boolean isSynchronous(); + + public static CacheEntryListenerRegistration + New(final CacheEntryListenerConfiguration configuration) + { + return new Default<>(configuration); + } + + public static class Default implements CacheEntryListenerRegistration + { + private final CacheEntryListenerConfiguration configuration; + private final CacheEntryListener listener; + private final CacheEntryEventFilter filter; + private final boolean oldValueRequired; + private final boolean synchronous; + + Default(final CacheEntryListenerConfiguration configuration) + { + super(); + + this.configuration = configuration; + this.listener = configuration.getCacheEntryListenerFactory().create(); + this.filter = configuration.getCacheEntryEventFilterFactory() == null + ? null + : configuration.getCacheEntryEventFilterFactory().create(); + this.oldValueRequired = configuration.isOldValueRequired(); + this.synchronous = configuration.isSynchronous(); + } + + @Override + public CacheEntryListener getCacheEntryListener() + { + return this.listener; + } + + @Override + public CacheEntryEventFilter getCacheEntryFilter() + { + return this.filter; + } + + @Override + public CacheEntryListenerConfiguration getConfiguration() + { + return this.configuration; + } + + @Override + public boolean isOldValueRequired() + { + return this.oldValueRequired; + } + + @Override + public boolean isSynchronous() + { + return this.synchronous; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + (this.filter == null ? 0 : this.filter.hashCode()); + result = prime * result + (this.oldValueRequired ? 1231 : 1237); + result = prime * result + (this.synchronous ? 1231 : 1237); + result = prime * result + (this.listener == null ? 0 : this.listener.hashCode()); + return result; + } + + @Override + public boolean equals(final Object object) + { + if(this == object) + { + return true; + } + if(object == null) + { + return false; + } + if(!(object instanceof CacheEntryListenerRegistration)) + { + return false; + } + final CacheEntryListenerRegistration other = (CacheEntryListenerRegistration)object; + if(this.filter == null) + { + if(other.getCacheEntryFilter() != null) + { + return false; + } + } + else if(!this.filter.equals(other.getCacheEntryFilter())) + { + return false; + } + if(this.oldValueRequired != other.isOldValueRequired()) + { + return false; + } + if(this.synchronous != other.isSynchronous()) + { + return false; + } + if(this.listener == null) + { + if(other.getCacheEntryListener() != null) + { + return false; + } + } + else if(!this.listener.equals(other.getCacheEntryListener())) + { + return false; + } + return true; + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheEvent.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheEvent.java new file mode 100644 index 00000000..eeecda38 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheEvent.java @@ -0,0 +1,120 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import javax.cache.Cache; +import javax.cache.event.CacheEntryEvent; +import javax.cache.event.EventType; + + +public class CacheEvent extends CacheEntryEvent implements Unwrappable +{ + private final K key; + private final V value; + private final V oldValue; + private final boolean oldValueAvailable; + + CacheEvent( + final Cache source, + final EventType eventType, + final K key, + final V value + ) + { + this( + source, + eventType, + key, + value, + null, + false + ); + } + + CacheEvent( + final Cache source, + final EventType eventType, + final K key, + final V value, + final V oldValue + ) + { + this( + source, + eventType, + key, + value, + oldValue, + true + ); + } + + CacheEvent( + final Cache source, + final EventType eventType, + final K key, + final V value, + final V oldValue, + final boolean oldValueAvailable + ) + { + super(source, eventType); + + this.key = key; + this.value = value; + this.oldValue = oldValue; + this.oldValueAvailable = oldValueAvailable; + } + + @SuppressWarnings("unchecked") + public Cache getCache() + { + return super.getSource(); + } + + @Override + public K getKey() + { + return this.key; + } + + @Override + public V getValue() + { + return this.value; + } + + @Override + public V getOldValue() throws UnsupportedOperationException + { + return this.isOldValueAvailable() + ? this.oldValue + : null; + } + + @Override + public boolean isOldValueAvailable() + { + return this.oldValueAvailable; + } + + @Override + public T unwrap(final Class clazz) + { + return Static.unwrap(this, clazz); + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheEventDispatcher.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheEventDispatcher.java new file mode 100644 index 00000000..e10a88e7 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheEventDispatcher.java @@ -0,0 +1,192 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import static org.eclipse.serializer.util.X.notNull; + +import java.util.function.BiConsumer; + +import javax.cache.event.CacheEntryCreatedListener; +import javax.cache.event.CacheEntryEvent; +import javax.cache.event.CacheEntryEventFilter; +import javax.cache.event.CacheEntryExpiredListener; +import javax.cache.event.CacheEntryListener; +import javax.cache.event.CacheEntryRemovedListener; +import javax.cache.event.CacheEntryUpdatedListener; +import javax.cache.event.EventType; + +import org.eclipse.serializer.collections.BulkList; +import org.eclipse.serializer.collections.EqHashTable; +import org.eclipse.serializer.collections.types.XIterable; +import org.eclipse.serializer.collections.types.XList; +import org.eclipse.serializer.collections.types.XTable; +import org.eclipse.serializer.util.cql.CQL; +import org.eclipse.serializer.util.cql.CqlSelection; + + +/* + * @SuppressWarnings annotations due to insufficient generics in JCache API + */ +public interface CacheEventDispatcher +{ + @SuppressWarnings("rawtypes") + public CacheEventDispatcher addEvent( + final Class listenerClass, + final CacheEvent event + ); + + public void dispatch( + org.eclipse.serializer.collections.types.XIterable> registrations + ); + + public static CacheEventDispatcher New() + { + return new Default<>(); + } + + public static class Default implements CacheEventDispatcher + { + @SuppressWarnings("rawtypes") + private XTable, XList>> eventMap; + + Default() + { + super(); + } + + @SuppressWarnings("rawtypes") + @Override + public synchronized CacheEventDispatcher addEvent( + final Class listenerClass, + final CacheEvent event + ) + { + notNull(listenerClass); + notNull(event); + + // lazy init eventMap + XTable, XList>> eventMap; + if((eventMap = this.eventMap) == null) + { + eventMap = this.eventMap = EqHashTable.New(); + } + eventMap + .ensure(listenerClass, c -> BulkList.New()) + .add(event); + + return this; + } + + @SuppressWarnings("unchecked") + @Override + public synchronized void dispatch( + final XIterable> registrations + ) + { + if(this.eventMap == null) + { + // no event registered + return; + } + + this.dispatch(registrations, CacheEntryExpiredListener.class, CacheEntryExpiredListener::onExpired, true); + this.dispatch(registrations, CacheEntryCreatedListener.class, CacheEntryCreatedListener::onCreated, false); + this.dispatch(registrations, CacheEntryUpdatedListener.class, CacheEntryUpdatedListener::onUpdated, true); + this.dispatch(registrations, CacheEntryRemovedListener.class, CacheEntryRemovedListener::onRemoved, true); + } + + @SuppressWarnings("unchecked") + private > void dispatch( + final XIterable> registrations, + final Class type, + final BiConsumer>> logic, + final boolean oldValueAvailable + ) + { + final XList> events; + if((events = this.eventMap.get(type)) != null) + { + registrations.iterate(registration -> + { + final CacheEntryListener listener; + if(type.isInstance(listener = registration.getCacheEntryListener())) + { + logic.accept( + type.cast(listener), + this.selectEvents(registration, events, oldValueAvailable) + ); + } + }); + } + } + + @SuppressWarnings("rawtypes") + private Iterable selectEvents( + final CacheEntryListenerRegistration registration, + final XList> events, + final boolean oldValueAvailable + ) + { + CqlSelection> selection = CQL.from(events); + final CacheEntryEventFilter filter; + if((filter = registration.getCacheEntryFilter()) != null) + { + selection = selection.select(e -> filter.evaluate(e)); + } + return selection + .project(e -> this.cloneEvent(registration, e, oldValueAvailable)) + .into(BulkList.New()) + .execute(); + } + + private CacheEvent cloneEvent( + final CacheEntryListenerRegistration registration, + final CacheEvent event, + final boolean oldValueAvailable + ) + { + if(oldValueAvailable && registration.isOldValueRequired()) + { + return new CacheEvent<>( + event.getCache(), + event.getEventType(), + event.getKey(), + event.getValue(), + event.getOldValue() + ); + } + + if(event.getEventType() == EventType.REMOVED || event.getEventType() == EventType.EXPIRED) + { + return new CacheEvent<>( + event.getCache(), + event.getEventType(), + event.getKey(), + null + ); + } + + return new CacheEvent<>( + event.getCache(), + event.getEventType(), + event.getKey(), + event.getValue() + ); + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheManager.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheManager.java new file mode 100644 index 00000000..b2330b15 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheManager.java @@ -0,0 +1,317 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import static org.eclipse.serializer.chars.XChars.notEmpty; +import static org.eclipse.serializer.util.X.notNull; + +import java.lang.ref.WeakReference; +import java.net.URI; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.cache.CacheException; +import javax.cache.configuration.CompleteConfiguration; +import javax.cache.configuration.Configuration; + +import org.eclipse.serializer.collections.EqHashTable; + + +/** + * JSR-107 compliant {@link javax.cache.CacheManager}. + * + */ +public interface CacheManager extends javax.cache.CacheManager +{ + @Override + public Cache getCache(String cacheName); + + @Override + public Cache getCache(String cacheName, Class keyType, Class valueType); + + @Override + public > Cache createCache(String cacheName, C configuration) + throws IllegalArgumentException; + + @Override + public CachingProvider getCachingProvider(); + + public void removeCache(final String cacheName); + + @Override + public default T unwrap(final Class clazz) + { + return Unwrappable.Static.unwrap(this, clazz); + } + + static CacheManager New( + final CachingProvider cachingProvider, + final URI uri, + final ClassLoader classLoader, + final Properties properties + ) + { + return new Default( + cachingProvider, + uri, + classLoader, + properties + ); + } + + public static class Default implements CacheManager + { + private final CachingProvider cachingProvider; + private final URI uri; + private final WeakReference classLoaderReference; + private final Properties properties; + private final EqHashTable> caches = EqHashTable.New(); + private final AtomicBoolean isClosed = new AtomicBoolean(false); + + Default( + final CachingProvider cachingProvider, + final URI uri, + final ClassLoader classLoader, + final Properties properties) + { + super(); + + this.cachingProvider = notNull(cachingProvider); + this.uri = notNull(uri); + this.classLoaderReference = new WeakReference<>(notNull(classLoader)); + this.properties = new Properties(); + if(properties != null) + { + this.properties.putAll(properties); + } + } + + @Override + public CachingProvider getCachingProvider() + { + return this.cachingProvider; + } + + @Override + public boolean isClosed() + { + return this.isClosed.get(); + } + + @Override + public URI getURI() + { + return this.uri; + } + + @Override + public Properties getProperties() + { + return this.properties; + } + + @Override + public ClassLoader getClassLoader() + { + return this.classLoaderReference.get(); + } + + @Override + public > Cache + createCache(final String cacheName, final C configuration) throws IllegalArgumentException + { + notEmpty(cacheName); + notNull(configuration); + + if(this.getCache(cacheName) != null) + { + throw new CacheException("A cache named " + cacheName + " already exists."); + } + + synchronized(this.caches) + { + final Cache cache = Cache.New( + cacheName, + this, + CacheConfiguration.New(configuration) + ); + this.caches.put(cacheName, cache); + return cache; + } + } + + @SuppressWarnings("unchecked") + @Override + public Cache getCache(final String cacheName) + { + this.ensureOpen(); + + notNull(cacheName); + + synchronized(this.caches) + { + return (Cache)this.caches.get(cacheName); + } + } + + @SuppressWarnings("unchecked") + @Override + public Cache getCache(final String cacheName, final Class keyType, final Class valueType) + { + this.ensureOpen(); + + notNull(keyType); + notNull(valueType); + + Cache cache; + synchronized(this.caches) + { + cache = (Cache)this.caches.get(notNull(cacheName)); + } + if(cache == null) + { + return null; + } + + final CompleteConfiguration configuration = cache.getConfiguration(CompleteConfiguration.class); + final Class configuredKeyType = configuration.getKeyType(); + final Class configuredValueType = configuration.getValueType(); + if(configuredKeyType != null && !configuredKeyType.equals(keyType)) + { + throw new ClassCastException("Incompatible key types: " + keyType + " <> " + configuredKeyType); + } + if(configuredValueType != null && !configuredValueType.equals(valueType)) + { + throw new ClassCastException("Incompatible value types: " + valueType + " <> " + configuredValueType); + } + + return cache; + } + + @Override + public Iterable getCacheNames() + { + this.ensureOpen(); + + synchronized(this.caches) + { + return this.caches.keys().immure(); + } + } + + @SuppressWarnings("resource") + @Override + public void destroyCache(final String cacheName) + { + this.ensureOpen(); + + Cache cache; + synchronized(this.caches) + { + cache = this.caches.get(notNull(cacheName)); + } + if(cache != null) + { + cache.close(); + } + } + + @Override + public void removeCache(final String cacheName) + { + notNull(cacheName); + + synchronized(this.caches) + { + this.caches.removeFor(cacheName); + } + } + + @Override + public void enableManagement(final String cacheName, final boolean enabled) + { + this.ensureOpen(); + + notNull(cacheName); + + synchronized(this.caches) + { + this.caches.get(cacheName) + .setManagementEnabled(enabled); + } + } + + @Override + public void enableStatistics(final String cacheName, final boolean enabled) + { + this.ensureOpen(); + + notNull(cacheName); + + synchronized(this.caches) + { + this.caches.get(cacheName) + .setStatisticsEnabled(enabled); + } + } + + @Override + public synchronized void close() + { + if(this.isClosed.get()) + { + // no-op, according to spec + return; + } + + this.isClosed.set(true); + + this.cachingProvider.remove( + this.getURI(), + this.getClassLoader() + ); + + try + { + for(final Cache cache : this.caches.values()) + { + try + { + cache.close(); + } + catch(final Exception e) + { + // ignore, according to spec + } + } + } + finally + { + this.caches.clear(); + } + } + + private void ensureOpen() + { + if(this.isClosed.get()) + { + throw new IllegalStateException("CacheManager is closed"); + } + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheStatisticsMXBean.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheStatisticsMXBean.java new file mode 100644 index 00000000..603756f9 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheStatisticsMXBean.java @@ -0,0 +1,248 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.LongSupplier; + + +public interface CacheStatisticsMXBean extends javax.cache.management.CacheStatisticsMXBean +{ + public void increaseCacheRemovals(final long number); + + public void increaseCacheExpiries(final long number); + + public void increaseCachePuts(final long number); + + public void increaseCacheHits(final long number); + + public void increaseCacheMisses(final long number); + + public void increaseCacheEvictions(final long number); + + public void addGetTimeNano(final long duration); + + public void addPutTimeNano(final long duration); + + public void addRemoveTimeNano(final long duration); + + + public static class Default implements CacheStatisticsMXBean + { + private final static long NANOSECONDS_IN_A_MICROSECOND = 1000L; + + private final transient LongSupplier sizeSupplier; + + private final AtomicLong cacheRemovals = new AtomicLong(); + private final AtomicLong cacheExpiries = new AtomicLong(); + private final AtomicLong cachePuts = new AtomicLong(); + private final AtomicLong cacheHits = new AtomicLong(); + private final AtomicLong cacheMisses = new AtomicLong(); + private final AtomicLong cacheEvictions = new AtomicLong(); + private final AtomicLong cachePutTimeTakenNanos = new AtomicLong(); + private final AtomicLong cacheGetTimeTakenNanos = new AtomicLong(); + private final AtomicLong cacheRemoveTimeTakenNanos = new AtomicLong(); + + Default(final LongSupplier sizeSupplier) + { + this.sizeSupplier = sizeSupplier; + } + + @Override + public void clear() + { + this.cachePuts.set(0); + this.cacheMisses.set(0); + this.cacheRemovals.set(0); + this.cacheExpiries.set(0); + this.cacheHits.set(0); + this.cacheEvictions.set(0); + this.cacheGetTimeTakenNanos.set(0); + this.cachePutTimeTakenNanos.set(0); + this.cacheRemoveTimeTakenNanos.set(0); + } + + public long getEntryCount() + { + return this.sizeSupplier.getAsLong(); + } + + @Override + public long getCacheHits() + { + return this.cacheHits.longValue(); + } + + @Override + public float getCacheHitPercentage() + { + final long hits = this.getCacheHits(); + return hits == 0 + ? 0 + : (float)hits / this.getCacheGets() * 100.0f; + } + + @Override + public long getCacheMisses() + { + return this.cacheMisses.longValue(); + } + + @Override + public float getCacheMissPercentage() + { + final long misses = this.getCacheMisses(); + return misses == 0 + ? 0 + : (float)misses / this.getCacheGets() * 100.0f; + } + + @Override + public long getCacheGets() + { + return this.getCacheHits() + this.getCacheMisses(); + } + + @Override + public long getCachePuts() + { + return this.cachePuts.longValue(); + } + + @Override + public long getCacheRemovals() + { + return this.cacheRemovals.longValue(); + } + + @Override + public long getCacheEvictions() + { + return this.cacheEvictions.longValue(); + } + + @Override + public float getAverageGetTime() + { + final long cacheGetTimeTakenNanos = this.cacheGetTimeTakenNanos.longValue(); + final long cacheGets = this.getCacheGets(); + return cacheGetTimeTakenNanos == 0 || cacheGets == 0 + ? 0 + : (cacheGetTimeTakenNanos / cacheGets) / NANOSECONDS_IN_A_MICROSECOND; + } + + @Override + public float getAveragePutTime() + { + final long cachePutTimeTakenNanos = this.cachePutTimeTakenNanos.longValue(); + final long cacheGets = this.getCacheGets(); + return cachePutTimeTakenNanos == 0 || cacheGets == 0 + ? 0 + : (cachePutTimeTakenNanos / cacheGets) / NANOSECONDS_IN_A_MICROSECOND; + } + + @Override + public float getAverageRemoveTime() + { + final long cacheRemoveTimeTakenNanos = this.cacheRemoveTimeTakenNanos.longValue(); + final long cacheGets = this.getCacheGets(); + return cacheRemoveTimeTakenNanos == 0 || cacheGets == 0 + ? 0 + : (cacheRemoveTimeTakenNanos / cacheGets) / NANOSECONDS_IN_A_MICROSECOND; + } + + @Override + public void increaseCacheRemovals(final long number) + { + this.cacheRemovals.getAndAdd(number); + } + + @Override + public void increaseCacheExpiries(final long number) + { + this.cacheExpiries.getAndAdd(number); + } + + @Override + public void increaseCachePuts(final long number) + { + this.cachePuts.getAndAdd(number); + } + + @Override + public void increaseCacheHits(final long number) + { + this.cacheHits.getAndAdd(number); + } + + @Override + public void increaseCacheMisses(final long number) + { + this.cacheMisses.getAndAdd(number); + } + + @Override + public void increaseCacheEvictions(final long number) + { + this.cacheEvictions.getAndAdd(number); + } + + @Override + public void addGetTimeNano(final long duration) + { + if(this.cacheGetTimeTakenNanos.get() <= Long.MAX_VALUE - duration) + { + this.cacheGetTimeTakenNanos.addAndGet(duration); + } + else + { + // Counter full. Just reset. + this.clear(); + this.cacheGetTimeTakenNanos.set(duration); + } + } + + @Override + public void addPutTimeNano(final long duration) + { + if(this.cachePutTimeTakenNanos.get() <= Long.MAX_VALUE - duration) + { + this.cachePutTimeTakenNanos.addAndGet(duration); + } + else + { + this.clear(); + this.cachePutTimeTakenNanos.set(duration); + } + } + + @Override + public void addRemoveTimeNano(final long duration) + { + if(this.cacheRemoveTimeTakenNanos.get() <= Long.MAX_VALUE - duration) + { + this.cacheRemoveTimeTakenNanos.addAndGet(duration); + } + else + { + this.clear(); + this.cacheRemoveTimeTakenNanos.set(duration); + } + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheStore.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheStore.java new file mode 100644 index 00000000..bfa8e7f1 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheStore.java @@ -0,0 +1,222 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import static org.eclipse.serializer.chars.XChars.notEmpty; +import static org.eclipse.serializer.util.X.notNull; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.cache.Cache.Entry; +import javax.cache.integration.CacheLoader; +import javax.cache.integration.CacheLoaderException; +import javax.cache.integration.CacheWriter; +import javax.cache.integration.CacheWriterException; + +import org.eclipse.serializer.collections.EqHashTable; +import org.eclipse.serializer.collections.types.XTable; +import org.eclipse.serializer.reference.Lazy; +import org.eclipse.store.storage.types.StorageManager; + + +public interface CacheStore extends CacheLoader, CacheWriter +{ + public Iterator keys(); + + + public static CacheStore New(final String cacheKey, final StorageManager storage) + { + return new Default<>(cacheKey, storage); + } + + public static class Default implements CacheStore + { + private final String cacheKey; + private final StorageManager storage; + + Default(final String cacheKey, final StorageManager storage) + { + super(); + + this.cacheKey = notEmpty(cacheKey); + this.storage = notNull(storage); + } + + @SuppressWarnings("unchecked") + private XTable> cacheTable(final boolean create) + { + synchronized(this.storage) + { + if(!this.storage.isRunning()) + { + this.storage.start(); + } + + boolean storeRoot = false; + XTable>>> root; + if((root = (XTable>>>)this.storage.root()) == null) + { + this.storage.setRoot(root = EqHashTable.New()); + storeRoot = true; + } + XTable> cacheTable; + if((cacheTable = Lazy.get(root.get(this.cacheKey))) == null && create) + { + root.put(this.cacheKey, Lazy.Reference(cacheTable = EqHashTable.New())); + storeRoot = true; + } + if(storeRoot) + { + this.storage.storeRoot(); + } + return cacheTable; + } + } + + @Override + public synchronized Iterator keys() + { + final XTable> cacheTable = this.cacheTable(false); + return cacheTable != null + ? cacheTable.keys().iterator() + : Collections.emptyIterator() + ; + } + + @Override + public synchronized V load(final K key) throws CacheLoaderException + { + try + { + final XTable> cacheTable; + return (cacheTable = this.cacheTable(false)) != null + ? Lazy.get(cacheTable.get(key)) + : null; + } + catch(final Exception e) + { + throw new CacheLoaderException(e); + } + } + + @Override + public synchronized Map loadAll(final Iterable keys) throws CacheLoaderException + { + try + { + final Map result = new HashMap<>(); + final XTable> cacheTable; + if((cacheTable = this.cacheTable(false)) != null) + { + keys.forEach(key -> result.put(key, Lazy.get(cacheTable.get(key)))); + } + return result; + } + catch(final Exception e) + { + throw new CacheLoaderException(e); + } + } + + @Override + public synchronized void write(final Entry entry) throws CacheWriterException + { + try + { + final XTable> cacheTable = this.cacheTable(true); + cacheTable.put(entry.getKey(), Lazy.Reference(entry.getValue())); + this.storage.store(cacheTable); + } + catch(final Exception e) + { + throw new CacheWriterException(e); + } + } + + @Override + public synchronized void writeAll(final Collection> entries) + throws CacheWriterException + { + try + { + final XTable> cacheTable = this.cacheTable(true); + entries.forEach(entry -> cacheTable.put(entry.getKey(), Lazy.Reference(entry.getValue()))); + this.storage.store(cacheTable); + } + catch(final Exception e) + { + throw new CacheWriterException(e); + } + } + + @SuppressWarnings("unchecked") // Object in typed interface [sigh] + @Override + public synchronized void delete(final Object key) throws CacheWriterException + { + try + { + final XTable> cacheTable; + if((cacheTable = this.cacheTable(false)) != null + && cacheTable.removeFor((K)key) != null) + { + this.storage.store(cacheTable); + } + } + catch(final Exception e) + { + throw new CacheWriterException(e); + } + } + + @Override + public synchronized void deleteAll(final Collection keys) throws CacheWriterException + { + try + { + final XTable> cacheTable; + if((cacheTable = this.cacheTable(false)) != null) + { + boolean changed = false; + final Iterator iterator = keys.iterator(); + while(iterator.hasNext()) + { + @SuppressWarnings("unchecked") + final K key = (K)iterator.next(); + if(cacheTable.removeFor(key) != null) + { + iterator.remove(); + changed = true; + } + } + if(changed) + { + this.storage.store(cacheTable); + } + } + } + catch(final Exception e) + { + throw new CacheWriterException(e); + } + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheTable.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheTable.java new file mode 100644 index 00000000..b335e4cb --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheTable.java @@ -0,0 +1,236 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.Comparator; +import java.util.Iterator; +import java.util.function.Consumer; +import java.util.function.Predicate; + +import org.eclipse.serializer.collections.EqHashTable; +import org.eclipse.serializer.functional.Aggregator; +import org.eclipse.serializer.typing.KeyValue; +import org.eclipse.serializer.util.X; + + +public interface CacheTable +{ + public CachedValue get(Object key); + + public boolean put(Object key, CachedValue value); + + public CachedValue remove(Object key); + + public Iterable keys(); + + public Iterator> iterator(); + + public void iterate(Consumer> procedure); + + public KeyValue search(Predicate> predicate); + + public long size(); + + public void clear(); + + public KeyValue min(Comparator> comparator); + + public KeyValue rangeMin( + long offset , + long length , + Comparator> comparator + ); + + + public static CacheTable New() + { + return new Default(); + } + + + public static class Default implements CacheTable + { + final EqHashTable table; + + Default() + { + super(); + + this.table = EqHashTable.New(); + } + + @Override + public CachedValue get(final Object key) + { + return this.table.get(key); + } + + @Override + public boolean put(final Object key, final CachedValue value) + { + return this.table.put(key, value); + } + + @Override + public CachedValue remove(final Object key) + { + return this.table.removeFor(key); + } + + @Override + public Iterable keys() + { + return this.table.keys(); + } + + @Override + public Iterator> iterator() + { + final Iterator> it = this.table.iterator(); + /* + * Iterator#remove is used by Cache, so we have to implement it + * since EqHashTable's iterators don't. + */ + return new Iterator>() + { + KeyValue next; + + @Override + public boolean hasNext() + { + return it.hasNext(); + } + + @Override + public KeyValue next() + { + return this.next = it.next(); + } + + @Override + public void remove() + { + CacheTable.Default.this.table.remove(this.next); + } + }; + } + + @Override + public void iterate(final Consumer> procedure) + { + this.table.iterate(procedure); + } + + @Override + public KeyValue search(final Predicate> predicate) + { + return this.table.search(predicate); + } + + @Override + public long size() + { + return this.table.size(); + } + + @Override + public void clear() + { + this.table.clear(); + } + + @Override + public KeyValue min(final Comparator> comparator) + { + return this.table.min(comparator); + } + + @Override + public KeyValue rangeMin( + final long offset, + final long length, + final Comparator> comparator + ) + { + return this.table.iterate(new RangeMin<>(offset, length, comparator)).yield(); + } + + + static class RangeMin implements Aggregator + { + private final long offset, length; + private final Comparator order; + private long iterationOffset, iterationLength; + private E iterationElement; + + RangeMin(final long offset, final long length, final Comparator order) + { + super(); + + this.offset = offset; + this.length = length; + this.order = order ; + + this.reset(); + } + + @Override + public final RangeMin reset() + { + this.iterationElement = null; + this.iterationOffset = this.offset; + this.iterationLength = this.length; + + return this; + } + + @Override + public final void accept(final E element) + { + if(this.iterationOffset > 0) + { + this.iterationOffset--; + return; + } + + if(this.iterationLength <= 0) + { + throw X.BREAK(); + } + + if(this.iterationLength-- == this.length) + { + this.iterationElement = element; + return; + } + + if(this.order.compare(element, this.iterationElement) < 0) + { + this.iterationElement = element; + } + } + + @Override + public final E yield() + { + return this.iterationElement; + } + + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheValueValidator.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheValueValidator.java new file mode 100644 index 00000000..6ea47102 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/CacheValueValidator.java @@ -0,0 +1,94 @@ +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public interface CacheValueValidator +{ + public void validate( + Object value + ); + + + public static CacheValueValidator New( + final String slot, + final Class expectedType + ) + { + return expectedType == null || Object.class.equals(expectedType) + ? new Simple(slot) + : new Typed(slot, expectedType) + ; + } + + + public static class Simple implements CacheValueValidator + { + final String slot; + + Simple( + final String slot + ) + { + super(); + this.slot = slot; + } + + @Override + public void validate( + final Object value + ) + { + if(value == null) + { + throw new NullPointerException( + this.slot + " cannot be null" + ); + } + } + + } + + public static class Typed extends Simple + { + final Class expectedType; + + Typed( + final String slot, + final Class expectedType + ) + { + super(slot); + this.expectedType = expectedType; + } + + @Override + public void validate( + final Object value + ) + { + super.validate(value); // null check + + if(!this.expectedType.isInstance(value)) + { + throw new ClassCastException( + "Type mismatch for " + this.slot + ": " + + value + " <> " + this.expectedType.getName() + ); + } + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/CachedValue.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/CachedValue.java new file mode 100644 index 00000000..6aa2d71c --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/CachedValue.java @@ -0,0 +1,164 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public interface CachedValue +{ + public long creationTime(); + + public long accessTime(); + + public long accessCount(); + + public long modificationTime(); + + public long modificationCount(); + + public long expiryTime(); + + public CachedValue expiryTime(long expiryTime); + + public boolean isExpiredAt(long now); + + public Object value(); + + public Object value(long accessTime); + + public CachedValue value(Object value); + + public CachedValue value(Object value, long accessTime); + + public long byteSizeEstimate(); + + public static CachedValue New(final Object value, final long creationTime, final long expiryTime) + { + return new Default(value, creationTime, expiryTime); + } + + public static class Default implements CachedValue + { + private Object value; + private final long creationTime; + private long accessTime; + private long accessCount; + private long modificationTime; + private long modificationCount; + private long expiryTime; + + Default(final Object value, final long creationTime, final long expiryTime) + { + super(); + + this.value = value; + this.creationTime = creationTime; + this.accessTime = creationTime; + this.modificationTime = creationTime; + this.expiryTime = expiryTime; + this.accessCount = 0; + this.modificationCount = 0; + } + + @Override + public long creationTime() + { + return this.creationTime; + } + + @Override + public long accessTime() + { + return this.accessTime; + } + + @Override + public long accessCount() + { + return this.accessCount; + } + + @Override + public long modificationTime() + { + return this.modificationTime; + } + + @Override + public long modificationCount() + { + return this.modificationCount; + } + + @Override + public long expiryTime() + { + return this.expiryTime; + } + + @Override + public CachedValue expiryTime(final long expiryTime) + { + this.expiryTime = expiryTime; + return this; + } + + @Override + public boolean isExpiredAt(final long now) + { + final long expiryTime = this.expiryTime; + return expiryTime > -1 && expiryTime <= now; + } + + @Override + public Object value() + { + return this.value; + } + + @Override + public Object value(final long accessTime) + { + this.accessTime = accessTime; + this.accessCount++; + return this.value; + } + + @Override + public CachedValue value(final Object value) + { + this.value = value; + return this; + } + + @Override + public CachedValue value(final Object value, final long modificationTime) + { + this.modificationTime = modificationTime; + this.value = value; + this.modificationCount++; + return this; + } + + @Override + public long byteSizeEstimate() + { + return this.value instanceof ByteSized + ? ((ByteSized)this.value).byteSize() + : -1; + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/CachingProvider.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/CachingProvider.java new file mode 100644 index 00000000..6631f01f --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/CachingProvider.java @@ -0,0 +1,201 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.List; +import java.util.Properties; +import java.util.WeakHashMap; +import java.util.stream.Collectors; + +import javax.cache.configuration.OptionalFeature; + + +/** + * JSR-107 compliant {@link javax.cache.spi.CachingProvider}. + * + */ +public class CachingProvider implements javax.cache.spi.CachingProvider +{ + public static URI defaultURI() + { + try + { + return new URI("eclipsestore"); + } + catch(final URISyntaxException e) + { + throw new RuntimeException(e); + } + } + + private final WeakHashMap> cacheManagers = new WeakHashMap<>(); + + public CachingProvider() + { + super(); + } + + @Override + public ClassLoader getDefaultClassLoader() + { + return this.getClass().getClassLoader(); + } + + @Override + public URI getDefaultURI() + { + return defaultURI(); + } + + @Override + public Properties getDefaultProperties() + { + return null; + } + + @Override + public CacheManager getCacheManager() + { + return this.getCacheManager( + this.getDefaultURI(), + this.getDefaultClassLoader() + ); + } + + @Override + public CacheManager getCacheManager( + final URI uri, + final ClassLoader classLoader + ) + { + return this.getCacheManager( + uri, + classLoader, + this.getDefaultProperties() + ); + } + + @Override + public synchronized CacheManager getCacheManager( + final URI uri, + final ClassLoader classLoader, + final Properties properties + ) + { + final URI managerURI = uri == null + ? this.getDefaultURI() + : uri; + + final ClassLoader managerClassLoader = classLoader == null + ? this.getDefaultClassLoader() + : classLoader; + + final Properties managerProperties = properties == null + ? new Properties() + : properties; + + return this.cacheManagers.computeIfAbsent(managerClassLoader, cl -> new HashMap<>()) + .computeIfAbsent(managerURI, + key -> CacheManager.New(this, managerURI, managerClassLoader, managerProperties) + ); + } + + @Override + public synchronized void close() + { + /* + * Collect to list because CacheManager#close modifies this#cacheManagers + */ + final List managers = this.cacheManagers.values().stream() + .flatMap(kv -> kv.values().stream()) + .collect(Collectors.toList()); + managers.forEach(CacheManager::close); + + this.cacheManagers.clear(); + } + + @Override + public synchronized void close(final ClassLoader classLoader) + { + final ClassLoader managerClassLoader = classLoader == null + ? this.getDefaultClassLoader() + : classLoader; + + final HashMap cacheManagersByURI; + if((cacheManagersByURI = this.cacheManagers.remove(managerClassLoader)) != null) + { + cacheManagersByURI.values() + .forEach(CacheManager::close); + } + } + + @SuppressWarnings("resource") + @Override + public synchronized void close(final URI uri, final ClassLoader classLoader) + { + final URI managerURI = uri == null + ? this.getDefaultURI() + : uri; + + final ClassLoader managerClassLoader = classLoader == null + ? this.getDefaultClassLoader() + : classLoader; + + final HashMap cacheManagersByURI; + if((cacheManagersByURI = this.cacheManagers.get(managerClassLoader)) != null) + { + final CacheManager cacheManager; + if((cacheManager = cacheManagersByURI.remove(managerURI)) != null) + { + cacheManager.close(); + + if(cacheManagersByURI.size() == 0) + { + this.cacheManagers.remove(managerClassLoader); + } + } + } + } + + synchronized void remove(final URI uri, final ClassLoader classLoader) + { + final HashMap cacheManagersByURI; + if((cacheManagersByURI = this.cacheManagers.get(classLoader)) != null) + { + if(cacheManagersByURI.remove(uri) != null && cacheManagersByURI.size() == 0) + { + this.cacheManagers.remove(classLoader); + } + } + } + + @Override + public boolean isSupported(final OptionalFeature optionalFeature) + { + switch(optionalFeature) + { + case STORE_BY_REFERENCE: + return true; + + default: + return false; + } + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/EntryProcessorResult.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/EntryProcessorResult.java new file mode 100644 index 00000000..7e4b2b63 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/EntryProcessorResult.java @@ -0,0 +1,37 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import javax.cache.processor.EntryProcessorException; + + +public interface EntryProcessorResult extends javax.cache.processor.EntryProcessorResult +{ + public static EntryProcessorResult New(final T value) + { + return () -> value; + } + + public static EntryProcessorResult New(final Exception e) + { + final EntryProcessorException epe = e instanceof EntryProcessorException + ? (EntryProcessorException)e + : new EntryProcessorException(e); + return () -> { + throw epe; + }; + } +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/EvictionManager.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/EvictionManager.java new file mode 100644 index 00000000..44817cc2 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/EvictionManager.java @@ -0,0 +1,234 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import static org.eclipse.serializer.util.X.notNull; + +import java.lang.ref.WeakReference; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.cache.configuration.CacheEntryListenerConfiguration; +import javax.cache.configuration.MutableCacheEntryListenerConfiguration; +import javax.cache.event.CacheEntryCreatedListener; + +import org.eclipse.serializer.reference._longReference; +import org.eclipse.serializer.typing.KeyValue; + + +public interface EvictionManager +{ + public void install(Cache cache, CacheTable cacheTable); + + public void uninstall(Cache cache, CacheTable cacheTable); + + + public static EvictionManager OnEntryCreation(final EvictionPolicy evictionPolicy) + { + return new OnEntryCreation<>(evictionPolicy); + } + + public static EvictionManager Interval( + final EvictionPolicy evictionPolicy, + final long milliTimeInterval + ) + { + return new Interval<>(evictionPolicy, () -> milliTimeInterval); + } + + public static EvictionManager Interval( + final EvictionPolicy evictionPolicy, + final _longReference milliTimeIntervalProvider + ) + { + return new Interval<>(evictionPolicy, milliTimeIntervalProvider); + } + + + public static abstract class Abstract implements EvictionManager + { + final EvictionPolicy evictionPolicy; + + Abstract(final EvictionPolicy evictionPolicy) + { + super(); + + this.evictionPolicy = notNull(evictionPolicy); + } + + void evict( + final Cache cache, + final CacheTable cacheTable + ) + { + final Iterable> entriesToEvict; + if((entriesToEvict = this.evictionPolicy.pickEntriesToEvict(cacheTable)) != null) + { + cache.evict(entriesToEvict); + } + } + } + + + public static class OnEntryCreation extends Abstract + { + private CacheEntryListenerConfiguration listenerConfiguration; + + OnEntryCreation(final EvictionPolicy evictionPolicy) + { + super(evictionPolicy); + } + + @Override + public void install(final Cache cache, final CacheTable cacheTable) + { + if(this.listenerConfiguration == null) + { + final CacheEntryCreatedListener entryCreatedListener = events -> + events.forEach(event -> this.evict(cache, cacheTable)) + ; + + this.listenerConfiguration = new MutableCacheEntryListenerConfiguration<>( + () -> entryCreatedListener, + null, // no filter required + false, // no old value required + true // synchronous + ); + + cache.registerCacheEntryListener(this.listenerConfiguration); + } + } + + @Override + public void uninstall(final Cache cache, final CacheTable cacheTable) + { + if(this.listenerConfiguration != null) + { + cache.deregisterCacheEntryListener(this.listenerConfiguration); + + this.listenerConfiguration = null; + } + } + + } + + + public static class Interval extends Abstract + { + private final _longReference milliTimeIntervalProvider; + private Cache cache; + private CacheTable cacheTable; + private AtomicBoolean running = new AtomicBoolean(); + + Interval( + final EvictionPolicy evictionPolicy, + final _longReference milliTimeIntervalProvider + ) + { + super(evictionPolicy); + + this.milliTimeIntervalProvider = milliTimeIntervalProvider; + } + + @Override + public void install(final Cache cache, final CacheTable cacheTable) + { + this.cache = cache; + this.cacheTable = cacheTable; + + if(!this.running.get()) + { + this.running.set(true); + new IntervalThread(new WeakReference<>(this), this.milliTimeIntervalProvider).start(); + } + } + + @Override + public void uninstall(final Cache cache, final CacheTable cacheTable) + { + this.running.set(false); + this.cache = null; + this.cacheTable = null; + } + + void evict() + { + this.evict(this.cache, this.cacheTable); + } + + + static final class IntervalThread extends Thread + { + // lazy reference for automatic thread termination + private final WeakReference> parent; + private final _longReference milliTimeIntervalProvider; + + IntervalThread( + final WeakReference> parent, + final _longReference milliTimeIntervalProvider + ) + { + super(EvictionManager.class.getSimpleName()+"@"+System.identityHashCode(parent)); + + this.parent = parent; + this.milliTimeIntervalProvider = milliTimeIntervalProvider; + } + + @Override + public void run() + { + EvictionManager.Interval parent; + while((parent = this.parent.get()) != null) + { + // sleep for a dynamically specified milli time until the next check + try + { + // check for running state. Must be the first action in case of swallowed exception + if(!parent.running.get()) + { + break; + } + + // perform eviction + parent.evict(); + + // very nasty: must clear the reference from the stack in order for the weak reference to work + parent = null; + + // extra nasty: must sleep with nulled reference for WR to work, not before. + try + { + Thread.sleep(this.milliTimeIntervalProvider.get()); + } + catch(final InterruptedException e) + { + // sleep interrupted, proceed with check immediately + } + } + catch(final Exception e) + { + /* thread may not die on any exception, just continue looping as long as parent exists + * and running is true + */ + } + } + // either parent has been garbage collected or stopped, so terminate. + } + + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/EvictionPolicy.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/EvictionPolicy.java new file mode 100644 index 00000000..fa43188a --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/EvictionPolicy.java @@ -0,0 +1,382 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import static org.eclipse.serializer.util.X.notNull; + +import java.util.Comparator; +import java.util.Random; +import java.util.function.Predicate; + +import org.eclipse.serializer.collections.EqHashEnum; +import org.eclipse.serializer.collections.types.XEnum; +import org.eclipse.serializer.reference._intReference; +import org.eclipse.serializer.typing.KeyValue; +import org.eclipse.serializer.util.X; + +/** + * Function to pick the entries which should be evicted. + * + */ +@FunctionalInterface +public interface EvictionPolicy +{ + /** + * Select the entries which should be evicted. + * @param cacheTable the source cache table to check + * @return all entries which should be evicted + */ + public Iterable> pickEntriesToEvict(CacheTable cacheTable); + + + public static Predicate MaxCacheSizePredicate(final long maxCacheSize) + { + return cache -> cache.size() >= maxCacheSize; + } + + public static Comparator> LeastRecentlyUsedComparator() + { + return (kv1, kv2) -> Long.compare(kv1.value().accessTime(), kv2.value().accessTime()); + } + + public static Comparator> LeastFrequentlyUsedComparator() + { + return (kv1, kv2) -> Long.compare(kv1.value().accessCount(), kv2.value().accessCount()); + } + + public static Comparator> BiggestObjectsComparator() + { + return (kv1, kv2) -> Long.compare(kv2.value().byteSizeEstimate(), kv1.value().byteSizeEstimate()); + } + + public static int DefaultElementCount() + { + return 4; + } + + public static EvictionPolicy LeastRecentlyUsed(final long maxCacheSize) + { + return LeastRecentlyUsed( + DefaultElementCount(), + maxCacheSize + ); + } + + public static EvictionPolicy LeastRecentlyUsed( + final int elementCount, + final long maxCacheSize + ) + { + return LeastRecentlyUsed( + () -> elementCount, + MaxCacheSizePredicate(maxCacheSize), + null + ); + } + + public static EvictionPolicy LeastRecentlyUsed( + final _intReference elementCount, + final Predicate evictionNecessity, + final Predicate> evictionPermission + ) + { + return Sampling( + elementCount, + evictionNecessity, + evictionPermission, + LeastRecentlyUsedComparator() + ); + } + + public static EvictionPolicy LeastFrequentlyUsed(final long maxCacheSize) + { + return LeastFrequentlyUsed( + DefaultElementCount(), + maxCacheSize + ); + } + + public static EvictionPolicy LeastFrequentlyUsed( + final int elementCount, + final long maxCacheSize + ) + { + return LeastFrequentlyUsed( + () -> elementCount, + MaxCacheSizePredicate(maxCacheSize), + null + ); + } + + public static EvictionPolicy LeastFrequentlyUsed( + final _intReference elementCount, + final Predicate evictionNecessity, + final Predicate> evictionPermission + ) + { + return Sampling( + elementCount, + evictionNecessity, + evictionPermission, + LeastFrequentlyUsedComparator() + ); + } + + public static EvictionPolicy BiggestObjects( + final int elementCount, + final long maxCacheSize + ) + { + return BiggestObjects( + () -> elementCount, + MaxCacheSizePredicate(maxCacheSize), + null + ); + } + + public static EvictionPolicy BiggestObjects( + final _intReference elementCount, + final Predicate evictionNecessity, + final Predicate> evictionPermission + ) + { + return Sampling( + elementCount, + evictionNecessity, + evictionPermission, + BiggestObjectsComparator() + ); + } + + public static EvictionPolicy FirstInFirstOut( + final int elementCount, + final long maxCacheSize + ) + { + return FirstInFirstOut( + () -> elementCount, + MaxCacheSizePredicate(maxCacheSize), + null + ); + } + + public static EvictionPolicy FirstInFirstOut( + final _intReference elementCount, + final Predicate evictionNecessity, + final Predicate> evictionPermission + ) + { + return Searching( + elementCount, + evictionNecessity, + evictionPermission + ); + } + + public static EvictionPolicy Sampling( + final _intReference elementCount, + final Predicate evictionNecessity, + final Predicate> evictionPermission, + final Comparator> comparator + ) + { + return new Sampling( + elementCount, + evictionNecessity, + evictionPermission, + comparator + ); + } + + public static EvictionPolicy Searching( + final _intReference elementCount, + final Predicate evictionNecessity, + final Predicate> evictionPermission + ) + { + return new Searching( + elementCount, + evictionNecessity, + evictionPermission + ); + } + + + + /* + * Eviction by sampling. + * Pick sample range of bigger caches and sort instead of whole cache. + * Extensive tests show deviation <~1% and massive performace gain. + */ + public static class Sampling implements EvictionPolicy + { + final static int MAX_SAMPLE_COUNT = 10 ; + final static int SAMPLE_THRESHOLD = 10_000 ; + final static int MIN_SAMPLE_SIZE = 15 ; + final static int MAX_SAMPLE_SIZE = 100 ; + final static double SAMPLE_SIZE_FACTOR = 0.002; + + private final _intReference elementCount; + private final Predicate evictionNecessity; + private final Predicate> evictionPermission; + private final Comparator> comparator; + private final Random random; + + Sampling( + final _intReference elementCount, + final Predicate evictionNecessity, + final Predicate> evictionPermission, + final Comparator> comparator + ) + { + super(); + + this.elementCount = notNull(elementCount); + this.evictionNecessity = evictionNecessity; + this.evictionPermission = evictionPermission != null + ? evictionPermission + : kv -> true; + this.comparator = notNull(comparator); + this.random = new Random(); + } + + @Override + public Iterable> pickEntriesToEvict(final CacheTable cacheTable) + { + if(this.evictionNecessity != null && !this.evictionNecessity.test(cacheTable)) + { + return null; + } + + final int elementCount = this.elementCount.get(); + if(elementCount <= 0) + { + throw new RuntimeException("Illegal element count for eviction: " + elementCount + " <= 0"); + } + + + if(elementCount == 1) + { + for(int sample = 0; sample < MAX_SAMPLE_COUNT; sample++) + { + final KeyValue entryToEvict = this.sample(cacheTable); + if(entryToEvict != null && this.evictionPermission.test(entryToEvict)) + { + return X.Constant(entryToEvict); + } + } + } + else + { + for(int sample = 0; sample < MAX_SAMPLE_COUNT; sample++) + { + final XEnum> entriesToEvict = EqHashEnum.NewCustom(elementCount); + for(int i = 0; i < elementCount; i++) + { + final KeyValue entryToEvict = this.sample(cacheTable); + if(entryToEvict != null && this.evictionPermission.test(entryToEvict)) + { + entriesToEvict.add(entryToEvict); + } + } + if(!entriesToEvict.isEmpty()) + { + return entriesToEvict; + } + } + } + + return null; + } + + private KeyValue sample(final CacheTable cacheTable) + { + final int cacheSize = X.checkArrayRange(cacheTable.size()); + if(cacheSize < SAMPLE_THRESHOLD) + { + return cacheTable.min(this.comparator); + } + + final int optSampleSize = (int)(cacheSize * SAMPLE_SIZE_FACTOR); + final int sampleSize = optSampleSize < MIN_SAMPLE_SIZE + ? MIN_SAMPLE_SIZE + : optSampleSize > MAX_SAMPLE_SIZE + ? MAX_SAMPLE_SIZE + : optSampleSize; + final int offset = this.random.nextInt(cacheSize - sampleSize - 1); + return cacheTable.rangeMin( + offset, + sampleSize, + this.comparator + ); + } + + } + + + public static class Searching implements EvictionPolicy + { + private final _intReference elementCount; + private final Predicate evictionNecessity; + private final Predicate> evictionPermission; + + Searching( + final _intReference elementCount, + final Predicate evictionNecessity, + final Predicate> evictionPermission + ) + { + super(); + + this.elementCount = notNull(elementCount); + this.evictionNecessity = evictionNecessity; + this.evictionPermission = evictionPermission != null + ? evictionPermission + : kv -> true; + } + + @Override + public Iterable> pickEntriesToEvict(final CacheTable cacheTable) + { + if(this.evictionNecessity != null && !this.evictionNecessity.test(cacheTable)) + { + return null; + } + + final int elementCount = this.elementCount.get(); + if(elementCount <= 0) + { + throw new RuntimeException("Illegal element count for eviction: " + elementCount + " <= 0"); + } + + final XEnum> entriesToEvict = EqHashEnum.NewCustom(elementCount); + cacheTable.iterate(kv -> { + if(this.evictionPermission.test(kv)) + { + entriesToEvict.add(kv); + if(entriesToEvict.size() >= elementCount) + { + throw X.BREAK(); + } + } + }); + + return entriesToEvict; + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/MBeanServerUtils.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/MBeanServerUtils.java new file mode 100644 index 00000000..ce412dd8 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/MBeanServerUtils.java @@ -0,0 +1,115 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.lang.management.ManagementFactory; + +import javax.cache.CacheException; +import javax.management.MBeanServer; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; + + +class MBeanServerUtils +{ + public static enum MBeanType + { + CacheConfiguration, + CacheStatistics + } + + private static MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); + + public static void registerCacheObject( + final Cache cache, + final Object bean, + final MBeanType beanType + ) + { + final ObjectName objectName = createObjectName(cache, bean, beanType); + + try + { + if(mBeanServer.queryNames(objectName, null).isEmpty()) + { + mBeanServer.registerMBean(bean, objectName); + } + } + catch(final Exception e) + { + throw new CacheException("Error registering cache MXBeans for CacheManager " + + objectName + " . Error was " + e.getMessage(), e); + } + } + + public static void unregisterCacheObject( + final Cache cache, + final Object bean, + final MBeanType beanType + ) + { + mBeanServer.queryNames( + createObjectName(cache, bean, beanType), + null + ) + .forEach(MBeanServerUtils::unregisterCacheObject); + } + + private static void unregisterCacheObject(final ObjectName objectName) + { + try + { + mBeanServer.unregisterMBean(objectName); + } + catch(final Exception e) + { + throw new CacheException("Error unregistering object instance " + objectName, e); + } + } + + private static ObjectName createObjectName( + final Cache cache, + final Object bean, + final MBeanType beanType + ) + { + final String cacheManagerName = normalize(cache.getCacheManager().getURI().toString()); + final String cacheName = normalize(cache.getName()); + final String name = "javax.cache:type=" + beanType.name() + + ",CacheManager=" + cacheManagerName + ",Cache=" + cacheName; + try + { + return new ObjectName(name); + } + catch(final MalformedObjectNameException e) + { + throw new CacheException("Illegal ObjectName for Management Bean. " + + "CacheManager=[" + cacheManagerName + "], Cache=[" + cacheName + "]", e); + } + } + + private static String normalize(final String string) + { + return string == null + ? "" + : string.replaceAll(":|=|\n|,", "."); + } + + private MBeanServerUtils() + { + throw new Error(); + } +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/MutableCacheEntry.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/MutableCacheEntry.java new file mode 100644 index 00000000..cede8504 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/MutableCacheEntry.java @@ -0,0 +1,183 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import static org.eclipse.serializer.util.X.notNull; + +import javax.cache.integration.CacheLoader; +import javax.cache.integration.CacheLoaderException; +import javax.cache.processor.MutableEntry; + + +public interface MutableCacheEntry extends MutableEntry, Unwrappable +{ + public Operation getOperation(); + + @Override + public default T unwrap(final Class clazz) + { + return Static.unwrap(this, clazz); + } + + public static enum Operation + { + NONE, + ACCESS, + CREATE, + LOAD, + REMOVE, + UPDATE; + } + + public static MutableCacheEntry New( + final ObjectConverter converter, + final K key, + final CachedValue cachedValue, + final long now, + final CacheLoader cacheLoader + ) + { + return new Default<>( + converter, + key, + cachedValue, + now, + cacheLoader + ); + } + + public static class Default implements MutableCacheEntry + { + private final K key; + private final CachedValue cachedValue; + private final ObjectConverter converter; + private final long now; + private final CacheLoader cacheLoader; + private V value; + private Operation operation; + + Default( + final ObjectConverter converter, + final K key, + final CachedValue cachedValue, + final long now, + final CacheLoader cacheLoader + ) + { + this.converter = converter; + this.key = key; + this.cachedValue = cachedValue; + this.operation = Operation.NONE; + this.value = null; + this.now = now; + this.cacheLoader = cacheLoader; + } + + @Override + public K getKey() + { + return this.key; + } + + @Override + public V getValue() + { + if(this.operation == Operation.NONE) + { + if(this.cachedValue == null || this.cachedValue.isExpiredAt(this.now)) + { + this.value = null; + } + else if(this.value == null) + { + final Object internalValue; + this.value = (internalValue = this.cachedValue.value(this.now)) == null + ? null + : this.converter.externalize(internalValue); + } + } + + if(this.value != null) + { + // mark as Accessed so AccessedExpiry will be computed upon return from entry processor. + if(this.operation == Operation.NONE) + { + this.operation = Operation.ACCESS; + } + } + else + { + // check for read-through + if(this.cacheLoader != null) + { + try + { + if((this.value = this.cacheLoader.load(this.key)) != null) + { + this.operation = Operation.LOAD; + } + } + catch(final Exception e) + { + if(!(e instanceof CacheLoaderException)) + { + throw new CacheLoaderException("Exception in CacheLoader", e); + } + + throw e; + } + } + } + return this.value; + } + + @Override + public boolean exists() + { + return this.value != null + || this.operation == Operation.NONE + && this.cachedValue != null + && !this.cachedValue.isExpiredAt(this.now); + } + + @Override + public void remove() + { + this.operation = this.operation == Operation.CREATE || this.operation == Operation.LOAD + ? Operation.NONE + : Operation.REMOVE; + this.value = null; + } + + @Override + public void setValue(final V value) + { + notNull(value); + this.operation = this.cachedValue == null || this.cachedValue.isExpiredAt(this.now) + ? Operation.CREATE + : Operation.UPDATE; + this.value = value; + } + + @Override + public Operation getOperation() + { + return this.operation; + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/ObjectConverter.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/ObjectConverter.java new file mode 100644 index 00000000..8d850396 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/ObjectConverter.java @@ -0,0 +1,92 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.Serializer; +import org.eclipse.serializer.persistence.binary.types.Binary; + + +public interface ObjectConverter +{ + public Object internalize(T value); + + public T externalize(Object internal); + + + public static ObjectConverter ByReference() + { + return new ByReference(); + } + + public static ObjectConverter ByValue(final Serializer serializer) + { + return new ByValue(serializer); + } + + + public static class ByReference implements ObjectConverter + { + ByReference() + { + super(); + } + + @Override + public Object internalize(final T value) + { + return value; + } + + @SuppressWarnings("unchecked") + @Override + public T externalize(final Object internal) + { + return (T)internal; + } + + } + + public static class ByValue implements ObjectConverter + { + private final Serializer serializer; + + ByValue(final Serializer serializer) + { + super(); + + this.serializer = serializer; + } + + @Override + public Object internalize(final T value) + { + return SerializedObject.New( + value.hashCode(), + this.serializer.serialize(value) + ); + } + + @Override + public T externalize(final Object internal) + { + return this.serializer.deserialize( + ((SerializedObject)internal).serializedData() + ); + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/SerializedObject.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/SerializedObject.java new file mode 100644 index 00000000..31265633 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/SerializedObject.java @@ -0,0 +1,74 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import static org.eclipse.serializer.util.X.notNull; + +import org.eclipse.serializer.persistence.binary.types.Binary; + + +public interface SerializedObject extends ByteSized +{ + public Binary serializedData(); + + public static SerializedObject New(final int hashCode, final Binary serializedData) + { + return new Default(hashCode, serializedData); + } + + public static class Default implements SerializedObject + { + private final int hashCode; + private final Binary serializedData; + + Default(final int hashCode, final Binary serializedData) + { + super(); + + this.hashCode = hashCode; + this.serializedData = notNull(serializedData); + } + + @Override + public Binary serializedData() + { + return this.serializedData; + } + + @Override + public long byteSize() + { + return this.serializedData.totalLength(); + } + + @Override + public int hashCode() + { + return this.hashCode; + } + + @Override + public boolean equals(final Object obj) + { + return obj == this + || ( obj instanceof SerializedObject + && obj.hashCode() == this.hashCode + ); + } + + } + +} diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/Unwrappable.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/Unwrappable.java new file mode 100644 index 00000000..c20d0662 --- /dev/null +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/Unwrappable.java @@ -0,0 +1,40 @@ + +package org.eclipse.store.cache.types; + +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public interface Unwrappable +{ + public T unwrap(final Class clazz); + + final class Static + { + public static T unwrap(final Object subject, final Class clazz) + { + if(clazz.isAssignableFrom(subject.getClass())) + { + return clazz.cast(subject); + } + throw new IllegalArgumentException("Unwrapping to " + clazz + " is not supported by this implementation"); + } + + private Static() + { + throw new Error(); + } + + } + +} diff --git a/cache/cache/src/main/resources/META-INF/services/javax.cache.spi.CachingProvider b/cache/cache/src/main/resources/META-INF/services/javax.cache.spi.CachingProvider new file mode 100644 index 00000000..96f801b5 --- /dev/null +++ b/cache/cache/src/main/resources/META-INF/services/javax.cache.spi.CachingProvider @@ -0,0 +1 @@ +org.eclipse.store.cache.types.CachingProvider diff --git a/cache/hibernate/LICENSE b/cache/hibernate/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/cache/hibernate/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/cache/hibernate/pom.xml b/cache/hibernate/pom.xml new file mode 100644 index 00000000..37c21a1a --- /dev/null +++ b/cache/hibernate/pom.xml @@ -0,0 +1,36 @@ + + + + + 4.0.0 + + + org.eclipse.store + cache-parent + 1.1.0-SNAPSHOT + ../pom.xml + + + cache-hibernate + + EclipseStore Cache for Hibernate + Hibernate Cache Region Factory + https://projects.eclipse.org/projects/technology.store + + + + org.eclipse.store + cache + 1.1.0-SNAPSHOT + + + org.hibernate + hibernate-core + 5.4.30.Final + provided + + + + diff --git a/cache/hibernate/src/main/java/module-info.java b/cache/hibernate/src/main/java/module-info.java new file mode 100644 index 00000000..7e534d77 --- /dev/null +++ b/cache/hibernate/src/main/java/module-info.java @@ -0,0 +1,23 @@ +/*- + * #%L + * EclipseStore Cache for Hibernate + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.cache.hibernate +{ + exports org.eclipse.store.cache.hibernate.types; + + requires transitive org.eclipse.store.cache; + requires transitive java.naming; + requires transitive java.persistence; + requires transitive org.hibernate.orm.core; + requires org.eclipse.serializer.base; +} diff --git a/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/CacheRegionFactory.java b/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/CacheRegionFactory.java new file mode 100644 index 00000000..e1ba798d --- /dev/null +++ b/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/CacheRegionFactory.java @@ -0,0 +1,455 @@ +package org.eclipse.store.cache.hibernate.types; + +/*- + * #%L + * EclipseStore Cache for Hibernate + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; + +import org.eclipse.serializer.chars.XChars; +import org.eclipse.serializer.configuration.types.ConfigurationMapperMap; +import org.eclipse.store.cache.types.Cache; +import org.eclipse.store.cache.types.CacheConfiguration; +import org.eclipse.store.cache.types.CacheConfigurationBuilderConfigurationBased; +import org.eclipse.store.cache.types.CacheManager; +import org.eclipse.store.cache.types.CachingProvider; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.cfg.spi.DomainDataRegionBuildingContext; +import org.hibernate.cache.cfg.spi.DomainDataRegionConfig; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; +import org.hibernate.cache.spi.CacheKeysFactory; +import org.hibernate.cache.spi.DomainDataRegion; +import org.hibernate.cache.spi.SecondLevelCacheLogger; +import org.hibernate.cache.spi.support.DomainDataRegionImpl; +import org.hibernate.cache.spi.support.DomainDataStorageAccess; +import org.hibernate.cache.spi.support.RegionFactoryTemplate; +import org.hibernate.cache.spi.support.RegionNameQualifier; +import org.hibernate.cache.spi.support.SimpleTimestamper; +import org.hibernate.engine.spi.SessionFactoryImplementor; + + +public class CacheRegionFactory extends RegionFactoryTemplate +{ + private final CacheKeysFactory cacheKeysFactory; + private volatile CacheManager cacheManager; + private final AtomicBoolean isExplicitCacheManager = new AtomicBoolean(); + private volatile CacheConfiguration cacheConfiguration; + private volatile MissingCacheStrategy missingCacheStrategy; + private final AtomicLong cacheLockTimeout = new AtomicLong(); + + public CacheRegionFactory() + { + this(DefaultCacheKeysFactory.INSTANCE); + } + + public CacheRegionFactory( + final CacheKeysFactory cacheKeysFactory + ) + { + super(); + this.cacheKeysFactory = cacheKeysFactory; + } + + @Override + protected CacheKeysFactory getImplicitCacheKeysFactory() + { + return this.cacheKeysFactory; + } + + @Override + protected void prepareForUse( + final SessionFactoryOptions settings, + @SuppressWarnings("rawtypes") // superclass uses raw type + final Map properties + ) + { + this.cacheManager = this.resolveCacheManager( + settings, + properties + ); + + this.cacheConfiguration = this.resolveCacheConfiguration( + settings, + properties + ); + + this.missingCacheStrategy = MissingCacheStrategy.ofSetting( + properties.get(ConfigurationPropertyNames.MISSING_CACHE_STRATEGY) + ); + + final Object cacheLockTimeoutConfigValue = properties.get( + ConfigurationPropertyNames.CACHE_LOCK_TIMEOUT + ); + if(cacheLockTimeoutConfigValue != null) + { + final int lockTimeoutInMillis = cacheLockTimeoutConfigValue instanceof String + ? Integer.decode((String)cacheLockTimeoutConfigValue) + : ((Number)cacheLockTimeoutConfigValue).intValue() + ; + this.cacheLockTimeout.set(SimpleTimestamper.ONE_MS * lockTimeoutInMillis); + } + } + + @SuppressWarnings("rawtypes") + protected CacheManager resolveCacheManager( + final SessionFactoryOptions settings, + final Map properties + ) + { + final Object explicitCacheManager = properties.get(ConfigurationPropertyNames.CACHE_MANAGER); + this.isExplicitCacheManager.set(explicitCacheManager != null); + return this.isExplicitCacheManager.get() + ? this.useExplicitCacheManager(settings, explicitCacheManager) + : this.createCacheManager (settings, properties) + ; + } + + @SuppressWarnings("unchecked") + protected CacheManager useExplicitCacheManager( + final SessionFactoryOptions settings, + final Object setting + ) + { + if(setting instanceof CacheManager) + { + return (CacheManager)setting; + } + + try + { + final Class cacheManagerClass = setting instanceof Class + ? (Class)setting + : this.loadClass(setting.toString(), settings) + ; + return cacheManagerClass.getDeclaredConstructor().newInstance(); + } + catch(ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) + { + throw new CacheException("Could not use explicit CacheManager : " + setting, e); + } + } + + @SuppressWarnings({"rawtypes", "resource"}) + protected CacheManager createCacheManager( + final SessionFactoryOptions settings, + final Map properties) + { + return new CachingProvider().getCacheManager(); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + protected CacheConfiguration resolveCacheConfiguration( + final SessionFactoryOptions settings, + final Map properties + ) + { + // 1. Check for configured external resource + final String configurationResourceName = properties != null + ? (String)properties.get(ConfigurationPropertyNames.CONFIGURATION_RESOURCE_NAME) + : null; + if(!XChars.isEmpty(configurationResourceName)) + { + final URL url = this.loadResource(configurationResourceName, settings); + if(url == null) + { + throw new CacheException("Storage configuration not found: " + configurationResourceName); + } + return CacheConfiguration.load(url, Object.class, Object.class); + } + + // 2. Check for properties in context config + final String prefix = "hibernate.cache.eclipsestore."; + final Map msCacheProperties = ((Map)properties).entrySet().stream() + .filter(kv -> kv.getKey().toString().startsWith(prefix)) + .collect(Collectors.toMap( + kv -> kv.getKey().toString().substring(prefix.length()), + kv -> kv.getValue().toString() + )) + ; + if(msCacheProperties.size() > 0L) + { + return (CacheConfiguration)CacheConfigurationBuilderConfigurationBased.New( + className -> this.loadClass(className, settings) + ) + .buildCacheConfiguration( + ConfigurationMapperMap.New() + .mapConfiguration(msCacheProperties) + .buildConfiguration() + ) + .build(); + } + + // 3. Check for default property resource + final CacheConfiguration configuration = + CacheConfiguration.load(Object.class, Object.class); + return configuration != null + ? configuration + // 4. Otherwise use simple default configuration + : CacheConfiguration.Builder(Object.class, Object.class) + .storeByReference() + .build(); + } + + protected URL loadResource( + final String configurationResourceName, + final SessionFactoryOptions settings + ) + { + if(!super.isStarted()) + { + throw new IllegalStateException("Cannot load resource through a non-started CacheRegionFactory"); + } + + URL url = settings.getServiceRegistry() + .getService(ClassLoaderService.class) + .locateResource(configurationResourceName) + ; + + if(url == null) + { + final ClassLoader contextClassloader = Thread.currentThread().getContextClassLoader(); + if(contextClassloader != null) + { + url = contextClassloader.getResource(configurationResourceName); + } + if(url == null) + { + url = this.getClass().getResource(configurationResourceName); + + if(url == null) + { + try + { + url = new URL(configurationResourceName); + } + catch(final MalformedURLException e) + { + // ignore + } + } + } + } + + return url; + } + + @SuppressWarnings("unchecked") + protected Class loadClass( + final String configurationClassName, + final SessionFactoryOptions settings + ) throws ClassNotFoundException + { + if(!super.isStarted()) + { + throw new IllegalStateException("Cannot load class through a non-started CacheRegionFactory"); + } + + Class clazz = settings.getServiceRegistry() + .getService(ClassLoaderService.class) + .classForName(configurationClassName) + ; + + if(clazz == null) + { + final ClassLoader contextClassloader = Thread.currentThread().getContextClassLoader(); + if(contextClassloader != null) + { + clazz = (Class)contextClassloader.loadClass(configurationClassName); + } + if(clazz == null) + { + clazz = (Class)Class.forName(configurationClassName); + } + } + + return clazz; + } + + @Override + public long getTimeout() + { + return this.cacheLockTimeout.get(); + } + + @Override + protected DomainDataStorageAccess createDomainDataStorageAccess( + final DomainDataRegionConfig regionConfig, + final DomainDataRegionBuildingContext buildingContext) + { + return StorageAccess.New( + this.getOrCreateCache(regionConfig.getRegionName(), buildingContext.getSessionFactory()) + ); + } + + @Override + public DomainDataRegion buildDomainDataRegion( + final DomainDataRegionConfig regionConfig, + final DomainDataRegionBuildingContext buildingContext + ) + { + return new DomainDataRegionImpl( + regionConfig, + this, + this.createDomainDataStorageAccess(regionConfig, buildingContext), + this.cacheKeysFactory, + buildingContext + ); + } + + @Override + protected StorageAccess createQueryResultsRegionStorageAccess( + final String regionName, + final SessionFactoryImplementor sessionFactory + ) + { + final String defaultedRegionName = this.defaultRegionName( + regionName, + sessionFactory, + DEFAULT_QUERY_RESULTS_REGION_UNQUALIFIED_NAME, + LEGACY_QUERY_RESULTS_REGION_UNQUALIFIED_NAMES + ); + return StorageAccess.New( + this.getOrCreateCache(defaultedRegionName, sessionFactory) + ); + } + + @Override + protected StorageAccess createTimestampsRegionStorageAccess( + final String regionName, + final SessionFactoryImplementor sessionFactory + ) + { + final String defaultedRegionName = this.defaultRegionName( + regionName, + sessionFactory, + DEFAULT_UPDATE_TIMESTAMPS_REGION_UNQUALIFIED_NAME, + LEGACY_UPDATE_TIMESTAMPS_REGION_UNQUALIFIED_NAMES + ); + return StorageAccess.New( + this.getOrCreateCache(defaultedRegionName, sessionFactory) + ); + } + + protected final String defaultRegionName( + final String regionName, + final SessionFactoryImplementor sessionFactory, + final String defaultRegionName, + final List legacyDefaultRegionNames + ) + { + if(defaultRegionName.equals(regionName) && !this.cacheExists(regionName, sessionFactory)) + { + for(final String legacyDefaultRegionName : legacyDefaultRegionNames) + { + if(this.cacheExists(legacyDefaultRegionName, sessionFactory)) + { + SecondLevelCacheLogger.INSTANCE.usingLegacyCacheName( + defaultRegionName, + legacyDefaultRegionName + ); + return legacyDefaultRegionName; + } + } + } + + return regionName; + } + + protected boolean cacheExists( + final String unqualifiedRegionName, + final SessionFactoryImplementor sessionFactory + ) + { + final String qualifiedRegionName = RegionNameQualifier.INSTANCE.qualify( + unqualifiedRegionName, + sessionFactory.getSessionFactoryOptions() + ); + return this.cacheManager.getCache(qualifiedRegionName) != null; + } + + protected Cache getOrCreateCache( + final String unqualifiedRegionName, + final SessionFactoryImplementor sessionFactory + ) + { + this.verifyStarted(); + + final String qualifiedRegionName = RegionNameQualifier.INSTANCE.qualify( + unqualifiedRegionName, + sessionFactory.getSessionFactoryOptions() + ); + + final Cache cache = this.cacheManager.getCache(qualifiedRegionName); + return cache != null + ? cache + : this.createCache(qualifiedRegionName) + ; + } + + protected Cache createCache( + final String regionName + ) + { + switch(this.missingCacheStrategy) + { + case CREATE_WARN: + SecondLevelCacheLogger.INSTANCE.missingCacheCreated( + regionName, + ConfigurationPropertyNames.MISSING_CACHE_STRATEGY, + MissingCacheStrategy.CREATE.getExternalRepresentation() + ); + // fall-through to create + + case CREATE: + return this.cacheManager.createCache( + regionName, + this.cacheConfiguration + ); + + case FAIL: + throw new CacheException("On-the-fly creation of EclipseStore Cache objects is not supported [" + regionName + "]"); + + default: + throw new IllegalStateException("Unsupported missing cache strategy: " + this.missingCacheStrategy); + } + } + + @Override + protected void releaseFromUse() + { + if(this.cacheManager != null) + { + try + { + if(!this.isExplicitCacheManager.get()) + { + this.cacheManager.close(); + } + } + finally + { + this.cacheManager = null; + } + } + } + +} diff --git a/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/CacheStrategyRegistrationProvider.java b/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/CacheStrategyRegistrationProvider.java new file mode 100644 index 00000000..655bc7cc --- /dev/null +++ b/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/CacheStrategyRegistrationProvider.java @@ -0,0 +1,45 @@ +package org.eclipse.store.cache.hibernate.types; + +/*- + * #%L + * EclipseStore Cache for Hibernate + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.Collections; + +import org.hibernate.boot.registry.selector.SimpleStrategyRegistrationImpl; +import org.hibernate.boot.registry.selector.StrategyRegistration; +import org.hibernate.boot.registry.selector.StrategyRegistrationProvider; +import org.hibernate.cache.spi.RegionFactory; + + +public class CacheStrategyRegistrationProvider implements StrategyRegistrationProvider +{ + public CacheStrategyRegistrationProvider() + { + super(); + } + + @SuppressWarnings("rawtypes") + @Override + public Iterable getStrategyRegistrations() + { + SimpleStrategyRegistrationImpl registration = new SimpleStrategyRegistrationImpl<>( + RegionFactory.class, + CacheRegionFactory.class, + "jcache", + CacheRegionFactory.class.getName(), + CacheRegionFactory.class.getSimpleName() + ); + return Collections.singleton(registration); + } +} diff --git a/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/ConfigurationPropertyNames.java b/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/ConfigurationPropertyNames.java new file mode 100644 index 00000000..b1bbf93f --- /dev/null +++ b/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/ConfigurationPropertyNames.java @@ -0,0 +1,25 @@ +package org.eclipse.store.cache.hibernate.types; + +/*- + * #%L + * EclipseStore Cache for Hibernate + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public interface ConfigurationPropertyNames +{ + public static final String PREFIX = "hibernate.cache.eclipsestore."; + + public static final String CACHE_MANAGER = PREFIX + "cache-manager"; + public static final String MISSING_CACHE_STRATEGY = PREFIX + "missing-cache-strategy"; + public static final String CACHE_LOCK_TIMEOUT = PREFIX + "cache-lock-timeout"; + public static final String CONFIGURATION_RESOURCE_NAME = PREFIX + "configuration-resource-name"; +} diff --git a/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/MissingCacheStrategy.java b/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/MissingCacheStrategy.java new file mode 100644 index 00000000..dcb8ebcf --- /dev/null +++ b/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/MissingCacheStrategy.java @@ -0,0 +1,73 @@ +package org.eclipse.store.cache.hibernate.types; + +/*- + * #%L + * EclipseStore Cache for Hibernate + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.chars.XChars; + + +public enum MissingCacheStrategy +{ + FAIL("fail"), + CREATE_WARN("create-warn"), + CREATE("create"); + + + public static MissingCacheStrategy Default() + { + return MissingCacheStrategy.CREATE_WARN; + } + + + private final String externalRepresentation; + + MissingCacheStrategy( + final String externalRepresentation + ) + { + this.externalRepresentation = externalRepresentation; + } + + public String getExternalRepresentation() + { + return this.externalRepresentation; + } + + public static MissingCacheStrategy ofSetting(Object value) + { + if(value instanceof MissingCacheStrategy) + { + return (MissingCacheStrategy)value; + } + + final String externalRepresentation = value == null + ? null + : value.toString().trim(); + + if(XChars.isEmpty(externalRepresentation)) + { + return MissingCacheStrategy.Default(); + } + + for(MissingCacheStrategy strategy : values()) + { + if(strategy.externalRepresentation.equals(externalRepresentation)) + { + return strategy; + } + } + + throw new IllegalArgumentException("Unrecognized missing cache strategy value : `" + value + '`'); + } +} diff --git a/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/StorageAccess.java b/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/StorageAccess.java new file mode 100644 index 00000000..02162ad2 --- /dev/null +++ b/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/StorageAccess.java @@ -0,0 +1,139 @@ +package org.eclipse.store.cache.hibernate.types; + +/*- + * #%L + * EclipseStore Cache for Hibernate + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import static org.eclipse.serializer.util.X.notNull; + +import javax.cache.CacheException; + +import org.eclipse.store.cache.types.Cache; +import org.hibernate.cache.spi.support.DomainDataStorageAccess; +import org.hibernate.engine.spi.SharedSessionContractImplementor; + + +public interface StorageAccess extends DomainDataStorageAccess +{ + public static StorageAccess New( + final Cache cache + ) + { + return new Default(notNull(cache)); + } + + + public static class Default implements StorageAccess + { + private final Cache cache; + + Default( + final Cache cache + ) + { + super(); + this.cache = cache; + } + + @Override + public Object getFromCache( + final Object key, + final SharedSessionContractImplementor session + ) + { + try + { + return this.cache.get(key); + } + catch(CacheException e) + { + throw new org.hibernate.cache.CacheException(e); + } + } + + @Override + public void putIntoCache( + final Object key, + final Object value, + final SharedSessionContractImplementor session + ) + { + try + { + this.cache.put(key, value); + } + catch(CacheException e) + { + throw new org.hibernate.cache.CacheException(e); + } + } + + @Override + public boolean contains( + final Object key + ) + { + try + { + return this.cache.containsKey(key); + } + catch(CacheException e) + { + throw new org.hibernate.cache.CacheException(e); + } + } + + @Override + public void evictData() + { + try + { + this.cache.removeAll(); + } + catch(CacheException e) + { + throw new org.hibernate.cache.CacheException(e); + } + } + + @Override + public void evictData( + final Object key + ) + { + try + { + this.cache.remove(key); + } + catch(CacheException e) + { + throw new org.hibernate.cache.CacheException(e); + } + } + + @Override + public void release() + { + try + { + this.cache.close(); + } + catch(CacheException e) + { + throw new org.hibernate.cache.CacheException(e); + } + } + + } + +} diff --git a/cache/hibernate/src/main/resources/META-INF/services/org.hibernate.boot.registry.selector.StrategyRegistrationProvider b/cache/hibernate/src/main/resources/META-INF/services/org.hibernate.boot.registry.selector.StrategyRegistrationProvider new file mode 100644 index 00000000..267ad01f --- /dev/null +++ b/cache/hibernate/src/main/resources/META-INF/services/org.hibernate.boot.registry.selector.StrategyRegistrationProvider @@ -0,0 +1 @@ +org.eclipse.store.cache.hibernate.types.CacheStrategyRegistrationProvider diff --git a/cache/pom.xml b/cache/pom.xml new file mode 100644 index 00000000..3d4fd7f3 --- /dev/null +++ b/cache/pom.xml @@ -0,0 +1,28 @@ + + + + + 4.0.0 + + + org.eclipse.store + store-parent + 1.1.0-SNAPSHOT + ../pom.xml + + + cache-parent + pom + + EclipseStore Cache Parent + EclipseStore Cache Project + https://projects.eclipse.org/projects/technology.store + + + cache + hibernate + + + diff --git a/pom.xml b/pom.xml index 8d3b3366..41afb2e0 100644 --- a/pom.xml +++ b/pom.xml @@ -54,6 +54,7 @@ afs + cache storage From 85b262a795a2d15e7ff70f95f2331dccbf9b45fc Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Wed, 6 Dec 2023 11:48:03 +0100 Subject: [PATCH 023/126] Add docs for Cache (#90) --- docs/modules/ROOT/nav.adoc | 8 ++ .../cache/pages/configuration/index.adoc | 30 ++++++ .../cache/pages/configuration/properties.adoc | 60 ++++++++++++ .../cache/pages/configuration/storage.adoc | 95 +++++++++++++++++++ docs/modules/cache/pages/getting-started.adoc | 67 +++++++++++++ docs/modules/cache/pages/index.adoc | 51 ++++++++++ .../hibernate-second-level-cache.adoc | 71 ++++++++++++++ .../cache/pages/use-cases/spring-cache.adoc | 63 ++++++++++++ 8 files changed, 445 insertions(+) create mode 100644 docs/modules/cache/pages/configuration/index.adoc create mode 100644 docs/modules/cache/pages/configuration/properties.adoc create mode 100644 docs/modules/cache/pages/configuration/storage.adoc create mode 100644 docs/modules/cache/pages/getting-started.adoc create mode 100644 docs/modules/cache/pages/index.adoc create mode 100644 docs/modules/cache/pages/use-cases/hibernate-second-level-cache.adoc create mode 100644 docs/modules/cache/pages/use-cases/spring-cache.adoc diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index a4620d25..d9d6cdb2 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -70,6 +70,14 @@ *** xref:storage:addendum/specialized-type-handlers.adoc[Specialized Type Handlers] *** xref:storage:addendum/examples-and-demo-projects.adoc[Examples and Demo Projects] * xref:serializer:index.adoc[Serializer] +* xref:cache:index.adoc[Cache] +** xref:cache:getting-started.adoc[Getting Started] +** xref:cache:configuration/index.adoc[Configuration] +*** xref:cache:configuration/properties.adoc[Properties] +*** xref:cache:configuration/storage.adoc[Storage] +** Use Cases +*** xref:cache:use-cases/hibernate-second-level-cache.adoc[Hibernate Second Level Cache] +*** xref:cache:use-cases/spring-cache.adoc[Spring Cache] * Miscellaneous ** xref:misc:logging/index.adoc[Logging] diff --git a/docs/modules/cache/pages/configuration/index.adoc b/docs/modules/cache/pages/configuration/index.adoc new file mode 100644 index 00000000..fc47fa11 --- /dev/null +++ b/docs/modules/cache/pages/configuration/index.adoc @@ -0,0 +1,30 @@ += Configuration + +The default way to configure a JCache provider is to use the class `javax.cache.configuration.MutableConfiguration`. +This is mostly used to avoid provider specific code. + +If you want to use all of {product-name}'s Cache features, you can use our configuration implementation: `org.eclipse.store.cache.types.CacheConfiguration` + +[source, java] +---- +CachingProvider provider = Caching.getCachingProvider(); +CacheManager cacheManager = provider.getCacheManager(); +CacheConfiguration configuration = CacheConfiguration + .Builder(Integer.class, String.class) + .storeByValue() + .expiryPolicyFactory(CreatedExpiryPolicy.factoryOf(Duration.ONE_MINUTE)) + .build(); +Cache cache = cacheManager.createCache("jCache", configuration); +cache.put(1, "Hello World"); +String value = cache.get(1); +---- + +To read an external configuration use `CacheConfigurationLoader` and `CacheConfigurationParser` or the `load*()` methods of `CacheConfiguration`. + +[source, java] +---- +CacheConfiguration configuration = CacheConfiguration + .load("cache-config.properties", Integer.class, String.class); +---- + +If you just use `CacheConfiguration.load()` the default configuration file is used, which is either a file in the classpath root named `eclipsestore-cache.properties`, or the path configured via the system property `eclipsestore.cache.configuration.path`. diff --git a/docs/modules/cache/pages/configuration/properties.adoc b/docs/modules/cache/pages/configuration/properties.adoc new file mode 100644 index 00000000..ff09a20a --- /dev/null +++ b/docs/modules/cache/pages/configuration/properties.adoc @@ -0,0 +1,60 @@ += Properties + +These are the available properties of the `CacheConfiguration` type. +The property names are used in the external configuration files. +They can be found as constants in `CacheConfigurationPropertyNames`. + +[options="header",cols="1,1,2a"] +|=== +|Property +|Type +|Description + +|key-type +|Fully Qualified Class Name +|Determines the required type of keys for the Cache. + +|value-type +|Fully Qualified Class Name +|Determines the required type of values for the Cache. + +|storage-configuration-resource-name +|absolute or relative file name +|Path for the xref:storage:configuration/index.adoc#external-configuration[storage configuration] for the backing store. + +|cache-loader-factory +|Fully Qualified Class Name of JCache factory implementation for a `javax.cache.integration.CacheLoader` +|A CacheLoader should be configured for "Read Through" caches to load values when a cache miss occurs. + +|cache-writer-factory +|Fully Qualified Class Name of JCache factory implementation for a `javax.cache.integration.CacheWriter` +|A CacheWriter is used for write-through to an external resource. + +|expiry-policy-factory +|Fully Qualified Class Name of JCache factory implementation for a `javax.cache.expiry.ExpiryPolicy` +|Determines when cache entries will expire based on creation, access and modification operations. + +|eviction-manager-factory +|Fully Qualified Class Name of JCache factory implementation for a `org.eclipse.store.cache.types.EvictionManager` +|Clears cache entries using a policy. Works interval-based or on entry creation. + +|read-through +|boolean parsed according to the https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html#parseBoolean-java.lang.String-[java.lang.Boolean.parseBoolean()] rules +|When in "read-through" mode, cache misses that occur due to cache entries not existing as a result of performing a "get" will appropriately cause the configured CacheLoader to be invoked. + +|write-through +|boolean parsed according to the https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html#parseBoolean-java.lang.String-[java.lang.Boolean.parseBoolean()] rules +|When in "write-through" mode, cache updates that occur as a result of performing "put" operations will appropriately cause the configured CacheWriter to be invoked. + +|store-by-value +|boolean parsed according to the https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html#parseBoolean-java.lang.String-[java.lang.Boolean.parseBoolean()] rules +|When a cache is storeByValue, any mutation to the key or value does not affect the key of value stored in the cache. + +|statistics-enabled +|boolean parsed according to the https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html#parseBoolean-java.lang.String-[java.lang.Boolean.parseBoolean()] rules +|Checks whether statistics collection is enabled in this cache. + +|management-enabled +|boolean parsed according to the https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html#parseBoolean-java.lang.String-[java.lang.Boolean.parseBoolean()] rules +|Checks whether management is enabled on this cache. +|=== diff --git a/docs/modules/cache/pages/configuration/storage.adoc b/docs/modules/cache/pages/configuration/storage.adoc new file mode 100644 index 00000000..d23be80e --- /dev/null +++ b/docs/modules/cache/pages/configuration/storage.adoc @@ -0,0 +1,95 @@ += Storage + +{product-name}'s storage can be used as a backing store for the cache. +It functions as a CacheWriter as well as a CacheReader, depending on the writeThrough and readThrough configuration. +Per default it is used for both. + +[source, java] +---- +EmbeddedStorageManager storageManager = EmbeddedStorage.start(); +CachingProvider provider = Caching.getCachingProvider(); +CacheManager cacheManager = provider.getCacheManager(); +CacheConfiguration configuration = CacheConfiguration + .Builder(Integer.class, String.class, "my-cache", storageManager) + .build(); +Cache cache = cacheManager.createCache("jCache", configuration); +---- + +If you prefer an external configuration, you can link the xref:storage:configuration/index.adoc#external-configuration[storage configuration]: + +[source, text, title="cache-config.properties"] +---- +key-type = java.lang.Integer +value-type = java.lang.String + +read-through = true +write-through = true + +storage-configuration-resource-name = eclipsestore-storage.properties +---- + +[source, text, title="eclipsestore-storage.properties"] +---- +storage-directory = ~/cache-data +channel-count = 4 +---- + +Or you can embed the storage configuration within the cache configuration using the `storage.` prefix: + +[source, text, title="cache-config.properties"] +---- +key-type = java.lang.Integer +value-type = java.lang.String + +read-through = true +write-through = true + +storage.storage-directory = ~/cache-data +storage.channel-count = 4 +---- + +== Cache expiry and StorageManager + +Since the validity of a Cache entry is only determined when the value is retrieved, the expiry durations are not always respected when using the `StorageManager` when the application is restarted. An example makes this clear. + +Suppose we have defined a cache where the https://github.com/jsr107/jsr107spec/blob/master/src/main/java/javax/cache/expiry/ExpiryPolicy.java[ExpiryPolicy] is set to 1 Minute. + +When we create an entry in this cache and we did not request the cache entry after the 1-minute expiry before we do shut down the application. + +When we start up the application again, When we request the cache entry, it is loaded from the {product-name} Storage Manager and 'created' with a new expiry of 1 minute. + +This means that even if the entry was already created more than 1 minute ago (even when we only take into consideration the application uptime), the entry is still returned to the calling code. + +== Spring example + +[source, text, title="application.properties"] +---- +spring.jpa.properties.hibernate.cache.eclipsestore.missing_cache_strategy = create +spring.jpa.properties.hibernate.cache.eclipsestore.readThrough = true +spring.jpa.properties.hibernate.cache.eclipsestore.writeThrough = true +spring.jpa.properties.hibernate.cache.eclipsestore.storage.baseDirectory = ~/cache-data +spring.jpa.properties.hibernate.cache.eclipsestore.storage.channelCount = 4 +spring.jpa.properties.hibernate.cache.region.factory_class = org.eclipse.store.cache.hibernate.types.CacheRegionFactory +spring.jpa.properties.hibernate.cache.use_query_cache = true +spring.jpa.properties.hibernate.cache.use_second_level_cache = true +---- + +[source, yaml, title="application.yml"] +---- +spring: + jpa: + properties: + hibernate: + cache: + eclipsestore: + missing_cache_strategy: create + readThrough: true + writeThrough: true + storage: + baseDirectory: ~/cache-data + channelCount: 4 + region: + factory_class: org.eclipse.store.cache.hibernate.types.CacheRegionFactory + use_query_cache: true + use_second_level_cache: true +---- diff --git a/docs/modules/cache/pages/getting-started.adoc b/docs/modules/cache/pages/getting-started.adoc new file mode 100644 index 00000000..8388f1f5 --- /dev/null +++ b/docs/modules/cache/pages/getting-started.adoc @@ -0,0 +1,67 @@ += Getting Started + +== Prerequisites + +[source, xml, subs=attributes+, title="pom.xml"] +---- + + + org.eclipse.store + cache + {maven-version} + + +---- + +The above dependency adds the JCache API and {product-name} Embedded Storage as transient dependencies to your project. + +== Hello World + +[source, java] +---- +CachingProvider provider = Caching.getCachingProvider(); +CacheManager cacheManager = provider.getCacheManager(); +MutableConfiguration configuration = new MutableConfiguration() + .setStoreByValue(false) + .setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(Duration.ONE_MINUTE)); +Cache cache = cacheManager.createCache("jCache", configuration); +cache.put(1, "Hello World"); +String value = cache.get(1); +---- + +. Get the default `CachingProvider` implementation from the application's classpath. +This method will work if and only if there is only one JCache implementation available in the classpath. +If there are multiple providers then use the fully qualified name + `Caching.getCachingProvider("org.eclipse.store.cache.types.CachingProvider")` instead. + +. Get the default `CacheManager` instance using the provider. + +. Create a cache configuration using `MutableConfiguration` + +. with key type and value type as `Integer` and `String` respectively + +. configured to store the cache entries by reference (not by value) + +. and with an expiry time of one minute defined for entries from the moment they are created. + +. Using the cache manager, create a cache named `jCache` with the configuration created in step 3. + +. Put some data into the cache + +. And retrieve it. + +The same can be done using {product-name}'s `CacheConfiguration` API. +This time we use a `EmbeddedStorageManager` as a backing store for the cache. + +[source, java] +---- +EmbeddedStorageManager storageManager = EmbeddedStorage.start(); +CachingProvider provider = Caching.getCachingProvider(); +CacheManager cacheManager = provider.getCacheManager(); +CacheConfiguration configuration = CacheConfiguration + .Builder(Integer.class, String.class, "jCache", storageManager) + .expiryPolicyFactory(CreatedExpiryPolicy.factoryOf(Duration.ONE_HOUR)) + .build(); +Cache cache = cacheManager.createCache("jCache", configuration); +cache.put(1, "one"); +String value = cache.get(1); +---- diff --git a/docs/modules/cache/pages/index.adoc b/docs/modules/cache/pages/index.adoc new file mode 100644 index 00000000..2b0cac39 --- /dev/null +++ b/docs/modules/cache/pages/index.adoc @@ -0,0 +1,51 @@ += Cache + +{product-name} provides a JCache (https://www.jcp.org/en/jsr/detail?id=107[JSR-107]) implementation, which is optionally backed by a {product-name} Storage. + +JCache standardizes caching for the Java platform. +It provides a common mechanism to cache values in a map-like structure. +It expedites the mainstream adoption of in-memory computing by giving all Java developers an easy way to access memory from within Java. +Businesses can change providers without rewriting their applications or maintaining a proprietary cache abstraction layer. + +This caching standard is used in a wide variety of environments. +The most common use cases are: + +* Second-level cache in JPA (e.g. xref:use-cases/hibernate-second-level-cache.adoc[Hibernate]) +* xref:use-cases/spring-cache.adoc[Spring Cache Abstraction] +* and many more + +== Motivation + +Why another JCache implementation, you may wonder. +There is already a myriad of providers out there. + +{product-name}'s very own serialization and storage can be utilized to get the best out of caches. +For example, you are not limited to `java.io.Serializable` types, when storing a value. +That means every key-value pair gets copied every time you put and get entries in and out of a cache. +And if a cache is used with a backing store, {product-name}'s storage can be used to get the best possible performance. + +And now, {product-name} being a JCache provider, you can use it as a drop-in replacement in your existing application. + +== Basic Concepts of JCache + +=== CachingProvider + +The caching provider represents the implementation of JCache that you are using. +You can use more than one JCache implementation in your project if you wish, and CachingProvider is how you access the different providers that are in use. + +=== CacheManager + +It is responsible for managing and providing access to many named caches. + +=== Cache + +The cache holds the different values being cached. +You can have several caches, each of which may be holding data for a different purpose. +Each one can have a different configuration; +for example, different caches may evict old data using different techniques. + +=== Entry + +Each item of data in a cache is an entry, which is a key-value pair. + +The key is a unique value used to store and look up the data. + +The value is the actual data you wish to cache. + +Caches have some different properties than Maps, but the calls that you would use to store and lookup data is very similar. diff --git a/docs/modules/cache/pages/use-cases/hibernate-second-level-cache.adoc b/docs/modules/cache/pages/use-cases/hibernate-second-level-cache.adoc new file mode 100644 index 00000000..e8ec998a --- /dev/null +++ b/docs/modules/cache/pages/use-cases/hibernate-second-level-cache.adoc @@ -0,0 +1,71 @@ += Hibernate Second Level Cache + +{product-name} offers a Hibernate cache region factory, which can be found in the `cache.hibernate` module. + +[source, xml, title="pom.xml", subs=attributes+] +---- + + + org.eclipse.store + cache-hibernate + {maven-version} + + +---- + +The region factory's class name is `org.eclipse.store.cache.hibernate.types.CacheRegionFactory`. + +It is configured via the property `hibernate.cache.region.factory_class`. + +Depending on your environment it can be configured in different ways. + +If you use a good old persistence.xml, set the property there: + +[source, xml, title="persistence.xml"] +---- + + + + org.hibernate.jpa.HibernatePersistenceProvider + ... + + ... + + ... + + + +---- + +== Spring Example + +[source, text, title="application.properties"] +---- +spring.jpa.properties.hibernate.cache.eclipsestore.missing_cache_strategy=create +spring.jpa.properties.hibernate.cache.region.factory_class=org.eclipse.store.cache.hibernate.types.CacheRegionFactory +spring.jpa.properties.hibernate.cache.use_query_cache=true +spring.jpa.properties.hibernate.cache.use_second_level_cache=true +spring.jpa.properties.javax.persistence.sharedCache.mode=ALL +---- + +[source, yaml, title="application.yml"] +---- +spring: + jpa: + properties: + hibernate: + cache: + eclipsestore: + missing_cache_strategy: create + region: + factory_class: org.eclipse.store.cache.hibernate.types.CacheRegionFactory + use_query_cache: true + use_second_level_cache: true + javax: + persistence: + sharedCache: + mode: ALL +---- diff --git a/docs/modules/cache/pages/use-cases/spring-cache.adoc b/docs/modules/cache/pages/use-cases/spring-cache.adoc new file mode 100644 index 00000000..01fda39c --- /dev/null +++ b/docs/modules/cache/pages/use-cases/spring-cache.adoc @@ -0,0 +1,63 @@ += Spring Cache + +First of all add the {product-name} Cache dependency: + +[source, xml, title="pom.xml", subs=attributes+] +---- + + + org.eclipse.store + cache + {maven-version} + + +---- + +The core caching abstraction provided by Spring comes in the https://search.maven.org/search?q=g:org.springframework%20a:spring-context[spring-context] module. + +[source, xml] +---- + + org.springframework + spring-context + ... + +---- + +If you use Spring Boot, then add the https://search.maven.org/search?q=g:org.springframework.boot%20a:spring-boot-starter-cache[spring-boot-starter-cache] package to add the caching dependencies: + +[source, xml] +---- + + org.springframework.boot + spring-boot-starter-cache + +---- + +To enable caching, Spring makes good use of annotations, much like enabling any other configuration level feature in the framework. + +The caching feature can be enabled by simply providing a cache setup component. + +[source, java] +---- +@SpringBootApplication +@EnableCaching +public class MyApplication +---- + +[source, java] +---- +@Component +public class CachingSetup implements JCacheManagerCustomizer +{ + @Override + public void customize(CacheManager cacheManager) + { + cacheManager.createCache("my_cache", new MutableConfiguration<>() + .setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(new Duration(SECONDS, 10000))) + .setStoreByValue(true) + .setStatisticsEnabled(true)); + } +} +---- + +TIP: More information about the Spring Cache Abstraction: https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#cache From 942e3546a61a792145ef7396cfb8851ae6fd73f1 Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Wed, 6 Dec 2023 15:43:49 +0100 Subject: [PATCH 024/126] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5a18818c..e965db37 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ EclipseStore is available under [Eclipse Public License - v 2.0](LICENSE). - [Reference manual](https://docs.eclipsestore.io) - [Get started](https://docs.eclipsestore.io/manual/storage/getting-started.html) - [Changelog](https://docs.eclipsestore.io/manual/intro/changelog.html) +- [Examples](/examples) +- [Demo project](https://github.com/eclipse-store/bookstore-demo) ## Build From 7acfe4ea475e6b605fde1a6e2b7f1f4d2064f936 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Fri, 27 Oct 2023 09:28:35 +0200 Subject: [PATCH 025/126] Spring Integration --- cache/cache/pom.xml | 2 +- .../misc/pages/integrations/index.adoc | 10 + .../misc/pages/integrations/spring-boot.adoc | 204 ++++++++ examples/custom-legacy-type-handler/pom.xml | 2 +- examples/custom-type-handler/pom.xml | 2 +- examples/items/pom.xml | 2 +- examples/layered-entities/pom.xml | 4 +- examples/lazy-loading/pom.xml | 2 +- examples/loading/pom.xml | 2 +- examples/pom.xml | 30 +- examples/spring-boot3-simple/pom.xml | 78 +++ examples/spring-boot3-simple/readme.md | 53 +++ .../spring/boot/example/JokesApplication.java | 41 ++ .../example/controller/JokesController.java | 115 +++++ .../spring/boot/example/model/Root.java | 33 ++ .../boot/example/service/JokesServices.java | 71 +++ .../example/service/JokesServicesImpl.java | 85 ++++ .../boot/example/storage/JokesStorage.java | 73 +++ .../example/storage/JokesStorageImpl.java | 92 ++++ .../src/main/resources/META-INF/MANIFEST.MF | 1 + .../src/main/resources/application.properties | 3 + .../src/main/resources/jokes.txt | 250 ++++++++++ .../src/main/resources/logback.xml | 16 + examples/storing/pom.xml | 2 +- integrations/pom.xml | 36 ++ integrations/spring-boot3/pom.xml | 117 +++++ .../src/main/java/module-info.java | 39 ++ .../boot/types/EclipseStoreBeanFactory.java | 63 +++ .../boot/types/EclipseStoreProvider.java | 57 +++ .../boot/types/EclipseStoreProviderImpl.java | 120 +++++ .../boot/types/EclipseStoreSpringBoot.java | 47 ++ .../boot/types/concurent/LockAspect.java | 169 +++++++ .../spring/boot/types/concurent/Mutex.java | 47 ++ .../spring/boot/types/concurent/Read.java | 45 ++ .../spring/boot/types/concurent/Write.java | 45 ++ .../configuration/ConfigurationPair.java | 33 ++ .../configuration/EclipseStoreProperties.java | 444 ++++++++++++++++++ .../configuration/StorageFilesystem.java | 124 +++++ .../aws/AbstractAwsProperties.java | 71 +++ .../boot/types/configuration/aws/Aws.java | 47 ++ .../types/configuration/aws/Credentials.java | 79 ++++ .../types/configuration/aws/Dynamodb.java | 21 + .../boot/types/configuration/aws/S3.java | 20 + .../boot/types/configuration/azure/Azure.java | 34 ++ .../configuration/azure/Credentials.java | 101 ++++ .../types/configuration/azure/Storage.java | 79 ++++ .../googlecloud/Googlecloud.java | 34 ++ .../googlecloud/firestore/Credentials.java | 51 ++ .../googlecloud/firestore/Firestore.java | 50 ++ .../configuration/oraclecloud/Client.java | 64 +++ .../configuration/oraclecloud/ConfigFile.java | 64 +++ .../oraclecloud/ObjectStorage.java | 77 +++ .../oraclecloud/Oraclecloud.java | 34 ++ .../boot/types/configuration/redis/Redis.java | 34 ++ .../sql/AbstractSqlConfiguration.java | 86 ++++ .../boot/types/configuration/sql/Mariadb.java | 20 + .../boot/types/configuration/sql/Oracle.java | 21 + .../types/configuration/sql/Postgres.java | 19 + .../boot/types/configuration/sql/Sql.java | 74 +++ .../boot/types/configuration/sql/Sqlite.java | 19 + .../boot/types/converter/ConfigKeys.java | 105 +++++ .../EclipseStoreConfigConverter.java | 256 ++++++++++ .../types/EclipseConfigurationSpringTest.java | 56 +++ .../EclipseConfigurationSqlSpringTest.java | 54 +++ .../boot/types/InjectStorageBeanTest.java | 40 ++ .../boot/types/RestartStorageBeanTest.java | 101 ++++ .../types/converter/ConfigFieldsTest.java | 53 +++ .../EclipseStoreConfigConverterTest.java | 102 ++++ .../boot/types/root/AutostartRootTest.java | 39 ++ .../spring/boot/types/root/Root.java | 19 + .../spring/boot/types/storages/FirstRoot.java | 35 ++ .../boot/types/storages/SecondRoot.java | 40 ++ .../types/storages/TwoBeanConfiguration.java | 66 +++ .../boot/types/storages/TwoStoragesTest.java | 49 ++ .../application-autostart-root.properties | 4 + .../test/resources/application-run.properties | 3 + .../test/resources/application-sql.properties | 3 + .../resources/application-test.properties | 6 + .../application-two-storages.properties | 7 + .../src/test/resources/banner.txt | 9 + .../src/test/resources/logback-test.xml | 14 + pom.xml | 3 +- 82 files changed, 4703 insertions(+), 19 deletions(-) create mode 100644 docs/modules/misc/pages/integrations/index.adoc create mode 100644 docs/modules/misc/pages/integrations/spring-boot.adoc create mode 100644 examples/spring-boot3-simple/pom.xml create mode 100644 examples/spring-boot3-simple/readme.md create mode 100644 examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/JokesApplication.java create mode 100644 examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/controller/JokesController.java create mode 100644 examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/model/Root.java create mode 100644 examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServices.java create mode 100644 examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServicesImpl.java create mode 100644 examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorage.java create mode 100644 examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorageImpl.java create mode 100644 examples/spring-boot3-simple/src/main/resources/META-INF/MANIFEST.MF create mode 100644 examples/spring-boot3-simple/src/main/resources/application.properties create mode 100644 examples/spring-boot3-simple/src/main/resources/jokes.txt create mode 100644 examples/spring-boot3-simple/src/main/resources/logback.xml create mode 100644 integrations/pom.xml create mode 100644 integrations/spring-boot3/pom.xml create mode 100644 integrations/spring-boot3/src/main/java/module-info.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreBeanFactory.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProvider.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProviderImpl.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreSpringBoot.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/LockAspect.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Mutex.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Read.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Write.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/ConfigurationPair.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/StorageFilesystem.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/AbstractAwsProperties.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Aws.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Credentials.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Dynamodb.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/S3.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Azure.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Credentials.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Storage.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/Googlecloud.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Credentials.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Firestore.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Client.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ConfigFile.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ObjectStorage.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Oraclecloud.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/redis/Redis.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/AbstractSqlConfiguration.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Mariadb.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Oracle.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Postgres.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sql.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sqlite.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java create mode 100644 integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSpringTest.java create mode 100644 integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSqlSpringTest.java create mode 100644 integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/InjectStorageBeanTest.java create mode 100644 integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/RestartStorageBeanTest.java create mode 100644 integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigFieldsTest.java create mode 100644 integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverterTest.java create mode 100644 integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/root/AutostartRootTest.java create mode 100644 integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/root/Root.java create mode 100644 integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/FirstRoot.java create mode 100644 integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/SecondRoot.java create mode 100644 integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoBeanConfiguration.java create mode 100644 integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoStoragesTest.java create mode 100644 integrations/spring-boot3/src/test/resources/application-autostart-root.properties create mode 100644 integrations/spring-boot3/src/test/resources/application-run.properties create mode 100644 integrations/spring-boot3/src/test/resources/application-sql.properties create mode 100644 integrations/spring-boot3/src/test/resources/application-test.properties create mode 100644 integrations/spring-boot3/src/test/resources/application-two-storages.properties create mode 100644 integrations/spring-boot3/src/test/resources/banner.txt create mode 100644 integrations/spring-boot3/src/test/resources/logback-test.xml diff --git a/cache/cache/pom.xml b/cache/cache/pom.xml index 40965983..baae0e0f 100644 --- a/cache/cache/pom.xml +++ b/cache/cache/pom.xml @@ -38,7 +38,7 @@ org.eclipse.serializer serializer - 1.1.0-SNAPSHOT + ${eclipse.serializer.version} diff --git a/docs/modules/misc/pages/integrations/index.adoc b/docs/modules/misc/pages/integrations/index.adoc new file mode 100644 index 00000000..da21ab88 --- /dev/null +++ b/docs/modules/misc/pages/integrations/index.adoc @@ -0,0 +1,10 @@ += Integrations + +Various Eclise Store integrations are currently available. + +Integrations created by MicroStream are + +- xref:misc:integrations/spring-boot.adoc[Spring Boot] + +Other integrations will be added in the future. + diff --git a/docs/modules/misc/pages/integrations/spring-boot.adoc b/docs/modules/misc/pages/integrations/spring-boot.adoc new file mode 100644 index 00000000..bf91500f --- /dev/null +++ b/docs/modules/misc/pages/integrations/spring-boot.adoc @@ -0,0 +1,204 @@ += Spring Boot Integration + +image::https://upload.wikimedia.org/wikipedia/commons/4/44/Spring_Framework_Logo_2018.svg[] + +Eclipse Store comes with a Spring Boot integration. +It is available within this artifact: + +[source, xml, title="pom.xml", subs=attributes+] +---- + + + org.eclipse.store + integrations-spring-boot3 + {maven-version} + + +---- + +Official Spring Boot site: https://spring.io/projects/spring-boot[] + +The integration requires Spring Boot 3.x. + +== Configuration + +The configuration of the _StorageManager_ can be done using key/value pairs that are provided by Spring Boot external Configuration. The configuration keys must be prefixed by `org.eclipse.store` + +[source,properties] +---- +org.eclipse.store.storage-directory=/opt/data/eclipse-store-storage +org.eclipse.store.channel-count=2 +---- + +The list of all Eclipse Store configuration properties and their meaning are listed on our xref:storage:configuration/properties.adoc[documentation page]. + +The configuration values are handled using the https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config.typesafe-configuration-properties[typesafe configuration] approach, and you can read these values by accessing the `EclipseStoreProperties` Spring bean. + +== StorageManager injection + +The simplest way to use this integration is when you can externalize all the configuration using Spring configuration files. Subsequently, you just create a Spring Boot application and add a dependency on the integration. Then, in the Bean where you need access to the StorageManager, you add the @Autowired annotation and a StorageManager is created for you. All configuration values are loaded from the external configuration and the StorageManager is already initialized and ready to use. + +=== Example: +[source,java] +---- +@SpringBootApplication +@Import(EclipseStoreSpringBoot.class) +public class SomeSpringApplication +{ + public static void main(String... args) + { + SpringApplication.run(SomeSpringApplication.class, args); + } +} + +@Component +public class JokesStorageImpl implements JokesStorage +{ + private final EmbeddedStorageManager storageManager; + + // Inject the StorageManager (Constructor injection) + public JokesStorageImpl(EmbeddedStorageManager storageManager) + { + this.storageManager = storageManager; + } + + // Implement the JokesStorage interface +} +---- + +== Configuration Injection + +In case you need to modify the configuration in some way in the program, change something, add and the like, you can have the `EclipseStoreProperties` Spring bean injected into your class. This class contains all the configuration values that are used to create a `StorageManager`. You can modify these values and then use the `EclipseStoreProvider` Bean to create a new StorageManager or `EmbeddedStorageFoundation`. + +[source,java] +---- + @Bean + EmbeddedStorageManager injectStorageTest(@Autowired EclipseStoreProperties myConfiguration) + { + // Modify the configuration + myConfiguration.setStorageDirectory(temp.getDir().getAbsolutePath()); + // Create a new StorageFoundation + EmbeddedStorageFoundation storageFoundation = provider.createStorageFoundation(myConfiguration); + + // Modify the storageFoundation + //storageFoundation.onConnectionFoundation(f -> f.someOperation); + + // Create a new StorageManager + return storageFoundation.createEmbeddedStorageManager(); + } + +---- + +== Autostart +- The _StorageManager_ is already started unless you specified the configuration value `org.eclipse.store.auto-start=false`. +- If you have used the `org.eclipse.store.root` configuration item, the _StorageManager_ is already associated with an instance of that class as the Root object. This class must have a default or public no-argument constructor. + +It is also possible to obtain the entire configuration within the `StorageManagerConfiguration` Bean, enabling you to directly create a foundation and storage manager. This can be helpful if you need to stop storage at runtime and then restart it. + +== Multiple Storage Managers + +You can have a more than one Storage Manager in your application. This can be useful if you want to have different storage targets for different data. For example, you might want to have a datastore for your user data and another for your product data. You can do this by creating multiple configuration classes and multiple Storage Managers. + +[source,java] +---- +@Configuration +public class TwoBeanConfiguration +{ + + @Autowired + private EclipseStoreProvider provider; + + @Bean("first_config") + @ConfigurationProperties("org.eclipse.store.first") + EclipseStoreProperties firstStoreProperties() + { + return new EclipseStoreProperties(); + } + + @Bean("second_config") + @ConfigurationProperties("org.eclipse.store.second") + EclipseStoreProperties secondStoreProperties() + { + return new EclipseStoreProperties(); + } + + @Bean + @Lazy + @Qualifier("first_storage") + EmbeddedStorageManager createFirstStorage(@Qualifier("first_config") EclipseStoreProperties firstStoreProperties) + { + return provider.createStorage(firstStoreProperties); + } + + @Bean + @Lazy + @Qualifier("second_storage") + EmbeddedStorageManager createSecondStorage(@Qualifier("second_config") EclipseStoreProperties secondStoreProperties) + { + return provider.createStorage(secondStoreProperties); + } + +} +---- + +The configuration properties are defined in the `application.properties` file with appropriate prefixes. + +[source,properties] +---- +org.eclipse.store.first.storage-directory=${java.io.tmpdir}/${random.int} +org.eclipse.store.first.auto-start=false +org.eclipse.store.first.root=org.eclipse.store.integrations.spring.boot.types.storages.FirstRoot + +org.eclipse.store.second.storage-directory=${java.io.tmpdir}/${random.int} +org.eclipse.store.second.auto-start=false +org.eclipse.store.second.root=org.eclipse.store.integrations.spring.boot.types.storages.SecondRoot +---- + +== Mutext Locking +Eclipse store supports mutex locking. This is useful if you have multiple processes that need to access the same objects. Easiest way to use it is to use the annotation `@read` and `@write` on the methods that need to be locked. The annotation @read is used for methods that only read data and @write is used for methods that modify data. + +[source,java] +---- +@Component +public class SomeStorageImpl implements SomeStorage +{ + @Read + public String getSomethingById(Integer Id) + { + // Read something from the storage + } + + @Write + public void addSomething(String something) + { + // Add something to the storage + } +} +---- + +If you have larger object graph, you can consider to add more Mutexes and lock different parts of the object graph. This can be done by adding the `@Mutex` annotation to the class. The parameter of this annotation is the name of the mutex. If you have multiple classes with the same mutex name, they will be locked together. + +[source,java] +---- +@Component +@Mutex("jokes") +public class JokesStorageImpl implements JokesStorage +{ +} +---- + +== Logging + +Eclipse Store Spring module supports standard Spring logging, so you can add this into your config: +`logging.level.org.eclipse.store=debug` +to obtain all Eclipse Store configuration keys: + +[source, log] +---- +15:57:34.923 [main] DEBUG o.e.s.i.s.b.t.EclipseStoreProviderImpl -- EclipseStore configuration items: +15:57:34.923 [main] DEBUG o.e.s.i.s.b.t.EclipseStoreProviderImpl -- storage-directory : jokes_storage +15:57:34.923 [main] DEBUG o.e.s.i.s.b.t.EclipseStoreProviderImpl -- channel-count : 2 +15:57:34.923 [main] DEBUG o.e.s.i.s.b.t.EclipseStoreProviderImpl -- auto-start : true +---- + +Key values containing "password" are replaced by "xxxxx". diff --git a/examples/custom-legacy-type-handler/pom.xml b/examples/custom-legacy-type-handler/pom.xml index c7950c14..65018bd0 100644 --- a/examples/custom-legacy-type-handler/pom.xml +++ b/examples/custom-legacy-type-handler/pom.xml @@ -28,7 +28,7 @@ org.eclipse.serializer persistence-binary-jdk8 - 1.0.0-SNAPSHOT + ${eclipse.serializer.version} diff --git a/examples/custom-type-handler/pom.xml b/examples/custom-type-handler/pom.xml index f4f0ab9d..1bd42f04 100644 --- a/examples/custom-type-handler/pom.xml +++ b/examples/custom-type-handler/pom.xml @@ -28,7 +28,7 @@ org.eclipse.serializer persistence-binary-jdk8 - 1.0.0-SNAPSHOT + ${eclipse.serializer.version} diff --git a/examples/items/pom.xml b/examples/items/pom.xml index 168f9acd..63c1c5f7 100644 --- a/examples/items/pom.xml +++ b/examples/items/pom.xml @@ -28,7 +28,7 @@ org.eclipse.serializer persistence-binary-jdk8 - 1.0.0-SNAPSHOT + ${eclipse.serializer.version} info.picocli diff --git a/examples/layered-entities/pom.xml b/examples/layered-entities/pom.xml index 74a15309..98aff01f 100644 --- a/examples/layered-entities/pom.xml +++ b/examples/layered-entities/pom.xml @@ -24,12 +24,12 @@ org.eclipse.serializer base - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.serializer codegen-entity - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT diff --git a/examples/lazy-loading/pom.xml b/examples/lazy-loading/pom.xml index 72251a1c..5b2e8a01 100644 --- a/examples/lazy-loading/pom.xml +++ b/examples/lazy-loading/pom.xml @@ -28,7 +28,7 @@ org.eclipse.serializer persistence-binary-jdk8 - 1.0.0-SNAPSHOT + ${eclipse.serializer.version} diff --git a/examples/loading/pom.xml b/examples/loading/pom.xml index 795f23bc..ec137a19 100644 --- a/examples/loading/pom.xml +++ b/examples/loading/pom.xml @@ -28,7 +28,7 @@ org.eclipse.serializer persistence-binary-jdk8 - 1.0.0-SNAPSHOT + ${eclipse.serializer.version} diff --git a/examples/pom.xml b/examples/pom.xml index 25e517da..8f6367d2 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -13,13 +13,13 @@ ../pom.xml - examples-parent + examples-parent pom - + EclipseStore Examples Examples for EclipseStore https://projects.eclipse.org/projects/technology.store - + blobs custom-type-handler @@ -37,7 +37,7 @@ reloader storing - + @@ -57,11 +57,11 @@ - - - - - org.apache.maven.plugins + + + + + org.apache.maven.plugins maven-deploy-plugin true @@ -77,4 +77,16 @@ + + + + from_java_17 + + [17,) + + + spring-boot3-simple + + + diff --git a/examples/spring-boot3-simple/pom.xml b/examples/spring-boot3-simple/pom.xml new file mode 100644 index 00000000..cdeb7b00 --- /dev/null +++ b/examples/spring-boot3-simple/pom.xml @@ -0,0 +1,78 @@ + + + 4.0.0 + + org.eclipse.store + examples-parent + 1.1.0-SNAPSHOT + ../pom.xml + + + spring-boot3-simple + + + 17 + 17 + UTF-8 + 3.1.5 + + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-aop + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.eclipse.store + integrations-spring-boot3 + 1.1.0-SNAPSHOT + + + + + spring-boot3-simple + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + + + diff --git a/examples/spring-boot3-simple/readme.md b/examples/spring-boot3-simple/readme.md new file mode 100644 index 00000000..bbd8f018 --- /dev/null +++ b/examples/spring-boot3-simple/readme.md @@ -0,0 +1,53 @@ +# Spring Boot Eclipse Store Sample Application + +This application is aimed at showcasing the capabilities of the Eclipse Store Spring Boot extension. It demonstrates how to integrate a pre-configured storage into an application as a bean, how to utilize the locking API, and how to design an MVC application using Eclipse Store. + +## Implementation Notes +* Synchronization over shared data structures is handled using the annotations `@Read` and `@Write`. +* The Controller performs data conversion into JSON, therefore it must always operate with immutable data or, in the case of mutable data, it must receive a copy of such data. + +## Build + +The generation of the executable jar file can be performed by issuing the following command + +```shell +mvn clean package +``` + +This will create an executable jar file **spring-boot3-simple.jar** within the _target_ maven folder. This can be started by executing the following command + +```shell +java -jar target/spring-boot3-simple.jar +``` + +To launch the test page, open your browser at the following URL + +```shell +http://localhost:8080/ +``` + +## Using App rest api +Load sample data +```shell +curl --location --request POST 'http://localhost:8080/init' \ +--header 'Content-Type: application/json' +``` + +Get all jokes +```shell +curl --location --request GET 'http://localhost:8080' \ +--header 'Content-Type: application/json' +``` + +Get joke by Id +```shell +curl --location --request GET 'http://localhost:8080/joke?id=50' \ +--header 'Content-Type: application/json' +``` + +Add new Joke +```shell +curl --location --request POST 'http://localhost:8080/add' \ +--header 'Content-Type: application/json' \ +--data-raw '{great new joke}' +``` diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/JokesApplication.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/JokesApplication.java new file mode 100644 index 00000000..4b7a6868 --- /dev/null +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/JokesApplication.java @@ -0,0 +1,41 @@ +package org.microstream.spring.boot.example; + +/*- + * #%L + * spring-boot3-simple + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.integrations.spring.boot.types.EclipseStoreSpringBoot; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Import; + +/** + * The {@code EclipseStoreProperties} class holds the configuration properties for the Eclipse Store. + * These properties are loaded from the application's configuration files and can be used to configure the Eclipse Store. + * + *

This class is annotated with {@code @Configuration}, {@code @Primary}, and {@code @ConfigurationProperties}, + * which means it is a Spring configuration class, it is the primary bean of its type, + * and its properties are bound to the "org.eclipse.store" prefix in the configuration files.

+ * + *

Each property in this class corresponds to a configuration option for the Eclipse Store. + * The properties are loaded from the configuration files when the application starts.

+ */ +@SpringBootApplication +@Import(EclipseStoreSpringBoot.class) +public class JokesApplication +{ + public static void main(String... args) + { + SpringApplication.run(JokesApplication.class, args); + } +} diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/controller/JokesController.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/controller/JokesController.java new file mode 100644 index 00000000..a2f9e8e7 --- /dev/null +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/controller/JokesController.java @@ -0,0 +1,115 @@ +package org.microstream.spring.boot.example.controller; + +/*- + * #%L + * spring-boot3-simple + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.microstream.spring.boot.example.service.JokesServices; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * The {@code JokesController} class is a Spring REST controller that provides endpoints for managing jokes. + * It uses the {@code JokesServices} to perform operations on jokes. + * + *

This class is annotated with {@code @RestController}, which means it is a Spring MVC controller and its methods return domain objects instead of views.

+ * + *

Here's an example of how to use this controller:

+ *
+ * 
+ * GET /joke?id=1
+ * POST /add
+ * {
+ *     "joke": "Why don't scientists trust atoms? Because they make up everything!"
+ * }
+ * 
+ * 
+ * + * In this example, the first request gets the joke with ID 1 and the second request adds a new joke. + */ +@RestController +public class JokesController +{ + + private final JokesServices jokesServices; + + /** + * Constructs a new {@code JokesController} with the provided {@code JokesServices}. + * + * @param jokesServices The services used to perform operations on jokes. + */ + public JokesController(JokesServices jokesServices) + { + this.jokesServices = jokesServices; + } + + /** + * Returns all jokes. + * + * @return A list of all jokes. + */ + @GetMapping + public List getAll() + { + return jokesServices.allJokes(); + } + + /** + * Returns the joke with the specified ID. + * + * @param id The ID of the joke. + * @return The joke with the specified ID. + */ + @GetMapping("/joke") + public String getOneJoke(@RequestParam(required = false) Integer id) + { + return jokesServices.oneJoke(id); + } + + /** + * Adds a new joke. + * + * @param joke The joke to add. + * @return The ID of the added joke. + */ + @PostMapping("/add") + public Integer putOne(@RequestBody String joke) + { + return jokesServices.addNewJoke(joke); + } + + /** + * Loads predefined jokes. + */ + @PostMapping("/init") + public void init() + { + jokesServices.loadPredefinedJokes(); + } + + /** + * Inserts a new joke. + * This method functions similarly to the 'putOne' method. However, it differs in its implementation by utilizing a nested locking mechanism. + * The '@Write Lock' annotation is applied at the service layer, invoking the storage layer within another locking annotation. + * This implementation is solely intended for demonstration purposes. + * + * @param joke The new joke to be added. + * @return The position of the currently inserted joke in storage. + */ + @PostMapping("/insert") + public Integer insert(@RequestBody String joke) + { + return jokesServices.insertNewJoke(joke); + } +} diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/model/Root.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/model/Root.java new file mode 100644 index 00000000..78f2273b --- /dev/null +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/model/Root.java @@ -0,0 +1,33 @@ +package org.microstream.spring.boot.example.model; + +/*- + * #%L + * spring-boot3-simple + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.ArrayList; +import java.util.List; + +public class Root +{ + private List jokes = new ArrayList<>(); + + public List getJokes() + { + return jokes; + } + + public void setJokes(List jokes) + { + this.jokes = jokes; + } +} diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServices.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServices.java new file mode 100644 index 00000000..5324db0e --- /dev/null +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServices.java @@ -0,0 +1,71 @@ +package org.microstream.spring.boot.example.service; + +/*- + * #%L + * spring-boot3-simple + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.List; + +/** + * The {@code JokesServices} interface provides methods for managing jokes in the application. + * It is used as a part of the joke service in the application. + * + *

Here's an example of how to use this interface:

+ *
+ * 
+ * JokesServices jokesServices = ... // get an instance of JokesServices
+ * jokesServices.addNewJoke("Why don't scientists trust atoms? Because they make up everything!");
+ * List allJokes = jokesServices.allJokes();
+ * 
+ * 
+ * + * In this example, a new joke is added to the service and then all jokes are retrieved. + */ +public interface JokesServices +{ + /** + * Returns a joke with the specified ID. + * + * @param id The ID of the joke. + * @return The joke with the specified ID. + */ + String oneJoke(Integer id); + + /** + * Returns all jokes. + * + * @return A list of all jokes. + */ + List allJokes(); + + /** + * Adds a new joke. + * + * @param joke The joke to add. + * @return The ID of the added joke. + */ + Integer addNewJoke(String joke); + + /** + * Loads predefined jokes. + */ + void loadPredefinedJokes(); + + /** + * Inserts a new joke. + * + * @param joke The joke to insert. + * @return The ID of the inserted joke. + */ + Integer insertNewJoke(String joke); +} diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServicesImpl.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServicesImpl.java new file mode 100644 index 00000000..eafbd5a6 --- /dev/null +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServicesImpl.java @@ -0,0 +1,85 @@ +package org.microstream.spring.boot.example.service; + +/*- + * #%L + * spring-boot3-simple + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.integrations.spring.boot.types.concurent.Write; +import org.microstream.spring.boot.example.storage.JokesStorage; +import org.springframework.stereotype.Service; +import org.springframework.util.ResourceUtils; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +@Service +public class JokesServicesImpl implements JokesServices +{ + private final JokesStorage jokesStorage; + + + @Override + public String oneJoke(Integer id) + { + String joke; + joke = jokesStorage.oneJoke(Objects.requireNonNullElse(id, 0)); + return joke; + } + + public JokesServicesImpl(JokesStorage jokesStorage) + { + this.jokesStorage = jokesStorage; + } + + @Override + public List allJokes() + { + return jokesStorage.allJokes(); + } + + @Override + public Integer addNewJoke(String joke) + { + return jokesStorage.addNewJoke(joke); + } + + @Override + public void loadPredefinedJokes() + { + List jokes = null; + InputStream inputStream = getClass().getClassLoader().getResourceAsStream("jokes.txt"); + assert inputStream != null; + jokes = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)) + .lines() + .collect(Collectors.toList()); + List existingJokes = jokesStorage.allJokes(); + if (existingJokes.containsAll(jokes)) + { + return; + } + jokesStorage.addJokes(jokes); + } + + @Override + @Write + public Integer insertNewJoke(String joke) + { + List jokes = jokesStorage.allJokes(); + jokes.add(joke); + return jokesStorage.saveAllJokes(jokes); + } +} diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorage.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorage.java new file mode 100644 index 00000000..dcc0b792 --- /dev/null +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorage.java @@ -0,0 +1,73 @@ +package org.microstream.spring.boot.example.storage; + +/*- + * #%L + * spring-boot3-simple + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.List; + +/** + * The {@code JokesStorage} interface provides methods for storing and retrieving jokes. + * It is used as a part of the joke service in the application. + * + *

Here's an example of how to use this interface:

+ *
+ * 
+ * JokesStorage jokesStorage = ... // get an instance of JokesStorage
+ * jokesStorage.addNewJoke("Why don't scientists trust atoms? Because they make up everything!");
+ * List allJokes = jokesStorage.allJokes();
+ * 
+ * 
+ * + * In this example, a new joke is added to the storage and then all jokes are retrieved. + */ +public interface JokesStorage +{ + /** + * Returns a joke with the specified ID. + * + * @param id The ID of the joke. + * @return The joke with the specified ID. + */ + String oneJoke(Integer id); + + /** + * Returns all jokes in the storage. + * + * @return A list of all jokes. + */ + List allJokes(); + + /** + * Adds a new joke to the storage. + * + * @param joke The joke to add. + * @return The ID of the added joke. + */ + Integer addNewJoke(String joke); + + /** + * Adds multiple jokes to the storage. + * + * @param jokes The jokes to add. + */ + void addJokes(List jokes); + + /** + * Saves all jokes to the storage. + * + * @param jokes The jokes to save. + * @return The number of jokes saved. + */ + Integer saveAllJokes(List jokes); +} diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorageImpl.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorageImpl.java new file mode 100644 index 00000000..d6477a7d --- /dev/null +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorageImpl.java @@ -0,0 +1,92 @@ +package org.microstream.spring.boot.example.storage; + +/*- + * #%L + * spring-boot3-simple + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.persistence.types.Storer; +import org.eclipse.store.integrations.spring.boot.types.concurent.Mutex; +import org.eclipse.store.integrations.spring.boot.types.concurent.Read; +import org.eclipse.store.integrations.spring.boot.types.concurent.Write; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.microstream.spring.boot.example.model.Root; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + + +@Component +public class JokesStorageImpl implements JokesStorage +{ + private final EmbeddedStorageManager storageManager; + + public JokesStorageImpl(EmbeddedStorageManager storageManager) + { + this.storageManager = storageManager; + } + + + @Override + @Read + public String oneJoke(Integer id) + { + String joke; + Root root = (Root) storageManager.root(); + if (id > root.getJokes().size()) + { + throw new IllegalArgumentException("No jokes with this id"); + } + joke = root.getJokes().get(id); + return joke; + } + + @Override + @Read + public List allJokes() + { + Root root = (Root) storageManager.root(); + return new ArrayList<>(root.getJokes()); // Create new List... never return original one. + } + + @Override + @Write + public Integer addNewJoke(String joke) + { + Root root = (Root) storageManager.root(); + root.getJokes().add(joke); + storageManager.storeRoot(); + return root.getJokes().size(); + } + + @Override + @Write + public void addJokes(List jokes) + { + Root root = (Root) storageManager.root(); + root.getJokes().addAll(jokes); + storageManager.store(root.getJokes()); + } + + @Override + @Write + public Integer saveAllJokes(List jokes) + { + Root root = (Root) storageManager.root(); + root.setJokes(jokes); + Storer eagerStorer = storageManager.createEagerStorer(); + eagerStorer.store(root); + eagerStorer.commit(); + return root.getJokes().size(); + } +} diff --git a/examples/spring-boot3-simple/src/main/resources/META-INF/MANIFEST.MF b/examples/spring-boot3-simple/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 00000000..9d885be5 --- /dev/null +++ b/examples/spring-boot3-simple/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1 @@ +Manifest-Version: 1.0 diff --git a/examples/spring-boot3-simple/src/main/resources/application.properties b/examples/spring-boot3-simple/src/main/resources/application.properties new file mode 100644 index 00000000..7f30485c --- /dev/null +++ b/examples/spring-boot3-simple/src/main/resources/application.properties @@ -0,0 +1,3 @@ +org.eclipse.store.auto-start=true +org.eclipse.store.root=org.microstream.spring.boot.example.model.Root +org.eclipse.store.storage-directory=jokes_storage diff --git a/examples/spring-boot3-simple/src/main/resources/jokes.txt b/examples/spring-boot3-simple/src/main/resources/jokes.txt new file mode 100644 index 00000000..5060ab40 --- /dev/null +++ b/examples/spring-boot3-simple/src/main/resources/jokes.txt @@ -0,0 +1,250 @@ +What did one pirate say to the other when he beat him at chess?<>Checkmatey. +I burned 2000 calories today<>I left my food in the oven for too long. +I startled my next-door neighbor with my new electric power tool. <>I had to calm him down by saying “Don’t worry, this is just a drill!” +I broke my arm in two places. <>My doctor told me to stop going to those places. +I quit my job at the coffee shop the other day. <>It was just the same old grind over and over. +I never buy anything that has Velcro with it...<>it’s a total rip-off. +I used to work at a soft drink can crushing company...<>it was soda pressing. +I wondered why the frisbee kept on getting bigger. <>Then it hit me. +I was going to tell you a fighting joke...<>but I forgot the punch line. +What is the most groundbreaking invention of all time? <>The shovel. +I’m starting my new job at a restaurant next week. <>I can’t wait. +I visited a weight loss website...<>they told me I have to have cookies disabled. +Did you hear about the famous Italian chef that recently died? <>He pasta way. +Broken guitar for sale<>no strings attached. +I could never be a plumber<>it’s too hard watching your life’s work go down the drain. +I cut my finger slicing cheese the other day...<>but I think I may have grater problems than that. +What time did you go to the dentist yesterday?<>Tooth-hurty. +What kind of music do astronauts listen to?<>Neptunes. +Rest in peace, boiled water. <>You will be mist. +What is the only concert in the world that costs 45 cents? <>50 Cent, featuring Nickelback. +It’s not a dad bod<> it’s a father figure. +My wife recently went on a tropical food diet and now our house is full of this stuff. <>It’s enough to make a mango crazy. +What do you call Santa’s little helpers? <>Subordinate clauses. +Want to hear a construction joke? <>Sorry, I’m still working on it. +What’s the difference between a hippo and a zippo? <>One is extremely big and heavy, and the other is a little lighter. +I burnt my Hawaiian pizza today in the oven, <>I should have cooked it on aloha temperature. +Anyone can be buried when they die<>but if you want to be cremated then you have to urn it. +Where did Captain Hook get his hook? <>From the second-hand store. +I am such a good singer that people always ask me to sing solo<>solo that they can’t hear me. +I am such a good singer that people ask me to sing tenor<>tenor twelve miles away. +Occasionally to relax I just like to tuck my knees into my chest and lean forward.<> That’s just how I roll. +What did the glass of wine say to the glass of beer? Nothing. <>They barley knew each other. +I’ve never trusted stairs. <>They are always up to something. +Why did Shakespeare’s wife leave him? <>She got sick of all the drama. +I just bought a dictionary but all of the pages are blank. <>I have no words to describe how mad I am. +If you want to get a job at the moisturizer factory... <>you’re going to have to apply daily. +I don’t know what’s going to happen next year. <>It’s probably because I don’t have 2020 vision. +Want to hear a joke about going to the bathroom? <>Urine for a treat. +I couldn’t figure out how to use the seat belt. <>Then it just clicked. +I got an email the other day teaching me how to read maps backwards<>turns out it was just spam. +I'm reading a book about anti-gravity.<> It's impossible to put down! +You're American when you go into the bathroom, and you're American when you come out, but do you know what you are while you're in there?<> European. +Did you know the first French fries weren't actually cooked in France?<> They were cooked in Greece. +Want to hear a joke about a piece of paper? Never mind... <>it's tearable. +I just watched a documentary about beavers. <>It was the best dam show I ever saw! +If you see a robbery at an Apple Store what re you?<> An iWitness? +Spring is here! <>I got so excited I wet my plants! +What’s Forrest Gump’s password?<> 1forrest1 +Why did the Clydesdale give the pony a glass of water? <>Because he was a little horse! +CASHIER: "Would you like the milk in a bag, sir?" <>DAD: "No, just leave it in the carton!’” +Did you hear about the guy who invented Lifesavers? <>They say he made a mint. +I bought some shoes from a drug dealer.<> I don't know what he laced them with, but I was tripping all day! +Why do chicken coops only have two doors?<> Because if they had four, they would be chicken sedans! +How do you make a Kleenex dance? <>Put a little boogie in it! +A termite walks into a bar and asks<>"Is the bar tender here?" +Why did the invisible man turn down the job offer?<> He couldn't see himself doing it. +I used to have a job at a calendar factory <>but I got the sack because I took a couple of days off. +A woman is on trial for beating her husband to death with his guitar collection. Judge says, "First offender?" <>She says, "No, first a Gibson! Then a Fender!” +How do you make holy water?<> You boil the hell out of it. +I had a dream that I was a muffler last night.<> I woke up exhausted! +Did you hear about the circus fire?<> It was in tents! +Don't trust atoms.<> They make up everything! +How many tickles does it take to make an octopus laugh? <>Ten-tickles. +I’m only familiar with 25 letters in the English language.<> I don’t know why. +Why did the cow in the pasture get promoted at work?<> Because he is OUT-STANDING in his field! +What do prisoners use to call each other?<> Cell phones. +Why couldn't the bike standup by itself? <>It was two tired. +Who was the fattest knight at King Arthur’s round table?<> Sir Cumference. +Did you see they made round bails of hay illegal in Wisconsin? <>It’s because the cows weren’t getting a square meal. +You know what the loudest pet you can get is?<> A trumpet. +What do you get when you cross a snowman with a vampire?<> Frostbite. +What do you call a deer with no eyes?<> No idea! +Can February March? <>No, but April May! +What do you call a lonely cheese? <>Provolone. +Why can't you hear a pterodactyl go to the bathroom?<> Because the pee is silent. +What did the buffalo say to his son when he dropped him off at school?<> Bison. +What do you call someone with no body and no nose? <>Nobody knows. +You heard of that new band 1023MB? <>They're good but they haven't got a gig yet. +Why did the crab never share?<> Because he's shellfish. +How do you get a squirrel to like you? <>Act like a nut. +Why don't eggs tell jokes? <>They'd crack each other up. +Why can't a nose be 12 inches long? <>Because then it would be a foot. +Did you hear the rumor about butter? <>Well, I'm not going to spread it! +I made a pencil with two erasers. <>It was pointless. +I used to hate facial hair...<>but then it grew on me. +I decided to sell my vacuum cleaner—<>it was just gathering dust! +I had a neck brace fitted years ago<> and I've never looked back since. +You know, people say they pick their nose,<> but I feel like I was just born with mine. +What do you call an elephant that doesn't matter?<> An irrelephant. +What do you get from a pampered cow? <>Spoiled milk. +It's inappropriate to make a 'dad joke' if you're not a dad.<> It's a faux pa. +How do lawyers say goodbye? <>Sue ya later! +Wanna hear a joke about paper? <>Never mind—it's tearable. +What's the best way to watch a fly fishing tournament? <>Live stream. +I could tell a joke about pizza,<> but it's a little cheesy. +When does a joke become a dad joke?<> When it becomes apparent. +What’s an astronaut’s favorite part of a computer? <>The space bar. +What did the shy pebble wish for?<>That she was a little boulder. +I'm tired of following my dreams. <>I'm just going to ask them where they are going and meet up with them later. +Did you hear about the guy whose whole left side was cut off? <>He's all right now. +Why didn’t the skeleton cross the road? <>Because he had no guts. +What did one nut say as he chased another nut? <> I'm a cashew! +Chances are if you' ve seen one shopping center...<> you've seen a mall. +I knew I shouldn't steal a mixer from work...<>but it was a whisk I was willing to take. +How come the stadium got hot after the game? <>Because all of the fans left. +Why was it called the dark ages? <>Because of all the knights. +Why did the tomato blush? <>Because it saw the salad dressing. +Did you hear the joke about the wandering nun? <>She was a roman catholic. +What creature is smarter than a talking parrot? <>A spelling bee. +I'll tell you what often gets over looked...<> garden fences. +Why did the kid cross the playground? <>To get to the other slide. +Why do birds fly south for the winter?<> Because it's too far to walk. +What is a centipedes's favorite Beatle song? <> I want to hold your hand, hand, hand, hand... +My first time using an elevator was an uplifting experience. <>The second time let me down. +To be Frank...<> I'd have to change my name. +Slept like a log last night … <>woke up in the fireplace. +Why does a Moon-rock taste better than an Earth-rock? <>Because it's a little meteor. +How many South Americans does it take to change a lightbulb?<> A Brazilian +I don't trust stairs.<> They're always up to something. +A police officer caught two kids playing with a firework and a car battery.<> He charged one and let the other one off. +What is the difference between ignorance and apathy?<>I don't know and I don't care. +I went to a Foo Fighters Concert once... <>It was Everlong... +Some people eat light bulbs. <>They say it's a nice light snack. +What do you get hanging from Apple trees? <> Sore arms. +Last night me and my girlfriend watched three DVDs back to back.<> Luckily I was the one facing the TV. +I got a reversible jacket for Christmas,<> I can't wait to see how it turns out. +What did Romans use to cut pizza before the rolling cutter was invented? <>Lil Caesars +My pet mouse 'Elvis' died last night. <>He was caught in a trap.. +Never take advice from electrons. <>They are always negative. +Why are oranges the smartest fruit? <>Because they are made to concentrate. +What did the beaver say to the tree? <>It's been nice gnawing you. +How do you fix a damaged jack-o-lantern?<> You use a pumpkin patch. +What did the late tomato say to the early tomato? <>I’ll ketch up +I have kleptomania...<>when it gets bad, I take something for it. +I used to be addicted to soap...<> but I'm clean now. +When is a door not a door?<> When it's ajar. +I made a belt out of watches once...<> It was a waist of time. +This furniture store keeps emailing me,<> all I wanted was one night stand! +How do you find Will Smith in the snow?<> Look for fresh prints. +I just read a book about Stockholm syndrome.<> It was pretty bad at first, but by the end I liked it. +Why do trees seem suspicious on sunny days? <>Dunno, they're just a bit shady. +If at first you don't succeed<> sky diving is not for you! +What kind of music do mummy's like?<>Rap +A book just fell on my head. <>I only have my shelf to blame. +What did the dog say to the two trees? <>Bark bark. +If a child refuses to sleep during nap time...<> are they guilty of resisting a rest? +Have you ever heard of a music group called Cellophane?<> They mostly wrap. +What did the mountain climber name his son?<>Cliff. +Why should you never trust a pig with a secret?<> Because it's bound to squeal. +Why are mummys scared of vacation?<> They're afraid to unwind. +Whiteboards ...<> are remarkable. +What kind of dinosaur loves to sleep?<>A stega-snore-us. +What kind of tree fits in your hand?<> A palm tree! +I used to be addicted to the hokey pokey<> but I turned myself around. +How many tickles does it take to tickle an octopus?<> Ten-tickles! +What musical instrument is found in the bathroom?<> A tuba toothpaste. +My boss told me to attach two pieces of wood together... <>I totally nailed it! +What was the pumpkin’s favorite sport?<>Squash. +What do you call corn that joins the army?<> Kernel. +I've been trying to come up with a dad joke about momentum <>but I just can't seem to get it going. +Why don't sharks eat clowns? <> Because they taste funny. +Just read a few facts about frogs.<> They were ribbiting. +Why didn’t the melons get married?<>Because they cantaloupe. +What’s a computer’s favorite snack?<>Microchips! +Why was the robot so tired after his road trip?<>He had a hard drive. +Why did the computer have no money left?<>Someone cleaned out its cache! +I'm not anti-social. <>I'm just not user friendly. +Why did the computer get cold?<>Because it forgot to close windows. +What is an astronaut's favorite key on a keyboard?<>The space bar! +What's the difference between a computer salesman and a used-car salesman?<>The used-car salesman KNOWS when he's lying. +If at first you don't succeed...<> call it version 1.0 +Why did Microsoft PowerPoint cross the road?<>To get to the other slide! +What did the computer do at lunchtime?<>Had a byte! +Why did the computer keep sneezing?<>It had a virus! +What did one toilet say to the other?<>You look a bit flushed. +Why did the picture go to jail?<>Because it was framed. +What did one wall say to the other wall?<>I'll meet you at the corner. +What do you call a boy named Lee that no one talks to?<>Lonely +Why do bicycles fall over?<>Because they are two-tired! +Why was the broom late?<>It over swept! +What part of the car is the laziest?<>The wheels, because they are always tired! +What's the difference between a TV and a newspaper?<>Ever tried swatting a fly with a TV? +What did one elevator say to the other elevator?<>I think I'm coming down with something! +Why was the belt arrested?<>Because it held up some pants! +What makes the calendar seem so popular?<>Because it has a lot of dates! +Why did Mickey Mouse take a trip into space?He wanted to find Pluto! +Why do you go to bed every night?<>Because the bed won't come to you! +What has four wheels and flies?<>A garbage truck! +Why did the robber take a bath before he stole from the bank?<>He wanted to make a clean get away! +Just watched a documentary about beavers.<>It was the best damn program I’ve ever seen. +Slept like a log last night<>woke up in the fireplace. +Why did the scarecrow win an award?<>Because he was outstanding in his field. +Why does a chicken coop only have two doors? <>Because if it had four doors it would be a chicken sedan. +What’s the difference between an African elephant and an Indian elephant? <>About 5000 miles +Why did the coffee file a police report? <>It got mugged. +What did the grape do when he got stepped on? <>He let out a little wine. +How many apples grow on a tree? <>All of them. +What name do you give a person with a rubber toe? <>Roberto +Did you hear about the kidnapping at school? <>It’s fine, he woke up. +Why do scuba divers fall backwards into the water? <>Because if they fell forwards they’d still be in the boat. +How does a penguin build it’s house? <>Igloos it together. +What do you call a man with a rubber toe?<>Roberto +Did you hear about the restaurant on the moon?<>Great food, no atmosphere. +Why was the belt sent to jail?<>For holding up a pair of pants! +Did you hear about the scientist who was lab partners with a pot of boiling water?<>He had a very esteemed colleague. +What happens when a frogs car dies?<>He needs a jump. If that doesn't work he has to get it toad. +What did the flowers do when the bride walked down the aisle?<>They rose. +Why did the man fall down the well?<>Because he couldn’t see that well. +My boss told me to have a good day...<>...so I went home. +How can you tell it’s a dogwood tree?<>By the bark. +Did you hear about the kidnapping at school?<>It’s fine, he woke up. +Why is Peter Pan always flying?<>Because he Neverlands. +Which state has the most streets?<>Rhode Island. +What do you call 26 letters that went for a swim?<>Alphawetical. +Why was the color green notoriously single?<>It was always so jaded. +Why did the coach go to the bank?<>To get his quarterback. +How do celebrities stay cool?<>They have many fans. +What's the most depressing day of the week?<>sadder day. +Dogs can’t operate MRI machines<>But catscan. +I was going to tell a time-traveling joke<>but you guys didn’t like it. +Stop looking for the perfect match<>instead look for a lighter. +I told my doctor I heard buzzing<>but he said it’s just a bug going around. +What kind of car does a sheep like to drive?<>A lamborghini. +What did the accountant say while auditing a document?<>This is taxing. +What did the two pieces of bread say on their wedding day?<>It was loaf at first sight. +Why do melons have weddings?<>Because they cantaloupe. +What did the drummer call his twin daughters?<>Anna One, Anna Two! +What do you call a toothless bear?<> A gummy bear! +Two goldfish are in a tank. <>One says to the other, “Do you know how to drive this thing?” +What’s Forrest Gump’s password?<>1forrest1 +What is a child guilty of if they refuse to nap?<> Resisting a rest. +I know a lot of jokes about retired people<>but none of them work. +Why are spiders so smart?<>They can find everything on the web. +What has one head, one foot, and four legs?<> A bed. +What does a house wear?<> Address. +What’s red and smells like blue paint?<>Red paint. +My son asked me to put his shoes on<> but I don’t think they’ll fit me. +I’ve been bored recently, so I decided to take up fencing.<> The neighbors keep demanding that I put it back. +What do you call an unpredictable camera?<>A loose Canon. +Which U.S. state is known for its especially small soft drinks?<>Minnesota. +What do sprinters eat before a race?<> Nothing—they fast. +I’m so good at sleeping...<>I can do it with my eyes closed. +People are usually shocked that I have a Police record.<>But I love their greatest hits! +I told my girlfriend she drew on her eyebrows too high.<> She seemed surprised. +What do you call a fibbing cat?<> A lion. +Why shouldn’t you write with a broken pencil?<> Because it’s pointless. +I like telling Dad jokes…<>sometimes he laughs. +How do you weigh a millennial?<> In Instagrams. +The wedding was so beautiful<>even the cake was in tiers. +What’s the most patriotic sport?<> Flag football. diff --git a/examples/spring-boot3-simple/src/main/resources/logback.xml b/examples/spring-boot3-simple/src/main/resources/logback.xml new file mode 100644 index 00000000..37599769 --- /dev/null +++ b/examples/spring-boot3-simple/src/main/resources/logback.xml @@ -0,0 +1,16 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n + + + + + + + + + diff --git a/examples/storing/pom.xml b/examples/storing/pom.xml index fdf522b7..28e28cbd 100644 --- a/examples/storing/pom.xml +++ b/examples/storing/pom.xml @@ -29,7 +29,7 @@ org.eclipse.serializer persistence-binary-jdk8 - 1.0.0-SNAPSHOT + ${eclipse.serializer.version} diff --git a/integrations/pom.xml b/integrations/pom.xml new file mode 100644 index 00000000..4da41d10 --- /dev/null +++ b/integrations/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + org.eclipse.store + store-parent + 1.1.0-SNAPSHOT + + + org.example + integrations + + pom + + + + 11 + 11 + UTF-8 + + + + + from_java_17 + + [17,) + + + spring-boot3 + + + + + diff --git a/integrations/spring-boot3/pom.xml b/integrations/spring-boot3/pom.xml new file mode 100644 index 00000000..4c79d980 --- /dev/null +++ b/integrations/spring-boot3/pom.xml @@ -0,0 +1,117 @@ + + + 4.0.0 + + org.eclipse.store + store-parent + 1.1.0-SNAPSHOT + ../../pom.xml + + + integrattions-spring-boot3 + + + 17 + 17 + UTF-8 + 3.1.5 + + + + + org.springframework.boot + spring-boot + ${org.springframework.boot.version} + provided + + + + org.springframework.boot + spring-boot-autoconfigure + ${org.springframework.boot.version} + provided + + + + org.springframework.boot + spring-boot-configuration-processor + ${org.springframework.boot.version} + provided + true + + + + org.springframework.boot + spring-boot-starter-aop + ${org.springframework.boot.version} + provided + + + + org.springframework.boot + spring-boot-starter-test + ${org.springframework.boot.version} + test + + + + org.eclipse.store + storage-embedded + 1.1.0-SNAPSHOT + + + + org.eclipse.serializer + persistence-binary-jdk17 + ${eclipse.serializer.version} + + + + org.eclipse.store + storage-embedded-configuration + 1.1.0-SNAPSHOT + + + + org.junit.jupiter + junit-jupiter-engine + 5.10.0 + test + + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + + + enforce-files-exist + + enforce + + package + + + + File: '/target/classes/META-INF/spring-configuration-metadata.json' is not present + + + ${project.basedir}/target/classes/META-INF/spring-configuration-metadata.json + + + + + true + + + + + + + + diff --git a/integrations/spring-boot3/src/main/java/module-info.java b/integrations/spring-boot3/src/main/java/module-info.java new file mode 100644 index 00000000..a5777e35 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/module-info.java @@ -0,0 +1,39 @@ +/*- + * #%L + * microstream-integrations-spring-boot3 + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +open module org.eclipse.store.integrations.spring.boot +{ + exports org.eclipse.store.integrations.spring.boot.types.configuration; + exports org.eclipse.store.integrations.spring.boot.types.configuration.aws; + exports org.eclipse.store.integrations.spring.boot.types.configuration.azure; + exports org.eclipse.store.integrations.spring.boot.types.configuration.googlecloud; + exports org.eclipse.store.integrations.spring.boot.types.configuration.googlecloud.firestore; + exports org.eclipse.store.integrations.spring.boot.types.configuration.oraclecloud; + exports org.eclipse.store.integrations.spring.boot.types.configuration.redis; + exports org.eclipse.store.integrations.spring.boot.types.configuration.sql; + exports org.eclipse.store.integrations.spring.boot.types; + exports org.eclipse.store.integrations.spring.boot.types.converter; + exports org.eclipse.store.integrations.spring.boot.types.concurent; + + requires transitive spring.beans; + requires transitive spring.boot; + requires transitive spring.boot.autoconfigure; + requires transitive spring.context; + requires transitive spring.core; + requires transitive org.eclipse.store.storage.embedded.configuration; + requires transitive org.eclipse.serializer.configuration; + requires transitive org.aspectj.weaver; + requires transitive org.eclipse.serializer.persistence.binary.jdk17; + + +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreBeanFactory.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreBeanFactory.java new file mode 100644 index 00000000..8827ec4d --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreBeanFactory.java @@ -0,0 +1,63 @@ +package org.eclipse.store.integrations.spring.boot.types; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Lazy; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; + +/** + * The {@code EclipseStoreBeanFactory} class is a Spring component that provides a factory for creating {@code EmbeddedStorageManager} beans. + * It uses the {@code EclipseStoreProvider} and {@code EclipseStoreProperties} to create the {@code EmbeddedStorageManager}. + */ +@Component +@Lazy +public class EclipseStoreBeanFactory +{ + private final EclipseStoreProvider eclipseStoreProvider; + private final EclipseStoreProperties eclipseStoreProperties; + + /** + * Constructs a new {@code EclipseStoreBeanFactory} with the provided {@code EclipseStoreProvider} and {@code EclipseStoreProperties}. + * + * @param eclipseStoreProvider The provider used to create {@code EmbeddedStorageManager} instances. + * @param eclipseStoreProperties The properties used to configure the {@code EmbeddedStorageManager}. + */ + public EclipseStoreBeanFactory(EclipseStoreProvider eclipseStoreProvider, EclipseStoreProperties eclipseStoreProperties) + { + this.eclipseStoreProvider = eclipseStoreProvider; + this.eclipseStoreProperties = eclipseStoreProperties; + } + + + /** + * Creates a new {@code EmbeddedStorageManager} bean using the {@code EclipseStoreProvider} and {@code EclipseStoreProperties}. + * This bean is marked as primary and lazy, meaning it will be the default choice for autowiring and will only be initialized on demand. + * + * @return A new {@code EmbeddedStorageManager} instance. + */ + @Bean + @Primary + @Lazy + public EmbeddedStorageManager embeddedStorageManager() + { + return eclipseStoreProvider.createStorage(eclipseStoreProperties); + } + + +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProvider.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProvider.java new file mode 100644 index 00000000..47eed6fb --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProvider.java @@ -0,0 +1,57 @@ +package org.eclipse.store.integrations.spring.boot.types; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.integrations.spring.boot.types.configuration.ConfigurationPair; +import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + +/** + * The {@code EclipseStoreProvider} interface is responsible for the creation of the EmbeddedStorageManager and EmbeddedStorageFoundation instances. + * It provides methods for creating the EmbeddedStorageManager and EmbeddedStorageFoundation instances based on the provided configuration. + */ +public interface EclipseStoreProvider +{ + /** + * Creates an {@code EmbeddedStorageManager} using the provided configuration. + * + * @param eclipseStoreProperties Configuration file structure representing configuration elements mapped by Spring Configuration. + * @param additionalConfiguration Optional additional parameters that allow the inclusion of configuration keys not present in {@code EclipseStoreProperties}. + * @return A new {@code EmbeddedStorageManager} instance based on the provided configuration. + */ + EmbeddedStorageManager createStorage(EclipseStoreProperties eclipseStoreProperties, ConfigurationPair... additionalConfiguration); + + /** + * Creates an {@code EmbeddedStorageManager} using a pre-configured foundation. This method is beneficial when additional configuration for the foundation is required. + * + * @param foundation The {@code EmbeddedStorageFoundation} to be configured before calling this method. + * @param autoStart Determines whether the newly created {@code EmbeddedStorageManager} should start directly after creation. + * @return A new {@code EmbeddedStorageManager} instance based on the provided {@code EmbeddedStorageFoundation}. + */ + EmbeddedStorageManager createStorage(EmbeddedStorageFoundation foundation, boolean autoStart); + + + /** + * Creates an {@code EmbeddedStorageFoundation} using the provided configuration. This method should be called when the additional configuration for the foundation is required. + * + * @param eclipseStoreProperties Configuration file structure representing configuration elements mapped by Spring Configuration. + * @param additionalConfiguration Optional additional parameters that allow the inclusion of configuration keys not present in {@code EclipseStoreProperties}. + * @return A new {@code EmbeddedStorageFoundation} instance based on the provided configuration. + */ + EmbeddedStorageFoundation createStorageFoundation(EclipseStoreProperties eclipseStoreProperties, ConfigurationPair... additionalConfiguration); + + +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProviderImpl.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProviderImpl.java new file mode 100644 index 00000000..e7c01d4f --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProviderImpl.java @@ -0,0 +1,120 @@ +package org.eclipse.store.integrations.spring.boot.types; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.Map; + +import org.eclipse.serializer.persistence.binary.jdk17.types.BinaryHandlersJDK17; +import org.eclipse.serializer.util.logging.Logging; +import org.eclipse.store.integrations.spring.boot.types.configuration.ConfigurationPair; +import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; +import org.eclipse.store.integrations.spring.boot.types.converter.EclipseStoreConfigConverter; +import org.eclipse.store.storage.embedded.configuration.types.EmbeddedStorageConfigurationBuilder; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.slf4j.Logger; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; + +@Component +public class EclipseStoreProviderImpl implements EclipseStoreProvider +{ + private final EclipseStoreConfigConverter converter; + private final ApplicationContext applicationContext; + + private final Logger logger = Logging.getLogger(EclipseStoreProviderImpl.class); + + public EclipseStoreProviderImpl(EclipseStoreConfigConverter converter, ApplicationContext applicationContext) + { + this.converter = converter; + this.applicationContext = applicationContext; + } + + @Override + public EmbeddedStorageManager createStorage(EclipseStoreProperties eclipseStoreProperties, ConfigurationPair... additionalConfiguration) + { + EmbeddedStorageFoundation storageFoundation = createStorageFoundation(eclipseStoreProperties, additionalConfiguration); + return createStorage(storageFoundation, eclipseStoreProperties.getAutoStart()); + } + + @Override + public EmbeddedStorageManager createStorage(EmbeddedStorageFoundation foundation, boolean autoStart) + { + EmbeddedStorageManager storageManager = foundation.createEmbeddedStorageManager(); + if (autoStart) + { + storageManager.start(); + } + return storageManager; + } + + @Override + public EmbeddedStorageFoundation createStorageFoundation(EclipseStoreProperties eclipseStoreProperties, ConfigurationPair... additionalConfiguration) + { + + final EmbeddedStorageConfigurationBuilder builder = EmbeddedStorageConfigurationBuilder.New(); + Map valueMap = converter.convertConfigurationToMap(eclipseStoreProperties); + for (ConfigurationPair pair : additionalConfiguration) { + valueMap.put(pair.key(), pair.value()); + } + + this.logger.debug("EclipseStore configuration items: "); + valueMap.forEach((key, value) -> + { + if (value != null) + { + String logValue = key.contains("password") ? "xxxxxx" : value; + this.logger.debug(key + " : " + logValue); + builder.set(key, value); + } + }); + + EmbeddedStorageFoundation storageFoundation = builder.createEmbeddedStorageFoundation(); + + Object root = provideRoot(eclipseStoreProperties); + if (root != null) + { + this.logger.debug("Root object: " + root.getClass().getName()); + storageFoundation.setRoot(root); + } + + storageFoundation.getConnectionFoundation() + .setClassLoaderProvider(typeName -> this.applicationContext.getClassLoader()); + + if (eclipseStoreProperties.isRegisterJdk17Handlers()) { + this.logger.debug("Register JDK17 handlers. "); + storageFoundation.onConnectionFoundation(BinaryHandlersJDK17::registerJDK17TypeHandlers); + } + + return storageFoundation; + } + + private Object provideRoot(EclipseStoreProperties properties) + { + Class rootClass = properties.getRoot(); + if (rootClass == null) + { + return null; + } + try + { + return rootClass.getDeclaredConstructor().newInstance(); + } catch (Exception e) + { + throw new RuntimeException("Failed to instantiate class: " + rootClass, e); + } + } + +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreSpringBoot.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreSpringBoot.java new file mode 100644 index 00000000..67471f8b --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreSpringBoot.java @@ -0,0 +1,47 @@ +package org.eclipse.store.integrations.spring.boot.types; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; + +/** + * The {@code EclipseStoreSpringBoot} class is responsible for the auto-configuration of the Spring Boot application. + * It sets up the configuration properties for the Eclipse Store and initiates a scan of the base packages for any necessary Spring components. + * + *

Here's an example of how to use this class in a Spring Boot application:

+ *
+ * 
+ *
+ * {@literal @}SpringBootApplication
+ * {@literal @}Import(EclipseStoreSpringBoot.class)
+ *  public class SomeSpringApplication {
+ *     public static void main(String... args) {
+ *         SpringApplication.run(SomeSpringApplication.class, args);
+ *     }
+ *  }
+ * 
+ * 
+ */ + +@AutoConfiguration +@ComponentScan(basePackages = "org.eclipse.store.integrations.spring.boot.types") +@EnableConfigurationProperties(EclipseStoreProperties.class) +public class EclipseStoreSpringBoot +{ +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/LockAspect.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/LockAspect.java new file mode 100644 index 00000000..62670cfa --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/LockAspect.java @@ -0,0 +1,169 @@ +package org.eclipse.store.integrations.spring.boot.types.concurent; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.lang.reflect.Method; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.eclipse.serializer.util.logging.Logging; +import org.slf4j.Logger; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.context.annotation.Conditional; +import org.springframework.core.type.AnnotatedTypeMetadata; +import org.springframework.stereotype.Component; +import org.springframework.util.ClassUtils; + + +/** + * The {@code LockAspect} class is a Spring component that provides a mechanism for handling concurrent access to shared resources. + * It uses Aspect Oriented Programming (AOP) to intercept method calls that are annotated with {@code @Read} or {@code @Write} and applies the appropriate lock. + * The class also supports the {@code @Mutex} annotation which can be used to specify a named lock for a method or a class. + */ +@Aspect +@Component +@Conditional(LockAspect.AspectJCondition.class) +public class LockAspect +{ + + private final Logger logger = Logging.getLogger(LockAspect.class); + + private final ReentrantReadWriteLock globalLock = new ReentrantReadWriteLock(); + + private final ConcurrentHashMap locks = new ConcurrentHashMap<>(); + + /** + * Intercepts method calls that are annotated with {@code @Read} and applies a read lock. + * + * @param joinPoint The join point representing the method call. + * @return The result of the method call. + * @throws Throwable If the method call throws an exception. + */ + @Around("@annotation(Read)") + public Object readOperation(ProceedingJoinPoint joinPoint) throws Throwable + { + ReentrantReadWriteLock lock = this.findLock(joinPoint); + lock.readLock().lock(); + logger.trace("lock readLock"); + Object proceed; + try + { + proceed = joinPoint.proceed(); + } finally + { + lock.readLock().unlock(); + logger.trace("unlock readLock"); + } + return proceed; + } + + /** + * Intercepts method calls that are annotated with {@code @Write} and applies a write lock. + * + * @param joinPoint The join point representing the method call. + * @return The result of the method call. + * @throws Throwable If the method call throws an exception. + */ + @Around("@annotation(Write)") + public Object writeOperation(ProceedingJoinPoint joinPoint) throws Throwable + { + ReentrantReadWriteLock lock = this.findLock(joinPoint); + lock.writeLock().lock(); + logger.trace("write lock"); + + Object proceed; + try + { + proceed = joinPoint.proceed(); + } finally + { + lock.writeLock().unlock(); + logger.trace("write unlock"); + } + + return proceed; + } + + /** + * Finds the appropriate lock for the given join point. + * If the method or the class of the method is annotated with {@code @Mutex}, the named lock is used. + * Otherwise, the global lock is used. + * + * @param joinPoint The join point representing the method call. + * @return The lock to be used. + */ + private ReentrantReadWriteLock findLock(ProceedingJoinPoint joinPoint) + { + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + Method method = methodSignature.getMethod(); + + //method annotation first + ReentrantReadWriteLock finalLock; + Mutex annotation = method.getAnnotation(Mutex.class); + if (annotation != null) + { + String lockName = annotation.value(); + logger.trace("Found method lock annotation for lock: {}", lockName); + finalLock = getOrCreateLock(lockName); + } else + { + //class annotation second + Class declaringClass = method.getDeclaringClass(); + Mutex classAnnotation = declaringClass.getAnnotation(Mutex.class); + if (classAnnotation != null) + { + String classLockName = classAnnotation.value(); + logger.trace("Found class lock annotation for lock: {}", classLockName); + finalLock = getOrCreateLock(classLockName); + } else + { + // no annotation, use global lock + logger.trace("Found no @Lockable annotation, use global lock"); + finalLock = globalLock; + } + } + return finalLock; + } + + /** + * Gets or creates a named lock. + * + * @param lockName The name of the lock. + * @return The named lock. + */ + private ReentrantReadWriteLock getOrCreateLock(String lockName) { + return locks.computeIfAbsent(lockName, k -> { + logger.trace("Lock for name: {} not found, creating a new one", lockName); + return new ReentrantReadWriteLock(); + }); + } + + /** + * A condition that checks if AspectJ is present on the classpath. + * This condition is used to enable or disable the {@code LockAspect} based on the presence of AspectJ. + */ + static class AspectJCondition implements Condition + { + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return ClassUtils.isPresent("org.aspectj.lang.ProceedingJoinPoint", context.getClassLoader()); + } + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Mutex.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Mutex.java new file mode 100644 index 00000000..82a471b7 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Mutex.java @@ -0,0 +1,47 @@ +package org.eclipse.store.integrations.spring.boot.types.concurent; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The {@code Mutex} annotation can be used to specify a named lock for a type or a method. + * This annotation is used in conjunction with the {@code LockAspect} to handle concurrent access to shared resources. + * + *

Here's an example of how to use this annotation:

+ *
+ * 
+ * {@literal @}Mutex("myLock")
+ *    public class MyClass {
+ *
+ *      {@literal @}Mutex("myMethodLock")
+ *       public void myMethod() {
+ *          // method implementation
+ *       }
+ *  }
+ * 
+ * 
+ * + * In this example, the {@code MyClass} type and the {@code myMethod} method each have their own named lock. + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Mutex +{ + String value(); +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Read.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Read.java new file mode 100644 index 00000000..ced6ec72 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Read.java @@ -0,0 +1,45 @@ +package org.eclipse.store.integrations.spring.boot.types.concurent; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The {@code Read} annotation is used to mark methods that should acquire a read lock before execution. + * This annotation is used in conjunction with the {@code LockAspect} to handle concurrent access to shared resources. + * + *

Here's an example of how to use this annotation:

+ *
+ * 
+ * public class MyClass {
+ *
+ *     {@literal @}Read
+ *      public void myMethod() {
+ *         // method implementation
+ *      }
+ * }
+ * 
+ * 
+ *

+ * In this example, the {@code myMethod} method will acquire a read lock before execution. + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Read +{ +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Write.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Write.java new file mode 100644 index 00000000..0d871d38 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Write.java @@ -0,0 +1,45 @@ +package org.eclipse.store.integrations.spring.boot.types.concurent; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The {@code Write} annotation is used to mark methods that should acquire a write lock before execution. + * This annotation is used in conjunction with the {@code LockAspect} to handle concurrent access to shared resources. + * + *

Here's an example of how to use this annotation:

+ *
+ * 
+ * public class MyClass {
+ *
+ *     {@literal @}Write
+ *      public void myMethod() {
+ *         // method implementation
+ *      }
+ * }
+ * 
+ * 
+ * + * In this example, the {@code myMethod} method will acquire a write lock before execution. + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Write +{ +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/ConfigurationPair.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/ConfigurationPair.java new file mode 100644 index 00000000..85cc824b --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/ConfigurationPair.java @@ -0,0 +1,33 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +/** + * The {@code ConfigurationPair} record represents a key-value pair in a configuration. + * It is used to store configuration parameters for the application. + * + *

Here's an example of how to use this record:

+ *
+ * 
+ * ConfigurationPair pair = new ConfigurationPair("key", "value");
+ * 
+ * 
+ * + * In this example, a new {@code ConfigurationPair} is created with the key "key" and the value "value". + */ +public record ConfigurationPair(String key, String value) +{ + +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java new file mode 100644 index 00000000..43a266dd --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java @@ -0,0 +1,444 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +/** + * The {@code EclipseStoreProperties} class holds the configuration properties for the Eclipse Store. + * These properties are loaded from the application's configuration files and can be used to configure the Eclipse Store. + * + *

This class is annotated with {@code @Configuration}, {@code @Primary}, and {@code @ConfigurationProperties}, + * which means it is a Spring configuration class, it is the primary bean of its type, and its properties are bound to the "org.eclipse.store" prefix in the configuration files.

+ * + *

Each property in this class corresponds to a configuration option for the Eclipse Store. + * The properties are loaded from the configuration files when the application starts.

+ */ +@Configuration +@Primary +@ConfigurationProperties(prefix = "org.eclipse.store") +public class EclipseStoreProperties +{ + + /** + * Specify the complete path for the class, which will serve as the root. This class must have a public parameterless constructor. + * Example: "org.eclipse.store.Root" + */ + private Class root; + + /** + * The base directory of the storage in the file system. Default is "storage" in the working directory. + */ + private String storageDirectory; + + /** + * The live file system configuration + */ + @NestedConfigurationProperty + private StorageFilesystem storageFilesystem; + + /** + * If configured, the storage will not delete files. Instead of deleting a file it will be moved to this directory. + */ + private String deletionDirectory; + + /** + * If configured, files that will get truncated are copied into this directory. + */ + private String truncationDirectory; + + /** + * The backup directory. + */ + private String backupDirectory; + + /** + * The backup file system configuration. See storage targets configuration. + */ + @NestedConfigurationProperty + private StorageFilesystem backupFilesystem; + + /** + * The number of threads and number of directories used by the storage engine. Every thread has exclusive access to its directory. Default is 1. + */ + private String channelCount; + + /** + * Name prefix of the subdirectories used by the channel threads. Default is "channel_". + */ + private String channelDirectoryPrefix; + + /** + * Name prefix of the storage files. Default is "channel_". + */ + private String dataFilePrefix; + + /** + * Name suffix of the storage files. Default is ".dat". + */ + private String dataFileSuffix; + + /** + * Name prefix of the storage transaction file. Default is "transactions_". + */ + private String transactionFilePrefix; + + /** + * Name suffix of the storage transaction file. Default is ".sft". + */ + private String transactionFileSuffix; + + /** + * The name of the dictionary file. Default is "PersistenceTypeDictionary.ptd". + */ + private String typeDictionaryFileName; + + /** + * Name suffix of the storage rescue files. Default is ".bak". + */ + private String rescuedFileSuffix; + + /** + * Name of the lock file. Default is "used.lock". + */ + private String lockFileName; + + /** + * Interval for the housekeeping. This is work like garbage collection or cache checking. + * In combination with houseKeepingNanoTimeBudget the maximum processor time for housekeeping work can be set. + * Default is 1 second. + */ + private String housekeepingInterval; + + /** + * Number of nanoseconds used for each housekeeping cycle. + * Default is 10 milliseconds = 0.01 seconds. + */ + private String housekeepingTimeBudget; + + /** + * Timeout in milliseconds for the entity cache evaluator. + * If an entity was not accessed in this timespan it will be removed from the cache. Default is 1 day. + */ + private String entityCacheTimeout; + + /** + * Abstract threshold value for the lifetime of entities in the cache. Default is 1000000000. + */ + private String entityCacheThreshold; + + /** + * Minimum file size for a data file to avoid cleaning it up. Default is 1024^2 = 1 MiB. + */ + private String dataFileMinimumSize; + + /** + * Maximum file size for a data file to avoid cleaning it up. Default is 1024^2*8 = 8 MiB. + */ + private String dataFileMaximumSize; + + /** + * The ratio (value in ]0.0;1.0]) of non-gap data contained in a storage file to prevent the file from being dissolved. Default is 0.75 (75%). + */ + private String dataFileMinimumUseRatio; + + /** + * A flag defining whether the current head file (the only file actively written to) shall be subjected to file cleanups as well. + */ + private String dataFileCleanupHeadFile; + + /** + * Is the {@code StorageManager} started when the CDI bean for the instance is created or not. + * Be aware that when you don't rely on the autostart of the StorageManager, you are responsible for starting it + * and might result in Exceptions when code is executed that relies on a started StorageManager. + * Default value is true. + */ + private boolean autoStart = true; + + /** + * A flag defining whether the default handlers for JDK 1.7 classes shall be registered or not. + * Default value is true. + */ + private boolean registerJdk17Handlers = true; + + public Class getRoot() + { + return root; + } + + public void setRoot(Class root) + { + this.root = root; + } + + public String getStorageDirectory() + { + return storageDirectory; + } + + public void setStorageDirectory(String storageDirectory) + { + this.storageDirectory = storageDirectory; + } + + public StorageFilesystem getStorageFilesystem() + { + return storageFilesystem; + } + + public void setStorageFilesystem(StorageFilesystem storageFilesystem) + { + this.storageFilesystem = storageFilesystem; + } + + public String getDeletionDirectory() + { + return deletionDirectory; + } + + public void setDeletionDirectory(String deletionDirectory) + { + this.deletionDirectory = deletionDirectory; + } + + public String getTruncationDirectory() + { + return truncationDirectory; + } + + public void setTruncationDirectory(String truncationDirectory) + { + this.truncationDirectory = truncationDirectory; + } + + public String getBackupDirectory() + { + return backupDirectory; + } + + public void setBackupDirectory(String backupDirectory) + { + this.backupDirectory = backupDirectory; + } + + public StorageFilesystem getBackupFilesystem() + { + return backupFilesystem; + } + + public void setBackupFilesystem(StorageFilesystem backupFilesystem) + { + this.backupFilesystem = backupFilesystem; + } + + public String getChannelCount() + { + return channelCount; + } + + public void setChannelCount(String channelCount) + { + this.channelCount = channelCount; + } + + public String getChannelDirectoryPrefix() + { + return channelDirectoryPrefix; + } + + public void setChannelDirectoryPrefix(String channelDirectoryPrefix) + { + this.channelDirectoryPrefix = channelDirectoryPrefix; + } + + public String getDataFilePrefix() + { + return dataFilePrefix; + } + + public void setDataFilePrefix(String dataFilePrefix) + { + this.dataFilePrefix = dataFilePrefix; + } + + public String getDataFileSuffix() + { + return dataFileSuffix; + } + + public void setDataFileSuffix(String dataFileSuffix) + { + this.dataFileSuffix = dataFileSuffix; + } + + public String getTransactionFilePrefix() + { + return transactionFilePrefix; + } + + public void setTransactionFilePrefix(String transactionFilePrefix) + { + this.transactionFilePrefix = transactionFilePrefix; + } + + public String getTransactionFileSuffix() + { + return transactionFileSuffix; + } + + public void setTransactionFileSuffix(String transactionFileSuffix) + { + this.transactionFileSuffix = transactionFileSuffix; + } + + public String getTypeDictionaryFileName() + { + return typeDictionaryFileName; + } + + public void setTypeDictionaryFileName(String typeDictionaryFileName) + { + this.typeDictionaryFileName = typeDictionaryFileName; + } + + public String getRescuedFileSuffix() + { + return rescuedFileSuffix; + } + + public void setRescuedFileSuffix(String rescuedFileSuffix) + { + this.rescuedFileSuffix = rescuedFileSuffix; + } + + public String getLockFileName() + { + return lockFileName; + } + + public void setLockFileName(String lockFileName) + { + this.lockFileName = lockFileName; + } + + public String getHousekeepingInterval() + { + return housekeepingInterval; + } + + public void setHousekeepingInterval(String housekeepingInterval) + { + this.housekeepingInterval = housekeepingInterval; + } + + public String getHousekeepingTimeBudget() + { + return housekeepingTimeBudget; + } + + public void setHousekeepingTimeBudget(String housekeepingTimeBudget) + { + this.housekeepingTimeBudget = housekeepingTimeBudget; + } + + public String getEntityCacheTimeout() + { + return entityCacheTimeout; + } + + public void setEntityCacheTimeout(String entityCacheTimeout) + { + this.entityCacheTimeout = entityCacheTimeout; + } + + public String getEntityCacheThreshold() + { + return entityCacheThreshold; + } + + public void setEntityCacheThreshold(String entityCacheThreshold) + { + this.entityCacheThreshold = entityCacheThreshold; + } + + public String getDataFileMinimumSize() + { + return dataFileMinimumSize; + } + + public void setDataFileMinimumSize(String dataFileMinimumSize) + { + this.dataFileMinimumSize = dataFileMinimumSize; + } + + public String getDataFileMaximumSize() + { + return dataFileMaximumSize; + } + + public void setDataFileMaximumSize(String dataFileMaximumSize) + { + this.dataFileMaximumSize = dataFileMaximumSize; + } + + public String getDataFileMinimumUseRatio() + { + return dataFileMinimumUseRatio; + } + + public void setDataFileMinimumUseRatio(String dataFileMinimumUseRatio) + { + this.dataFileMinimumUseRatio = dataFileMinimumUseRatio; + } + + public String getDataFileCleanupHeadFile() + { + return dataFileCleanupHeadFile; + } + + public void setDataFileCleanupHeadFile(String dataFileCleanupHeadFile) + { + this.dataFileCleanupHeadFile = dataFileCleanupHeadFile; + } + + public boolean getAutoStart() + { + return autoStart; + } + + public void setAutoStart(boolean autoStart) + { + this.autoStart = autoStart; + } + + public boolean isAutoStart() + { + return autoStart; + } + + public boolean isRegisterJdk17Handlers() + { + return registerJdk17Handlers; + } + + public void setRegisterJdk17Handlers(boolean registerJdk17Handlers) + { + this.registerJdk17Handlers = registerJdk17Handlers; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/StorageFilesystem.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/StorageFilesystem.java new file mode 100644 index 00000000..91853586 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/StorageFilesystem.java @@ -0,0 +1,124 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import java.util.Map; + +import org.eclipse.store.integrations.spring.boot.types.configuration.aws.Aws; +import org.eclipse.store.integrations.spring.boot.types.configuration.azure.Azure; +import org.eclipse.store.integrations.spring.boot.types.configuration.googlecloud.Googlecloud; +import org.eclipse.store.integrations.spring.boot.types.configuration.oraclecloud.Oraclecloud; +import org.eclipse.store.integrations.spring.boot.types.configuration.redis.Redis; +import org.eclipse.store.integrations.spring.boot.types.configuration.sql.Sql; +import org.springframework.boot.context.properties.NestedConfigurationProperty; + +public class StorageFilesystem +{ + + @NestedConfigurationProperty + private Sql sql; + + @NestedConfigurationProperty + private Aws aws; + + @NestedConfigurationProperty + private Azure azure; + + /** + * Supported properties + * All supported properties of Kafka, see https://kafka.apache.org/documentation/ + */ + private Map kafkaProperties; + + @NestedConfigurationProperty + private Oraclecloud oraclecloud; + + @NestedConfigurationProperty + private Googlecloud googlecloud; + + @NestedConfigurationProperty + private Redis redis; + + public Sql getSql() + { + return sql; + } + + public void setSql(Sql sql) + { + this.sql = sql; + } + + public Aws getAws() + { + return aws; + } + + public void setAws(Aws aws) + { + this.aws = aws; + } + + public Map getKafkaProperties() + { + return kafkaProperties; + } + + public void setKafkaProperties(Map kafkaProperties) + { + this.kafkaProperties = kafkaProperties; + } + + public Oraclecloud getOraclecloud() + { + return oraclecloud; + } + + public void setOraclecloud(Oraclecloud oraclecloud) + { + this.oraclecloud = oraclecloud; + } + + public Redis getRedis() + { + return redis; + } + + public void setRedis(Redis redis) + { + this.redis = redis; + } + + public Azure getAzure() + { + return azure; + } + + public void setAzure(Azure azure) + { + this.azure = azure; + } + + public Googlecloud getGooglecloud() + { + return googlecloud; + } + + public void setGooglecloud(Googlecloud googlecloud) + { + this.googlecloud = googlecloud; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/AbstractAwsProperties.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/AbstractAwsProperties.java new file mode 100644 index 00000000..67f46f8f --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/AbstractAwsProperties.java @@ -0,0 +1,71 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.aws; + +/*- + * #%L + * microstream-integrations-spring-boot3 + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.springframework.boot.context.properties.NestedConfigurationProperty; + +public abstract class AbstractAwsProperties +{ + + @NestedConfigurationProperty + private Credentials credentials; + + /** + * The endpoint with which the SDK should communicate. + */ + private String endpointOverride; + + /** + * Configure the region with which the SDK should communicate. If this is not specified, the SDK will attempt to identify the endpoint automatically using the following logic: + *
    + *
  1. Check the 'aws.region' system property for the region.
  2. + *
  3. Check the 'AWS_REGION' environment variable for the region.
  4. + *
  5. Check the {user.home}/.aws/credentials and {user.home}/.aws/config files for the region.
  6. + *
  7. If running in EC2, check the EC2 metadata service for the region.
  8. + *
+ */ + private String region; + + + public Credentials getCredentials() + { + return credentials; + } + + public void setCredentials(Credentials credentials) + { + this.credentials = credentials; + } + + public String getEndpointOverride() + { + return endpointOverride; + } + + public void setEndpointOverride(String endpointOverride) + { + this.endpointOverride = endpointOverride; + } + + public String getRegion() + { + return region; + } + + public void setRegion(String region) + { + this.region = region; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Aws.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Aws.java new file mode 100644 index 00000000..f8b63094 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Aws.java @@ -0,0 +1,47 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.aws; + +/*- + * #%L + * microstream-integrations-spring-boot3 + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.springframework.boot.context.properties.NestedConfigurationProperty; + +public class Aws +{ + + @NestedConfigurationProperty + private Dynamodb dynamodb; + + @NestedConfigurationProperty + private S3 s3; + + public Dynamodb getDynamodb() + { + return this.dynamodb; + } + + public void setDynamodb(final Dynamodb dynamodb) + { + this.dynamodb = dynamodb; + } + + public S3 getS3() + { + return this.s3; + } + + public void setS3(final S3 s3) + { + this.s3 = s3; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Credentials.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Credentials.java new file mode 100644 index 00000000..956ecbfa --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Credentials.java @@ -0,0 +1,79 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.aws; + +/*- + * #%L + * microstream-integrations-spring-boot3 + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class Credentials +{ + + /** + * The type of the credentials provider. Supported values are: + *
    + * + *
  • "environment-variables" Credentials will be loaded from the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN environment variables.
  • + *
  • "system-properties" Credentials will be loaded from the aws.accessKeyId, aws.secretAccessKey and aws.sessionToken system properties.
  • + *
  • "static" Credentials will be loaded from the credentials.access-key-id and credentials.secret-access-key properties.
  • + *
  • "default" Credentials provider chain that looks for credentials in this order:
  • + *
      + *
    1. Java System Properties - aws.accessKeyId and aws.secretKey + *
    2. Environment Variables - AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
    3. + *
    4. Credential profiles file at the default location (~/.aws/credentials) shared by all AWS SDKs and the AWS CLI
    5. + *
    6. Credentials delivered through the Amazon EC2 container service if AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" environment variable is set and security manager has permission to access the variable
    7. + *
    8. Instance profile credentials delivered through the Amazon EC2 metadata service
    9. + *
    + *
+ */ + private String type; + + /** + * The access key id, used when "credentials.type" is "static". + */ + private String accessKeyId; + + /** + * The secret access key, used when "credentials.type" is "static". + */ + private String secretAccessKey; + + + public String getType() + { + return type; + } + + public void setType(String type) + { + this.type = type; + } + + public String getAccessKeyId() + { + return accessKeyId; + } + + public void setAccessKeyId(String accessKeyId) + { + this.accessKeyId = accessKeyId; + } + + public String getSecretAccessKey() + { + return secretAccessKey; + } + + public void setSecretAccessKey(String secretAccessKey) + { + this.secretAccessKey = secretAccessKey; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Dynamodb.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Dynamodb.java new file mode 100644 index 00000000..b32119ce --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Dynamodb.java @@ -0,0 +1,21 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.aws; + +/*- + * #%L + * microstream-integrations-spring-boot3 + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class Dynamodb extends AbstractAwsProperties +{ + + +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/S3.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/S3.java new file mode 100644 index 00000000..7a2a91ae --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/S3.java @@ -0,0 +1,20 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.aws; + +/*- + * #%L + * microstream-integrations-spring-boot3 + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class S3 extends AbstractAwsProperties +{ + +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Azure.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Azure.java new file mode 100644 index 00000000..4beb5251 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Azure.java @@ -0,0 +1,34 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.azure; + +/*- + * #%L + * microstream-integrations-spring-boot3 + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.springframework.boot.context.properties.NestedConfigurationProperty; + +public class Azure +{ + + @NestedConfigurationProperty + private Storage storage; + + public Storage getStorage() + { + return storage; + } + + public void setStorage(Storage storage) + { + this.storage = storage; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Credentials.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Credentials.java new file mode 100644 index 00000000..a04c8f0b --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Credentials.java @@ -0,0 +1,101 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.azure; + +/*- + * #%L + * microstream-integrations-spring-boot3 + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class Credentials +{ + + /** + * The type of the credentials provider. Supported values are: + *
    + *
  • "basic"
  • + * Credentials will be loaded from the credentials.username and credentials.password properties. + * + *
  • "shared-key"
  • + * Credentials will be loaded from the credentials.account-name and credentials.account-key properties. + *
+ */ + private String type; + + /** + * The username, used when "credentials.type" is "basic". + */ + private String username; + + /** + * The password, used when "credentials.type" is "basic". + */ + private String password; + + /** + * The account name, used when "credentials.type" is "shared-key". + */ + private String accountMame; + + /** + * The account key, used when "credentials.type" is "shared-key". + */ + private String accountKey; + + public String getType() + { + return type; + } + + public void setType(String type) + { + this.type = type; + } + + public String getUsername() + { + return username; + } + + public void setUsername(String username) + { + this.username = username; + } + + public String getPassword() + { + return password; + } + + public void setPassword(String password) + { + this.password = password; + } + + public String getAccountMame() + { + return accountMame; + } + + public void setAccountMame(String accountMame) + { + this.accountMame = accountMame; + } + + public String getAccountKey() + { + return accountKey; + } + + public void setAccountKey(String accountKey) + { + this.accountKey = accountKey; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Storage.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Storage.java new file mode 100644 index 00000000..7e830c73 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Storage.java @@ -0,0 +1,79 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.azure; + +/*- + * #%L + * microstream-integrations-spring-boot3 + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.springframework.boot.context.properties.NestedConfigurationProperty; + +public class Storage +{ + + @NestedConfigurationProperty + private Credentials credentials; + + /** + * Sets the blob service endpoint, additionally parses it for information (SAS token). + */ + private String endpoint; + + /** + * Sets the connection string to connect to the service. + */ + private String connectionString; + + /** + * Sets the encryption scope that is used to encrypt blob contents on the server. + */ + private String encryptionScope; + + public Credentials getCredentials() + { + return credentials; + } + + public void setCredentials(Credentials credentials) + { + this.credentials = credentials; + } + + public String getEndpoint() + { + return endpoint; + } + + public void setEndpoint(String endpoint) + { + this.endpoint = endpoint; + } + + public String getConnectionString() + { + return connectionString; + } + + public void setConnectionString(String connectionString) + { + this.connectionString = connectionString; + } + + public String getEncryptionScope() + { + return encryptionScope; + } + + public void setEncryptionScope(String encryptionScope) + { + this.encryptionScope = encryptionScope; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/Googlecloud.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/Googlecloud.java new file mode 100644 index 00000000..c98cdc0b --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/Googlecloud.java @@ -0,0 +1,34 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.googlecloud; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.integrations.spring.boot.types.configuration.googlecloud.firestore.Firestore; +import org.springframework.boot.context.properties.NestedConfigurationProperty; + +public class Googlecloud +{ + @NestedConfigurationProperty + private Firestore firestore; + + public Firestore getFirestore() + { + return firestore; + } + + public void setFirestore(Firestore firestore) + { + this.firestore = firestore; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Credentials.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Credentials.java new file mode 100644 index 00000000..2c20da31 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Credentials.java @@ -0,0 +1,51 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.googlecloud.firestore; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class Credentials +{ + /** + * The type of the credentials provider. Supported values are: + * + *
    + *
  • "none": No credentials are used.
  • + *
  • "input-stream": Path of a JSON file stream. The stream can contain a Service Account key file in JSON format from the Google Developers Console or a stored user credential using the format supported by the Cloud SDK.
  • + *
  • "default": Returns the Application Default Credentials which are used to identify and authorize the whole application. The following are searched (in order) to find the Application Default Credentials: + *
      + *
    • Credentials file pointed to by the GOOGLE_APPLICATION_CREDENTIALS environment variable.
    • + *
    • Credentials provided by the Google Cloud SDK.
    • + *
        + *
      • gcloud auth application-default login for user account credentials.
      • + *
      • gcloud auth application-default login --impersonate-service-account for impersonated service account credentials.
      • + *
      + *
    • Google App Engine built-in credentials.
    • + *
    • Google Cloud Shell built-in credentials.
    • + *
    • Google Compute Engine built-in credentials.
    • + *
    + *
  • + *
+ */ + private String type; + + public String getType() + { + return type; + } + + public void setType(String type) + { + this.type = type; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Firestore.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Firestore.java new file mode 100644 index 00000000..735fc966 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Firestore.java @@ -0,0 +1,50 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.googlecloud.firestore; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.springframework.boot.context.properties.NestedConfigurationProperty; + +public class Firestore +{ + /** + * he database ID to use with this Firestore client. + */ + private String databaseId; + + /** + * + * The emulator host to use with this Firestore client. + */ + private String emulatorHost; + + /** + * The service host. + */ + private String host; + + /** + * + * The project ID. If no project ID is set, the project ID from the environment will be used. + */ + private String projectId; + + /** + * The project ID that specifies the project used for quota and billing purposes. + */ + private String quotaProjectId; + + @NestedConfigurationProperty + private Credentials credentials; +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Client.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Client.java new file mode 100644 index 00000000..ac5fba03 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Client.java @@ -0,0 +1,64 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.oraclecloud; + +/*- + * #%L + * microstream-integrations-spring-boot3 + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class Client +{ + + /** + * The max time to wait for a connection, in millis. Default is 10000. + */ + private String connectionTimeoutMillis; + + /** + * The max time to wait for data, in millis. Default is 60000. + */ + private String readTimeoutMillis; + + /** + * The max number of async threads to use. Default is 50. + */ + private String maxAsyncThreads; + + public String getConnectionTimeoutMillis() + { + return connectionTimeoutMillis; + } + + public void setConnectionTimeoutMillis(String connectionTimeoutMillis) + { + this.connectionTimeoutMillis = connectionTimeoutMillis; + } + + public String getReadTimeoutMillis() + { + return readTimeoutMillis; + } + + public void setReadTimeoutMillis(String readTimeoutMillis) + { + this.readTimeoutMillis = readTimeoutMillis; + } + + public String getMaxAsyncThreads() + { + return maxAsyncThreads; + } + + public void setMaxAsyncThreads(String maxAsyncThreads) + { + this.maxAsyncThreads = maxAsyncThreads; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ConfigFile.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ConfigFile.java new file mode 100644 index 00000000..abfe9f9e --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ConfigFile.java @@ -0,0 +1,64 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.oraclecloud; + +/*- + * #%L + * microstream-integrations-spring-boot3 + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class ConfigFile +{ + + /** + * The path of the config file, if not set the default is used: "~/.oci/config" + */ + private String path; + + /** + * The configuration profile to use, if not set "DEFAULT" is used. + */ + private String profile; + + /** + * The encoding of the config file. + */ + private String charset; + + public String getPath() + { + return path; + } + + public void setPath(String path) + { + this.path = path; + } + + public String getProfile() + { + return profile; + } + + public void setProfile(String profile) + { + this.profile = profile; + } + + public String getCharset() + { + return charset; + } + + public void setCharset(String charset) + { + this.charset = charset; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ObjectStorage.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ObjectStorage.java new file mode 100644 index 00000000..ddd3e38d --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ObjectStorage.java @@ -0,0 +1,77 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.oraclecloud; + +/*- + * #%L + * microstream-integrations-spring-boot3 + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.springframework.boot.context.properties.NestedConfigurationProperty; + +public class ObjectStorage +{ + + @NestedConfigurationProperty + private ConfigFile configFile; + + @NestedConfigurationProperty + private Client client; + + /** + * Sets the region to call (ex, 'us-phoenix-1'). + */ + private String region; + + /** + * Sets the endpoint to call (ex, https://www.example.com). + */ + private String endpoint; + + public ConfigFile getConfigFile() + { + return configFile; + } + + public void setConfigFile(ConfigFile configFile) + { + this.configFile = configFile; + } + + public Client getClient() + { + return client; + } + + public void setClient(Client client) + { + this.client = client; + } + + public String getRegion() + { + return region; + } + + public void setRegion(String region) + { + this.region = region; + } + + public String getEndpoint() + { + return endpoint; + } + + public void setEndpoint(String endpoint) + { + this.endpoint = endpoint; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Oraclecloud.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Oraclecloud.java new file mode 100644 index 00000000..6aa052da --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Oraclecloud.java @@ -0,0 +1,34 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.oraclecloud; + +/*- + * #%L + * microstream-integrations-spring-boot3 + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.springframework.boot.context.properties.NestedConfigurationProperty; + +public class Oraclecloud +{ + + @NestedConfigurationProperty + private ObjectStorage objectStorage; + + public ObjectStorage getObjectStorage() + { + return objectStorage; + } + + public void setObjectStorage(ObjectStorage objectStorage) + { + this.objectStorage = objectStorage; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/redis/Redis.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/redis/Redis.java new file mode 100644 index 00000000..9bf27606 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/redis/Redis.java @@ -0,0 +1,34 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.redis; + +/*- + * #%L + * microstream-integrations-spring-boot3 + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class Redis +{ + + /** + * The RedisURI contains the host/port and can carry authentication/database details. On a successful connect you get authenticated, and the database is selected afterward. This applies also after re-establishing a connection after a connection loss. + */ + private String uri; + + public String getUri() + { + return uri; + } + + public void setUri(String uri) + { + this.uri = uri; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/AbstractSqlConfiguration.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/AbstractSqlConfiguration.java new file mode 100644 index 00000000..2bef752b --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/AbstractSqlConfiguration.java @@ -0,0 +1,86 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.sql; + +/*- + * #%L + * microstream-integrations-spring-boot3 + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class AbstractSqlConfiguration +{ + + private String dataSourceProvider; + private String catalog; + private String schema; + private String url; + private String user; + private String password; + + public String getDataSourceProvider() + { + return dataSourceProvider; + } + + public void setDataSourceProvider(String dataSourceProvider) + { + this.dataSourceProvider = dataSourceProvider; + } + + public String getCatalog() + { + return catalog; + } + + public void setCatalog(String catalog) + { + this.catalog = catalog; + } + + public String getSchema() + { + return schema; + } + + public void setSchema(String schema) + { + this.schema = schema; + } + + public String getUrl() + { + return url; + } + + public void setUrl(String url) + { + this.url = url; + } + + public String getUser() + { + return user; + } + + public void setUser(String user) + { + this.user = user; + } + + public String getPassword() + { + return password; + } + + public void setPassword(String password) + { + this.password = password; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Mariadb.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Mariadb.java new file mode 100644 index 00000000..6fdf8adc --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Mariadb.java @@ -0,0 +1,20 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.sql; + +/*- + * #%L + * microstream-integrations-spring-boot3 + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class Mariadb extends AbstractSqlConfiguration +{ + +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Oracle.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Oracle.java new file mode 100644 index 00000000..187de17f --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Oracle.java @@ -0,0 +1,21 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.sql; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +public class Oracle extends AbstractSqlConfiguration +{ + +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Postgres.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Postgres.java new file mode 100644 index 00000000..85dd79f7 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Postgres.java @@ -0,0 +1,19 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.sql; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class Postgres extends AbstractSqlConfiguration +{ +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sql.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sql.java new file mode 100644 index 00000000..d9f5bf16 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sql.java @@ -0,0 +1,74 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.sql; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import org.springframework.boot.context.properties.NestedConfigurationProperty; + +public class Sql +{ + + @NestedConfigurationProperty + private Mariadb mariadb; + + @NestedConfigurationProperty + private Oracle oracle; + + @NestedConfigurationProperty + private Postgres postgres; + + @NestedConfigurationProperty + private Sqlite sqlite; + + public Mariadb getMariadb() + { + return mariadb; + } + + public void setMariadb(Mariadb mariadb) + { + this.mariadb = mariadb; + } + + public Oracle getOracle() + { + return oracle; + } + + public void setOracle(Oracle oracle) + { + this.oracle = oracle; + } + + public Postgres getPostgres() + { + return postgres; + } + + public void setPostgres(Postgres postgres) + { + this.postgres = postgres; + } + + public Sqlite getSqlite() + { + return sqlite; + } + + public void setSqlite(Sqlite sqlite) + { + this.sqlite = sqlite; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sqlite.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sqlite.java new file mode 100644 index 00000000..7e3676b7 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sqlite.java @@ -0,0 +1,19 @@ +package org.eclipse.store.integrations.spring.boot.types.configuration.sql; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class Sqlite extends AbstractSqlConfiguration +{ +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java new file mode 100644 index 00000000..1fa41e79 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java @@ -0,0 +1,105 @@ +package org.eclipse.store.integrations.spring.boot.types.converter; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +/** + * The {@code ConfigKeys} enum provides a list of configuration keys used in the application. + * These keys are used to retrieve configuration values from the application's configuration files. + * The keys are grouped by the service they are related to (e.g., AWS, Azure, Oracle Cloud, etc.). + */ +public enum ConfigKeys +{ + + //storage-filesystem + SQL("sql"), + MARIADB("mariadb"), + ORACLE("oracle"), + POSTGRES("postgres"), + SQLITE("sqlite"), + + //aws + AWS("aws"), + DYNAMODB("dynamodb"), + S3("s3"), + AWS_CREDENTIALS_TYPE("credentials.type"), + AWS_CREDENTIALS_ACCESS_KEY_ID("credentials.access-key-id"), + AWS_CREDENTIALS_SECRET_ACCESS_KEY("credentials.secret-access-key"), + AWS_ENDPOINT_OVERRIDE("endpointOverride"), + AWS_REGION("region"), + + //azure + AZURE("azure"), + AZURE_STORAGE_ENDPOINT("storage.endpoint"), + AZURE_STORAGE_CONNECTION_STRING("storage.connection-string"), + AZURE_STORAGE_ENCRYPTION_SCOPE("storage.encryption-scope"), + AZURE_STORAGE_CREDENTIALS_TYPE("storage.credentials.type"), + AZURE_STORAGE_CREDENTIALS_USERNAME("storage.credentials.username"), + AZURE_STORAGE_CREDENTIALS_PASSWORD("storage.credentials.password"), + AZURE_STORAGE_CREDENTIALS_ACCOUNT_NAME("storage.credentials.account-name"), + AZURE_STORAGE_CREDENTIALS_ACCOUNT_KEY("storage.credentials.account-key"), + + //Hazelcast + HAZELCAST_CONFIGURATION("hazelcast.configuration"), + + // Oracle Cloud + ORACLECLOUD("oraclecloud"), + ORACLECLOUD_CONFIG_FILE_PATH("object-storage.config-file.path"), + ORACLECLOUD_CONFIG_FILE_PROFILE("object-storage.config-file.profile"), + ORACLECLOUD_CONFIG_FILE_CHARSET("object-storage.config-file.charset"), + ORACLECLOUD_CLIENT_CONNECTION_TIMEOUT_MILLIS("object-storage.client.connection-timeout-millis"), + ORACLECLOUD_CLIENT_READ_TIMEOUT_MILLIS("object-storage.client.read-timeout-millis"), + ORACLECLOUD_CLIENT_MAX_ASYNC_THREADS("object-storage.client.max-async-threads"), + ORACLECLOUD_REGION("object-storage.region"), + ORACLECLOUD_ENDPOINT("object-storage.endpoint"), + + //Coherence + COHERENCE("coherence"), + COHERENCE_CACHE_NAME("cache-name"), + COHERENCE_CACHE_CONFIG("cache-config"), + + //redis + REDIS_URI("redis.uri"), + + //sql + SQL_DATA_SOURCE_PROVIDER("data-source-provider"), + SQL_CATALOG("catalog"), + SQL_SCHEMA("schema"), + SQL_URL("url"), + SQL_USER("user"), + SQL_PASSWORD("password") + ; + + private String value; + + /** + * Constructs a new {@code ConfigKeys} enum with the provided value. + * + * @param value The string value of the configuration key. + */ + ConfigKeys(String value) + { + this.value = value; + } + + /** + * Returns the string value of the configuration key. + * + * @return The string value of the configuration key. + */ + public String value() + { + return value; + } +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java new file mode 100644 index 00000000..3b68567f --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java @@ -0,0 +1,256 @@ +package org.eclipse.store.integrations.spring.boot.types.converter; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; +import org.eclipse.store.integrations.spring.boot.types.configuration.StorageFilesystem; +import org.eclipse.store.integrations.spring.boot.types.configuration.aws.AbstractAwsProperties; +import org.eclipse.store.integrations.spring.boot.types.configuration.aws.Aws; +import org.eclipse.store.integrations.spring.boot.types.configuration.azure.Azure; +import org.eclipse.store.integrations.spring.boot.types.configuration.oraclecloud.Oraclecloud; +import org.eclipse.store.integrations.spring.boot.types.configuration.sql.AbstractSqlConfiguration; +import org.eclipse.store.integrations.spring.boot.types.configuration.sql.Sql; +import org.eclipse.store.storage.embedded.configuration.types.EmbeddedStorageConfigurationPropertyNames; +import org.springframework.stereotype.Component; + +/** + * The {@code EclipseStoreConfigConverter} class is a Spring component that converts the Eclipse Store properties into a map. + * This map can then be used to configure the Eclipse Store. + */ +@Component +public class EclipseStoreConfigConverter +{ + + // Fields for testing if all keys from Eclipse Store Configuration are covered by these module. + // These fields are protected so they can be accessed in tests. + // Each field represents a key in the Eclipse Store Configuration. + + // Fields for the storage directory configuration + protected static final String STORAGE_DIRECTORY = EmbeddedStorageConfigurationPropertyNames.STORAGE_DIRECTORY; + protected static final String STORAGE_FILESYSTEM = EmbeddedStorageConfigurationPropertyNames.STORAGE_FILESYSTEM; + protected static final String DELETION_DIRECTORY = EmbeddedStorageConfigurationPropertyNames.DELETION_DIRECTORY; + protected static final String TRUNCATION_DIRECTORY = EmbeddedStorageConfigurationPropertyNames.TRUNCATION_DIRECTORY; + protected static final String BACKUP_DIRECTORY = EmbeddedStorageConfigurationPropertyNames.BACKUP_DIRECTORY; + protected static final String BACKUP_FILESYSTEM = EmbeddedStorageConfigurationPropertyNames.BACKUP_FILESYSTEM; + + // Fields for the channel configuration + protected static final String CHANNEL_COUNT = EmbeddedStorageConfigurationPropertyNames.CHANNEL_COUNT; + protected static final String CHANNEL_DIRECTORY_PREFIX = EmbeddedStorageConfigurationPropertyNames.CHANNEL_DIRECTORY_PREFIX; + + // Fields for configuring file names + protected static final String DATA_FILE_PREFIX = EmbeddedStorageConfigurationPropertyNames.DATA_FILE_PREFIX; + protected static final String DATA_FILE_SUFFIX = EmbeddedStorageConfigurationPropertyNames.DATA_FILE_SUFFIX; + protected static final String TRANSACTION_FILE_PREFIX = EmbeddedStorageConfigurationPropertyNames.TRANSACTION_FILE_PREFIX; + protected static final String TRANSACTION_FILE_SUFFIX = EmbeddedStorageConfigurationPropertyNames.TRANSACTION_FILE_SUFFIX; + protected static final String TYPE_DICTIONARY_FILE_NAME = EmbeddedStorageConfigurationPropertyNames.TYPE_DICTIONARY_FILE_NAME; + protected static final String RESCUED_FILE_SUFFIX = EmbeddedStorageConfigurationPropertyNames.RESCUED_FILE_SUFFIX; + protected static final String LOCK_FILE_NAME = EmbeddedStorageConfigurationPropertyNames.LOCK_FILE_NAME; + + // Fields for the housekeeping configuration + protected static final String HOUSEKEEPING_INTERVAL = EmbeddedStorageConfigurationPropertyNames.HOUSEKEEPING_INTERVAL; + protected static final String HOUSEKEEPING_TIME_BUDGET = EmbeddedStorageConfigurationPropertyNames.HOUSEKEEPING_TIME_BUDGET; + + // Fields for the entity cache configuration + protected static final String ENTITY_CACHE_THRESHOLD = EmbeddedStorageConfigurationPropertyNames.ENTITY_CACHE_THRESHOLD; + protected static final String ENTITY_CACHE_TIMEOUT = EmbeddedStorageConfigurationPropertyNames.ENTITY_CACHE_TIMEOUT; + + // Fields for the data file configuration + protected static final String DATA_FILE_MINIMUM_SIZE = EmbeddedStorageConfigurationPropertyNames.DATA_FILE_MINIMUM_SIZE; + protected static final String DATA_FILE_MAXIMUM_SIZE = EmbeddedStorageConfigurationPropertyNames.DATA_FILE_MAXIMUM_SIZE; + protected static final String DATA_FILE_MINIMUM_USE_RATIO = EmbeddedStorageConfigurationPropertyNames.DATA_FILE_MINIMUM_USE_RATIO; + protected static final String DATA_FILE_CLEANUP_HEAD_FILE = EmbeddedStorageConfigurationPropertyNames.DATA_FILE_CLEANUP_HEAD_FILE; + + + /** + * Converts the provided Eclipse Store properties into a map. + * The keys of the map are the configuration keys and the values are the corresponding configuration values. + * + * @param properties The Eclipse Store properties to convert. + * @return A map representing the provided Eclipse Store properties. + */ + public Map convertConfigurationToMap(EclipseStoreProperties properties) + { + + Map configValues = new HashMap<>(); + configValues.put(STORAGE_DIRECTORY, properties.getStorageDirectory()); + + if (properties.getStorageFilesystem() != null) + { + configValues.putAll(prepareFileSystem(properties.getStorageFilesystem(), STORAGE_FILESYSTEM)); + } + + configValues.put(DELETION_DIRECTORY, properties.getDeletionDirectory()); + configValues.put(TRUNCATION_DIRECTORY, properties.getTruncationDirectory()); + configValues.put(BACKUP_DIRECTORY, properties.getBackupDirectory()); + + if (properties.getBackupFilesystem() != null) + { + configValues.putAll(prepareFileSystem(properties.getBackupFilesystem(), BACKUP_FILESYSTEM)); + } + + configValues.put(CHANNEL_COUNT, properties.getChannelCount()); + configValues.put(CHANNEL_DIRECTORY_PREFIX, properties.getChannelDirectoryPrefix()); + configValues.put(DATA_FILE_PREFIX, properties.getDataFilePrefix()); + configValues.put(DATA_FILE_SUFFIX, properties.getDataFileSuffix()); + configValues.put(TRANSACTION_FILE_PREFIX, properties.getTransactionFilePrefix()); + configValues.put(TRANSACTION_FILE_SUFFIX, properties.getTransactionFileSuffix()); + configValues.put(TYPE_DICTIONARY_FILE_NAME, properties.getTypeDictionaryFileName()); + configValues.put(RESCUED_FILE_SUFFIX, properties.getRescuedFileSuffix()); + configValues.put(LOCK_FILE_NAME, properties.getLockFileName()); + configValues.put(HOUSEKEEPING_INTERVAL, properties.getHousekeepingInterval()); + configValues.put(HOUSEKEEPING_TIME_BUDGET, properties.getHousekeepingTimeBudget()); + configValues.put(ENTITY_CACHE_THRESHOLD, properties.getEntityCacheThreshold()); + configValues.put(ENTITY_CACHE_TIMEOUT, properties.getEntityCacheTimeout()); + configValues.put(DATA_FILE_MINIMUM_SIZE, properties.getDataFileMinimumSize()); + configValues.put(DATA_FILE_MAXIMUM_SIZE, properties.getDataFileMaximumSize()); + configValues.put(DATA_FILE_MINIMUM_USE_RATIO, properties.getDataFileMinimumUseRatio()); + configValues.put(DATA_FILE_CLEANUP_HEAD_FILE, properties.getDataFileCleanupHeadFile()); + + + //remove keys with null value + configValues.values().removeIf(Objects::isNull); + + + return configValues; + } + + private Map prepareFileSystem(StorageFilesystem properties, String key) + { + Map values = new HashMap<>(); + if (properties.getSql() != null) + { + values.putAll(prepareSql(properties.getSql(), composeKey(key, ConfigKeys.SQL.value()))); + } + if (properties.getAws() != null) + { + values.putAll(prepareAws(properties.getAws(), composeKey(key, ConfigKeys.AWS.value()))); + } + if (properties.getAzure() != null) + { + values.putAll(prepareAzure(properties.getAzure(), composeKey(key, ConfigKeys.AZURE.value()))); + } + if (properties.getOraclecloud() != null) + { + values.putAll(prepareOracleCloud(properties.getOraclecloud(), composeKey(key, ConfigKeys.ORACLECLOUD.value()))); + } + if (properties.getRedis() != null) + { + values.put(ConfigKeys.REDIS_URI.value(), properties.getRedis().getUri()); + } + + + return values; + } + + private Map prepareOracleCloud(Oraclecloud oraclecloud, String key) + { + Map values = new HashMap<>(); + values.put(composeKey(key, ConfigKeys.ORACLECLOUD_CONFIG_FILE_PATH.value()), oraclecloud.getObjectStorage().getConfigFile().getPath()); + values.put(composeKey(key, ConfigKeys.ORACLECLOUD_CONFIG_FILE_PROFILE.value()), oraclecloud.getObjectStorage().getConfigFile().getProfile()); + values.put(composeKey(key, ConfigKeys.ORACLECLOUD_CONFIG_FILE_CHARSET.value()), oraclecloud.getObjectStorage().getConfigFile().getCharset()); + values.put(composeKey(key, ConfigKeys.ORACLECLOUD_CLIENT_CONNECTION_TIMEOUT_MILLIS.value()), oraclecloud.getObjectStorage().getClient().getConnectionTimeoutMillis()); + values.put(composeKey(key, ConfigKeys.ORACLECLOUD_CLIENT_READ_TIMEOUT_MILLIS.value()), oraclecloud.getObjectStorage().getClient().getReadTimeoutMillis()); + values.put(composeKey(key, ConfigKeys.ORACLECLOUD_CLIENT_MAX_ASYNC_THREADS.value()), oraclecloud.getObjectStorage().getClient().getMaxAsyncThreads()); + values.put(composeKey(key, ConfigKeys.ORACLECLOUD_REGION.value()), oraclecloud.getObjectStorage().getRegion()); + values.put(composeKey(key, ConfigKeys.ORACLECLOUD_ENDPOINT.value()), oraclecloud.getObjectStorage().getEndpoint()); + return values; + } + + + private Map prepareAzure(Azure azure, String key) + { + Map values = new HashMap<>(); + values.put(composeKey(key, ConfigKeys.AZURE_STORAGE_CONNECTION_STRING.value()), azure.getStorage().getConnectionString()); + values.put(composeKey(key, ConfigKeys.AZURE_STORAGE_ENCRYPTION_SCOPE.value()), azure.getStorage().getEncryptionScope()); + values.put(composeKey(key, ConfigKeys.AZURE_STORAGE_CREDENTIALS_TYPE.value()), azure.getStorage().getCredentials().getType()); + values.put(composeKey(key, ConfigKeys.AZURE_STORAGE_CREDENTIALS_USERNAME.value()), azure.getStorage().getCredentials().getUsername()); + values.put(composeKey(key, ConfigKeys.AZURE_STORAGE_CREDENTIALS_PASSWORD.value()), azure.getStorage().getCredentials().getPassword()); + values.put(composeKey(key, ConfigKeys.AZURE_STORAGE_CREDENTIALS_ACCOUNT_NAME.value()), azure.getStorage().getCredentials().getAccountMame()); + values.put(composeKey(key, ConfigKeys.AZURE_STORAGE_CREDENTIALS_ACCOUNT_KEY.value()), azure.getStorage().getCredentials().getAccountKey()); + return values; + } + + private Map prepareAws(Aws aws, String key) + { + Map values = new HashMap<>(); + if (aws.getDynamodb() != null) + { + values.putAll(prepareAwsProperties(aws.getDynamodb(), composeKey(key, ConfigKeys.DYNAMODB.value()))); + } + if (aws.getS3() != null) + { + values.putAll(prepareAwsProperties(aws.getS3(), composeKey(key, ConfigKeys.S3.value()))); + } + return values; + } + + + private Map prepareAwsProperties(AbstractAwsProperties awsProperties, String key) + { + Map values = new HashMap<>(); + values.put(composeKey(key, ConfigKeys.AWS_ENDPOINT_OVERRIDE.value()), awsProperties.getEndpointOverride()); + values.put(composeKey(key, ConfigKeys.AWS_REGION.value()), awsProperties.getRegion()); + values.put(composeKey(key, ConfigKeys.AWS_CREDENTIALS_TYPE.value()), awsProperties.getCredentials().getType()); + values.put(composeKey(key, ConfigKeys.AWS_CREDENTIALS_ACCESS_KEY_ID.value()), awsProperties.getCredentials().getAccessKeyId()); + values.put(composeKey(key, ConfigKeys.AWS_CREDENTIALS_SECRET_ACCESS_KEY.value()), awsProperties.getCredentials().getSecretAccessKey()); + return values; + } + + + private Map prepareSql(Sql sql, String key) + { + Map values = new HashMap<>(); + if (sql.getMariadb() != null) + { + values.putAll(prepareSqlBasic(sql.getMariadb(), composeKey(key, ConfigKeys.MARIADB.value()))); + } + if (sql.getOracle() != null) + { + values.putAll(prepareSqlBasic(sql.getOracle(), composeKey(key, ConfigKeys.ORACLE.value()))); + } + if (sql.getPostgres() != null) + { + values.putAll(prepareSqlBasic(sql.getPostgres(), composeKey(key, ConfigKeys.POSTGRES.value()))); + } + if (sql.getSqlite() != null) + { + values.putAll(prepareSqlBasic(sql.getSqlite(), composeKey(key, ConfigKeys.SQLITE.value()))); + } + + return values; + } + + private Map prepareSqlBasic(AbstractSqlConfiguration properties, String key) + { + Map values = new HashMap<>(); + values.put(composeKey(key, ConfigKeys.SQL_DATA_SOURCE_PROVIDER.value()), properties.getDataSourceProvider()); + values.put(composeKey(key, ConfigKeys.SQL_CATALOG.value()), properties.getCatalog()); + values.put(composeKey(key, ConfigKeys.SQL_SCHEMA.value()), properties.getSchema()); + values.put(composeKey(key, ConfigKeys.SQL_URL.value()), properties.getUrl()); + values.put(composeKey(key, ConfigKeys.SQL_USER.value()), properties.getUser()); + values.put(composeKey(key, ConfigKeys.SQL_PASSWORD.value()), properties.getPassword()); + return values; + } + + protected String composeKey(String prefix, String suffix) + { + return prefix + "." + suffix; + } + +} diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSpringTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSpringTest.java new file mode 100644 index 00000000..653b4024 --- /dev/null +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSpringTest.java @@ -0,0 +1,56 @@ +package org.eclipse.store.integrations.spring.boot.types; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; +import org.eclipse.store.integrations.spring.boot.types.converter.EclipseStoreConfigConverter; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; + +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestPropertySource("classpath:application-test.properties") +@SpringBootTest(classes = {EclipseStoreSpringBoot.class}) +public class EclipseConfigurationSpringTest +{ + + @Qualifier("eclipseStoreProperties") + @Autowired + EclipseStoreProperties values; + + @Autowired + EclipseStoreConfigConverter converter; + + @Test + void checkStorageDirectoryValue() + { + assertNotNull(values.getStorageDirectory()); + } + + @Test + void converterBasicTest() + { + Map valueMap = converter.convertConfigurationToMap(values); + + assertTrue(valueMap.containsKey("storage-filesystem.sql.postgres.data-source-provider")); + + } +} diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSqlSpringTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSqlSpringTest.java new file mode 100644 index 00000000..554f74ec --- /dev/null +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSqlSpringTest.java @@ -0,0 +1,54 @@ +package org.eclipse.store.integrations.spring.boot.types; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; +import org.eclipse.store.integrations.spring.boot.types.converter.EclipseStoreConfigConverter; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; + +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestPropertySource("classpath:application-sql.properties") +@SpringBootTest(classes = {EclipseStoreSpringBoot.class}) +public class EclipseConfigurationSqlSpringTest +{ + + @Qualifier("eclipseStoreProperties") + @Autowired + EclipseStoreProperties values; + + @Autowired + EclipseStoreConfigConverter converter; + + @Test + void checkStorageDirectoryValue() + { + assertNotNull(values.getStorageFilesystem()); + } + + @Test + void converterBasicTest() + { + Map valueMap = converter.convertConfigurationToMap(values); + assertTrue(valueMap.containsKey("storage-filesystem.sql.postgres.user")); + } +} diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/InjectStorageBeanTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/InjectStorageBeanTest.java new file mode 100644 index 00000000..66b76346 --- /dev/null +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/InjectStorageBeanTest.java @@ -0,0 +1,40 @@ +package org.eclipse.store.integrations.spring.boot.types; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; + +@TestPropertySource("classpath:application-run.properties") +@SpringBootTest(classes = {EclipseStoreSpringBoot.class}) +public class InjectStorageBeanTest +{ + + @Autowired + EmbeddedStorageManager manager; + + + @Test + void storeSomething() + { + manager.start(); + manager.setRoot("hello"); + manager.storeRoot(); + manager.shutdown(); + } +} diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/RestartStorageBeanTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/RestartStorageBeanTest.java new file mode 100644 index 00000000..3a55d262 --- /dev/null +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/RestartStorageBeanTest.java @@ -0,0 +1,101 @@ +package org.eclipse.store.integrations.spring.boot.types; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import org.eclipse.store.integrations.spring.boot.types.configuration.ConfigurationPair; +import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.system.ApplicationTemp; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.TestPropertySource; + +@TestPropertySource("classpath:application-run.properties") +@SpringBootTest(classes = {EclipseStoreSpringBoot.class, RestartStorageBeanTest.class}) +public class RestartStorageBeanTest +{ + + @Autowired + EclipseStoreProvider provider; + + @Qualifier("eclipseStoreProperties") + @Autowired + EclipseStoreProperties myConfiguration; + + static String tempFolder = null; + + @Bean + EmbeddedStorageManager injectStorageTest() + { + + ApplicationTemp temp = new ApplicationTemp(); + tempFolder = temp.getDir().getAbsolutePath(); + myConfiguration.setStorageDirectory(temp.getDir().getAbsolutePath()); + EmbeddedStorageFoundation storageFoundation = provider.createStorageFoundation(myConfiguration); + + return storageFoundation.createEmbeddedStorageManager(); + } + + @Test + void restartStorageTest(@Autowired EmbeddedStorageManager manager) + { + RestartRoot root = new RestartRoot("hello"); + manager.start(); + manager.setRoot(root); + manager.storeRoot(); + manager.shutdown(); + + Assertions.assertEquals(tempFolder, manager.configuration().fileProvider().baseDirectory().toPathString()); + + ConfigurationPair pair = new ConfigurationPair("someKey", "someValue"); + EmbeddedStorageFoundation storageFoundation = provider.createStorageFoundation(myConfiguration, pair); + RestartRoot root2 = new RestartRoot(); + storageFoundation.setRoot(root2); + try (EmbeddedStorageManager storage = storageFoundation.start()) + { + RestartRoot rootFromStorage = (RestartRoot) storage.root(); + Assertions.assertEquals("hello", rootFromStorage.getValue()); + } + } + + static class RestartRoot { + private String value; + + public RestartRoot(String value) + { + this.value = value; + } + + public RestartRoot() + { + } + + public String getValue() + { + return value; + } + + public void setValue(String value) + { + this.value = value; + } + } +} diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigFieldsTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigFieldsTest.java new file mode 100644 index 00000000..ff92008c --- /dev/null +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigFieldsTest.java @@ -0,0 +1,53 @@ +package org.eclipse.store.integrations.spring.boot.types.converter; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.storage.embedded.configuration.types.EmbeddedStorageConfigurationPropertyNames; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ConfigFieldsTest +{ + + /** + * Failed, when the new configuration key is present in Eclipse Store Configuration + * but not present in Spring Integration + */ + @Test + void check_all_fields_eclipse_store_in_spring_integration_present() + { + Class embeddedStorageConfigurationPropertyNames = EmbeddedStorageConfigurationPropertyNames.class; + Field[] originalFields = embeddedStorageConfigurationPropertyNames.getDeclaredFields(); + + EclipseStoreConfigConverter converter = new EclipseStoreConfigConverter(); + Field[] converterFields = converter.getClass() + .getDeclaredFields(); + + List originalFieldNames = Arrays.stream(originalFields) + .map(Field::getName) + .toList(); + + List converterFieldsNames = Arrays.stream(converterFields) + .map(Field::getName) + .toList(); + + assertTrue(converterFieldsNames.containsAll(originalFieldNames)); + } +} diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverterTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverterTest.java new file mode 100644 index 00000000..c33b22b3 --- /dev/null +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverterTest.java @@ -0,0 +1,102 @@ +package org.eclipse.store.integrations.spring.boot.types.converter; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; +import org.eclipse.store.integrations.spring.boot.types.configuration.StorageFilesystem; +import org.eclipse.store.integrations.spring.boot.types.configuration.sql.Mariadb; +import org.eclipse.store.integrations.spring.boot.types.configuration.sql.Sql; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; + +class EclipseStoreConfigConverterTest +{ + + private final EclipseStoreConfigConverter converter = new EclipseStoreConfigConverter(); + + @Test + void testBasicConversion() + { + EclipseStoreProperties properties = new EclipseStoreProperties(); + properties.setChannelCount("4"); + + EclipseStoreConfigConverter converter = new EclipseStoreConfigConverter(); + Map stringStringMap = converter.convertConfigurationToMap(properties); + + assertNotNull(stringStringMap); + assertEquals(1, stringStringMap.size()); + } + + @Test + void testSQLConfiguration() + { + final String CATALOG = "super_catalog"; + + Sql sql = new Sql(); + Mariadb mariadb = new Mariadb(); + mariadb.setCatalog(CATALOG); + mariadb.setPassword("myPssw"); + sql.setMariadb(mariadb); + StorageFilesystem storageFilesystem = new StorageFilesystem(); + storageFilesystem.setSql(sql); + EclipseStoreProperties values = new EclipseStoreProperties(); + values.setStorageFilesystem(storageFilesystem); + + EclipseStoreConfigConverter converter = new EclipseStoreConfigConverter(); + Map valueMap = converter.convertConfigurationToMap(values); + + assertTrue(valueMap.containsKey("storage-filesystem.sql.mariadb.catalog")); + assertEquals(CATALOG, valueMap.get("storage-filesystem.sql.mariadb.catalog")); + } + + @Test + void testConvertConfigurationToMap() { + EclipseStoreProperties configValues = new EclipseStoreProperties(); + Map result = converter.convertConfigurationToMap(configValues); + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + @Test + void testConvertConfigurationToMapWithStorageDirectory() { + EclipseStoreProperties configValues = new EclipseStoreProperties(); + configValues.setStorageDirectory("storage/dir"); + Map result = converter.convertConfigurationToMap(configValues); + assertNotNull(result); + assertEquals("storage/dir", result.get(EclipseStoreConfigConverter.STORAGE_DIRECTORY)); + } + + @Test + void testNullValuesAreRemoved() { + EclipseStoreProperties configValues = new EclipseStoreProperties(); + configValues.setStorageDirectory(null); + configValues.setStorageFilesystem(new StorageFilesystem()); + configValues.setBackupDirectory("backup/dir"); + + Map result = converter.convertConfigurationToMap(configValues); + + assertNull(result.get(EclipseStoreConfigConverter.STORAGE_DIRECTORY)); + assertNotNull(result.get(EclipseStoreConfigConverter.BACKUP_DIRECTORY)); + } + + @Test + void testComposeKey() { + String result = converter.composeKey("prefix", "suffix"); + assertEquals("prefix.suffix", result); + } +} diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/root/AutostartRootTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/root/AutostartRootTest.java new file mode 100644 index 00000000..3d498ba3 --- /dev/null +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/root/AutostartRootTest.java @@ -0,0 +1,39 @@ +package org.eclipse.store.integrations.spring.boot.types.root; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.integrations.spring.boot.types.EclipseStoreSpringBoot; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestPropertySource("classpath:application-autostart-root.properties") +@SpringBootTest(classes = {EclipseStoreSpringBoot.class}) +public class AutostartRootTest +{ + + @Test + void name(@Autowired EmbeddedStorageManager storage) + { + assertTrue(storage.isRunning() || storage.isStartingUp()); + + Object o = storage.root(); + assertTrue(o instanceof Root); + } +} diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/root/Root.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/root/Root.java new file mode 100644 index 00000000..e768de33 --- /dev/null +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/root/Root.java @@ -0,0 +1,19 @@ +package org.eclipse.store.integrations.spring.boot.types.root; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class Root +{ +} diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/FirstRoot.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/FirstRoot.java new file mode 100644 index 00000000..aca80eb7 --- /dev/null +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/FirstRoot.java @@ -0,0 +1,35 @@ +package org.eclipse.store.integrations.spring.boot.types.storages; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class FirstRoot +{ + private final String value = "First root value"; + + public String getValue() + { + return value; + } + + @Override + public String toString() + { + return "FirstRoot{" + + "value='" + value + '\'' + + '}'; + } + + +} diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/SecondRoot.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/SecondRoot.java new file mode 100644 index 00000000..e4a47b54 --- /dev/null +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/SecondRoot.java @@ -0,0 +1,40 @@ +package org.eclipse.store.integrations.spring.boot.types.storages; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class SecondRoot +{ + private final Integer intValue = 50; + private final char c = 'c'; + + @Override + public String toString() + { + return "SecondRoot{" + + "intValue=" + intValue + + ", c=" + c + + '}'; + } + + public Integer getIntValue() + { + return intValue; + } + + public char getC() + { + return c; + } +} diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoBeanConfiguration.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoBeanConfiguration.java new file mode 100644 index 00000000..59078bb5 --- /dev/null +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoBeanConfiguration.java @@ -0,0 +1,66 @@ +package org.eclipse.store.integrations.spring.boot.types.storages; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.integrations.spring.boot.types.EclipseStoreProvider; +import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Lazy; +import org.springframework.context.annotation.Profile; + +@TestConfiguration +public class TwoBeanConfiguration +{ + + @Autowired + private EclipseStoreProvider provider; + + @Bean("first_config") + @ConfigurationProperties("org.eclipse.store.first") + EclipseStoreProperties firstStoreProperties() + { + return new EclipseStoreProperties(); + } + + @Bean("second_config") + @ConfigurationProperties("org.eclipse.store.second") + EclipseStoreProperties secondStoreProperties() + { + return new EclipseStoreProperties(); + } + + @Bean + @Lazy + @Qualifier("first_storage") + EmbeddedStorageManager createFirstStorage(@Qualifier("first_config") EclipseStoreProperties firstStoreProperties) + { + return provider.createStorage(firstStoreProperties); + } + + @Bean + @Lazy + @Qualifier("second_storage") + EmbeddedStorageManager createSecondStorage(@Qualifier("second_config") EclipseStoreProperties secondStoreProperties) + { + return provider.createStorage(secondStoreProperties); + } + + +} diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoStoragesTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoStoragesTest.java new file mode 100644 index 00000000..f819a722 --- /dev/null +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoStoragesTest.java @@ -0,0 +1,49 @@ +package org.eclipse.store.integrations.spring.boot.types.storages; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.integrations.spring.boot.types.EclipseStoreSpringBoot; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.TestPropertySource; + +@TestPropertySource("classpath:application-two-storages.properties") +@Import(TwoBeanConfiguration.class) +@SpringBootTest(classes = {EclipseStoreSpringBoot.class, TwoStoragesTest.class}) +public class TwoStoragesTest +{ + + @Autowired + @Qualifier("first_storage") + EmbeddedStorageManager firstStorage; + + @Autowired + @Qualifier("second_storage") + EmbeddedStorageManager secondStorage; + + + @Test + void name() + { + Assertions.assertEquals("FirstRoot{value='First root value'}", firstStorage.root().toString()); + Assertions.assertEquals("SecondRoot{intValue=50, c=c}", secondStorage.root().toString()); + } + +} diff --git a/integrations/spring-boot3/src/test/resources/application-autostart-root.properties b/integrations/spring-boot3/src/test/resources/application-autostart-root.properties new file mode 100644 index 00000000..c9800b65 --- /dev/null +++ b/integrations/spring-boot3/src/test/resources/application-autostart-root.properties @@ -0,0 +1,4 @@ +debug=true +org.eclipse.store.storage-directory=${java.io.tmpdir}/${random.int} +org.eclipse.store.auto-start=true +org.eclipse.store.root=org.eclipse.store.integrations.spring.boot.types.root.Root diff --git a/integrations/spring-boot3/src/test/resources/application-run.properties b/integrations/spring-boot3/src/test/resources/application-run.properties new file mode 100644 index 00000000..92e9e479 --- /dev/null +++ b/integrations/spring-boot3/src/test/resources/application-run.properties @@ -0,0 +1,3 @@ +debug=true +org.eclipse.store.storage-directory=${java.io.tmpdir}/${random.int} +org.eclipse.store.auto-start=false diff --git a/integrations/spring-boot3/src/test/resources/application-sql.properties b/integrations/spring-boot3/src/test/resources/application-sql.properties new file mode 100644 index 00000000..58be8234 --- /dev/null +++ b/integrations/spring-boot3/src/test/resources/application-sql.properties @@ -0,0 +1,3 @@ +org.eclipse.store.storage-filesystem.sql.postgres.user=super_user +org.eclipse.store.storage-filesystem.sql.postgres.password=super_password +org.eclipse.store.auto-start=false diff --git a/integrations/spring-boot3/src/test/resources/application-test.properties b/integrations/spring-boot3/src/test/resources/application-test.properties new file mode 100644 index 00000000..fa83194e --- /dev/null +++ b/integrations/spring-boot3/src/test/resources/application-test.properties @@ -0,0 +1,6 @@ +debug=true +org.eclipse.store.storage-filesystem.sql.postgres.data-source-provider=MyDataSourceProvider +org.eclipse.store.storage-filesystem.sql.postgres.password=password1 +org.eclipse.store.storage-filesystem.sql.postgres.user=postgres +org.eclipse.store.storage-directory=microstream_storage +org.eclipse.store.auto-start=false diff --git a/integrations/spring-boot3/src/test/resources/application-two-storages.properties b/integrations/spring-boot3/src/test/resources/application-two-storages.properties new file mode 100644 index 00000000..965e1b6c --- /dev/null +++ b/integrations/spring-boot3/src/test/resources/application-two-storages.properties @@ -0,0 +1,7 @@ +org.eclipse.store.first.storage-directory=${java.io.tmpdir}/${random.int} +org.eclipse.store.first.auto-start=false +org.eclipse.store.first.root=org.eclipse.store.integrations.spring.boot.types.storages.FirstRoot + +org.eclipse.store.second.storage-directory=${java.io.tmpdir}/${random.int} +org.eclipse.store.second.auto-start=false +org.eclipse.store.second.root=org.eclipse.store.integrations.spring.boot.types.storages.SecondRoot diff --git a/integrations/spring-boot3/src/test/resources/banner.txt b/integrations/spring-boot3/src/test/resources/banner.txt new file mode 100644 index 00000000..e1101d97 --- /dev/null +++ b/integrations/spring-boot3/src/test/resources/banner.txt @@ -0,0 +1,9 @@ + + _____ _ _ _____ _ _____ _ +| ___| | (_) / ___| | / ___| (_) +| |__ ___| |_ _ __ ___ ___ \ `--.| |_ ___ _ __ ___ \ `--. _ __ _ __ _ _ __ __ _ +| __|/ __| | | '_ \/ __|/ _ \ `--. \ __/ _ \| '__/ _ \ `--. \ '_ \| '__| | '_ \ / _` | +| |__| (__| | | |_) \__ \ __/ /\__/ / || (_) | | | __/ /\__/ / |_) | | | | | | | (_| | +\____/\___|_|_| .__/|___/\___| \____/ \__\___/|_| \___| \____/| .__/|_| |_|_| |_|\__, | + | | | | __/ | + |_| |_| |___/ diff --git a/integrations/spring-boot3/src/test/resources/logback-test.xml b/integrations/spring-boot3/src/test/resources/logback-test.xml new file mode 100644 index 00000000..a79611a3 --- /dev/null +++ b/integrations/spring-boot3/src/test/resources/logback-test.xml @@ -0,0 +1,14 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n + + + + + + + diff --git a/pom.xml b/pom.xml index 41afb2e0..34779cff 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,7 @@ afs cache storage + integrations @@ -95,7 +96,7 @@ org.slf4j slf4j-api - 1.7.32 + 2.0.9 org.junit.jupiter From 911234cef4401b152ce5fe84948d6de33848f79e Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 12 Dec 2023 13:21:35 +0100 Subject: [PATCH 026/126] fix serializer version --- examples/layered-entities/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/layered-entities/pom.xml b/examples/layered-entities/pom.xml index 98aff01f..2741456c 100644 --- a/examples/layered-entities/pom.xml +++ b/examples/layered-entities/pom.xml @@ -24,12 +24,12 @@ org.eclipse.serializer base - 1.1.0-SNAPSHOT + ${eclipse.serializer.version} org.eclipse.serializer codegen-entity - 1.1.0-SNAPSHOT + ${eclipse.serializer.version} From a74a4756d2c4024218b1fbaa653fb5a1bc062b0a Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 12 Dec 2023 15:27:42 +0100 Subject: [PATCH 027/126] add housekeeping adaptive configuration --- .../misc/pages/integrations/spring-boot.adoc | 10 ++ .../pages/configuration/properties.adoc | 2 +- integrations/spring-boot3/pom.xml | 6 + .../src/main/java/module-info.java | 1 + .../boot/types/EclipseStoreProviderImpl.java | 8 +- .../configuration/EclipseStoreProperties.java | 104 +++++++++++++++++- .../EclipseStoreConfigConverter.java | 10 ++ .../types/converter/ConfigFieldsTest.java | 9 +- 8 files changed, 140 insertions(+), 10 deletions(-) diff --git a/docs/modules/misc/pages/integrations/spring-boot.adoc b/docs/modules/misc/pages/integrations/spring-boot.adoc index bf91500f..c4c5b5f2 100644 --- a/docs/modules/misc/pages/integrations/spring-boot.adoc +++ b/docs/modules/misc/pages/integrations/spring-boot.adoc @@ -202,3 +202,13 @@ to obtain all Eclipse Store configuration keys: ---- Key values containing "password" are replaced by "xxxxx". + +== Register JDK 17 and JDK 8 Handlers +Handler for JDK 17 are registered automatically. +Handler for JDK 8 are not registered automatically, because of the backwards compatibility. If you create a new storage you can enable these handlers. If you have an existing storage created with JDK8 handlers, you have to active it too. +If you need to register JDK 8 handlers, you can do it by adding the following code to your configuration: + +[source,properties] +---- +org.eclipse.store.register-jdk8-handlers=true +---- diff --git a/docs/modules/storage/pages/configuration/properties.adoc b/docs/modules/storage/pages/configuration/properties.adoc index bca89a47..96db2a23 100644 --- a/docs/modules/storage/pages/configuration/properties.adoc +++ b/docs/modules/storage/pages/configuration/properties.adoc @@ -90,7 +90,7 @@ They can be found as constants in `EmbeddedStorageConfigurationPropertyNames`. |A flag defining whether the current head file (the only file actively written to) shall be subjected to file cleanups as well. |xref:#transaction-file-maximum-size[transaction-file-maximum-size] -Maximum file size for each channels transactions log file. If this limit is exceeded the file wile be cleaned up during housekeeping. Default is 100 MiB. +|Maximum file size for each channels transactions log file. If this limit is exceeded the file wile be cleaned up during housekeeping. Default is 100 MiB. Maximum value is 1 GiB. |=== diff --git a/integrations/spring-boot3/pom.xml b/integrations/spring-boot3/pom.xml index 4c79d980..9c11d247 100644 --- a/integrations/spring-boot3/pom.xml +++ b/integrations/spring-boot3/pom.xml @@ -68,6 +68,12 @@ ${eclipse.serializer.version} + + org.eclipse.serializer + persistence-binary-jdk8 + ${eclipse.serializer.version} + + org.eclipse.store storage-embedded-configuration diff --git a/integrations/spring-boot3/src/main/java/module-info.java b/integrations/spring-boot3/src/main/java/module-info.java index a5777e35..138f04b8 100644 --- a/integrations/spring-boot3/src/main/java/module-info.java +++ b/integrations/spring-boot3/src/main/java/module-info.java @@ -34,6 +34,7 @@ requires transitive org.eclipse.serializer.configuration; requires transitive org.aspectj.weaver; requires transitive org.eclipse.serializer.persistence.binary.jdk17; + requires transitive org.eclipse.serializer.persistence.binary.jdk8; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProviderImpl.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProviderImpl.java index e7c01d4f..2c99551a 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProviderImpl.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProviderImpl.java @@ -17,6 +17,7 @@ import java.util.Map; import org.eclipse.serializer.persistence.binary.jdk17.types.BinaryHandlersJDK17; +import org.eclipse.serializer.persistence.binary.jdk8.types.BinaryHandlersJDK8; import org.eclipse.serializer.util.logging.Logging; import org.eclipse.store.integrations.spring.boot.types.configuration.ConfigurationPair; import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; @@ -46,7 +47,7 @@ public EclipseStoreProviderImpl(EclipseStoreConfigConverter converter, Applicati public EmbeddedStorageManager createStorage(EclipseStoreProperties eclipseStoreProperties, ConfigurationPair... additionalConfiguration) { EmbeddedStorageFoundation storageFoundation = createStorageFoundation(eclipseStoreProperties, additionalConfiguration); - return createStorage(storageFoundation, eclipseStoreProperties.getAutoStart()); + return createStorage(storageFoundation, eclipseStoreProperties.isAutoStart()); } @Override @@ -93,6 +94,11 @@ public EmbeddedStorageFoundation createStorageFoundation(EclipseStoreProperti storageFoundation.getConnectionFoundation() .setClassLoaderProvider(typeName -> this.applicationContext.getClassLoader()); + if (eclipseStoreProperties.isRegisterJdk8Handlers()) { + this.logger.debug("Register JDK8 handlers. "); + storageFoundation.onConnectionFoundation(BinaryHandlersJDK8::registerJDK8TypeHandlers); + } + if (eclipseStoreProperties.isRegisterJdk17Handlers()) { this.logger.debug("Register JDK17 handlers. "); storageFoundation.onConnectionFoundation(BinaryHandlersJDK17::registerJDK17TypeHandlers); diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java index 43a266dd..a6adbb97 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java @@ -15,6 +15,8 @@ */ +import java.time.Duration; + import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.context.annotation.Configuration; @@ -132,6 +134,33 @@ public class EclipseStoreProperties */ private String housekeepingTimeBudget; + /** + * Usage of an adaptive housekeeping controller, which will increase the time budgets on demand, + * if the garbage collector needs more time to reach the sweeping phase. + */ + private boolean housekeepingAdaptive = false; + + /** + * The threshold of the adaption cycle to calculate new budgets for the housekeeping process. Default is 5 seconds. + */ + private String housekeepingIncreaseThreshold; + + /** + * The amount the housekeeping budgets will be increased each cycle. Default is 50 ms. + */ + private String housekeepingIncreaseAmount; + + /** + * The upper limit of the housekeeping time budgets. Default is 0.5 seconds. + */ + private String housekeepingMaximumTimeBudget; + + /** + * The maximum size of a transaction file. If the file is larger than this value, it will be split into multiple files. + * Default is 1 GiB. + */ + private String transactionFileMaximumSize; + /** * Timeout in milliseconds for the entity cache evaluator. * If an entity was not accessed in this timespan it will be removed from the cache. Default is 1 day. @@ -177,6 +206,14 @@ public class EclipseStoreProperties */ private boolean registerJdk17Handlers = true; + /** + * Determines whether to register default handlers for JDK 1.8 classes. + * By default, this is set to false for compatibility reasons with previously created storage. + * Enabling this requires adding these handlers to your storage configuration later when used in another application with Eclipse Store. + * Default value is false. + */ + private boolean registerJdk8Handlers; + public Class getRoot() { return root; @@ -357,6 +394,56 @@ public void setHousekeepingTimeBudget(String housekeepingTimeBudget) this.housekeepingTimeBudget = housekeepingTimeBudget; } + public boolean isHousekeepingAdaptive() + { + return housekeepingAdaptive; + } + + public void setHousekeepingAdaptive(boolean housekeepingAdaptive) + { + this.housekeepingAdaptive = housekeepingAdaptive; + } + + public String getHousekeepingIncreaseThreshold() + { + return housekeepingIncreaseThreshold; + } + + public void setHousekeepingIncreaseThreshold(String housekeepingIncreaseThreshold) + { + this.housekeepingIncreaseThreshold = housekeepingIncreaseThreshold; + } + + public String getHousekeepingIncreaseAmount() + { + return housekeepingIncreaseAmount; + } + + public void setHousekeepingIncreaseAmount(String housekeepingIncreaseAmount) + { + this.housekeepingIncreaseAmount = housekeepingIncreaseAmount; + } + + public String getHousekeepingMaximumTimeBudget() + { + return housekeepingMaximumTimeBudget; + } + + public void setHousekeepingMaximumTimeBudget(String housekeepingMaximumTimeBudget) + { + this.housekeepingMaximumTimeBudget = housekeepingMaximumTimeBudget; + } + + public String getTransactionFileMaximumSize() + { + return transactionFileMaximumSize; + } + + public void setTransactionFileMaximumSize(String transactionFileMaximumSize) + { + this.transactionFileMaximumSize = transactionFileMaximumSize; + } + public String getEntityCacheTimeout() { return entityCacheTimeout; @@ -417,7 +504,7 @@ public void setDataFileCleanupHeadFile(String dataFileCleanupHeadFile) this.dataFileCleanupHeadFile = dataFileCleanupHeadFile; } - public boolean getAutoStart() + public boolean isAutoStart() { return autoStart; } @@ -427,11 +514,6 @@ public void setAutoStart(boolean autoStart) this.autoStart = autoStart; } - public boolean isAutoStart() - { - return autoStart; - } - public boolean isRegisterJdk17Handlers() { return registerJdk17Handlers; @@ -441,4 +523,14 @@ public void setRegisterJdk17Handlers(boolean registerJdk17Handlers) { this.registerJdk17Handlers = registerJdk17Handlers; } + + public boolean isRegisterJdk8Handlers() + { + return registerJdk8Handlers; + } + + public void setRegisterJdk8Handlers(boolean registerJdk8Handlers) + { + this.registerJdk8Handlers = registerJdk8Handlers; + } } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java index 3b68567f..cbd8c556 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java @@ -58,6 +58,7 @@ public class EclipseStoreConfigConverter protected static final String DATA_FILE_SUFFIX = EmbeddedStorageConfigurationPropertyNames.DATA_FILE_SUFFIX; protected static final String TRANSACTION_FILE_PREFIX = EmbeddedStorageConfigurationPropertyNames.TRANSACTION_FILE_PREFIX; protected static final String TRANSACTION_FILE_SUFFIX = EmbeddedStorageConfigurationPropertyNames.TRANSACTION_FILE_SUFFIX; + protected static final String TRANSACTION_FILE_MAXIMUM_SIZE = EmbeddedStorageConfigurationPropertyNames.TRANSACTION_FILE_MAXIMUM_SIZE; protected static final String TYPE_DICTIONARY_FILE_NAME = EmbeddedStorageConfigurationPropertyNames.TYPE_DICTIONARY_FILE_NAME; protected static final String RESCUED_FILE_SUFFIX = EmbeddedStorageConfigurationPropertyNames.RESCUED_FILE_SUFFIX; protected static final String LOCK_FILE_NAME = EmbeddedStorageConfigurationPropertyNames.LOCK_FILE_NAME; @@ -65,6 +66,10 @@ public class EclipseStoreConfigConverter // Fields for the housekeeping configuration protected static final String HOUSEKEEPING_INTERVAL = EmbeddedStorageConfigurationPropertyNames.HOUSEKEEPING_INTERVAL; protected static final String HOUSEKEEPING_TIME_BUDGET = EmbeddedStorageConfigurationPropertyNames.HOUSEKEEPING_TIME_BUDGET; + protected static final String HOUSEKEEPING_ADAPTIVE = EmbeddedStorageConfigurationPropertyNames.HOUSEKEEPING_ADAPTIVE; + protected static final String HOUSEKEEPING_INCREASE_THRESHOLD = EmbeddedStorageConfigurationPropertyNames.HOUSEKEEPING_INCREASE_THRESHOLD; + protected static final String HOUSEKEEPING_INCREASE_AMOUNT = EmbeddedStorageConfigurationPropertyNames.HOUSEKEEPING_INCREASE_AMOUNT; + protected static final String HOUSEKEEPING_MAXIMUM_TIME_BUDGET = EmbeddedStorageConfigurationPropertyNames.HOUSEKEEPING_MAXIMUM_TIME_BUDGET; // Fields for the entity cache configuration protected static final String ENTITY_CACHE_THRESHOLD = EmbeddedStorageConfigurationPropertyNames.ENTITY_CACHE_THRESHOLD; @@ -110,11 +115,16 @@ public Map convertConfigurationToMap(EclipseStoreProperties prop configValues.put(DATA_FILE_SUFFIX, properties.getDataFileSuffix()); configValues.put(TRANSACTION_FILE_PREFIX, properties.getTransactionFilePrefix()); configValues.put(TRANSACTION_FILE_SUFFIX, properties.getTransactionFileSuffix()); + configValues.put(TRANSACTION_FILE_MAXIMUM_SIZE, properties.getTransactionFileMaximumSize()); configValues.put(TYPE_DICTIONARY_FILE_NAME, properties.getTypeDictionaryFileName()); configValues.put(RESCUED_FILE_SUFFIX, properties.getRescuedFileSuffix()); configValues.put(LOCK_FILE_NAME, properties.getLockFileName()); configValues.put(HOUSEKEEPING_INTERVAL, properties.getHousekeepingInterval()); configValues.put(HOUSEKEEPING_TIME_BUDGET, properties.getHousekeepingTimeBudget()); + configValues.put(HOUSEKEEPING_ADAPTIVE, properties.isHousekeepingAdaptive() ? "true" : null); + configValues.put(HOUSEKEEPING_INCREASE_THRESHOLD, properties.getHousekeepingIncreaseThreshold()); + configValues.put(HOUSEKEEPING_INCREASE_AMOUNT, properties.getHousekeepingIncreaseAmount()); + configValues.put(HOUSEKEEPING_MAXIMUM_TIME_BUDGET, properties.getHousekeepingMaximumTimeBudget()); configValues.put(ENTITY_CACHE_THRESHOLD, properties.getEntityCacheThreshold()); configValues.put(ENTITY_CACHE_TIMEOUT, properties.getEntityCacheTimeout()); configValues.put(DATA_FILE_MINIMUM_SIZE, properties.getDataFileMinimumSize()); diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigFieldsTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigFieldsTest.java index ff92008c..12857762 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigFieldsTest.java +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigFieldsTest.java @@ -20,6 +20,7 @@ import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -42,12 +43,16 @@ void check_all_fields_eclipse_store_in_spring_integration_present() List originalFieldNames = Arrays.stream(originalFields) .map(Field::getName) - .toList(); + .collect(Collectors.toList()); List converterFieldsNames = Arrays.stream(converterFields) .map(Field::getName) .toList(); - assertTrue(converterFieldsNames.containsAll(originalFieldNames)); + //show different between original and converter + originalFieldNames.removeAll(converterFieldsNames); + + assertTrue(originalFieldNames.isEmpty(), "The following fields are missing in Eclipse Store Configuration: " + originalFieldNames); + } } From 112a5fbcb29ed2b7556e8d2b23f53183b58b540e Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Wed, 13 Dec 2023 09:31:29 +0100 Subject: [PATCH 028/126] fix format --- integrations/spring-boot3/src/main/java/module-info.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/spring-boot3/src/main/java/module-info.java b/integrations/spring-boot3/src/main/java/module-info.java index 138f04b8..26a064de 100644 --- a/integrations/spring-boot3/src/main/java/module-info.java +++ b/integrations/spring-boot3/src/main/java/module-info.java @@ -34,7 +34,7 @@ requires transitive org.eclipse.serializer.configuration; requires transitive org.aspectj.weaver; requires transitive org.eclipse.serializer.persistence.binary.jdk17; - requires transitive org.eclipse.serializer.persistence.binary.jdk8; + requires transitive org.eclipse.serializer.persistence.binary.jdk8; } From 09bb60973da5ee994f37457f6112f5523e965472 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Wed, 13 Dec 2023 10:30:53 +0100 Subject: [PATCH 029/126] fix naming + readme --- examples/spring-boot3-simple/readme.md | 14 ++++++++++---- .../boot/example/service/JokesServicesImpl.java | 4 +--- .../boot/example/storage/JokesStorageImpl.java | 6 +++--- .../src/main/resources/logback.xml | 2 +- .../spring-boot3/src/main/java/module-info.java | 2 +- .../{concurent => concurrent}/LockAspect.java | 2 +- .../types/{concurent => concurrent}/Mutex.java | 2 +- .../boot/types/{concurent => concurrent}/Read.java | 2 +- .../types/{concurent => concurrent}/Write.java | 2 +- 9 files changed, 20 insertions(+), 16 deletions(-) rename integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/{concurent => concurrent}/LockAspect.java (98%) rename integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/{concurent => concurrent}/Mutex.java (94%) rename integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/{concurent => concurrent}/Read.java (94%) rename integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/{concurent => concurrent}/Write.java (94%) diff --git a/examples/spring-boot3-simple/readme.md b/examples/spring-boot3-simple/readme.md index bbd8f018..cdbccfbd 100644 --- a/examples/spring-boot3-simple/readme.md +++ b/examples/spring-boot3-simple/readme.md @@ -1,19 +1,24 @@ # Spring Boot Eclipse Store Sample Application -This application is aimed at showcasing the capabilities of the Eclipse Store Spring Boot extension. It demonstrates how to integrate a pre-configured storage into an application as a bean, how to utilize the locking API, and how to design an MVC application using Eclipse Store. +This application serves as a comprehensive display of the Eclipse Store Spring Boot extension's functionalities. It exemplifies the seamless integration of a pre-configured storage into an application as a bean, illustrates effective utilization of the locking API, and provides insights into designing an MVC application using Eclipse Store. + +Moreover, it offers practical demonstrations on leveraging concurrent extensions within the Eclipse Store API, showcasing the implementation of annotations like `@Read` and `@Write` for optimized functionality. ## Implementation Notes * Synchronization over shared data structures is handled using the annotations `@Read` and `@Write`. * The Controller performs data conversion into JSON, therefore it must always operate with immutable data or, in the case of mutable data, it must receive a copy of such data. +* Minimum Java version is 17. +* Build tool is Maven. ## Build -The generation of the executable jar file can be performed by issuing the following command +The generation of the executable jar file can be performed by issuing the following command: ```shell mvn clean package ``` + This will create an executable jar file **spring-boot3-simple.jar** within the _target_ maven folder. This can be started by executing the following command ```shell @@ -21,13 +26,14 @@ java -jar target/spring-boot3-simple.jar ``` To launch the test page, open your browser at the following URL - ```shell http://localhost:8080/ ``` ## Using App rest api -Load sample data +This examples use Curl for Linux/MacOS. You can use any other tool for sending HTTP requests. +§ +Load sample data. Without this step, the application will not contain any data. It is not mandatory to execute this step, but without it you will have to add all your data manually. ```shell curl --location --request POST 'http://localhost:8080/init' \ --header 'Content-Type: application/json' diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServicesImpl.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServicesImpl.java index eafbd5a6..26e2809e 100644 --- a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServicesImpl.java +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServicesImpl.java @@ -14,14 +14,12 @@ * #L% */ -import org.eclipse.store.integrations.spring.boot.types.concurent.Write; +import org.eclipse.store.integrations.spring.boot.types.concurrent.Write; import org.microstream.spring.boot.example.storage.JokesStorage; import org.springframework.stereotype.Service; -import org.springframework.util.ResourceUtils; import java.io.*; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorageImpl.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorageImpl.java index d6477a7d..49a2ac6b 100644 --- a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorageImpl.java +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorageImpl.java @@ -15,9 +15,9 @@ */ import org.eclipse.serializer.persistence.types.Storer; -import org.eclipse.store.integrations.spring.boot.types.concurent.Mutex; -import org.eclipse.store.integrations.spring.boot.types.concurent.Read; -import org.eclipse.store.integrations.spring.boot.types.concurent.Write; +import org.eclipse.store.integrations.spring.boot.types.concurrent.Mutex; +import org.eclipse.store.integrations.spring.boot.types.concurrent.Read; +import org.eclipse.store.integrations.spring.boot.types.concurrent.Write; import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; import org.microstream.spring.boot.example.model.Root; import org.springframework.stereotype.Component; diff --git a/examples/spring-boot3-simple/src/main/resources/logback.xml b/examples/spring-boot3-simple/src/main/resources/logback.xml index 37599769..ae37a8f0 100644 --- a/examples/spring-boot3-simple/src/main/resources/logback.xml +++ b/examples/spring-boot3-simple/src/main/resources/logback.xml @@ -8,7 +8,7 @@ - + diff --git a/integrations/spring-boot3/src/main/java/module-info.java b/integrations/spring-boot3/src/main/java/module-info.java index 26a064de..4e10c54a 100644 --- a/integrations/spring-boot3/src/main/java/module-info.java +++ b/integrations/spring-boot3/src/main/java/module-info.java @@ -23,7 +23,7 @@ exports org.eclipse.store.integrations.spring.boot.types.configuration.sql; exports org.eclipse.store.integrations.spring.boot.types; exports org.eclipse.store.integrations.spring.boot.types.converter; - exports org.eclipse.store.integrations.spring.boot.types.concurent; + exports org.eclipse.store.integrations.spring.boot.types.concurrent; requires transitive spring.beans; requires transitive spring.boot; diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/LockAspect.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/LockAspect.java similarity index 98% rename from integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/LockAspect.java rename to integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/LockAspect.java index 62670cfa..648fcdf5 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/LockAspect.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/LockAspect.java @@ -1,4 +1,4 @@ -package org.eclipse.store.integrations.spring.boot.types.concurent; +package org.eclipse.store.integrations.spring.boot.types.concurrent; /*- * #%L diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Mutex.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Mutex.java similarity index 94% rename from integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Mutex.java rename to integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Mutex.java index 82a471b7..d6618616 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Mutex.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Mutex.java @@ -1,4 +1,4 @@ -package org.eclipse.store.integrations.spring.boot.types.concurent; +package org.eclipse.store.integrations.spring.boot.types.concurrent; /*- * #%L diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Read.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Read.java similarity index 94% rename from integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Read.java rename to integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Read.java index ced6ec72..e132bacf 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Read.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Read.java @@ -1,4 +1,4 @@ -package org.eclipse.store.integrations.spring.boot.types.concurent; +package org.eclipse.store.integrations.spring.boot.types.concurrent; /*- * #%L diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Write.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Write.java similarity index 94% rename from integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Write.java rename to integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Write.java index 0d871d38..fc655cae 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurent/Write.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Write.java @@ -1,4 +1,4 @@ -package org.eclipse.store.integrations.spring.boot.types.concurent; +package org.eclipse.store.integrations.spring.boot.types.concurrent; /*- * #%L From c52b7698a07e07dfb4684cbc73913b79798bb9da Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Wed, 13 Dec 2023 10:46:20 +0100 Subject: [PATCH 030/126] fix typo --- integrations/spring-boot3/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/spring-boot3/pom.xml b/integrations/spring-boot3/pom.xml index 9c11d247..38b6af92 100644 --- a/integrations/spring-boot3/pom.xml +++ b/integrations/spring-boot3/pom.xml @@ -10,7 +10,7 @@ ../../pom.xml - integrattions-spring-boot3 + integrations-spring-boot3 17 From 3ca91c95c8f7444d4993c4d6601cb975c19a6b63 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Wed, 13 Dec 2023 13:37:15 +0100 Subject: [PATCH 031/126] improve docu --- examples/spring-boot3-simple/readme.md | 2 -- .../spring/boot/example/controller/JokesController.java | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/spring-boot3-simple/readme.md b/examples/spring-boot3-simple/readme.md index cdbccfbd..b5fe3033 100644 --- a/examples/spring-boot3-simple/readme.md +++ b/examples/spring-boot3-simple/readme.md @@ -18,7 +18,6 @@ The generation of the executable jar file can be performed by issuing the follow mvn clean package ``` - This will create an executable jar file **spring-boot3-simple.jar** within the _target_ maven folder. This can be started by executing the following command ```shell @@ -32,7 +31,6 @@ http://localhost:8080/ ## Using App rest api This examples use Curl for Linux/MacOS. You can use any other tool for sending HTTP requests. -§ Load sample data. Without this step, the application will not contain any data. It is not mandatory to execute this step, but without it you will have to add all your data manually. ```shell curl --location --request POST 'http://localhost:8080/init' \ diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/controller/JokesController.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/controller/JokesController.java index a2f9e8e7..a36edcd2 100644 --- a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/controller/JokesController.java +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/controller/JokesController.java @@ -46,6 +46,7 @@ public class JokesController /** * Constructs a new {@code JokesController} with the provided {@code JokesServices}. + * JokesServices is a Spring component and is injected by Spring. * * @param jokesServices The services used to perform operations on jokes. */ From 43c4023f6e97e721927d2d83b0c8bc763f8c9c21 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Thu, 14 Dec 2023 10:47:29 +0100 Subject: [PATCH 032/126] add param name and update to last spring --- examples/spring-boot3-simple/pom.xml | 2 +- .../spring/boot/example/controller/JokesController.java | 2 +- integrations/spring-boot3/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/spring-boot3-simple/pom.xml b/examples/spring-boot3-simple/pom.xml index cdeb7b00..64fbea75 100644 --- a/examples/spring-boot3-simple/pom.xml +++ b/examples/spring-boot3-simple/pom.xml @@ -16,7 +16,7 @@ 17 17 UTF-8 - 3.1.5 + 3.2.0 diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/controller/JokesController.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/controller/JokesController.java index a36edcd2..12000ace 100644 --- a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/controller/JokesController.java +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/controller/JokesController.java @@ -73,7 +73,7 @@ public List getAll() * @return The joke with the specified ID. */ @GetMapping("/joke") - public String getOneJoke(@RequestParam(required = false) Integer id) + public String getOneJoke(@RequestParam(name = "id") Integer id) { return jokesServices.oneJoke(id); } diff --git a/integrations/spring-boot3/pom.xml b/integrations/spring-boot3/pom.xml index 38b6af92..a6166147 100644 --- a/integrations/spring-boot3/pom.xml +++ b/integrations/spring-boot3/pom.xml @@ -16,7 +16,7 @@ 17 17 UTF-8 - 3.1.5 + 3.2.0 From c23758408771bc98e31efe31d150e437fda0c4c6 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Thu, 14 Dec 2023 11:31:56 +0100 Subject: [PATCH 033/126] git add licences --- examples/spring-boot3-simple/LICENSE | 277 +++++++++++++++++++++++++++ integrations/LICENSE | 277 +++++++++++++++++++++++++++ integrations/spring-boot3/LICENSE | 277 +++++++++++++++++++++++++++ 3 files changed, 831 insertions(+) create mode 100644 examples/spring-boot3-simple/LICENSE create mode 100644 integrations/LICENSE create mode 100644 integrations/spring-boot3/LICENSE diff --git a/examples/spring-boot3-simple/LICENSE b/examples/spring-boot3-simple/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/spring-boot3-simple/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/integrations/LICENSE b/integrations/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/integrations/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/integrations/spring-boot3/LICENSE b/integrations/spring-boot3/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/integrations/spring-boot3/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. From ac4742f9ae2c5d143da23c164029c41efc29fac4 Mon Sep 17 00:00:00 2001 From: Michael Keppler Date: Mon, 18 Dec 2023 08:58:59 +0100 Subject: [PATCH 034/126] Fix wrong markdown (#96) The continuation operator ("+") is not valid at the beginning of a line (but rather at the end), and also not necessary in all fixed cases here. Therefore the plus character was rendered verbatim. --- .../pages/configuration/properties.adoc | 20 +++++++++---------- .../modules/storage/pages/root-instances.adoc | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/modules/storage/pages/configuration/properties.adoc b/docs/modules/storage/pages/configuration/properties.adoc index bca89a47..4e6225a6 100644 --- a/docs/modules/storage/pages/configuration/properties.adoc +++ b/docs/modules/storage/pages/configuration/properties.adoc @@ -6,8 +6,8 @@ They can be found as constants in `EmbeddedStorageConfigurationPropertyNames`. [options="header",cols="1,2"] |=== -|Property -|Short Description +|Property +|Short Description //------------- |storage-directory |The base directory of the storage in the file system. Default is `"storage"` in the working directory. @@ -16,11 +16,11 @@ They can be found as constants in `EmbeddedStorageConfigurationPropertyNames`. |The live file system configuration. See xref:storage-targets/index.adoc[storage targets] configuration. |deletion-directory -|If configured, the storage will not delete files. Instead of deleting a file it will be moved to this directory. +|If configured, the storage will not delete files. Instead of deleting a file it will be moved to this directory. |truncation-directory |If configured, files that will get truncated are copied into this directory. - + |backup-directory |The backup directory. |backup-filesystem @@ -90,7 +90,7 @@ They can be found as constants in `EmbeddedStorageConfigurationPropertyNames`. |A flag defining whether the current head file (the only file actively written to) shall be subjected to file cleanups as well. |xref:#transaction-file-maximum-size[transaction-file-maximum-size] -Maximum file size for each channels transactions log file. If this limit is exceeded the file wile be cleaned up during housekeeping. Default is 100 MiB. +Maximum file size for each channels transactions log file. If this limit is exceeded the file wile be cleaned up during housekeeping. Default is 100 MiB. Maximum value is 1 GiB. |=== @@ -142,9 +142,9 @@ Time used for each housekeeping cycle. However, no matter how low the number is, one item of work will always be completed. But if there is nothing to clean up, no processor time will be wasted. Default is `10000000` (10 million nanoseconds = 10 milliseconds = 0.01 seconds). -+ However, no matter how small the time is, one item is done at least. +However, no matter how small the time is, one item is done at least. This is to avoid no-ops, if a too small time window is configured. -+ This time budget is a "best effort" threshold, meaning when at 1ns left, a huge file has to be cleaned or the references of a huge collection have to be marked for GC, then this budget can be exceeded considerably. +This time budget is a "best effort" threshold, meaning when at 1ns left, a huge file has to be cleaned or the references of a huge collection have to be marked for GC, then this budget can be exceeded considerably. For further information see xref:configuration/housekeeping.adoc[Housekeeping]. @@ -152,13 +152,13 @@ For further information see xref:configuration/housekeeping.adoc[Housekeeping]. === data-file-minimum-size Minimum file size in bytes of a storage file to avoid merging with other files during housekeeping. -+ Must be greater than 1, maximum is 2GB. +Must be greater than 1, maximum is 2GB. [#data-file-maximum-size] === data-file-maximum-size Maximum file size in bytes of a storage file to avoid splitting in more files during housekeeping. -+ Must be greater than 1, maximum is 2GB. +Must be greater than 1, maximum is 2GB. TIP: Due to internal implementation details files larger than 2GB are not supported! @@ -178,7 +178,7 @@ for each storage files. FileCreation entries are kept, FileDeletion entries are if the storage data file still exists on the file system. Otherwise all entries related to deleted files are removed if the storage data file does no more exist. -Default is 100 MB. +Default is 100 MB. Maximum value is 1 GB. == Involved Types diff --git a/docs/modules/storage/pages/root-instances.adoc b/docs/modules/storage/pages/root-instances.adoc index abb7c773..679b004b 100644 --- a/docs/modules/storage/pages/root-instances.adoc +++ b/docs/modules/storage/pages/root-instances.adoc @@ -3,14 +3,14 @@ Object instances can be stored as simple records. One value after another as a trivial byte stream. References between objects are mapped with unique numbers, called _ObjectId_, or short _OID_. -+ With both combined, byte streams and OIDs, an object graph can be stored in a simple and quick way, as well as loaded, as a whole or partially. +With both combined, byte streams and OIDs, an object graph can be stored in a simple and quick way, as well as loaded, as a whole or partially. image::graph.png[] But there is a small catch. Where does it start? What is the first instance or reference at startup? -+ Strictly speaking "nothing". +Strictly speaking "nothing". That's why at least one instance or a reference to an instance must be registered in a special way, so that the application has a starting point from where the object graph can be loaded. This is a "Root Instance". @@ -43,7 +43,7 @@ In the most common cases, *nothing at all*. The default behavior is enough to get things going. By default, a single instance can be registered as the entity graph's root, accessible via `EmbeddedStorage.root()`. -+ Therefore, this is already a fully fledged (although tiny) database application: +Therefore, this is already a fully fledged (although tiny) database application: [source, java] ---- From 06006751983cbe4b69c0cd9472a8c191bc896a50 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Mon, 18 Dec 2023 14:07:16 +0100 Subject: [PATCH 035/126] fixes from release/1x --- docs/modules/intro/pages/system-requirements.adoc | 2 +- .../pages/storage-targets/blob-stores/azure-storage.adoc | 2 +- .../storage-targets/blob-stores/google-cloud-firestore.adoc | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/modules/intro/pages/system-requirements.adoc b/docs/modules/intro/pages/system-requirements.adoc index ea955f98..6f25ae9c 100644 --- a/docs/modules/intro/pages/system-requirements.adoc +++ b/docs/modules/intro/pages/system-requirements.adoc @@ -14,7 +14,7 @@ Tested and officially supported JDKs: | 11, 17, 21 | https://adoptium.net/[Adoptium Temurin (HotSpot / OpenJ9)] -| 11, 17 +| 11, 17, 21 | https://developers.redhat.com/products/openjdk/download/[Red Hat OpenJDK] | 11 diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/azure-storage.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/azure-storage.adoc index 729622e2..0e7390aa 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/azure-storage.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/azure-storage.adoc @@ -10,7 +10,7 @@ com.azure azure-storage-blob - 1.0.2 + 12.10.0 ---- diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/google-cloud-firestore.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/google-cloud-firestore.adoc index 2277dd7d..c55cd225 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/google-cloud-firestore.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/google-cloud-firestore.adoc @@ -10,7 +10,7 @@ com.google.cloud google-cloud-firestore - 25.0.0 + 3.0.17 ---- @@ -74,4 +74,4 @@ Returns the Application Default Credentials which are used to identify and autho |=== -CAUTION: Depending on the amount of data and transactions, charges may apply depending on service usage. Please check with your service provider for details. \ No newline at end of file +CAUTION: Depending on the amount of data and transactions, charges may apply depending on service usage. Please check with your service provider for details. From d1d46a41478fe310d27e12a266cdee353119704c Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Mon, 18 Dec 2023 14:29:40 +0100 Subject: [PATCH 036/126] adapt github actions to spring module with java 17 --- .github/workflows/maven_build.yml | 13 ++++++++++-- .github/workflows/maven_converter.yml | 2 -- .github/workflows/maven_deploy_snapshot.yml | 23 +++++++++++++++++++++ .github/workflows/maven_javadoc.yml | 8 +++---- .github/workflows/maven_release.yml | 23 +++++++++++++++++++++ integrations/spring-boot3/pom.xml | 7 +++++++ 6 files changed, 67 insertions(+), 9 deletions(-) diff --git a/.github/workflows/maven_build.yml b/.github/workflows/maven_build.yml index 23436f2d..51611580 100644 --- a/.github/workflows/maven_build.yml +++ b/.github/workflows/maven_build.yml @@ -12,9 +12,7 @@ on: jobs: build: - runs-on: ubuntu-latest - steps: #Build with java 11 - uses: actions/checkout@v3 @@ -26,3 +24,14 @@ jobs: cache: 'maven' - name: Build with Maven run: mvn -P examples -B package --file pom.xml -U + + #Build with java 17 + - uses: actions/checkout@v3 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + cache: 'maven' + - name: Build with Maven + run: mvn -P examples -B package --file pom.xml -U diff --git a/.github/workflows/maven_converter.yml b/.github/workflows/maven_converter.yml index f60e5dbc..7f03015a 100644 --- a/.github/workflows/maven_converter.yml +++ b/.github/workflows/maven_converter.yml @@ -12,9 +12,7 @@ on: jobs: build: - runs-on: ubuntu-latest - steps: #Build with java 11 - uses: actions/checkout@v2 diff --git a/.github/workflows/maven_deploy_snapshot.yml b/.github/workflows/maven_deploy_snapshot.yml index e06c0e48..bbd2351b 100644 --- a/.github/workflows/maven_deploy_snapshot.yml +++ b/.github/workflows/maven_deploy_snapshot.yml @@ -36,3 +36,26 @@ jobs: MAVEN_USERNAME: ${{ secrets.ORG_OSSRH_USERNAME }} MAVEN_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} PASSPHRASE: ${{ secrets.ORG_GPG_PASSPHRASE }} + + #java 17 build + - uses: actions/checkout@v3 + - name: Set up Java 17 for publishing to Maven Central Repository + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + cache: 'maven' + server-id: ossrh + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + gpg-passphrase: PASSPHRASE + - name: Build with java 17 + run: | + mvn -pl integrations/spring-boot3 clean install -am -B + - name: Deploy module build with java 17 + run: | + mvn -Pdeploy -pl integrations/spring-boot3 deploy + env: + MAVEN_USERNAME: ${{ secrets.ORG_OSSRH_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} + PASSPHRASE: ${{ secrets.ORG_GPG_PASSPHRASE }} diff --git a/.github/workflows/maven_javadoc.yml b/.github/workflows/maven_javadoc.yml index 795d623f..2f1dceee 100644 --- a/.github/workflows/maven_javadoc.yml +++ b/.github/workflows/maven_javadoc.yml @@ -12,16 +12,14 @@ on: jobs: build: - runs-on: ubuntu-latest - steps: - #Build with java 11 + #Build with java 17 - uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '11' + java-version: '17' distribution: 'temurin' cache: 'maven' - name: Build with Maven diff --git a/.github/workflows/maven_release.yml b/.github/workflows/maven_release.yml index cb3fb2a8..bf9bc912 100644 --- a/.github/workflows/maven_release.yml +++ b/.github/workflows/maven_release.yml @@ -35,3 +35,26 @@ jobs: MAVEN_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} PASSPHRASE: ${{ secrets.ORG_GPG_PASSPHRASE }} + #java 17 build + - uses: actions/checkout@v3 + - name: Set up Java 17 for publishing to Maven Central Repository + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + cache: 'maven' + server-id: ossrh + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + gpg-passphrase: PASSPHRASE + - name: Build with java 17 + run: | + mvn -pl integrations/spring-boot3 clean install -am -B + - name: Deploy module build with java 17 + run: | + mvn -Pdeploy -pl integrations/spring-boot3 deploy + env: + MAVEN_USERNAME: ${{ secrets.ORG_OSSRH_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} + PASSPHRASE: ${{ secrets.ORG_GPG_PASSPHRASE }} + diff --git a/integrations/spring-boot3/pom.xml b/integrations/spring-boot3/pom.xml index a6166147..db68dda6 100644 --- a/integrations/spring-boot3/pom.xml +++ b/integrations/spring-boot3/pom.xml @@ -117,6 +117,13 @@
+ + org.apache.maven.plugins + maven-javadoc-plugin + + 17 + +
From 84c27ed9b09d129b2d7b465a6704901e443b18b1 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Mon, 18 Dec 2023 14:40:15 +0100 Subject: [PATCH 037/126] remove duplicated properties --- integrations/pom.xml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/integrations/pom.xml b/integrations/pom.xml index 4da41d10..46206247 100644 --- a/integrations/pom.xml +++ b/integrations/pom.xml @@ -14,13 +14,6 @@ pom - - - 11 - 11 - UTF-8 - - from_java_17 From 8fa6e22096ffde120e509070c4dc1c92c666d869 Mon Sep 17 00:00:00 2001 From: fh-ms Date: Mon, 18 Dec 2023 14:53:34 +0100 Subject: [PATCH 038/126] Update docs --- docs/modules/misc/pages/integrations/index.adoc | 4 ++-- docs/modules/misc/pages/integrations/spring-boot.adoc | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/modules/misc/pages/integrations/index.adoc b/docs/modules/misc/pages/integrations/index.adoc index da21ab88..5d8cd800 100644 --- a/docs/modules/misc/pages/integrations/index.adoc +++ b/docs/modules/misc/pages/integrations/index.adoc @@ -1,8 +1,8 @@ = Integrations -Various Eclise Store integrations are currently available. +Various {product-name} integrations are currently available. -Integrations created by MicroStream are +Currently available integrations: - xref:misc:integrations/spring-boot.adoc[Spring Boot] diff --git a/docs/modules/misc/pages/integrations/spring-boot.adoc b/docs/modules/misc/pages/integrations/spring-boot.adoc index c4c5b5f2..eacab68e 100644 --- a/docs/modules/misc/pages/integrations/spring-boot.adoc +++ b/docs/modules/misc/pages/integrations/spring-boot.adoc @@ -2,7 +2,7 @@ image::https://upload.wikimedia.org/wikipedia/commons/4/44/Spring_Framework_Logo_2018.svg[] -Eclipse Store comes with a Spring Boot integration. +{product-name} comes with a Spring Boot integration. It is available within this artifact: [source, xml, title="pom.xml", subs=attributes+] @@ -30,7 +30,7 @@ org.eclipse.store.storage-directory=/opt/data/eclipse-store-storage org.eclipse.store.channel-count=2 ---- -The list of all Eclipse Store configuration properties and their meaning are listed on our xref:storage:configuration/properties.adoc[documentation page]. +The list of all {product-name} configuration properties and their meaning are listed on our xref:storage:configuration/properties.adoc[documentation page]. The configuration values are handled using the https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config.typesafe-configuration-properties[typesafe configuration] approach, and you can read these values by accessing the `EclipseStoreProperties` Spring bean. @@ -155,7 +155,7 @@ org.eclipse.store.second.root=org.eclipse.store.integrations.spring.boot.types.s ---- == Mutext Locking -Eclipse store supports mutex locking. This is useful if you have multiple processes that need to access the same objects. Easiest way to use it is to use the annotation `@read` and `@write` on the methods that need to be locked. The annotation @read is used for methods that only read data and @write is used for methods that modify data. +{product-name} supports mutex locking. This is useful if you have multiple processes that need to access the same objects. Easiest way to use it is to use the annotation `@read` and `@write` on the methods that need to be locked. The annotation @read is used for methods that only read data and @write is used for methods that modify data. [source,java] ---- @@ -189,9 +189,9 @@ public class JokesStorageImpl implements JokesStorage == Logging -Eclipse Store Spring module supports standard Spring logging, so you can add this into your config: +{product-name} Spring module supports standard Spring logging, so you can add this into your config: `logging.level.org.eclipse.store=debug` -to obtain all Eclipse Store configuration keys: +to obtain all {product-name} configuration keys: [source, log] ---- From df7ec9065f499a2b22509d1f5ceba69f2785c75c Mon Sep 17 00:00:00 2001 From: fh-ms Date: Mon, 18 Dec 2023 14:53:48 +0100 Subject: [PATCH 039/126] Update poms --- integrations/pom.xml | 11 ++--------- integrations/spring-boot3/pom.xml | 6 +++--- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/integrations/pom.xml b/integrations/pom.xml index 4da41d10..040afdf8 100644 --- a/integrations/pom.xml +++ b/integrations/pom.xml @@ -3,24 +3,17 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 + org.eclipse.store store-parent 1.1.0-SNAPSHOT + ../pom.xml - org.example integrations - pom - - - 11 - 11 - UTF-8 - - from_java_17 diff --git a/integrations/spring-boot3/pom.xml b/integrations/spring-boot3/pom.xml index db68dda6..a5ee9101 100644 --- a/integrations/spring-boot3/pom.xml +++ b/integrations/spring-boot3/pom.xml @@ -3,11 +3,12 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 + org.eclipse.store - store-parent + integrations 1.1.0-SNAPSHOT - ../../pom.xml + ../pom.xml integrations-spring-boot3 @@ -15,7 +16,6 @@ 17 17 - UTF-8 3.2.0 From 31efa34c3c88a54bb0c32abd5178eb496d1a98da Mon Sep 17 00:00:00 2001 From: fh-ms Date: Mon, 18 Dec 2023 14:54:33 +0100 Subject: [PATCH 040/126] Adjust code style --- .../boot/types/EclipseStoreBeanFactory.java | 4 +- .../boot/types/EclipseStoreProviderImpl.java | 30 ++-- .../boot/types/concurrent/LockAspect.java | 52 +++---- .../configuration/EclipseStoreProperties.java | 145 ++++++++---------- .../configuration/StorageFilesystem.java | 28 ++-- .../aws/AbstractAwsProperties.java | 12 +- .../types/configuration/aws/Credentials.java | 12 +- .../types/configuration/aws/Dynamodb.java | 2 - .../boot/types/configuration/aws/S3.java | 1 - .../boot/types/configuration/azure/Azure.java | 4 +- .../configuration/azure/Credentials.java | 22 +-- .../types/configuration/azure/Storage.java | 16 +- .../googlecloud/Googlecloud.java | 4 +- .../googlecloud/firestore/Credentials.java | 4 +- .../googlecloud/firestore/Firestore.java | 61 ++++++++ .../configuration/oraclecloud/Client.java | 12 +- .../configuration/oraclecloud/ConfigFile.java | 12 +- .../oraclecloud/ObjectStorage.java | 16 +- .../oraclecloud/Oraclecloud.java | 4 +- .../boot/types/configuration/redis/Redis.java | 4 +- .../sql/AbstractSqlConfiguration.java | 25 ++- .../boot/types/configuration/sql/Mariadb.java | 1 - .../boot/types/configuration/sql/Oracle.java | 1 - .../boot/types/configuration/sql/Sql.java | 16 +- .../boot/types/converter/ConfigKeys.java | 6 +- .../EclipseStoreConfigConverter.java | 110 ++++++------- .../types/EclipseConfigurationSpringTest.java | 14 +- .../EclipseConfigurationSqlSpringTest.java | 14 +- .../boot/types/InjectStorageBeanTest.java | 8 +- .../boot/types/RestartStorageBeanTest.java | 24 +-- .../EclipseStoreConfigConverterTest.java | 43 +++--- .../spring/boot/types/storages/FirstRoot.java | 4 +- .../boot/types/storages/SecondRoot.java | 8 +- .../types/storages/TwoBeanConfiguration.java | 9 +- .../boot/types/storages/TwoStoragesTest.java | 4 +- 35 files changed, 386 insertions(+), 346 deletions(-) diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreBeanFactory.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreBeanFactory.java index 8827ec4d..01f70e70 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreBeanFactory.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreBeanFactory.java @@ -38,7 +38,7 @@ public class EclipseStoreBeanFactory * @param eclipseStoreProvider The provider used to create {@code EmbeddedStorageManager} instances. * @param eclipseStoreProperties The properties used to configure the {@code EmbeddedStorageManager}. */ - public EclipseStoreBeanFactory(EclipseStoreProvider eclipseStoreProvider, EclipseStoreProperties eclipseStoreProperties) + public EclipseStoreBeanFactory(final EclipseStoreProvider eclipseStoreProvider, final EclipseStoreProperties eclipseStoreProperties) { this.eclipseStoreProvider = eclipseStoreProvider; this.eclipseStoreProperties = eclipseStoreProperties; @@ -56,7 +56,7 @@ public EclipseStoreBeanFactory(EclipseStoreProvider eclipseStoreProvider, Eclips @Lazy public EmbeddedStorageManager embeddedStorageManager() { - return eclipseStoreProvider.createStorage(eclipseStoreProperties); + return this.eclipseStoreProvider.createStorage(this.eclipseStoreProperties); } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProviderImpl.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProviderImpl.java index 2c99551a..a91d1849 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProviderImpl.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProviderImpl.java @@ -37,23 +37,23 @@ public class EclipseStoreProviderImpl implements EclipseStoreProvider private final Logger logger = Logging.getLogger(EclipseStoreProviderImpl.class); - public EclipseStoreProviderImpl(EclipseStoreConfigConverter converter, ApplicationContext applicationContext) + public EclipseStoreProviderImpl(final EclipseStoreConfigConverter converter, final ApplicationContext applicationContext) { this.converter = converter; this.applicationContext = applicationContext; } @Override - public EmbeddedStorageManager createStorage(EclipseStoreProperties eclipseStoreProperties, ConfigurationPair... additionalConfiguration) + public EmbeddedStorageManager createStorage(final EclipseStoreProperties eclipseStoreProperties, final ConfigurationPair... additionalConfiguration) { - EmbeddedStorageFoundation storageFoundation = createStorageFoundation(eclipseStoreProperties, additionalConfiguration); - return createStorage(storageFoundation, eclipseStoreProperties.isAutoStart()); + final EmbeddedStorageFoundation storageFoundation = this.createStorageFoundation(eclipseStoreProperties, additionalConfiguration); + return this.createStorage(storageFoundation, eclipseStoreProperties.isAutoStart()); } @Override - public EmbeddedStorageManager createStorage(EmbeddedStorageFoundation foundation, boolean autoStart) + public EmbeddedStorageManager createStorage(final EmbeddedStorageFoundation foundation, final boolean autoStart) { - EmbeddedStorageManager storageManager = foundation.createEmbeddedStorageManager(); + final EmbeddedStorageManager storageManager = foundation.createEmbeddedStorageManager(); if (autoStart) { storageManager.start(); @@ -62,12 +62,12 @@ public EmbeddedStorageManager createStorage(EmbeddedStorageFoundation foundat } @Override - public EmbeddedStorageFoundation createStorageFoundation(EclipseStoreProperties eclipseStoreProperties, ConfigurationPair... additionalConfiguration) + public EmbeddedStorageFoundation createStorageFoundation(final EclipseStoreProperties eclipseStoreProperties, final ConfigurationPair... additionalConfiguration) { final EmbeddedStorageConfigurationBuilder builder = EmbeddedStorageConfigurationBuilder.New(); - Map valueMap = converter.convertConfigurationToMap(eclipseStoreProperties); - for (ConfigurationPair pair : additionalConfiguration) { + final Map valueMap = this.converter.convertConfigurationToMap(eclipseStoreProperties); + for (final ConfigurationPair pair : additionalConfiguration) { valueMap.put(pair.key(), pair.value()); } @@ -76,15 +76,15 @@ public EmbeddedStorageFoundation createStorageFoundation(EclipseStoreProperti { if (value != null) { - String logValue = key.contains("password") ? "xxxxxx" : value; + final String logValue = key.contains("password") ? "xxxxxx" : value; this.logger.debug(key + " : " + logValue); builder.set(key, value); } }); - EmbeddedStorageFoundation storageFoundation = builder.createEmbeddedStorageFoundation(); + final EmbeddedStorageFoundation storageFoundation = builder.createEmbeddedStorageFoundation(); - Object root = provideRoot(eclipseStoreProperties); + final Object root = this.provideRoot(eclipseStoreProperties); if (root != null) { this.logger.debug("Root object: " + root.getClass().getName()); @@ -107,9 +107,9 @@ public EmbeddedStorageFoundation createStorageFoundation(EclipseStoreProperti return storageFoundation; } - private Object provideRoot(EclipseStoreProperties properties) + private Object provideRoot(final EclipseStoreProperties properties) { - Class rootClass = properties.getRoot(); + final Class rootClass = properties.getRoot(); if (rootClass == null) { return null; @@ -117,7 +117,7 @@ private Object provideRoot(EclipseStoreProperties properties) try { return rootClass.getDeclaredConstructor().newInstance(); - } catch (Exception e) + } catch (final Exception e) { throw new RuntimeException("Failed to instantiate class: " + rootClass, e); } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/LockAspect.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/LockAspect.java index 648fcdf5..92429e7e 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/LockAspect.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/LockAspect.java @@ -57,11 +57,11 @@ public class LockAspect * @throws Throwable If the method call throws an exception. */ @Around("@annotation(Read)") - public Object readOperation(ProceedingJoinPoint joinPoint) throws Throwable + public Object readOperation(final ProceedingJoinPoint joinPoint) throws Throwable { - ReentrantReadWriteLock lock = this.findLock(joinPoint); + final ReentrantReadWriteLock lock = this.findLock(joinPoint); lock.readLock().lock(); - logger.trace("lock readLock"); + this.logger.trace("lock readLock"); Object proceed; try { @@ -69,7 +69,7 @@ public Object readOperation(ProceedingJoinPoint joinPoint) throws Throwable } finally { lock.readLock().unlock(); - logger.trace("unlock readLock"); + this.logger.trace("unlock readLock"); } return proceed; } @@ -82,11 +82,11 @@ public Object readOperation(ProceedingJoinPoint joinPoint) throws Throwable * @throws Throwable If the method call throws an exception. */ @Around("@annotation(Write)") - public Object writeOperation(ProceedingJoinPoint joinPoint) throws Throwable + public Object writeOperation(final ProceedingJoinPoint joinPoint) throws Throwable { - ReentrantReadWriteLock lock = this.findLock(joinPoint); + final ReentrantReadWriteLock lock = this.findLock(joinPoint); lock.writeLock().lock(); - logger.trace("write lock"); + this.logger.trace("write lock"); Object proceed; try @@ -95,7 +95,7 @@ public Object writeOperation(ProceedingJoinPoint joinPoint) throws Throwable } finally { lock.writeLock().unlock(); - logger.trace("write unlock"); + this.logger.trace("write unlock"); } return proceed; @@ -109,34 +109,34 @@ public Object writeOperation(ProceedingJoinPoint joinPoint) throws Throwable * @param joinPoint The join point representing the method call. * @return The lock to be used. */ - private ReentrantReadWriteLock findLock(ProceedingJoinPoint joinPoint) + private ReentrantReadWriteLock findLock(final ProceedingJoinPoint joinPoint) { - MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); - Method method = methodSignature.getMethod(); + final MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + final Method method = methodSignature.getMethod(); //method annotation first ReentrantReadWriteLock finalLock; - Mutex annotation = method.getAnnotation(Mutex.class); + final Mutex annotation = method.getAnnotation(Mutex.class); if (annotation != null) { - String lockName = annotation.value(); - logger.trace("Found method lock annotation for lock: {}", lockName); - finalLock = getOrCreateLock(lockName); + final String lockName = annotation.value(); + this.logger.trace("Found method lock annotation for lock: {}", lockName); + finalLock = this.getOrCreateLock(lockName); } else { //class annotation second - Class declaringClass = method.getDeclaringClass(); - Mutex classAnnotation = declaringClass.getAnnotation(Mutex.class); + final Class declaringClass = method.getDeclaringClass(); + final Mutex classAnnotation = declaringClass.getAnnotation(Mutex.class); if (classAnnotation != null) { - String classLockName = classAnnotation.value(); - logger.trace("Found class lock annotation for lock: {}", classLockName); - finalLock = getOrCreateLock(classLockName); + final String classLockName = classAnnotation.value(); + this.logger.trace("Found class lock annotation for lock: {}", classLockName); + finalLock = this.getOrCreateLock(classLockName); } else { // no annotation, use global lock - logger.trace("Found no @Lockable annotation, use global lock"); - finalLock = globalLock; + this.logger.trace("Found no @Lockable annotation, use global lock"); + finalLock = this.globalLock; } } return finalLock; @@ -148,9 +148,9 @@ private ReentrantReadWriteLock findLock(ProceedingJoinPoint joinPoint) * @param lockName The name of the lock. * @return The named lock. */ - private ReentrantReadWriteLock getOrCreateLock(String lockName) { - return locks.computeIfAbsent(lockName, k -> { - logger.trace("Lock for name: {} not found, creating a new one", lockName); + private ReentrantReadWriteLock getOrCreateLock(final String lockName) { + return this.locks.computeIfAbsent(lockName, k -> { + this.logger.trace("Lock for name: {} not found, creating a new one", lockName); return new ReentrantReadWriteLock(); }); } @@ -162,7 +162,7 @@ private ReentrantReadWriteLock getOrCreateLock(String lockName) { static class AspectJCondition implements Condition { @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) { return ClassUtils.isPresent("org.aspectj.lang.ProceedingJoinPoint", context.getClassLoader()); } } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java index a6adbb97..86c29428 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java @@ -1,22 +1,5 @@ package org.eclipse.store.integrations.spring.boot.types.configuration; -/*- - * #%L - * spring-boot3 - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ - - -import java.time.Duration; - import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.context.annotation.Configuration; @@ -216,320 +199,320 @@ public class EclipseStoreProperties public Class getRoot() { - return root; + return this.root; } - public void setRoot(Class root) + public void setRoot(final Class root) { this.root = root; } public String getStorageDirectory() { - return storageDirectory; + return this.storageDirectory; } - public void setStorageDirectory(String storageDirectory) + public void setStorageDirectory(final String storageDirectory) { this.storageDirectory = storageDirectory; } public StorageFilesystem getStorageFilesystem() { - return storageFilesystem; + return this.storageFilesystem; } - public void setStorageFilesystem(StorageFilesystem storageFilesystem) + public void setStorageFilesystem(final StorageFilesystem storageFilesystem) { this.storageFilesystem = storageFilesystem; } public String getDeletionDirectory() { - return deletionDirectory; + return this.deletionDirectory; } - public void setDeletionDirectory(String deletionDirectory) + public void setDeletionDirectory(final String deletionDirectory) { this.deletionDirectory = deletionDirectory; } public String getTruncationDirectory() { - return truncationDirectory; + return this.truncationDirectory; } - public void setTruncationDirectory(String truncationDirectory) + public void setTruncationDirectory(final String truncationDirectory) { this.truncationDirectory = truncationDirectory; } public String getBackupDirectory() { - return backupDirectory; + return this.backupDirectory; } - public void setBackupDirectory(String backupDirectory) + public void setBackupDirectory(final String backupDirectory) { this.backupDirectory = backupDirectory; } public StorageFilesystem getBackupFilesystem() { - return backupFilesystem; + return this.backupFilesystem; } - public void setBackupFilesystem(StorageFilesystem backupFilesystem) + public void setBackupFilesystem(final StorageFilesystem backupFilesystem) { this.backupFilesystem = backupFilesystem; } public String getChannelCount() { - return channelCount; + return this.channelCount; } - public void setChannelCount(String channelCount) + public void setChannelCount(final String channelCount) { this.channelCount = channelCount; } public String getChannelDirectoryPrefix() { - return channelDirectoryPrefix; + return this.channelDirectoryPrefix; } - public void setChannelDirectoryPrefix(String channelDirectoryPrefix) + public void setChannelDirectoryPrefix(final String channelDirectoryPrefix) { this.channelDirectoryPrefix = channelDirectoryPrefix; } public String getDataFilePrefix() { - return dataFilePrefix; + return this.dataFilePrefix; } - public void setDataFilePrefix(String dataFilePrefix) + public void setDataFilePrefix(final String dataFilePrefix) { this.dataFilePrefix = dataFilePrefix; } public String getDataFileSuffix() { - return dataFileSuffix; + return this.dataFileSuffix; } - public void setDataFileSuffix(String dataFileSuffix) + public void setDataFileSuffix(final String dataFileSuffix) { this.dataFileSuffix = dataFileSuffix; } public String getTransactionFilePrefix() { - return transactionFilePrefix; + return this.transactionFilePrefix; } - public void setTransactionFilePrefix(String transactionFilePrefix) + public void setTransactionFilePrefix(final String transactionFilePrefix) { this.transactionFilePrefix = transactionFilePrefix; } public String getTransactionFileSuffix() { - return transactionFileSuffix; + return this.transactionFileSuffix; } - public void setTransactionFileSuffix(String transactionFileSuffix) + public void setTransactionFileSuffix(final String transactionFileSuffix) { this.transactionFileSuffix = transactionFileSuffix; } public String getTypeDictionaryFileName() { - return typeDictionaryFileName; + return this.typeDictionaryFileName; } - public void setTypeDictionaryFileName(String typeDictionaryFileName) + public void setTypeDictionaryFileName(final String typeDictionaryFileName) { this.typeDictionaryFileName = typeDictionaryFileName; } public String getRescuedFileSuffix() { - return rescuedFileSuffix; + return this.rescuedFileSuffix; } - public void setRescuedFileSuffix(String rescuedFileSuffix) + public void setRescuedFileSuffix(final String rescuedFileSuffix) { this.rescuedFileSuffix = rescuedFileSuffix; } public String getLockFileName() { - return lockFileName; + return this.lockFileName; } - public void setLockFileName(String lockFileName) + public void setLockFileName(final String lockFileName) { this.lockFileName = lockFileName; } public String getHousekeepingInterval() { - return housekeepingInterval; + return this.housekeepingInterval; } - public void setHousekeepingInterval(String housekeepingInterval) + public void setHousekeepingInterval(final String housekeepingInterval) { this.housekeepingInterval = housekeepingInterval; } public String getHousekeepingTimeBudget() { - return housekeepingTimeBudget; + return this.housekeepingTimeBudget; } - public void setHousekeepingTimeBudget(String housekeepingTimeBudget) + public void setHousekeepingTimeBudget(final String housekeepingTimeBudget) { this.housekeepingTimeBudget = housekeepingTimeBudget; } public boolean isHousekeepingAdaptive() { - return housekeepingAdaptive; + return this.housekeepingAdaptive; } - public void setHousekeepingAdaptive(boolean housekeepingAdaptive) + public void setHousekeepingAdaptive(final boolean housekeepingAdaptive) { this.housekeepingAdaptive = housekeepingAdaptive; } public String getHousekeepingIncreaseThreshold() { - return housekeepingIncreaseThreshold; + return this.housekeepingIncreaseThreshold; } - public void setHousekeepingIncreaseThreshold(String housekeepingIncreaseThreshold) + public void setHousekeepingIncreaseThreshold(final String housekeepingIncreaseThreshold) { this.housekeepingIncreaseThreshold = housekeepingIncreaseThreshold; } public String getHousekeepingIncreaseAmount() { - return housekeepingIncreaseAmount; + return this.housekeepingIncreaseAmount; } - public void setHousekeepingIncreaseAmount(String housekeepingIncreaseAmount) + public void setHousekeepingIncreaseAmount(final String housekeepingIncreaseAmount) { this.housekeepingIncreaseAmount = housekeepingIncreaseAmount; } public String getHousekeepingMaximumTimeBudget() { - return housekeepingMaximumTimeBudget; + return this.housekeepingMaximumTimeBudget; } - public void setHousekeepingMaximumTimeBudget(String housekeepingMaximumTimeBudget) + public void setHousekeepingMaximumTimeBudget(final String housekeepingMaximumTimeBudget) { this.housekeepingMaximumTimeBudget = housekeepingMaximumTimeBudget; } public String getTransactionFileMaximumSize() { - return transactionFileMaximumSize; + return this.transactionFileMaximumSize; } - public void setTransactionFileMaximumSize(String transactionFileMaximumSize) + public void setTransactionFileMaximumSize(final String transactionFileMaximumSize) { this.transactionFileMaximumSize = transactionFileMaximumSize; } public String getEntityCacheTimeout() { - return entityCacheTimeout; + return this.entityCacheTimeout; } - public void setEntityCacheTimeout(String entityCacheTimeout) + public void setEntityCacheTimeout(final String entityCacheTimeout) { this.entityCacheTimeout = entityCacheTimeout; } public String getEntityCacheThreshold() { - return entityCacheThreshold; + return this.entityCacheThreshold; } - public void setEntityCacheThreshold(String entityCacheThreshold) + public void setEntityCacheThreshold(final String entityCacheThreshold) { this.entityCacheThreshold = entityCacheThreshold; } public String getDataFileMinimumSize() { - return dataFileMinimumSize; + return this.dataFileMinimumSize; } - public void setDataFileMinimumSize(String dataFileMinimumSize) + public void setDataFileMinimumSize(final String dataFileMinimumSize) { this.dataFileMinimumSize = dataFileMinimumSize; } public String getDataFileMaximumSize() { - return dataFileMaximumSize; + return this.dataFileMaximumSize; } - public void setDataFileMaximumSize(String dataFileMaximumSize) + public void setDataFileMaximumSize(final String dataFileMaximumSize) { this.dataFileMaximumSize = dataFileMaximumSize; } public String getDataFileMinimumUseRatio() { - return dataFileMinimumUseRatio; + return this.dataFileMinimumUseRatio; } - public void setDataFileMinimumUseRatio(String dataFileMinimumUseRatio) + public void setDataFileMinimumUseRatio(final String dataFileMinimumUseRatio) { this.dataFileMinimumUseRatio = dataFileMinimumUseRatio; } public String getDataFileCleanupHeadFile() { - return dataFileCleanupHeadFile; + return this.dataFileCleanupHeadFile; } - public void setDataFileCleanupHeadFile(String dataFileCleanupHeadFile) + public void setDataFileCleanupHeadFile(final String dataFileCleanupHeadFile) { this.dataFileCleanupHeadFile = dataFileCleanupHeadFile; } public boolean isAutoStart() { - return autoStart; + return this.autoStart; } - public void setAutoStart(boolean autoStart) + public void setAutoStart(final boolean autoStart) { this.autoStart = autoStart; } public boolean isRegisterJdk17Handlers() { - return registerJdk17Handlers; + return this.registerJdk17Handlers; } - public void setRegisterJdk17Handlers(boolean registerJdk17Handlers) + public void setRegisterJdk17Handlers(final boolean registerJdk17Handlers) { this.registerJdk17Handlers = registerJdk17Handlers; } public boolean isRegisterJdk8Handlers() { - return registerJdk8Handlers; + return this.registerJdk8Handlers; } - public void setRegisterJdk8Handlers(boolean registerJdk8Handlers) + public void setRegisterJdk8Handlers(final boolean registerJdk8Handlers) { this.registerJdk8Handlers = registerJdk8Handlers; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/StorageFilesystem.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/StorageFilesystem.java index 91853586..30936066 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/StorageFilesystem.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/StorageFilesystem.java @@ -54,70 +54,70 @@ public class StorageFilesystem public Sql getSql() { - return sql; + return this.sql; } - public void setSql(Sql sql) + public void setSql(final Sql sql) { this.sql = sql; } public Aws getAws() { - return aws; + return this.aws; } - public void setAws(Aws aws) + public void setAws(final Aws aws) { this.aws = aws; } public Map getKafkaProperties() { - return kafkaProperties; + return this.kafkaProperties; } - public void setKafkaProperties(Map kafkaProperties) + public void setKafkaProperties(final Map kafkaProperties) { this.kafkaProperties = kafkaProperties; } public Oraclecloud getOraclecloud() { - return oraclecloud; + return this.oraclecloud; } - public void setOraclecloud(Oraclecloud oraclecloud) + public void setOraclecloud(final Oraclecloud oraclecloud) { this.oraclecloud = oraclecloud; } public Redis getRedis() { - return redis; + return this.redis; } - public void setRedis(Redis redis) + public void setRedis(final Redis redis) { this.redis = redis; } public Azure getAzure() { - return azure; + return this.azure; } - public void setAzure(Azure azure) + public void setAzure(final Azure azure) { this.azure = azure; } public Googlecloud getGooglecloud() { - return googlecloud; + return this.googlecloud; } - public void setGooglecloud(Googlecloud googlecloud) + public void setGooglecloud(final Googlecloud googlecloud) { this.googlecloud = googlecloud; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/AbstractAwsProperties.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/AbstractAwsProperties.java index 67f46f8f..168461dd 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/AbstractAwsProperties.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/AbstractAwsProperties.java @@ -41,30 +41,30 @@ public abstract class AbstractAwsProperties public Credentials getCredentials() { - return credentials; + return this.credentials; } - public void setCredentials(Credentials credentials) + public void setCredentials(final Credentials credentials) { this.credentials = credentials; } public String getEndpointOverride() { - return endpointOverride; + return this.endpointOverride; } - public void setEndpointOverride(String endpointOverride) + public void setEndpointOverride(final String endpointOverride) { this.endpointOverride = endpointOverride; } public String getRegion() { - return region; + return this.region; } - public void setRegion(String region) + public void setRegion(final String region) { this.region = region; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Credentials.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Credentials.java index 956ecbfa..5f137d25 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Credentials.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Credentials.java @@ -49,30 +49,30 @@ public class Credentials public String getType() { - return type; + return this.type; } - public void setType(String type) + public void setType(final String type) { this.type = type; } public String getAccessKeyId() { - return accessKeyId; + return this.accessKeyId; } - public void setAccessKeyId(String accessKeyId) + public void setAccessKeyId(final String accessKeyId) { this.accessKeyId = accessKeyId; } public String getSecretAccessKey() { - return secretAccessKey; + return this.secretAccessKey; } - public void setSecretAccessKey(String secretAccessKey) + public void setSecretAccessKey(final String secretAccessKey) { this.secretAccessKey = secretAccessKey; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Dynamodb.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Dynamodb.java index b32119ce..40f8c44a 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Dynamodb.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Dynamodb.java @@ -16,6 +16,4 @@ public class Dynamodb extends AbstractAwsProperties { - - } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/S3.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/S3.java index 7a2a91ae..3cd25e07 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/S3.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/S3.java @@ -16,5 +16,4 @@ public class S3 extends AbstractAwsProperties { - } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Azure.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Azure.java index 4beb5251..2275a339 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Azure.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Azure.java @@ -24,10 +24,10 @@ public class Azure public Storage getStorage() { - return storage; + return this.storage; } - public void setStorage(Storage storage) + public void setStorage(final Storage storage) { this.storage = storage; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Credentials.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Credentials.java index a04c8f0b..7a0f361b 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Credentials.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Credentials.java @@ -16,7 +16,7 @@ public class Credentials { - + /** * The type of the credentials provider. Supported values are: *
    @@ -51,50 +51,50 @@ public class Credentials public String getType() { - return type; + return this.type; } - public void setType(String type) + public void setType(final String type) { this.type = type; } public String getUsername() { - return username; + return this.username; } - public void setUsername(String username) + public void setUsername(final String username) { this.username = username; } public String getPassword() { - return password; + return this.password; } - public void setPassword(String password) + public void setPassword(final String password) { this.password = password; } public String getAccountMame() { - return accountMame; + return this.accountMame; } - public void setAccountMame(String accountMame) + public void setAccountMame(final String accountMame) { this.accountMame = accountMame; } public String getAccountKey() { - return accountKey; + return this.accountKey; } - public void setAccountKey(String accountKey) + public void setAccountKey(final String accountKey) { this.accountKey = accountKey; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Storage.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Storage.java index 7e830c73..248f4038 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Storage.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Storage.java @@ -39,40 +39,40 @@ public class Storage public Credentials getCredentials() { - return credentials; + return this.credentials; } - public void setCredentials(Credentials credentials) + public void setCredentials(final Credentials credentials) { this.credentials = credentials; } public String getEndpoint() { - return endpoint; + return this.endpoint; } - public void setEndpoint(String endpoint) + public void setEndpoint(final String endpoint) { this.endpoint = endpoint; } public String getConnectionString() { - return connectionString; + return this.connectionString; } - public void setConnectionString(String connectionString) + public void setConnectionString(final String connectionString) { this.connectionString = connectionString; } public String getEncryptionScope() { - return encryptionScope; + return this.encryptionScope; } - public void setEncryptionScope(String encryptionScope) + public void setEncryptionScope(final String encryptionScope) { this.encryptionScope = encryptionScope; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/Googlecloud.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/Googlecloud.java index c98cdc0b..11b6fda2 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/Googlecloud.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/Googlecloud.java @@ -24,10 +24,10 @@ public class Googlecloud public Firestore getFirestore() { - return firestore; + return this.firestore; } - public void setFirestore(Firestore firestore) + public void setFirestore(final Firestore firestore) { this.firestore = firestore; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Credentials.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Credentials.java index 2c20da31..543a783b 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Credentials.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Credentials.java @@ -41,10 +41,10 @@ public class Credentials public String getType() { - return type; + return this.type; } - public void setType(String type) + public void setType(final String type) { this.type = type; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Firestore.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Firestore.java index 735fc966..b086cb0b 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Firestore.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Firestore.java @@ -47,4 +47,65 @@ public class Firestore @NestedConfigurationProperty private Credentials credentials; + + public String getDatabaseId() + { + return this.databaseId; + } + + public void setDatabaseId(final String databaseId) + { + this.databaseId = databaseId; + } + + public String getEmulatorHost() + { + return this.emulatorHost; + } + + public void setEmulatorHost(final String emulatorHost) + { + this.emulatorHost = emulatorHost; + } + + public String getHost() + { + return this.host; + } + + public void setHost(final String host) + { + this.host = host; + } + + public String getProjectId() + { + return this.projectId; + } + + public void setProjectId(final String projectId) + { + this.projectId = projectId; + } + + public String getQuotaProjectId() + { + return this.quotaProjectId; + } + + public void setQuotaProjectId(final String quotaProjectId) + { + this.quotaProjectId = quotaProjectId; + } + + public Credentials getCredentials() + { + return this.credentials; + } + + public void setCredentials(final Credentials credentials) + { + this.credentials = credentials; + } + } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Client.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Client.java index ac5fba03..2bdb1f57 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Client.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Client.java @@ -34,30 +34,30 @@ public class Client public String getConnectionTimeoutMillis() { - return connectionTimeoutMillis; + return this.connectionTimeoutMillis; } - public void setConnectionTimeoutMillis(String connectionTimeoutMillis) + public void setConnectionTimeoutMillis(final String connectionTimeoutMillis) { this.connectionTimeoutMillis = connectionTimeoutMillis; } public String getReadTimeoutMillis() { - return readTimeoutMillis; + return this.readTimeoutMillis; } - public void setReadTimeoutMillis(String readTimeoutMillis) + public void setReadTimeoutMillis(final String readTimeoutMillis) { this.readTimeoutMillis = readTimeoutMillis; } public String getMaxAsyncThreads() { - return maxAsyncThreads; + return this.maxAsyncThreads; } - public void setMaxAsyncThreads(String maxAsyncThreads) + public void setMaxAsyncThreads(final String maxAsyncThreads) { this.maxAsyncThreads = maxAsyncThreads; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ConfigFile.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ConfigFile.java index abfe9f9e..dfec8db5 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ConfigFile.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ConfigFile.java @@ -34,30 +34,30 @@ public class ConfigFile public String getPath() { - return path; + return this.path; } - public void setPath(String path) + public void setPath(final String path) { this.path = path; } public String getProfile() { - return profile; + return this.profile; } - public void setProfile(String profile) + public void setProfile(final String profile) { this.profile = profile; } public String getCharset() { - return charset; + return this.charset; } - public void setCharset(String charset) + public void setCharset(final String charset) { this.charset = charset; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ObjectStorage.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ObjectStorage.java index ddd3e38d..eec065e3 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ObjectStorage.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ObjectStorage.java @@ -37,40 +37,40 @@ public class ObjectStorage public ConfigFile getConfigFile() { - return configFile; + return this.configFile; } - public void setConfigFile(ConfigFile configFile) + public void setConfigFile(final ConfigFile configFile) { this.configFile = configFile; } public Client getClient() { - return client; + return this.client; } - public void setClient(Client client) + public void setClient(final Client client) { this.client = client; } public String getRegion() { - return region; + return this.region; } - public void setRegion(String region) + public void setRegion(final String region) { this.region = region; } public String getEndpoint() { - return endpoint; + return this.endpoint; } - public void setEndpoint(String endpoint) + public void setEndpoint(final String endpoint) { this.endpoint = endpoint; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Oraclecloud.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Oraclecloud.java index 6aa052da..39e808ef 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Oraclecloud.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Oraclecloud.java @@ -24,10 +24,10 @@ public class Oraclecloud public ObjectStorage getObjectStorage() { - return objectStorage; + return this.objectStorage; } - public void setObjectStorage(ObjectStorage objectStorage) + public void setObjectStorage(final ObjectStorage objectStorage) { this.objectStorage = objectStorage; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/redis/Redis.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/redis/Redis.java index 9bf27606..3163e318 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/redis/Redis.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/redis/Redis.java @@ -24,10 +24,10 @@ public class Redis public String getUri() { - return uri; + return this.uri; } - public void setUri(String uri) + public void setUri(final String uri) { this.uri = uri; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/AbstractSqlConfiguration.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/AbstractSqlConfiguration.java index 2bef752b..206683cc 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/AbstractSqlConfiguration.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/AbstractSqlConfiguration.java @@ -16,7 +16,6 @@ public class AbstractSqlConfiguration { - private String dataSourceProvider; private String catalog; private String schema; @@ -26,60 +25,60 @@ public class AbstractSqlConfiguration public String getDataSourceProvider() { - return dataSourceProvider; + return this.dataSourceProvider; } - public void setDataSourceProvider(String dataSourceProvider) + public void setDataSourceProvider(final String dataSourceProvider) { this.dataSourceProvider = dataSourceProvider; } public String getCatalog() { - return catalog; + return this.catalog; } - public void setCatalog(String catalog) + public void setCatalog(final String catalog) { this.catalog = catalog; } public String getSchema() { - return schema; + return this.schema; } - public void setSchema(String schema) + public void setSchema(final String schema) { this.schema = schema; } public String getUrl() { - return url; + return this.url; } - public void setUrl(String url) + public void setUrl(final String url) { this.url = url; } public String getUser() { - return user; + return this.user; } - public void setUser(String user) + public void setUser(final String user) { this.user = user; } public String getPassword() { - return password; + return this.password; } - public void setPassword(String password) + public void setPassword(final String password) { this.password = password; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Mariadb.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Mariadb.java index 6fdf8adc..0671ddd4 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Mariadb.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Mariadb.java @@ -16,5 +16,4 @@ public class Mariadb extends AbstractSqlConfiguration { - } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Oracle.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Oracle.java index 187de17f..9934a509 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Oracle.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Oracle.java @@ -17,5 +17,4 @@ public class Oracle extends AbstractSqlConfiguration { - } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sql.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sql.java index d9f5bf16..c2ba5521 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sql.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sql.java @@ -34,40 +34,40 @@ public class Sql public Mariadb getMariadb() { - return mariadb; + return this.mariadb; } - public void setMariadb(Mariadb mariadb) + public void setMariadb(final Mariadb mariadb) { this.mariadb = mariadb; } public Oracle getOracle() { - return oracle; + return this.oracle; } - public void setOracle(Oracle oracle) + public void setOracle(final Oracle oracle) { this.oracle = oracle; } public Postgres getPostgres() { - return postgres; + return this.postgres; } - public void setPostgres(Postgres postgres) + public void setPostgres(final Postgres postgres) { this.postgres = postgres; } public Sqlite getSqlite() { - return sqlite; + return this.sqlite; } - public void setSqlite(Sqlite sqlite) + public void setSqlite(final Sqlite sqlite) { this.sqlite = sqlite; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java index 1fa41e79..3c81dc79 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java @@ -81,14 +81,14 @@ public enum ConfigKeys SQL_PASSWORD("password") ; - private String value; + private final String value; /** * Constructs a new {@code ConfigKeys} enum with the provided value. * * @param value The string value of the configuration key. */ - ConfigKeys(String value) + ConfigKeys(final String value) { this.value = value; } @@ -100,6 +100,6 @@ public enum ConfigKeys */ public String value() { - return value; + return this.value; } } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java index cbd8c556..e29243d6 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java @@ -89,15 +89,15 @@ public class EclipseStoreConfigConverter * @param properties The Eclipse Store properties to convert. * @return A map representing the provided Eclipse Store properties. */ - public Map convertConfigurationToMap(EclipseStoreProperties properties) + public Map convertConfigurationToMap(final EclipseStoreProperties properties) { - Map configValues = new HashMap<>(); + final Map configValues = new HashMap<>(); configValues.put(STORAGE_DIRECTORY, properties.getStorageDirectory()); if (properties.getStorageFilesystem() != null) { - configValues.putAll(prepareFileSystem(properties.getStorageFilesystem(), STORAGE_FILESYSTEM)); + configValues.putAll(this.prepareFileSystem(properties.getStorageFilesystem(), STORAGE_FILESYSTEM)); } configValues.put(DELETION_DIRECTORY, properties.getDeletionDirectory()); @@ -106,7 +106,7 @@ public Map convertConfigurationToMap(EclipseStoreProperties prop if (properties.getBackupFilesystem() != null) { - configValues.putAll(prepareFileSystem(properties.getBackupFilesystem(), BACKUP_FILESYSTEM)); + configValues.putAll(this.prepareFileSystem(properties.getBackupFilesystem(), BACKUP_FILESYSTEM)); } configValues.put(CHANNEL_COUNT, properties.getChannelCount()); @@ -140,24 +140,24 @@ public Map convertConfigurationToMap(EclipseStoreProperties prop return configValues; } - private Map prepareFileSystem(StorageFilesystem properties, String key) + private Map prepareFileSystem(final StorageFilesystem properties, final String key) { - Map values = new HashMap<>(); + final Map values = new HashMap<>(); if (properties.getSql() != null) { - values.putAll(prepareSql(properties.getSql(), composeKey(key, ConfigKeys.SQL.value()))); + values.putAll(this.prepareSql(properties.getSql(), this.composeKey(key, ConfigKeys.SQL.value()))); } if (properties.getAws() != null) { - values.putAll(prepareAws(properties.getAws(), composeKey(key, ConfigKeys.AWS.value()))); + values.putAll(this.prepareAws(properties.getAws(), this.composeKey(key, ConfigKeys.AWS.value()))); } if (properties.getAzure() != null) { - values.putAll(prepareAzure(properties.getAzure(), composeKey(key, ConfigKeys.AZURE.value()))); + values.putAll(this.prepareAzure(properties.getAzure(), this.composeKey(key, ConfigKeys.AZURE.value()))); } if (properties.getOraclecloud() != null) { - values.putAll(prepareOracleCloud(properties.getOraclecloud(), composeKey(key, ConfigKeys.ORACLECLOUD.value()))); + values.putAll(this.prepareOracleCloud(properties.getOraclecloud(), this.composeKey(key, ConfigKeys.ORACLECLOUD.value()))); } if (properties.getRedis() != null) { @@ -168,97 +168,97 @@ private Map prepareFileSystem(StorageFilesystem properties, Stri return values; } - private Map prepareOracleCloud(Oraclecloud oraclecloud, String key) + private Map prepareOracleCloud(final Oraclecloud oraclecloud, final String key) { - Map values = new HashMap<>(); - values.put(composeKey(key, ConfigKeys.ORACLECLOUD_CONFIG_FILE_PATH.value()), oraclecloud.getObjectStorage().getConfigFile().getPath()); - values.put(composeKey(key, ConfigKeys.ORACLECLOUD_CONFIG_FILE_PROFILE.value()), oraclecloud.getObjectStorage().getConfigFile().getProfile()); - values.put(composeKey(key, ConfigKeys.ORACLECLOUD_CONFIG_FILE_CHARSET.value()), oraclecloud.getObjectStorage().getConfigFile().getCharset()); - values.put(composeKey(key, ConfigKeys.ORACLECLOUD_CLIENT_CONNECTION_TIMEOUT_MILLIS.value()), oraclecloud.getObjectStorage().getClient().getConnectionTimeoutMillis()); - values.put(composeKey(key, ConfigKeys.ORACLECLOUD_CLIENT_READ_TIMEOUT_MILLIS.value()), oraclecloud.getObjectStorage().getClient().getReadTimeoutMillis()); - values.put(composeKey(key, ConfigKeys.ORACLECLOUD_CLIENT_MAX_ASYNC_THREADS.value()), oraclecloud.getObjectStorage().getClient().getMaxAsyncThreads()); - values.put(composeKey(key, ConfigKeys.ORACLECLOUD_REGION.value()), oraclecloud.getObjectStorage().getRegion()); - values.put(composeKey(key, ConfigKeys.ORACLECLOUD_ENDPOINT.value()), oraclecloud.getObjectStorage().getEndpoint()); + final Map values = new HashMap<>(); + values.put(this.composeKey(key, ConfigKeys.ORACLECLOUD_CONFIG_FILE_PATH.value()), oraclecloud.getObjectStorage().getConfigFile().getPath()); + values.put(this.composeKey(key, ConfigKeys.ORACLECLOUD_CONFIG_FILE_PROFILE.value()), oraclecloud.getObjectStorage().getConfigFile().getProfile()); + values.put(this.composeKey(key, ConfigKeys.ORACLECLOUD_CONFIG_FILE_CHARSET.value()), oraclecloud.getObjectStorage().getConfigFile().getCharset()); + values.put(this.composeKey(key, ConfigKeys.ORACLECLOUD_CLIENT_CONNECTION_TIMEOUT_MILLIS.value()), oraclecloud.getObjectStorage().getClient().getConnectionTimeoutMillis()); + values.put(this.composeKey(key, ConfigKeys.ORACLECLOUD_CLIENT_READ_TIMEOUT_MILLIS.value()), oraclecloud.getObjectStorage().getClient().getReadTimeoutMillis()); + values.put(this.composeKey(key, ConfigKeys.ORACLECLOUD_CLIENT_MAX_ASYNC_THREADS.value()), oraclecloud.getObjectStorage().getClient().getMaxAsyncThreads()); + values.put(this.composeKey(key, ConfigKeys.ORACLECLOUD_REGION.value()), oraclecloud.getObjectStorage().getRegion()); + values.put(this.composeKey(key, ConfigKeys.ORACLECLOUD_ENDPOINT.value()), oraclecloud.getObjectStorage().getEndpoint()); return values; } - private Map prepareAzure(Azure azure, String key) + private Map prepareAzure(final Azure azure, final String key) { - Map values = new HashMap<>(); - values.put(composeKey(key, ConfigKeys.AZURE_STORAGE_CONNECTION_STRING.value()), azure.getStorage().getConnectionString()); - values.put(composeKey(key, ConfigKeys.AZURE_STORAGE_ENCRYPTION_SCOPE.value()), azure.getStorage().getEncryptionScope()); - values.put(composeKey(key, ConfigKeys.AZURE_STORAGE_CREDENTIALS_TYPE.value()), azure.getStorage().getCredentials().getType()); - values.put(composeKey(key, ConfigKeys.AZURE_STORAGE_CREDENTIALS_USERNAME.value()), azure.getStorage().getCredentials().getUsername()); - values.put(composeKey(key, ConfigKeys.AZURE_STORAGE_CREDENTIALS_PASSWORD.value()), azure.getStorage().getCredentials().getPassword()); - values.put(composeKey(key, ConfigKeys.AZURE_STORAGE_CREDENTIALS_ACCOUNT_NAME.value()), azure.getStorage().getCredentials().getAccountMame()); - values.put(composeKey(key, ConfigKeys.AZURE_STORAGE_CREDENTIALS_ACCOUNT_KEY.value()), azure.getStorage().getCredentials().getAccountKey()); + final Map values = new HashMap<>(); + values.put(this.composeKey(key, ConfigKeys.AZURE_STORAGE_CONNECTION_STRING.value()), azure.getStorage().getConnectionString()); + values.put(this.composeKey(key, ConfigKeys.AZURE_STORAGE_ENCRYPTION_SCOPE.value()), azure.getStorage().getEncryptionScope()); + values.put(this.composeKey(key, ConfigKeys.AZURE_STORAGE_CREDENTIALS_TYPE.value()), azure.getStorage().getCredentials().getType()); + values.put(this.composeKey(key, ConfigKeys.AZURE_STORAGE_CREDENTIALS_USERNAME.value()), azure.getStorage().getCredentials().getUsername()); + values.put(this.composeKey(key, ConfigKeys.AZURE_STORAGE_CREDENTIALS_PASSWORD.value()), azure.getStorage().getCredentials().getPassword()); + values.put(this.composeKey(key, ConfigKeys.AZURE_STORAGE_CREDENTIALS_ACCOUNT_NAME.value()), azure.getStorage().getCredentials().getAccountMame()); + values.put(this.composeKey(key, ConfigKeys.AZURE_STORAGE_CREDENTIALS_ACCOUNT_KEY.value()), azure.getStorage().getCredentials().getAccountKey()); return values; } - private Map prepareAws(Aws aws, String key) + private Map prepareAws(final Aws aws, final String key) { - Map values = new HashMap<>(); + final Map values = new HashMap<>(); if (aws.getDynamodb() != null) { - values.putAll(prepareAwsProperties(aws.getDynamodb(), composeKey(key, ConfigKeys.DYNAMODB.value()))); + values.putAll(this.prepareAwsProperties(aws.getDynamodb(), this.composeKey(key, ConfigKeys.DYNAMODB.value()))); } if (aws.getS3() != null) { - values.putAll(prepareAwsProperties(aws.getS3(), composeKey(key, ConfigKeys.S3.value()))); + values.putAll(this.prepareAwsProperties(aws.getS3(), this.composeKey(key, ConfigKeys.S3.value()))); } return values; } - private Map prepareAwsProperties(AbstractAwsProperties awsProperties, String key) + private Map prepareAwsProperties(final AbstractAwsProperties awsProperties, final String key) { - Map values = new HashMap<>(); - values.put(composeKey(key, ConfigKeys.AWS_ENDPOINT_OVERRIDE.value()), awsProperties.getEndpointOverride()); - values.put(composeKey(key, ConfigKeys.AWS_REGION.value()), awsProperties.getRegion()); - values.put(composeKey(key, ConfigKeys.AWS_CREDENTIALS_TYPE.value()), awsProperties.getCredentials().getType()); - values.put(composeKey(key, ConfigKeys.AWS_CREDENTIALS_ACCESS_KEY_ID.value()), awsProperties.getCredentials().getAccessKeyId()); - values.put(composeKey(key, ConfigKeys.AWS_CREDENTIALS_SECRET_ACCESS_KEY.value()), awsProperties.getCredentials().getSecretAccessKey()); + final Map values = new HashMap<>(); + values.put(this.composeKey(key, ConfigKeys.AWS_ENDPOINT_OVERRIDE.value()), awsProperties.getEndpointOverride()); + values.put(this.composeKey(key, ConfigKeys.AWS_REGION.value()), awsProperties.getRegion()); + values.put(this.composeKey(key, ConfigKeys.AWS_CREDENTIALS_TYPE.value()), awsProperties.getCredentials().getType()); + values.put(this.composeKey(key, ConfigKeys.AWS_CREDENTIALS_ACCESS_KEY_ID.value()), awsProperties.getCredentials().getAccessKeyId()); + values.put(this.composeKey(key, ConfigKeys.AWS_CREDENTIALS_SECRET_ACCESS_KEY.value()), awsProperties.getCredentials().getSecretAccessKey()); return values; } - private Map prepareSql(Sql sql, String key) + private Map prepareSql(final Sql sql, final String key) { - Map values = new HashMap<>(); + final Map values = new HashMap<>(); if (sql.getMariadb() != null) { - values.putAll(prepareSqlBasic(sql.getMariadb(), composeKey(key, ConfigKeys.MARIADB.value()))); + values.putAll(this.prepareSqlBasic(sql.getMariadb(), this.composeKey(key, ConfigKeys.MARIADB.value()))); } if (sql.getOracle() != null) { - values.putAll(prepareSqlBasic(sql.getOracle(), composeKey(key, ConfigKeys.ORACLE.value()))); + values.putAll(this.prepareSqlBasic(sql.getOracle(), this.composeKey(key, ConfigKeys.ORACLE.value()))); } if (sql.getPostgres() != null) { - values.putAll(prepareSqlBasic(sql.getPostgres(), composeKey(key, ConfigKeys.POSTGRES.value()))); + values.putAll(this.prepareSqlBasic(sql.getPostgres(), this.composeKey(key, ConfigKeys.POSTGRES.value()))); } if (sql.getSqlite() != null) { - values.putAll(prepareSqlBasic(sql.getSqlite(), composeKey(key, ConfigKeys.SQLITE.value()))); + values.putAll(this.prepareSqlBasic(sql.getSqlite(), this.composeKey(key, ConfigKeys.SQLITE.value()))); } return values; } - private Map prepareSqlBasic(AbstractSqlConfiguration properties, String key) + private Map prepareSqlBasic(final AbstractSqlConfiguration properties, final String key) { - Map values = new HashMap<>(); - values.put(composeKey(key, ConfigKeys.SQL_DATA_SOURCE_PROVIDER.value()), properties.getDataSourceProvider()); - values.put(composeKey(key, ConfigKeys.SQL_CATALOG.value()), properties.getCatalog()); - values.put(composeKey(key, ConfigKeys.SQL_SCHEMA.value()), properties.getSchema()); - values.put(composeKey(key, ConfigKeys.SQL_URL.value()), properties.getUrl()); - values.put(composeKey(key, ConfigKeys.SQL_USER.value()), properties.getUser()); - values.put(composeKey(key, ConfigKeys.SQL_PASSWORD.value()), properties.getPassword()); + final Map values = new HashMap<>(); + values.put(this.composeKey(key, ConfigKeys.SQL_DATA_SOURCE_PROVIDER.value()), properties.getDataSourceProvider()); + values.put(this.composeKey(key, ConfigKeys.SQL_CATALOG.value()), properties.getCatalog()); + values.put(this.composeKey(key, ConfigKeys.SQL_SCHEMA.value()), properties.getSchema()); + values.put(this.composeKey(key, ConfigKeys.SQL_URL.value()), properties.getUrl()); + values.put(this.composeKey(key, ConfigKeys.SQL_USER.value()), properties.getUser()); + values.put(this.composeKey(key, ConfigKeys.SQL_PASSWORD.value()), properties.getPassword()); return values; } - protected String composeKey(String prefix, String suffix) + protected String composeKey(final String prefix, final String suffix) { return prefix + "." + suffix; } diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSpringTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSpringTest.java index 653b4024..f9436c11 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSpringTest.java +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSpringTest.java @@ -1,5 +1,10 @@ package org.eclipse.store.integrations.spring.boot.types; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Map; + /*- * #%L * spring-boot3 @@ -22,11 +27,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; -import java.util.Map; - -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - @TestPropertySource("classpath:application-test.properties") @SpringBootTest(classes = {EclipseStoreSpringBoot.class}) public class EclipseConfigurationSpringTest @@ -42,13 +42,13 @@ public class EclipseConfigurationSpringTest @Test void checkStorageDirectoryValue() { - assertNotNull(values.getStorageDirectory()); + assertNotNull(this.values.getStorageDirectory()); } @Test void converterBasicTest() { - Map valueMap = converter.convertConfigurationToMap(values); + final Map valueMap = this.converter.convertConfigurationToMap(this.values); assertTrue(valueMap.containsKey("storage-filesystem.sql.postgres.data-source-provider")); diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSqlSpringTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSqlSpringTest.java index 554f74ec..a0ff19c4 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSqlSpringTest.java +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSqlSpringTest.java @@ -1,5 +1,10 @@ package org.eclipse.store.integrations.spring.boot.types; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Map; + /*- * #%L * spring-boot3 @@ -22,11 +27,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; -import java.util.Map; - -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - @TestPropertySource("classpath:application-sql.properties") @SpringBootTest(classes = {EclipseStoreSpringBoot.class}) public class EclipseConfigurationSqlSpringTest @@ -42,13 +42,13 @@ public class EclipseConfigurationSqlSpringTest @Test void checkStorageDirectoryValue() { - assertNotNull(values.getStorageFilesystem()); + assertNotNull(this.values.getStorageFilesystem()); } @Test void converterBasicTest() { - Map valueMap = converter.convertConfigurationToMap(values); + final Map valueMap = this.converter.convertConfigurationToMap(this.values); assertTrue(valueMap.containsKey("storage-filesystem.sql.postgres.user")); } } diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/InjectStorageBeanTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/InjectStorageBeanTest.java index 66b76346..0917cddb 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/InjectStorageBeanTest.java +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/InjectStorageBeanTest.java @@ -32,9 +32,9 @@ public class InjectStorageBeanTest @Test void storeSomething() { - manager.start(); - manager.setRoot("hello"); - manager.storeRoot(); - manager.shutdown(); + this.manager.start(); + this.manager.setRoot("hello"); + this.manager.storeRoot(); + this.manager.shutdown(); } } diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/RestartStorageBeanTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/RestartStorageBeanTest.java index 3a55d262..8b289c1e 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/RestartStorageBeanTest.java +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/RestartStorageBeanTest.java @@ -46,18 +46,18 @@ public class RestartStorageBeanTest EmbeddedStorageManager injectStorageTest() { - ApplicationTemp temp = new ApplicationTemp(); + final ApplicationTemp temp = new ApplicationTemp(); tempFolder = temp.getDir().getAbsolutePath(); - myConfiguration.setStorageDirectory(temp.getDir().getAbsolutePath()); - EmbeddedStorageFoundation storageFoundation = provider.createStorageFoundation(myConfiguration); + this.myConfiguration.setStorageDirectory(temp.getDir().getAbsolutePath()); + final EmbeddedStorageFoundation storageFoundation = this.provider.createStorageFoundation(this.myConfiguration); return storageFoundation.createEmbeddedStorageManager(); } @Test - void restartStorageTest(@Autowired EmbeddedStorageManager manager) + void restartStorageTest(@Autowired final EmbeddedStorageManager manager) { - RestartRoot root = new RestartRoot("hello"); + final RestartRoot root = new RestartRoot("hello"); manager.start(); manager.setRoot(root); manager.storeRoot(); @@ -65,13 +65,13 @@ void restartStorageTest(@Autowired EmbeddedStorageManager manager) Assertions.assertEquals(tempFolder, manager.configuration().fileProvider().baseDirectory().toPathString()); - ConfigurationPair pair = new ConfigurationPair("someKey", "someValue"); - EmbeddedStorageFoundation storageFoundation = provider.createStorageFoundation(myConfiguration, pair); - RestartRoot root2 = new RestartRoot(); + final ConfigurationPair pair = new ConfigurationPair("someKey", "someValue"); + final EmbeddedStorageFoundation storageFoundation = this.provider.createStorageFoundation(this.myConfiguration, pair); + final RestartRoot root2 = new RestartRoot(); storageFoundation.setRoot(root2); try (EmbeddedStorageManager storage = storageFoundation.start()) { - RestartRoot rootFromStorage = (RestartRoot) storage.root(); + final RestartRoot rootFromStorage = (RestartRoot) storage.root(); Assertions.assertEquals("hello", rootFromStorage.getValue()); } } @@ -79,7 +79,7 @@ void restartStorageTest(@Autowired EmbeddedStorageManager manager) static class RestartRoot { private String value; - public RestartRoot(String value) + public RestartRoot(final String value) { this.value = value; } @@ -90,10 +90,10 @@ public RestartRoot() public String getValue() { - return value; + return this.value; } - public void setValue(String value) + public void setValue(final String value) { this.value = value; } diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverterTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverterTest.java index c33b22b3..20580ba0 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverterTest.java +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverterTest.java @@ -1,5 +1,12 @@ package org.eclipse.store.integrations.spring.boot.types.converter; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Map; + /*- * #%L * spring-boot3 @@ -20,10 +27,6 @@ import org.eclipse.store.integrations.spring.boot.types.configuration.sql.Sql; import org.junit.jupiter.api.Test; -import java.util.Map; - -import static org.junit.jupiter.api.Assertions.*; - class EclipseStoreConfigConverterTest { @@ -32,11 +35,11 @@ class EclipseStoreConfigConverterTest @Test void testBasicConversion() { - EclipseStoreProperties properties = new EclipseStoreProperties(); + final EclipseStoreProperties properties = new EclipseStoreProperties(); properties.setChannelCount("4"); - EclipseStoreConfigConverter converter = new EclipseStoreConfigConverter(); - Map stringStringMap = converter.convertConfigurationToMap(properties); + final EclipseStoreConfigConverter converter = new EclipseStoreConfigConverter(); + final Map stringStringMap = converter.convertConfigurationToMap(properties); assertNotNull(stringStringMap); assertEquals(1, stringStringMap.size()); @@ -47,18 +50,18 @@ void testSQLConfiguration() { final String CATALOG = "super_catalog"; - Sql sql = new Sql(); - Mariadb mariadb = new Mariadb(); + final Sql sql = new Sql(); + final Mariadb mariadb = new Mariadb(); mariadb.setCatalog(CATALOG); mariadb.setPassword("myPssw"); sql.setMariadb(mariadb); - StorageFilesystem storageFilesystem = new StorageFilesystem(); + final StorageFilesystem storageFilesystem = new StorageFilesystem(); storageFilesystem.setSql(sql); - EclipseStoreProperties values = new EclipseStoreProperties(); + final EclipseStoreProperties values = new EclipseStoreProperties(); values.setStorageFilesystem(storageFilesystem); - EclipseStoreConfigConverter converter = new EclipseStoreConfigConverter(); - Map valueMap = converter.convertConfigurationToMap(values); + final EclipseStoreConfigConverter converter = new EclipseStoreConfigConverter(); + final Map valueMap = converter.convertConfigurationToMap(values); assertTrue(valueMap.containsKey("storage-filesystem.sql.mariadb.catalog")); assertEquals(CATALOG, valueMap.get("storage-filesystem.sql.mariadb.catalog")); @@ -66,29 +69,29 @@ void testSQLConfiguration() @Test void testConvertConfigurationToMap() { - EclipseStoreProperties configValues = new EclipseStoreProperties(); - Map result = converter.convertConfigurationToMap(configValues); + final EclipseStoreProperties configValues = new EclipseStoreProperties(); + final Map result = this.converter.convertConfigurationToMap(configValues); assertNotNull(result); assertTrue(result.isEmpty()); } @Test void testConvertConfigurationToMapWithStorageDirectory() { - EclipseStoreProperties configValues = new EclipseStoreProperties(); + final EclipseStoreProperties configValues = new EclipseStoreProperties(); configValues.setStorageDirectory("storage/dir"); - Map result = converter.convertConfigurationToMap(configValues); + final Map result = this.converter.convertConfigurationToMap(configValues); assertNotNull(result); assertEquals("storage/dir", result.get(EclipseStoreConfigConverter.STORAGE_DIRECTORY)); } @Test void testNullValuesAreRemoved() { - EclipseStoreProperties configValues = new EclipseStoreProperties(); + final EclipseStoreProperties configValues = new EclipseStoreProperties(); configValues.setStorageDirectory(null); configValues.setStorageFilesystem(new StorageFilesystem()); configValues.setBackupDirectory("backup/dir"); - Map result = converter.convertConfigurationToMap(configValues); + final Map result = this.converter.convertConfigurationToMap(configValues); assertNull(result.get(EclipseStoreConfigConverter.STORAGE_DIRECTORY)); assertNotNull(result.get(EclipseStoreConfigConverter.BACKUP_DIRECTORY)); @@ -96,7 +99,7 @@ void testNullValuesAreRemoved() { @Test void testComposeKey() { - String result = converter.composeKey("prefix", "suffix"); + final String result = this.converter.composeKey("prefix", "suffix"); assertEquals("prefix.suffix", result); } } diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/FirstRoot.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/FirstRoot.java index aca80eb7..42ef5b34 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/FirstRoot.java +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/FirstRoot.java @@ -20,14 +20,14 @@ public class FirstRoot public String getValue() { - return value; + return this.value; } @Override public String toString() { return "FirstRoot{" + - "value='" + value + '\'' + + "value='" + this.value + '\'' + '}'; } diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/SecondRoot.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/SecondRoot.java index e4a47b54..44c55bdf 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/SecondRoot.java +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/SecondRoot.java @@ -23,18 +23,18 @@ public class SecondRoot public String toString() { return "SecondRoot{" + - "intValue=" + intValue + - ", c=" + c + + "intValue=" + this.intValue + + ", c=" + this.c + '}'; } public Integer getIntValue() { - return intValue; + return this.intValue; } public char getC() { - return c; + return this.c; } } diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoBeanConfiguration.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoBeanConfiguration.java index 59078bb5..419f9015 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoBeanConfiguration.java +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoBeanConfiguration.java @@ -23,7 +23,6 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Lazy; -import org.springframework.context.annotation.Profile; @TestConfiguration public class TwoBeanConfiguration @@ -49,17 +48,17 @@ EclipseStoreProperties secondStoreProperties() @Bean @Lazy @Qualifier("first_storage") - EmbeddedStorageManager createFirstStorage(@Qualifier("first_config") EclipseStoreProperties firstStoreProperties) + EmbeddedStorageManager createFirstStorage(@Qualifier("first_config") final EclipseStoreProperties firstStoreProperties) { - return provider.createStorage(firstStoreProperties); + return this.provider.createStorage(firstStoreProperties); } @Bean @Lazy @Qualifier("second_storage") - EmbeddedStorageManager createSecondStorage(@Qualifier("second_config") EclipseStoreProperties secondStoreProperties) + EmbeddedStorageManager createSecondStorage(@Qualifier("second_config") final EclipseStoreProperties secondStoreProperties) { - return provider.createStorage(secondStoreProperties); + return this.provider.createStorage(secondStoreProperties); } diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoStoragesTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoStoragesTest.java index f819a722..73e29c65 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoStoragesTest.java +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoStoragesTest.java @@ -42,8 +42,8 @@ public class TwoStoragesTest @Test void name() { - Assertions.assertEquals("FirstRoot{value='First root value'}", firstStorage.root().toString()); - Assertions.assertEquals("SecondRoot{intValue=50, c=c}", secondStorage.root().toString()); + Assertions.assertEquals("FirstRoot{value='First root value'}", this.firstStorage.root().toString()); + Assertions.assertEquals("SecondRoot{intValue=50, c=c}", this.secondStorage.root().toString()); } } From 6cba64a76ef28f9c153ae6e673efd843837e09c8 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 19 Dec 2023 09:26:11 +0100 Subject: [PATCH 041/126] add build script for non main branches --- .../workflows/maven_deploy_snapshot_dev.yml | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 .github/workflows/maven_deploy_snapshot_dev.yml diff --git a/.github/workflows/maven_deploy_snapshot_dev.yml b/.github/workflows/maven_deploy_snapshot_dev.yml new file mode 100644 index 00000000..3efa968c --- /dev/null +++ b/.github/workflows/maven_deploy_snapshot_dev.yml @@ -0,0 +1,65 @@ +# This workflow will build a Java project with Maven +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven + +name: Make snapshot and deploy + +on: + push: + branches-ignore: + - main + - 'release/**' + +jobs: + prepareSuffix: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Prepare suffix + run: | + function prepareSuffix() { + local branch=$1 + local result=${branch//\//_} + result=${result//#/} + local maxLength=10 + if (( ${#result} > maxLength )); then + result=${result:0:maxLength} + fi + local hashFromContent=$(echo -n "$branch" | md5sum | cut -f1 -d" ") + echo "${result}-${hashFromContent:0:10}" + } + echo "Suffix: $(prepareSuffix ${GITHUB_REF#refs/heads/})" + + publish: + if: github.repository == 'eclipse-store/store' + runs-on: ubuntu-latest + steps: + - id: install-secret-key + name: Install gpg secret key + run: | + cat <(echo -e "${{ secrets.ORG_GPG_PRIVATE_KEY }}") | gpg --batch --import + gpg --list-secret-keys --keyid-format LONG + - uses: actions/checkout@v3 + - name: Set up Java for publishing to Maven Central Snapshot Repository + uses: actions/setup-java@v3 + with: + java-version: '11' + distribution: 'temurin' + cache: 'maven' + server-id: ossrh + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + gpg-passphrase: PASSPHRASE + - name: Update project version + run: | + currentVersion=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) + newVersion="${currentVersion}-${{ needs.prepareSuffix.outputs.suffix }}" + mvn versions:set -DnewVersion=$newVersion --batch-mode + - name: Make a snapshot + # run: mvn -Pdeploy -Pproduction --no-transfer-progress --batch-mode clean deploy -U + run: mvn -Pdeploy -Pproduction --no-transfer-progress --batch-mode clean package -U #testing without deploy + env: + MAVEN_USERNAME: ${{ secrets.ORG_OSSRH_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} + PASSPHRASE: ${{ secrets.ORG_GPG_PASSPHRASE }} From 4540d3ff1212987db74a5d3ffa8b9e62a48dfff0 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 19 Dec 2023 09:27:13 +0100 Subject: [PATCH 042/126] add build script for non main branches --- .github/workflows/maven_deploy_snapshot_dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven_deploy_snapshot_dev.yml b/.github/workflows/maven_deploy_snapshot_dev.yml index 3efa968c..ff36a7c5 100644 --- a/.github/workflows/maven_deploy_snapshot_dev.yml +++ b/.github/workflows/maven_deploy_snapshot_dev.yml @@ -1,7 +1,7 @@ # This workflow will build a Java project with Maven # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven -name: Make snapshot and deploy +name: Make branch snapshot and deploy on: push: From b3a3297cb14226b8e528af23958f5ca8bb1e5afb Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 19 Dec 2023 09:32:34 +0100 Subject: [PATCH 043/126] change the function scope --- .../workflows/maven_deploy_snapshot_dev.yml | 35 ++++++++----------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/.github/workflows/maven_deploy_snapshot_dev.yml b/.github/workflows/maven_deploy_snapshot_dev.yml index ff36a7c5..7dfaf31e 100644 --- a/.github/workflows/maven_deploy_snapshot_dev.yml +++ b/.github/workflows/maven_deploy_snapshot_dev.yml @@ -10,27 +10,6 @@ on: - 'release/**' jobs: - prepareSuffix: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Prepare suffix - run: | - function prepareSuffix() { - local branch=$1 - local result=${branch//\//_} - result=${result//#/} - local maxLength=10 - if (( ${#result} > maxLength )); then - result=${result:0:maxLength} - fi - local hashFromContent=$(echo -n "$branch" | md5sum | cut -f1 -d" ") - echo "${result}-${hashFromContent:0:10}" - } - echo "Suffix: $(prepareSuffix ${GITHUB_REF#refs/heads/})" - publish: if: github.repository == 'eclipse-store/store' runs-on: ubuntu-latest @@ -51,6 +30,20 @@ jobs: server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD gpg-passphrase: PASSPHRASE + - name: Prepare suffix + run: | + function prepareSuffix() { + local branch=$1 + local result=${branch//\//_} + result=${result//#/} + local maxLength=10 + if (( ${#result} > maxLength )); then + result=${result:0:maxLength} + fi + local hashFromContent=$(echo -n "$branch" | md5sum | cut -f1 -d" ") + echo "${result}-${hashFromContent:0:10}" + } + echo "Suffix: $(prepareSuffix ${GITHUB_REF#refs/heads/})" - name: Update project version run: | currentVersion=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) From 052fa29bd1b3810965970924873a3581989a575b Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 19 Dec 2023 09:38:20 +0100 Subject: [PATCH 044/126] try to use global variable --- .github/workflows/maven_deploy_snapshot_dev.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven_deploy_snapshot_dev.yml b/.github/workflows/maven_deploy_snapshot_dev.yml index 7dfaf31e..c519395c 100644 --- a/.github/workflows/maven_deploy_snapshot_dev.yml +++ b/.github/workflows/maven_deploy_snapshot_dev.yml @@ -43,11 +43,13 @@ jobs: local hashFromContent=$(echo -n "$branch" | md5sum | cut -f1 -d" ") echo "${result}-${hashFromContent:0:10}" } - echo "Suffix: $(prepareSuffix ${GITHUB_REF#refs/heads/})" + suffix=$(prepareSuffix ${GITHUB_REF#refs/heads/}) + echo "Suffix: $suffix" + echo "SUFFIX=$suffix" >> $GITHUB_ENV - name: Update project version run: | currentVersion=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) - newVersion="${currentVersion}-${{ needs.prepareSuffix.outputs.suffix }}" + newVersion="${currentVersion}-$SUFFIX" mvn versions:set -DnewVersion=$newVersion --batch-mode - name: Make a snapshot # run: mvn -Pdeploy -Pproduction --no-transfer-progress --batch-mode clean deploy -U From 1a85f23d7a709576ddd5b53d6dbaddd6fa144749 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 19 Dec 2023 10:03:13 +0100 Subject: [PATCH 045/126] enable deploy --- .github/workflows/maven_deploy_snapshot_dev.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/maven_deploy_snapshot_dev.yml b/.github/workflows/maven_deploy_snapshot_dev.yml index c519395c..731e1038 100644 --- a/.github/workflows/maven_deploy_snapshot_dev.yml +++ b/.github/workflows/maven_deploy_snapshot_dev.yml @@ -52,8 +52,7 @@ jobs: newVersion="${currentVersion}-$SUFFIX" mvn versions:set -DnewVersion=$newVersion --batch-mode - name: Make a snapshot - # run: mvn -Pdeploy -Pproduction --no-transfer-progress --batch-mode clean deploy -U - run: mvn -Pdeploy -Pproduction --no-transfer-progress --batch-mode clean package -U #testing without deploy + run: mvn -Pdeploy -Pproduction --no-transfer-progress --batch-mode clean deploy -U env: MAVEN_USERNAME: ${{ secrets.ORG_OSSRH_USERNAME }} MAVEN_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} From 6d478ef7d8059f561ed8d6199fad4cd674c203a4 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 19 Dec 2023 09:26:11 +0100 Subject: [PATCH 046/126] add build script for non main branches --- .../workflows/maven_deploy_snapshot_dev.yml | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 .github/workflows/maven_deploy_snapshot_dev.yml diff --git a/.github/workflows/maven_deploy_snapshot_dev.yml b/.github/workflows/maven_deploy_snapshot_dev.yml new file mode 100644 index 00000000..3efa968c --- /dev/null +++ b/.github/workflows/maven_deploy_snapshot_dev.yml @@ -0,0 +1,65 @@ +# This workflow will build a Java project with Maven +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven + +name: Make snapshot and deploy + +on: + push: + branches-ignore: + - main + - 'release/**' + +jobs: + prepareSuffix: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Prepare suffix + run: | + function prepareSuffix() { + local branch=$1 + local result=${branch//\//_} + result=${result//#/} + local maxLength=10 + if (( ${#result} > maxLength )); then + result=${result:0:maxLength} + fi + local hashFromContent=$(echo -n "$branch" | md5sum | cut -f1 -d" ") + echo "${result}-${hashFromContent:0:10}" + } + echo "Suffix: $(prepareSuffix ${GITHUB_REF#refs/heads/})" + + publish: + if: github.repository == 'eclipse-store/store' + runs-on: ubuntu-latest + steps: + - id: install-secret-key + name: Install gpg secret key + run: | + cat <(echo -e "${{ secrets.ORG_GPG_PRIVATE_KEY }}") | gpg --batch --import + gpg --list-secret-keys --keyid-format LONG + - uses: actions/checkout@v3 + - name: Set up Java for publishing to Maven Central Snapshot Repository + uses: actions/setup-java@v3 + with: + java-version: '11' + distribution: 'temurin' + cache: 'maven' + server-id: ossrh + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + gpg-passphrase: PASSPHRASE + - name: Update project version + run: | + currentVersion=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) + newVersion="${currentVersion}-${{ needs.prepareSuffix.outputs.suffix }}" + mvn versions:set -DnewVersion=$newVersion --batch-mode + - name: Make a snapshot + # run: mvn -Pdeploy -Pproduction --no-transfer-progress --batch-mode clean deploy -U + run: mvn -Pdeploy -Pproduction --no-transfer-progress --batch-mode clean package -U #testing without deploy + env: + MAVEN_USERNAME: ${{ secrets.ORG_OSSRH_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} + PASSPHRASE: ${{ secrets.ORG_GPG_PASSPHRASE }} From 7e52d1051462b832b6f2810a2157e815191c5bd0 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 19 Dec 2023 09:27:13 +0100 Subject: [PATCH 047/126] add build script for non main branches --- .github/workflows/maven_deploy_snapshot_dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven_deploy_snapshot_dev.yml b/.github/workflows/maven_deploy_snapshot_dev.yml index 3efa968c..ff36a7c5 100644 --- a/.github/workflows/maven_deploy_snapshot_dev.yml +++ b/.github/workflows/maven_deploy_snapshot_dev.yml @@ -1,7 +1,7 @@ # This workflow will build a Java project with Maven # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven -name: Make snapshot and deploy +name: Make branch snapshot and deploy on: push: From baa0a6e756b128c9aa26a82f5aadf0b5ede2e5a2 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 19 Dec 2023 09:32:34 +0100 Subject: [PATCH 048/126] change the function scope --- .../workflows/maven_deploy_snapshot_dev.yml | 35 ++++++++----------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/.github/workflows/maven_deploy_snapshot_dev.yml b/.github/workflows/maven_deploy_snapshot_dev.yml index ff36a7c5..7dfaf31e 100644 --- a/.github/workflows/maven_deploy_snapshot_dev.yml +++ b/.github/workflows/maven_deploy_snapshot_dev.yml @@ -10,27 +10,6 @@ on: - 'release/**' jobs: - prepareSuffix: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Prepare suffix - run: | - function prepareSuffix() { - local branch=$1 - local result=${branch//\//_} - result=${result//#/} - local maxLength=10 - if (( ${#result} > maxLength )); then - result=${result:0:maxLength} - fi - local hashFromContent=$(echo -n "$branch" | md5sum | cut -f1 -d" ") - echo "${result}-${hashFromContent:0:10}" - } - echo "Suffix: $(prepareSuffix ${GITHUB_REF#refs/heads/})" - publish: if: github.repository == 'eclipse-store/store' runs-on: ubuntu-latest @@ -51,6 +30,20 @@ jobs: server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD gpg-passphrase: PASSPHRASE + - name: Prepare suffix + run: | + function prepareSuffix() { + local branch=$1 + local result=${branch//\//_} + result=${result//#/} + local maxLength=10 + if (( ${#result} > maxLength )); then + result=${result:0:maxLength} + fi + local hashFromContent=$(echo -n "$branch" | md5sum | cut -f1 -d" ") + echo "${result}-${hashFromContent:0:10}" + } + echo "Suffix: $(prepareSuffix ${GITHUB_REF#refs/heads/})" - name: Update project version run: | currentVersion=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) From a498e181398658813907cb74188b3afa0f97197d Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 19 Dec 2023 09:38:20 +0100 Subject: [PATCH 049/126] try to use global variable --- .github/workflows/maven_deploy_snapshot_dev.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven_deploy_snapshot_dev.yml b/.github/workflows/maven_deploy_snapshot_dev.yml index 7dfaf31e..c519395c 100644 --- a/.github/workflows/maven_deploy_snapshot_dev.yml +++ b/.github/workflows/maven_deploy_snapshot_dev.yml @@ -43,11 +43,13 @@ jobs: local hashFromContent=$(echo -n "$branch" | md5sum | cut -f1 -d" ") echo "${result}-${hashFromContent:0:10}" } - echo "Suffix: $(prepareSuffix ${GITHUB_REF#refs/heads/})" + suffix=$(prepareSuffix ${GITHUB_REF#refs/heads/}) + echo "Suffix: $suffix" + echo "SUFFIX=$suffix" >> $GITHUB_ENV - name: Update project version run: | currentVersion=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) - newVersion="${currentVersion}-${{ needs.prepareSuffix.outputs.suffix }}" + newVersion="${currentVersion}-$SUFFIX" mvn versions:set -DnewVersion=$newVersion --batch-mode - name: Make a snapshot # run: mvn -Pdeploy -Pproduction --no-transfer-progress --batch-mode clean deploy -U From 104eb1fc19154e584238e26757356726fed7829b Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 19 Dec 2023 10:03:13 +0100 Subject: [PATCH 050/126] enable deploy --- .github/workflows/maven_deploy_snapshot_dev.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/maven_deploy_snapshot_dev.yml b/.github/workflows/maven_deploy_snapshot_dev.yml index c519395c..731e1038 100644 --- a/.github/workflows/maven_deploy_snapshot_dev.yml +++ b/.github/workflows/maven_deploy_snapshot_dev.yml @@ -52,8 +52,7 @@ jobs: newVersion="${currentVersion}-$SUFFIX" mvn versions:set -DnewVersion=$newVersion --batch-mode - name: Make a snapshot - # run: mvn -Pdeploy -Pproduction --no-transfer-progress --batch-mode clean deploy -U - run: mvn -Pdeploy -Pproduction --no-transfer-progress --batch-mode clean package -U #testing without deploy + run: mvn -Pdeploy -Pproduction --no-transfer-progress --batch-mode clean deploy -U env: MAVEN_USERNAME: ${{ secrets.ORG_OSSRH_USERNAME }} MAVEN_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} From 9256756bb03ceb3555ffab0fa0e28856601a46d9 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 19 Dec 2023 10:52:40 +0100 Subject: [PATCH 051/126] update script for java 17 --- .../workflows/maven_deploy_snapshot_dev.yml | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/.github/workflows/maven_deploy_snapshot_dev.yml b/.github/workflows/maven_deploy_snapshot_dev.yml index 731e1038..c6ea3a9c 100644 --- a/.github/workflows/maven_deploy_snapshot_dev.yml +++ b/.github/workflows/maven_deploy_snapshot_dev.yml @@ -57,3 +57,47 @@ jobs: MAVEN_USERNAME: ${{ secrets.ORG_OSSRH_USERNAME }} MAVEN_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} PASSPHRASE: ${{ secrets.ORG_GPG_PASSPHRASE }} + + #java 17 build + - uses: actions/checkout@v3 + - name: Set up Java for publishing to Maven Central Snapshot Repository + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + cache: 'maven' + server-id: ossrh + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + gpg-passphrase: PASSPHRASE + - name: Prepare suffix + run: | + function prepareSuffix() { + local branch=$1 + local result=${branch//\//_} + result=${result//#/} + local maxLength=10 + if (( ${#result} > maxLength )); then + result=${result:0:maxLength} + fi + local hashFromContent=$(echo -n "$branch" | md5sum | cut -f1 -d" ") + echo "${result}-${hashFromContent:0:10}" + } + suffix=$(prepareSuffix ${GITHUB_REF#refs/heads/}) + echo "Suffix: $suffix" + echo "SUFFIX=$suffix" >> $GITHUB_ENV + - name: Update project version java 17 + run: | + currentVersion=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) + newVersion="${currentVersion}-$SUFFIX" + mvn versions:set -DnewVersion=$newVersion --batch-mode + - name: Make a snapshot java 17 + run: | + mvn -pl integrations/spring-boot3 clean install -am -B + - name: Deploy module build with java 17 + run: | + mvn -Pdeploy -pl integrations/spring-boot3 deploy + env: + MAVEN_USERNAME: ${{ secrets.ORG_OSSRH_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} + PASSPHRASE: ${{ secrets.ORG_GPG_PASSPHRASE }} From a7593f42db94052ec9caf64e294edfe62038795e Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 19 Dec 2023 11:29:34 +0100 Subject: [PATCH 052/126] change version generation --- .github/workflows/maven_deploy_snapshot_dev.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven_deploy_snapshot_dev.yml b/.github/workflows/maven_deploy_snapshot_dev.yml index c6ea3a9c..8da89b6d 100644 --- a/.github/workflows/maven_deploy_snapshot_dev.yml +++ b/.github/workflows/maven_deploy_snapshot_dev.yml @@ -49,7 +49,8 @@ jobs: - name: Update project version run: | currentVersion=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) - newVersion="${currentVersion}-$SUFFIX" + currentVersionWithoutSnapshot=${currentVersion%-SNAPSHOT} + newVersion="${currentVersionWithoutSnapshot}-$SUFFIX-SNAPSHOT" mvn versions:set -DnewVersion=$newVersion --batch-mode - name: Make a snapshot run: mvn -Pdeploy -Pproduction --no-transfer-progress --batch-mode clean deploy -U @@ -89,7 +90,8 @@ jobs: - name: Update project version java 17 run: | currentVersion=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) - newVersion="${currentVersion}-$SUFFIX" + currentVersionWithoutSnapshot=${currentVersion%-SNAPSHOT} + newVersion="${currentVersionWithoutSnapshot}-$SUFFIX-SNAPSHOT" mvn versions:set -DnewVersion=$newVersion --batch-mode - name: Make a snapshot java 17 run: | From c02998a047e468e6174d51c76b089317e5386998 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Wed, 20 Dec 2023 11:29:55 +0100 Subject: [PATCH 053/126] remove module-info.java and check --- afs/aws/aws/src/main/java/module-info.java | 25 --------- .../dynamodb/src/main/java/module-info.java | 25 --------- afs/aws/s3/src/main/java/module-info.java | 26 ---------- .../storage/src/main/java/module-info.java | 27 ---------- afs/blobstore/src/main/java/module-info.java | 19 ------- .../firestore/src/main/java/module-info.java | 31 ----------- afs/kafka/src/main/java/module-info.java | 25 --------- afs/nio/src/main/java/module-info.java | 19 ------- .../src/main/java/module-info.java | 27 ---------- afs/redis/src/main/java/module-info.java | 27 ---------- afs/sql/src/main/java/module-info.java | 29 ----------- cache/cache/src/main/java/module-info.java | 30 ----------- .../hibernate/src/main/java/module-info.java | 23 --------- .../src/main/java/module-info.java | 40 --------------- .../configuration/EclipseStoreProperties.java | 14 +++++ pom.xml | 35 ------------- .../src/main/java/module-info.java | 21 -------- .../src/main/java/module-info.java | 19 ------- .../src/main/java/module-info.java | 28 ---------- .../embedded/src/main/java/module-info.java | 20 -------- .../adapter/src/main/java/module-info.java | 20 -------- .../client-app/src/main/java/module-info.java | 51 ------------------- .../src/main/java/module-info.java | 21 -------- .../client/src/main/java/module-info.java | 20 -------- .../src/main/java/module-info.java | 29 ----------- .../service/src/main/java/module-info.java | 20 -------- .../storage/src/main/java/module-info.java | 22 -------- 27 files changed, 14 insertions(+), 679 deletions(-) delete mode 100644 afs/aws/aws/src/main/java/module-info.java delete mode 100644 afs/aws/dynamodb/src/main/java/module-info.java delete mode 100644 afs/aws/s3/src/main/java/module-info.java delete mode 100644 afs/azure/storage/src/main/java/module-info.java delete mode 100644 afs/blobstore/src/main/java/module-info.java delete mode 100644 afs/googlecloud/firestore/src/main/java/module-info.java delete mode 100644 afs/kafka/src/main/java/module-info.java delete mode 100644 afs/nio/src/main/java/module-info.java delete mode 100644 afs/oraclecloud/objectstorage/src/main/java/module-info.java delete mode 100644 afs/redis/src/main/java/module-info.java delete mode 100644 afs/sql/src/main/java/module-info.java delete mode 100644 cache/cache/src/main/java/module-info.java delete mode 100644 cache/hibernate/src/main/java/module-info.java delete mode 100644 integrations/spring-boot3/src/main/java/module-info.java delete mode 100644 storage/embedded-configuration/src/main/java/module-info.java delete mode 100644 storage/embedded-tools/storage-converter/src/main/java/module-info.java delete mode 100644 storage/embedded-tools/storage-migrator/src/main/java/module-info.java delete mode 100644 storage/embedded/src/main/java/module-info.java delete mode 100644 storage/rest/adapter/src/main/java/module-info.java delete mode 100644 storage/rest/client-app/src/main/java/module-info.java delete mode 100644 storage/rest/client-jersey/src/main/java/module-info.java delete mode 100644 storage/rest/client/src/main/java/module-info.java delete mode 100644 storage/rest/service-sparkjava/src/main/java/module-info.java delete mode 100644 storage/rest/service/src/main/java/module-info.java delete mode 100644 storage/storage/src/main/java/module-info.java diff --git a/afs/aws/aws/src/main/java/module-info.java b/afs/aws/aws/src/main/java/module-info.java deleted file mode 100644 index 2129246e..00000000 --- a/afs/aws/aws/src/main/java/module-info.java +++ /dev/null @@ -1,25 +0,0 @@ -/*- - * #%L - * EclipseStore Abstract File System AWS - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.afs.aws -{ - exports org.eclipse.store.afs.aws.types; - - requires transitive org.eclipse.serializer.afs; - requires transitive org.eclipse.serializer.configuration; - requires transitive software.amazon.awssdk.auth; - requires transitive software.amazon.awssdk.awscore; - requires transitive software.amazon.awssdk.core; - requires transitive software.amazon.awssdk.regions; - requires transitive software.amazon.awssdk.utils; -} diff --git a/afs/aws/dynamodb/src/main/java/module-info.java b/afs/aws/dynamodb/src/main/java/module-info.java deleted file mode 100644 index 45e9ed46..00000000 --- a/afs/aws/dynamodb/src/main/java/module-info.java +++ /dev/null @@ -1,25 +0,0 @@ -/*- - * #%L - * EclipseStore Abstract File System AWS DynamoDB - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.afs.aws.dynamodb -{ - exports org.eclipse.store.afs.aws.dynamodb.types; - - provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator - with org.eclipse.store.afs.aws.dynamodb.types.DynamoDbFileSystemCreator - ; - - requires transitive org.eclipse.store.afs.aws; - requires transitive org.eclipse.store.afs.blobstore; - requires transitive software.amazon.awssdk.services.dynamodb; -} diff --git a/afs/aws/s3/src/main/java/module-info.java b/afs/aws/s3/src/main/java/module-info.java deleted file mode 100644 index b8bc6145..00000000 --- a/afs/aws/s3/src/main/java/module-info.java +++ /dev/null @@ -1,26 +0,0 @@ -/*- - * #%L - * EclipseStore Abstract File System AWS S3 - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.afs.aws.s3 -{ - exports org.eclipse.store.afs.aws.s3.types; - - provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator - with org.eclipse.store.afs.aws.s3.types.S3FileSystemCreator - ; - - requires transitive org.eclipse.store.afs.aws; - requires transitive org.eclipse.store.afs.blobstore; - requires transitive software.amazon.awssdk.http; - requires transitive software.amazon.awssdk.services.s3; -} diff --git a/afs/azure/storage/src/main/java/module-info.java b/afs/azure/storage/src/main/java/module-info.java deleted file mode 100644 index ed2d6325..00000000 --- a/afs/azure/storage/src/main/java/module-info.java +++ /dev/null @@ -1,27 +0,0 @@ -/*- - * #%L - * EclipseStore Abstract File System Azure Storage - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.afs.azure.storage -{ - exports org.eclipse.store.afs.azure.storage.types; - - provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator - with org.eclipse.store.afs.azure.storage.types.AzureStorageFileSystemCreator - ; - - requires transitive org.eclipse.serializer.configuration; - requires transitive org.eclipse.store.afs.blobstore; - requires transitive com.azure.core; - requires transitive com.azure.storage.blob; - requires transitive com.azure.storage.common; -} diff --git a/afs/blobstore/src/main/java/module-info.java b/afs/blobstore/src/main/java/module-info.java deleted file mode 100644 index 5cc2cba9..00000000 --- a/afs/blobstore/src/main/java/module-info.java +++ /dev/null @@ -1,19 +0,0 @@ -/*- - * #%L - * EclipseStore Abstract File System Blobstore - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.afs.blobstore -{ - exports org.eclipse.store.afs.blobstore.types; - - requires transitive org.eclipse.serializer.afs; -} diff --git a/afs/googlecloud/firestore/src/main/java/module-info.java b/afs/googlecloud/firestore/src/main/java/module-info.java deleted file mode 100644 index 9dc2e364..00000000 --- a/afs/googlecloud/firestore/src/main/java/module-info.java +++ /dev/null @@ -1,31 +0,0 @@ -/*- - * #%L - * EclipseStore Abstract File System Google Cloud Firestore - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.afs.googlecloud.firestore -{ - exports org.eclipse.store.afs.googlecloud.firestore.types; - - provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator - with org.eclipse.store.afs.googlecloud.firestore.types.GoogleCloudFirestoreFileSystemCreator - ; - - requires transitive org.eclipse.serializer.configuration; - requires transitive org.eclipse.store.afs.blobstore; - requires transitive com.google.api.apicommon; - requires transitive com.google.auth; - requires transitive com.google.auth.oauth2; - requires transitive com.google.protobuf; - requires transitive gax; - requires transitive google.cloud.core; - requires transitive google.cloud.firestore; -} diff --git a/afs/kafka/src/main/java/module-info.java b/afs/kafka/src/main/java/module-info.java deleted file mode 100644 index c5e4d992..00000000 --- a/afs/kafka/src/main/java/module-info.java +++ /dev/null @@ -1,25 +0,0 @@ -/*- - * #%L - * EclipseStore Abstract File System Kafka - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.afs.kafka -{ - exports org.eclipse.store.afs.kafka.types; - - provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator - with org.eclipse.store.afs.kafka.types.KafkaFileSystemCreator - ; - - requires transitive org.eclipse.serializer.configuration; - requires transitive org.eclipse.store.afs.blobstore; - requires transitive kafka.clients; -} diff --git a/afs/nio/src/main/java/module-info.java b/afs/nio/src/main/java/module-info.java deleted file mode 100644 index 27f24964..00000000 --- a/afs/nio/src/main/java/module-info.java +++ /dev/null @@ -1,19 +0,0 @@ -/*- - * #%L - * EclipseStore Abstract File System - Java NIO - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.afs.nio -{ - exports org.eclipse.store.afs.nio.types; - - requires transitive org.eclipse.serializer.afs; -} diff --git a/afs/oraclecloud/objectstorage/src/main/java/module-info.java b/afs/oraclecloud/objectstorage/src/main/java/module-info.java deleted file mode 100644 index b0aa787f..00000000 --- a/afs/oraclecloud/objectstorage/src/main/java/module-info.java +++ /dev/null @@ -1,27 +0,0 @@ -/*- - * #%L - * EclipseStore Abstract File System Oracle Cloud ObjectStorage - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.afs.oraclecloud.objectstorage -{ - exports org.eclipse.store.afs.oraclecloud.objectstorage.types; - - provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator - with org.eclipse.store.afs.oraclecloud.objectstorage.types.OracleCloudObjectStorageFileSystemCreator - ; - - requires transitive org.eclipse.serializer.configuration; - requires transitive org.eclipse.store.afs.blobstore; - requires transitive oci.java.sdk.common; - requires transitive oci.java.sdk.objectstorage.extensions; - requires transitive oci.java.sdk.objectstorage.generated; -} diff --git a/afs/redis/src/main/java/module-info.java b/afs/redis/src/main/java/module-info.java deleted file mode 100644 index c74820a9..00000000 --- a/afs/redis/src/main/java/module-info.java +++ /dev/null @@ -1,27 +0,0 @@ -/*- - * #%L - * EclipseStore Abstract File System Redis - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.afs.redis -{ - exports org.eclipse.store.afs.redis.types; - - provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator - with org.eclipse.store.afs.redis.types.RedisFileSystemCreator - ; - - requires transitive org.eclipse.serializer.configuration; - requires transitive org.eclipse.store.afs.blobstore; - requires transitive io.netty.buffer; - requires transitive io.netty.common; - requires transitive lettuce.core; -} diff --git a/afs/sql/src/main/java/module-info.java b/afs/sql/src/main/java/module-info.java deleted file mode 100644 index cbb1afe8..00000000 --- a/afs/sql/src/main/java/module-info.java +++ /dev/null @@ -1,29 +0,0 @@ -/*- - * #%L - * EclipseStore Abstract File System SQL - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.afs.sql -{ - exports org.eclipse.store.afs.sql.types; - - provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator - with org.eclipse.store.afs.sql.types.SqlFileSystemCreatorHana, - org.eclipse.store.afs.sql.types.SqlFileSystemCreatorMariaDb, - org.eclipse.store.afs.sql.types.SqlFileSystemCreatorOracle, - org.eclipse.store.afs.sql.types.SqlFileSystemCreatorPostgres, - org.eclipse.store.afs.sql.types.SqlFileSystemCreatorSqlite - ; - - requires transitive org.eclipse.serializer.afs; - requires transitive org.eclipse.serializer.configuration; - requires transitive java.sql; -} diff --git a/cache/cache/src/main/java/module-info.java b/cache/cache/src/main/java/module-info.java deleted file mode 100644 index 6417b7f9..00000000 --- a/cache/cache/src/main/java/module-info.java +++ /dev/null @@ -1,30 +0,0 @@ -/*- - * #%L - * EclipseStore Cache - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.cache -{ - exports org.eclipse.store.cache.types; - - provides javax.cache.spi.CachingProvider - with org.eclipse.store.cache.types.CachingProvider - ; - - requires transitive org.eclipse.serializer.persistence.binary; - requires transitive org.eclipse.store.storage.embedded.configuration; - requires transitive cache.api; - requires transitive java.management; - requires org.eclipse.store.storage.embedded; - requires org.eclipse.serializer.configuration; - requires org.eclipse.serializer; - requires org.eclipse.serializer.base; -} diff --git a/cache/hibernate/src/main/java/module-info.java b/cache/hibernate/src/main/java/module-info.java deleted file mode 100644 index 7e534d77..00000000 --- a/cache/hibernate/src/main/java/module-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/*- - * #%L - * EclipseStore Cache for Hibernate - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.cache.hibernate -{ - exports org.eclipse.store.cache.hibernate.types; - - requires transitive org.eclipse.store.cache; - requires transitive java.naming; - requires transitive java.persistence; - requires transitive org.hibernate.orm.core; - requires org.eclipse.serializer.base; -} diff --git a/integrations/spring-boot3/src/main/java/module-info.java b/integrations/spring-boot3/src/main/java/module-info.java deleted file mode 100644 index 4e10c54a..00000000 --- a/integrations/spring-boot3/src/main/java/module-info.java +++ /dev/null @@ -1,40 +0,0 @@ -/*- - * #%L - * microstream-integrations-spring-boot3 - * %% - * Copyright (C) 2019 - 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -open module org.eclipse.store.integrations.spring.boot -{ - exports org.eclipse.store.integrations.spring.boot.types.configuration; - exports org.eclipse.store.integrations.spring.boot.types.configuration.aws; - exports org.eclipse.store.integrations.spring.boot.types.configuration.azure; - exports org.eclipse.store.integrations.spring.boot.types.configuration.googlecloud; - exports org.eclipse.store.integrations.spring.boot.types.configuration.googlecloud.firestore; - exports org.eclipse.store.integrations.spring.boot.types.configuration.oraclecloud; - exports org.eclipse.store.integrations.spring.boot.types.configuration.redis; - exports org.eclipse.store.integrations.spring.boot.types.configuration.sql; - exports org.eclipse.store.integrations.spring.boot.types; - exports org.eclipse.store.integrations.spring.boot.types.converter; - exports org.eclipse.store.integrations.spring.boot.types.concurrent; - - requires transitive spring.beans; - requires transitive spring.boot; - requires transitive spring.boot.autoconfigure; - requires transitive spring.context; - requires transitive spring.core; - requires transitive org.eclipse.store.storage.embedded.configuration; - requires transitive org.eclipse.serializer.configuration; - requires transitive org.aspectj.weaver; - requires transitive org.eclipse.serializer.persistence.binary.jdk17; - requires transitive org.eclipse.serializer.persistence.binary.jdk8; - - -} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java index 86c29428..ed7f8169 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java @@ -1,5 +1,19 @@ package org.eclipse.store.integrations.spring.boot.types.configuration; +/*- + * #%L + * integrations-spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.context.annotation.Configuration; diff --git a/pom.xml b/pom.xml index 34779cff..dbd228ad 100644 --- a/pom.xml +++ b/pom.xml @@ -442,41 +442,6 @@ - - module-info-check - - - src/main/java - - - - - - org.apache.maven.plugins - maven-enforcer-plugin - - - enforce-files-exist - - enforce - - - - - The module-info is not present - - ${project.basedir}/src/main/java/module-info.java - - - - true - - - - - - - javadoc-check diff --git a/storage/embedded-configuration/src/main/java/module-info.java b/storage/embedded-configuration/src/main/java/module-info.java deleted file mode 100644 index 3ac95244..00000000 --- a/storage/embedded-configuration/src/main/java/module-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/*- - * #%L - * EclipseStore Storage Embedded Configuration - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.storage.embedded.configuration -{ - exports org.eclipse.store.storage.embedded.configuration.types; - - requires java.xml; - requires transitive org.eclipse.serializer.configuration; - requires transitive org.eclipse.store.storage.embedded; -} diff --git a/storage/embedded-tools/storage-converter/src/main/java/module-info.java b/storage/embedded-tools/storage-converter/src/main/java/module-info.java deleted file mode 100644 index d62ee551..00000000 --- a/storage/embedded-tools/storage-converter/src/main/java/module-info.java +++ /dev/null @@ -1,19 +0,0 @@ -/*- - * #%L - * EclipseStore Storage Embedded Tools Storage Converter - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.storage.embedded.tools.storage.converter -{ - exports org.eclipse.store.storage.embedded.tools.storage.converter; - - requires transitive org.eclipse.store.storage.embedded.configuration; -} diff --git a/storage/embedded-tools/storage-migrator/src/main/java/module-info.java b/storage/embedded-tools/storage-migrator/src/main/java/module-info.java deleted file mode 100644 index f754a3f7..00000000 --- a/storage/embedded-tools/storage-migrator/src/main/java/module-info.java +++ /dev/null @@ -1,28 +0,0 @@ -/*- - * #%L - * EclipseStore Storage Embedded Tools Storage Migrator - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.storage.embedded.tools.storage.migrator -{ - exports org.eclipse.store.storage.embedded.tools.storage.migrator; - exports org.eclipse.store.storage.embedded.tools.storage.migrator.mappings; - exports org.eclipse.store.storage.embedded.tools.storage.migrator.typedictionary; - - requires transitive org.eclipse.serializer.persistence.binary; - requires transitive com.fasterxml.jackson.annotation; - requires transitive java.object.diff; - requires transitive lombok; - requires transitive micrometer.core; - requires transitive rewrite.core; - requires transitive rewrite.java; - requires transitive rewrite.maven; -} diff --git a/storage/embedded/src/main/java/module-info.java b/storage/embedded/src/main/java/module-info.java deleted file mode 100644 index ba075f2f..00000000 --- a/storage/embedded/src/main/java/module-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/*- - * #%L - * EclipseStore Storage Embedded - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.storage.embedded -{ - exports org.eclipse.store.storage.embedded.types; - - requires transitive org.eclipse.store.storage; - requires transitive org.slf4j; -} diff --git a/storage/rest/adapter/src/main/java/module-info.java b/storage/rest/adapter/src/main/java/module-info.java deleted file mode 100644 index 945ad10c..00000000 --- a/storage/rest/adapter/src/main/java/module-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/*- - * #%L - * EclipseStore Storage REST Adapter - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.storage.restadapter -{ - exports org.eclipse.store.storage.restadapter.types; - exports org.eclipse.store.storage.restadapter.exceptions; - - requires transitive org.eclipse.store.storage; -} diff --git a/storage/rest/client-app/src/main/java/module-info.java b/storage/rest/client-app/src/main/java/module-info.java deleted file mode 100644 index 96976fd5..00000000 --- a/storage/rest/client-app/src/main/java/module-info.java +++ /dev/null @@ -1,51 +0,0 @@ -/*- - * #%L - * EclipseStore Storage REST Client App - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ - -module org.eclipse.store.storage.restclient.app -{ - exports org.eclipse.store.storage.restclient.app.types; - exports org.eclipse.store.storage.restclient.app.ui; - - provides com.vaadin.flow.server.VaadinServiceInitListener - with org.eclipse.store.storage.restclient.app.types.ApplicationServiceInitListener - ; - - requires transitive flow.data; - requires transitive flow.html.components; - requires transitive flow.server; - requires transitive gwt.elemental; - requires transitive org.eclipse.serializer.base; - requires transitive org.eclipse.store.storage.restadapter; - requires transitive org.eclipse.store.storage.restclient; - requires transitive org.eclipse.store.storage.restclient.jersey; - requires transitive org.apache.tomcat.embed.core; - requires transitive org.slf4j; - requires transitive spring.beans; - requires transitive spring.boot; - requires transitive spring.boot.autoconfigure; - requires transitive spring.context; - requires transitive spring.core; - requires transitive spring.web; - requires transitive vaadin.spring; - requires transitive vaadin.button.flow; - requires transitive vaadin.combo.box.flow; - requires transitive vaadin.details.flow; - requires transitive vaadin.grid.flow; - requires transitive vaadin.lumo.theme; - requires transitive vaadin.notification.flow; - requires transitive vaadin.ordered.layout.flow; - requires transitive vaadin.split.layout.flow; - requires transitive vaadin.tabs.flow; - requires transitive vaadin.text.field.flow; -} diff --git a/storage/rest/client-jersey/src/main/java/module-info.java b/storage/rest/client-jersey/src/main/java/module-info.java deleted file mode 100644 index fb6fd6e1..00000000 --- a/storage/rest/client-jersey/src/main/java/module-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/*- - * #%L - * EclipseStore Storage REST Client Jersey - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.storage.restclient.jersey -{ - exports org.eclipse.store.storage.restclient.jersey.types; - - requires transitive com.google.gson; - requires transitive java.ws.rs; - requires transitive org.eclipse.store.storage.restclient; -} diff --git a/storage/rest/client/src/main/java/module-info.java b/storage/rest/client/src/main/java/module-info.java deleted file mode 100644 index f4e30ba8..00000000 --- a/storage/rest/client/src/main/java/module-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/*- - * #%L - * EclipseStore Storage REST Client - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.storage.restclient -{ - exports org.eclipse.store.storage.restclient.exceptions; - exports org.eclipse.store.storage.restclient.types; - - requires transitive org.eclipse.store.storage.restadapter; -} diff --git a/storage/rest/service-sparkjava/src/main/java/module-info.java b/storage/rest/service-sparkjava/src/main/java/module-info.java deleted file mode 100644 index c2221b33..00000000 --- a/storage/rest/service-sparkjava/src/main/java/module-info.java +++ /dev/null @@ -1,29 +0,0 @@ -/*- - * #%L - * EclipseStore Storage REST Service Sparkjava - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.storage.restservice.sparkjava -{ - exports org.eclipse.store.storage.restservice.sparkjava.exceptions; - exports org.eclipse.store.storage.restservice.sparkjava.types; - - provides org.eclipse.store.storage.restadapter.types.StorageViewDataConverter - with org.eclipse.store.storage.restservice.sparkjava.types.StorageViewDataConverterJson - ; - provides org.eclipse.store.storage.restservice.types.StorageRestServiceProvider - with org.eclipse.store.storage.restservice.sparkjava.types.StorageRestServiceProviderSparkJava - ; - - requires transitive org.eclipse.store.storage.restservice; - requires transitive com.google.gson; - requires transitive spark.core; -} diff --git a/storage/rest/service/src/main/java/module-info.java b/storage/rest/service/src/main/java/module-info.java deleted file mode 100644 index 81f3b0cb..00000000 --- a/storage/rest/service/src/main/java/module-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/*- - * #%L - * EclipseStore Storage REST Service - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.storage.restservice -{ - exports org.eclipse.store.storage.restservice.types; - exports org.eclipse.store.storage.restservice.exceptions; - - requires transitive org.eclipse.store.storage.restadapter; -} diff --git a/storage/storage/src/main/java/module-info.java b/storage/storage/src/main/java/module-info.java deleted file mode 100644 index c9e0d82a..00000000 --- a/storage/storage/src/main/java/module-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/*- - * #%L - * EclipseStore Storage - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ -module org.eclipse.store.storage -{ - exports org.eclipse.store.storage.util; - exports org.eclipse.store.storage.types; - exports org.eclipse.store.storage.exceptions; - - requires transitive org.eclipse.store.afs.nio; - requires transitive org.eclipse.serializer.persistence.binary; -} From a20d685d4b32d9fe22f80b9276132e51372963f7 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Wed, 20 Dec 2023 11:31:39 +0100 Subject: [PATCH 054/126] remove modified file --- .../configuration/EclipseStoreProperties.java | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java index ed7f8169..86c29428 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java @@ -1,19 +1,5 @@ package org.eclipse.store.integrations.spring.boot.types.configuration; -/*- - * #%L - * integrations-spring-boot3 - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ - import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.context.annotation.Configuration; From dad485adb7d87ac613cd82303a707e0997a8d36b Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Thu, 21 Dec 2023 11:01:47 +0100 Subject: [PATCH 055/126] Add property type description (#101) * Add property type description * Add links --- .../pages/configuration/properties.adoc | 82 +++++++++++++++++-- 1 file changed, 76 insertions(+), 6 deletions(-) diff --git a/docs/modules/storage/pages/configuration/properties.adoc b/docs/modules/storage/pages/configuration/properties.adoc index 5459c878..55ec80f6 100644 --- a/docs/modules/storage/pages/configuration/properties.adoc +++ b/docs/modules/storage/pages/configuration/properties.adoc @@ -4,95 +4,165 @@ These are the available properties of the `EmbeddedStorageConfigurationBuilder` The names are used accordingly in the external configuration files. They can be found as constants in `EmbeddedStorageConfigurationPropertyNames`. -[options="header",cols="1,2"] +[options="header",cols="2,4,1"] |=== |Property |Short Description -//------------- +|Type + |storage-directory |The base directory of the storage in the file system. Default is `"storage"` in the working directory. +|xref:#type-string[String] |storage-filesystem |The live file system configuration. See xref:storage-targets/index.adoc[storage targets] configuration. +|xref:#type-complex[Complex] |deletion-directory |If configured, the storage will not delete files. Instead of deleting a file it will be moved to this directory. +|xref:#type-string[String] |truncation-directory |If configured, files that will get truncated are copied into this directory. +|xref:#type-string[String] |backup-directory |The backup directory. +|xref:#type-string[String] + |backup-filesystem -|The backup file system configuration. See storage targets configuration. +|The backup file system configuration. See xref:storage-targets/index.adoc[storage targets] configuration. +|xref:#type-complex[Complex] |xref:#channel-count[channel-count] |The number of threads and number of directories used by the storage engine. Every thread has exclusive access to its directory. Default is `1`. +|xref:#type-integer[Integer] |channel-directory-prefix |Name prefix of the subdirectories used by the channel threads. Default is `"channel_"`. +|xref:#type-string[String] |data-file-prefix |Name prefix of the storage files. Default is `"channel_"`. +|xref:#type-string[String] |data-file-suffix -|Name suffix of the storage files. Default is `".dat"`. +|Name suffix of the storage files. Default is `"dat"`. +|xref:#type-string[String] |transaction-file-prefix |Name prefix of the storage transaction file. Default is `"transactions_"`. +|xref:#type-string[String] |transaction-file-suffix -|Name suffix of the storage transaction file. Default is `".sft"`. +|Name suffix of the storage transaction file. Default is `"sft"`. +|xref:#type-string[String] |type-dictionary-file-name |The name of the dictionary file. Default is `"PersistenceTypeDictionary.ptd"`. +|xref:#type-string[String] |rescued-file-suffix -|Name suffix of the storage rescue files. Default is `".bak"`. +|Name suffix of the storage rescue files. Default is `"bak"`. +|xref:#type-string[String] |lock-file-name |Name of the lock file. Default is `"used.lock"`. +|xref:#type-string[String] |xref:#housekeeping-interval[housekeeping-interval] |Interval for the housekeeping. This is work like garbage collection or cache checking. In combination with houseKeepingNanoTimeBudget the maximum processor time for housekeeping work can be set. Default is 1 second. +|xref:#type-duration[Duration] |xref:#housekeeping-time-budget[housekeeping-time-budget] |Number of nanoseconds used for each housekeeping cycle. Default is 10 milliseconds = 0.01 seconds. +|xref:#type-duration[Duration] |housekeeping-adaptive |Usage of an adaptive housekeeping controller, which will increase the time budgets on demand, if the garbage collector needs more time to reach the sweeping phase. +|xref:#type-boolean[Boolean] |housekeeping-increase-threshold |The threshold of the adaption cycle to calculate new budgets for the housekeeping process. Default is 5 seconds. +|xref:#type-duration[Duration] |housekeeping-increase-amount |The amount the housekeeping budgets will be increased each cycle. Default is 50 ms. +|xref:#type-duration[Duration] |housekeeping-maximum-time-budget |The upper limit of the housekeeping time budgets. Default is 0.5 seconds. +|xref:#type-duration[Duration] |entity-cache-threshold |Abstract threshold value for the lifetime of entities in the cache. Default is `1000000000`. +|xref:#type-long[Long] |entity-cache-timeout |Timeout in milliseconds for the entity cache evaluator. If an entity wasn't accessed in this timespan it will be removed from the cache. Default is 1 day. +|xref:#type-duration[Duration] |xref:#data-file-minimum-size[data-file-minimum-size] |Minimum file size for a data file to avoid cleaning it up. Default is 1024^2 = 1 MiB. +|xref:#type-bytes[Bytes] |xref:#data-file-maximum-size[data-file-maximum-size] |Maximum file size for a data file to avoid cleaning it up. Default is 1024^2*8 = 8 MiB. +|xref:#type-bytes[Bytes] |xref:#data-file-minimum-use-ratio[data-file-minimum-use-ratio] |The ratio (value in ]0.0;1.0]) of non-gap data contained in a storage file to prevent the file from being dissolved. Default is `0.75` (75%). +|xref:#type-double[Double] |data-file-cleanup-head-file |A flag defining whether the current head file (the only file actively written to) shall be subjected to file cleanups as well. +|xref:#type-boolean[Boolean] |xref:#transaction-file-maximum-size[transaction-file-maximum-size] |Maximum file size for each channels transactions log file. If this limit is exceeded the file wile be cleaned up during housekeeping. Default is 100 MiB. Maximum value is 1 GiB. +|xref:#type-bytes[Bytes] |=== +== Property Types + +[#type-complex] +=== Complex +Parent property with multiple possible children. + +[#type-string] +=== String +Simple string literal. + +Special case for directories: Prefix `~` can be used for user home, e.g. `~/my-app/storage` + +[#type-integer] +=== Integer +Signed integer, same as Java's `int`. + +[#type-long] +=== Long +Signed long, same as Java's `long`. + +[#type-double] +=== Double +Signed double, same as Java's `double`. + +[#type-boolean] +=== Boolean +`true` or `false` + +[#type-duration] +=== Duration +Time interval, either in ISO format `PnDTnHnMn.nS`, or simple amount and unit `amount[ns|ms|s|m|h|d]`, e.g. `30 M` + +More details in https://github.com/eclipse-serializer/serializer/blob/main/configuration/configuration/src/main/java/org/eclipse/serializer/configuration/types/DurationParser.java[DurationParser]. + +[#type-bytes] +=== Bytes +Amount of bytes: `amount[b|kb|kib|mb|mib|gb|big|tb|tib|pb|pib]`, e.g. `1.5 GB` + +More details in https://github.com/eclipse-serializer/serializer/blob/main/configuration/configuration/src/main/java/org/eclipse/serializer/configuration/types/ByteSizeParser.java[ByteSizeParser] and https://github.com/eclipse-serializer/serializer/blob/main/configuration/configuration/src/main/java/org/eclipse/serializer/configuration/types/ByteUnit.java[ByteUnit]. + == Detailed Description From 32f913130d45d6e1c43e63b862b8a05c526227fe Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Thu, 21 Dec 2023 11:05:03 +0100 Subject: [PATCH 056/126] Update Maven Plugins (#104) * working commit - layeered entities cannot be build * fix layered entities * fix workflows * add name to spring project * downgrade compiler plugin for spring boot * remove skiptests --- .github/workflows/maven_build.yml | 2 +- .github/workflows/maven_converter.yml | 2 +- examples/layered-entities/pom.xml | 4 ++++ examples/spring-boot3-simple/pom.xml | 12 +++++----- .../configuration/EclipseStoreProperties.java | 14 +++++++++++ pom.xml | 23 ++++++++----------- .../embedded-tools/storage-converter/pom.xml | 1 - 7 files changed, 35 insertions(+), 23 deletions(-) diff --git a/.github/workflows/maven_build.yml b/.github/workflows/maven_build.yml index 51611580..537bb0c1 100644 --- a/.github/workflows/maven_build.yml +++ b/.github/workflows/maven_build.yml @@ -6,7 +6,7 @@ name: Java CI with Maven on: push: branches: - - '*' + - '**' pull_request: branches: [ main ] diff --git a/.github/workflows/maven_converter.yml b/.github/workflows/maven_converter.yml index 7f03015a..9e92a12a 100644 --- a/.github/workflows/maven_converter.yml +++ b/.github/workflows/maven_converter.yml @@ -6,7 +6,7 @@ name: Java Converter Fat Jar build on: push: branches: - - '*' + - '**' pull_request: branches: [ master ] diff --git a/examples/layered-entities/pom.xml b/examples/layered-entities/pom.xml index 2741456c..bd1ea71e 100644 --- a/examples/layered-entities/pom.xml +++ b/examples/layered-entities/pom.xml @@ -20,6 +20,10 @@ EclipseStore Layered Entities Example https://projects.eclipse.org/projects/technology.store + + false + + org.eclipse.serializer diff --git a/examples/spring-boot3-simple/pom.xml b/examples/spring-boot3-simple/pom.xml index 64fbea75..2d44ea6b 100644 --- a/examples/spring-boot3-simple/pom.xml +++ b/examples/spring-boot3-simple/pom.xml @@ -10,6 +10,7 @@ ../pom.xml + EclipseStore Example Spring Boot3 Simple spring-boot3-simple @@ -44,12 +45,6 @@ spring-boot-starter-aop - - org.springframework.boot - spring-boot-starter-test - test - - org.eclipse.store integrations-spring-boot3 @@ -72,6 +67,11 @@ + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java index 86c29428..ed7f8169 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java @@ -1,5 +1,19 @@ package org.eclipse.store.integrations.spring.boot.types.configuration; +/*- + * #%L + * integrations-spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.context.annotation.Configuration; diff --git a/pom.xml b/pom.xml index dbd228ad..b6e670f5 100644 --- a/pom.xml +++ b/pom.xml @@ -157,17 +157,17 @@ org.apache.maven.plugins maven-compiler-plugin - 3.11.0 + 3.12.0 org.apache.maven.plugins maven-dependency-plugin - 3.6.0 + 3.6.1 org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.5.1 org.apache.felix @@ -228,7 +228,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.5.0 + 3.6.3 none ${javadoc.failed.on.error} @@ -254,7 +254,7 @@ org.codehaus.mojo license-maven-plugin - 2.2.0 + 2.3.0 **/*.java @@ -301,7 +301,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.4.0 + 3.4.1 enforce-env @@ -340,22 +340,17 @@ org.apache.maven.plugins maven-site-plugin - 4.0.0-M9 - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.0 + 4.0.0-M13 org.apache.maven.plugins maven-surefire-plugin - 3.1.0 + 3.2.3 org.cyclonedx cyclonedx-maven-plugin - 2.7.9 + 2.7.10 prepare-package diff --git a/storage/embedded-tools/storage-converter/pom.xml b/storage/embedded-tools/storage-converter/pom.xml index 33cd29af..9978e970 100644 --- a/storage/embedded-tools/storage-converter/pom.xml +++ b/storage/embedded-tools/storage-converter/pom.xml @@ -35,7 +35,6 @@ org.apache.maven.plugins maven-shade-plugin - 3.3.0 From 7bfaf54548c8ad8dd0b96f5e32ae80b28c768092 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Thu, 21 Dec 2023 13:40:34 +0100 Subject: [PATCH 057/126] Zj/fix docu 1223 (#105) * fix links * fix links and docu * small docu fixes * Add missing anchor --------- Co-authored-by: fh-ms --- .gitignore | 4 -- SECURITY.md | 4 +- .../org/eclipse/store/cache/types/Cache.java | 4 +- .../hibernate/types/CacheRegionFactory.java | 2 +- .../addendum/supported-java-features.adoc | 4 +- .../pages/legacy-type-mapping/index.adoc | 1 + .../pages/storing-data/best-practice.adoc | 2 +- examples/spring-boot3-simple/readme.md | 2 +- storage/rest/service-sparkjava/README.md | 47 +++++++++---------- 9 files changed, 32 insertions(+), 38 deletions(-) diff --git a/.gitignore b/.gitignore index 3fc1a38c..cfdf09dc 100644 --- a/.gitignore +++ b/.gitignore @@ -55,7 +55,6 @@ tmp/ *.swp *~.nib local.properties -.settings/ .loadpath .recommenders .externalToolBuilders/ @@ -72,7 +71,6 @@ local.properties # NetBeans nbproject/private/ -build/ nbbuild/ dist/ nbdist/ @@ -88,5 +86,3 @@ profile .asciidoctor/ .asciidoctorconfig.adoc -# Vim -*.swp diff --git a/SECURITY.md b/SECURITY.md index aaa0def5..fba7a04b 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -10,10 +10,10 @@ These versions of Eclipse Store are currently being supported with security updates. | Version | Released | Supported | -| ------- | ---------- | ------------------ | +|---------|------------|--------------------| | 1.0.0 | 2023-10-18 | :white_check_mark: | ## Reporting a Vulnerability Please report vulnerabilities to the Eclipse Foundation Security Team at -security@eclipse.org \ No newline at end of file +security@eclipse.org diff --git a/cache/cache/src/main/java/org/eclipse/store/cache/types/Cache.java b/cache/cache/src/main/java/org/eclipse/store/cache/types/Cache.java index dcd406d0..d7f917cd 100644 --- a/cache/cache/src/main/java/org/eclipse/store/cache/types/Cache.java +++ b/cache/cache/src/main/java/org/eclipse/store/cache/types/Cache.java @@ -110,7 +110,7 @@ public default void putAll(final Map map) * Short for putAll(map, replaceExistingValues, true) * * @param map entries to add - * @param replaceExistingValues if values with same keys should be replaces + * @param replaceExistingValues if values with same keys should be replaced * @see #putAll(Map, boolean, boolean) */ public default void putAll( @@ -125,7 +125,7 @@ public default void putAll( * Adds all entries to this cache. * * @param map entries to add - * @param replaceExistingValues if values with same keys should be replaces + * @param replaceExistingValues if values with same keys should be replaced * @param useWriteThrough enable write through mode for this operation */ public void putAll( diff --git a/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/CacheRegionFactory.java b/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/CacheRegionFactory.java index e1ba798d..10d1428d 100644 --- a/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/CacheRegionFactory.java +++ b/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/CacheRegionFactory.java @@ -203,7 +203,7 @@ protected CacheConfiguration resolveCacheConfiguration( CacheConfiguration.load(Object.class, Object.class); return configuration != null ? configuration - // 4. Otherwise use simple default configuration + // 4. Otherwise, use simple default configuration : CacheConfiguration.Builder(Object.class, Object.class) .storeByReference() .build(); diff --git a/docs/modules/storage/pages/addendum/supported-java-features.adoc b/docs/modules/storage/pages/addendum/supported-java-features.adoc index c5da8707..6d33f38b 100644 --- a/docs/modules/storage/pages/addendum/supported-java-features.adoc +++ b/docs/modules/storage/pages/addendum/supported-java-features.adoc @@ -140,9 +140,9 @@ |Immutable Set |image::symbol-check.svg[] -|Automatically handled until Java 14, for Java 15 and later use the persistence-binary-jdk17 module, see xref:addendum/specialized-type-handlers.adoc#JDK17[persistence-binary-jdk17] +|Automatically handled until Java 14, for Java 15 and later use the persistence-binary-jdk17 module, see xref:addendum/specialized-type-handlers.adoc#jdk17[persistence-binary-jdk17] |Immutable List |image::symbol-check.svg[] -|Automatically handled until Java 14, for Java 15 and later use the persistence-binary-jdk17 module, see xref:addendum/specialized-type-handlers.adoc#JDK17[persistence-binary-jdk17] +|Automatically handled until Java 14, for Java 15 and later use the persistence-binary-jdk17 module, see xref:addendum/specialized-type-handlers.adoc#jdk17[persistence-binary-jdk17] |=== diff --git a/docs/modules/storage/pages/legacy-type-mapping/index.adoc b/docs/modules/storage/pages/legacy-type-mapping/index.adoc index 94ff4e77..8537a124 100644 --- a/docs/modules/storage/pages/legacy-type-mapping/index.adoc +++ b/docs/modules/storage/pages/legacy-type-mapping/index.adoc @@ -111,6 +111,7 @@ EmbeddedStorageManager storageManager = foundation.createEmbeddedStorageManager(myRoot).start(); ---- +[#explicit-mapping] == Explicit Mapping All you need is two columns of strings: from old to new. + diff --git a/docs/modules/storage/pages/storing-data/best-practice.adoc b/docs/modules/storage/pages/storing-data/best-practice.adoc index f7f39ddb..5a310c29 100644 --- a/docs/modules/storage/pages/storing-data/best-practice.adoc +++ b/docs/modules/storage/pages/storing-data/best-practice.adoc @@ -2,7 +2,7 @@ == Storing Hidden Encapsulated Objects -In some cases, it can be necessary to store modified encapsulated objects that cannot be a accessed from your code. +In some cases, it can be necessary to store modified encapsulated objects that cannot be accessed from your code. [source, java] ---- diff --git a/examples/spring-boot3-simple/readme.md b/examples/spring-boot3-simple/readme.md index b5fe3033..b43cecf7 100644 --- a/examples/spring-boot3-simple/readme.md +++ b/examples/spring-boot3-simple/readme.md @@ -30,7 +30,7 @@ http://localhost:8080/ ``` ## Using App rest api -This examples use Curl for Linux/MacOS. You can use any other tool for sending HTTP requests. +This examples use Curl for Linux/macOS. You can use any other tool for sending HTTP requests. Load sample data. Without this step, the application will not contain any data. It is not mandatory to execute this step, but without it you will have to add all your data manually. ```shell curl --location --request POST 'http://localhost:8080/init' \ diff --git a/storage/rest/service-sparkjava/README.md b/storage/rest/service-sparkjava/README.md index c78ae472..22cea25a 100644 --- a/storage/rest/service-sparkjava/README.md +++ b/storage/rest/service-sparkjava/README.md @@ -5,20 +5,20 @@ sparkjava# Storage Viewer HowTo: - [Usage](#2-usage) - [Example](#3-example) - [Routes](#4-available-routes) - - [typeDictionary](#4-1-typedictionary) - - [object](#4-2-object) - - [root](#4-3-root) - - [filesStatistics](#4-4-filesstatistics) + - [typeDictionary](#41-typedictionary) + - [object](#42-object) + - [root](#43-root) + - [filesStatistics](#44-filesstatistics) - [Configuration](#5-configuration) - - [Server](#5-1-server) - - [URL](#5-1-1-url-root) - - [port](#5-1-2-port) - - [Logging](#5-2-logging) + - [Server](#51-server) + - [URL](#511-url-root) + - [port](#512-port) + - [Logging](#52-logging) ## 1. Setup: ### Maven Dependencies -``` +```xml org.eclipse.store storage-restservice-sparkjava @@ -34,7 +34,7 @@ org.eclipse.storage.restservice.types.StorageRestService ## 2. Usage ### 2.1. Start the Eclipse Store storage as usual: -``` +```java EmbeddedStorageManager storage = EmbeddedStorage .Foundation(storageDir) .start(); @@ -44,7 +44,7 @@ EmbeddedStorageManager storage = EmbeddedStorage - Start the server By default the server will listen on port 4567 -``` +```java final StorageRestService service = RestServiceResolver.getType(storage, StorageRestServiceSparkJava.class); service.start(); ``` @@ -56,7 +56,7 @@ service.stop(); the EmbeddedStorageManager will not be stopped. ## 3. Example -``` +```java public class MainTestStorageRestService { public static void main(final String[] args) @@ -72,20 +72,19 @@ public class MainTestStorageRestService service.start(); } } - ``` ## 4. Available Routes ### 4.1 TypeDictionary -/[InstanceName]/ dictionary +`/[InstanceName]/ dictionary` Get the typeDictionary as String ``` -http://localhost:4567/store-data/dictionary" +http://localhost:4567/store-data/dictionary ``` ### 4.2 Object -/[InstanceName]/object/:oid +`/[InstanceName]/object/:oid` Get an objects description and values by the object’s storage id the default InstanceName is "store-data" @@ -134,7 +133,7 @@ optional, default is default is java.lang.Long.MAX_VALUE \ limit the number of returned resolved references to supplied count.\ requires “references=true” -### 4.3. Root +### 4.3. Root /[InstanceName]/root Get Name and object ID of the current storage root element ``` @@ -154,7 +153,7 @@ The Storage viewer uses the Spark micro framework from http://sparkjava.com/ as To provide a custom configured server just create an Spark.service and initialize the StorageRestService with this Spark.service -``` +```java final Service service = Service.ignite().port(port); final StorageRestServiceDefault service = RestServiceResolver.getType(storage, StorageRestServiceDefault.class); service.setSparkService(sparkService); @@ -162,29 +161,27 @@ service.start(); ``` #### 5.1.1 Url Root -To set an other url root then 'store-data' use the constructor: +To set another url root then 'store-data' use the constructor: -``` +```java final StorageRestServiceSparkJava service = RestServiceResolver.getType(storage, StorageRestServiceSparkJava.class); service.setInstanceName(storageName); service.start(); - ``` #### 5.1.2 Port -To set an other port then the default port 4567 it is required to provide a custom configured Spark Server session to the StorageRestService constructor: +To set another port then the default port 4567 it is required to provide a custom configured Spark Server session to the StorageRestService constructor: -``` +```java final Service service = Service.ignite().port(port); final StorageRestServiceSparkJava service = RestServiceResolver.getType(storage, StorageRestServiceSparkJava.class); service.setSparkService(sparkService); service.start(); - ``` ### 5.2 Logging To enable logging add the following dependency to the project: -``` +```xml org.slf4j slf4j-simple From 779f6a491cb449e2a470e17901bf4860e4c1d542 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Thu, 21 Dec 2023 13:50:18 +0100 Subject: [PATCH 058/126] fix import (#106) bases on https://github.com/eclipse-store/store/pull/98 --- docs/modules/storage/pages/rest-interface/setup.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/storage/pages/rest-interface/setup.adoc b/docs/modules/storage/pages/rest-interface/setup.adoc index 585c702d..78cd5e9a 100644 --- a/docs/modules/storage/pages/rest-interface/setup.adoc +++ b/docs/modules/storage/pages/rest-interface/setup.adoc @@ -10,7 +10,7 @@ Just add the dependency to your project, the logger is optional. ---- - org.eclise.store + org.eclipse.store storage-restservice-sparkjava {maven-version} From 28b550c625f39fa3f99964a3d7e660342b3b7310 Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Thu, 21 Dec 2023 14:03:43 +0100 Subject: [PATCH 059/126] Add docs for code generators (#107) * Add docs for code generators * Update Java version * fixes (#108) --------- Co-authored-by: Zdenek Jonas --- docs/modules/ROOT/nav.adoc | 13 + .../pages/layered-entities/configuration.adoc | 43 ++ .../layered-entities/creating-entities.adoc | 54 ++ .../layered-entities/defining-entities.adoc | 529 ++++++++++++++++++ .../misc/pages/layered-entities/index.adoc | 340 +++++++++++ .../misc/pages/layered-entities/logging.adoc | 56 ++ .../layered-entities/multiple-layers.adoc | 20 + .../layered-entities/updating-entities.adoc | 21 + .../pages/layered-entities/versioning.adoc | 115 ++++ .../misc/pages/wrapping/configuration.adoc | 67 +++ docs/modules/misc/pages/wrapping/index.adoc | 144 +++++ docs/modules/misc/pages/wrapping/usage.adoc | 124 ++++ 12 files changed, 1526 insertions(+) create mode 100644 docs/modules/misc/pages/layered-entities/configuration.adoc create mode 100644 docs/modules/misc/pages/layered-entities/creating-entities.adoc create mode 100644 docs/modules/misc/pages/layered-entities/defining-entities.adoc create mode 100644 docs/modules/misc/pages/layered-entities/index.adoc create mode 100644 docs/modules/misc/pages/layered-entities/logging.adoc create mode 100644 docs/modules/misc/pages/layered-entities/multiple-layers.adoc create mode 100644 docs/modules/misc/pages/layered-entities/updating-entities.adoc create mode 100644 docs/modules/misc/pages/layered-entities/versioning.adoc create mode 100644 docs/modules/misc/pages/wrapping/configuration.adoc create mode 100644 docs/modules/misc/pages/wrapping/index.adoc create mode 100644 docs/modules/misc/pages/wrapping/usage.adoc diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index d9d6cdb2..cb90062a 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -80,6 +80,19 @@ *** xref:cache:use-cases/spring-cache.adoc[Spring Cache] * Miscellaneous ** xref:misc:logging/index.adoc[Logging] +** xref:misc:integrations/index.adoc[Integrations] +*** xref:misc:integrations/spring-boot.adoc[Spring-Boot] +** xref:misc:layered-entities/index.adoc[Layered Entities] +*** xref:misc:layered-entities/configuration.adoc[Configuration] +*** xref:misc:layered-entities/defining-entities.adoc[Defining Entities] +*** xref:misc:layered-entities/creating-entities.adoc[Creating Entities] +*** xref:misc:layered-entities/updating-entities.adoc[Updating Entities] +*** xref:misc:layered-entities/versioning.adoc[Versioning] +*** xref:misc:layered-entities/logging.adoc[Logging] +*** xref:misc:layered-entities/multiple-layers.adoc[Multiple Layers] +** xref:misc:wrapping/index.adoc[Wrapping] +*** xref:misc:wrapping/configuration.adoc[Configuration] +*** xref:misc:wrapping/usage.adoc[Usage] diff --git a/docs/modules/misc/pages/layered-entities/configuration.adoc b/docs/modules/misc/pages/layered-entities/configuration.adoc new file mode 100644 index 00000000..4f581bad --- /dev/null +++ b/docs/modules/misc/pages/layered-entities/configuration.adoc @@ -0,0 +1,43 @@ += Configuration + +The layered entities code generator is an annotation processor, provided by the `codegen-entity` module. + +The maven configuration looks like this: + +[source, xml, title="pom.xml", subs=attributes+] +---- + + + org.eclipse.serializer + entity-codegen + {maven-version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 11 + 11 + UTF-8 + + org.eclipse.serializer.codegen.entity.EntityProcessor + + + -Aentity.hashequalator=true + -Aentity.appendable=true + + + + + +---- + +If you don't want the `HashEqualator` to be generated, just set the `entity.hashequalator` argument to `false`. +You can leave it out otherwise, the default value is `true`. + +The same applies to the `Appendable`. diff --git a/docs/modules/misc/pages/layered-entities/creating-entities.adoc b/docs/modules/misc/pages/layered-entities/creating-entities.adoc new file mode 100644 index 00000000..b5773705 --- /dev/null +++ b/docs/modules/misc/pages/layered-entities/creating-entities.adoc @@ -0,0 +1,54 @@ += Creating Entities + +Given is the following entity: + +[source, java] +---- +public interface Person extends Entity +{ + public String firstName(); + + public String lastName(); +} +---- + +So how is it done? +Since the code generator provides a creator, we can use it to create a new `Person`. + +[source, java] +---- +Person john = PersonCreator.New() + .firstName("John") + .lastName("Doe") + .create(); +---- + +Let's see what the debugger displays if we run this code: + +image::entity-debugger.png[] + +There's always an entity chain, with + +* The identity (`PersonEntity`) as outer layer +* Then the logic layers, none here in our example +* And the innermost layer is always the data (`PersonData`), which holds the properties. + +The properties can be accessed like defined in the entity's interface: + +[source, java] +---- +String firstName = john.firstName(); // -> John +String lastName = john.lastName(); // -> Doe +---- + +The creator can also be used to create copies. +Just hand over the existing one as template: + +[source, java] +---- +Person mike = PersonCreator.New(john) // use John as template + .firstName("Mike") + .create(); +---- + +This will create a "Mike Doe". diff --git a/docs/modules/misc/pages/layered-entities/defining-entities.adoc b/docs/modules/misc/pages/layered-entities/defining-entities.adoc new file mode 100644 index 00000000..827f3bed --- /dev/null +++ b/docs/modules/misc/pages/layered-entities/defining-entities.adoc @@ -0,0 +1,529 @@ += Defining Entities + +The entity types are just simple interfaces with value methods, which have the following requirements: + +* A return type, no void +* No parameters +* No type parameters +* No declared checked exceptions + +You are not limited otherwise. +Use any types you want. +Inheritance and generics are supported as well. + +== Entities + +[source, java, title="Beeing.java"] +---- +public interface Beeing +{ + public B partner(); +} +---- + +[source, java, title="Named.java"] +---- +public interface Named +{ + public String name(); +} +---- + +[source, java, title="Animal.java"] +---- +public interface Animal extends Beeing, Entity +{ + public String species(); +} +---- + +[source, java, title="Pet.java"] +---- +public interface Pet extends Animal, Named +{ +} +---- + +[source, java, title="Human.java"] +---- +public interface Human extends Beeing, Named, Entity +{ +} +---- + +There is one base type (`Beeing`), one feature interface (`Named`) and three entities (`Animal`, `Pet`, `Human`). + +== Generated Code + +The code generator takes care of the three entities, and its output looks like this: + +[source, java, title="AnimalEntity.java"] +---- +public class AnimalEntity extends EntityLayerIdentity implements Animal +{ + protected AnimalEntity() + { + super(); + } + + @Override + protected Animal entityData() + { + return (Animal)super.entityData(); + } + + @Override + public final String species() + { + return this.entityData().species(); + } + + @Override + public final Animal partner() + { + return this.entityData().partner(); + } +} +---- + +[source, java, title="AnimalData.java"] +---- +public class AnimalData extends EntityData implements Animal +{ + private final String species; + private final Animal partner; + + protected AnimalData(final Animal entity, + final String species, + final Animal partner) + { + super(entity); + + this.species = species; + this.partner = partner; + } + + @Override + public String species() + { + return this.species; + } + + @Override + public Animal partner() + { + return this.partner; + } +} +---- + +[source, java, title="AnimalCreator.java"] +---- +public interface AnimalCreator extends Entity.Creator +{ + public AnimalCreator species(String species); + + public AnimalCreator partner(Animal partner); + + public static AnimalCreator New() + { + return new Default(); + } + + public static AnimalCreator New(final Animal other) + { + return new Default().copy(other); + } + + public class Default + extends Entity.Creator.Abstract + implements AnimalCreator + { + private String species; + private Animal partner; + + protected Default() + { + super(); + } + + @Override + public AnimalCreator species(final String species) + { + this.species = species; + return this; + } + + @Override + public AnimalCreator partner(final Animal partner) + { + this.partner = partner; + return this; + } + + @Override + protected EntityLayerIdentity createEntityInstance() + { + return new AnimalEntity(); + } + + @Override + public Animal createData(final Animal entityInstance) + { + return new AnimalData(entityInstance, + this.species, + this.partner); + } + + @Override + public AnimalCreator copy(final Animal other) + { + final Animal data = Entity.data(other); + this.species = data.species(); + this.partner = data.partner(); + return this; + } + } +} +---- + +[source, java, title="AnimalUpdater.java"] +---- +public interface AnimalUpdater extends Entity.Updater +{ + public static boolean setSpecies(final Animal animal, final String species) + { + return New(animal).species(species).update(); + } + + public static boolean setPartner(final Animal animal, final Animal partner) + { + return New(animal).partner(partner).update(); + } + + public AnimalUpdater species(String species); + + public AnimalUpdater partner(Animal partner); + + public static AnimalUpdater New(final Animal animal) + { + return new Default(animal); + } + + public class Default + extends Entity.Updater.Abstract + implements AnimalUpdater + { + private String species; + private Animal partner; + + protected Default(final Animal animal) + { + super(animal); + } + + @Override + public AnimalUpdater species(final String species) + { + this.species = species; + return this; + } + + @Override + public AnimalUpdater partner(final Animal partner) + { + this.partner = partner; + return this; + } + + @Override + public Animal createData(final Animal entityInstance) + { + return new AnimalData(entityInstance, + this.species, + this.partner); + } + + @Override + public AnimalUpdater copy(final Animal other) + { + final Animal data = Entity.data(other); + this.species = data.species(); + this.partner = data.partner(); + return this; + } + } +} +---- + +[source, java, title="PetEntity.java"] +---- +public class PetEntity extends EntityLayerIdentity implements Pet +{ + protected PetEntity() + { + super(); + } + + @Override + protected Pet entityData() + { + return (Pet)super.entityData(); + } + + @Override + public final String species() + { + return this.entityData().species(); + } + + @Override + public final Animal partner() + { + return this.entityData().partner(); + } + + @Override + public final String name() + { + return this.entityData().name(); + } +} +---- + +[source, java, title="PetData.java"] +---- +public class PetData extends EntityData implements Pet +{ + private final String species; + private final Animal partner; + private final String name ; + + protected PetData(final Pet entity, + final String species, + final Animal partner, + final String name ) + { + super(entity); + + this.species = species; + this.partner = partner; + this.name = name ; + } + + @Override + public String species() + { + return this.species; + } + + @Override + public Animal partner() + { + return this.partner; + } + + @Override + public String name() + { + return this.name; + } +} +---- + +[source, java, title="PetCreator.java"] +---- +public interface PetCreator extends Entity.Creator +{ + public PetCreator species(String species); + + public PetCreator partner(Animal partner); + + public PetCreator name(String name); + + public static PetCreator New() + { + return new Default(); + } + + public static PetCreator New(final Pet other) + { + return new Default().copy(other); + } + + public class Default + extends Entity.Creator.Abstract + implements PetCreator + { + private String species; + private Animal partner; + private String name ; + + protected Default() + { + super(); + } + + @Override + public PetCreator species(final String species) + { + this.species = species; + return this; + } + + @Override + public PetCreator partner(final Animal partner) + { + this.partner = partner; + return this; + } + + @Override + public PetCreator name(final String name) + { + this.name = name; + return this; + } + + @Override + protected EntityLayerIdentity createEntityInstance() + { + return new PetEntity(); + } + + @Override + public Pet createData(final Pet entityInstance) + { + return new PetData(entityInstance, + this.species, + this.partner, + this.name ); + } + + @Override + public PetCreator copy(final Pet other) + { + final Pet data = Entity.data(other); + this.species = data.species(); + this.partner = data.partner(); + this.name = data.name (); + return this; + } + } +} +---- + +[source, java, title="PetUpdater.java"] +---- +public interface PetUpdater extends Entity.Updater +{ + public static boolean setSpecies(final Pet pet, final String species) + { + return New(pet).species(species).update(); + } + + public static boolean setPartner(final Pet pet, final Animal partner) + { + return New(pet).partner(partner).update(); + } + + public static boolean setName(final Pet pet, final String name) + { + return New(pet).name(name).update(); + } + + public PetUpdater species(String species); + + public PetUpdater partner(Animal partner); + + public PetUpdater name(String name); + + public static PetUpdater New(final Pet pet) + { + return new Default(pet); + } + + public class Default + extends Entity.Updater.Abstract + implements PetUpdater + { + private String species; + private Animal partner; + private String name ; + + protected Default(final Pet pet) + { + super(pet); + } + + @Override + public PetUpdater species(final String species) + { + this.species = species; + return this; + } + + @Override + public PetUpdater partner(final Animal partner) + { + this.partner = partner; + return this; + } + + @Override + public PetUpdater name(final String name) + { + this.name = name; + return this; + } + + @Override + public Pet createData(final Pet entityInstance) + { + return new PetData(entityInstance, + this.species, + this.partner, + this.name ); + } + + @Override + public PetUpdater copy(final Pet other) + { + final Pet data = Entity.data(other); + this.species = data.species(); + this.partner = data.partner(); + this.name = data.name (); + return this; + } + } +} +---- + +[source, java, title="HumanEntity.java"] +---- +public class HumanEntity extends EntityLayerIdentity implements Human +{ + protected HumanEntity() + { + super(); + } + + @Override + protected Human entityData() + { + return (Human)super.entityData(); + } + + @Override + public final Human partner() + { + return this.entityData().partner(); + } + + @Override + public final String name() + { + return this.entityData().name(); + } +} +---- diff --git a/docs/modules/misc/pages/layered-entities/index.adoc b/docs/modules/misc/pages/layered-entities/index.adoc new file mode 100644 index 00000000..2a19934d --- /dev/null +++ b/docs/modules/misc/pages/layered-entities/index.adoc @@ -0,0 +1,340 @@ += Layered Entities + +Concept to separate the basic aspects of what defines an entity into separate instances of different layers: + +* _Identity_, a never to be replaced instance representing an entity in terms of references to it +* _Logic_, nestable in an arbitrary number of dynamically created logic layers, e.g. +logging, locking, versioning, etc. +* _Data_, always immutable + +Entity graphs are constructed by strictly only referencing identity instances (the "outer shell" of an entity), while every inner layer instance is unshared. +This also allows the actual data instance to be immutable, while at the same time leaving referential integrity of an entity graph intact. + +Ready-to-use logic layers are provided for: + +* Logging +* Versioning + +While the layers admittedly introduce considerable technical complexity and runtime overhead, this concept is a production ready solution for nearly all requirements regarding cross cutting concerns and aspects. + +To use this concept in your code, there need to be at least implementations for the entity's identity and data. + +Let's say the entity looks like this: + +[source, java] +---- +public interface Person extends Entity +{ + public String firstName(); + + public String lastName(); +} +---- + +There needs to be an identity class: + +[source, java] +---- +public class PersonEntity extends EntityLayerIdentity implements Person +{ + protected PersonEntity() + { + super(); + } + + @Override + protected Person entityData() + { + return (Person)super.entityData(); + } + + @Override + public final String firstName() + { + return this.entityData().firstName(); + } + + @Override + public final String lastName() + { + return this.entityData().lastName(); + } +} +---- + +And a data class: + +[source, java] +---- +public class PersonData extends EntityData implements Person +{ + private final String firstName; + private final String lastName ; + + protected PersonData(final Person entity, + final String firstName, + final String lastName ) + { + super(entity); + + this.firstName = firstName; + this.lastName = lastName ; + } + + @Override + public String firstName() + { + return this.firstName; + } + + @Override + public String lastName() + { + return this.lastName; + } +} +---- + +[NOTE] +==== +A lot of code to write to get an entity with two properties! + +But don't worry, there is a code generator for that. +An annotation processor to be precise. +The only code you have to provide are the entity interfaces, all the other stuff will be generated. + +Just add the annotation processor type `org.eclipse.serializer.codegen.entity.EntityProcessor` to your xref:layered-entities/configuration.adoc[compiler configuration]. +That's it. +==== + +The generator also builds a creator: + +[source, java] +---- +public interface PersonCreator extends Entity.Creator +{ + public PersonCreator firstName(String firstName); + + public PersonCreator lastName(String lastName); + + public static PersonCreator New() + { + return new Default(); + } + + public static PersonCreator New(final Person other) + { + return new Default().copy(other); + } + + public class Default + extends Entity.Creator.Abstract + implements PersonCreator + { + private String firstName; + private String lastName ; + + protected Default() + { + super(); + } + + @Override + public PersonCreator firstName(final String firstName) + { + this.firstName = firstName; + return this; + } + + @Override + public PersonCreator lastName(final String lastName) + { + this.lastName = lastName; + return this; + } + + @Override + protected EntityLayerIdentity createEntityInstance() + { + return new PersonEntity(); + } + + @Override + public Person createData(final Person entityInstance) + { + return new PersonData(entityInstance, + this.firstName, + this.lastName ); + } + + @Override + public PersonCreator copy(final Person other) + { + final Person data = Entity.data(other); + this.firstName = data.firstName(); + this.lastName = data.lastName (); + return this; + } + } +} +---- + +An Updater: + +[source, java] +---- +public interface PersonUpdater extends Entity.Updater +{ + public static boolean setFirstName(final Person person, final String firstName) + { + return New(person).firstName(firstName).update(); + } + + public static boolean setLastName(final Person person, final String lastName) + { + return New(person).lastName(lastName).update(); + } + + public PersonUpdater firstName(String firstName); + + public PersonUpdater lastName(String lastName); + + public static PersonUpdater New(final Person person) + { + return new Default(person); + } + + public class Default + extends Entity.Updater.Abstract + implements PersonUpdater + { + private String firstName; + private String lastName ; + + protected Default(final Person person) + { + super(person); + } + + @Override + public PersonUpdater firstName(final String firstName) + { + this.firstName = firstName; + return this; + } + + @Override + public PersonUpdater lastName(final String lastName) + { + this.lastName = lastName; + return this; + } + + @Override + public Person createData(final Person entityInstance) + { + return new PersonData(entityInstance, + this.firstName, + this.lastName ); + } + + @Override + public PersonUpdater copy(final Person other) + { + final Person data = Entity.data(other); + this.firstName = data.firstName(); + this.lastName = data.lastName (); + return this; + } + } +} +---- + +An optional equalator, with `equals` and `hashCode` methods: + +[source, java] +---- +public interface PersonHashEqualator extends HashEqualator +{ + public static PersonHashEqualator New() + { + return new Default(); + } + + public final class Default implements PersonHashEqualator, Stateless + { + public static boolean equals(final Person person1, final Person person2) + { + return X.equal(person1.firstName(), person2.firstName()) + && X.equal(person1.lastName (), person2.lastName ()) + ; + } + + public static int hashCode(final Person person) + { + return Objects.hash( + person.firstName(), + person.lastName () + ); + } + + Default() + { + super(); + } + + @Override + public boolean equal(final Person person1, final Person person2) + { + return equals(person1, person2); + } + + @Override + public int hash(final Person person) + { + return hashCode(person); + } + } +} +---- + +And an optional Appendable: + +[source, java] +---- +public interface PersonAppendable extends VarString.Appendable +{ + public static String toString(final Person person) + { + return New(person).appendTo(VarString.New()).toString(); + } + + public static PersonAppendable New(final Person person) + { + return new Default(person); + } + + public static class Default implements PersonAppendable + { + private final Person person; + + Default(final Person person) + { + super(); + + this.person = person; + } + + @Override + public VarString appendTo(final VarString vs) + { + return vs.append(this.person.getClass().getSimpleName()) + .append(" [lastName = ") + .append(this.person.lastName()) + .append(", firstName = ") + .append(this.person.firstName()) + .append(']'); + } + } +} +---- diff --git a/docs/modules/misc/pages/layered-entities/logging.adoc b/docs/modules/misc/pages/layered-entities/logging.adoc new file mode 100644 index 00000000..bdc8c9b3 --- /dev/null +++ b/docs/modules/misc/pages/layered-entities/logging.adoc @@ -0,0 +1,56 @@ += Logging + +Another predefined logic layer is for logging purposes. +Since there is a myriad of loggers out there, we don't provide any special adapter, but a generic type which can be used to adapt to the logging framework of your choice. + +Just create a class and implement `EntityLogger`, and you are good to go. + +[source, java] +---- +public class JulLogger implements EntityLogger +{ + @Override + public void afterUpdate( + final Entity identity, + final Entity data, + final boolean successful) + { + Logger.getLogger(identity.getClass().getName()) + .info("Entity updated"); + } +} +---- + +Additional to `afterUpdate` there are further hooks: + +* `entityCreated` +* `afterRead` +* `beforeUpdate` + +Now just add the logger when creating entities: + +[source, java] +---- +JulLogger logger = new JulLogger(); + +Person john = PersonCreator.New() + .addLayer(logger) + .firstName("John") + .lastName("Doe") + .create(); +---- + +When you call + +[source, java] +---- +PersonUpdater.setLastName(john, "Smith"); +---- + +the logger's output is + +[source, text] +---- +Oct 15, 2019 11:17:53 AM JulLogger afterUpdate +INFO: Entity updated +---- diff --git a/docs/modules/misc/pages/layered-entities/multiple-layers.adoc b/docs/modules/misc/pages/layered-entities/multiple-layers.adoc new file mode 100644 index 00000000..6feb1a33 --- /dev/null +++ b/docs/modules/misc/pages/layered-entities/multiple-layers.adoc @@ -0,0 +1,20 @@ += Multiple Layers + +Entities can be created with an arbitrary amount of layers, so feel free to combine them as you like: + +[source, java] +---- +EntityVersionContext versionContext = + EntityVersionContext.AutoIncrementingLong(); + +JulLogger logger = new JulLogger(); + +Person john = PersonCreator.New() + .addLayer(versionContext) + .addLayer(logger) + .firstName("John") + .lastName("Doe") + .create(); +---- + +TIP: The example on https://github.com/eclipse-store/store/tree/main/examples/layered-entities[GitHub] makes use of all the described features. diff --git a/docs/modules/misc/pages/layered-entities/updating-entities.adoc b/docs/modules/misc/pages/layered-entities/updating-entities.adoc new file mode 100644 index 00000000..3ad76d64 --- /dev/null +++ b/docs/modules/misc/pages/layered-entities/updating-entities.adoc @@ -0,0 +1,21 @@ += Updating Entities + +The data layer is always immutable. +In order to update the values we have to replace the data layer completely. +This is done with the updater. +The property setter methods can be chained, so it is easy to update multiple properties, for example: + +[source, java] +---- +PersonUpdater.New(mike) + .firstName("Jim") + .lastName("Hope") + .update(); +---- + +If only one property needs to be updated, the updater class offers static convenience methods for that: + +[source, java] +---- +PersonUpdater.setFirstName(mike, "Jim"); +---- diff --git a/docs/modules/misc/pages/layered-entities/versioning.adoc b/docs/modules/misc/pages/layered-entities/versioning.adoc new file mode 100644 index 00000000..a3f1438e --- /dev/null +++ b/docs/modules/misc/pages/layered-entities/versioning.adoc @@ -0,0 +1,115 @@ += Versioning + +An arbitrary amount of logic layers can be added to entities. + +Let's use the predefined versioning layer. +It will keep track of all changes. +Technically every new data layer which is added by the updater, will create a new version entry. + +[source, java] +---- +EntityVersionContext versionContext = + EntityVersionContext.AutoIncrementingLong(); + +Person john = PersonCreator.New() + .addLayer(versionContext) + .firstName("John") + .lastName("Doe") + .create(); +---- + +Let's have a look at the debugger: + +image::entity-versioning-debugger.png[] + +Now the versioning layer is chained between the identity layer and the data layer. + +If we update the entity a few times, we will see how the versioning layer works. +In this case we use an auto-incrementing Long as key. + +[source, java] +---- +PersonUpdater.setLastName(john, "Smith"); +PersonUpdater.setLastName(john, "Archer"); +PersonUpdater.setLastName(john, "Bennett"); +---- + +image::entity-versioning-debugger2.png[] + +[source, java] +---- +john.lastName() // now returns "Bennett" +---- + +If you want to access older versions use the context: + +[source, java] +---- +versionContext.versions(john).get(1L); // -> "John Smith" +---- + +To limit the amount of preserved versions, a cleaner can be utilized: + +[source, java] +---- +EntityVersionCleaner versionCleaner = + EntityVersionCleaner.AmountPreserving(10); +EntityVersionContext versionContext = + EntityVersionContext.AutoIncrementingLong(cleaner); +---- + +This will keep only the last ten versions of the person. + +Additionally to number keys, timestamps can be used as well. + +[source, java] +---- +EntityVersionContext systemTimeContext = + EntityVersionContext.AutoIncrementingSystemTimeMillis(); +EntityVersionContext nanoTimeContext = + EntityVersionContext.AutoIncrementingSystemNanoTime(); +EntityVersionContext instantContext = + EntityVersionContext.AutoIncrementingInstant(); +---- + +They can be preserved for a specific time range: + +[source, java] +---- +EntityVersionCleaner cleaner = + EntityVersionCleaner.AgePreservingInstant(Duration.of(1, ChronoUnit.YEARS)); +EntityVersionContext context = + EntityVersionContext.AutoIncrementingInstant(cleaner); +---- + +[NOTE] +==== +The version context can be used as a shared state object. +So you can control versioning for multiple entities at once, or even for the hole entity graph. +==== + +The auto-incrementing contexts take care of the key creation. +If you need to control it by yourself, use the mutable context. +But be aware that you have to set the version before updating any data, otherwise the current one will be overwritten. + +[source, java] +---- +EntityVersionContext.Mutable versionContext = + EntityVersionContext.Mutable(); + +versionContext.currentVersion("rev-1"); + +Person john = PersonCreator.New() + .addLayer(versionContext) + .firstName("John") + .lastName("Doe") + .create(); + +versionContext.currentVersion("rev-2"); +PersonUpdater.setLastName(john, "Smith"); + +versionContext.currentVersion("rev-3"); +PersonUpdater.setLastName(john, "Archer"); + +versionContext.currentVersion("rev-4"); +PersonUpdater.setLastName(john, "Bennett"); +---- diff --git a/docs/modules/misc/pages/wrapping/configuration.adoc b/docs/modules/misc/pages/wrapping/configuration.adoc new file mode 100644 index 00000000..c1195eea --- /dev/null +++ b/docs/modules/misc/pages/wrapping/configuration.adoc @@ -0,0 +1,67 @@ += Configuration + +The wrapper code generator is an annotation processor, provided by the `codegen-wrapping` module. + +The maven configuration looks like this: + +[source, xml, title="pom.xml", subs=attributes+] +---- + + + org.eclipse.serializer + codegen-wrapping + {maven-version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 11 + 11 + UTF-8 + + org.eclipse.serializer.codegen.wrapping.WrapperProcessor + + + -Awrapper.types=org.eclipse.serializer.persistence.types.PersistenceStoring + + + + + +---- + +There are following ways to get the base wrapper types generated. +If you want it for your own types, the best way is to use the `GenerateWrapper` annotation. + +[source, java] +---- +@GenerateWrapper +public interface MyInterface +{ + public void doStuff(); + + public String getStuff(); +} +---- + +Or, if you want it for interfaces in libraries, like `PersistenceStoring`, you cannot add an annotation. +That's what the `microstream.wrapper.types` parameter is for. +This is just a comma separated list of types. +Alternatively you can use the `GenerateWrapperFor` annotation: + +[source, java] +---- +@GenerateWrapperFor("org.eclipse.serializer.persistence.types.PersistenceStoring") +public class WrapperGenerationDummy +{ +} +---- + +It accepts a list of type names. +Plain strings have to be used instead of class literals, because it is read inside the compilation cycle which prohibits access to class elements. diff --git a/docs/modules/misc/pages/wrapping/index.adoc b/docs/modules/misc/pages/wrapping/index.adoc new file mode 100644 index 00000000..0acafe3f --- /dev/null +++ b/docs/modules/misc/pages/wrapping/index.adoc @@ -0,0 +1,144 @@ += Wrapping + +{product-name} uses a strictly interface-based architecture. +All types in the public API are, whenever possible, interfaces. +This offers the best possibilities to extend or exchange parts of the engine. +A good ways to enrich a type with features, is the wrapper (decorator) pattern. + +For example, let's say we want to add logging to the ``PersistenceStoring``'s `store(object)` method. + +[source, java, title="PersistenceStoring.java"] +---- +public interface PersistenceStoring +{ + public long store(Object instance); + + public long[] storeAll(Object... instances); + + public void storeAll(Iterable instances); + + public void storeSelfStoring(SelfStoring storing); +} +---- + +Conventionally it would be done that way: A new type, implementing the original interface, would be handed over the wrapped instance, all interface methods have to be implemented and delegated. +And in the single method, we wanted to add functionality; +the actual implementation of the logging is done. + +[source, java] +---- +public class PersistenceStoringWithLogging implements PersistenceStoring +{ + private final PersistenceStoring wrapped; + + public PersistenceStoringWithLogging(final PersistenceStoring wrapped) + { + super(); + + this.wrapped = wrapped; + } + + @Override + public long store(final Object instance) + { + Logger.getLogger(PersistenceStoring.class.getName()) + .info("Object stored: " + instance); + + return this.wrapped.store(instance); + } + + @Override + public long[] storeAll(final Object... instances) + { + return this.wrapped.storeAll(instances); + } + + @Override + public void storeAll(final Iterable instances) + { + this.wrapped.storeAll(instances); + } + + @Override + public void storeSelfStoring(final SelfStoring storing) + { + this.wrapped.storeSelfStoring(storing); + } +} +---- + +This produces a lot of overhead. +In this case, three methods are just boilerplate code to delegate the calls to the wrapped instance. +A common solution for that is to create an abstract base wrapper type for the designated interface, and to reuse it whenever needed. + +[source, java] +---- +public abstract class BaseWrapperPersistenceStoring implements PersistenceStoring +{ + private final PersistenceStoring wrapped; + + public BaseWrapperPersistenceStoring(final PersistenceStoring wrapped) + { + super(); + + this.wrapped = wrapped; + } + + @Override + public long store(final Object instance) + { + return this.wrapped.store(instance); + } + + @Override + public long[] storeAll(final Object... instances) + { + return this.wrapped.storeAll(instances); + } + + @Override + public void storeAll(final Iterable instances) + { + this.wrapped.storeAll(instances); + } + + @Override + public void storeSelfStoring(final SelfStoring storing) + { + this.wrapped.storeSelfStoring(storing); + } +} +---- + +And then, based on that, the implementation of the logger type would look like this: + +[source, java] +---- +public class PersistenceStoringWithLogging extends BaseWrapperPersistenceStoring +{ + public PersistenceStoringWithLogging(PersistenceStoring wrapped) + { + super(wrapped); + } + + @Override + public long store(Object instance) + { + Logger.getLogger(PersistenceStoring.class.getName()) + .info("Object stored: " + instance); + + return super.store(instance); + } +} +---- + +That's better. +No more boilerplate code. +Just overwrite the methods you want to extend. + +The only work left is, to generate the base wrapper types. +One way is to let your IDE generate the wrapper or delegation code. +Disadvantage of that is, it has to be redone every time your interfaces change. +A code generator, which does it automatically would be nice. +And that's what the base module brings along. +Like the xref:layered-entities/configuration.adoc[layered entity code generator], it is an annotation processor. diff --git a/docs/modules/misc/pages/wrapping/usage.adoc b/docs/modules/misc/pages/wrapping/usage.adoc new file mode 100644 index 00000000..42ea3cc2 --- /dev/null +++ b/docs/modules/misc/pages/wrapping/usage.adoc @@ -0,0 +1,124 @@ += Usage + +The wrapper code generator generates following wrapper type for `PersistenceStoring`: + +[source, java] +---- +public interface WrapperPersistenceStoring + extends Wrapper, PersistenceStoring +{ + @Override + public default long store(final Object instance) + { + return this.wrapped().store(instance); + } + + @Override + public default long[] storeAll(final Object... instances) + { + return this.wrapped().storeAll(instances); + } + + @Override + public default void storeAll(final Iterable instances) + { + this.wrapped().storeAll(instances); + } + + @Override + public default void storeSelfStoring(final SelfStoring storing) + { + this.wrapped().storeSelfStoring(storing); + } +} +---- + +It is not an abstract class, but an interface, which extends the `Wrapper` interface of the _base_ module, and the wrapped type itself. +This offers you the most flexible way to use it in your application. + +The `Wrapper` type is just a typed interface and an abstract implementation of itself. + +[source, java, title="Wrapper.java"] +---- +public interface Wrapper +{ + public W wrapped(); + + public abstract class Abstract implements Wrapper + { + private final W wrapped; + + protected Abstract(final W wrapped) + { + super(); + + this.wrapped = wrapped; + } + + @Override + public final W wrapped() + { + return this.wrapped; + } + } +} +---- + +You can either implement the `Wrapper` interface and provide the wrapped instance via the `wrapped()` method, or you can extend the abstract class and hand over the wrapped instance to the super constructor. + +Version with the abstract type: + +[source, java] +---- +public class PersistenceStoringWithLogging + extends Wrapper.Abstract + implements WrapperPersistenceStoring +{ + public PersistenceStoringWithLogging(final PersistenceStoring wrapped) + { + super(wrapped); + } + + @Override + public long store(Object instance) + { + Logger.getLogger(PersistenceStoring.class.getName()) + .info("Object stored: " + instance); + + return WrapperPersistenceStoring.super.store(instance); + } +} +---- + +Or only the interface, then you have to provide the wrapped instance via `wrapped()`: + +[source, java] +---- +public class PersistenceStoringWithLogging + implements WrapperPersistenceStoring +{ + private final PersistenceStoring wrapped; + + public PersistenceStoringWithLogging(final PersistenceStoring wrapped) + { + super(); + + this.wrapped = wrapped; + } + + @Override + public PersistenceStoring wrapped() + { + return this.wrapped; + } + + @Override + public long store(Object instance) + { + Logger.getLogger(PersistenceStoring.class.getName()) + .info("Object stored: " + instance); + + return WrapperPersistenceStoring.super.store(instance); + } +} +---- From 2bd57835b4720455a7cd96d12d19c03a2416a634 Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Thu, 21 Dec 2023 15:12:18 +0100 Subject: [PATCH 060/126] Update docs (#109) --- docs/modules/storage/pages/faq/java-features.adoc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/modules/storage/pages/faq/java-features.adoc b/docs/modules/storage/pages/faq/java-features.adoc index 5e2493d1..14a78bf4 100644 --- a/docs/modules/storage/pages/faq/java-features.adoc +++ b/docs/modules/storage/pages/faq/java-features.adoc @@ -1,9 +1,5 @@ = Java Features -== Does {product-name} work with the Java Module System (Jigsaw)? - -Yes, all jars bring the necessary module-info class. - [#records] == Can {product-name} handle Records? From aa500d08496a9c94c7b28d68f1bc393ea68280dd Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Wed, 10 Jan 2024 15:00:59 +0100 Subject: [PATCH 061/126] Update lazy-collections.adoc (#114) --- .../lazy-loading/lazy-collections.adoc | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/docs/modules/storage/pages/loading-data/lazy-loading/lazy-collections.adoc b/docs/modules/storage/pages/loading-data/lazy-loading/lazy-collections.adoc index d712af27..2c469b7d 100644 --- a/docs/modules/storage/pages/loading-data/lazy-loading/lazy-collections.adoc +++ b/docs/modules/storage/pages/loading-data/lazy-loading/lazy-collections.adoc @@ -1,15 +1,13 @@ = Lazy collections -New functionality since MicroStream v8.0 - [#background] == Background -A List, Map, or Set is a single entity within MicroStream. So this means that all data are loaded at once into memory. This can be an issue if you have a very large collection, like a list with several millions of __Customer__s. +A List, Map, or Set is a single entity within ${product-name}. So this means that all data are loaded at once into memory. This can be an issue if you have a very large collection, like a list with several millions of __Customer__s. -That is why we recommend splitting up large lists using an indexing strategy like a `HashMap` that contains a `Lazy` list of data as _value_. Or when more advanced functionality is required, you can make use of an Apache Lucene index that efficiently determines which data needs to be loaded. +That is why we recommend splitting up large lists using an indexing strategy like a `HashMap` that contains a `Lazy` list of data as _value_. Or, when more advanced functionality is required, you can make use of an Apache Lucene index that efficiently determines which data needs to be loaded. -The Lazy collections that are added to the library can help you to maintain a larger block of data in a more memory-efficient way. The implementation might need to load and unload data (when there is not enough memory) so access time to the data might be slightly increased. +The Lazy collections that are added to the library can help you to maintain a larger block of data in a more memory-efficient way. The implementation might need to load and unload data (when there is not enough memory), so access time to the data might be slightly increased. [#config] == Configuration @@ -30,16 +28,16 @@ When you need to instantiate an instance, you can just call the default construc The default constructor takes a value of 1000 items in each segment. This is not a hard limit since various factors, like the hash collision with a Map, can result in the fact that more elements are maintained in a segment. -You can specify the number of items that should be maintained by specifying this value as a constructor parameter. Note that small values, like smaller than 100, or large values like 1_000_000 and more might negatively impact the performance. +You can specify the number of items that should be maintained by specifying this value as a constructor parameter. Note that small values, like smaller than 100, or large values, like 1_000_000 and more, might negatively impact the performance. == Internals As mentioned, the implementation stores the data in different _segments_ which are lazily operated. Initially, at the startup of the _StorageManager_, the data is not yet loaded into memory and your object graph. -When accessing the values, it loads the required _segments_ to fulfill your request. Depending on how you access the data, it might be that all segments need to be loaded. Since they behave like Lazy objects, they can be unloaded by the Garbage collector if needed when the memory consumption of your Java application is high. +When accessing the values, it loads the required _segments_ to fulfil your request. Depending on how you access the data, it might be that all segments need to be loaded. Since they behave like Lazy objects, they can be unloaded by the Garbage collector if needed when the memory consumption of your Java application is high. Some aspects of the implementations The _size_ property is cached, so calling for the amount of data in the collection doesn't need to load the segments. -Accessing the `LazyHashMap` by a key value will load at maximum log2(n) segments when the implementation uses n segments since the search is implemented as btree. \ No newline at end of file +Accessing the `LazyHashMap` by a key value will load at maximum log2(n) segments when the implementation uses n segments since the search is implemented as btree. From d9caf15d9f7e1c0ee6db21483719b6478a8999a9 Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Mon, 15 Jan 2024 13:25:12 +0100 Subject: [PATCH 062/126] serializer communication docu migration (#93) * serializer communication docu migration * Update index.adoc --------- Co-authored-by: Florian Habermann --- docs/modules/communication/pages/index.adoc | 183 ++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 docs/modules/communication/pages/index.adoc diff --git a/docs/modules/communication/pages/index.adoc b/docs/modules/communication/pages/index.adoc new file mode 100644 index 00000000..4349d55d --- /dev/null +++ b/docs/modules/communication/pages/index.adoc @@ -0,0 +1,183 @@ += Communication + +{product-name} provides a module for simple object based network communication over TCP connections. + +This module utilizes the Eclipse Serializer engine to serialize and deserialize Java objects and provides additional APIs to setup the required TCP connections. + +== Getting Started + +== Prerequisites +If using Maven, just add module *communication-binary* into your pom.xml dependencies. + +[source, xml, subs=attributes+, title="pom.xml"] +---- + + + org.eclipse.serializer + communication-binary + {maven-version} + + +---- + +== Hello World +The Hello World example consists of two applications. The Host and the Client application. +The host will open a network port and listen for incoming connections from the client. +If a client connects successfully, it awaits data from the client that will be sent back to the client. +The basic example won't do any configuration, so the connection is not secured, and the client and host use +the local system address at port 1099. + +=== Host +[source, java, EchoServer] +---- +public class EchoServer +{ + public static void main(final String[] args) + { + final ComHost host = ComBinaryDynamic.Foundation() + .setHostChannelAcceptor(channel -> + { + final Object received = channel.receive(); + System.out.println("received: " + received); + channel.send(received); + }) + .createHost(); + + // run the host, making it constantly listen for new connections and relaying them to the logic + host.run(); + } +} +---- + +=== Client +[source, java, EchoClient] +---- +public class EchoClient +{ + public static void main(final String[] args) + { + //create the client + final ComClient client = ComBinaryDynamic.Foundation() + .createClient(); + + //connect to the host and communicate + try(final ComChannel channel = client.connect()) + { + channel.send("Hello Host"); + final Object received = channel.receive(); + System.out.println("received: " + received); + } + } +} +---- + +== Configuration +Configuration of host and client is done using the `ComFoundation.Default` implementation of the `ComFoundation` interface. +To get a preconfigured foundation instance, the classes `ComBinaryDynamic` and `ComBinary` provide the convenient method `Foundation()`. + +=== ComBinaryDynamic and ComBinary +The Object communication of Eclipse Serializer is available in two flavours: +*Dynamic and non-dynamic*. + +They differ in the way classes that should be serialized and transferred are handled: + +The non-dynamic version requires all classes that should be transferred to be registered at initialization time. +This can be done with the `registerEntityType` methods of the `ComFoundation`. +If a transferred object graph references any unregistered class, an exception will occur! + +The dynamic implementation automatically registers all classes that are part of the communication at runtime. +It will also do a type-mapping if classes with the same name have different implementations on the client and host. + +=== Common configuration values + +[cols="1"] +|=== +| *host binding address* + +The host's IP address is configured with +`ComFoundation.setHostBindingAddress(InetSocketAddress)`. + +| *client target address* + +The address the client connects to is configured by +`ComFoundation.setClientTargetAddress(InetSocketAddress)`. + +| *port only* + +If no host or client target address is configured, it is possible to use +`ComFoundation.setPort(int)` +to set a port that is used together with the default IP addresses for the host and client. + +| *registering entity types* + +to register entity types at startup, use +`ComFoundation.registerEntityTypes(Class...)` +for example. +|=== + +=== TLS +In order to use TLS encrypted communication, you need to setup a `ComTLSConnectionHandler` and supply it +using `ComFoundation.setConnectionHandler(ComConnectionHandler)`. +The default implementation of the ComTLSConnectionHandler uses the java https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/SSLEngine.html[SSLEngine]. +The required configuration elements have to be provided using either the provided implementations of the +`TLSKeyManagerProvider` , +`TLSTrustManagerProvider` , +`TLSParametersProvider` and +`SecureRandomProvider` +interfaces or by custom implementations. + +[source, java, TLS setup] +---- +public class EchoServerTLS +{ + public static void main(final String[] args) + { + Path serverKeyStore = Paths.get(args[0]); + Path serverTrustStore = Paths.get(args[1]); + char[] serverKeyStorePassword = args[2].toCharArray(); + char[] serverTrustStorePassword = args[2].toCharArray(); + + final ComHost host = ComBinaryDynamic.Foundation() + .setConnectionHandler(ComTLSConnectionHandler.New( + new TLSKeyManagerProvider.PKCS12( + serverKeyStore, + serverKeyStorePassword), + new TLSTrustManagerProvider.PKCS12( + serverTrustStore, + serverTrustStorePassword), + new TLSParametersProvider.Default(), + new SecureRandomProvider.Default() + )) + .setHostChannelAcceptor(channel -> + { + final Object received = channel.receive(); + System.out.println("received: " + received); + channel.send(received); + }) + .createHost(); + + // run the host, making it constantly listen for new connections and relaying them to the logic + host.run(); + } +} +---- + +The provided implementations are: + +[cols="1"] +|=== +| *org.eclipse.serializer.communication.tls.TLSKeyManagerProvider.Default* + +provides no https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/KeyManager.html[javax.net.ssl.KeyManagers], so the SSLEngine uses the systems's default KeyManager. + +| *org.eclipse.serializer.communication.tls.TLSKeyManagerProvider.PKCS12* + +Creates a SunX509 https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/KeyManager.html[javax.net.ssl.KeyManagers] by loading a PKCS12 key store from the file system. + +| *org.eclipse.serializer.communication.tls.TLSTrustManagerProvider.Default* + +provides no https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/TrustManager.html[javax.net.ssl.TrustManager], so the SSLEngine uses the systems's default TrustManager. + +| *org.eclipse.serializer.communication.tls.TLSTrustManagerProvider.PKCS12* + +Creates a SunX509 https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/TrustManager.html[javax.net.ssl.TrustManager] by loading a PKCS12 key store from the file system. + +| *org.eclipse.serializer.communication.tls.TLSParametersProvider.Default* + +- provides https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/SSLParameters.html[javax.net.ssl.SSLParameters] with client authentication enabled + +- protocol string is TLSv1.2 + +- timeout of 1000ms for the TLS handshake + +| *org.eclipse.serializer.communication.tls.SecureRandomProvider.Default* + +provides a null https://docs.oracle.com/javase/8/docs/api/index.html?java/security/SecureRandom.html[java.security.SecureRandom] to let the SLLengine use the system default SecureRandom +|=== From 9b0f2ce46e2afa81c63260eea43fb5e279f2952f Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Wed, 17 Jan 2024 10:08:51 +0100 Subject: [PATCH 063/126] Vaadin24 update (#94) Updated Client GUI to Vaadin 24 Co-authored-by: Zdenek Jonas --- .github/workflows/maven_deploy_snapshot.yml | 2 + .../workflows/maven_deploy_snapshot_dev.yml | 2 + .github/workflows/maven_release.yml | 2 + .../pages/rest-interface/client-gui.adoc | 5 ++ storage/rest/client-app/.gitignore | 38 +++++++++++++ storage/rest/client-app/pom.xml | 53 ++++++++++++++++--- .../restclient/app/ui/ConnectView.java | 36 ++++++------- .../restclient/app/ui/InternalErrorView.java | 20 +++---- .../storage/restclient/app/ui/RootLayout.java | 31 ++++------- .../restclient/app/ui/RouteNotFoundView.java | 6 +-- .../{shared-styles.html => shared-styles.css} | 5 -- .../client-app/src/main/resources/logback.xml | 11 ++++ storage/rest/client-jersey/pom.xml | 16 +++--- .../restclient/jersey/types/GsonReader.java | 13 +++-- .../jersey/types/StorageRestClientJersey.java | 22 ++++---- storage/rest/pom.xml | 15 +++++- 16 files changed, 185 insertions(+), 92 deletions(-) create mode 100644 storage/rest/client-app/.gitignore rename storage/rest/client-app/src/main/resources/META-INF/resources/frontend/styles/{shared-styles.html => shared-styles.css} (97%) create mode 100644 storage/rest/client-app/src/main/resources/logback.xml diff --git a/.github/workflows/maven_deploy_snapshot.yml b/.github/workflows/maven_deploy_snapshot.yml index bbd2351b..6eaf0b6f 100644 --- a/.github/workflows/maven_deploy_snapshot.yml +++ b/.github/workflows/maven_deploy_snapshot.yml @@ -52,9 +52,11 @@ jobs: - name: Build with java 17 run: | mvn -pl integrations/spring-boot3 clean install -am -B + mvn -P production -pl storage/rest/client-app clean install -am -B - name: Deploy module build with java 17 run: | mvn -Pdeploy -pl integrations/spring-boot3 deploy + mvn -Pdeploy -Pproduction -pl storage/rest/client-app deploy env: MAVEN_USERNAME: ${{ secrets.ORG_OSSRH_USERNAME }} MAVEN_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} diff --git a/.github/workflows/maven_deploy_snapshot_dev.yml b/.github/workflows/maven_deploy_snapshot_dev.yml index 8da89b6d..0c7de5b1 100644 --- a/.github/workflows/maven_deploy_snapshot_dev.yml +++ b/.github/workflows/maven_deploy_snapshot_dev.yml @@ -96,9 +96,11 @@ jobs: - name: Make a snapshot java 17 run: | mvn -pl integrations/spring-boot3 clean install -am -B + mvn -P production -pl storage/rest/client-app clean install -am -B - name: Deploy module build with java 17 run: | mvn -Pdeploy -pl integrations/spring-boot3 deploy + mvn -Pdeploy -Pproduction -pl storage/rest/client-app deploy env: MAVEN_USERNAME: ${{ secrets.ORG_OSSRH_USERNAME }} MAVEN_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} diff --git a/.github/workflows/maven_release.yml b/.github/workflows/maven_release.yml index bf9bc912..e741191b 100644 --- a/.github/workflows/maven_release.yml +++ b/.github/workflows/maven_release.yml @@ -50,9 +50,11 @@ jobs: - name: Build with java 17 run: | mvn -pl integrations/spring-boot3 clean install -am -B + mvn -P production -pl storage/rest/client-app clean install -am -B - name: Deploy module build with java 17 run: | mvn -Pdeploy -pl integrations/spring-boot3 deploy + mvn -Pdeploy -Pproduction -pl storage/rest/client-app deploy env: MAVEN_USERNAME: ${{ secrets.ORG_OSSRH_USERNAME }} MAVEN_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} diff --git a/docs/modules/storage/pages/rest-interface/client-gui.adoc b/docs/modules/storage/pages/rest-interface/client-gui.adoc index f433dcb0..e309b8da 100644 --- a/docs/modules/storage/pages/rest-interface/client-gui.adoc +++ b/docs/modules/storage/pages/rest-interface/client-gui.adoc @@ -4,6 +4,11 @@ Based on the REST API we provide a client, which serves a convenient web user in It is a runnable jar which starts a simple web server which then can be accessed by a browser of your choice. +[NOTE] +==== +Since {product-name} version 1.1.0 The Client GUI requires java 17! +==== + To download it use the following Maven command to download it into the current directory. [source, shell, title="CLI"] diff --git a/storage/rest/client-app/.gitignore b/storage/rest/client-app/.gitignore new file mode 100644 index 00000000..eeec6ae8 --- /dev/null +++ b/storage/rest/client-app/.gitignore @@ -0,0 +1,38 @@ +*.class +*.log +~* + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# Maven +target/ +.m2/ +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +dependency-reduced-pom.xml +release.properties +buildNumber.properties +.flattened-pom.xml + +# Gradle +.gradle/ +build/ + +# Package Files +*.jar +*.war +*.nar +frontend/ +node_modules/ + +/package.json +/package-lock.json +/tsconfig.json +/types.d.ts +/vite.config.ts +/vite.generated.ts diff --git a/storage/rest/client-app/pom.xml b/storage/rest/client-app/pom.xml index cfbd755f..da43d9c0 100644 --- a/storage/rest/client-app/pom.xml +++ b/storage/rest/client-app/pom.xml @@ -14,14 +14,17 @@ storage-restclient-app - + EclipseStore Storage REST Client App Executable Client App with Web User Interface https://projects.eclipse.org/projects/technology.store - 14.8.9 - 2.6.7 + 17 + 17 + 17 + 24.2.6 + 3.2.0 @@ -58,8 +61,14 @@ vaadin-spring-boot-starter - com.vaadin - flow-server-compatibility-mode + jakarta.activation + jakarta.activation-api + + + org.slf4j + slf4j-api + + 2.0.9 @@ -71,13 +80,27 @@ spring-boot-maven-plugin ${spring.boot.version} - org.eclipse.store.storage.restclient.app.types.Application - 500 240 + + com.vaadin + vaadin-maven-plugin + ${vaadin.version} + + + + prepare-frontend + + + + @@ -94,7 +117,8 @@ spring-boot-maven-plugin ${spring.boot.version} - org.eclipse.store.storage.restclient.app.types.Application + + org.eclipse.store.storage.restclient.app.types.Application -Dvaadin.productionMode JAR @@ -106,6 +130,19 @@ + + com.vaadin + vaadin-maven-plugin + ${vaadin.version} + + + + build-frontend + + compile + + + diff --git a/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/ConnectView.java b/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/ConnectView.java index aaa291f0..cf533ef9 100644 --- a/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/ConnectView.java +++ b/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/ConnectView.java @@ -22,16 +22,15 @@ import java.util.Set; import java.util.stream.Collectors; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import org.eclipse.store.storage.restclient.app.types.SessionData; +import org.eclipse.store.storage.restclient.jersey.types.StorageRestClientJersey; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.html.H3; import com.vaadin.flow.component.html.Hr; import com.vaadin.flow.component.html.Image; -import com.vaadin.flow.component.html.Label; +import com.vaadin.flow.component.html.NativeLabel; import com.vaadin.flow.component.notification.Notification; import com.vaadin.flow.component.notification.Notification.Position; import com.vaadin.flow.component.orderedlayout.HorizontalLayout; @@ -42,13 +41,14 @@ import com.vaadin.flow.server.VaadinRequest; import com.vaadin.flow.server.VaadinResponse; -import org.eclipse.store.storage.restclient.app.types.SessionData; -import org.eclipse.store.storage.restclient.jersey.types.StorageRestClientJersey; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; @Route(value = "", layout = RootLayout.class) public class ConnectView extends VerticalLayout implements HasDynamicTitle -{ +{ public ConnectView() { super(); @@ -56,11 +56,11 @@ public ConnectView() final ComboBox urlChooser = new ComboBox<>(); urlChooser.setId(ElementIds.COMBO_URL); urlChooser.setMinWidth("50ch"); - urlChooser.setDataProvider(DataProvider.ofCollection(this.urls())); + urlChooser.setItems(DataProvider.ofCollection(this.urls())); urlChooser.setAllowCustomValue(true); urlChooser.addCustomValueSetListener(event -> urlChooser.setValue(event.getDetail())); - final Button cmdConnect = new Button(this.getTranslation("CONNECT"), + final Button cmdConnect = new Button(this.getTranslation("CONNECT"), event -> { String url = urlChooser.getValue(); if(url != null && (url = url.trim()).length() > 0) @@ -76,8 +76,8 @@ public ConnectView() cmdConnect.setDisableOnClick(true); final HorizontalLayout connectLayout = new HorizontalLayout( - new Label(this.getTranslation("URL") + ":"), - urlChooser, + new NativeLabel(this.getTranslation("URL") + ":"), + urlChooser, cmdConnect ); connectLayout.setDefaultVerticalComponentAlignment(Alignment.CENTER); @@ -128,15 +128,15 @@ private void tryConnect( header.addClassName(ClassNames.ERROR); final Button close = new Button( - this.getTranslation("OK"), + this.getTranslation("OK"), event -> notification.close() ); final VerticalLayout content = new VerticalLayout( header, new Hr(), - new Label(this.getTranslation("INTERNAL_ERROR_HINT", baseUrl)), - close + new NativeLabel(this.getTranslation("INTERNAL_ERROR_HINT", baseUrl)), + close ); content.setHorizontalComponentAlignment(Alignment.END, close); @@ -164,7 +164,7 @@ private Set urls() if(urlCookie != null) { final String urls = new String( - Base64.getUrlDecoder().decode(urlCookie.getValue()), + Base64.getUrlDecoder().decode(urlCookie.getValue()), StandardCharsets.UTF_8 ); for(final String url : urls.split("\n")) @@ -187,15 +187,15 @@ private void updateUrlCookie( final HttpServletResponse response = (HttpServletResponse) VaadinResponse.getCurrent(); final Cookie cookie = new Cookie( - "URL", + "URL", new String( Base64.getUrlEncoder().encode( cookieData.getBytes(StandardCharsets.UTF_8) - ), + ), StandardCharsets.UTF_8 ) ); - response.addCookie(cookie); + response.addCookie(cookie); } } diff --git a/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/InternalErrorView.java b/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/InternalErrorView.java index fe60eea7..ab614db5 100644 --- a/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/InternalErrorView.java +++ b/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/InternalErrorView.java @@ -17,15 +17,13 @@ import java.io.PrintWriter; import java.io.StringWriter; -import javax.servlet.http.HttpServletResponse; - import org.eclipse.store.storage.restclient.app.types.ApplicationErrorHandler; import org.eclipse.store.storage.restclient.app.types.SessionData; import com.vaadin.flow.component.details.Details; import com.vaadin.flow.component.html.H3; import com.vaadin.flow.component.html.Hr; -import com.vaadin.flow.component.html.Label; +import com.vaadin.flow.component.html.NativeLabel; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.textfield.TextArea; import com.vaadin.flow.router.BeforeEnterEvent; @@ -36,9 +34,11 @@ import com.vaadin.flow.router.Route; import com.vaadin.flow.server.VaadinSession; +import jakarta.servlet.http.HttpServletResponse; + @Route(value = "error", layout = RootLayout.class) -public class InternalErrorView extends VerticalLayout +public class InternalErrorView extends VerticalLayout implements HasDynamicTitle, HasErrorParameter, BeforeEnterObserver { public InternalErrorView() @@ -51,12 +51,12 @@ public InternalErrorView() @Override public String getPageTitle() { - return getTranslation("ERROR") + " - " + RootLayout.PAGE_TITLE; + return this.getTranslation("ERROR") + " - " + RootLayout.PAGE_TITLE; } @Override public int setErrorParameter( - final BeforeEnterEvent event, + final BeforeEnterEvent event, final ErrorParameter parameter ) { @@ -73,8 +73,8 @@ public int setErrorParameter( public void beforeEnter( final BeforeEnterEvent event ) - { - final H3 header = new H3(getTranslation("INTERNAL_ERROR_TITLE")); + { + final H3 header = new H3(this.getTranslation("INTERNAL_ERROR_TITLE")); header.addClassName(ClassNames.ERROR); this.add(header); @@ -82,7 +82,7 @@ public void beforeEnter( final SessionData sessionData = session.getAttribute(SessionData.class); if(sessionData != null) { - this.add(new Label(getTranslation("INTERNAL_ERROR_HINT", sessionData.baseUrl()))); + this.add(new NativeLabel(this.getTranslation("INTERNAL_ERROR_HINT", sessionData.baseUrl()))); } final Throwable t = (Throwable)session.getAttribute( @@ -103,7 +103,7 @@ public void beforeEnter( stackTrace.setReadOnly(true); stackTrace.setWidth("100%"); - final Details details = new Details(getTranslation("DETAILS"), stackTrace); + final Details details = new Details(this.getTranslation("DETAILS"), stackTrace); details.setOpened(false); this.add(details); this.setHorizontalComponentAlignment(Alignment.STRETCH, details); diff --git a/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/RootLayout.java b/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/RootLayout.java index da38affe..66162e8f 100644 --- a/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/RootLayout.java +++ b/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/RootLayout.java @@ -19,31 +19,30 @@ import com.vaadin.flow.component.Component; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.ButtonVariant; -import com.vaadin.flow.component.dependency.HtmlImport; +import com.vaadin.flow.component.dependency.CssImport; import com.vaadin.flow.component.html.Image; -import com.vaadin.flow.component.html.Label; +import com.vaadin.flow.component.html.NativeLabel; import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.component.page.AppShellConfigurator; import com.vaadin.flow.component.page.Push; import com.vaadin.flow.router.BeforeEnterEvent; import com.vaadin.flow.router.BeforeEnterObserver; import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.server.InitialPageSettings; -import com.vaadin.flow.server.PageConfigurator; import com.vaadin.flow.theme.Theme; import com.vaadin.flow.theme.lumo.Lumo; @Push -@Theme(value = Lumo.class, variant = Lumo.DARK) -@HtmlImport("styles/shared-styles.html") -public class RootLayout extends VerticalLayout - implements RouterLayout, BeforeEnterObserver, PageConfigurator +@Theme(themeClass = Lumo.class, variant = Lumo.DARK) +@CssImport("./styles/shared-styles.css") +public class RootLayout extends VerticalLayout + implements RouterLayout, BeforeEnterObserver, AppShellConfigurator { public final static String PAGE_TITLE = "Eclipse Store Client"; - private Component toolBar; - private Label headerLabel; + private Component toolBar; + private NativeLabel headerLabel; public RootLayout() { @@ -58,7 +57,7 @@ public RootLayout() private Component createHeader() { - this.headerLabel = new Label(); + this.headerLabel = new NativeLabel(); final Button cmdDisconnect = new Button(this.getTranslation("DISCONNECT"), event -> { this.getUI().ifPresent(ui -> { @@ -90,7 +89,7 @@ private Component createHeader() public void beforeEnter( final BeforeEnterEvent event ) - { + { final SessionData sessionData = event.getUI().getSession().getAttribute(SessionData.class); this.headerLabel.setText( sessionData != null @@ -103,12 +102,4 @@ public void beforeEnter( ); } - @Override - public void configurePage( - final InitialPageSettings settings - ) - { - settings.addLink ("shortcut icon", UIUtils.imagePath("icon.ico") ); - settings.addFavIcon("icon" , UIUtils.imagePath("icon.png"), "256x256"); - } } diff --git a/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/RouteNotFoundView.java b/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/RouteNotFoundView.java index 66741e1c..07e49933 100644 --- a/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/RouteNotFoundView.java +++ b/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/RouteNotFoundView.java @@ -14,8 +14,6 @@ * #L% */ -import javax.servlet.http.HttpServletResponse; - import com.vaadin.flow.component.html.Span; import com.vaadin.flow.router.BeforeEnterEvent; import com.vaadin.flow.router.ErrorParameter; @@ -24,6 +22,8 @@ import com.vaadin.flow.router.Route; import com.vaadin.flow.router.RouteNotFoundError; +import jakarta.servlet.http.HttpServletResponse; + @Route(value = "404", layout = RootLayout.class) @PageTitle("404 - " + RootLayout.PAGE_TITLE) public class RouteNotFoundView extends RouteNotFoundError @@ -36,7 +36,7 @@ public RouteNotFoundView() @Override public int setErrorParameter(BeforeEnterEvent event, ErrorParameter parameter) { - getElement().appendChild(new Span("404 - not found").getElement()); + this.getElement().appendChild(new Span("404 - not found").getElement()); return HttpServletResponse.SC_NOT_FOUND; } diff --git a/storage/rest/client-app/src/main/resources/META-INF/resources/frontend/styles/shared-styles.html b/storage/rest/client-app/src/main/resources/META-INF/resources/frontend/styles/shared-styles.css similarity index 97% rename from storage/rest/client-app/src/main/resources/META-INF/resources/frontend/styles/shared-styles.html rename to storage/rest/client-app/src/main/resources/META-INF/resources/frontend/styles/shared-styles.css index 3ab7e5c3..d3f0768b 100644 --- a/storage/rest/client-app/src/main/resources/META-INF/resources/frontend/styles/shared-styles.html +++ b/storage/rest/client-app/src/main/resources/META-INF/resources/frontend/styles/shared-styles.css @@ -1,6 +1,3 @@ - - - diff --git a/storage/rest/client-app/src/main/resources/logback.xml b/storage/rest/client-app/src/main/resources/logback.xml new file mode 100644 index 00000000..b59fd428 --- /dev/null +++ b/storage/rest/client-app/src/main/resources/logback.xml @@ -0,0 +1,11 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp -%msg%n + + + + + + + \ No newline at end of file diff --git a/storage/rest/client-jersey/pom.xml b/storage/rest/client-jersey/pom.xml index 93c329da..eda89698 100644 --- a/storage/rest/client-jersey/pom.xml +++ b/storage/rest/client-jersey/pom.xml @@ -14,15 +14,15 @@ storage-restclient-jersey - + EclipseStore Storage REST Client Jersey Jersey REST Client Implementation https://projects.eclipse.org/projects/technology.store - + - 2.33 - 2.8.9 - 2.3.1 + 3.1.4 + 2.10.1 + 4.0.1 @@ -47,9 +47,9 @@ ${gson.version} - javax.xml.bind - jaxb-api - ${jaxb.version} + jakarta.xml.bind + jakarta.xml.bind-api + 4.0.1 diff --git a/storage/rest/client-jersey/src/main/java/org/eclipse/store/storage/restclient/jersey/types/GsonReader.java b/storage/rest/client-jersey/src/main/java/org/eclipse/store/storage/restclient/jersey/types/GsonReader.java index df2512c4..e01d229f 100644 --- a/storage/rest/client-jersey/src/main/java/org/eclipse/store/storage/restclient/jersey/types/GsonReader.java +++ b/storage/rest/client-jersey/src/main/java/org/eclipse/store/storage/restclient/jersey/types/GsonReader.java @@ -24,18 +24,17 @@ import java.time.Instant; import java.util.Date; -import javax.ws.rs.Consumes; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.ext.MessageBodyReader; -import javax.ws.rs.ext.Provider; - import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonDeserializer; import com.google.gson.LongSerializationPolicy; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.ext.MessageBodyReader; +import jakarta.ws.rs.ext.Provider; @Provider @Consumes(MediaType.APPLICATION_JSON) diff --git a/storage/rest/client-jersey/src/main/java/org/eclipse/store/storage/restclient/jersey/types/StorageRestClientJersey.java b/storage/rest/client-jersey/src/main/java/org/eclipse/store/storage/restclient/jersey/types/StorageRestClientJersey.java index 48eaba24..567d61b4 100644 --- a/storage/rest/client-jersey/src/main/java/org/eclipse/store/storage/restclient/jersey/types/StorageRestClientJersey.java +++ b/storage/rest/client-jersey/src/main/java/org/eclipse/store/storage/restclient/jersey/types/StorageRestClientJersey.java @@ -20,22 +20,22 @@ import java.util.Map; import java.util.function.Consumer; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.MediaType; - -import org.eclipse.store.storage.restadapter.types.ViewerObjectDescription; -import org.eclipse.store.storage.restadapter.types.ViewerRootDescription; -import org.eclipse.store.storage.restadapter.types.ViewerStorageFileStatistics; -import org.eclipse.store.storage.restclient.types.ObjectRequest; -import org.eclipse.store.storage.restclient.types.StorageRestClient; import org.eclipse.serializer.persistence.binary.types.BinaryFieldLengthResolver; import org.eclipse.serializer.persistence.types.PersistenceTypeDescription; import org.eclipse.serializer.persistence.types.PersistenceTypeDictionaryParser; import org.eclipse.serializer.persistence.types.PersistenceTypeNameMapper; import org.eclipse.serializer.persistence.types.PersistenceTypeResolver; import org.eclipse.serializer.reflect.ClassLoaderProvider; +import org.eclipse.store.storage.restadapter.types.ViewerObjectDescription; +import org.eclipse.store.storage.restadapter.types.ViewerRootDescription; +import org.eclipse.store.storage.restadapter.types.ViewerStorageFileStatistics; +import org.eclipse.store.storage.restclient.types.ObjectRequest; +import org.eclipse.store.storage.restclient.types.StorageRestClient; + +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.MediaType; public interface StorageRestClientJersey extends StorageRestClient @@ -90,7 +90,7 @@ public void setClientCustomizer( final Consumer clientCustomizer ) { - this.clientCustomizer = clientCustomizer; + this.clientCustomizer = clientCustomizer; } private WebTarget storageRestService() diff --git a/storage/rest/pom.xml b/storage/rest/pom.xml index ee4316e6..5362fa3e 100644 --- a/storage/rest/pom.xml +++ b/storage/rest/pom.xml @@ -15,7 +15,7 @@ storage-rest-parent pom - + EclipseStore Storage REST Parent EclipseStore Storage REST Project https://projects.eclipse.org/projects/technology.store @@ -23,10 +23,21 @@ adapter client - client-app client-jersey service service-sparkjava + + + from_java_17 + + [17,) + + + client-app + + + + From ee3a92d179f081848b0a14392ff90dc5cc02c138 Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Wed, 17 Jan 2024 16:23:26 +0100 Subject: [PATCH 064/126] Wait until table is created (#118) --- .../afs/aws/dynamodb/types/DynamoDbConnector.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/afs/aws/dynamodb/src/main/java/org/eclipse/store/afs/aws/dynamodb/types/DynamoDbConnector.java b/afs/aws/dynamodb/src/main/java/org/eclipse/store/afs/aws/dynamodb/types/DynamoDbConnector.java index 1af717db..63d9edc1 100644 --- a/afs/aws/dynamodb/src/main/java/org/eclipse/store/afs/aws/dynamodb/types/DynamoDbConnector.java +++ b/afs/aws/dynamodb/src/main/java/org/eclipse/store/afs/aws/dynamodb/types/DynamoDbConnector.java @@ -27,6 +27,7 @@ import java.util.regex.Pattern; import java.util.stream.Stream; +import org.eclipse.serializer.concurrency.XThreads; import org.eclipse.serializer.exceptions.IORuntimeException; import org.eclipse.serializer.io.ByteBufferInputStream; import org.eclipse.serializer.io.LimitedInputStream; @@ -40,6 +41,7 @@ import software.amazon.awssdk.services.dynamodb.model.BillingMode; import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest; import software.amazon.awssdk.services.dynamodb.model.Delete; +import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest; import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement; @@ -53,6 +55,7 @@ import software.amazon.awssdk.services.dynamodb.model.ScanResponse; import software.amazon.awssdk.services.dynamodb.model.Select; import software.amazon.awssdk.services.dynamodb.model.TableDescription; +import software.amazon.awssdk.services.dynamodb.model.TableStatus; import software.amazon.awssdk.services.dynamodb.model.TransactWriteItem; import software.amazon.awssdk.services.dynamodb.model.TransactWriteItemsRequest; @@ -181,7 +184,16 @@ private TableDescription createTable( .billingMode(BillingMode.PAY_PER_REQUEST) .build() ; - return this.client.createTable(request).tableDescription(); + TableDescription description = this.client.createTable(request).tableDescription(); + while(description.tableStatus() != TableStatus.ACTIVE) + { + XThreads.sleep(1000l); + + description = this.client.describeTable( + DescribeTableRequest.builder().tableName(name).build() + ).table(); + } + return description; } } From 4050ca93a01f6e503f3f8948f64a11573bcb4d93 Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Thu, 18 Jan 2024 13:08:20 +0100 Subject: [PATCH 065/126] Feature/monitoring (#77) JMX Storage monitoring support --------- Co-authored-by: Florian Habermann Co-authored-by: Zdenek Jonas --- .../EmbeddedStorageConnectionFoundation.java | 8 +- .../types/EmbeddedStorageFoundation.java | 7 +- .../types/EmbeddedStorageManager.java | 19 +- .../monitoring/EntityCacheMonitor.java | 72 +++++++ .../monitoring/EntityCacheMonitorMBean.java | 66 ++++++ .../monitoring/EntityCacheSummaryMonitor.java | 57 ++++++ .../EntityCacheSummaryMonitorMBean.java | 42 ++++ .../monitoring/ObjectRegistryMonitor.java | 50 +++++ .../ObjectRegistryMonitorMBean.java | 42 ++++ .../StorageChannelHousekeepingMonitor.java | 128 ++++++++++++ ...torageChannelHousekeepingMonitorMBean.java | 123 +++++++++++ .../monitoring/StorageManagerMonitor.java | 192 ++++++++++++++++++ .../StorageManagerMonitorMXBean.java | 59 ++++++ .../store/storage/types/StorageChannel.java | 33 ++- .../StorageChannelHousekeepingResult.java | 95 +++++++++ .../storage/types/StorageChannelsCreator.java | 24 ++- .../storage/types/StorageEntityCache.java | 4 +- .../storage/types/StorageFoundation.java | 31 ++- .../store/storage/types/StorageSystem.java | 11 +- 19 files changed, 1040 insertions(+), 23 deletions(-) create mode 100644 storage/storage/src/main/java/org/eclipse/store/storage/monitoring/EntityCacheMonitor.java create mode 100644 storage/storage/src/main/java/org/eclipse/store/storage/monitoring/EntityCacheMonitorMBean.java create mode 100644 storage/storage/src/main/java/org/eclipse/store/storage/monitoring/EntityCacheSummaryMonitor.java create mode 100644 storage/storage/src/main/java/org/eclipse/store/storage/monitoring/EntityCacheSummaryMonitorMBean.java create mode 100644 storage/storage/src/main/java/org/eclipse/store/storage/monitoring/ObjectRegistryMonitor.java create mode 100644 storage/storage/src/main/java/org/eclipse/store/storage/monitoring/ObjectRegistryMonitorMBean.java create mode 100644 storage/storage/src/main/java/org/eclipse/store/storage/monitoring/StorageChannelHousekeepingMonitor.java create mode 100644 storage/storage/src/main/java/org/eclipse/store/storage/monitoring/StorageChannelHousekeepingMonitorMBean.java create mode 100644 storage/storage/src/main/java/org/eclipse/store/storage/monitoring/StorageManagerMonitor.java create mode 100644 storage/storage/src/main/java/org/eclipse/store/storage/monitoring/StorageManagerMonitorMXBean.java create mode 100644 storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannelHousekeepingResult.java diff --git a/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageConnectionFoundation.java b/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageConnectionFoundation.java index a6f3647f..9f633f42 100644 --- a/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageConnectionFoundation.java +++ b/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageConnectionFoundation.java @@ -18,10 +18,6 @@ import java.util.function.Supplier; -import org.eclipse.store.storage.types.StorageConnection; -import org.eclipse.store.storage.types.StorageRequestAcceptor; -import org.eclipse.store.storage.types.StorageSystem; -import org.eclipse.store.storage.types.StorageWriteController; import org.eclipse.serializer.exceptions.MissingFoundationPartException; import org.eclipse.serializer.persistence.binary.types.Binary; import org.eclipse.serializer.persistence.binary.types.BinaryLoader; @@ -31,6 +27,10 @@ import org.eclipse.serializer.persistence.types.PersistenceManager; import org.eclipse.serializer.persistence.types.PersistenceStorer; import org.eclipse.serializer.reference.Reference; +import org.eclipse.store.storage.types.StorageConnection; +import org.eclipse.store.storage.types.StorageRequestAcceptor; +import org.eclipse.store.storage.types.StorageSystem; +import org.eclipse.store.storage.types.StorageWriteController; public interface EmbeddedStorageConnectionFoundation> extends BinaryPersistenceFoundation diff --git a/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageFoundation.java b/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageFoundation.java index 35b690bd..6e26cbd2 100644 --- a/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageFoundation.java +++ b/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageFoundation.java @@ -807,7 +807,12 @@ public synchronized EmbeddedStorageManager createEmbeddedStorageManager(final Ob this.initializeEmbeddedStorageRootTypeIdProvider(this.getRootTypeIdProvider(), thm); // everything bundled together in the actual manager instance - final EmbeddedStorageManager esm = EmbeddedStorageManager.New(database, stm.configuration(), ecf, prp); + final EmbeddedStorageManager esm = EmbeddedStorageManager.New( + database, + stm.configuration(), + ecf, + prp, + this.getStorageMonitorManager()); // link back to database database.setStorage(esm); diff --git a/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageManager.java b/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageManager.java index f87da3b1..ff01d936 100644 --- a/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageManager.java +++ b/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageManager.java @@ -25,6 +25,7 @@ import org.eclipse.serializer.collections.XSort; import org.eclipse.serializer.collections.types.XGettingEnum; import org.eclipse.serializer.collections.types.XGettingTable; +import org.eclipse.serializer.monitoring.MonitoringManager; import org.eclipse.serializer.persistence.binary.types.Binary; import org.eclipse.serializer.persistence.types.Persistence; import org.eclipse.serializer.persistence.types.PersistenceManager; @@ -40,6 +41,8 @@ import org.eclipse.serializer.typing.KeyValue; import org.eclipse.serializer.util.logging.Logging; import org.eclipse.store.storage.exceptions.StorageExceptionConsistency; +import org.eclipse.store.storage.monitoring.StorageManagerMonitor; +import org.eclipse.store.storage.monitoring.ObjectRegistryMonitor; import org.eclipse.store.storage.types.Database; import org.eclipse.store.storage.types.StorageConfiguration; import org.eclipse.store.storage.types.StorageConnection; @@ -75,14 +78,16 @@ public static EmbeddedStorageManager.Default New( final Database database , final StorageConfiguration configuration , final EmbeddedStorageConnectionFoundation connectionFoundation, - final PersistenceRootsProvider rootsProvider + final PersistenceRootsProvider rootsProvider , + final MonitoringManager monitorManager ) { return new EmbeddedStorageManager.Default( notNull(database) , notNull(configuration) , notNull(connectionFoundation), - notNull(rootsProvider) + notNull(rootsProvider) , + monitorManager ); } @@ -104,6 +109,8 @@ public final class Default implements EmbeddedStorageManager, Unpersistable, Laz private StorageConnection singletonConnection; + private final MonitoringManager monitorManager; + /////////////////////////////////////////////////////////////////////////// @@ -114,7 +121,8 @@ public final class Default implements EmbeddedStorageManager, Unpersistable, Laz final Database database , final StorageConfiguration configuration , final EmbeddedStorageConnectionFoundation connectionFoundation, - final PersistenceRootsProvider rootsProvider + final PersistenceRootsProvider rootsProvider , + final MonitoringManager monitorManager ) { super(); @@ -123,6 +131,7 @@ public final class Default implements EmbeddedStorageManager, Unpersistable, Laz this.storageSystem = connectionFoundation.getStorageSystem(); // to ensure consistency this.connectionFoundation = connectionFoundation ; this.rootsProvider = rootsProvider ; + this.monitorManager = monitorManager ; } @@ -270,6 +279,8 @@ public final EmbeddedStorageManager.Default start() throw t; } + this.monitorManager.registerMonitor(new StorageManagerMonitor(this)); + return this; } @@ -354,6 +365,8 @@ private void initialize() try { final StorageConnection initConnection = this.createConnection(); + + this.monitorManager.registerMonitor(new ObjectRegistryMonitor(initConnection.persistenceManager().objectRegistry())); PersistenceRoots loadedRoots = this.loadExistingRoots(initConnection); if(loadedRoots == null) diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/EntityCacheMonitor.java b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/EntityCacheMonitor.java new file mode 100644 index 00000000..486e4ed0 --- /dev/null +++ b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/EntityCacheMonitor.java @@ -0,0 +1,72 @@ +package org.eclipse.store.storage.monitoring; + +/*- + * #%L + * EclipseStore Storage + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.lang.ref.WeakReference; + +import org.eclipse.serializer.monitoring.MetricMonitor; +import org.eclipse.store.storage.types.StorageEntityCache; + +public class EntityCacheMonitor implements EntityCacheMonitorMBean, MetricMonitor +{ + private final WeakReference storageEntityCache; + private int channelIndex; + + public EntityCacheMonitor(final StorageEntityCache.Default storageEntityCache) + { + super(); + this.storageEntityCache = new WeakReference<>(storageEntityCache); + this.channelIndex = storageEntityCache.channelIndex(); + } + + @Override + public int getChannelIndex() + { + return this.channelIndex; + } + + @Override + public long getLastSweepStart() + { + return this.storageEntityCache.get().lastSweepStart(); + } + + @Override + public long getLastSweepEnd() + { + return this.storageEntityCache.get().lastSweepEnd(); + } + + @Override + public long getEntityCount() + { + return this.storageEntityCache.get().entityCount(); + } + + @Override + public long getUsedCacheSize() + { + return this.storageEntityCache.get().cacheSize(); + } + + @Override + public String getName() + { + return "channel=channel-" + + this.channelIndex + + ",group=Entity cache"; + } + +} diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/EntityCacheMonitorMBean.java b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/EntityCacheMonitorMBean.java new file mode 100644 index 00000000..6f0026e0 --- /dev/null +++ b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/EntityCacheMonitorMBean.java @@ -0,0 +1,66 @@ +package org.eclipse.store.storage.monitoring; + +/*- + * #%L + * EclipseStore Storage + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.monitoring.MonitorDescription; +import org.eclipse.store.storage.types.StorageEntityCache; + +/** + * JMX MBean definition that provides monitoring and metrics for + * a {@link StorageEntityCache} instance. + */ +@MonitorDescription("Provides monitoring and metrics data of a StorageEntityCache instance.") +public interface EntityCacheMonitorMBean +{ + /** + * Get the channel index. + * + * @return the channel index. + */ + @MonitorDescription("The channel index") + public int getChannelIndex(); + + /** + * Get the timestamp of the last start of a cache sweep. + * + * @return time stamp in ms. + */ + @MonitorDescription("Timestamp of the last start of a cache sweep in ms.") + public long getLastSweepStart(); + + /** + * Get the timestamp of the last end of a cache sweep. + * + * @return time stamp in ms. + */ + @MonitorDescription("Timestamp of the last end of a cache sweep in ms.") + public long getLastSweepEnd(); + + /** + * The number of entries in the channels entity cache. + * + * @return The number of entries in the channels entity cache. + */ + @MonitorDescription("The number of entries in the channels entity cache.") + public long getEntityCount(); + + /** + * Get the used cache size in bytes. + * + * @return used cache size in bytes. + */ + @MonitorDescription("The used cache size in bytes.") + public long getUsedCacheSize(); +} diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/EntityCacheSummaryMonitor.java b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/EntityCacheSummaryMonitor.java new file mode 100644 index 00000000..540879f1 --- /dev/null +++ b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/EntityCacheSummaryMonitor.java @@ -0,0 +1,57 @@ +package org.eclipse.store.storage.monitoring; + +/*- + * #%L + * EclipseStore Storage + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.monitoring.MetricMonitor; + +public class EntityCacheSummaryMonitor implements EntityCacheSummaryMonitorMBean, MetricMonitor +{ + private final EntityCacheMonitor[] cacheMonitors; + + public EntityCacheSummaryMonitor(final EntityCacheMonitor[] cacheMonitors) + { + this.cacheMonitors = cacheMonitors; + } + + @Override + public String getName() + { + return "name=EntityCacheSummary"; + } + + @Override + public synchronized long getEntityCount() + { + int entityCount = 0; + for (final EntityCacheMonitor entityCacheMonitor : this.cacheMonitors) + { + entityCount += entityCacheMonitor.getEntityCount(); + } + return entityCount; + + } + + @Override + public synchronized long getUsedCacheSize() + { + int usedCacheSize = 0; + for (final EntityCacheMonitor entityCacheMonitor : this.cacheMonitors) + { + usedCacheSize += entityCacheMonitor.getUsedCacheSize(); + } + return usedCacheSize; + } + +} diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/EntityCacheSummaryMonitorMBean.java b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/EntityCacheSummaryMonitorMBean.java new file mode 100644 index 00000000..3f980773 --- /dev/null +++ b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/EntityCacheSummaryMonitorMBean.java @@ -0,0 +1,42 @@ +package org.eclipse.store.storage.monitoring; + +/*- + * #%L + * EclipseStore Storage + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.monitoring.MonitorDescription; +import org.eclipse.store.storage.types.StorageEntityCache; + +/** + * JMX MBean definition that provides a summary of monitoring and metrics for + * all {@link StorageEntityCache} instances of a storage. + */ +@MonitorDescription("Provides a summary of all storage channels entity caches.") +public interface EntityCacheSummaryMonitorMBean +{ + /** + * Get the aggregated used cache size from all channel entity caches in bytes. + * + * @return used cache size in bytes. + */ + @MonitorDescription("The total size of all channel entity caches in bytes.") + long getUsedCacheSize(); + + /** + * The number of entries aggregated from all channel entity caches. + * + * @return The number of entries. + */ + @MonitorDescription("The number of entries aggregated from all channel entity caches.") + long getEntityCount(); +} diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/ObjectRegistryMonitor.java b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/ObjectRegistryMonitor.java new file mode 100644 index 00000000..630bde2d --- /dev/null +++ b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/ObjectRegistryMonitor.java @@ -0,0 +1,50 @@ +package org.eclipse.store.storage.monitoring; + +/*- + * #%L + * EclipseStore Storage + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.lang.ref.WeakReference; + +import org.eclipse.serializer.monitoring.MetricMonitor; +import org.eclipse.serializer.persistence.types.PersistenceObjectRegistry; + +public class ObjectRegistryMonitor implements ObjectRegistryMonitorMBean, MetricMonitor +{ + WeakReference persistenceObjectRegistry; + + public ObjectRegistryMonitor(final PersistenceObjectRegistry persistenceObjectRegistry) + { + super(); + this.persistenceObjectRegistry = new WeakReference<>(persistenceObjectRegistry); + } + + @Override + public long getCapacity() + { + return this.persistenceObjectRegistry.get().capacity(); + } + + @Override + public long getSize() + { + return this.persistenceObjectRegistry.get().size(); + } + + @Override + public String getName() + { + return "name=ObjectRegistry"; + } + +} diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/ObjectRegistryMonitorMBean.java b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/ObjectRegistryMonitorMBean.java new file mode 100644 index 00000000..5dd30ded --- /dev/null +++ b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/ObjectRegistryMonitorMBean.java @@ -0,0 +1,42 @@ +package org.eclipse.store.storage.monitoring; + +/*- + * #%L + * EclipseStore Storage + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.monitoring.MonitorDescription; +import org.eclipse.serializer.persistence.types.PersistenceObjectRegistry; + +/** + * JMX MBean definition that provides monitoring and metrics for + * a {@link PersistenceObjectRegistry} instance. + */ +@MonitorDescription("Provides object registry related data.") +public interface ObjectRegistryMonitorMBean +{ + /** + * Get the number of registered objects (size of object registry). + * + * @return the number of registered objects. + */ + @MonitorDescription("The number of currently registered objects.") + long getSize(); + + /** + * Get the reserved size (number of objects) of the object registry. + * + * @return reserved size (as number of objects). + */ + @MonitorDescription("The reserved size(number of objects) of the object registry.") + long getCapacity(); +} diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/StorageChannelHousekeepingMonitor.java b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/StorageChannelHousekeepingMonitor.java new file mode 100644 index 00000000..6e38dad0 --- /dev/null +++ b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/StorageChannelHousekeepingMonitor.java @@ -0,0 +1,128 @@ +package org.eclipse.store.storage.monitoring; + +/*- + * #%L + * EclipseStore Storage + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.monitoring.MetricMonitor; +import org.eclipse.store.storage.types.StorageChannelHousekeepingResult; + +public class StorageChannelHousekeepingMonitor implements StorageChannelHousekeepingMonitorMBean, MetricMonitor +{ + private final int channelIndex; + private StorageChannelHousekeepingResult fileCleanupCheckResult; + private StorageChannelHousekeepingResult garbageCollectionResult; + private StorageChannelHousekeepingResult entityCacheCheckResult; + + + public StorageChannelHousekeepingMonitor(final int channelIndex) + { + this.channelIndex = channelIndex; + } + + @Override + public String getName() + { + return "channel=channel-" + + this.channelIndex + + ",group=housekeeping"; + } + + public void setFileCleanupCheckResult(final StorageChannelHousekeepingResult fileCleanupCheckResult) + { + this.fileCleanupCheckResult = fileCleanupCheckResult; + } + + public void setGarbageCollectionResult(final StorageChannelHousekeepingResult garbageCollectionResult) + { + this.garbageCollectionResult = garbageCollectionResult; + } + + public void setEntityCacheCheckResult(final StorageChannelHousekeepingResult entityCacheCheckResult) + { + this.entityCacheCheckResult = entityCacheCheckResult; + } + + @Override + public long getFileCleanupCheckDuration() + { + return this.fileCleanupCheckResult.getDuration(); + } + + @Override + public long getFileCleanupCheckStartTime() + { + return this.fileCleanupCheckResult.getStartTime(); + } + + @Override + public boolean getFileCleanupCheckResult() + { + return this.fileCleanupCheckResult.getResult(); + } + + @Override + public long getFileCleanupCheckBudget() + { + return this.fileCleanupCheckResult.getBudget(); + } + + @Override + public long getGarbageCollectionDuration() + { + return this.garbageCollectionResult.getDuration(); + } + + @Override + public long getGarbageCollectionStartTime() + { + return this.garbageCollectionResult.getStartTime(); + } + + @Override + public boolean getGarbageCollectionResult() + { + return this.garbageCollectionResult.getResult(); + } + + @Override + public long getGarbageCollectionBudget() + { + return this.garbageCollectionResult.getBudget(); + } + + @Override + public long getEntityCacheCheckDuration() + { + return this.entityCacheCheckResult.getDuration(); + } + + @Override + public long getEntityCacheCheckStartTime() + { + return this.entityCacheCheckResult.getStartTime(); + } + + @Override + public boolean getEntityCacheCheckResult() + { + return this.entityCacheCheckResult.getResult(); + } + + @Override + public long getEntityCacheCheckBudget() + { + return this.entityCacheCheckResult.getBudget(); + } + +} diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/StorageChannelHousekeepingMonitorMBean.java b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/StorageChannelHousekeepingMonitorMBean.java new file mode 100644 index 00000000..445e4ea5 --- /dev/null +++ b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/StorageChannelHousekeepingMonitorMBean.java @@ -0,0 +1,123 @@ +package org.eclipse.store.storage.monitoring; + +/*- + * #%L + * EclipseStore Storage + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.monitoring.MonitorDescription; +import org.eclipse.store.storage.types.StorageChannel; + +/** + * JMX MBean definition that provides monitoring and metrics of + * the {@link StorageChannel}. + */ +@MonitorDescription("Provides monitoring and metrics data of a storage channel.") +public interface StorageChannelHousekeepingMonitorMBean +{ + /** + * Get the result of the last housekeeping cache check cycle. + * + * @return True if cache is empty. + */ + @MonitorDescription("Result of the last housekeeping cache check.") + boolean getEntityCacheCheckResult(); + + /** + * Get starting time of the last housekeeping cache check cycle. + * + * @return Time in ms since 1970. + */ + @MonitorDescription("Starting time of the last housekeeping cache check in ms since 1970.") + long getEntityCacheCheckStartTime(); + + /** + * Get the duration of the last housekeeping cache check cycle in ns. + * + * @return Duration of the last housekeeping cache check cycle in ns. + */ + @MonitorDescription("Duration of the last housekeeping cache check cycle in ns") + long getEntityCacheCheckDuration(); + + /** + * Get the time budget of the last housekeeping cache check cycle in ns. + * + * @return Time budget of the last housekeeping cache check cycle in ns. + */ + @MonitorDescription("Time budget of the last housekeeping cache check cycle in ns.") + long getEntityCacheCheckBudget(); + + /** + * Get the result of the last housekeeping garbage collection cycle. + * + * @return True if completed in time budget. + */ + @MonitorDescription("Result of the last housekeeping garbage collection cycle.") + boolean getGarbageCollectionResult(); + + /** + * Get starting time of the last housekeeping garbage collection cycle. + * + * @return Time in ms since 1970. + */ + @MonitorDescription("Starting time of the last housekeeping garbage collection cycle in ms since 1970.") + long getGarbageCollectionStartTime(); + + /** + * Get the duration of the last housekeeping garbage collection cycle in ns. + * + * @return Duration of the last housekeeping garbage collection cycle in ns. + */ + @MonitorDescription("Duration of the last housekeeping garbage collection cycle in ns") + long getGarbageCollectionDuration(); + + /** + * Get the time budget of the last housekeeping garbage collection cycle in ns. + * + * @return Time budget of the last housekeeping garbage collection cycle in ns. + */ + @MonitorDescription("Time budget of the last housekeeping garbage collection cycle in ns.") + long getGarbageCollectionBudget(); + + /** + * Get the result of the last housekeeping file cleanup cycle. + * + * @return True if completed in time budget. + */ + @MonitorDescription("Result of the last housekeeping file cleanup cycle.") + boolean getFileCleanupCheckResult(); + + /** + * Get starting time of the last housekeeping file cleanup cycle. + * + * @return Time in ms since 1970. + */ + @MonitorDescription("Starting time of the last housekeeping file cleanup cycle in ms since 1970.") + long getFileCleanupCheckStartTime(); + + /** + * Get the duration of the last housekeeping file cleanup cycle in ns. + * + * @return Duration of the last housekeeping file cleanup cycle in ns. + */ + @MonitorDescription("Duration of the last housekeeping file cleanup cycle in ns") + long getFileCleanupCheckDuration(); + + /** + * Get the time budget of the last housekeeping file cleanup cycle in ns. + * + * @return Time budget of the last housekeeping file cleanup cycle in ns. + */ + @MonitorDescription("Time budget of the last housekeeping garbage collection cycle in ns.") + long getFileCleanupCheckBudget(); + +} diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/StorageManagerMonitor.java b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/StorageManagerMonitor.java new file mode 100644 index 00000000..86e0067b --- /dev/null +++ b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/StorageManagerMonitor.java @@ -0,0 +1,192 @@ +package org.eclipse.store.storage.monitoring; + +/*- + * #%L + * EclipseStore Storage + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.lang.ref.WeakReference; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.serializer.monitoring.MetricMonitor; +import org.eclipse.serializer.typing.KeyValue; +import org.eclipse.store.storage.types.StorageManager; +import org.eclipse.store.storage.types.StorageRawFileStatistics; + +public class StorageManagerMonitor implements StorageManagerMonitorMXBean, MetricMonitor +{ + + private final WeakReference storageManager; + + + public static class FileStatistics + { + + private final String fileName; + private final long totalDataLength; + private final long liveDataLength; + + public FileStatistics(final org.eclipse.store.storage.types.StorageRawFileStatistics.FileStatistics fileStatistics) + { + this.fileName = fileStatistics.file(); + this.totalDataLength = fileStatistics.totalDataLength(); + this.liveDataLength = fileStatistics.liveDataLength(); + } + + public String getFileName() + { + return this.fileName; + } + + public long getTotalDataLength() + { + return this.totalDataLength; + } + + public long getLiveDataLength() + { + return this.liveDataLength; + } + + } + + public static class ChannelStatistics + { + + private final long fileCount; + private final long totalDataLength; + private final long liveDataLength; + + private final List fileStatistics = new ArrayList<>(); + + public ChannelStatistics( + final KeyValue channelStatistics) + { + + this.fileCount = channelStatistics.value().fileCount(); + this.totalDataLength = channelStatistics.value().totalDataLength(); + this.liveDataLength = channelStatistics.value().liveDataLength(); + + channelStatistics.value().files().forEach(f -> this.fileStatistics.add(new FileStatistics(f))); + } + + public long getFileCount() + { + return this.fileCount; + } + + public long getTotalDataLength() + { + return this.totalDataLength; + } + + public long getLiveDataLength() + { + return this.liveDataLength; + } + + public List getFileStatistics() + { + return this.fileStatistics; + } + } + + public static class StorageStatistics + { + + private final int channelCount; + private final long fileCount; + private final long totalDataLength; + private final long liveDataLength; + + private final List channelStatistics = new ArrayList<>(); + + public StorageStatistics(final StorageRawFileStatistics statistics) + { + this.channelCount = statistics.channelCount(); + this.fileCount = statistics.fileCount(); + this.totalDataLength = statistics.totalDataLength(); + this.liveDataLength = statistics.liveDataLength(); + + statistics.channelStatistics().forEach( c-> this.channelStatistics.add(new ChannelStatistics(c))); + } + + public int getChannelCount() + { + return this.channelCount; + } + + public long getFileCount() + { + return this.fileCount; + } + + public long getTotalDataLength() + { + return this.totalDataLength; + } + + public long getLiveDataLength() + { + return this.liveDataLength; + } + + public double getUsageRatio() + { + return ((double)this.liveDataLength / (double)this.totalDataLength); + } + + public List getChannelStatistics() + { + return this.channelStatistics; + } + + } + + public StorageManagerMonitor(final StorageManager storageConnection) + { + this.storageManager = new WeakReference<>(storageConnection); + } + + @Override + public void issueFullGarbageCollection() + { + this.storageManager.get().issueFullGarbageCollection(); + } + + @Override + public void issueFullCacheCheck() + { + this.storageManager.get().issueFullCacheCheck(); + } + + @Override + public void issueFullFileCheck() + { + this.storageManager.get().issueFullFileCheck(); + } + + @Override + public StorageStatistics getStorageStatistics() + { + return new StorageStatistics(this.storageManager.get().createStorageStatistics()); + } + + @Override + public String getName() + { + return "name=EmbeddedStorage"; + } + +} diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/StorageManagerMonitorMXBean.java b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/StorageManagerMonitorMXBean.java new file mode 100644 index 00000000..213548c3 --- /dev/null +++ b/storage/storage/src/main/java/org/eclipse/store/storage/monitoring/StorageManagerMonitorMXBean.java @@ -0,0 +1,59 @@ +package org.eclipse.store.storage.monitoring; + +/*- + * #%L + * EclipseStore Storage + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.monitoring.MonitorDescription; + +import org.eclipse.store.storage.monitoring.StorageManagerMonitor.StorageStatistics; +import org.eclipse.store.storage.types.StorageManager; + +/** + * JMX MBean definition that provides monitoring and metrics for + * a {@link StorageManager} instance. + */ +@MonitorDescription("Provides storage statistics and house keeping operations") +public interface StorageManagerMonitorMXBean +{ + /** + * Get storage statistics. + * + * @return storage statistics. + */ + @MonitorDescription("query the storage for storage statistics. " + + "This will block storage operations until it is completed.") + StorageStatistics getStorageStatistics(); + + /** + * Issue a full storage garbage collection. + */ + @MonitorDescription("issue a full storage garbage collection run. " + + "This will block storage operations until it is completed.") + + void issueFullGarbageCollection(); + + /** + * Issue a full storage file check. + */ + @MonitorDescription("issue a full storage file check run. " + + "This will block storage operations until it is completed.") + void issueFullFileCheck(); + + /** + * Issue a full storage cache check. + */ + @MonitorDescription("issue a full storage chache check run. " + + "This will block storage operations until it is completed.") + void issueFullCacheCheck(); +} diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannel.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannel.java index 4ded8b5d..b1d99a6d 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannel.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannel.java @@ -26,6 +26,7 @@ import org.eclipse.serializer.collections.BulkList; import org.eclipse.serializer.functional.ThrowingProcedure; import org.eclipse.serializer.functional._longProcedure; +import org.eclipse.serializer.monitoring.MonitoringManager; import org.eclipse.serializer.persistence.binary.types.Chunk; import org.eclipse.serializer.persistence.binary.types.ChunksBuffer; import org.eclipse.serializer.persistence.binary.types.ChunksBufferByteReversing; @@ -38,6 +39,7 @@ import org.eclipse.serializer.util.X; import org.eclipse.serializer.util.logging.Logging; import org.eclipse.store.storage.exceptions.StorageExceptionConsistency; +import org.eclipse.store.storage.monitoring.StorageChannelHousekeepingMonitor; import org.slf4j.Logger; @@ -144,7 +146,8 @@ public final class Default implements StorageChannel, Unpersistable, StorageHous private long housekeepingIntervalBudgetNs; private boolean active; - + + private final StorageChannelHousekeepingMonitor monitoringData; /////////////////////////////////////////////////////////////////////////// @@ -162,7 +165,8 @@ public Default( final boolean switchByteOrder , final BufferSizeProviderIncremental loadingBufferSizeProvider, final StorageFileManager.Default fileManager , - final StorageEventLogger eventLogger + final StorageEventLogger eventLogger , + final MonitoringManager monitorManager ) { super(); @@ -180,6 +184,9 @@ public Default( // depends on this.fileManager! this.housekeepingTasks = this.defineHouseKeepingTasks(); + + this.monitoringData = new StorageChannelHousekeepingMonitor(this.channelIndex); + monitorManager.registerMonitor(this.monitoringData); } @@ -303,7 +310,13 @@ public final boolean performFileCleanupCheck(final long nanoTimeBudget) // turn budget into the budget bounding value for easier and faster checking final long nanoTimeBudgetBound = XTime.calculateNanoTimeBudgetBound(nanoTimeBudget); - return this.fileManager.incrementalFileCleanupCheck(nanoTimeBudgetBound); + + final StorageChannelHousekeepingResult result = StorageChannelHousekeepingResult.create(nanoTimeBudget, + () -> this.fileManager.incrementalFileCleanupCheck(nanoTimeBudgetBound)); + + this.monitoringData.setFileCleanupCheckResult(result); + + return result.getResult(); } @Override @@ -314,7 +327,12 @@ public boolean performGarbageCollection(final long nanoTimeBudget) // turn budget into the budget bounding value for easier and faster checking final long nanoTimeBudgetBound = XTime.calculateNanoTimeBudgetBound(nanoTimeBudget); - return this.entityCache.incrementalGarbageCollection(nanoTimeBudgetBound, this); + final StorageChannelHousekeepingResult result = StorageChannelHousekeepingResult.create(nanoTimeBudget, + () -> this.entityCache.incrementalGarbageCollection(nanoTimeBudgetBound, this)); + + this.monitoringData.setGarbageCollectionResult(result); + + return result.getResult(); } @Override @@ -327,7 +345,12 @@ public boolean performEntityCacheCheck( // turn budget into the budget bounding value for easier and faster checking final long nanoTimeBudgetBound = XTime.calculateNanoTimeBudgetBound(nanoTimeBudget); - return this.entityCache.incrementalEntityCacheCheck(nanoTimeBudgetBound); + final StorageChannelHousekeepingResult result = StorageChannelHousekeepingResult.create(nanoTimeBudget, + () -> this.entityCache.incrementalEntityCacheCheck(nanoTimeBudgetBound)); + + this.monitoringData.setEntityCacheCheckResult(result); + + return result.getResult(); } @Override diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannelHousekeepingResult.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannelHousekeepingResult.java new file mode 100644 index 00000000..b431ad47 --- /dev/null +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannelHousekeepingResult.java @@ -0,0 +1,95 @@ +package org.eclipse.store.storage.types; + +/*- + * #%L + * EclipseStore Storage + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.storage.types.StorageChannel.HousekeepingTask; + +public interface StorageChannelHousekeepingResult +{ + long getDuration(); + + long getStartTime(); + + boolean getResult(); + + long getBudget(); + + public static StorageChannelHousekeepingResult create(long nanoTimeBudget, final HousekeepingTask task) + { + final long startTime = System.currentTimeMillis(); + final long startTimeStamp = System.nanoTime(); + final boolean result = task.perform(); + final long duration = System.nanoTime() - startTimeStamp; + + return new Default(nanoTimeBudget, result, startTime, duration); + } + + public final class Default implements StorageChannelHousekeepingResult + { + /////////////////////////////////////////////////////////////////////////// + // instance fields // + //////////////////// + + private long nanoTimeBudget; + private final boolean result; + private final long startTime; + private final long duration; + + + /////////////////////////////////////////////////////////////////////////// + // constructors // + ///////////////// + + private Default(long nanoTimeBudget, final boolean result, final long startTime, final long duration) + { + super(); + this.nanoTimeBudget = nanoTimeBudget; + this.result = result; + this.startTime = startTime; + this.duration = duration; + } + + + /////////////////////////////////////////////////////////////////////////// + // methods // + //////////// + + @Override + public long getBudget() + { + return this.nanoTimeBudget; + } + + @Override + public boolean getResult() + { + return this.result; + } + + @Override + public long getStartTime() + { + return this.startTime; + } + + @Override + public long getDuration() + { + return this.duration; + } + + } + +} diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannelsCreator.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannelsCreator.java index e2857ff0..a5a4cb2a 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannelsCreator.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageChannelsCreator.java @@ -15,11 +15,14 @@ */ import org.eclipse.serializer.memory.XMemory; +import org.eclipse.serializer.monitoring.MonitoringManager; import org.eclipse.serializer.persistence.types.ObjectIdsSelector; import org.eclipse.serializer.persistence.types.PersistenceLiveStorerRegistry; import org.eclipse.serializer.reference.Referencing; import org.eclipse.serializer.util.BufferSizeProvider; import org.eclipse.serializer.util.BufferSizeProviderIncremental; +import org.eclipse.store.storage.monitoring.EntityCacheMonitor; +import org.eclipse.store.storage.monitoring.EntityCacheSummaryMonitor; public interface StorageChannelsCreator @@ -45,10 +48,11 @@ public StorageChannel[] createChannels( StorageEntityMarkMonitor.Creator entityMarkMonitorCreator , StorageBackupHandler backupHandler , StorageEventLogger eventLogger , - ObjectIdsSelector liveObjectIdChecker , + ObjectIdsSelector liveObjectIdChecker , Referencing refStorerRegistry , boolean switchByteOrder , - long rootTypeId + long rootTypeId , + MonitoringManager monitorManager ); @@ -84,7 +88,8 @@ public final StorageChannel.Default[] createChannels( final ObjectIdsSelector liveObjectIdChecker , final Referencing refStorerRegistry , final boolean switchByteOrder , - final long rootTypeId + final long rootTypeId , + final MonitoringManager monitorManager ) { // (14.07.2016 TM)TODO: make configuration dynamic @@ -108,7 +113,9 @@ public final StorageChannel.Default[] createChannels( final BufferSizeProviderIncremental loadingBufferSizeProvider = BufferSizeProviderIncremental.New(loadingBufferSize); final BufferSizeProvider readingDefaultBufferSizeProvider = BufferSizeProvider.New(readingDefaultBufferSize); - + + final EntityCacheMonitor[] cacheMonitors = new EntityCacheMonitor[channelCount]; + for(int i = 0; i < channels.length; i++) { // entity cache to register entities, cache entity data, perform garbage collection @@ -127,6 +134,9 @@ public final StorageChannel.Default[] createChannels( markingWaitTimeMs , markBufferLength ); + + cacheMonitors[i] = new EntityCacheMonitor(entityCache); + monitorManager.registerMonitor(cacheMonitors[i]); // file manager to handle "file" IO (whatever "file" might be, might be a RDBMS binary table as well) final StorageFileManager.Default fileManager = new StorageFileManager.Default( @@ -157,10 +167,14 @@ public final StorageChannel.Default[] createChannels( switchByteOrder , loadingBufferSizeProvider, fileManager , - eventLogger + eventLogger , + monitorManager ); } + + monitorManager.registerMonitor(new EntityCacheSummaryMonitor(cacheMonitors)); + return channels; } diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageEntityCache.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageEntityCache.java index 1612f183..1b638df9 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageEntityCache.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageEntityCache.java @@ -199,12 +199,12 @@ final long sweepGeneration() return this.sweepGeneration; } - final long lastSweepStart() + public final long lastSweepStart() { return this.lastSweepStart; } - final long lastSweepEnd() + public final long lastSweepEnd() { return this.lastSweepEnd; } diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFoundation.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFoundation.java index ccd4aee7..ffed9e48 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFoundation.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFoundation.java @@ -19,6 +19,7 @@ import java.nio.ByteOrder; import org.eclipse.serializer.exceptions.MissingFoundationPartException; +import org.eclipse.serializer.monitoring.MonitoringManager; import org.eclipse.serializer.persistence.binary.types.BinaryEntityRawDataIterator; import org.eclipse.serializer.persistence.types.ObjectIdsSelector; import org.eclipse.serializer.persistence.types.Persistence; @@ -523,6 +524,8 @@ public interface StorageFoundation> extends Insta */ public StorageStructureValidator getStorageStructureValidator(); + public MonitoringManager getStorageMonitorManager(); + /** * Sets the {@link StorageConfiguration} instance to be used for the assembly. * @@ -833,6 +836,8 @@ public default F setEventLogger(final StorageEventLogger eventLogger) */ public F setStorageStructureValidator(final StorageStructureValidator storageStructureValidator); + public F setStorageMonitorManager(MonitoringManager storageMonitorManager); + /** * Creates and returns a new {@link StorageSystem} instance by using the current state of all registered * logic part instances and by on-demand creating missing ones via a default logic. @@ -897,6 +902,7 @@ public class Default> private ObjectIdsSelector liveObjectIdChecker ; private Reference storerRegistryReference ; private StorageStructureValidator storageStructureValidator ; + private MonitoringManager storageMonitorManager ; @@ -1146,6 +1152,11 @@ protected StorageStructureValidator ensureStorageStructureValidator() ); } + protected MonitoringManager ensureStorageMonitorManager() + { + return MonitoringManager.New(); + } + @Override public StorageOperationController.Creator getOperationControllerCreator() @@ -1527,6 +1538,16 @@ public StorageStructureValidator getStorageStructureValidator() return this.storageStructureValidator; } + @Override + public MonitoringManager getStorageMonitorManager() + { + if(this.storageMonitorManager == null) + { + this.storageMonitorManager = this.dispatch(this.ensureStorageMonitorManager()); + } + return this.storageMonitorManager; + } + @Override public F setOperationControllerCreator( @@ -1827,6 +1848,13 @@ public F setStorageStructureValidator(final StorageStructureValidator storageStr return this.$(); } + @Override + public F setStorageMonitorManager(final MonitoringManager storageMonitorManager) + { + this.storageMonitorManager = storageMonitorManager; + return this.$(); + } + public final boolean isByteOrderMismatch() { /* (11.02.2019 TM)NOTE: On byte order switching: @@ -1878,7 +1906,8 @@ public StorageSystem createStorageSystem() this.getEventLogger() , this.getLiveObjectIdChecker() , this.getLiveStorerRegistryReference() , - this.getStorageStructureValidator() + this.getStorageStructureValidator() , + this.getStorageMonitorManager() ); } diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageSystem.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageSystem.java index 7b944d3b..daa6ddc6 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageSystem.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageSystem.java @@ -22,6 +22,7 @@ import org.eclipse.serializer.afs.types.AFileSystem; import org.eclipse.serializer.meta.XDebug; +import org.eclipse.serializer.monitoring.MonitoringManager; import org.eclipse.serializer.persistence.types.ObjectIdsSelector; import org.eclipse.serializer.persistence.types.Persistence; import org.eclipse.serializer.persistence.types.PersistenceLiveStorerRegistry; @@ -112,6 +113,7 @@ public final class Default implements StorageSystem, Unpersistable, StorageKilla private final Referencing refStorerRegistry ; private final boolean switchByteOrder ; private final StorageStructureValidator storageStructureValidator ; + private final MonitoringManager monitorManager ; // state flags // private final AtomicBoolean isStartingUp = new AtomicBoolean(); @@ -166,7 +168,8 @@ public Default( final StorageEventLogger eventLogger , final ObjectIdsSelector liveObjectIdChecker , final Referencing refStorerRegistry , - final StorageStructureValidator storageStructureValidator + final StorageStructureValidator storageStructureValidator , + final MonitoringManager monitorManager ) { super(); @@ -212,6 +215,7 @@ public Default( this.refStorerRegistry = notNull(refStorerRegistry) ; this.switchByteOrder = switchByteOrder ; this.storageStructureValidator = notNull(storageStructureValidator) ; + this.monitorManager = notNull(monitorManager) ; } @@ -465,7 +469,8 @@ private void createChannels() this.liveObjectIdChecker , this.refStorerRegistry , this.switchByteOrder , - this.rootTypeIdProvider.provideRootTypeId() + this.rootTypeIdProvider.provideRootTypeId(), + this.monitorManager ); final ChannelKeeper[] keepers = this.channelKeepers; @@ -548,6 +553,8 @@ private void internalShutdown() throws InterruptedException this.shutdownBackup(); this.operationController.deactivate(); + + this.monitorManager.shutdown(); /* (07.03.2019 TM)FIXME: Shutdown must wait for ongoing activities. * Such as a StorageBackupHandler thread with a non-empty item queue. From 8e53cca1d8e834ef386b73a088a6aff000ac62b1 Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Mon, 22 Jan 2024 13:21:15 +0100 Subject: [PATCH 066/126] unregister JMX beans in case of errors during storage startup (#120) --- .../store/storage/embedded/types/EmbeddedStorageManager.java | 3 ++- .../java/org/eclipse/store/storage/types/StorageSystem.java | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageManager.java b/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageManager.java index ff01d936..323ea2d3 100644 --- a/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageManager.java +++ b/storage/embedded/src/main/java/org/eclipse/store/storage/embedded/types/EmbeddedStorageManager.java @@ -41,8 +41,8 @@ import org.eclipse.serializer.typing.KeyValue; import org.eclipse.serializer.util.logging.Logging; import org.eclipse.store.storage.exceptions.StorageExceptionConsistency; -import org.eclipse.store.storage.monitoring.StorageManagerMonitor; import org.eclipse.store.storage.monitoring.ObjectRegistryMonitor; +import org.eclipse.store.storage.monitoring.StorageManagerMonitor; import org.eclipse.store.storage.types.Database; import org.eclipse.store.storage.types.StorageConfiguration; import org.eclipse.store.storage.types.StorageConnection; @@ -261,6 +261,7 @@ public final EmbeddedStorageManager.Default start() try { this.rollbackLazyReferenceManager(lazyReferenceManager); + this.monitorManager.shutdown(); if(this.storageSystem instanceof StorageKillable) { diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageSystem.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageSystem.java index daa6ddc6..118f2117 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageSystem.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageSystem.java @@ -605,11 +605,13 @@ public final StorageSystem.Default start() catch(final InterruptedException e) { this.operationController.deactivate(); + this.monitorManager.shutdown(); throw new StorageExceptionInitialization(e); } catch(final Throwable t) { this.operationController.deactivate(); + this.monitorManager.shutdown(); throw t; } finally From 93c41810f95c9905f97218290ae8b8be8ad964d0 Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Wed, 24 Jan 2024 09:25:21 +0100 Subject: [PATCH 067/126] Add multi-version hibernate logging (#121) --- .../hibernate/types/CacheRegionFactory.java | 47 +++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/CacheRegionFactory.java b/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/CacheRegionFactory.java index 10d1428d..9943ba9c 100644 --- a/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/CacheRegionFactory.java +++ b/cache/hibernate/src/main/java/org/eclipse/store/cache/hibernate/types/CacheRegionFactory.java @@ -21,6 +21,7 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Consumer; import java.util.stream.Collectors; import org.eclipse.serializer.chars.XChars; @@ -362,10 +363,10 @@ protected final String defaultRegionName( { if(this.cacheExists(legacyDefaultRegionName, sessionFactory)) { - SecondLevelCacheLogger.INSTANCE.usingLegacyCacheName( + log(logger -> logger.usingLegacyCacheName( defaultRegionName, legacyDefaultRegionName - ); + )); return legacyDefaultRegionName; } } @@ -412,11 +413,11 @@ protected Cache createCache( switch(this.missingCacheStrategy) { case CREATE_WARN: - SecondLevelCacheLogger.INSTANCE.missingCacheCreated( + log(logger -> logger.missingCacheCreated( regionName, ConfigurationPropertyNames.MISSING_CACHE_STRATEGY, MissingCacheStrategy.CREATE.getExternalRepresentation() - ); + )); // fall-through to create case CREATE: @@ -451,5 +452,43 @@ protected void releaseFromUse() } } } + + private static void log(final Consumer logAction) + { + try + { + final SecondLevelCacheLogger logger = acquireSecondLevelCacheLogger(); + logAction.accept(logger); + } + catch(final Exception e) + { + // ignore, unable to acquire logger + } + } + + private static SecondLevelCacheLogger acquireSecondLevelCacheLogger() + { + try + { + // Hibernate < 6 + return (SecondLevelCacheLogger)SecondLevelCacheLogger.class.getDeclaredField("INSTANCE").get(null); + } + catch(final NoSuchFieldException e) + { + try + { + // Hibernate >= 6 + return (SecondLevelCacheLogger)SecondLevelCacheLogger.class.getDeclaredField("L2CACHE_LOGGER").get(null); + } + catch(final NoSuchFieldException | IllegalArgumentException | IllegalAccessException e2) + { + throw new RuntimeException(e); + } + } + catch(SecurityException | IllegalArgumentException | IllegalAccessException e) + { + throw new RuntimeException(e); + } + } } From 0dfee1b3bad94ca028c06d9622b59534f5ba9188 Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Wed, 24 Jan 2024 12:08:40 +0100 Subject: [PATCH 068/126] 1.1.0 docs (#123) * Add changelog * Update docs * jmx monitoring docu (#122) * Update docs --------- Co-authored-by: hg-ms <53219833+hg-ms@users.noreply.github.com> --- docs/modules/ROOT/nav.adoc | 3 ++ docs/modules/intro/pages/changelog.adoc | 19 +++++++++ .../misc/pages/integrations/index.adoc | 6 ++- .../misc/pages/integrations/micronaut.adoc | 7 ++++ docs/modules/misc/pages/monitoring/index.adoc | 41 +++++++++++++++++++ 5 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 docs/modules/misc/pages/integrations/micronaut.adoc create mode 100644 docs/modules/misc/pages/monitoring/index.adoc diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index cb90062a..c96ebe58 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -78,10 +78,13 @@ ** Use Cases *** xref:cache:use-cases/hibernate-second-level-cache.adoc[Hibernate Second Level Cache] *** xref:cache:use-cases/spring-cache.adoc[Spring Cache] +* xref:communication:index.adoc[Communication] * Miscellaneous ** xref:misc:logging/index.adoc[Logging] +** xref:misc:monitoring/index.adoc[Monitoring] ** xref:misc:integrations/index.adoc[Integrations] *** xref:misc:integrations/spring-boot.adoc[Spring-Boot] +*** xref:misc:integrations/micronaut.adoc[Micronaut] ** xref:misc:layered-entities/index.adoc[Layered Entities] *** xref:misc:layered-entities/configuration.adoc[Configuration] *** xref:misc:layered-entities/defining-entities.adoc[Defining Entities] diff --git a/docs/modules/intro/pages/changelog.adoc b/docs/modules/intro/pages/changelog.adoc index b45fe5d0..ce5f89f4 100644 --- a/docs/modules/intro/pages/changelog.adoc +++ b/docs/modules/intro/pages/changelog.adoc @@ -1,5 +1,24 @@ = Changelog + +== 1.1.0 + +=== Features + +* xref:misc:monitoring/index.adoc[Monitoring] +* xref:communication:index.adoc[Communication layer] +* JSR-107 compatible xref:cache:index.adoc[JCache provider] with additional xref:cache:use-cases/hibernate-second-level-cache.adoc[Hibernate cache region factory] +* xref:misc:integrations/spring-boot.adoc[Spring Boot integration] +* xref:storage:configuration/housekeeping.adoc[Adaptive housekeeping] +* xref:storage:configuration/housekeeping.adoc#transaction-file-maximum-size[Transaction file housekeeping] +* Update rest client UI to Vaadin 24 https://github.com/eclipse-store/store/pull/94[[94]] +* Serialization support for Throwable https://github.com/eclipse-serializer/serializer/pull/86[[86]] + +=== Bugfixes + +* DynamoDB connector fix https://github.com/eclipse-store/store/pull/118[[118]] + + == 1.0.0 This is the first release of {product-name}, the successor of https://github.com/microstream-one[MicroStream]. diff --git a/docs/modules/misc/pages/integrations/index.adoc b/docs/modules/misc/pages/integrations/index.adoc index 5d8cd800..4a4548f4 100644 --- a/docs/modules/misc/pages/integrations/index.adoc +++ b/docs/modules/misc/pages/integrations/index.adoc @@ -4,7 +4,9 @@ Various {product-name} integrations are currently available. Currently available integrations: -- xref:misc:integrations/spring-boot.adoc[Spring Boot] +* xref:misc:integrations/spring-boot.adoc[Spring Boot] -Other integrations will be added in the future. +And {product-name} is also integrated by the following vendors + +* xref:misc:integrations/micronaut.adoc[Micronaut] diff --git a/docs/modules/misc/pages/integrations/micronaut.adoc b/docs/modules/misc/pages/integrations/micronaut.adoc new file mode 100644 index 00000000..8509bcda --- /dev/null +++ b/docs/modules/misc/pages/integrations/micronaut.adoc @@ -0,0 +1,7 @@ += Micronaut Integration + +The Micronaut integration for {product-name} ships with the official Micronaut releases and is hosted at their https://github.com/micronaut-projects/micronaut-eclipsestore[Github repository]. + +For more information see the https://guides.micronaut.io/latest/micronaut-eclipsestore-persitence-gradle-java.html[official guide]. + +Official Micronaut site: https://micronaut.io/[] \ No newline at end of file diff --git a/docs/modules/misc/pages/monitoring/index.adoc b/docs/modules/misc/pages/monitoring/index.adoc new file mode 100644 index 00000000..4f7d3b9b --- /dev/null +++ b/docs/modules/misc/pages/monitoring/index.adoc @@ -0,0 +1,41 @@ += Monitoring + +{product-name} supports monitoring using the https://docs.oracle.com/en/java/javase/11/management/monitoring-and-management-using-jmx-technology.html#GUID-805517EC-2D33-4D61-81D8-4D0FA770D1B8[Java Management Extensions (JMX) framework]. + +== Enable JMX +Please see https://docs.oracle.com/en/java/javase/11/management/monitoring-and-management-using-jmx-technology.html#GUID-E17343B0-FED2-4050-88D7-E4793E704ED5[how to enable JMX]. + +== Provided JMX beans +By default, all provided beans use the domain `org.eclipse.store`. + +Storage-specific beans have the key `storage`. The value comprises the string `storage` and an increasing counter. + +Channel-specific beans have the key `channel`. The value is composed of the string `channel-` and an increasing counter. + +The provided beans are: + +[options="header",cols="1,1"] +|=== +|name +|description + +|org.eclipse.store:name=LazyReferenceManager +|Provides information of the storage LazyReferenceManager. There is only one instance of this bean. + +|org.eclipse.store:storage=storageX,name=EmbeddedStorage +|Provides information about the amount of persisted data. + +|org.eclipse.store:storage=storageX,name=EntityCacheSummary +|Provides information of the storage entity cache + +|org.eclipse.store:storage=storageX,name=ObjectRegistry +|Provides information of the storage object registry + +|org.eclipse.store:storage=storageX,channel=channel-X,group=Entity cache +|Provides information of each channel's entity cache + +|org.eclipse.store:storage=storageX,channel=channel-X,group=housekeeping +|Provides information about the storage's channel housekeeping + +|=== + From e533ada23b1346e661acb90e01736a4fdf6ec817 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Wed, 24 Jan 2024 14:12:48 +0100 Subject: [PATCH 069/126] new dev version --- afs/aws/aws/pom.xml | 4 ++-- afs/aws/dynamodb/pom.xml | 4 ++-- afs/aws/pom.xml | 2 +- afs/aws/s3/pom.xml | 4 ++-- afs/azure/pom.xml | 2 +- afs/azure/storage/pom.xml | 4 ++-- afs/blobstore/pom.xml | 2 +- afs/googlecloud/firestore/pom.xml | 2 +- afs/googlecloud/pom.xml | 4 ++-- afs/kafka/pom.xml | 4 ++-- afs/nio/pom.xml | 2 +- afs/oraclecloud/objectstorage/pom.xml | 4 ++-- afs/oraclecloud/pom.xml | 2 +- afs/pom.xml | 2 +- afs/redis/pom.xml | 4 ++-- afs/sql/pom.xml | 2 +- cache/cache/pom.xml | 6 +++--- cache/hibernate/pom.xml | 4 ++-- cache/pom.xml | 2 +- examples/blobs/pom.xml | 4 ++-- examples/custom-legacy-type-handler/pom.xml | 4 ++-- examples/custom-type-handler/pom.xml | 4 ++-- examples/deleting/pom.xml | 4 ++-- examples/eager-storing/pom.xml | 4 ++-- examples/extension-wrapper/pom.xml | 4 ++-- examples/filesystems/pom.xml | 4 ++-- examples/helloworld-ini/pom.xml | 6 +++--- examples/helloworld/pom.xml | 4 ++-- examples/items/pom.xml | 4 ++-- examples/layered-entities/pom.xml | 2 +- examples/lazy-loading/pom.xml | 4 ++-- examples/loading/pom.xml | 4 ++-- examples/pom.xml | 2 +- examples/reloader/pom.xml | 4 ++-- examples/spring-boot3-simple/pom.xml | 4 ++-- examples/storing/pom.xml | 4 ++-- integrations/pom.xml | 2 +- integrations/spring-boot3/pom.xml | 6 +++--- pom.xml | 2 +- storage/embedded-configuration/pom.xml | 4 ++-- storage/embedded-tools/pom.xml | 2 +- storage/embedded-tools/storage-converter/pom.xml | 4 ++-- storage/embedded-tools/storage-migrator/pom.xml | 2 +- storage/embedded/pom.xml | 4 ++-- storage/pom.xml | 2 +- storage/rest/adapter/pom.xml | 4 ++-- storage/rest/client-app/pom.xml | 4 ++-- storage/rest/client-jersey/pom.xml | 4 ++-- storage/rest/client/pom.xml | 4 ++-- storage/rest/pom.xml | 2 +- storage/rest/service-sparkjava/pom.xml | 4 ++-- storage/rest/service/pom.xml | 4 ++-- storage/storage/pom.xml | 4 ++-- 53 files changed, 92 insertions(+), 92 deletions(-) diff --git a/afs/aws/aws/pom.xml b/afs/aws/aws/pom.xml index ad5e1360..f39fefef 100644 --- a/afs/aws/aws/pom.xml +++ b/afs/aws/aws/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-aws-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-blobstore - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/aws/dynamodb/pom.xml b/afs/aws/dynamodb/pom.xml index 3fb62e7e..38f636e6 100644 --- a/afs/aws/dynamodb/pom.xml +++ b/afs/aws/dynamodb/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-aws-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-aws - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT software.amazon.awssdk diff --git a/afs/aws/pom.xml b/afs/aws/pom.xml index 97ea6ea3..03473cd8 100644 --- a/afs/aws/pom.xml +++ b/afs/aws/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml diff --git a/afs/aws/s3/pom.xml b/afs/aws/s3/pom.xml index 6599b57a..28097ae6 100644 --- a/afs/aws/s3/pom.xml +++ b/afs/aws/s3/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-aws-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-aws - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT software.amazon.awssdk diff --git a/afs/azure/pom.xml b/afs/azure/pom.xml index 69e713ea..f7fb4578 100644 --- a/afs/azure/pom.xml +++ b/afs/azure/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml diff --git a/afs/azure/storage/pom.xml b/afs/azure/storage/pom.xml index 24064045..b5626758 100644 --- a/afs/azure/storage/pom.xml +++ b/afs/azure/storage/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-azure-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ org.eclipse.store afs-blobstore - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/blobstore/pom.xml b/afs/blobstore/pom.xml index 25382a9e..4e99dad4 100644 --- a/afs/blobstore/pom.xml +++ b/afs/blobstore/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml diff --git a/afs/googlecloud/firestore/pom.xml b/afs/googlecloud/firestore/pom.xml index ffe53a69..886f3925 100644 --- a/afs/googlecloud/firestore/pom.xml +++ b/afs/googlecloud/firestore/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-googlecloud-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml diff --git a/afs/googlecloud/pom.xml b/afs/googlecloud/pom.xml index 440fdd2c..91850a52 100644 --- a/afs/googlecloud/pom.xml +++ b/afs/googlecloud/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -40,7 +40,7 @@ org.eclipse.store afs-blobstore - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/kafka/pom.xml b/afs/kafka/pom.xml index 93c0f528..63d52759 100644 --- a/afs/kafka/pom.xml +++ b/afs/kafka/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ org.eclipse.store afs-blobstore - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/nio/pom.xml b/afs/nio/pom.xml index cc785c1e..ae667dd2 100644 --- a/afs/nio/pom.xml +++ b/afs/nio/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml diff --git a/afs/oraclecloud/objectstorage/pom.xml b/afs/oraclecloud/objectstorage/pom.xml index adbb09ae..6ba704c0 100644 --- a/afs/oraclecloud/objectstorage/pom.xml +++ b/afs/oraclecloud/objectstorage/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-oraclecloud-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-blobstore - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/oraclecloud/pom.xml b/afs/oraclecloud/pom.xml index 4a6a45d9..85667e28 100644 --- a/afs/oraclecloud/pom.xml +++ b/afs/oraclecloud/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml diff --git a/afs/pom.xml b/afs/pom.xml index c94d6e27..ec68475d 100644 --- a/afs/pom.xml +++ b/afs/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store store-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml diff --git a/afs/redis/pom.xml b/afs/redis/pom.xml index 8d085de5..6e9a9245 100644 --- a/afs/redis/pom.xml +++ b/afs/redis/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-blobstore - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/sql/pom.xml b/afs/sql/pom.xml index 3efb36d0..cbda51d5 100644 --- a/afs/sql/pom.xml +++ b/afs/sql/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml diff --git a/cache/cache/pom.xml b/cache/cache/pom.xml index baae0e0f..ff60477d 100644 --- a/cache/cache/pom.xml +++ b/cache/cache/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store cache-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,12 +23,12 @@ org.eclipse.store storage-embedded - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.eclipse.store storage-embedded-configuration - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT javax.cache diff --git a/cache/hibernate/pom.xml b/cache/hibernate/pom.xml index 37c21a1a..42aab9a3 100644 --- a/cache/hibernate/pom.xml +++ b/cache/hibernate/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store cache-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store cache - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.hibernate diff --git a/cache/pom.xml b/cache/pom.xml index 3d4fd7f3..f0520555 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store store-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml diff --git a/examples/blobs/pom.xml b/examples/blobs/pom.xml index 25330877..3166aca5 100644 --- a/examples/blobs/pom.xml +++ b/examples/blobs/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store examples-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ org.eclipse.store storage-embedded - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT diff --git a/examples/custom-legacy-type-handler/pom.xml b/examples/custom-legacy-type-handler/pom.xml index 65018bd0..ffe5109e 100644 --- a/examples/custom-legacy-type-handler/pom.xml +++ b/examples/custom-legacy-type-handler/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/custom-type-handler/pom.xml b/examples/custom-type-handler/pom.xml index 1bd42f04..d44347e6 100644 --- a/examples/custom-type-handler/pom.xml +++ b/examples/custom-type-handler/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/deleting/pom.xml b/examples/deleting/pom.xml index c84b2af6..d92d101c 100644 --- a/examples/deleting/pom.xml +++ b/examples/deleting/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT diff --git a/examples/eager-storing/pom.xml b/examples/eager-storing/pom.xml index 85dc535b..1b0bee7c 100644 --- a/examples/eager-storing/pom.xml +++ b/examples/eager-storing/pom.xml @@ -10,7 +10,7 @@ org.eclipse.store examples-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -24,7 +24,7 @@ org.eclipse.store storage-embedded - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT diff --git a/examples/extension-wrapper/pom.xml b/examples/extension-wrapper/pom.xml index 035de4c6..81675a15 100644 --- a/examples/extension-wrapper/pom.xml +++ b/examples/extension-wrapper/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store examples-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ org.eclipse.store storage-embedded - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT diff --git a/examples/filesystems/pom.xml b/examples/filesystems/pom.xml index 9bff63d8..042f1059 100644 --- a/examples/filesystems/pom.xml +++ b/examples/filesystems/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT com.google.jimfs diff --git a/examples/helloworld-ini/pom.xml b/examples/helloworld-ini/pom.xml index 643dd11a..8700005e 100644 --- a/examples/helloworld-ini/pom.xml +++ b/examples/helloworld-ini/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,12 +23,12 @@ org.eclipse.store storage-embedded - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.eclipse.store storage-embedded-configuration - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml index 3ea555b2..23089300 100644 --- a/examples/helloworld/pom.xml +++ b/examples/helloworld/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT diff --git a/examples/items/pom.xml b/examples/items/pom.xml index 63c1c5f7..44f08b93 100644 --- a/examples/items/pom.xml +++ b/examples/items/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/layered-entities/pom.xml b/examples/layered-entities/pom.xml index bd1ea71e..bbb278af 100644 --- a/examples/layered-entities/pom.xml +++ b/examples/layered-entities/pom.xml @@ -10,7 +10,7 @@ org.eclipse.store examples-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml diff --git a/examples/lazy-loading/pom.xml b/examples/lazy-loading/pom.xml index 5b2e8a01..3df414a1 100644 --- a/examples/lazy-loading/pom.xml +++ b/examples/lazy-loading/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/loading/pom.xml b/examples/loading/pom.xml index ec137a19..c9251248 100644 --- a/examples/loading/pom.xml +++ b/examples/loading/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/pom.xml b/examples/pom.xml index 8f6367d2..fc4777b5 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store store-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml diff --git a/examples/reloader/pom.xml b/examples/reloader/pom.xml index 2d8a399c..83197810 100644 --- a/examples/reloader/pom.xml +++ b/examples/reloader/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded-configuration - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT diff --git a/examples/spring-boot3-simple/pom.xml b/examples/spring-boot3-simple/pom.xml index 2d44ea6b..bcedb84c 100644 --- a/examples/spring-boot3-simple/pom.xml +++ b/examples/spring-boot3-simple/pom.xml @@ -6,7 +6,7 @@ org.eclipse.store examples-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -48,7 +48,7 @@ org.eclipse.store integrations-spring-boot3 - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT diff --git a/examples/storing/pom.xml b/examples/storing/pom.xml index 28e28cbd..9fdcfba7 100644 --- a/examples/storing/pom.xml +++ b/examples/storing/pom.xml @@ -10,7 +10,7 @@ org.eclipse.store examples-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -24,7 +24,7 @@ org.eclipse.store storage-embedded - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.eclipse.serializer diff --git a/integrations/pom.xml b/integrations/pom.xml index 040afdf8..9de0a7c7 100644 --- a/integrations/pom.xml +++ b/integrations/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store store-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml diff --git a/integrations/spring-boot3/pom.xml b/integrations/spring-boot3/pom.xml index a5ee9101..a77e0ebf 100644 --- a/integrations/spring-boot3/pom.xml +++ b/integrations/spring-boot3/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store integrations - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -59,7 +59,7 @@ org.eclipse.store storage-embedded - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT @@ -77,7 +77,7 @@ org.eclipse.store storage-embedded-configuration - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index b6e670f5..38e9dbf4 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ org.eclipse.store store-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT pom EclipseStore diff --git a/storage/embedded-configuration/pom.xml b/storage/embedded-configuration/pom.xml index 79a4849b..b2665b13 100644 --- a/storage/embedded-configuration/pom.xml +++ b/storage/embedded-configuration/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.eclipse.serializer diff --git a/storage/embedded-tools/pom.xml b/storage/embedded-tools/pom.xml index 51d13177..018eb5fc 100644 --- a/storage/embedded-tools/pom.xml +++ b/storage/embedded-tools/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml diff --git a/storage/embedded-tools/storage-converter/pom.xml b/storage/embedded-tools/storage-converter/pom.xml index 9978e970..aaa84ae2 100644 --- a/storage/embedded-tools/storage-converter/pom.xml +++ b/storage/embedded-tools/storage-converter/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-embedded-tools-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded-configuration - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT diff --git a/storage/embedded-tools/storage-migrator/pom.xml b/storage/embedded-tools/storage-migrator/pom.xml index ecb13d7d..3cf27fef 100644 --- a/storage/embedded-tools/storage-migrator/pom.xml +++ b/storage/embedded-tools/storage-migrator/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-embedded-tools-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml diff --git a/storage/embedded/pom.xml b/storage/embedded/pom.xml index 9392bbdd..7007bf31 100644 --- a/storage/embedded/pom.xml +++ b/storage/embedded/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT diff --git a/storage/pom.xml b/storage/pom.xml index 01cac3b2..f15f78fe 100644 --- a/storage/pom.xml +++ b/storage/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store store-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml diff --git a/storage/rest/adapter/pom.xml b/storage/rest/adapter/pom.xml index c16756a1..a7314714 100644 --- a/storage/rest/adapter/pom.xml +++ b/storage/rest/adapter/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT diff --git a/storage/rest/client-app/pom.xml b/storage/rest/client-app/pom.xml index da43d9c0..3e4ac0b0 100644 --- a/storage/rest/client-app/pom.xml +++ b/storage/rest/client-app/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -50,7 +50,7 @@ org.eclipse.store storage-restclient-jersey - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT com.vaadin diff --git a/storage/rest/client-jersey/pom.xml b/storage/rest/client-jersey/pom.xml index eda89698..45cec86e 100644 --- a/storage/rest/client-jersey/pom.xml +++ b/storage/rest/client-jersey/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -29,7 +29,7 @@ org.eclipse.store storage-restclient - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.glassfish.jersey.core diff --git a/storage/rest/client/pom.xml b/storage/rest/client/pom.xml index 534185b1..320994cc 100644 --- a/storage/rest/client/pom.xml +++ b/storage/rest/client/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-restadapter - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT diff --git a/storage/rest/pom.xml b/storage/rest/pom.xml index 5362fa3e..bb2e9f1f 100644 --- a/storage/rest/pom.xml +++ b/storage/rest/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml diff --git a/storage/rest/service-sparkjava/pom.xml b/storage/rest/service-sparkjava/pom.xml index d200b352..b496c102 100644 --- a/storage/rest/service-sparkjava/pom.xml +++ b/storage/rest/service-sparkjava/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -29,7 +29,7 @@ org.eclipse.store storage-restservice - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT com.sparkjava diff --git a/storage/rest/service/pom.xml b/storage/rest/service/pom.xml index 1d3da606..efe8f65d 100644 --- a/storage/rest/service/pom.xml +++ b/storage/rest/service/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-restadapter - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT diff --git a/storage/storage/pom.xml b/storage/storage/pom.xml index 66fe9b11..dea8f336 100644 --- a/storage/storage/pom.xml +++ b/storage/storage/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-nio - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT org.eclipse.serializer From a47c4ac3c535ea645f94a0a2ef485429dae214ae Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Wed, 24 Jan 2024 14:13:21 +0100 Subject: [PATCH 070/126] new dev version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 38e9dbf4..121db641 100644 --- a/pom.xml +++ b/pom.xml @@ -47,7 +47,7 @@ ${basedir}/LICENSE 1 false - 1.1.0-SNAPSHOT + 1.2.0-SNAPSHOT 2 2 From 18272b33c75083457ceaaddc511f94bef2560bda Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 6 Feb 2024 09:51:30 +0100 Subject: [PATCH 071/126] Spring docu fix - autowired into method param (#125) --- docs/modules/misc/pages/integrations/spring-boot.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/misc/pages/integrations/spring-boot.adoc b/docs/modules/misc/pages/integrations/spring-boot.adoc index eacab68e..5344fb38 100644 --- a/docs/modules/misc/pages/integrations/spring-boot.adoc +++ b/docs/modules/misc/pages/integrations/spring-boot.adoc @@ -73,7 +73,7 @@ In case you need to modify the configuration in some way in the program, change [source,java] ---- @Bean - EmbeddedStorageManager injectStorageTest(@Autowired EclipseStoreProperties myConfiguration) + EmbeddedStorageManager injectStorageTest(@Autowired EclipseStoreProperties myConfiguration, @Autowired EclipseStoreProvider provider) { // Modify the configuration myConfiguration.setStorageDirectory(temp.getDir().getAbsolutePath()); From 7ed0c70dcd094e44c9329c25230a52f37a7510bc Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Wed, 14 Feb 2024 12:59:33 +0100 Subject: [PATCH 072/126] fix maven bundle config (#142) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 121db641..e6c64e16 100644 --- a/pom.xml +++ b/pom.xml @@ -185,7 +185,7 @@ - org.eclipse.storage*;-split-package:=merge-first + org.eclipse.store*;-split-package:=merge-first * * From 00100a7ed2c2c09ae6514ce7923822539704dd00 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Thu, 15 Feb 2024 14:29:44 +0100 Subject: [PATCH 073/126] Add module-info.java back into project (#144) * Revert "remove module-info.java and check" --- afs/aws/aws/src/main/java/module-info.java | 25 +++++++++ .../dynamodb/src/main/java/module-info.java | 25 +++++++++ afs/aws/s3/src/main/java/module-info.java | 26 ++++++++++ .../storage/src/main/java/module-info.java | 27 ++++++++++ afs/blobstore/src/main/java/module-info.java | 19 +++++++ .../firestore/src/main/java/module-info.java | 31 +++++++++++ afs/kafka/src/main/java/module-info.java | 25 +++++++++ afs/nio/src/main/java/module-info.java | 19 +++++++ .../src/main/java/module-info.java | 27 ++++++++++ afs/redis/src/main/java/module-info.java | 27 ++++++++++ afs/sql/src/main/java/module-info.java | 29 +++++++++++ cache/cache/src/main/java/module-info.java | 30 +++++++++++ .../hibernate/src/main/java/module-info.java | 23 +++++++++ .../src/main/java/module-info.java | 40 +++++++++++++++ .../configuration/EclipseStoreProperties.java | 14 ----- pom.xml | 35 +++++++++++++ .../src/main/java/module-info.java | 21 ++++++++ .../src/main/java/module-info.java | 19 +++++++ .../src/main/java/module-info.java | 28 ++++++++++ storage/embedded/pom.xml | 4 ++ .../embedded/src/main/java/module-info.java | 20 ++++++++ .../adapter/src/main/java/module-info.java | 20 ++++++++ .../client-app/src/main/java/module-info.java | 51 +++++++++++++++++++ .../src/main/java/module-info.java | 21 ++++++++ .../client/src/main/java/module-info.java | 20 ++++++++ .../src/main/java/module-info.java | 29 +++++++++++ .../service/src/main/java/module-info.java | 20 ++++++++ .../storage/src/main/java/module-info.java | 24 +++++++++ 28 files changed, 685 insertions(+), 14 deletions(-) create mode 100644 afs/aws/aws/src/main/java/module-info.java create mode 100644 afs/aws/dynamodb/src/main/java/module-info.java create mode 100644 afs/aws/s3/src/main/java/module-info.java create mode 100644 afs/azure/storage/src/main/java/module-info.java create mode 100644 afs/blobstore/src/main/java/module-info.java create mode 100644 afs/googlecloud/firestore/src/main/java/module-info.java create mode 100644 afs/kafka/src/main/java/module-info.java create mode 100644 afs/nio/src/main/java/module-info.java create mode 100644 afs/oraclecloud/objectstorage/src/main/java/module-info.java create mode 100644 afs/redis/src/main/java/module-info.java create mode 100644 afs/sql/src/main/java/module-info.java create mode 100644 cache/cache/src/main/java/module-info.java create mode 100644 cache/hibernate/src/main/java/module-info.java create mode 100644 integrations/spring-boot3/src/main/java/module-info.java create mode 100644 storage/embedded-configuration/src/main/java/module-info.java create mode 100644 storage/embedded-tools/storage-converter/src/main/java/module-info.java create mode 100644 storage/embedded-tools/storage-migrator/src/main/java/module-info.java create mode 100644 storage/embedded/src/main/java/module-info.java create mode 100644 storage/rest/adapter/src/main/java/module-info.java create mode 100644 storage/rest/client-app/src/main/java/module-info.java create mode 100644 storage/rest/client-jersey/src/main/java/module-info.java create mode 100644 storage/rest/client/src/main/java/module-info.java create mode 100644 storage/rest/service-sparkjava/src/main/java/module-info.java create mode 100644 storage/rest/service/src/main/java/module-info.java create mode 100644 storage/storage/src/main/java/module-info.java diff --git a/afs/aws/aws/src/main/java/module-info.java b/afs/aws/aws/src/main/java/module-info.java new file mode 100644 index 00000000..2129246e --- /dev/null +++ b/afs/aws/aws/src/main/java/module-info.java @@ -0,0 +1,25 @@ +/*- + * #%L + * EclipseStore Abstract File System AWS + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.afs.aws +{ + exports org.eclipse.store.afs.aws.types; + + requires transitive org.eclipse.serializer.afs; + requires transitive org.eclipse.serializer.configuration; + requires transitive software.amazon.awssdk.auth; + requires transitive software.amazon.awssdk.awscore; + requires transitive software.amazon.awssdk.core; + requires transitive software.amazon.awssdk.regions; + requires transitive software.amazon.awssdk.utils; +} diff --git a/afs/aws/dynamodb/src/main/java/module-info.java b/afs/aws/dynamodb/src/main/java/module-info.java new file mode 100644 index 00000000..45e9ed46 --- /dev/null +++ b/afs/aws/dynamodb/src/main/java/module-info.java @@ -0,0 +1,25 @@ +/*- + * #%L + * EclipseStore Abstract File System AWS DynamoDB + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.afs.aws.dynamodb +{ + exports org.eclipse.store.afs.aws.dynamodb.types; + + provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator + with org.eclipse.store.afs.aws.dynamodb.types.DynamoDbFileSystemCreator + ; + + requires transitive org.eclipse.store.afs.aws; + requires transitive org.eclipse.store.afs.blobstore; + requires transitive software.amazon.awssdk.services.dynamodb; +} diff --git a/afs/aws/s3/src/main/java/module-info.java b/afs/aws/s3/src/main/java/module-info.java new file mode 100644 index 00000000..b8bc6145 --- /dev/null +++ b/afs/aws/s3/src/main/java/module-info.java @@ -0,0 +1,26 @@ +/*- + * #%L + * EclipseStore Abstract File System AWS S3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.afs.aws.s3 +{ + exports org.eclipse.store.afs.aws.s3.types; + + provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator + with org.eclipse.store.afs.aws.s3.types.S3FileSystemCreator + ; + + requires transitive org.eclipse.store.afs.aws; + requires transitive org.eclipse.store.afs.blobstore; + requires transitive software.amazon.awssdk.http; + requires transitive software.amazon.awssdk.services.s3; +} diff --git a/afs/azure/storage/src/main/java/module-info.java b/afs/azure/storage/src/main/java/module-info.java new file mode 100644 index 00000000..ed2d6325 --- /dev/null +++ b/afs/azure/storage/src/main/java/module-info.java @@ -0,0 +1,27 @@ +/*- + * #%L + * EclipseStore Abstract File System Azure Storage + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.afs.azure.storage +{ + exports org.eclipse.store.afs.azure.storage.types; + + provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator + with org.eclipse.store.afs.azure.storage.types.AzureStorageFileSystemCreator + ; + + requires transitive org.eclipse.serializer.configuration; + requires transitive org.eclipse.store.afs.blobstore; + requires transitive com.azure.core; + requires transitive com.azure.storage.blob; + requires transitive com.azure.storage.common; +} diff --git a/afs/blobstore/src/main/java/module-info.java b/afs/blobstore/src/main/java/module-info.java new file mode 100644 index 00000000..5cc2cba9 --- /dev/null +++ b/afs/blobstore/src/main/java/module-info.java @@ -0,0 +1,19 @@ +/*- + * #%L + * EclipseStore Abstract File System Blobstore + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.afs.blobstore +{ + exports org.eclipse.store.afs.blobstore.types; + + requires transitive org.eclipse.serializer.afs; +} diff --git a/afs/googlecloud/firestore/src/main/java/module-info.java b/afs/googlecloud/firestore/src/main/java/module-info.java new file mode 100644 index 00000000..9dc2e364 --- /dev/null +++ b/afs/googlecloud/firestore/src/main/java/module-info.java @@ -0,0 +1,31 @@ +/*- + * #%L + * EclipseStore Abstract File System Google Cloud Firestore + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.afs.googlecloud.firestore +{ + exports org.eclipse.store.afs.googlecloud.firestore.types; + + provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator + with org.eclipse.store.afs.googlecloud.firestore.types.GoogleCloudFirestoreFileSystemCreator + ; + + requires transitive org.eclipse.serializer.configuration; + requires transitive org.eclipse.store.afs.blobstore; + requires transitive com.google.api.apicommon; + requires transitive com.google.auth; + requires transitive com.google.auth.oauth2; + requires transitive com.google.protobuf; + requires transitive gax; + requires transitive google.cloud.core; + requires transitive google.cloud.firestore; +} diff --git a/afs/kafka/src/main/java/module-info.java b/afs/kafka/src/main/java/module-info.java new file mode 100644 index 00000000..c5e4d992 --- /dev/null +++ b/afs/kafka/src/main/java/module-info.java @@ -0,0 +1,25 @@ +/*- + * #%L + * EclipseStore Abstract File System Kafka + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.afs.kafka +{ + exports org.eclipse.store.afs.kafka.types; + + provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator + with org.eclipse.store.afs.kafka.types.KafkaFileSystemCreator + ; + + requires transitive org.eclipse.serializer.configuration; + requires transitive org.eclipse.store.afs.blobstore; + requires transitive kafka.clients; +} diff --git a/afs/nio/src/main/java/module-info.java b/afs/nio/src/main/java/module-info.java new file mode 100644 index 00000000..27f24964 --- /dev/null +++ b/afs/nio/src/main/java/module-info.java @@ -0,0 +1,19 @@ +/*- + * #%L + * EclipseStore Abstract File System - Java NIO + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.afs.nio +{ + exports org.eclipse.store.afs.nio.types; + + requires transitive org.eclipse.serializer.afs; +} diff --git a/afs/oraclecloud/objectstorage/src/main/java/module-info.java b/afs/oraclecloud/objectstorage/src/main/java/module-info.java new file mode 100644 index 00000000..b0aa787f --- /dev/null +++ b/afs/oraclecloud/objectstorage/src/main/java/module-info.java @@ -0,0 +1,27 @@ +/*- + * #%L + * EclipseStore Abstract File System Oracle Cloud ObjectStorage + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.afs.oraclecloud.objectstorage +{ + exports org.eclipse.store.afs.oraclecloud.objectstorage.types; + + provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator + with org.eclipse.store.afs.oraclecloud.objectstorage.types.OracleCloudObjectStorageFileSystemCreator + ; + + requires transitive org.eclipse.serializer.configuration; + requires transitive org.eclipse.store.afs.blobstore; + requires transitive oci.java.sdk.common; + requires transitive oci.java.sdk.objectstorage.extensions; + requires transitive oci.java.sdk.objectstorage.generated; +} diff --git a/afs/redis/src/main/java/module-info.java b/afs/redis/src/main/java/module-info.java new file mode 100644 index 00000000..c74820a9 --- /dev/null +++ b/afs/redis/src/main/java/module-info.java @@ -0,0 +1,27 @@ +/*- + * #%L + * EclipseStore Abstract File System Redis + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.afs.redis +{ + exports org.eclipse.store.afs.redis.types; + + provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator + with org.eclipse.store.afs.redis.types.RedisFileSystemCreator + ; + + requires transitive org.eclipse.serializer.configuration; + requires transitive org.eclipse.store.afs.blobstore; + requires transitive io.netty.buffer; + requires transitive io.netty.common; + requires transitive lettuce.core; +} diff --git a/afs/sql/src/main/java/module-info.java b/afs/sql/src/main/java/module-info.java new file mode 100644 index 00000000..cbb1afe8 --- /dev/null +++ b/afs/sql/src/main/java/module-info.java @@ -0,0 +1,29 @@ +/*- + * #%L + * EclipseStore Abstract File System SQL + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.afs.sql +{ + exports org.eclipse.store.afs.sql.types; + + provides org.eclipse.serializer.configuration.types.ConfigurationBasedCreator + with org.eclipse.store.afs.sql.types.SqlFileSystemCreatorHana, + org.eclipse.store.afs.sql.types.SqlFileSystemCreatorMariaDb, + org.eclipse.store.afs.sql.types.SqlFileSystemCreatorOracle, + org.eclipse.store.afs.sql.types.SqlFileSystemCreatorPostgres, + org.eclipse.store.afs.sql.types.SqlFileSystemCreatorSqlite + ; + + requires transitive org.eclipse.serializer.afs; + requires transitive org.eclipse.serializer.configuration; + requires transitive java.sql; +} diff --git a/cache/cache/src/main/java/module-info.java b/cache/cache/src/main/java/module-info.java new file mode 100644 index 00000000..6417b7f9 --- /dev/null +++ b/cache/cache/src/main/java/module-info.java @@ -0,0 +1,30 @@ +/*- + * #%L + * EclipseStore Cache + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.cache +{ + exports org.eclipse.store.cache.types; + + provides javax.cache.spi.CachingProvider + with org.eclipse.store.cache.types.CachingProvider + ; + + requires transitive org.eclipse.serializer.persistence.binary; + requires transitive org.eclipse.store.storage.embedded.configuration; + requires transitive cache.api; + requires transitive java.management; + requires org.eclipse.store.storage.embedded; + requires org.eclipse.serializer.configuration; + requires org.eclipse.serializer; + requires org.eclipse.serializer.base; +} diff --git a/cache/hibernate/src/main/java/module-info.java b/cache/hibernate/src/main/java/module-info.java new file mode 100644 index 00000000..7e534d77 --- /dev/null +++ b/cache/hibernate/src/main/java/module-info.java @@ -0,0 +1,23 @@ +/*- + * #%L + * EclipseStore Cache for Hibernate + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.cache.hibernate +{ + exports org.eclipse.store.cache.hibernate.types; + + requires transitive org.eclipse.store.cache; + requires transitive java.naming; + requires transitive java.persistence; + requires transitive org.hibernate.orm.core; + requires org.eclipse.serializer.base; +} diff --git a/integrations/spring-boot3/src/main/java/module-info.java b/integrations/spring-boot3/src/main/java/module-info.java new file mode 100644 index 00000000..4e10c54a --- /dev/null +++ b/integrations/spring-boot3/src/main/java/module-info.java @@ -0,0 +1,40 @@ +/*- + * #%L + * microstream-integrations-spring-boot3 + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +open module org.eclipse.store.integrations.spring.boot +{ + exports org.eclipse.store.integrations.spring.boot.types.configuration; + exports org.eclipse.store.integrations.spring.boot.types.configuration.aws; + exports org.eclipse.store.integrations.spring.boot.types.configuration.azure; + exports org.eclipse.store.integrations.spring.boot.types.configuration.googlecloud; + exports org.eclipse.store.integrations.spring.boot.types.configuration.googlecloud.firestore; + exports org.eclipse.store.integrations.spring.boot.types.configuration.oraclecloud; + exports org.eclipse.store.integrations.spring.boot.types.configuration.redis; + exports org.eclipse.store.integrations.spring.boot.types.configuration.sql; + exports org.eclipse.store.integrations.spring.boot.types; + exports org.eclipse.store.integrations.spring.boot.types.converter; + exports org.eclipse.store.integrations.spring.boot.types.concurrent; + + requires transitive spring.beans; + requires transitive spring.boot; + requires transitive spring.boot.autoconfigure; + requires transitive spring.context; + requires transitive spring.core; + requires transitive org.eclipse.store.storage.embedded.configuration; + requires transitive org.eclipse.serializer.configuration; + requires transitive org.aspectj.weaver; + requires transitive org.eclipse.serializer.persistence.binary.jdk17; + requires transitive org.eclipse.serializer.persistence.binary.jdk8; + + +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java index ed7f8169..86c29428 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java @@ -1,19 +1,5 @@ package org.eclipse.store.integrations.spring.boot.types.configuration; -/*- - * #%L - * integrations-spring-boot3 - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ - import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.context.annotation.Configuration; diff --git a/pom.xml b/pom.xml index e6c64e16..b274b1d2 100644 --- a/pom.xml +++ b/pom.xml @@ -437,6 +437,41 @@ + + module-info-check + + + src/main/java + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + + + enforce-files-exist + + enforce + + + + + The module-info is not present + + ${project.basedir}/src/main/java/module-info.java + + + + true + + + + + + + javadoc-check diff --git a/storage/embedded-configuration/src/main/java/module-info.java b/storage/embedded-configuration/src/main/java/module-info.java new file mode 100644 index 00000000..3ac95244 --- /dev/null +++ b/storage/embedded-configuration/src/main/java/module-info.java @@ -0,0 +1,21 @@ +/*- + * #%L + * EclipseStore Storage Embedded Configuration + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.storage.embedded.configuration +{ + exports org.eclipse.store.storage.embedded.configuration.types; + + requires java.xml; + requires transitive org.eclipse.serializer.configuration; + requires transitive org.eclipse.store.storage.embedded; +} diff --git a/storage/embedded-tools/storage-converter/src/main/java/module-info.java b/storage/embedded-tools/storage-converter/src/main/java/module-info.java new file mode 100644 index 00000000..d62ee551 --- /dev/null +++ b/storage/embedded-tools/storage-converter/src/main/java/module-info.java @@ -0,0 +1,19 @@ +/*- + * #%L + * EclipseStore Storage Embedded Tools Storage Converter + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.storage.embedded.tools.storage.converter +{ + exports org.eclipse.store.storage.embedded.tools.storage.converter; + + requires transitive org.eclipse.store.storage.embedded.configuration; +} diff --git a/storage/embedded-tools/storage-migrator/src/main/java/module-info.java b/storage/embedded-tools/storage-migrator/src/main/java/module-info.java new file mode 100644 index 00000000..f754a3f7 --- /dev/null +++ b/storage/embedded-tools/storage-migrator/src/main/java/module-info.java @@ -0,0 +1,28 @@ +/*- + * #%L + * EclipseStore Storage Embedded Tools Storage Migrator + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.storage.embedded.tools.storage.migrator +{ + exports org.eclipse.store.storage.embedded.tools.storage.migrator; + exports org.eclipse.store.storage.embedded.tools.storage.migrator.mappings; + exports org.eclipse.store.storage.embedded.tools.storage.migrator.typedictionary; + + requires transitive org.eclipse.serializer.persistence.binary; + requires transitive com.fasterxml.jackson.annotation; + requires transitive java.object.diff; + requires transitive lombok; + requires transitive micrometer.core; + requires transitive rewrite.core; + requires transitive rewrite.java; + requires transitive rewrite.maven; +} diff --git a/storage/embedded/pom.xml b/storage/embedded/pom.xml index 7007bf31..260a189c 100644 --- a/storage/embedded/pom.xml +++ b/storage/embedded/pom.xml @@ -25,6 +25,10 @@ storage 1.2.0-SNAPSHOT + + org.slf4j + slf4j-api + diff --git a/storage/embedded/src/main/java/module-info.java b/storage/embedded/src/main/java/module-info.java new file mode 100644 index 00000000..ba075f2f --- /dev/null +++ b/storage/embedded/src/main/java/module-info.java @@ -0,0 +1,20 @@ +/*- + * #%L + * EclipseStore Storage Embedded + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.storage.embedded +{ + exports org.eclipse.store.storage.embedded.types; + + requires transitive org.eclipse.store.storage; + requires transitive org.slf4j; +} diff --git a/storage/rest/adapter/src/main/java/module-info.java b/storage/rest/adapter/src/main/java/module-info.java new file mode 100644 index 00000000..945ad10c --- /dev/null +++ b/storage/rest/adapter/src/main/java/module-info.java @@ -0,0 +1,20 @@ +/*- + * #%L + * EclipseStore Storage REST Adapter + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.storage.restadapter +{ + exports org.eclipse.store.storage.restadapter.types; + exports org.eclipse.store.storage.restadapter.exceptions; + + requires transitive org.eclipse.store.storage; +} diff --git a/storage/rest/client-app/src/main/java/module-info.java b/storage/rest/client-app/src/main/java/module-info.java new file mode 100644 index 00000000..96976fd5 --- /dev/null +++ b/storage/rest/client-app/src/main/java/module-info.java @@ -0,0 +1,51 @@ +/*- + * #%L + * EclipseStore Storage REST Client App + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +module org.eclipse.store.storage.restclient.app +{ + exports org.eclipse.store.storage.restclient.app.types; + exports org.eclipse.store.storage.restclient.app.ui; + + provides com.vaadin.flow.server.VaadinServiceInitListener + with org.eclipse.store.storage.restclient.app.types.ApplicationServiceInitListener + ; + + requires transitive flow.data; + requires transitive flow.html.components; + requires transitive flow.server; + requires transitive gwt.elemental; + requires transitive org.eclipse.serializer.base; + requires transitive org.eclipse.store.storage.restadapter; + requires transitive org.eclipse.store.storage.restclient; + requires transitive org.eclipse.store.storage.restclient.jersey; + requires transitive org.apache.tomcat.embed.core; + requires transitive org.slf4j; + requires transitive spring.beans; + requires transitive spring.boot; + requires transitive spring.boot.autoconfigure; + requires transitive spring.context; + requires transitive spring.core; + requires transitive spring.web; + requires transitive vaadin.spring; + requires transitive vaadin.button.flow; + requires transitive vaadin.combo.box.flow; + requires transitive vaadin.details.flow; + requires transitive vaadin.grid.flow; + requires transitive vaadin.lumo.theme; + requires transitive vaadin.notification.flow; + requires transitive vaadin.ordered.layout.flow; + requires transitive vaadin.split.layout.flow; + requires transitive vaadin.tabs.flow; + requires transitive vaadin.text.field.flow; +} diff --git a/storage/rest/client-jersey/src/main/java/module-info.java b/storage/rest/client-jersey/src/main/java/module-info.java new file mode 100644 index 00000000..29fc0c74 --- /dev/null +++ b/storage/rest/client-jersey/src/main/java/module-info.java @@ -0,0 +1,21 @@ +/*- + * #%L + * EclipseStore Storage REST Client Jersey + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.storage.restclient.jersey +{ + exports org.eclipse.store.storage.restclient.jersey.types; + + requires transitive com.google.gson; + requires transitive jakarta.ws.rs; + requires transitive org.eclipse.store.storage.restclient; +} diff --git a/storage/rest/client/src/main/java/module-info.java b/storage/rest/client/src/main/java/module-info.java new file mode 100644 index 00000000..f4e30ba8 --- /dev/null +++ b/storage/rest/client/src/main/java/module-info.java @@ -0,0 +1,20 @@ +/*- + * #%L + * EclipseStore Storage REST Client + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.storage.restclient +{ + exports org.eclipse.store.storage.restclient.exceptions; + exports org.eclipse.store.storage.restclient.types; + + requires transitive org.eclipse.store.storage.restadapter; +} diff --git a/storage/rest/service-sparkjava/src/main/java/module-info.java b/storage/rest/service-sparkjava/src/main/java/module-info.java new file mode 100644 index 00000000..c2221b33 --- /dev/null +++ b/storage/rest/service-sparkjava/src/main/java/module-info.java @@ -0,0 +1,29 @@ +/*- + * #%L + * EclipseStore Storage REST Service Sparkjava + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.storage.restservice.sparkjava +{ + exports org.eclipse.store.storage.restservice.sparkjava.exceptions; + exports org.eclipse.store.storage.restservice.sparkjava.types; + + provides org.eclipse.store.storage.restadapter.types.StorageViewDataConverter + with org.eclipse.store.storage.restservice.sparkjava.types.StorageViewDataConverterJson + ; + provides org.eclipse.store.storage.restservice.types.StorageRestServiceProvider + with org.eclipse.store.storage.restservice.sparkjava.types.StorageRestServiceProviderSparkJava + ; + + requires transitive org.eclipse.store.storage.restservice; + requires transitive com.google.gson; + requires transitive spark.core; +} diff --git a/storage/rest/service/src/main/java/module-info.java b/storage/rest/service/src/main/java/module-info.java new file mode 100644 index 00000000..81f3b0cb --- /dev/null +++ b/storage/rest/service/src/main/java/module-info.java @@ -0,0 +1,20 @@ +/*- + * #%L + * EclipseStore Storage REST Service + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.storage.restservice +{ + exports org.eclipse.store.storage.restservice.types; + exports org.eclipse.store.storage.restservice.exceptions; + + requires transitive org.eclipse.store.storage.restadapter; +} diff --git a/storage/storage/src/main/java/module-info.java b/storage/storage/src/main/java/module-info.java new file mode 100644 index 00000000..0c33b8de --- /dev/null +++ b/storage/storage/src/main/java/module-info.java @@ -0,0 +1,24 @@ +/*- + * #%L + * EclipseStore Storage + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module org.eclipse.store.storage +{ + exports org.eclipse.store.storage.util; + exports org.eclipse.store.storage.types; + exports org.eclipse.store.storage.exceptions; + exports org.eclipse.store.storage.monitoring; + + requires transitive org.eclipse.store.afs.nio; + requires transitive org.eclipse.serializer.persistence.binary; + requires transitive org.eclipse.serializer.base; +} From b35baf9bf707ebfa2f2ddd51b245c80bc2239aee Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Wed, 21 Feb 2024 11:42:58 +0100 Subject: [PATCH 074/126] Bug/client app module info (#147) * fixed build errors in eclipse IDE * added provides VaadinServiceInitListener --- .../client-app/src/main/java/module-info.java | 67 +++++++++---------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/storage/rest/client-app/src/main/java/module-info.java b/storage/rest/client-app/src/main/java/module-info.java index 96976fd5..3af3273d 100644 --- a/storage/rest/client-app/src/main/java/module-info.java +++ b/storage/rest/client-app/src/main/java/module-info.java @@ -2,7 +2,7 @@ * #%L * EclipseStore Storage REST Client App * %% - * Copyright (C) 2023 MicroStream Software + * Copyright (C) 2023 - 2024 MicroStream Software * %% * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -11,41 +11,40 @@ * SPDX-License-Identifier: EPL-2.0 * #L% */ - -module org.eclipse.store.storage.restclient.app -{ +module org.eclipse.store.storage.restclient.app { exports org.eclipse.store.storage.restclient.app.types; exports org.eclipse.store.storage.restclient.app.ui; - + provides com.vaadin.flow.server.VaadinServiceInitListener - with org.eclipse.store.storage.restclient.app.types.ApplicationServiceInitListener - ; + with org.eclipse.store.storage.restclient.app.types.ApplicationServiceInitListener; - requires transitive flow.data; - requires transitive flow.html.components; - requires transitive flow.server; - requires transitive gwt.elemental; - requires transitive org.eclipse.serializer.base; - requires transitive org.eclipse.store.storage.restadapter; - requires transitive org.eclipse.store.storage.restclient; - requires transitive org.eclipse.store.storage.restclient.jersey; - requires transitive org.apache.tomcat.embed.core; - requires transitive org.slf4j; - requires transitive spring.beans; - requires transitive spring.boot; - requires transitive spring.boot.autoconfigure; - requires transitive spring.context; - requires transitive spring.core; - requires transitive spring.web; - requires transitive vaadin.spring; - requires transitive vaadin.button.flow; - requires transitive vaadin.combo.box.flow; - requires transitive vaadin.details.flow; - requires transitive vaadin.grid.flow; - requires transitive vaadin.lumo.theme; - requires transitive vaadin.notification.flow; - requires transitive vaadin.ordered.layout.flow; - requires transitive vaadin.split.layout.flow; - requires transitive vaadin.tabs.flow; - requires transitive vaadin.text.field.flow; + requires flow.data; + requires flow.html.components; + requires flow.server; + requires gwt.elemental; + requires org.apache.tomcat.embed.core; + requires org.eclipse.serializer.base; + requires org.eclipse.store.storage.restadapter; + requires org.eclipse.store.storage.restclient; + requires org.eclipse.store.storage.restclient.jersey; + requires org.slf4j; + requires spring.beans; + requires spring.boot; + requires spring.boot.autoconfigure; + requires spring.context; + requires spring.core; + requires spring.web; + requires vaadin.button.flow; + requires vaadin.combo.box.flow; + requires vaadin.details.flow; + requires vaadin.flow.components.base; + requires vaadin.grid.flow; + requires vaadin.lumo.theme; + requires vaadin.notification.flow; + requires vaadin.ordered.layout.flow; + requires vaadin.renderer.flow; + requires vaadin.split.layout.flow; + requires vaadin.spring; + requires vaadin.tabs.flow; + requires vaadin.text.field.flow; } From bfc3d9e0531ccb9a82dd5acb25ff57070a16e3b8 Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Wed, 21 Feb 2024 12:03:38 +0100 Subject: [PATCH 075/126] 1.2.0 Docs (#148) * Add docs for 1.2.0 * Fix link --- docs/antora.yml | 8 ++++---- docs/modules/intro/pages/changelog.adoc | 12 +++++++++++- docs/modules/storage/pages/faq/java-features.adoc | 4 ++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/docs/antora.yml b/docs/antora.yml index 6c2a1d23..92cc3648 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -1,13 +1,13 @@ name: manual title: EclipseStore Reference Manual version: master -display_version: '1.0' +display_version: 'V1' start_page: intro:welcome.adoc nav: - modules/ROOT/nav.adoc asciidoc: attributes: product-name: 'EclipseStore' - display-version: '1.0' - api-version: '1.0' - maven-version: '1.0.0-SNAPSHOT' + display-version: '1.2' + api-version: '1' + maven-version: '1.2.0' diff --git a/docs/modules/intro/pages/changelog.adoc b/docs/modules/intro/pages/changelog.adoc index ce5f89f4..4d8c5837 100644 --- a/docs/modules/intro/pages/changelog.adoc +++ b/docs/modules/intro/pages/changelog.adoc @@ -1,5 +1,15 @@ = Changelog +== 1.2.0 + +=== Features + +* Module-infos are back https://github.com/eclipse-store/store/pull/144[[144]] + +=== Bugfixes + +* Fixed memory cleanup https://github.com/eclipse-serializer/serializer/pull/103[[103]] + == 1.1.0 @@ -10,7 +20,7 @@ * JSR-107 compatible xref:cache:index.adoc[JCache provider] with additional xref:cache:use-cases/hibernate-second-level-cache.adoc[Hibernate cache region factory] * xref:misc:integrations/spring-boot.adoc[Spring Boot integration] * xref:storage:configuration/housekeeping.adoc[Adaptive housekeeping] -* xref:storage:configuration/housekeeping.adoc#transaction-file-maximum-size[Transaction file housekeeping] +* xref:storage:configuration/properties.adoc#transaction-file-maximum-size[Transaction file housekeeping] * Update rest client UI to Vaadin 24 https://github.com/eclipse-store/store/pull/94[[94]] * Serialization support for Throwable https://github.com/eclipse-serializer/serializer/pull/86[[86]] diff --git a/docs/modules/storage/pages/faq/java-features.adoc b/docs/modules/storage/pages/faq/java-features.adoc index 14a78bf4..5e2493d1 100644 --- a/docs/modules/storage/pages/faq/java-features.adoc +++ b/docs/modules/storage/pages/faq/java-features.adoc @@ -1,5 +1,9 @@ = Java Features +== Does {product-name} work with the Java Module System (Jigsaw)? + +Yes, all jars bring the necessary module-info class. + [#records] == Can {product-name} handle Records? From 49bb115c7c97c3a7cb2194eccf9a2af94f02ac85 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Wed, 21 Feb 2024 14:06:34 +0100 Subject: [PATCH 076/126] fix serializer version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b274b1d2..c8a228d9 100644 --- a/pom.xml +++ b/pom.xml @@ -47,7 +47,7 @@ ${basedir}/LICENSE 1 false - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT 2 2 From 45350a8a149edce08d6f448878f0efc222ab43fd Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Thu, 22 Feb 2024 17:39:44 +0100 Subject: [PATCH 077/126] new dev version 1.3.0-snaphost --- afs/aws/aws/pom.xml | 4 ++-- afs/aws/dynamodb/pom.xml | 4 ++-- afs/aws/pom.xml | 2 +- afs/aws/s3/pom.xml | 4 ++-- afs/azure/pom.xml | 2 +- afs/azure/storage/pom.xml | 4 ++-- afs/blobstore/pom.xml | 2 +- afs/googlecloud/firestore/pom.xml | 2 +- afs/googlecloud/pom.xml | 4 ++-- afs/kafka/pom.xml | 4 ++-- afs/nio/pom.xml | 2 +- afs/oraclecloud/objectstorage/pom.xml | 4 ++-- afs/oraclecloud/pom.xml | 2 +- afs/pom.xml | 2 +- afs/redis/pom.xml | 4 ++-- afs/sql/pom.xml | 2 +- cache/cache/pom.xml | 6 +++--- cache/hibernate/pom.xml | 4 ++-- cache/pom.xml | 2 +- examples/blobs/pom.xml | 4 ++-- examples/custom-legacy-type-handler/pom.xml | 4 ++-- examples/custom-type-handler/pom.xml | 4 ++-- examples/deleting/pom.xml | 4 ++-- examples/eager-storing/pom.xml | 4 ++-- examples/extension-wrapper/pom.xml | 4 ++-- examples/filesystems/pom.xml | 4 ++-- examples/helloworld-ini/pom.xml | 6 +++--- examples/helloworld/pom.xml | 4 ++-- examples/items/pom.xml | 4 ++-- examples/layered-entities/pom.xml | 2 +- examples/lazy-loading/pom.xml | 4 ++-- examples/loading/pom.xml | 4 ++-- examples/pom.xml | 2 +- examples/reloader/pom.xml | 4 ++-- examples/spring-boot3-simple/pom.xml | 4 ++-- examples/storing/pom.xml | 4 ++-- integrations/pom.xml | 2 +- integrations/spring-boot3/pom.xml | 6 +++--- pom.xml | 2 +- storage/embedded-configuration/pom.xml | 4 ++-- storage/embedded-tools/pom.xml | 2 +- storage/embedded-tools/storage-converter/pom.xml | 4 ++-- storage/embedded-tools/storage-migrator/pom.xml | 2 +- storage/embedded/pom.xml | 4 ++-- storage/pom.xml | 2 +- storage/rest/adapter/pom.xml | 4 ++-- storage/rest/client-app/pom.xml | 4 ++-- storage/rest/client-jersey/pom.xml | 4 ++-- storage/rest/client/pom.xml | 4 ++-- storage/rest/pom.xml | 2 +- storage/rest/service-sparkjava/pom.xml | 4 ++-- storage/rest/service/pom.xml | 4 ++-- storage/storage/pom.xml | 4 ++-- 53 files changed, 92 insertions(+), 92 deletions(-) diff --git a/afs/aws/aws/pom.xml b/afs/aws/aws/pom.xml index f39fefef..a63a5edc 100644 --- a/afs/aws/aws/pom.xml +++ b/afs/aws/aws/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-aws-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-blobstore - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/aws/dynamodb/pom.xml b/afs/aws/dynamodb/pom.xml index 38f636e6..d61c57a4 100644 --- a/afs/aws/dynamodb/pom.xml +++ b/afs/aws/dynamodb/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-aws-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-aws - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT software.amazon.awssdk diff --git a/afs/aws/pom.xml b/afs/aws/pom.xml index 03473cd8..a2671eea 100644 --- a/afs/aws/pom.xml +++ b/afs/aws/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml diff --git a/afs/aws/s3/pom.xml b/afs/aws/s3/pom.xml index 28097ae6..a2d9a432 100644 --- a/afs/aws/s3/pom.xml +++ b/afs/aws/s3/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-aws-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-aws - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT software.amazon.awssdk diff --git a/afs/azure/pom.xml b/afs/azure/pom.xml index f7fb4578..9fbb7d4e 100644 --- a/afs/azure/pom.xml +++ b/afs/azure/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml diff --git a/afs/azure/storage/pom.xml b/afs/azure/storage/pom.xml index b5626758..1310803e 100644 --- a/afs/azure/storage/pom.xml +++ b/afs/azure/storage/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-azure-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ org.eclipse.store afs-blobstore - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/blobstore/pom.xml b/afs/blobstore/pom.xml index 4e99dad4..0faaeba5 100644 --- a/afs/blobstore/pom.xml +++ b/afs/blobstore/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml diff --git a/afs/googlecloud/firestore/pom.xml b/afs/googlecloud/firestore/pom.xml index 886f3925..2d848a96 100644 --- a/afs/googlecloud/firestore/pom.xml +++ b/afs/googlecloud/firestore/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-googlecloud-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml diff --git a/afs/googlecloud/pom.xml b/afs/googlecloud/pom.xml index 91850a52..ab30fa56 100644 --- a/afs/googlecloud/pom.xml +++ b/afs/googlecloud/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -40,7 +40,7 @@ org.eclipse.store afs-blobstore - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/kafka/pom.xml b/afs/kafka/pom.xml index 63d52759..0a668da0 100644 --- a/afs/kafka/pom.xml +++ b/afs/kafka/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ org.eclipse.store afs-blobstore - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/nio/pom.xml b/afs/nio/pom.xml index ae667dd2..7ea84f02 100644 --- a/afs/nio/pom.xml +++ b/afs/nio/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml diff --git a/afs/oraclecloud/objectstorage/pom.xml b/afs/oraclecloud/objectstorage/pom.xml index 6ba704c0..cb660917 100644 --- a/afs/oraclecloud/objectstorage/pom.xml +++ b/afs/oraclecloud/objectstorage/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-oraclecloud-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-blobstore - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/oraclecloud/pom.xml b/afs/oraclecloud/pom.xml index 85667e28..c5f4c457 100644 --- a/afs/oraclecloud/pom.xml +++ b/afs/oraclecloud/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml diff --git a/afs/pom.xml b/afs/pom.xml index ec68475d..a4e39e5f 100644 --- a/afs/pom.xml +++ b/afs/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store store-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml diff --git a/afs/redis/pom.xml b/afs/redis/pom.xml index 6e9a9245..d3402f11 100644 --- a/afs/redis/pom.xml +++ b/afs/redis/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-blobstore - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/sql/pom.xml b/afs/sql/pom.xml index cbda51d5..4d59ecef 100644 --- a/afs/sql/pom.xml +++ b/afs/sql/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml diff --git a/cache/cache/pom.xml b/cache/cache/pom.xml index ff60477d..1b89ecaa 100644 --- a/cache/cache/pom.xml +++ b/cache/cache/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store cache-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,12 +23,12 @@ org.eclipse.store storage-embedded - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.store storage-embedded-configuration - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT javax.cache diff --git a/cache/hibernate/pom.xml b/cache/hibernate/pom.xml index 42aab9a3..481895bd 100644 --- a/cache/hibernate/pom.xml +++ b/cache/hibernate/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store cache-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store cache - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.hibernate diff --git a/cache/pom.xml b/cache/pom.xml index f0520555..b6035bc1 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store store-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml diff --git a/examples/blobs/pom.xml b/examples/blobs/pom.xml index 3166aca5..b43d9bfe 100644 --- a/examples/blobs/pom.xml +++ b/examples/blobs/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store examples-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ org.eclipse.store storage-embedded - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT diff --git a/examples/custom-legacy-type-handler/pom.xml b/examples/custom-legacy-type-handler/pom.xml index ffe5109e..2fb19a62 100644 --- a/examples/custom-legacy-type-handler/pom.xml +++ b/examples/custom-legacy-type-handler/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/custom-type-handler/pom.xml b/examples/custom-type-handler/pom.xml index d44347e6..18eabc28 100644 --- a/examples/custom-type-handler/pom.xml +++ b/examples/custom-type-handler/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/deleting/pom.xml b/examples/deleting/pom.xml index d92d101c..c316ba00 100644 --- a/examples/deleting/pom.xml +++ b/examples/deleting/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT diff --git a/examples/eager-storing/pom.xml b/examples/eager-storing/pom.xml index 1b0bee7c..a03f6814 100644 --- a/examples/eager-storing/pom.xml +++ b/examples/eager-storing/pom.xml @@ -10,7 +10,7 @@ org.eclipse.store examples-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -24,7 +24,7 @@ org.eclipse.store storage-embedded - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT diff --git a/examples/extension-wrapper/pom.xml b/examples/extension-wrapper/pom.xml index 81675a15..93a673e7 100644 --- a/examples/extension-wrapper/pom.xml +++ b/examples/extension-wrapper/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store examples-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ org.eclipse.store storage-embedded - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT diff --git a/examples/filesystems/pom.xml b/examples/filesystems/pom.xml index 042f1059..c4d28226 100644 --- a/examples/filesystems/pom.xml +++ b/examples/filesystems/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT com.google.jimfs diff --git a/examples/helloworld-ini/pom.xml b/examples/helloworld-ini/pom.xml index 8700005e..11bcd9bf 100644 --- a/examples/helloworld-ini/pom.xml +++ b/examples/helloworld-ini/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,12 +23,12 @@ org.eclipse.store storage-embedded - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.store storage-embedded-configuration - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml index 23089300..4398f7a6 100644 --- a/examples/helloworld/pom.xml +++ b/examples/helloworld/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT diff --git a/examples/items/pom.xml b/examples/items/pom.xml index 44f08b93..0c88e12b 100644 --- a/examples/items/pom.xml +++ b/examples/items/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/layered-entities/pom.xml b/examples/layered-entities/pom.xml index bbb278af..a86b8332 100644 --- a/examples/layered-entities/pom.xml +++ b/examples/layered-entities/pom.xml @@ -10,7 +10,7 @@ org.eclipse.store examples-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml diff --git a/examples/lazy-loading/pom.xml b/examples/lazy-loading/pom.xml index 3df414a1..f49407c6 100644 --- a/examples/lazy-loading/pom.xml +++ b/examples/lazy-loading/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/loading/pom.xml b/examples/loading/pom.xml index c9251248..38123a82 100644 --- a/examples/loading/pom.xml +++ b/examples/loading/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/pom.xml b/examples/pom.xml index fc4777b5..d97cd993 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store store-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml diff --git a/examples/reloader/pom.xml b/examples/reloader/pom.xml index 83197810..66917dbc 100644 --- a/examples/reloader/pom.xml +++ b/examples/reloader/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded-configuration - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT diff --git a/examples/spring-boot3-simple/pom.xml b/examples/spring-boot3-simple/pom.xml index bcedb84c..8f698871 100644 --- a/examples/spring-boot3-simple/pom.xml +++ b/examples/spring-boot3-simple/pom.xml @@ -6,7 +6,7 @@ org.eclipse.store examples-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -48,7 +48,7 @@ org.eclipse.store integrations-spring-boot3 - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT diff --git a/examples/storing/pom.xml b/examples/storing/pom.xml index 9fdcfba7..34b96a06 100644 --- a/examples/storing/pom.xml +++ b/examples/storing/pom.xml @@ -10,7 +10,7 @@ org.eclipse.store examples-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -24,7 +24,7 @@ org.eclipse.store storage-embedded - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.serializer diff --git a/integrations/pom.xml b/integrations/pom.xml index 9de0a7c7..8ac0c3ff 100644 --- a/integrations/pom.xml +++ b/integrations/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store store-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml diff --git a/integrations/spring-boot3/pom.xml b/integrations/spring-boot3/pom.xml index a77e0ebf..2ff0461b 100644 --- a/integrations/spring-boot3/pom.xml +++ b/integrations/spring-boot3/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store integrations - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -59,7 +59,7 @@ org.eclipse.store storage-embedded - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT @@ -77,7 +77,7 @@ org.eclipse.store storage-embedded-configuration - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index c8a228d9..416edde5 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ org.eclipse.store store-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT pom EclipseStore diff --git a/storage/embedded-configuration/pom.xml b/storage/embedded-configuration/pom.xml index b2665b13..e3cdcb9e 100644 --- a/storage/embedded-configuration/pom.xml +++ b/storage/embedded-configuration/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.serializer diff --git a/storage/embedded-tools/pom.xml b/storage/embedded-tools/pom.xml index 018eb5fc..cbd57884 100644 --- a/storage/embedded-tools/pom.xml +++ b/storage/embedded-tools/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml diff --git a/storage/embedded-tools/storage-converter/pom.xml b/storage/embedded-tools/storage-converter/pom.xml index aaa84ae2..d40d5814 100644 --- a/storage/embedded-tools/storage-converter/pom.xml +++ b/storage/embedded-tools/storage-converter/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-embedded-tools-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded-configuration - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT diff --git a/storage/embedded-tools/storage-migrator/pom.xml b/storage/embedded-tools/storage-migrator/pom.xml index 3cf27fef..036c12d5 100644 --- a/storage/embedded-tools/storage-migrator/pom.xml +++ b/storage/embedded-tools/storage-migrator/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-embedded-tools-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml diff --git a/storage/embedded/pom.xml b/storage/embedded/pom.xml index 260a189c..25ce0ada 100644 --- a/storage/embedded/pom.xml +++ b/storage/embedded/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.slf4j diff --git a/storage/pom.xml b/storage/pom.xml index f15f78fe..951722cf 100644 --- a/storage/pom.xml +++ b/storage/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store store-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml diff --git a/storage/rest/adapter/pom.xml b/storage/rest/adapter/pom.xml index a7314714..2c2978ac 100644 --- a/storage/rest/adapter/pom.xml +++ b/storage/rest/adapter/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT diff --git a/storage/rest/client-app/pom.xml b/storage/rest/client-app/pom.xml index 3e4ac0b0..bb9c8306 100644 --- a/storage/rest/client-app/pom.xml +++ b/storage/rest/client-app/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -50,7 +50,7 @@ org.eclipse.store storage-restclient-jersey - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT com.vaadin diff --git a/storage/rest/client-jersey/pom.xml b/storage/rest/client-jersey/pom.xml index 45cec86e..46ef5ed7 100644 --- a/storage/rest/client-jersey/pom.xml +++ b/storage/rest/client-jersey/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -29,7 +29,7 @@ org.eclipse.store storage-restclient - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.glassfish.jersey.core diff --git a/storage/rest/client/pom.xml b/storage/rest/client/pom.xml index 320994cc..468f9a75 100644 --- a/storage/rest/client/pom.xml +++ b/storage/rest/client/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-restadapter - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT diff --git a/storage/rest/pom.xml b/storage/rest/pom.xml index bb2e9f1f..8ab2cdc9 100644 --- a/storage/rest/pom.xml +++ b/storage/rest/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml diff --git a/storage/rest/service-sparkjava/pom.xml b/storage/rest/service-sparkjava/pom.xml index b496c102..628a8b4b 100644 --- a/storage/rest/service-sparkjava/pom.xml +++ b/storage/rest/service-sparkjava/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -29,7 +29,7 @@ org.eclipse.store storage-restservice - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT com.sparkjava diff --git a/storage/rest/service/pom.xml b/storage/rest/service/pom.xml index efe8f65d..f8c92f7c 100644 --- a/storage/rest/service/pom.xml +++ b/storage/rest/service/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-restadapter - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT diff --git a/storage/storage/pom.xml b/storage/storage/pom.xml index dea8f336..4a4c7d7a 100644 --- a/storage/storage/pom.xml +++ b/storage/storage/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-nio - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.serializer From 6a4d85f90d67a2c27a0e5814fc53519099ed686f Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Thu, 29 Feb 2024 13:50:25 +0100 Subject: [PATCH 078/126] Update README.md (#155) --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e965db37..38f663ae 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ Store and load any Java Object Graph or Subgraphs partially, Relieved of Heavy-weight JPA. Microsecond Response Time. Ultra-High Throughput. Minimum of Latencies. Create Ultra-Fast In-Memory Database Applications & Microservices. +EclipseStore is based on the [Eclipse Serializer](https://github.com/eclipse-serializer/serializer). + ## License EclipseStore is available under [Eclipse Public License - v 2.0](LICENSE). From 9e31cdb1dc15aef5a7623f37923e0847727c8c4f Mon Sep 17 00:00:00 2001 From: Simon Zambrovski Date: Mon, 4 Mar 2024 13:51:43 +0100 Subject: [PATCH 079/126] Further SpringBoot improvements (#136) Add basic controller implementation, #130 Add console, splitt client app to actual app and assembly, move implementation of spring rest service --------- Co-authored-by: Zdenek Jonas Co-authored-by: hg-ms <53219833+hg-ms@users.noreply.github.com> Co-authored-by: Florian Habermann --- .gitignore | 2 + .../misc/pages/integrations/spring-boot.adoc | 84 +++++- .../pages/rest-interface/client-gui.adoc | 10 +- .../storage/pages/rest-interface/index.adoc | 8 +- .../pages/rest-interface/rest-api.adoc | 2 +- .../storage/pages/rest-interface/setup.adoc | 91 +++++- examples/pom.xml | 1 + examples/spring-boot3-advanced/LICENSE | 277 ++++++++++++++++++ examples/spring-boot3-advanced/pom.xml | 82 ++++++ examples/spring-boot3-advanced/readme.md | 91 ++++++ .../AdvancedJokesAndMuppetsApplication.java | 27 ++ .../advanced/controller/JokesController.java | 117 ++++++++ .../controller/MuppetsController.java | 52 ++++ .../example/advanced/model/JokesRoot.java | 34 +++ .../example/advanced/model/MuppetsRoot.java | 33 +++ .../advanced/service/JokesServices.java | 71 +++++ .../advanced/service/JokesServicesImpl.java | 83 ++++++ .../advanced/service/MuppetsInPort.java | 46 +++ .../advanced/service/MuppetsUseCase.java | 69 +++++ .../storage/AdvancedStorageConfiguration.java | 73 +++++ .../advanced/storage/JokesStorage.java | 73 +++++ .../advanced/storage/JokesStorageImpl.java | 95 ++++++ .../advanced/storage/MuppetStorage.java | 26 ++ .../advanced/storage/MuppetsStorageImpl.java | 75 +++++ .../src/main/resources/META-INF/MANIFEST.MF | 1 + .../src/main/resources/application.yaml | 21 ++ .../src/main/resources/jokes.txt | 250 ++++++++++++++++ .../src/main/resources/logback.xml | 17 ++ .../src/main/resources/muppets.txt | 30 ++ examples/spring-boot3-simple/pom.xml | 15 +- examples/spring-boot3-simple/readme.md | 12 + .../spring/boot/example/JokesApplication.java | 41 --- .../simple/SimpleJokesApplication.java | 25 ++ .../controller/JokesController.java | 4 +- .../boot/example/{ => simple}/model/Root.java | 2 +- .../{ => simple}/service/JokesServices.java | 2 +- .../service/JokesServicesImpl.java | 4 +- .../{ => simple}/storage/JokesStorage.java | 2 +- .../storage/JokesStorageImpl.java | 5 +- .../src/main/resources/application.properties | 9 +- .../src/main/resources/logback.xml | 3 +- integrations/itest/.gitignore | 1 + integrations/itest/LICENSE | 277 ++++++++++++++++++ integrations/itest/pom.xml | 71 +++++ .../spring/boot/ITestApplication.java | 21 ++ .../itest/src/main/resources/application.yaml | 7 + .../itest/src/main/resources/banner.txt | 3 + .../boot/types/StoreDataRestDisabledTest.java | 55 ++++ .../test/resources/application-web-itest.yaml | 14 + integrations/pom.xml | 22 ++ integrations/spring-boot3-console/LICENSE | 277 ++++++++++++++++++ integrations/spring-boot3-console/pom.xml | 74 +++++ .../src/main/java/module-info.java | 24 ++ .../RestConsoleAutoConfiguration.java | 58 ++++ .../RestConsoleUiConfiguration.java | 27 ++ .../configuration/RestConsoleProperties.java | 36 +++ .../configuration/UIProperties.java | 33 +++ ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../boot/restconsole/TestClassTest.java | 27 ++ integrations/spring-boot3/.gitignore | 2 + integrations/spring-boot3/pom.xml | 18 +- .../src/main/java/module-info.java | 45 ++- .../DefaultEclipseStoreConfiguration.java | 92 ++++++ .../boot/types/EclipseStoreBeanFactory.java | 63 ---- .../boot/types/EclipseStoreProvider.java | 16 +- .../boot/types/EclipseStoreSpringBoot.java | 84 ++++-- .../boot/types/concurrent/LockAspect.java | 6 +- .../spring/boot/types/concurrent/Mutex.java | 4 +- .../spring/boot/types/concurrent/Read.java | 2 +- .../spring/boot/types/concurrent/Write.java | 4 +- .../configuration/ConfigurationPair.java | 4 +- .../configuration/EclipseStoreProperties.java | 23 +- .../configuration/StorageFilesystem.java | 4 +- .../aws/AbstractAwsProperties.java | 2 +- .../boot/types/configuration/aws/Aws.java | 2 +- .../types/configuration/aws/Credentials.java | 4 +- .../types/configuration/aws/Dynamodb.java | 2 +- .../boot/types/configuration/aws/S3.java | 2 +- .../boot/types/configuration/azure/Azure.java | 2 +- .../configuration/azure/Credentials.java | 6 +- .../types/configuration/azure/Storage.java | 2 +- .../googlecloud/Googlecloud.java | 2 +- .../googlecloud/firestore/Credentials.java | 4 +- .../googlecloud/firestore/Firestore.java | 126 ++++---- .../configuration/oraclecloud/Client.java | 2 +- .../configuration/oraclecloud/ConfigFile.java | 2 +- .../oraclecloud/ObjectStorage.java | 2 +- .../oraclecloud/Oraclecloud.java | 2 +- .../boot/types/configuration/redis/Redis.java | 2 +- .../sql/AbstractSqlConfiguration.java | 2 +- .../boot/types/configuration/sql/Mariadb.java | 2 +- .../boot/types/configuration/sql/Oracle.java | 2 +- .../types/configuration/sql/Postgres.java | 2 +- .../boot/types/configuration/sql/Sql.java | 2 +- .../boot/types/configuration/sql/Sqlite.java | 2 +- .../boot/types/converter/ConfigKeys.java | 5 +- .../EclipseStoreConfigConverter.java | 2 +- .../EmbeddedStorageFoundationFactory.java} | 77 +++-- .../EmbeddedStorageManagerFactory.java | 46 +++ .../legacy/EclipseStoreProviderImpl.java | 61 ++++ ...ot.autoconfigure.AutoConfiguration.imports | 2 + .../types/converter/ConfigFieldsTest.java | 2 +- .../EclipseStoreConfigConverterTest.java | 14 +- .../types/storages/TwoBeanConfiguration.java | 65 ---- .../boot/types/storages/TwoStoragesTest.java | 49 ---- .../boot}/EclipseConfigurationSpringTest.java | 31 +- .../EclipseConfigurationSqlSpringTest.java | 28 +- .../spring/boot}/InjectStorageBeanTest.java | 27 +- .../spring/boot}/RestartStorageBeanTest.java | 72 +++-- .../spring/boot/TestApplication.java | 27 ++ .../spring/boot}/root/AutostartRootTest.java | 15 +- .../integrations/spring/boot}/root/Root.java | 4 +- .../spring/boot}/storages/FirstRoot.java | 2 +- .../spring/boot}/storages/SecondRoot.java | 4 +- .../spring/boot/storages/TwoStoragesTest.java | 110 +++++++ .../application-autostart-root.properties | 4 +- ...ies => application-inject-test.properties} | 2 +- .../resources/application-run-test.properties | 3 + .../resources/application-test.properties | 2 +- .../application-two-storages.properties | 4 +- .../src/test/resources/banner.txt | 12 +- .../src/test/resources/logback-test.xml | 2 +- .../client-app-standalone-assembly/LICENSE | 277 ++++++++++++++++++ .../client-app-standalone-assembly/pom.xml | 107 +++++++ .../src/main/java/module-info.java | 22 ++ .../app/standalone}/types/Application.java | 7 +- .../src/main/resources/application.properties | 8 +- .../src/main/resources/banner.txt | 0 .../src/main/resources/logback.xml | 0 .../app/standalone/types/ApplicationTest.java | 35 +++ storage/rest/client-app/pom.xml | 44 +-- .../client-app/src/main/java/module-info.java | 4 +- .../types/RestClientAppAutoConfiguration.java | 25 ++ .../restclient/app/ui/ConnectView.java | 13 +- .../storage/restclient/app/ui/UIUtils.java | 2 +- storage/rest/pom.xml | 97 +++--- storage/rest/service-springboot/LICENSE | 277 ++++++++++++++++++ storage/rest/service-springboot/pom.xml | 60 ++++ .../src/main/java/module-info.java | 28 ++ .../types/StoreDataRestAutoConfiguration.java | 55 ++++ .../StoreDataRestServiceProperties.java | 53 ++++ .../boot/types/rest/RouteWithMethodsDto.java | 32 ++ .../types/rest/StoreDataRestController.java | 144 +++++++++ ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../RouteWithMethodsDtoSerializationTest.java | 32 ++ 145 files changed, 4850 insertions(+), 681 deletions(-) create mode 100644 examples/spring-boot3-advanced/LICENSE create mode 100644 examples/spring-boot3-advanced/pom.xml create mode 100644 examples/spring-boot3-advanced/readme.md create mode 100644 examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/AdvancedJokesAndMuppetsApplication.java create mode 100644 examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/controller/JokesController.java create mode 100644 examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/controller/MuppetsController.java create mode 100644 examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/model/JokesRoot.java create mode 100644 examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/model/MuppetsRoot.java create mode 100644 examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/service/JokesServices.java create mode 100644 examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/service/JokesServicesImpl.java create mode 100644 examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/service/MuppetsInPort.java create mode 100644 examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/service/MuppetsUseCase.java create mode 100644 examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/AdvancedStorageConfiguration.java create mode 100644 examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/JokesStorage.java create mode 100644 examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/JokesStorageImpl.java create mode 100644 examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/MuppetStorage.java create mode 100644 examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/MuppetsStorageImpl.java create mode 100644 examples/spring-boot3-advanced/src/main/resources/META-INF/MANIFEST.MF create mode 100644 examples/spring-boot3-advanced/src/main/resources/application.yaml create mode 100644 examples/spring-boot3-advanced/src/main/resources/jokes.txt create mode 100644 examples/spring-boot3-advanced/src/main/resources/logback.xml create mode 100644 examples/spring-boot3-advanced/src/main/resources/muppets.txt delete mode 100644 examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/JokesApplication.java create mode 100644 examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/SimpleJokesApplication.java rename examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/{ => simple}/controller/JokesController.java (95%) rename examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/{ => simple}/model/Root.java (91%) rename examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/{ => simple}/service/JokesServices.java (96%) rename examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/{ => simple}/service/JokesServicesImpl.java (93%) rename examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/{ => simple}/storage/JokesStorage.java (96%) rename examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/{ => simple}/storage/JokesStorageImpl.java (92%) create mode 100644 integrations/itest/.gitignore create mode 100644 integrations/itest/LICENSE create mode 100644 integrations/itest/pom.xml create mode 100644 integrations/itest/src/main/java/test/eclipse/store/integration/spring/boot/ITestApplication.java create mode 100644 integrations/itest/src/main/resources/application.yaml create mode 100644 integrations/itest/src/main/resources/banner.txt create mode 100644 integrations/itest/src/test/java/test/eclipse/store/storage/restservice/spring/boot/types/StoreDataRestDisabledTest.java create mode 100644 integrations/itest/src/test/resources/application-web-itest.yaml create mode 100644 integrations/spring-boot3-console/LICENSE create mode 100644 integrations/spring-boot3-console/pom.xml create mode 100644 integrations/spring-boot3-console/src/main/java/module-info.java create mode 100644 integrations/spring-boot3-console/src/main/java/org/eclipse/store/integrations/spring/boot/restconsole/RestConsoleAutoConfiguration.java create mode 100644 integrations/spring-boot3-console/src/main/java/org/eclipse/store/integrations/spring/boot/restconsole/RestConsoleUiConfiguration.java create mode 100644 integrations/spring-boot3-console/src/main/java/org/eclipse/store/integrations/spring/boot/restconsole/configuration/RestConsoleProperties.java create mode 100644 integrations/spring-boot3-console/src/main/java/org/eclipse/store/integrations/spring/boot/restconsole/configuration/UIProperties.java create mode 100644 integrations/spring-boot3-console/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 integrations/spring-boot3-console/src/test/java/org/eclipse/store/integrations/spring/boot/restconsole/TestClassTest.java create mode 100644 integrations/spring-boot3/.gitignore create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java delete mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreBeanFactory.java rename integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/{EclipseStoreProviderImpl.java => factories/EmbeddedStorageFoundationFactory.java} (59%) create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/factories/EmbeddedStorageManagerFactory.java create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/factories/legacy/EclipseStoreProviderImpl.java create mode 100644 integrations/spring-boot3/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoBeanConfiguration.java delete mode 100644 integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoStoragesTest.java rename integrations/spring-boot3/src/test/java/{org/eclipse/store/integrations/spring/boot/types => test/eclipse/store/integrations/spring/boot}/EclipseConfigurationSpringTest.java (74%) rename integrations/spring-boot3/src/test/java/{org/eclipse/store/integrations/spring/boot/types => test/eclipse/store/integrations/spring/boot}/EclipseConfigurationSqlSpringTest.java (74%) rename integrations/spring-boot3/src/test/java/{org/eclipse/store/integrations/spring/boot/types => test/eclipse/store/integrations/spring/boot}/InjectStorageBeanTest.java (55%) rename integrations/spring-boot3/src/test/java/{org/eclipse/store/integrations/spring/boot/types => test/eclipse/store/integrations/spring/boot}/RestartStorageBeanTest.java (53%) create mode 100644 integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/TestApplication.java rename integrations/spring-boot3/src/test/java/{org/eclipse/store/integrations/spring/boot/types => test/eclipse/store/integrations/spring/boot}/root/AutostartRootTest.java (74%) rename integrations/spring-boot3/src/test/java/{org/eclipse/store/integrations/spring/boot/types => test/eclipse/store/integrations/spring/boot}/root/Root.java (83%) rename integrations/spring-boot3/src/test/java/{org/eclipse/store/integrations/spring/boot/types => test/eclipse/store/integrations/spring/boot}/storages/FirstRoot.java (90%) rename integrations/spring-boot3/src/test/java/{org/eclipse/store/integrations/spring/boot/types => test/eclipse/store/integrations/spring/boot}/storages/SecondRoot.java (91%) create mode 100644 integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/storages/TwoStoragesTest.java rename integrations/spring-boot3/src/test/resources/{application-run.properties => application-inject-test.properties} (88%) create mode 100644 integrations/spring-boot3/src/test/resources/application-run-test.properties create mode 100644 storage/rest/client-app-standalone-assembly/LICENSE create mode 100644 storage/rest/client-app-standalone-assembly/pom.xml create mode 100644 storage/rest/client-app-standalone-assembly/src/main/java/module-info.java rename storage/rest/{client-app/src/main/java/org/eclipse/store/storage/restclient/app => client-app-standalone-assembly/src/main/java/org/eclipse/store/storage/restclient/app/standalone}/types/Application.java (74%) rename storage/rest/{client-app => client-app-standalone-assembly}/src/main/resources/application.properties (99%) rename storage/rest/{client-app => client-app-standalone-assembly}/src/main/resources/banner.txt (100%) rename storage/rest/{client-app => client-app-standalone-assembly}/src/main/resources/logback.xml (100%) create mode 100644 storage/rest/client-app-standalone-assembly/src/test/java/org/eclipse/store/storage/restclient/app/standalone/types/ApplicationTest.java create mode 100644 storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/types/RestClientAppAutoConfiguration.java create mode 100644 storage/rest/service-springboot/LICENSE create mode 100644 storage/rest/service-springboot/pom.xml create mode 100644 storage/rest/service-springboot/src/main/java/module-info.java create mode 100644 storage/rest/service-springboot/src/main/java/org/eclipse/store/storage/restservice/spring/boot/types/StoreDataRestAutoConfiguration.java create mode 100644 storage/rest/service-springboot/src/main/java/org/eclipse/store/storage/restservice/spring/boot/types/configuration/StoreDataRestServiceProperties.java create mode 100644 storage/rest/service-springboot/src/main/java/org/eclipse/store/storage/restservice/spring/boot/types/rest/RouteWithMethodsDto.java create mode 100644 storage/rest/service-springboot/src/main/java/org/eclipse/store/storage/restservice/spring/boot/types/rest/StoreDataRestController.java create mode 100644 storage/rest/service-springboot/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 storage/rest/service-springboot/src/test/java/org/eclipse/store/storage/restservice/spring/boot/types/rest/RouteWithMethodsDtoSerializationTest.java diff --git a/.gitignore b/.gitignore index cfdf09dc..d952bf7d 100644 --- a/.gitignore +++ b/.gitignore @@ -86,3 +86,5 @@ profile .asciidoctor/ .asciidoctorconfig.adoc +jokes_storage/ +storage/rest/client-app/src/main/dev-bundle/ diff --git a/docs/modules/misc/pages/integrations/spring-boot.adoc b/docs/modules/misc/pages/integrations/spring-boot.adoc index 5344fb38..e14fec83 100644 --- a/docs/modules/misc/pages/integrations/spring-boot.adoc +++ b/docs/modules/misc/pages/integrations/spring-boot.adoc @@ -33,16 +33,17 @@ org.eclipse.store.channel-count=2 The list of all {product-name} configuration properties and their meaning are listed on our xref:storage:configuration/properties.adoc[documentation page]. The configuration values are handled using the https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config.typesafe-configuration-properties[typesafe configuration] approach, and you can read these values by accessing the `EclipseStoreProperties` Spring bean. +The Spring Boot integration provides a set of Bean Factories which read the configuration and initialize the relevant {product-name} facilities for you, +including `EmbeddedStorageManager`. == StorageManager injection -The simplest way to use this integration is when you can externalize all the configuration using Spring configuration files. Subsequently, you just create a Spring Boot application and add a dependency on the integration. Then, in the Bean where you need access to the StorageManager, you add the @Autowired annotation and a StorageManager is created for you. All configuration values are loaded from the external configuration and the StorageManager is already initialized and ready to use. +The simplest way to use this integration is when you can externalize all the configuration using Spring configuration files. Subsequently, you just create a Spring Boot application and add a dependency on the integration. Then, in the Bean where you need access to the StorageManager, you add the `@Autowired` annotation and a StorageManager is created for you. All configuration values are loaded from the external configuration and the StorageManager is already initialized and ready to use. === Example: [source,java] ---- @SpringBootApplication -@Import(EclipseStoreSpringBoot.class) public class SomeSpringApplication { public static void main(String... args) @@ -68,23 +69,29 @@ public class JokesStorageImpl implements JokesStorage == Configuration Injection -In case you need to modify the configuration in some way in the program, change something, add and the like, you can have the `EclipseStoreProperties` Spring bean injected into your class. This class contains all the configuration values that are used to create a `StorageManager`. You can modify these values and then use the `EclipseStoreProvider` Bean to create a new StorageManager or `EmbeddedStorageFoundation`. +In case you need to modify the configuration in some way in the program, change something, add and the like, you can have the `EclipseStoreProperties` Spring bean injected into your class. +This class contains all the configuration values that are used to create a `StorageManager`. +You can modify these values and then use the `EmbeddedStorageManagerFactory` Bean to create +a new `EmbeddedStorageManager` or `EmbeddedStorageFoundationFactory` to create a new `EmbeddedStorageFoundation`. [source,java] ---- @Bean - EmbeddedStorageManager injectStorageTest(@Autowired EclipseStoreProperties myConfiguration, @Autowired EclipseStoreProvider provider) - { + EmbeddedStorageManager injectStorageTest( + @Autowired EclipseStoreProperties myConfiguration, + @Autowired EmbeddedStorageManagerFactory managerFactory, + @Autowired EmbeddedStorageFoundationFactory foundationFactory + ) { // Modify the configuration myConfiguration.setStorageDirectory(temp.getDir().getAbsolutePath()); // Create a new StorageFoundation - EmbeddedStorageFoundation storageFoundation = provider.createStorageFoundation(myConfiguration); + EmbeddedStorageFoundation storageFoundation = foundationFactory.createStorageFoundation(myConfiguration); // Modify the storageFoundation //storageFoundation.onConnectionFoundation(f -> f.someOperation); // Create a new StorageManager - return storageFoundation.createEmbeddedStorageManager(); + return managerFactory.createEmbeddedStorageManager(storageFoundation, true); } ---- @@ -106,7 +113,9 @@ public class TwoBeanConfiguration { @Autowired - private EclipseStoreProvider provider; + private EmbeddedStorageFoundationFactory foundationFactory; + @Autowired + private EmbeddedStorageManagerFactory managerFactory; @Bean("first_config") @ConfigurationProperties("org.eclipse.store.first") @@ -123,19 +132,21 @@ public class TwoBeanConfiguration } @Bean - @Lazy @Qualifier("first_storage") - EmbeddedStorageManager createFirstStorage(@Qualifier("first_config") EclipseStoreProperties firstStoreProperties) - { - return provider.createStorage(firstStoreProperties); + EmbeddedStorageManager createFirstStorage(@Qualifier("first_config") final EclipseStoreProperties firstStoreProperties) { + return managerFactory.createStorage( + foundationFactory.createStorageFoundation(firstStoreProperties), + firstStoreProperties.isAutoStart() + ); } @Bean - @Lazy @Qualifier("second_storage") - EmbeddedStorageManager createSecondStorage(@Qualifier("second_config") EclipseStoreProperties secondStoreProperties) - { - return provider.createStorage(secondStoreProperties); + EmbeddedStorageManager createSecondStorage(@Qualifier("second_config") final EclipseStoreProperties secondStoreProperties) { + return managerFactory.createStorage( + foundationFactory.createStorageFoundation(secondStoreProperties), + secondStoreProperties.isAutoStart() + ); } } @@ -204,6 +215,7 @@ to obtain all {product-name} configuration keys: Key values containing "password" are replaced by "xxxxx". == Register JDK 17 and JDK 8 Handlers + Handler for JDK 17 are registered automatically. Handler for JDK 8 are not registered automatically, because of the backwards compatibility. If you create a new storage you can enable these handlers. If you have an existing storage created with JDK8 handlers, you have to active it too. If you need to register JDK 8 handlers, you can do it by adding the following code to your configuration: @@ -212,3 +224,43 @@ If you need to register JDK 8 handlers, you can do it by adding the following co ---- org.eclipse.store.register-jdk8-handlers=true ---- + +== Activating REST Service SpringBoot + +If you are interested in using the {product-name} REST service in your application, consider to include the SpringBoot REST Service. +Detailed documentation can be found at xref:storage:rest-interface/setup.adoc[Setup of Spring Boot REST Service]. + +== Activating Client GUI + +You can include the Client GUI application to be directly as a module served by your application. For this purpose, include +the SpringBoot Console to your application classpath. We assume that you are starting Spring MVC in your application already. + +Please add the following dependency to Maven pom.xml of your SpringBoot application: + +[source,xml] +---- + + org.eclipse.store + integrations-spring-boot3-console + {maven-version} + +---- + +In order to operate properly, Client GUI requires a working SpringBoot REST Service. This is already prepackaged in the +console module and needs to be activated. In addition, the path to the Client GUI needs to be configured. + +Please set the following properties in your configuration file: + +[source,properties] +---- +org.eclipse.store.rest.enabled=true +vaadin.url-mapping=/store-console/* +---- + +The Client GUI will start with your application and will be available at the specified URL. So if your SpringBoot application +starts a web server on port `8080` the Client GUI will be available at: http://localhost:8080/store-console/. Open this URL +in your browser, select from the dropdown list the endpoint of the Spring REST Service (http://localhost:8080/store-data/) +and click connect. + + + diff --git a/docs/modules/storage/pages/rest-interface/client-gui.adoc b/docs/modules/storage/pages/rest-interface/client-gui.adoc index e309b8da..efb39487 100644 --- a/docs/modules/storage/pages/rest-interface/client-gui.adoc +++ b/docs/modules/storage/pages/rest-interface/client-gui.adoc @@ -6,29 +6,29 @@ It is a runnable jar which starts a simple web server which then can be accessed [NOTE] ==== -Since {product-name} version 1.1.0 The Client GUI requires java 17! +Since {product-name} version 1.1.0 The Client GUI requires Java 17 to run! ==== To download it use the following Maven command to download it into the current directory. [source, shell, title="CLI"] ---- -mvn dependency:get -Dartifact=org.eclipse.store:storage-restclient-app:{maven-version}:jar -Dtransitive=false -Ddest=storage.restclient.app-{maven-version}.jar +mvn dependency:get -Dartifact=org.eclipse.store:storage-restclient-app-standalone:{maven-version}:jar -Dtransitive=false -Ddest=storage.restclient.app-{maven-version}.jar ---- or this direct link: -https://oss.sonatype.org/content/repositories/snapshots/org/eclipse/store/storage-restclient-app/{maven-version}/storage-restclient-app-{maven-version}.jar +https://oss.sonatype.org/content/repositories/snapshots/org/eclipse/store/storage-restclient-app/{maven-version}/storage-restclient-app-standalone-{maven-version}.jar Start the client. The port parameter is optional, default port is 8080. [source, text, subs=attributes+] ---- -java -jar storage-restclient-app-{maven-version}.jar --server.port=8888 +java -jar storage-restclient-app-standalone-{maven-version}.jar --server.port=8888 ---- -Then just open http://localhost:8888 in your browser, select the base URL of the REST service and click connect. +Then just open http://localhost:8888/ in your browser, select the base URL of the REST service and click connect. image::rest-client-gui.png[] diff --git a/docs/modules/storage/pages/rest-interface/index.adoc b/docs/modules/storage/pages/rest-interface/index.adoc index 1e3fd7eb..53d6f1c3 100644 --- a/docs/modules/storage/pages/rest-interface/index.adoc +++ b/docs/modules/storage/pages/rest-interface/index.adoc @@ -32,9 +32,15 @@ It is made up of the following modules: |storage-restservice-sparkjava |REST service implementation which utilizes SparkJava and provides REST endpoints. +|storage-restservice-springboot +|REST service implementation which utilizes SpringBoot and Spring MVC and provides REST endpoints. + |storage-restclient-jersey |REST client implementation which utilizes Jersey as a webservice framework. |storage-restclient-app -|Executable client app with web user interface, which connects to a REST service and provides a simple UI to navigate through the Object Graph from the root. +|Client app with web user interface, which connects to a REST service and provides a simple UI to navigate through the Object Graph from the root. + +|storage-restclient-app-standalone +|A standalone executable running from command line encapsulating the Client app from storage-restclient-app. |=== diff --git a/docs/modules/storage/pages/rest-interface/rest-api.adoc b/docs/modules/storage/pages/rest-interface/rest-api.adoc index e25b2190..53ca68de 100644 --- a/docs/modules/storage/pages/rest-interface/rest-api.adoc +++ b/docs/modules/storage/pages/rest-interface/rest-api.adoc @@ -106,7 +106,7 @@ Returns description and values of a distinct object. [instance-name]/dictionary ---- -Returns the type dictionary as plain text. +Returns the type dictionary as text output. [source, json, title="Response"] ---- diff --git a/docs/modules/storage/pages/rest-interface/setup.adoc b/docs/modules/storage/pages/rest-interface/setup.adoc index 78cd5e9a..7a0eb1ea 100644 --- a/docs/modules/storage/pages/rest-interface/setup.adoc +++ b/docs/modules/storage/pages/rest-interface/setup.adoc @@ -1,24 +1,85 @@ = Setup -== REST Service +An application that will expose the REST endpoints needs one of the provided implementations by {product-name} or you need to implement the provided interfaces. -An application that will expose the REST endpoints needs one of the provided implementations by {product-name} or you need to implement the provided interfaces. In this example, we will use the https://sparkjava.com/[Spark] implementation that {product-name} provides. +Currently, two implementations are available: -Just add the dependency to your project, the logger is optional. +- SpringBoot 3.x REST Service +- Spark Java REST Service + +== Spring Boot REST Service + +In this example, we will use Spring Boot implementation that {product-name} provides. This requires a fully functional +Spring Boot 3 with Spring Web MVC already set-up and configured. If you are unsure how to do so, please consult the +original https://spring.io/projects/spring-boot[SpringBoot] documentation. + +Please add the following dependencies to your project: [source, xml, title="pom.xml", subs=attributes+] ---- - + org.eclipse.store - storage-restservice-sparkjava + storage-restservice-springboot {maven-version} - - - org.slf4j - slf4j-simple - 1.7.32 - + + + org.springframework.boot + spring-boot-starter-web + ${spring-boot.version} + + +---- + +Using your preferred configuration format, please activate the REST service in your configuration. +For example using properties file the configuration looks like: + +[source, properties, title="application.properties", subs=attributes+] +---- +org.eclipse.store.rest.enabled=true +---- + +This is it. This configuration will provide an additional REST endpoint accessible via `/store-data/` providing information +about your store. If your application starts a web server on port 8080, and you haven't changed the default configuration, +the complete base URL will be `http://localhost:8080/store-data/`. Open it a browser to see further available URLs +provided by the REST service. + +The REST controller is able to provide information about multiple Storage managers of your system. For a storage manager called +`some` its details are available via `/storage-data/some`. If you haven't changed the storage manager configuration and use the +default one provided by the SpringBoot integration, it will be available via `/storage-data/default`. + +=== Additional Configuration + +You might want to change the base URL of your service. This is possible using the configuration file of your SpringBoot +application. The corresponding property is `org.eclipse.store.rest.base-url`. The example below changes the base URL to +`/some/other/location`: + +[source, properties, title="application.properties", subs=attributes+] +---- +org.eclipse.store.rest.base-url=/some/other/location +---- + +== Spark Java REST Service + +In this example, we will use the https://sparkjava.com/[Spark] implementation that {product-name} provides. +This has no dependencies to other frameworks and makes no assumptions about your runtime environment, IoC container, +dependency injection, web server or anything else. + +Just add the dependency to your project, the logger is optional. + +[source, xml, title="pom.xml", subs=attributes+] +---- + + + org.eclipse.store + storage-restservice-sparkjava + {maven-version} + + + org.slf4j + slf4j-simple + 1.7.32 + ---- @@ -46,11 +107,11 @@ service.start(); That's all you have to do to open the REST endpoints to access the stored data. -The base URL of the provided endpoints is per default: http://localhost:4567/eclipsestore/ and you can find out all available endpoints on the root http://localhost:4567 +The base URL of the provided endpoints is per default: http://localhost:4567/store-data/ and you can find out all available endpoints on the root http://localhost:4567 -== Configuration +=== Additional Configuration -If you want to change the default port (4567) or instance name (_eclipsestore_) it can be done by using the rest service implementation directly, and not go through the _Resolver` as in the previous snippet. +If you want to change the default port (4567) or instance name (_store-data_) it can be done by using the rest service implementation directly, and not go through the _Resolver` as in the previous snippet. The Spark service can then be customized to your liking. @@ -63,4 +124,4 @@ service.setSparkService( service.setInstanceName("my-name"); ---- -This will change the base URL to http://localhost/my-name/ +This will change the base URL to http://localhost:8888/my-name/ diff --git a/examples/pom.xml b/examples/pom.xml index d97cd993..e2efcb49 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -86,6 +86,7 @@ spring-boot3-simple + spring-boot3-advanced diff --git a/examples/spring-boot3-advanced/LICENSE b/examples/spring-boot3-advanced/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/examples/spring-boot3-advanced/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/examples/spring-boot3-advanced/pom.xml b/examples/spring-boot3-advanced/pom.xml new file mode 100644 index 00000000..3877bcf8 --- /dev/null +++ b/examples/spring-boot3-advanced/pom.xml @@ -0,0 +1,82 @@ + + + 4.0.0 + + org.eclipse.store + examples-parent + 1.3.0-SNAPSHOT + ../pom.xml + + + EclipseStore Example Spring Boot3 Advanced + examples-spring-boot3-advanced + + + 17 + 17 + UTF-8 + 3.2.2 + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.2.0 + + + + org.eclipse.store + integrations-spring-boot3 + 1.3.0-SNAPSHOT + + + + org.eclipse.store + integrations-spring-boot3-console + 1.3.0-SNAPSHOT + + + + + spring-boot3-advanced + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + + + + diff --git a/examples/spring-boot3-advanced/readme.md b/examples/spring-boot3-advanced/readme.md new file mode 100644 index 00000000..55faac6f --- /dev/null +++ b/examples/spring-boot3-advanced/readme.md @@ -0,0 +1,91 @@ +# Spring Boot Eclipse Store Sample Application (Advanced example) + +This application serves as a comprehensive display of the Eclipse Store Spring Boot extension's functionalities. +It exemplifies the seamless integration of a pre-configured storage into an application as a bean, illustrates +effective utilization of the locking API, and provides insights into designing an MVC application using Eclipse Store. + +## Implementation Notes +* The Controller performs data conversion into JSON, therefore it must always operate with immutable data or, in the case of mutable data, it must receive a copy of such data. +* Minimum Java version is 17. +* Build tool is Apache Maven. + +## Build + +The generation of the executable jar file can be performed by issuing the following command: + +```shell +mvn clean package +``` + +This will create an executable jar file **spring-boot3-advanced.jar** within the _target_ maven folder. +This can be started by executing the following command + +```shell +java -jar target/spring-boot3-advanced.jar +``` + +To launch the test page, open your browser at the following URL +```shell +http://localhost:8080/ +``` + +## Using Swagger UI + +The example application provides a handy UI for sending REST request to provided endpoints. To use the UI, please run the application +and open http://localhost:8080/swagger-ui/index.html in your browser. Then navigate to desired operation, fill required data and +send the requests. + +## Using Console + +You may be interested in the state of your data. The example includes the Console for debugging purposes. +Please open http://localhost:8080/store-console/ +in your browser, enter http://localhost:8080/store-data/jokesStore/, click connect and inspect the data jokes in your store. +Enter http://localhost:8080/store-data/muppetsStore/, click connect and inspect the data muppets in your store. + + +## Using App rest api +This examples use Curl for Linux/macOS. You can use any other tool for sending HTTP requests. +Load sample data. Without this step, the application will not contain any data. It is not mandatory to execute this step, but without it you will have to add all your data manually. +```shell +curl --location --request POST 'http://localhost:8080/jokes/init' \ +--header 'Content-Type: application/json' +``` + +Get all jokes +```shell +curl --location --request GET 'http://localhost:8080/jokes' \ +--header 'Content-Type: application/json' +``` + +Get joke by Id +```shell +curl --location --request GET 'http://localhost:8080/jokes/joke?id=50' \ +--header 'Content-Type: application/json' +``` + +Add new Joke +```shell +curl --location --request POST 'http://localhost:8080/jokes/add' \ +--header 'Content-Type: application/json' \ +--data-raw '{great new joke}' +``` + +## Using App rest api for Muppets + +Load sample data for Muppets. Without this step, the application will not contain any Muppet data. It is not mandatory to execute this step, but without it there will be no data in the storage. +```shell +curl --location --request POST 'http://localhost:8080/muppets/init' \ +--header 'Content-Type: application/json' +``` + +Get all Muppets +```shell +curl --location --request GET 'http://localhost:8080/muppets' \ +--header 'Content-Type: application/json' +``` + +Get Muppet by Id +```shell +curl --location --request GET 'http://localhost:8080/muppets/muppet?id=5' \ +--header 'Content-Type: application/json' +``` diff --git a/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/AdvancedJokesAndMuppetsApplication.java b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/AdvancedJokesAndMuppetsApplication.java new file mode 100644 index 00000000..a1bf6ab3 --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/AdvancedJokesAndMuppetsApplication.java @@ -0,0 +1,27 @@ +package org.microstream.spring.boot.example.advanced; + +/*- + * #%L + * spring-boot3-simple + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AdvancedJokesAndMuppetsApplication +{ + public static void main(String... args) + { + SpringApplication.run(AdvancedJokesAndMuppetsApplication.class, args); + } +} diff --git a/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/controller/JokesController.java b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/controller/JokesController.java new file mode 100644 index 00000000..795ab01e --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/controller/JokesController.java @@ -0,0 +1,117 @@ +package org.microstream.spring.boot.example.advanced.controller; + +/*- + * #%L + * spring-boot3-simple + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.microstream.spring.boot.example.advanced.service.JokesServices; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * The {@code JokesController} class is a Spring REST controller that provides endpoints for managing jokes. + * It uses the {@code JokesServices} to perform operations on jokes. + * + *

    This class is annotated with {@code @RestController}, which means it is a Spring MVC controller and its methods return domain objects instead of views.

    + * + *

    Here's an example of how to use this controller:

    + *
    + * 
    + * GET /jokes/joke?id=1
    + * POST /jokes/add
    + * {
    + *     "joke": "Why don't scientists trust atoms? Because they make up everything!"
    + * }
    + * 
    + * 
    + * + * In this example, the first request gets the joke with ID 1 and the second request adds a new joke. + */ +@RestController +@RequestMapping("/jokes") +public class JokesController +{ + + private final JokesServices jokesServices; + + /** + * Constructs a new {@code JokesController} with the provided {@code JokesServices}. + * JokesServices is a Spring component and is injected by Spring. + * + * @param jokesServices The services used to perform operations on jokes. + */ + public JokesController(JokesServices jokesServices) + { + this.jokesServices = jokesServices; + } + + /** + * Returns all jokes. + * + * @return A list of all jokes. + */ + @GetMapping + public List getAll() + { + return jokesServices.allJokes(); + } + + /** + * Returns the joke with the specified ID. + * + * @param id The ID of the joke. + * @return The joke with the specified ID. + */ + @GetMapping("/joke") + public String getOneJoke(@RequestParam(name = "id") Integer id) + { + return jokesServices.oneJoke(id); + } + + /** + * Adds a new joke. + * + * @param joke The joke to add. + * @return The ID of the added joke. + */ + @PostMapping("/add") + public Integer putOne(@RequestBody String joke) + { + return jokesServices.addNewJoke(joke); + } + + /** + * Loads predefined jokes. + */ + @PostMapping("/init") + public void init() + { + jokesServices.loadPredefinedJokes(); + } + + /** + * Inserts a new joke. + * This method functions similarly to the 'putOne' method. However, it differs in its implementation by utilizing a nested locking mechanism. + * The '@Write Lock' annotation is applied at the service layer, invoking the storage layer within another locking annotation. + * This implementation is solely intended for demonstration purposes. + * + * @param joke The new joke to be added. + * @return The position of the currently inserted joke in storage. + */ + @PostMapping("/insert") + public Integer insert(@RequestBody String joke) + { + return jokesServices.insertNewJoke(joke); + } +} diff --git a/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/controller/MuppetsController.java b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/controller/MuppetsController.java new file mode 100644 index 00000000..21a69f4e --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/controller/MuppetsController.java @@ -0,0 +1,52 @@ +package org.microstream.spring.boot.example.advanced.controller; + +/*- + * #%L + * EclipseStore Example Spring Boot3 Advanced + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.microstream.spring.boot.example.advanced.service.MuppetsInPort; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/muppets") +public class MuppetsController +{ + + private final MuppetsInPort muppets; + + public MuppetsController(MuppetsInPort muppets) + { + this.muppets = muppets; + } + + @GetMapping + public List getAll() + { + return muppets.getAllMuppets(); + } + + @GetMapping("/muppet") + public String getOneJoke(@RequestParam(name = "id") Integer id) + { + return muppets.getMuppet(id); + } + + @PostMapping("/init") + public void init() + { + muppets.initialize(); + } + +} diff --git a/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/model/JokesRoot.java b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/model/JokesRoot.java new file mode 100644 index 00000000..93208362 --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/model/JokesRoot.java @@ -0,0 +1,34 @@ +package org.microstream.spring.boot.example.advanced.model; + +/*- + * #%L + * spring-boot3-simple + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.ArrayList; +import java.util.List; + +public class JokesRoot +{ + private List jokes = new ArrayList<>(); + + public List getJokes() + { + return jokes; + } + + public void setJokes(List jokes) + { + this.jokes = jokes; + } + +} diff --git a/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/model/MuppetsRoot.java b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/model/MuppetsRoot.java new file mode 100644 index 00000000..cecf27ff --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/model/MuppetsRoot.java @@ -0,0 +1,33 @@ +package org.microstream.spring.boot.example.advanced.model; + +/*- + * #%L + * spring-boot3-simple + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.ArrayList; +import java.util.List; + +public class MuppetsRoot +{ + private List muppets = new ArrayList<>(); + + public List getMuppets() + { + return muppets; + } + + public void setMuppets(List muppets) + { + this.muppets = muppets; + } +} diff --git a/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/service/JokesServices.java b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/service/JokesServices.java new file mode 100644 index 00000000..9951e4f7 --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/service/JokesServices.java @@ -0,0 +1,71 @@ +package org.microstream.spring.boot.example.advanced.service; + +/*- + * #%L + * spring-boot3-simple + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.List; + +/** + * The {@code JokesServices} interface provides methods for managing jokes in the application. + * It is used as a part of the joke service in the application. + * + *

    Here's an example of how to use this interface:

    + *
    + * 
    + * JokesServices jokesServices = ... // get an instance of JokesServices
    + * jokesServices.addNewJoke("Why don't scientists trust atoms? Because they make up everything!");
    + * List allJokes = jokesServices.allJokes();
    + * 
    + * 
    + *

    + * In this example, a new joke is added to the service and then all jokes are retrieved. + */ +public interface JokesServices +{ + /** + * Returns a joke with the specified ID. + * + * @param id The ID of the joke. + * @return The joke with the specified ID. + */ + String oneJoke(Integer id); + + /** + * Returns all jokes. + * + * @return A list of all jokes. + */ + List allJokes(); + + /** + * Adds a new joke. + * + * @param joke The joke to add. + * @return The ID of the added joke. + */ + Integer addNewJoke(String joke); + + /** + * Loads predefined jokes. + */ + void loadPredefinedJokes(); + + /** + * Inserts a new joke. + * + * @param joke The joke to insert. + * @return The ID of the inserted joke. + */ + Integer insertNewJoke(String joke); +} diff --git a/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/service/JokesServicesImpl.java b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/service/JokesServicesImpl.java new file mode 100644 index 00000000..4d0086b9 --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/service/JokesServicesImpl.java @@ -0,0 +1,83 @@ +package org.microstream.spring.boot.example.advanced.service; + +/*- + * #%L + * spring-boot3-simple + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.integrations.spring.boot.types.concurrent.Write; +import org.microstream.spring.boot.example.advanced.storage.JokesStorage; +import org.springframework.stereotype.Service; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +@Service +public class JokesServicesImpl implements JokesServices +{ + private final JokesStorage jokesStorage; + + + @Override + public String oneJoke(Integer id) + { + String joke; + joke = jokesStorage.oneJoke(Objects.requireNonNullElse(id, 0)); + return joke; + } + + public JokesServicesImpl(JokesStorage jokesStorage) + { + this.jokesStorage = jokesStorage; + } + + @Override + public List allJokes() + { + return jokesStorage.allJokes(); + } + + @Override + public Integer addNewJoke(String joke) + { + return jokesStorage.addNewJoke(joke); + } + + @Override + public void loadPredefinedJokes() + { + List jokes = null; + InputStream inputStream = getClass().getClassLoader().getResourceAsStream("jokes.txt"); + assert inputStream != null; + jokes = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)) + .lines() + .collect(Collectors.toList()); + List existingJokes = jokesStorage.allJokes(); + if (existingJokes.containsAll(jokes)) + { + return; + } + jokesStorage.addJokes(jokes); + } + + @Override + @Write + public Integer insertNewJoke(String joke) + { + List jokes = jokesStorage.allJokes(); + jokes.add(joke); + return jokesStorage.saveAllJokes(jokes); + } +} diff --git a/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/service/MuppetsInPort.java b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/service/MuppetsInPort.java new file mode 100644 index 00000000..1126d270 --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/service/MuppetsInPort.java @@ -0,0 +1,46 @@ +package org.microstream.spring.boot.example.advanced.service; + +/*- + * #%L + * EclipseStore Example Spring Boot3 Advanced + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.List; + +/** + * The MuppetsInPort interface provides methods for managing Muppets in a port. + * This includes retrieving a specific Muppet by its ID, getting all Muppets, and initializing the port. + */ +public interface MuppetsInPort +{ + /** + * Retrieves a Muppet by its ID. + * + * @param id The ID of the Muppet to retrieve. + * @return The Muppet as a String. + */ + String getMuppet(Integer id); + + /** + * Retrieves all Muppets in the port. + * + * @return A list of all Muppets as Strings. + */ + List getAllMuppets(); + + /** + * Initializes the port. This method should be called before any operations are performed on the port. + * It is responsible for setting up necessary data structures and ensuring the port is ready for operations. + */ + void initialize(); + +} diff --git a/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/service/MuppetsUseCase.java b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/service/MuppetsUseCase.java new file mode 100644 index 00000000..b5dd39aa --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/service/MuppetsUseCase.java @@ -0,0 +1,69 @@ +package org.microstream.spring.boot.example.advanced.service; + +/*- + * #%L + * EclipseStore Example Spring Boot3 Advanced + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.microstream.spring.boot.example.advanced.storage.MuppetStorage; +import org.springframework.stereotype.Component; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +@Component +public class MuppetsUseCase implements MuppetsInPort +{ + private final MuppetStorage storage; + + public MuppetsUseCase(MuppetStorage storage) + { + this.storage = storage; + } + + @Override + public String getMuppet(Integer id) + { + return storage.oneMuppet(id); + } + + @Override + public List getAllMuppets() + { + return storage.allMuppets(); + } + + @Override + public void initialize() + { + try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("muppets.txt")) + { + List muppets = new BufferedReader(new InputStreamReader(Objects.requireNonNull(inputStream), StandardCharsets.UTF_8)) + .lines() + .collect(Collectors.toList()); + if (storage.allMuppets().containsAll(muppets)) + { + return; + } + storage.addMuppets(muppets); + } catch (IOException e) + { + throw new IllegalStateException("Could not read default muppets"); + } + } +} diff --git a/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/AdvancedStorageConfiguration.java b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/AdvancedStorageConfiguration.java new file mode 100644 index 00000000..dc346ec4 --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/AdvancedStorageConfiguration.java @@ -0,0 +1,73 @@ +package org.microstream.spring.boot.example.advanced.storage; + +/*- + * #%L + * EclipseStore Example Spring Boot3 Advanced + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; +import org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageFoundationFactory; +import org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageManagerFactory; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AdvancedStorageConfiguration +{ + + private final EmbeddedStorageFoundationFactory foundationFactory; + private final EmbeddedStorageManagerFactory managerFactory; + + public AdvancedStorageConfiguration(EmbeddedStorageFoundationFactory foundationFactory, EmbeddedStorageManagerFactory managerFactory) + { + this.foundationFactory = foundationFactory; + this.managerFactory = managerFactory; + } + + @Bean("jokes") + @ConfigurationProperties("org.eclipse.store.jokes") + EclipseStoreProperties jokesStoreProperties() + { + return new EclipseStoreProperties(); + } + + @Bean("muppets") + @ConfigurationProperties("org.eclipse.store.muppets") + EclipseStoreProperties muppetsStoreProperties() + { + return new EclipseStoreProperties(); + } + + @Bean + @Qualifier("jokes") + EmbeddedStorageManager jokesStore(@Qualifier("jokes") final EclipseStoreProperties jokesStoreProperties) + { + return managerFactory.createStorage( + foundationFactory.createStorageFoundation(jokesStoreProperties), + jokesStoreProperties.isAutoStart() + ); + } + + @Bean + @Qualifier("muppets") + EmbeddedStorageManager muppetsStore(@Qualifier("muppets") final EclipseStoreProperties muppetsStoreProperties) + { + return managerFactory.createStorage( + foundationFactory.createStorageFoundation(muppetsStoreProperties), + muppetsStoreProperties.isAutoStart() + ); + } + +} diff --git a/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/JokesStorage.java b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/JokesStorage.java new file mode 100644 index 00000000..f038fe3a --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/JokesStorage.java @@ -0,0 +1,73 @@ +package org.microstream.spring.boot.example.advanced.storage; + +/*- + * #%L + * spring-boot3-simple + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.List; + +/** + * The {@code JokesStorage} interface provides methods for storing and retrieving jokes. + * It is used as a part of the joke service in the application. + * + *

    Here's an example of how to use this interface:

    + *
    + * 
    + * JokesStorage jokesStorage = ... // get an instance of JokesStorage
    + * jokesStorage.addNewJoke("Why don't scientists trust atoms? Because they make up everything!");
    + * List allJokes = jokesStorage.allJokes();
    + * 
    + * 
    + * + * In this example, a new joke is added to the storage and then all jokes are retrieved. + */ +public interface JokesStorage +{ + /** + * Returns a joke with the specified ID. + * + * @param id The ID of the joke. + * @return The joke with the specified ID. + */ + String oneJoke(Integer id); + + /** + * Returns all jokes in the storage. + * + * @return A list of all jokes. + */ + List allJokes(); + + /** + * Adds a new joke to the storage. + * + * @param joke The joke to add. + * @return The ID of the added joke. + */ + Integer addNewJoke(String joke); + + /** + * Adds multiple jokes to the storage. + * + * @param jokes The jokes to add. + */ + void addJokes(List jokes); + + /** + * Saves all jokes to the storage. + * + * @param jokes The jokes to save. + * @return The number of jokes saved. + */ + Integer saveAllJokes(List jokes); +} diff --git a/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/JokesStorageImpl.java b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/JokesStorageImpl.java new file mode 100644 index 00000000..ef387567 --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/JokesStorageImpl.java @@ -0,0 +1,95 @@ +package org.microstream.spring.boot.example.advanced.storage; + +/*- + * #%L + * spring-boot3-simple + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.persistence.types.Storer; +import org.eclipse.store.integrations.spring.boot.types.concurrent.Read; +import org.eclipse.store.integrations.spring.boot.types.concurrent.Write; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.microstream.spring.boot.example.advanced.model.JokesRoot; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + + +@Component +public class JokesStorageImpl implements JokesStorage +{ + private final EmbeddedStorageManager storageManager; + + public JokesStorageImpl( + @Qualifier("jokes") + EmbeddedStorageManager storageManager + ) + { + this.storageManager = storageManager; + } + + + @Override + @Read + public String oneJoke(Integer id) + { + String joke; + JokesRoot root = (JokesRoot) storageManager.root(); + if (id > root.getJokes().size()) + { + throw new IllegalArgumentException("No jokes with this id"); + } + joke = root.getJokes().get(id); + return joke; + } + + @Override + @Read + public List allJokes() + { + JokesRoot root = (JokesRoot) storageManager.root(); + return new ArrayList<>(root.getJokes()); // Create new List... never return original one. + } + + @Override + @Write + public Integer addNewJoke(String joke) + { + JokesRoot root = (JokesRoot) storageManager.root(); + root.getJokes().add(joke); + storageManager.storeRoot(); + return root.getJokes().size(); + } + + @Override + @Write + public void addJokes(List jokes) + { + JokesRoot root = (JokesRoot) storageManager.root(); + root.getJokes().addAll(jokes); + storageManager.store(root.getJokes()); + } + + @Override + @Write + public Integer saveAllJokes(List jokes) + { + JokesRoot root = (JokesRoot) storageManager.root(); + root.setJokes(jokes); + Storer eagerStorer = storageManager.createEagerStorer(); + eagerStorer.store(root); + eagerStorer.commit(); + return root.getJokes().size(); + } +} diff --git a/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/MuppetStorage.java b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/MuppetStorage.java new file mode 100644 index 00000000..9ac19661 --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/MuppetStorage.java @@ -0,0 +1,26 @@ +package org.microstream.spring.boot.example.advanced.storage; + +/*- + * #%L + * EclipseStore Example Spring Boot3 Advanced + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.List; + +public interface MuppetStorage +{ + String oneMuppet(Integer id); + + List allMuppets(); + + int addMuppets(List muppets); +} diff --git a/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/MuppetsStorageImpl.java b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/MuppetsStorageImpl.java new file mode 100644 index 00000000..b8c37460 --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/java/org/microstream/spring/boot/example/advanced/storage/MuppetsStorageImpl.java @@ -0,0 +1,75 @@ +package org.microstream.spring.boot.example.advanced.storage; + +/*- + * #%L + * EclipseStore Example Spring Boot3 Advanced + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.persistence.types.Storer; +import org.eclipse.store.integrations.spring.boot.types.concurrent.Read; +import org.eclipse.store.integrations.spring.boot.types.concurrent.Write; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.microstream.spring.boot.example.advanced.model.MuppetsRoot; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +@Component +public class MuppetsStorageImpl implements MuppetStorage +{ + + private final EmbeddedStorageManager storageManager; + + public MuppetsStorageImpl( + @Qualifier("muppets") + EmbeddedStorageManager storageManager + ) + { + this.storageManager = storageManager; + } + + @Override + @Read + public String oneMuppet(Integer id) + { + MuppetsRoot root = (MuppetsRoot) storageManager.root(); + if (id > root.getMuppets().size()) + { + throw new IllegalArgumentException("No muppet with this id"); + } + return root.getMuppets().get(id); + } + + @Override + @Read + public List allMuppets() + { + MuppetsRoot root = (MuppetsRoot) storageManager.root(); + return new ArrayList<>(root.getMuppets()); // Create new List... never return original one. + + } + + @Override + @Write + public int addMuppets(List muppets) + { + MuppetsRoot root = (MuppetsRoot) storageManager.root(); + root.setMuppets(muppets); + Storer eagerStorer = storageManager.createEagerStorer(); + eagerStorer.store(root); + eagerStorer.commit(); + return root.getMuppets().size(); + + } +} diff --git a/examples/spring-boot3-advanced/src/main/resources/META-INF/MANIFEST.MF b/examples/spring-boot3-advanced/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 00000000..9d885be5 --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1 @@ +Manifest-Version: 1.0 diff --git a/examples/spring-boot3-advanced/src/main/resources/application.yaml b/examples/spring-boot3-advanced/src/main/resources/application.yaml new file mode 100644 index 00000000..207b3815 --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/resources/application.yaml @@ -0,0 +1,21 @@ +org: + eclipse: + store: + jokes: + auto-start: true + root: org.microstream.spring.boot.example.advanced.model.JokesRoot + storage-directory: ${java.io.tmpdir}/jokes_storage + muppets: + auto-start: true + root: org.microstream.spring.boot.example.advanced.model.MuppetsRoot + storage-directory: ${java.io.tmpdir}/muppets_storage + rest: + enabled: true + +springdoc: + swagger-ui: + try-it-out-enabled: true + url: /v3/api-docs + +vaadin: + url-mapping: /store-console/* diff --git a/examples/spring-boot3-advanced/src/main/resources/jokes.txt b/examples/spring-boot3-advanced/src/main/resources/jokes.txt new file mode 100644 index 00000000..5060ab40 --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/resources/jokes.txt @@ -0,0 +1,250 @@ +What did one pirate say to the other when he beat him at chess?<>Checkmatey. +I burned 2000 calories today<>I left my food in the oven for too long. +I startled my next-door neighbor with my new electric power tool. <>I had to calm him down by saying “Don’t worry, this is just a drill!” +I broke my arm in two places. <>My doctor told me to stop going to those places. +I quit my job at the coffee shop the other day. <>It was just the same old grind over and over. +I never buy anything that has Velcro with it...<>it’s a total rip-off. +I used to work at a soft drink can crushing company...<>it was soda pressing. +I wondered why the frisbee kept on getting bigger. <>Then it hit me. +I was going to tell you a fighting joke...<>but I forgot the punch line. +What is the most groundbreaking invention of all time? <>The shovel. +I’m starting my new job at a restaurant next week. <>I can’t wait. +I visited a weight loss website...<>they told me I have to have cookies disabled. +Did you hear about the famous Italian chef that recently died? <>He pasta way. +Broken guitar for sale<>no strings attached. +I could never be a plumber<>it’s too hard watching your life’s work go down the drain. +I cut my finger slicing cheese the other day...<>but I think I may have grater problems than that. +What time did you go to the dentist yesterday?<>Tooth-hurty. +What kind of music do astronauts listen to?<>Neptunes. +Rest in peace, boiled water. <>You will be mist. +What is the only concert in the world that costs 45 cents? <>50 Cent, featuring Nickelback. +It’s not a dad bod<> it’s a father figure. +My wife recently went on a tropical food diet and now our house is full of this stuff. <>It’s enough to make a mango crazy. +What do you call Santa’s little helpers? <>Subordinate clauses. +Want to hear a construction joke? <>Sorry, I’m still working on it. +What’s the difference between a hippo and a zippo? <>One is extremely big and heavy, and the other is a little lighter. +I burnt my Hawaiian pizza today in the oven, <>I should have cooked it on aloha temperature. +Anyone can be buried when they die<>but if you want to be cremated then you have to urn it. +Where did Captain Hook get his hook? <>From the second-hand store. +I am such a good singer that people always ask me to sing solo<>solo that they can’t hear me. +I am such a good singer that people ask me to sing tenor<>tenor twelve miles away. +Occasionally to relax I just like to tuck my knees into my chest and lean forward.<> That’s just how I roll. +What did the glass of wine say to the glass of beer? Nothing. <>They barley knew each other. +I’ve never trusted stairs. <>They are always up to something. +Why did Shakespeare’s wife leave him? <>She got sick of all the drama. +I just bought a dictionary but all of the pages are blank. <>I have no words to describe how mad I am. +If you want to get a job at the moisturizer factory... <>you’re going to have to apply daily. +I don’t know what’s going to happen next year. <>It’s probably because I don’t have 2020 vision. +Want to hear a joke about going to the bathroom? <>Urine for a treat. +I couldn’t figure out how to use the seat belt. <>Then it just clicked. +I got an email the other day teaching me how to read maps backwards<>turns out it was just spam. +I'm reading a book about anti-gravity.<> It's impossible to put down! +You're American when you go into the bathroom, and you're American when you come out, but do you know what you are while you're in there?<> European. +Did you know the first French fries weren't actually cooked in France?<> They were cooked in Greece. +Want to hear a joke about a piece of paper? Never mind... <>it's tearable. +I just watched a documentary about beavers. <>It was the best dam show I ever saw! +If you see a robbery at an Apple Store what re you?<> An iWitness? +Spring is here! <>I got so excited I wet my plants! +What’s Forrest Gump’s password?<> 1forrest1 +Why did the Clydesdale give the pony a glass of water? <>Because he was a little horse! +CASHIER: "Would you like the milk in a bag, sir?" <>DAD: "No, just leave it in the carton!’” +Did you hear about the guy who invented Lifesavers? <>They say he made a mint. +I bought some shoes from a drug dealer.<> I don't know what he laced them with, but I was tripping all day! +Why do chicken coops only have two doors?<> Because if they had four, they would be chicken sedans! +How do you make a Kleenex dance? <>Put a little boogie in it! +A termite walks into a bar and asks<>"Is the bar tender here?" +Why did the invisible man turn down the job offer?<> He couldn't see himself doing it. +I used to have a job at a calendar factory <>but I got the sack because I took a couple of days off. +A woman is on trial for beating her husband to death with his guitar collection. Judge says, "First offender?" <>She says, "No, first a Gibson! Then a Fender!” +How do you make holy water?<> You boil the hell out of it. +I had a dream that I was a muffler last night.<> I woke up exhausted! +Did you hear about the circus fire?<> It was in tents! +Don't trust atoms.<> They make up everything! +How many tickles does it take to make an octopus laugh? <>Ten-tickles. +I’m only familiar with 25 letters in the English language.<> I don’t know why. +Why did the cow in the pasture get promoted at work?<> Because he is OUT-STANDING in his field! +What do prisoners use to call each other?<> Cell phones. +Why couldn't the bike standup by itself? <>It was two tired. +Who was the fattest knight at King Arthur’s round table?<> Sir Cumference. +Did you see they made round bails of hay illegal in Wisconsin? <>It’s because the cows weren’t getting a square meal. +You know what the loudest pet you can get is?<> A trumpet. +What do you get when you cross a snowman with a vampire?<> Frostbite. +What do you call a deer with no eyes?<> No idea! +Can February March? <>No, but April May! +What do you call a lonely cheese? <>Provolone. +Why can't you hear a pterodactyl go to the bathroom?<> Because the pee is silent. +What did the buffalo say to his son when he dropped him off at school?<> Bison. +What do you call someone with no body and no nose? <>Nobody knows. +You heard of that new band 1023MB? <>They're good but they haven't got a gig yet. +Why did the crab never share?<> Because he's shellfish. +How do you get a squirrel to like you? <>Act like a nut. +Why don't eggs tell jokes? <>They'd crack each other up. +Why can't a nose be 12 inches long? <>Because then it would be a foot. +Did you hear the rumor about butter? <>Well, I'm not going to spread it! +I made a pencil with two erasers. <>It was pointless. +I used to hate facial hair...<>but then it grew on me. +I decided to sell my vacuum cleaner—<>it was just gathering dust! +I had a neck brace fitted years ago<> and I've never looked back since. +You know, people say they pick their nose,<> but I feel like I was just born with mine. +What do you call an elephant that doesn't matter?<> An irrelephant. +What do you get from a pampered cow? <>Spoiled milk. +It's inappropriate to make a 'dad joke' if you're not a dad.<> It's a faux pa. +How do lawyers say goodbye? <>Sue ya later! +Wanna hear a joke about paper? <>Never mind—it's tearable. +What's the best way to watch a fly fishing tournament? <>Live stream. +I could tell a joke about pizza,<> but it's a little cheesy. +When does a joke become a dad joke?<> When it becomes apparent. +What’s an astronaut’s favorite part of a computer? <>The space bar. +What did the shy pebble wish for?<>That she was a little boulder. +I'm tired of following my dreams. <>I'm just going to ask them where they are going and meet up with them later. +Did you hear about the guy whose whole left side was cut off? <>He's all right now. +Why didn’t the skeleton cross the road? <>Because he had no guts. +What did one nut say as he chased another nut? <> I'm a cashew! +Chances are if you' ve seen one shopping center...<> you've seen a mall. +I knew I shouldn't steal a mixer from work...<>but it was a whisk I was willing to take. +How come the stadium got hot after the game? <>Because all of the fans left. +Why was it called the dark ages? <>Because of all the knights. +Why did the tomato blush? <>Because it saw the salad dressing. +Did you hear the joke about the wandering nun? <>She was a roman catholic. +What creature is smarter than a talking parrot? <>A spelling bee. +I'll tell you what often gets over looked...<> garden fences. +Why did the kid cross the playground? <>To get to the other slide. +Why do birds fly south for the winter?<> Because it's too far to walk. +What is a centipedes's favorite Beatle song? <> I want to hold your hand, hand, hand, hand... +My first time using an elevator was an uplifting experience. <>The second time let me down. +To be Frank...<> I'd have to change my name. +Slept like a log last night … <>woke up in the fireplace. +Why does a Moon-rock taste better than an Earth-rock? <>Because it's a little meteor. +How many South Americans does it take to change a lightbulb?<> A Brazilian +I don't trust stairs.<> They're always up to something. +A police officer caught two kids playing with a firework and a car battery.<> He charged one and let the other one off. +What is the difference between ignorance and apathy?<>I don't know and I don't care. +I went to a Foo Fighters Concert once... <>It was Everlong... +Some people eat light bulbs. <>They say it's a nice light snack. +What do you get hanging from Apple trees? <> Sore arms. +Last night me and my girlfriend watched three DVDs back to back.<> Luckily I was the one facing the TV. +I got a reversible jacket for Christmas,<> I can't wait to see how it turns out. +What did Romans use to cut pizza before the rolling cutter was invented? <>Lil Caesars +My pet mouse 'Elvis' died last night. <>He was caught in a trap.. +Never take advice from electrons. <>They are always negative. +Why are oranges the smartest fruit? <>Because they are made to concentrate. +What did the beaver say to the tree? <>It's been nice gnawing you. +How do you fix a damaged jack-o-lantern?<> You use a pumpkin patch. +What did the late tomato say to the early tomato? <>I’ll ketch up +I have kleptomania...<>when it gets bad, I take something for it. +I used to be addicted to soap...<> but I'm clean now. +When is a door not a door?<> When it's ajar. +I made a belt out of watches once...<> It was a waist of time. +This furniture store keeps emailing me,<> all I wanted was one night stand! +How do you find Will Smith in the snow?<> Look for fresh prints. +I just read a book about Stockholm syndrome.<> It was pretty bad at first, but by the end I liked it. +Why do trees seem suspicious on sunny days? <>Dunno, they're just a bit shady. +If at first you don't succeed<> sky diving is not for you! +What kind of music do mummy's like?<>Rap +A book just fell on my head. <>I only have my shelf to blame. +What did the dog say to the two trees? <>Bark bark. +If a child refuses to sleep during nap time...<> are they guilty of resisting a rest? +Have you ever heard of a music group called Cellophane?<> They mostly wrap. +What did the mountain climber name his son?<>Cliff. +Why should you never trust a pig with a secret?<> Because it's bound to squeal. +Why are mummys scared of vacation?<> They're afraid to unwind. +Whiteboards ...<> are remarkable. +What kind of dinosaur loves to sleep?<>A stega-snore-us. +What kind of tree fits in your hand?<> A palm tree! +I used to be addicted to the hokey pokey<> but I turned myself around. +How many tickles does it take to tickle an octopus?<> Ten-tickles! +What musical instrument is found in the bathroom?<> A tuba toothpaste. +My boss told me to attach two pieces of wood together... <>I totally nailed it! +What was the pumpkin’s favorite sport?<>Squash. +What do you call corn that joins the army?<> Kernel. +I've been trying to come up with a dad joke about momentum <>but I just can't seem to get it going. +Why don't sharks eat clowns? <> Because they taste funny. +Just read a few facts about frogs.<> They were ribbiting. +Why didn’t the melons get married?<>Because they cantaloupe. +What’s a computer’s favorite snack?<>Microchips! +Why was the robot so tired after his road trip?<>He had a hard drive. +Why did the computer have no money left?<>Someone cleaned out its cache! +I'm not anti-social. <>I'm just not user friendly. +Why did the computer get cold?<>Because it forgot to close windows. +What is an astronaut's favorite key on a keyboard?<>The space bar! +What's the difference between a computer salesman and a used-car salesman?<>The used-car salesman KNOWS when he's lying. +If at first you don't succeed...<> call it version 1.0 +Why did Microsoft PowerPoint cross the road?<>To get to the other slide! +What did the computer do at lunchtime?<>Had a byte! +Why did the computer keep sneezing?<>It had a virus! +What did one toilet say to the other?<>You look a bit flushed. +Why did the picture go to jail?<>Because it was framed. +What did one wall say to the other wall?<>I'll meet you at the corner. +What do you call a boy named Lee that no one talks to?<>Lonely +Why do bicycles fall over?<>Because they are two-tired! +Why was the broom late?<>It over swept! +What part of the car is the laziest?<>The wheels, because they are always tired! +What's the difference between a TV and a newspaper?<>Ever tried swatting a fly with a TV? +What did one elevator say to the other elevator?<>I think I'm coming down with something! +Why was the belt arrested?<>Because it held up some pants! +What makes the calendar seem so popular?<>Because it has a lot of dates! +Why did Mickey Mouse take a trip into space?He wanted to find Pluto! +Why do you go to bed every night?<>Because the bed won't come to you! +What has four wheels and flies?<>A garbage truck! +Why did the robber take a bath before he stole from the bank?<>He wanted to make a clean get away! +Just watched a documentary about beavers.<>It was the best damn program I’ve ever seen. +Slept like a log last night<>woke up in the fireplace. +Why did the scarecrow win an award?<>Because he was outstanding in his field. +Why does a chicken coop only have two doors? <>Because if it had four doors it would be a chicken sedan. +What’s the difference between an African elephant and an Indian elephant? <>About 5000 miles +Why did the coffee file a police report? <>It got mugged. +What did the grape do when he got stepped on? <>He let out a little wine. +How many apples grow on a tree? <>All of them. +What name do you give a person with a rubber toe? <>Roberto +Did you hear about the kidnapping at school? <>It’s fine, he woke up. +Why do scuba divers fall backwards into the water? <>Because if they fell forwards they’d still be in the boat. +How does a penguin build it’s house? <>Igloos it together. +What do you call a man with a rubber toe?<>Roberto +Did you hear about the restaurant on the moon?<>Great food, no atmosphere. +Why was the belt sent to jail?<>For holding up a pair of pants! +Did you hear about the scientist who was lab partners with a pot of boiling water?<>He had a very esteemed colleague. +What happens when a frogs car dies?<>He needs a jump. If that doesn't work he has to get it toad. +What did the flowers do when the bride walked down the aisle?<>They rose. +Why did the man fall down the well?<>Because he couldn’t see that well. +My boss told me to have a good day...<>...so I went home. +How can you tell it’s a dogwood tree?<>By the bark. +Did you hear about the kidnapping at school?<>It’s fine, he woke up. +Why is Peter Pan always flying?<>Because he Neverlands. +Which state has the most streets?<>Rhode Island. +What do you call 26 letters that went for a swim?<>Alphawetical. +Why was the color green notoriously single?<>It was always so jaded. +Why did the coach go to the bank?<>To get his quarterback. +How do celebrities stay cool?<>They have many fans. +What's the most depressing day of the week?<>sadder day. +Dogs can’t operate MRI machines<>But catscan. +I was going to tell a time-traveling joke<>but you guys didn’t like it. +Stop looking for the perfect match<>instead look for a lighter. +I told my doctor I heard buzzing<>but he said it’s just a bug going around. +What kind of car does a sheep like to drive?<>A lamborghini. +What did the accountant say while auditing a document?<>This is taxing. +What did the two pieces of bread say on their wedding day?<>It was loaf at first sight. +Why do melons have weddings?<>Because they cantaloupe. +What did the drummer call his twin daughters?<>Anna One, Anna Two! +What do you call a toothless bear?<> A gummy bear! +Two goldfish are in a tank. <>One says to the other, “Do you know how to drive this thing?” +What’s Forrest Gump’s password?<>1forrest1 +What is a child guilty of if they refuse to nap?<> Resisting a rest. +I know a lot of jokes about retired people<>but none of them work. +Why are spiders so smart?<>They can find everything on the web. +What has one head, one foot, and four legs?<> A bed. +What does a house wear?<> Address. +What’s red and smells like blue paint?<>Red paint. +My son asked me to put his shoes on<> but I don’t think they’ll fit me. +I’ve been bored recently, so I decided to take up fencing.<> The neighbors keep demanding that I put it back. +What do you call an unpredictable camera?<>A loose Canon. +Which U.S. state is known for its especially small soft drinks?<>Minnesota. +What do sprinters eat before a race?<> Nothing—they fast. +I’m so good at sleeping...<>I can do it with my eyes closed. +People are usually shocked that I have a Police record.<>But I love their greatest hits! +I told my girlfriend she drew on her eyebrows too high.<> She seemed surprised. +What do you call a fibbing cat?<> A lion. +Why shouldn’t you write with a broken pencil?<> Because it’s pointless. +I like telling Dad jokes…<>sometimes he laughs. +How do you weigh a millennial?<> In Instagrams. +The wedding was so beautiful<>even the cake was in tiers. +What’s the most patriotic sport?<> Flag football. diff --git a/examples/spring-boot3-advanced/src/main/resources/logback.xml b/examples/spring-boot3-advanced/src/main/resources/logback.xml new file mode 100644 index 00000000..023a4825 --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/resources/logback.xml @@ -0,0 +1,17 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n + + + + + + + + + + diff --git a/examples/spring-boot3-advanced/src/main/resources/muppets.txt b/examples/spring-boot3-advanced/src/main/resources/muppets.txt new file mode 100644 index 00000000..13cafe5b --- /dev/null +++ b/examples/spring-boot3-advanced/src/main/resources/muppets.txt @@ -0,0 +1,30 @@ +Kermit the Frog +Miss Piggy +Fozzie Bear +Gonzo +Rowlf the Dog +Statler and Waldorf +The Electric Mayhem +Scooter +The Swedish Chef +Bunsen Honeydew +Beaker +Rizzo the Rat +Pepe the King Prawn +Sam the Eagle +Annie Sue +Robin the Frog +Sweetums +Uncle Deadly +Walter +Crazy Harry +Link Hogthrob +Dr. Strangepork +Lew Zealand +Camilla the Chicken +Bean Bunny +Constantine +Clifford +Mahna Mahna +The Newsman +Beauregard diff --git a/examples/spring-boot3-simple/pom.xml b/examples/spring-boot3-simple/pom.xml index 8f698871..1ff20bb5 100644 --- a/examples/spring-boot3-simple/pom.xml +++ b/examples/spring-boot3-simple/pom.xml @@ -11,13 +11,13 @@ EclipseStore Example Spring Boot3 Simple - spring-boot3-simple + examples-spring-boot3-simple 17 17 UTF-8 - 3.2.0 + 3.2.2 @@ -44,12 +44,23 @@ org.springframework.boot spring-boot-starter-aop
    + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.2.0 + org.eclipse.store integrations-spring-boot3 1.3.0-SNAPSHOT + + + org.eclipse.store + integrations-spring-boot3-console + 1.3.0-SNAPSHOT + diff --git a/examples/spring-boot3-simple/readme.md b/examples/spring-boot3-simple/readme.md index b43cecf7..9274697d 100644 --- a/examples/spring-boot3-simple/readme.md +++ b/examples/spring-boot3-simple/readme.md @@ -29,6 +29,18 @@ To launch the test page, open your browser at the following URL http://localhost:8080/ ``` +## Using Swagger UI + +The example application provides a handy UI for sending REST request to provided endpoints. To use the UI, please run the application +and open http://localhost:8080/swagger-ui/index.html in your browser. Then navigate to desired operation, fill required data and send the requests. + +## Using Console + +You may be interested in the state of your data. The example includes the Console for debugging purposes. Please open +http://localhost:8080/store-console/ in your browser, select http://localhost:8080/store-data/default/ from the list, +click connect and inspect the data in your store. + + ## Using App rest api This examples use Curl for Linux/macOS. You can use any other tool for sending HTTP requests. Load sample data. Without this step, the application will not contain any data. It is not mandatory to execute this step, but without it you will have to add all your data manually. diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/JokesApplication.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/JokesApplication.java deleted file mode 100644 index 4b7a6868..00000000 --- a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/JokesApplication.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.microstream.spring.boot.example; - -/*- - * #%L - * spring-boot3-simple - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ - -import org.eclipse.store.integrations.spring.boot.types.EclipseStoreSpringBoot; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Import; - -/** - * The {@code EclipseStoreProperties} class holds the configuration properties for the Eclipse Store. - * These properties are loaded from the application's configuration files and can be used to configure the Eclipse Store. - * - *

    This class is annotated with {@code @Configuration}, {@code @Primary}, and {@code @ConfigurationProperties}, - * which means it is a Spring configuration class, it is the primary bean of its type, - * and its properties are bound to the "org.eclipse.store" prefix in the configuration files.

    - * - *

    Each property in this class corresponds to a configuration option for the Eclipse Store. - * The properties are loaded from the configuration files when the application starts.

    - */ -@SpringBootApplication -@Import(EclipseStoreSpringBoot.class) -public class JokesApplication -{ - public static void main(String... args) - { - SpringApplication.run(JokesApplication.class, args); - } -} diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/SimpleJokesApplication.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/SimpleJokesApplication.java new file mode 100644 index 00000000..bda16474 --- /dev/null +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/SimpleJokesApplication.java @@ -0,0 +1,25 @@ +package org.microstream.spring.boot.example.simple; + +/*- + * #%L + * spring-boot3-simple + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SimpleJokesApplication { + public static void main(String... args) { + SpringApplication.run(SimpleJokesApplication.class, args); + } +} diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/controller/JokesController.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/controller/JokesController.java similarity index 95% rename from examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/controller/JokesController.java rename to examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/controller/JokesController.java index 12000ace..3fa0820d 100644 --- a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/controller/JokesController.java +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/controller/JokesController.java @@ -1,4 +1,4 @@ -package org.microstream.spring.boot.example.controller; +package org.microstream.spring.boot.example.simple.controller; /*- * #%L @@ -14,7 +14,7 @@ * #L% */ -import org.microstream.spring.boot.example.service.JokesServices; +import org.microstream.spring.boot.example.simple.service.JokesServices; import org.springframework.web.bind.annotation.*; import java.util.List; diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/model/Root.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/model/Root.java similarity index 91% rename from examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/model/Root.java rename to examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/model/Root.java index 78f2273b..eb4326a0 100644 --- a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/model/Root.java +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/model/Root.java @@ -1,4 +1,4 @@ -package org.microstream.spring.boot.example.model; +package org.microstream.spring.boot.example.simple.model; /*- * #%L diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServices.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/service/JokesServices.java similarity index 96% rename from examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServices.java rename to examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/service/JokesServices.java index 5324db0e..0e9b4287 100644 --- a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServices.java +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/service/JokesServices.java @@ -1,4 +1,4 @@ -package org.microstream.spring.boot.example.service; +package org.microstream.spring.boot.example.simple.service; /*- * #%L diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServicesImpl.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/service/JokesServicesImpl.java similarity index 93% rename from examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServicesImpl.java rename to examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/service/JokesServicesImpl.java index 26e2809e..4a91a33e 100644 --- a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/service/JokesServicesImpl.java +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/service/JokesServicesImpl.java @@ -1,4 +1,4 @@ -package org.microstream.spring.boot.example.service; +package org.microstream.spring.boot.example.simple.service; /*- * #%L @@ -15,7 +15,7 @@ */ import org.eclipse.store.integrations.spring.boot.types.concurrent.Write; -import org.microstream.spring.boot.example.storage.JokesStorage; +import org.microstream.spring.boot.example.simple.storage.JokesStorage; import org.springframework.stereotype.Service; import java.io.*; diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorage.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/storage/JokesStorage.java similarity index 96% rename from examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorage.java rename to examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/storage/JokesStorage.java index dcc0b792..ef88260a 100644 --- a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorage.java +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/storage/JokesStorage.java @@ -1,4 +1,4 @@ -package org.microstream.spring.boot.example.storage; +package org.microstream.spring.boot.example.simple.storage; /*- * #%L diff --git a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorageImpl.java b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/storage/JokesStorageImpl.java similarity index 92% rename from examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorageImpl.java rename to examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/storage/JokesStorageImpl.java index 49a2ac6b..1b04bdb8 100644 --- a/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/storage/JokesStorageImpl.java +++ b/examples/spring-boot3-simple/src/main/java/org/microstream/spring/boot/example/simple/storage/JokesStorageImpl.java @@ -1,4 +1,4 @@ -package org.microstream.spring.boot.example.storage; +package org.microstream.spring.boot.example.simple.storage; /*- * #%L @@ -15,11 +15,10 @@ */ import org.eclipse.serializer.persistence.types.Storer; -import org.eclipse.store.integrations.spring.boot.types.concurrent.Mutex; import org.eclipse.store.integrations.spring.boot.types.concurrent.Read; import org.eclipse.store.integrations.spring.boot.types.concurrent.Write; import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; -import org.microstream.spring.boot.example.model.Root; +import org.microstream.spring.boot.example.simple.model.Root; import org.springframework.stereotype.Component; import java.util.ArrayList; diff --git a/examples/spring-boot3-simple/src/main/resources/application.properties b/examples/spring-boot3-simple/src/main/resources/application.properties index 7f30485c..028fa597 100644 --- a/examples/spring-boot3-simple/src/main/resources/application.properties +++ b/examples/spring-boot3-simple/src/main/resources/application.properties @@ -1,3 +1,10 @@ org.eclipse.store.auto-start=true -org.eclipse.store.root=org.microstream.spring.boot.example.model.Root +org.eclipse.store.root=org.microstream.spring.boot.example.simple.model.Root org.eclipse.store.storage-directory=jokes_storage +org.eclipse.store.rest.enabled=true + + +springdoc.swagger-ui.try-it-out-enabled=true +springdoc.swagger-ui.url=/v3/api-docs + +vaadin.url-mapping=/store-console/* diff --git a/examples/spring-boot3-simple/src/main/resources/logback.xml b/examples/spring-boot3-simple/src/main/resources/logback.xml index ae37a8f0..023a4825 100644 --- a/examples/spring-boot3-simple/src/main/resources/logback.xml +++ b/examples/spring-boot3-simple/src/main/resources/logback.xml @@ -9,8 +9,9 @@ + - + diff --git a/integrations/itest/.gitignore b/integrations/itest/.gitignore new file mode 100644 index 00000000..34ff768e --- /dev/null +++ b/integrations/itest/.gitignore @@ -0,0 +1 @@ +storage/ diff --git a/integrations/itest/LICENSE b/integrations/itest/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/integrations/itest/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/integrations/itest/pom.xml b/integrations/itest/pom.xml new file mode 100644 index 00000000..51d456eb --- /dev/null +++ b/integrations/itest/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + + + org.eclipse.store + integrations + 1.3.0-SNAPSHOT + ../pom.xml + + + integrations-spring-boot3-itest + EclipseStore Integrations SpringBoot ITest + + + 3.2.2 + + + + + org.springframework.boot + spring-boot-starter-web + ${org.springframework.boot.version} + + + org.eclipse.store + integrations-spring-boot3 + ${project.version} + + + org.eclipse.store + integrations-spring-boot3-console + ${project.version} + + + org.eclipse.store + storage-restservice-springboot + ${project.version} + + + + + org.springframework.boot + spring-boot-starter-test + ${org.springframework.boot.version} + test + + + + org.junit.jupiter + junit-jupiter-engine + 5.10.0 + test + + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + + true + + + + + diff --git a/integrations/itest/src/main/java/test/eclipse/store/integration/spring/boot/ITestApplication.java b/integrations/itest/src/main/java/test/eclipse/store/integration/spring/boot/ITestApplication.java new file mode 100644 index 00000000..fd116c57 --- /dev/null +++ b/integrations/itest/src/main/java/test/eclipse/store/integration/spring/boot/ITestApplication.java @@ -0,0 +1,21 @@ +package test.eclipse.store.integration.spring.boot; + +/*- + * #%L + * integrations-spring-boot3-itest + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ITestApplication { +} diff --git a/integrations/itest/src/main/resources/application.yaml b/integrations/itest/src/main/resources/application.yaml new file mode 100644 index 00000000..ba2ad32c --- /dev/null +++ b/integrations/itest/src/main/resources/application.yaml @@ -0,0 +1,7 @@ +org: + eclipse: + store: + storage-directory: ${java.io.tmpdir}/${random.int} +logging: + level: + root: WARN diff --git a/integrations/itest/src/main/resources/banner.txt b/integrations/itest/src/main/resources/banner.txt new file mode 100644 index 00000000..c6e79af0 --- /dev/null +++ b/integrations/itest/src/main/resources/banner.txt @@ -0,0 +1,3 @@ +------------------------------------------------------------------------------- +EclipseStore SpringBoot System Test, version: ${spring-boot.version} +------------------------------------------------------------------------------- diff --git a/integrations/itest/src/test/java/test/eclipse/store/storage/restservice/spring/boot/types/StoreDataRestDisabledTest.java b/integrations/itest/src/test/java/test/eclipse/store/storage/restservice/spring/boot/types/StoreDataRestDisabledTest.java new file mode 100644 index 00000000..926629a8 --- /dev/null +++ b/integrations/itest/src/test/java/test/eclipse/store/storage/restservice/spring/boot/types/StoreDataRestDisabledTest.java @@ -0,0 +1,55 @@ +package test.eclipse.store.storage.restservice.spring.boot.types; + +/*- + * #%L + * EclipseStore Integrations SpringBoot ITest + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.storage.restadapter.types.StorageRestAdapter; +import org.eclipse.store.storage.restservice.spring.boot.types.rest.StoreDataRestController; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.ApplicationContext; +import test.eclipse.store.integration.spring.boot.ITestApplication; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +/** + * This test makes sure that the rest service is disabled by default. + */ +@SpringBootTest( + classes = ITestApplication.class, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = { + "org.eclipse.store.console.ui.enabled=false", // disable + } +) +@AutoConfigureMockMvc +public class StoreDataRestDisabledTest { + + @MockBean + private StorageRestAdapter adapterMock; + + @Autowired + private ApplicationContext context; + + @Test + public void controller_is_not_available_if_not_enabled_via_property() { + assertThatThrownBy(() -> context.getBean(StoreDataRestController.class)) + .isInstanceOf(NoSuchBeanDefinitionException.class) + .hasMessage("No qualifying bean of type '" + StoreDataRestController.class.getName() + "' available"); + } +} diff --git a/integrations/itest/src/test/resources/application-web-itest.yaml b/integrations/itest/src/test/resources/application-web-itest.yaml new file mode 100644 index 00000000..b854901f --- /dev/null +++ b/integrations/itest/src/test/resources/application-web-itest.yaml @@ -0,0 +1,14 @@ +org: + eclipse: + store: + rest: + enabled: true # enable the REST endpoint + base-url: /itesturl # change the URL + console: + ui: + enabled: false # disable console (and entire vaadin) + +logging: + level: + org.springframework.web: DEBUG + org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping: TRACE diff --git a/integrations/pom.xml b/integrations/pom.xml index 8ac0c3ff..99deb477 100644 --- a/integrations/pom.xml +++ b/integrations/pom.xml @@ -12,6 +12,7 @@ integrations + EclipseStore Integrations Parent pom @@ -22,7 +23,28 @@ spring-boot3 + spring-boot3-console + + itest + + 17 + 17 + 17 + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + 17 + + + + + diff --git a/integrations/spring-boot3-console/LICENSE b/integrations/spring-boot3-console/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/integrations/spring-boot3-console/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/integrations/spring-boot3-console/pom.xml b/integrations/spring-boot3-console/pom.xml new file mode 100644 index 00000000..1efd6478 --- /dev/null +++ b/integrations/spring-boot3-console/pom.xml @@ -0,0 +1,74 @@ + + + 4.0.0 + + + org.eclipse.store + integrations + 1.3.0-SNAPSHOT + ../pom.xml + + + integrations-spring-boot3-console + EclipseStore Integrations SpringBoot Console + + + 3.2.0 + + + + + org.eclipse.store + integrations-spring-boot3 + ${project.version} + + + org.eclipse.store + storage-restservice-springboot + ${project.version} + + + org.eclipse.store + storage-restclient-app + ${project.version} + + + + org.springframework.boot + spring-boot-starter-web + ${org.springframework.boot.version} + provided + + + + org.springframework.boot + spring-boot + ${org.springframework.boot.version} + provided + + + + org.springframework.boot + spring-boot-autoconfigure + ${org.springframework.boot.version} + provided + + + + org.springframework.boot + spring-boot-starter-test + ${org.springframework.boot.version} + test + + + + org.junit.jupiter + junit-jupiter-engine + 5.10.0 + test + + + + diff --git a/integrations/spring-boot3-console/src/main/java/module-info.java b/integrations/spring-boot3-console/src/main/java/module-info.java new file mode 100644 index 00000000..dd305a19 --- /dev/null +++ b/integrations/spring-boot3-console/src/main/java/module-info.java @@ -0,0 +1,24 @@ +/*- + * #%L + * EclipseStore Integrations SpringBoot Console + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module integrations.spring.boot3.console { + requires jakarta.annotation; + requires org.slf4j; + requires spring.beans; + requires spring.boot; + requires spring.boot.autoconfigure; + requires spring.context; + requires vaadin.spring; + requires org.eclipse.store.storage.restclient.app; + requires storage.restservice.springboot; +} diff --git a/integrations/spring-boot3-console/src/main/java/org/eclipse/store/integrations/spring/boot/restconsole/RestConsoleAutoConfiguration.java b/integrations/spring-boot3-console/src/main/java/org/eclipse/store/integrations/spring/boot/restconsole/RestConsoleAutoConfiguration.java new file mode 100644 index 00000000..8469e703 --- /dev/null +++ b/integrations/spring-boot3-console/src/main/java/org/eclipse/store/integrations/spring/boot/restconsole/RestConsoleAutoConfiguration.java @@ -0,0 +1,58 @@ +package org.eclipse.store.integrations.spring.boot.restconsole; + +/*- + * #%L + * EclipseStore Integrations SpringBoot Console + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import com.vaadin.flow.spring.VaadinConfigurationProperties; +import jakarta.annotation.PostConstruct; +import org.eclipse.store.integrations.spring.boot.restconsole.configuration.RestConsoleProperties; +import org.eclipse.store.storage.restservice.spring.boot.types.StoreDataRestAutoConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties(RestConsoleProperties.class) +@AutoConfigureAfter({ + StoreDataRestAutoConfiguration.class +}) +@ComponentScan +public class RestConsoleAutoConfiguration +{ + private final Logger logger = LoggerFactory.getLogger(RestConsoleAutoConfiguration.class); + private final VaadinConfigurationProperties vaadinProperties; + + public RestConsoleAutoConfiguration(@Autowired(required = false) VaadinConfigurationProperties vaadinProperties) + { + this.vaadinProperties = vaadinProperties; + } + + @PostConstruct + public void initialize() + { + final String prefix; + if (vaadinProperties != null) + { + prefix = vaadinProperties.getUrlMapping(); + } else + { + prefix = "/"; + } + logger.info("[ECLIPSE STORE CONSOLE]: Starting console service: '{}'.", prefix); + } +} diff --git a/integrations/spring-boot3-console/src/main/java/org/eclipse/store/integrations/spring/boot/restconsole/RestConsoleUiConfiguration.java b/integrations/spring-boot3-console/src/main/java/org/eclipse/store/integrations/spring/boot/restconsole/RestConsoleUiConfiguration.java new file mode 100644 index 00000000..a639bea3 --- /dev/null +++ b/integrations/spring-boot3-console/src/main/java/org/eclipse/store/integrations/spring/boot/restconsole/RestConsoleUiConfiguration.java @@ -0,0 +1,27 @@ +package org.eclipse.store.integrations.spring.boot.restconsole; + +/*- + * #%L + * EclipseStore Integrations SpringBoot Console + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.storage.restclient.app.types.RestClientAppAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@ConditionalOnProperty(value = "org.eclipse.store.console.ui.enabled", havingValue = "true", matchIfMissing = true) +@Configuration +@Import(RestClientAppAutoConfiguration.class) +public class RestConsoleUiConfiguration +{ +} diff --git a/integrations/spring-boot3-console/src/main/java/org/eclipse/store/integrations/spring/boot/restconsole/configuration/RestConsoleProperties.java b/integrations/spring-boot3-console/src/main/java/org/eclipse/store/integrations/spring/boot/restconsole/configuration/RestConsoleProperties.java new file mode 100644 index 00000000..9dfb40a5 --- /dev/null +++ b/integrations/spring-boot3-console/src/main/java/org/eclipse/store/integrations/spring/boot/restconsole/configuration/RestConsoleProperties.java @@ -0,0 +1,36 @@ +package org.eclipse.store.integrations.spring.boot.restconsole.configuration; + +/*- + * #%L + * EclipseStore Integrations SpringBoot Console + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; + +@ConfigurationProperties(prefix = "org.eclipse.store.console") +public class RestConsoleProperties +{ + + @NestedConfigurationProperty + private UIProperties ui = new UIProperties(); + + public UIProperties getUi() + { + return ui; + } + + public void setUi(UIProperties ui) + { + this.ui = ui; + } +} diff --git a/integrations/spring-boot3-console/src/main/java/org/eclipse/store/integrations/spring/boot/restconsole/configuration/UIProperties.java b/integrations/spring-boot3-console/src/main/java/org/eclipse/store/integrations/spring/boot/restconsole/configuration/UIProperties.java new file mode 100644 index 00000000..5b630044 --- /dev/null +++ b/integrations/spring-boot3-console/src/main/java/org/eclipse/store/integrations/spring/boot/restconsole/configuration/UIProperties.java @@ -0,0 +1,33 @@ +package org.eclipse.store.integrations.spring.boot.restconsole.configuration; + +/*- + * #%L + * EclipseStore Integrations SpringBoot Console + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class UIProperties +{ + /** + * Flag controlling if UI console is enabled, defaults to true + */ + private boolean enabled = true; + + public boolean isEnabled() + { + return enabled; + } + + public void setEnabled(boolean enabled) + { + this.enabled = enabled; + } +} diff --git a/integrations/spring-boot3-console/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/integrations/spring-boot3-console/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..ff573416 --- /dev/null +++ b/integrations/spring-boot3-console/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.eclipse.store.integrations.spring.boot.restconsole.RestConsoleAutoConfiguration diff --git a/integrations/spring-boot3-console/src/test/java/org/eclipse/store/integrations/spring/boot/restconsole/TestClassTest.java b/integrations/spring-boot3-console/src/test/java/org/eclipse/store/integrations/spring/boot/restconsole/TestClassTest.java new file mode 100644 index 00000000..6c7d5155 --- /dev/null +++ b/integrations/spring-boot3-console/src/test/java/org/eclipse/store/integrations/spring/boot/restconsole/TestClassTest.java @@ -0,0 +1,27 @@ +package org.eclipse.store.integrations.spring.boot.restconsole; + +/*- + * #%L + * EclipseStore Integrations SpringBoot Console + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class TestClassTest { + + @Test + public void test_it() { + assertThat(12 / 4).isEqualTo(3); + } +} diff --git a/integrations/spring-boot3/.gitignore b/integrations/spring-boot3/.gitignore new file mode 100644 index 00000000..bc49a5b6 --- /dev/null +++ b/integrations/spring-boot3/.gitignore @@ -0,0 +1,2 @@ +/storage +/microstream_storage diff --git a/integrations/spring-boot3/pom.xml b/integrations/spring-boot3/pom.xml index 2ff0461b..1ba17f20 100644 --- a/integrations/spring-boot3/pom.xml +++ b/integrations/spring-boot3/pom.xml @@ -12,11 +12,10 @@ integrations-spring-boot3 + EclipseStore Integrations SpringBoot - 17 - 17 - 3.2.0 + 3.2.2 @@ -56,6 +55,12 @@ test
    + + org.aspectj + aspectjweaver + 1.9.7 + + org.eclipse.store storage-embedded @@ -117,13 +122,6 @@ - - org.apache.maven.plugins - maven-javadoc-plugin - - 17 - - diff --git a/integrations/spring-boot3/src/main/java/module-info.java b/integrations/spring-boot3/src/main/java/module-info.java index 4e10c54a..3e719faf 100644 --- a/integrations/spring-boot3/src/main/java/module-info.java +++ b/integrations/spring-boot3/src/main/java/module-info.java @@ -7,34 +7,33 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ open module org.eclipse.store.integrations.spring.boot { - exports org.eclipse.store.integrations.spring.boot.types.configuration; - exports org.eclipse.store.integrations.spring.boot.types.configuration.aws; - exports org.eclipse.store.integrations.spring.boot.types.configuration.azure; - exports org.eclipse.store.integrations.spring.boot.types.configuration.googlecloud; - exports org.eclipse.store.integrations.spring.boot.types.configuration.googlecloud.firestore; - exports org.eclipse.store.integrations.spring.boot.types.configuration.oraclecloud; - exports org.eclipse.store.integrations.spring.boot.types.configuration.redis; - exports org.eclipse.store.integrations.spring.boot.types.configuration.sql; - exports org.eclipse.store.integrations.spring.boot.types; + exports org.eclipse.store.integrations.spring.boot.types.configuration; + exports org.eclipse.store.integrations.spring.boot.types.configuration.aws; + exports org.eclipse.store.integrations.spring.boot.types.configuration.azure; + exports org.eclipse.store.integrations.spring.boot.types.configuration.googlecloud; + exports org.eclipse.store.integrations.spring.boot.types.configuration.googlecloud.firestore; + exports org.eclipse.store.integrations.spring.boot.types.configuration.oraclecloud; + exports org.eclipse.store.integrations.spring.boot.types.configuration.redis; + exports org.eclipse.store.integrations.spring.boot.types.configuration.sql; + exports org.eclipse.store.integrations.spring.boot.types; exports org.eclipse.store.integrations.spring.boot.types.converter; - exports org.eclipse.store.integrations.spring.boot.types.concurrent; - - requires transitive spring.beans; - requires transitive spring.boot; - requires transitive spring.boot.autoconfigure; - requires transitive spring.context; - requires transitive spring.core; - requires transitive org.eclipse.store.storage.embedded.configuration; - requires transitive org.eclipse.serializer.configuration; - requires transitive org.aspectj.weaver; - requires transitive org.eclipse.serializer.persistence.binary.jdk17; - requires transitive org.eclipse.serializer.persistence.binary.jdk8; - + exports org.eclipse.store.integrations.spring.boot.types.factories; + exports org.eclipse.store.integrations.spring.boot.types.concurrent; + requires transitive spring.beans; + requires transitive spring.boot; + requires transitive spring.boot.autoconfigure; + requires transitive spring.context; + requires transitive spring.core; + requires transitive org.eclipse.store.storage.embedded.configuration; + requires transitive org.eclipse.serializer.configuration; + requires transitive org.eclipse.serializer.persistence.binary.jdk17; + requires transitive org.eclipse.serializer.persistence.binary.jdk8; + requires org.aspectj.weaver; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java new file mode 100644 index 00000000..b94ccc21 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java @@ -0,0 +1,92 @@ +package org.eclipse.store.integrations.spring.boot.types; + +/*- + * #%L + * EclipseStore Integrations SpringBoot + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; +import org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageFoundationFactory; +import org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageManagerFactory; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.function.Supplier; + +@Configuration +@AutoConfigureAfter(EclipseStoreSpringBoot.class) +public class DefaultEclipseStoreConfiguration +{ + + public static final String DEFAULT_QUALIFIER = "defaultEclipseStore"; + + /** + *

    This means is annotated with {@code @ConfigurationProperties}, + * which means its properties are bound to the "org.eclipse.store" prefix in the configuration files.

    + */ + @Bean + @Qualifier(DEFAULT_QUALIFIER) + @ConfigurationProperties(prefix = "org.eclipse.store") + public EclipseStoreProperties defaultEclipseStoreProperties() + { + return new EclipseStoreProperties(); + } + + /** + * Creates a supplier for embedded storage foundation. + * + * @param eclipseStoreProperties properties. + * @param foundationFactory embedded foundation factory. + * @return embedded foundation factory supplier with provided properties. + */ + @Bean + @Qualifier(DEFAULT_QUALIFIER) + @ConditionalOnMissingBean + public Supplier> defaultStorageFoundationSupplier( + @Qualifier(DEFAULT_QUALIFIER) EclipseStoreProperties eclipseStoreProperties, + EmbeddedStorageFoundationFactory foundationFactory + ) + { + return () -> foundationFactory.createStorageFoundation(eclipseStoreProperties); + } + + /** + * Creates embedded storage manager based on a single configuration. + * + * @param embeddedStorageManagerFactory embedded storage manager factory. + * @param eclipseStoreProperties properties used for construction. + * @param embeddedStorageFoundationSupplier embedded storage foundation factory supplier. + * @return storage manager. + */ + @Bean + @Qualifier(DEFAULT_QUALIFIER) + @ConditionalOnMissingBean + public EmbeddedStorageManager defaultStorageManager( + EmbeddedStorageManagerFactory embeddedStorageManagerFactory, + @Qualifier(DEFAULT_QUALIFIER) EclipseStoreProperties eclipseStoreProperties, + @Qualifier(DEFAULT_QUALIFIER) + Supplier> embeddedStorageFoundationSupplier + ) + { + return embeddedStorageManagerFactory.createStorage( + embeddedStorageFoundationSupplier.get(), + eclipseStoreProperties.isAutoStart() + ); + } + +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreBeanFactory.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreBeanFactory.java deleted file mode 100644 index 01f70e70..00000000 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreBeanFactory.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.eclipse.store.integrations.spring.boot.types; - -/*- - * #%L - * spring-boot3 - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ - -import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; -import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Lazy; -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Component; - -/** - * The {@code EclipseStoreBeanFactory} class is a Spring component that provides a factory for creating {@code EmbeddedStorageManager} beans. - * It uses the {@code EclipseStoreProvider} and {@code EclipseStoreProperties} to create the {@code EmbeddedStorageManager}. - */ -@Component -@Lazy -public class EclipseStoreBeanFactory -{ - private final EclipseStoreProvider eclipseStoreProvider; - private final EclipseStoreProperties eclipseStoreProperties; - - /** - * Constructs a new {@code EclipseStoreBeanFactory} with the provided {@code EclipseStoreProvider} and {@code EclipseStoreProperties}. - * - * @param eclipseStoreProvider The provider used to create {@code EmbeddedStorageManager} instances. - * @param eclipseStoreProperties The properties used to configure the {@code EmbeddedStorageManager}. - */ - public EclipseStoreBeanFactory(final EclipseStoreProvider eclipseStoreProvider, final EclipseStoreProperties eclipseStoreProperties) - { - this.eclipseStoreProvider = eclipseStoreProvider; - this.eclipseStoreProperties = eclipseStoreProperties; - } - - - /** - * Creates a new {@code EmbeddedStorageManager} bean using the {@code EclipseStoreProvider} and {@code EclipseStoreProperties}. - * This bean is marked as primary and lazy, meaning it will be the default choice for autowiring and will only be initialized on demand. - * - * @return A new {@code EmbeddedStorageManager} instance. - */ - @Bean - @Primary - @Lazy - public EmbeddedStorageManager embeddedStorageManager() - { - return this.eclipseStoreProvider.createStorage(this.eclipseStoreProperties); - } - - -} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProvider.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProvider.java index 47eed6fb..00482e84 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProvider.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProvider.java @@ -22,35 +22,45 @@ /** * The {@code EclipseStoreProvider} interface is responsible for the creation of the EmbeddedStorageManager and EmbeddedStorageFoundation instances. * It provides methods for creating the EmbeddedStorageManager and EmbeddedStorageFoundation instances based on the provided configuration. + * + * @deprecated this class is deprecated in favour of {@link org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageFoundationFactory} + * and {@link org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageManagerFactory} and will be removed in future releases. */ +@Deprecated(since = "1.2.0", forRemoval = true) public interface EclipseStoreProvider { /** * Creates an {@code EmbeddedStorageManager} using the provided configuration. * - * @param eclipseStoreProperties Configuration file structure representing configuration elements mapped by Spring Configuration. + * @param eclipseStoreProperties Configuration file structure representing configuration elements mapped by Spring Configuration. * @param additionalConfiguration Optional additional parameters that allow the inclusion of configuration keys not present in {@code EclipseStoreProperties}. * @return A new {@code EmbeddedStorageManager} instance based on the provided configuration. + * @deprecated please use {@link org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageManagerFactory} */ + @Deprecated(since = "1.2.0", forRemoval = true) EmbeddedStorageManager createStorage(EclipseStoreProperties eclipseStoreProperties, ConfigurationPair... additionalConfiguration); /** * Creates an {@code EmbeddedStorageManager} using a pre-configured foundation. This method is beneficial when additional configuration for the foundation is required. * * @param foundation The {@code EmbeddedStorageFoundation} to be configured before calling this method. - * @param autoStart Determines whether the newly created {@code EmbeddedStorageManager} should start directly after creation. + * @param autoStart Determines whether the newly created {@code EmbeddedStorageManager} should start directly after creation. * @return A new {@code EmbeddedStorageManager} instance based on the provided {@code EmbeddedStorageFoundation}. + * @deprecated please use {@link org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageManagerFactory} */ + @Deprecated(since = "1.2.0", forRemoval = true) EmbeddedStorageManager createStorage(EmbeddedStorageFoundation foundation, boolean autoStart); /** * Creates an {@code EmbeddedStorageFoundation} using the provided configuration. This method should be called when the additional configuration for the foundation is required. * - * @param eclipseStoreProperties Configuration file structure representing configuration elements mapped by Spring Configuration. + * @param eclipseStoreProperties Configuration file structure representing configuration elements mapped by Spring Configuration. * @param additionalConfiguration Optional additional parameters that allow the inclusion of configuration keys not present in {@code EclipseStoreProperties}. * @return A new {@code EmbeddedStorageFoundation} instance based on the provided configuration. + * @deprecated please use {@link org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageFoundationFactory} */ + @Deprecated(since = "1.2.0", forRemoval = true) EmbeddedStorageFoundation createStorageFoundation(EclipseStoreProperties eclipseStoreProperties, ConfigurationPair... additionalConfiguration); diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreSpringBoot.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreSpringBoot.java index 67471f8b..7a922834 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreSpringBoot.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreSpringBoot.java @@ -9,39 +9,79 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ -import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.ComponentScan; +import org.eclipse.serializer.reflect.ClassLoaderProvider; +import org.eclipse.store.integrations.spring.boot.types.converter.EclipseStoreConfigConverter; +import org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageFoundationFactory; +import org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageManagerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; /** * The {@code EclipseStoreSpringBoot} class is responsible for the auto-configuration of the Spring Boot application. * It sets up the configuration properties for the Eclipse Store and initiates a scan of the base packages for any necessary Spring components. - * - *

    Here's an example of how to use this class in a Spring Boot application:

    - *
    - * 
    - *
    - * {@literal @}SpringBootApplication
    - * {@literal @}Import(EclipseStoreSpringBoot.class)
    - *  public class SomeSpringApplication {
    - *     public static void main(String... args) {
    - *         SpringApplication.run(SomeSpringApplication.class, args);
    - *     }
    - *  }
    - * 
    - * 
    */ -@AutoConfiguration -@ComponentScan(basePackages = "org.eclipse.store.integrations.spring.boot.types") -@EnableConfigurationProperties(EclipseStoreProperties.class) +@Configuration public class EclipseStoreSpringBoot { + /** + * Properties converter. + * + * @return properties converter. + */ + @Bean + @ConditionalOnMissingBean + public EclipseStoreConfigConverter eclipseStoreConfigConverter() + { + return new EclipseStoreConfigConverter(); + } + + /** + * Class loader provider based on Spring class loader. + * + * @param applicationContext application context. + * @return class loader provider. + */ + @Bean + @Lazy + public ClassLoaderProvider classLoaderProvider(ApplicationContext applicationContext) + { + return (typeName) -> applicationContext.getClassLoader(); + } + + /** + * Creates embedded storage foundation factory. + * + * @param eclipseStoreConfigConverter converter to map Spring properties to EclipseStore foundation configuration. + * @param classLoaderProvider classloader to use in foundation. + * @return factory. + */ + @Bean + public EmbeddedStorageFoundationFactory embeddedStorageFoundationFactory( + EclipseStoreConfigConverter eclipseStoreConfigConverter, + ClassLoaderProvider classLoaderProvider + ) + { + return new EmbeddedStorageFoundationFactory(eclipseStoreConfigConverter, classLoaderProvider); + } + + /** + * Creates a new embedded storage manager factory. + * + * @return factory. + */ + @Bean + public EmbeddedStorageManagerFactory embeddedStorageManagerFactory() + { + return new EmbeddedStorageManagerFactory(); + } } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/LockAspect.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/LockAspect.java index 92429e7e..a4b15b29 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/LockAspect.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/LockAspect.java @@ -148,7 +148,8 @@ private ReentrantReadWriteLock findLock(final ProceedingJoinPoint joinPoint) * @param lockName The name of the lock. * @return The named lock. */ - private ReentrantReadWriteLock getOrCreateLock(final String lockName) { + private ReentrantReadWriteLock getOrCreateLock(final String lockName) + { return this.locks.computeIfAbsent(lockName, k -> { this.logger.trace("Lock for name: {} not found, creating a new one", lockName); return new ReentrantReadWriteLock(); @@ -162,7 +163,8 @@ private ReentrantReadWriteLock getOrCreateLock(final String lockName) { static class AspectJCondition implements Condition { @Override - public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) { + public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) + { return ClassUtils.isPresent("org.aspectj.lang.ProceedingJoinPoint", context.getClassLoader()); } } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Mutex.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Mutex.java index d6618616..cb47980d 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Mutex.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Mutex.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ @@ -36,7 +36,7 @@ * } * * - * + *

    * In this example, the {@code MyClass} type and the {@code myMethod} method each have their own named lock. */ @Target({ElementType.TYPE, ElementType.METHOD}) diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Read.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Read.java index e132bacf..60b45918 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Read.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Read.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Write.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Write.java index fc655cae..33417b05 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Write.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/concurrent/Write.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ @@ -35,7 +35,7 @@ * } * * - * + *

    * In this example, the {@code myMethod} method will acquire a write lock before execution. */ @Target(ElementType.METHOD) diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/ConfigurationPair.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/ConfigurationPair.java index 85cc824b..12c89566 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/ConfigurationPair.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/ConfigurationPair.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ @@ -24,7 +24,7 @@ * ConfigurationPair pair = new ConfigurationPair("key", "value"); * * - * + *

    * In this example, a new {@code ConfigurationPair} is created with the key "key" and the value "value". */ public record ConfigurationPair(String key, String value) diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java index 86c29428..69f097d6 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java @@ -1,23 +1,28 @@ package org.eclipse.store.integrations.spring.boot.types.configuration; -import org.springframework.boot.context.properties.ConfigurationProperties; +/*- + * #%L + * EclipseStore Integrations SpringBoot + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + import org.springframework.boot.context.properties.NestedConfigurationProperty; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; /** * The {@code EclipseStoreProperties} class holds the configuration properties for the Eclipse Store. * These properties are loaded from the application's configuration files and can be used to configure the Eclipse Store. * - *

    This class is annotated with {@code @Configuration}, {@code @Primary}, and {@code @ConfigurationProperties}, - * which means it is a Spring configuration class, it is the primary bean of its type, and its properties are bound to the "org.eclipse.store" prefix in the configuration files.

    - * *

    Each property in this class corresponds to a configuration option for the Eclipse Store. * The properties are loaded from the configuration files when the application starts.

    */ -@Configuration -@Primary -@ConfigurationProperties(prefix = "org.eclipse.store") public class EclipseStoreProperties { diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/StorageFilesystem.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/StorageFilesystem.java index 30936066..84fe67c4 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/StorageFilesystem.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/StorageFilesystem.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ @@ -39,7 +39,7 @@ public class StorageFilesystem /** * Supported properties - * All supported properties of Kafka, see https://kafka.apache.org/documentation/ + * All supported properties of Kafka, see ... */ private Map kafkaProperties; diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/AbstractAwsProperties.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/AbstractAwsProperties.java index 168461dd..cd978116 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/AbstractAwsProperties.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/AbstractAwsProperties.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Aws.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Aws.java index f8b63094..7f4c4fb2 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Aws.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Aws.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Credentials.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Credentials.java index 5f137d25..853db2e8 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Credentials.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Credentials.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ @@ -18,7 +18,7 @@ public class Credentials { /** - * The type of the credentials provider. Supported values are: + * The type of the credentials' provider. Supported values are: *
      * *
    • "environment-variables" Credentials will be loaded from the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN environment variables.
    • diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Dynamodb.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Dynamodb.java index 40f8c44a..10a0fdec 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Dynamodb.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/Dynamodb.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/S3.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/S3.java index 3cd25e07..2ce17819 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/S3.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/S3.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Azure.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Azure.java index 2275a339..9f9c7021 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Azure.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Azure.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Credentials.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Credentials.java index 7a0f361b..a98cf7ed 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Credentials.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Credentials.java @@ -9,16 +9,16 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ public class Credentials { - + /** - * The type of the credentials provider. Supported values are: + * The type of the credentials' provider. Supported values are: *
        *
      • "basic"
      • * Credentials will be loaded from the credentials.username and credentials.password properties. diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Storage.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Storage.java index 248f4038..63154c9c 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Storage.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/azure/Storage.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/Googlecloud.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/Googlecloud.java index 11b6fda2..3d8c7301 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/Googlecloud.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/Googlecloud.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Credentials.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Credentials.java index 543a783b..e45e39cc 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Credentials.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Credentials.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ @@ -17,7 +17,7 @@ public class Credentials { /** - * The type of the credentials provider. Supported values are: + * The type of the credentials' provider. Supported values are: * *
          *
        • "none": No credentials are used.
        • diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Firestore.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Firestore.java index b086cb0b..97b38327 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Firestore.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/googlecloud/firestore/Firestore.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ @@ -19,12 +19,11 @@ public class Firestore { /** - * he database ID to use with this Firestore client. + * the database ID to use with this Firestore client. */ private String databaseId; /** - * * The emulator host to use with this Firestore client. */ private String emulatorHost; @@ -35,7 +34,6 @@ public class Firestore private String host; /** - * * The project ID. If no project ID is set, the project ID from the environment will be used. */ private String projectId; @@ -48,64 +46,64 @@ public class Firestore @NestedConfigurationProperty private Credentials credentials; - public String getDatabaseId() - { - return this.databaseId; - } - - public void setDatabaseId(final String databaseId) - { - this.databaseId = databaseId; - } - - public String getEmulatorHost() - { - return this.emulatorHost; - } - - public void setEmulatorHost(final String emulatorHost) - { - this.emulatorHost = emulatorHost; - } - - public String getHost() - { - return this.host; - } - - public void setHost(final String host) - { - this.host = host; - } - - public String getProjectId() - { - return this.projectId; - } - - public void setProjectId(final String projectId) - { - this.projectId = projectId; - } - - public String getQuotaProjectId() - { - return this.quotaProjectId; - } - - public void setQuotaProjectId(final String quotaProjectId) - { - this.quotaProjectId = quotaProjectId; - } - - public Credentials getCredentials() - { - return this.credentials; - } - - public void setCredentials(final Credentials credentials) - { - this.credentials = credentials; - } - + public String getDatabaseId() + { + return this.databaseId; + } + + public void setDatabaseId(final String databaseId) + { + this.databaseId = databaseId; + } + + public String getEmulatorHost() + { + return this.emulatorHost; + } + + public void setEmulatorHost(final String emulatorHost) + { + this.emulatorHost = emulatorHost; + } + + public String getHost() + { + return this.host; + } + + public void setHost(final String host) + { + this.host = host; + } + + public String getProjectId() + { + return this.projectId; + } + + public void setProjectId(final String projectId) + { + this.projectId = projectId; + } + + public String getQuotaProjectId() + { + return this.quotaProjectId; + } + + public void setQuotaProjectId(final String quotaProjectId) + { + this.quotaProjectId = quotaProjectId; + } + + public Credentials getCredentials() + { + return this.credentials; + } + + public void setCredentials(final Credentials credentials) + { + this.credentials = credentials; + } + } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Client.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Client.java index 2bdb1f57..b29a5867 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Client.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Client.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ConfigFile.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ConfigFile.java index dfec8db5..bbee81ff 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ConfigFile.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ConfigFile.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ObjectStorage.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ObjectStorage.java index eec065e3..e76bbda8 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ObjectStorage.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/ObjectStorage.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Oraclecloud.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Oraclecloud.java index 39e808ef..8f4433c9 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Oraclecloud.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/oraclecloud/Oraclecloud.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/redis/Redis.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/redis/Redis.java index 3163e318..88bd1122 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/redis/Redis.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/redis/Redis.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/AbstractSqlConfiguration.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/AbstractSqlConfiguration.java index 206683cc..e4b9e08a 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/AbstractSqlConfiguration.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/AbstractSqlConfiguration.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Mariadb.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Mariadb.java index 0671ddd4..8c2d3f83 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Mariadb.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Mariadb.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Oracle.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Oracle.java index 9934a509..60b35a56 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Oracle.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Oracle.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Postgres.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Postgres.java index 85dd79f7..de427b0e 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Postgres.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Postgres.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sql.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sql.java index c2ba5521..bcde1c91 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sql.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sql.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sqlite.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sqlite.java index 7e3676b7..198deea0 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sqlite.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/sql/Sqlite.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java index 3c81dc79..66ad6a26 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ @@ -78,8 +78,7 @@ public enum ConfigKeys SQL_SCHEMA("schema"), SQL_URL("url"), SQL_USER("user"), - SQL_PASSWORD("password") - ; + SQL_PASSWORD("password"); private final String value; diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java index e29243d6..42332d65 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java @@ -38,7 +38,7 @@ public class EclipseStoreConfigConverter { // Fields for testing if all keys from Eclipse Store Configuration are covered by these module. - // These fields are protected so they can be accessed in tests. + // These fields are protected, so they can be accessed in tests. // Each field represents a key in the Eclipse Store Configuration. // Fields for the storage directory configuration diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProviderImpl.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/factories/EmbeddedStorageFoundationFactory.java similarity index 59% rename from integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProviderImpl.java rename to integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/factories/EmbeddedStorageFoundationFactory.java index a91d1849..08ff159e 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/EclipseStoreProviderImpl.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/factories/EmbeddedStorageFoundationFactory.java @@ -1,4 +1,4 @@ -package org.eclipse.store.integrations.spring.boot.types; +package org.eclipse.store.integrations.spring.boot.types.factories; /*- * #%L @@ -14,60 +14,52 @@ * #L% */ -import java.util.Map; - import org.eclipse.serializer.persistence.binary.jdk17.types.BinaryHandlersJDK17; import org.eclipse.serializer.persistence.binary.jdk8.types.BinaryHandlersJDK8; +import org.eclipse.serializer.reflect.ClassLoaderProvider; import org.eclipse.serializer.util.logging.Logging; import org.eclipse.store.integrations.spring.boot.types.configuration.ConfigurationPair; import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; import org.eclipse.store.integrations.spring.boot.types.converter.EclipseStoreConfigConverter; import org.eclipse.store.storage.embedded.configuration.types.EmbeddedStorageConfigurationBuilder; import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; -import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; import org.slf4j.Logger; -import org.springframework.context.ApplicationContext; -import org.springframework.stereotype.Component; -@Component -public class EclipseStoreProviderImpl implements EclipseStoreProvider +import java.util.Map; + + +/** + * The {@code EmbeddedStorageFoundationFactory} is responsible for the creation of the EmbeddedStorageFoundation instances. + * It provides methods for creating EmbeddedStorageFoundation instances based on the provided configuration. + * + * @since 1.2.0 + */ +public class EmbeddedStorageFoundationFactory { private final EclipseStoreConfigConverter converter; - private final ApplicationContext applicationContext; + private final ClassLoaderProvider classLoaderProvider; - private final Logger logger = Logging.getLogger(EclipseStoreProviderImpl.class); + private final Logger logger = Logging.getLogger(EmbeddedStorageFoundationFactory.class); - public EclipseStoreProviderImpl(final EclipseStoreConfigConverter converter, final ApplicationContext applicationContext) + public EmbeddedStorageFoundationFactory(final EclipseStoreConfigConverter converter, final ClassLoaderProvider classLoaderProvider) { this.converter = converter; - this.applicationContext = applicationContext; + this.classLoaderProvider = classLoaderProvider; } - @Override - public EmbeddedStorageManager createStorage(final EclipseStoreProperties eclipseStoreProperties, final ConfigurationPair... additionalConfiguration) - { - final EmbeddedStorageFoundation storageFoundation = this.createStorageFoundation(eclipseStoreProperties, additionalConfiguration); - return this.createStorage(storageFoundation, eclipseStoreProperties.isAutoStart()); - } - - @Override - public EmbeddedStorageManager createStorage(final EmbeddedStorageFoundation foundation, final boolean autoStart) - { - final EmbeddedStorageManager storageManager = foundation.createEmbeddedStorageManager(); - if (autoStart) - { - storageManager.start(); - } - return storageManager; - } - - @Override + /** + * Creates an {@code EmbeddedStorageFoundation} using the provided configuration. This method should be called when the additional configuration for the foundation is required. + * + * @param eclipseStoreProperties Configuration file structure representing configuration elements mapped by Spring Configuration. + * @param additionalConfiguration Optional additional parameters that allow the inclusion of configuration keys not present in {@code EclipseStoreProperties}. + * @return A new {@code EmbeddedStorageFoundation} instance based on the provided configuration. + */ public EmbeddedStorageFoundation createStorageFoundation(final EclipseStoreProperties eclipseStoreProperties, final ConfigurationPair... additionalConfiguration) { - final EmbeddedStorageConfigurationBuilder builder = EmbeddedStorageConfigurationBuilder.New(); final Map valueMap = this.converter.convertConfigurationToMap(eclipseStoreProperties); - for (final ConfigurationPair pair : additionalConfiguration) { + for (final ConfigurationPair pair : additionalConfiguration) + { valueMap.put(pair.key(), pair.value()); } @@ -84,22 +76,23 @@ public EmbeddedStorageFoundation createStorageFoundation(final EclipseStorePr final EmbeddedStorageFoundation storageFoundation = builder.createEmbeddedStorageFoundation(); - final Object root = this.provideRoot(eclipseStoreProperties); + storageFoundation.getConnectionFoundation().setClassLoaderProvider(classLoaderProvider); + + final Object root = this.createNewRootInstance(eclipseStoreProperties); if (root != null) { this.logger.debug("Root object: " + root.getClass().getName()); storageFoundation.setRoot(root); } - storageFoundation.getConnectionFoundation() - .setClassLoaderProvider(typeName -> this.applicationContext.getClassLoader()); - - if (eclipseStoreProperties.isRegisterJdk8Handlers()) { + if (eclipseStoreProperties.isRegisterJdk8Handlers()) + { this.logger.debug("Register JDK8 handlers. "); storageFoundation.onConnectionFoundation(BinaryHandlersJDK8::registerJDK8TypeHandlers); } - if (eclipseStoreProperties.isRegisterJdk17Handlers()) { + if (eclipseStoreProperties.isRegisterJdk17Handlers()) + { this.logger.debug("Register JDK17 handlers. "); storageFoundation.onConnectionFoundation(BinaryHandlersJDK17::registerJDK17TypeHandlers); } @@ -107,9 +100,9 @@ public EmbeddedStorageFoundation createStorageFoundation(final EclipseStorePr return storageFoundation; } - private Object provideRoot(final EclipseStoreProperties properties) + protected Object createNewRootInstance(final EclipseStoreProperties properties) { - final Class rootClass = properties.getRoot(); + var rootClass = properties.getRoot(); if (rootClass == null) { return null; @@ -119,7 +112,7 @@ private Object provideRoot(final EclipseStoreProperties properties) return rootClass.getDeclaredConstructor().newInstance(); } catch (final Exception e) { - throw new RuntimeException("Failed to instantiate class: " + rootClass, e); + throw new RuntimeException("Failed to instantiate storage root: " + rootClass, e); } } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/factories/EmbeddedStorageManagerFactory.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/factories/EmbeddedStorageManagerFactory.java new file mode 100644 index 00000000..2d1fa2ae --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/factories/EmbeddedStorageManagerFactory.java @@ -0,0 +1,46 @@ +package org.eclipse.store.integrations.spring.boot.types.factories; + +/*- + * #%L + * EclipseStore Integrations SpringBoot + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + +/** + * The {@code EmbeddedStorageManagerFactory} is responsible for the creation of the EmbeddedStorageManager instances. + * It provides methods for creating the EmbeddedStorageManager instances based on the provided foundation. + * + * @since 1.2.0 + */ +public class EmbeddedStorageManagerFactory +{ + + /** + * Creates an {@code EmbeddedStorageManager} using a pre-configured foundation. This method is beneficial when additional configuration for the foundation is required. + * + * @param foundation The {@code EmbeddedStorageFoundation} to be configured before calling this method. + * @param autoStart Determines whether the newly created {@code EmbeddedStorageManager} should start directly after creation. + * @return A new {@code EmbeddedStorageManager} instance based on the provided {@code EmbeddedStorageFoundation}. + */ + public EmbeddedStorageManager createStorage(final EmbeddedStorageFoundation foundation, final boolean autoStart) + { + final EmbeddedStorageManager storageManager = foundation.createEmbeddedStorageManager(); + if (autoStart) + { + storageManager.start(); + } + return storageManager; + } + +} diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/factories/legacy/EclipseStoreProviderImpl.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/factories/legacy/EclipseStoreProviderImpl.java new file mode 100644 index 00000000..5374e99d --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/factories/legacy/EclipseStoreProviderImpl.java @@ -0,0 +1,61 @@ +package org.eclipse.store.integrations.spring.boot.types.factories.legacy; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.serializer.reflect.ClassLoaderProvider; +import org.eclipse.store.integrations.spring.boot.types.EclipseStoreProvider; +import org.eclipse.store.integrations.spring.boot.types.configuration.ConfigurationPair; +import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; +import org.eclipse.store.integrations.spring.boot.types.converter.EclipseStoreConfigConverter; +import org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageFoundationFactory; +import org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageManagerFactory; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + + +@SuppressWarnings("removal") +@Deprecated +public class EclipseStoreProviderImpl implements EclipseStoreProvider +{ + + private final EmbeddedStorageFoundationFactory embeddedStorageFoundationFactory; + private final EmbeddedStorageManagerFactory embeddedStorageManagerFactory; + + public EclipseStoreProviderImpl(final EclipseStoreConfigConverter converter, final ClassLoaderProvider classLoaderProvider) + { + this.embeddedStorageFoundationFactory = new EmbeddedStorageFoundationFactory(converter, classLoaderProvider); + this.embeddedStorageManagerFactory = new EmbeddedStorageManagerFactory(); + } + + @Override + public EmbeddedStorageManager createStorage(final EclipseStoreProperties eclipseStoreProperties, final ConfigurationPair... additionalConfiguration) + { + final EmbeddedStorageFoundation storageFoundation = this.createStorageFoundation(eclipseStoreProperties, additionalConfiguration); + return this.createStorage(storageFoundation, eclipseStoreProperties.isAutoStart()); + } + + @Override + public EmbeddedStorageManager createStorage(final EmbeddedStorageFoundation foundation, final boolean autoStart) + { + return embeddedStorageManagerFactory.createStorage(foundation, autoStart); + } + + @Override + public EmbeddedStorageFoundation createStorageFoundation(final EclipseStoreProperties eclipseStoreProperties, final ConfigurationPair... additionalConfiguration) + { + return this.embeddedStorageFoundationFactory.createStorageFoundation(eclipseStoreProperties, additionalConfiguration); + } + +} diff --git a/integrations/spring-boot3/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/integrations/spring-boot3/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..a7cf5fb4 --- /dev/null +++ b/integrations/spring-boot3/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +org.eclipse.store.integrations.spring.boot.types.EclipseStoreSpringBoot +org.eclipse.store.integrations.spring.boot.types.DefaultEclipseStoreConfiguration diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigFieldsTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigFieldsTest.java index 12857762..4d66de6a 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigFieldsTest.java +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigFieldsTest.java @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverterTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverterTest.java index 20580ba0..6b86dfe6 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverterTest.java +++ b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverterTest.java @@ -16,7 +16,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ @@ -68,7 +68,8 @@ void testSQLConfiguration() } @Test - void testConvertConfigurationToMap() { + void testConvertConfigurationToMap() + { final EclipseStoreProperties configValues = new EclipseStoreProperties(); final Map result = this.converter.convertConfigurationToMap(configValues); assertNotNull(result); @@ -76,7 +77,8 @@ void testConvertConfigurationToMap() { } @Test - void testConvertConfigurationToMapWithStorageDirectory() { + void testConvertConfigurationToMapWithStorageDirectory() + { final EclipseStoreProperties configValues = new EclipseStoreProperties(); configValues.setStorageDirectory("storage/dir"); final Map result = this.converter.convertConfigurationToMap(configValues); @@ -85,7 +87,8 @@ void testConvertConfigurationToMapWithStorageDirectory() { } @Test - void testNullValuesAreRemoved() { + void testNullValuesAreRemoved() + { final EclipseStoreProperties configValues = new EclipseStoreProperties(); configValues.setStorageDirectory(null); configValues.setStorageFilesystem(new StorageFilesystem()); @@ -98,7 +101,8 @@ void testNullValuesAreRemoved() { } @Test - void testComposeKey() { + void testComposeKey() + { final String result = this.converter.composeKey("prefix", "suffix"); assertEquals("prefix.suffix", result); } diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoBeanConfiguration.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoBeanConfiguration.java deleted file mode 100644 index 419f9015..00000000 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoBeanConfiguration.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.eclipse.store.integrations.spring.boot.types.storages; - -/*- - * #%L - * spring-boot3 - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ - -import org.eclipse.store.integrations.spring.boot.types.EclipseStoreProvider; -import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; -import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Lazy; - -@TestConfiguration -public class TwoBeanConfiguration -{ - - @Autowired - private EclipseStoreProvider provider; - - @Bean("first_config") - @ConfigurationProperties("org.eclipse.store.first") - EclipseStoreProperties firstStoreProperties() - { - return new EclipseStoreProperties(); - } - - @Bean("second_config") - @ConfigurationProperties("org.eclipse.store.second") - EclipseStoreProperties secondStoreProperties() - { - return new EclipseStoreProperties(); - } - - @Bean - @Lazy - @Qualifier("first_storage") - EmbeddedStorageManager createFirstStorage(@Qualifier("first_config") final EclipseStoreProperties firstStoreProperties) - { - return this.provider.createStorage(firstStoreProperties); - } - - @Bean - @Lazy - @Qualifier("second_storage") - EmbeddedStorageManager createSecondStorage(@Qualifier("second_config") final EclipseStoreProperties secondStoreProperties) - { - return this.provider.createStorage(secondStoreProperties); - } - - -} diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoStoragesTest.java b/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoStoragesTest.java deleted file mode 100644 index 73e29c65..00000000 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/TwoStoragesTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.eclipse.store.integrations.spring.boot.types.storages; - -/*- - * #%L - * spring-boot3 - * %% - * Copyright (C) 2023 MicroStream Software - * %% - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * #L% - */ - -import org.eclipse.store.integrations.spring.boot.types.EclipseStoreSpringBoot; -import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.TestPropertySource; - -@TestPropertySource("classpath:application-two-storages.properties") -@Import(TwoBeanConfiguration.class) -@SpringBootTest(classes = {EclipseStoreSpringBoot.class, TwoStoragesTest.class}) -public class TwoStoragesTest -{ - - @Autowired - @Qualifier("first_storage") - EmbeddedStorageManager firstStorage; - - @Autowired - @Qualifier("second_storage") - EmbeddedStorageManager secondStorage; - - - @Test - void name() - { - Assertions.assertEquals("FirstRoot{value='First root value'}", this.firstStorage.root().toString()); - Assertions.assertEquals("SecondRoot{intValue=50, c=c}", this.secondStorage.root().toString()); - } - -} diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSpringTest.java b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/EclipseConfigurationSpringTest.java similarity index 74% rename from integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSpringTest.java rename to integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/EclipseConfigurationSpringTest.java index f9436c11..81bb472c 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSpringTest.java +++ b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/EclipseConfigurationSpringTest.java @@ -1,15 +1,10 @@ -package org.eclipse.store.integrations.spring.boot.types; - -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Map; +package test.eclipse.store.integrations.spring.boot; /*- * #%L - * spring-boot3 + * EclipseStore Integrations SpringBoot * %% - * Copyright (C) 2023 MicroStream Software + * Copyright (C) 2023 - 2024 MicroStream Software * %% * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -23,34 +18,34 @@ import org.eclipse.store.integrations.spring.boot.types.converter.EclipseStoreConfigConverter; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + @TestPropertySource("classpath:application-test.properties") -@SpringBootTest(classes = {EclipseStoreSpringBoot.class}) +@SpringBootTest public class EclipseConfigurationSpringTest { - @Qualifier("eclipseStoreProperties") @Autowired - EclipseStoreProperties values; - + private EclipseStoreProperties values; @Autowired - EclipseStoreConfigConverter converter; + private EclipseStoreConfigConverter converter; @Test - void checkStorageDirectoryValue() + void checks_storage_directory_value() { assertNotNull(this.values.getStorageDirectory()); } @Test - void converterBasicTest() + void converts_value_from_properties() { final Map valueMap = this.converter.convertConfigurationToMap(this.values); - assertTrue(valueMap.containsKey("storage-filesystem.sql.postgres.data-source-provider")); - } } diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSqlSpringTest.java b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/EclipseConfigurationSqlSpringTest.java similarity index 74% rename from integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSqlSpringTest.java rename to integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/EclipseConfigurationSqlSpringTest.java index a0ff19c4..2e046822 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/EclipseConfigurationSqlSpringTest.java +++ b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/EclipseConfigurationSqlSpringTest.java @@ -1,15 +1,10 @@ -package org.eclipse.store.integrations.spring.boot.types; - -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Map; +package test.eclipse.store.integrations.spring.boot; /*- * #%L - * spring-boot3 + * EclipseStore Integrations SpringBoot * %% - * Copyright (C) 2023 MicroStream Software + * Copyright (C) 2023 - 2024 MicroStream Software * %% * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -23,30 +18,33 @@ import org.eclipse.store.integrations.spring.boot.types.converter.EclipseStoreConfigConverter; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@SpringBootTest @TestPropertySource("classpath:application-sql.properties") -@SpringBootTest(classes = {EclipseStoreSpringBoot.class}) public class EclipseConfigurationSqlSpringTest { - @Qualifier("eclipseStoreProperties") @Autowired - EclipseStoreProperties values; + private EclipseStoreProperties values; @Autowired - EclipseStoreConfigConverter converter; + private EclipseStoreConfigConverter converter; @Test - void checkStorageDirectoryValue() + void checks_storage_directory_value() { assertNotNull(this.values.getStorageFilesystem()); } @Test - void converterBasicTest() + void converts_value_from_properties() { final Map valueMap = this.converter.convertConfigurationToMap(this.values); assertTrue(valueMap.containsKey("storage-filesystem.sql.postgres.user")); diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/InjectStorageBeanTest.java b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/InjectStorageBeanTest.java similarity index 55% rename from integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/InjectStorageBeanTest.java rename to integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/InjectStorageBeanTest.java index 0917cddb..38424382 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/InjectStorageBeanTest.java +++ b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/InjectStorageBeanTest.java @@ -1,4 +1,4 @@ -package org.eclipse.store.integrations.spring.boot.types; +package test.eclipse.store.integrations.spring.boot; /*- * #%L @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ @@ -20,21 +20,28 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; -@TestPropertySource("classpath:application-run.properties") -@SpringBootTest(classes = {EclipseStoreSpringBoot.class}) +import static org.assertj.core.api.Assertions.assertThat; + + +@SpringBootTest +@TestPropertySource("classpath:application-inject-test.properties") public class InjectStorageBeanTest { @Autowired - EmbeddedStorageManager manager; + private EmbeddedStorageManager manager; @Test - void storeSomething() + void injects_storage_manager() { - this.manager.start(); - this.manager.setRoot("hello"); - this.manager.storeRoot(); - this.manager.shutdown(); + assertThat(manager.isRunning()).isFalse(); + manager.start(); + assertThat(manager.isRunning()).isTrue(); + manager.setRoot("hello"); + manager.storeRoot(); + manager.shutdown(); + assertThat(manager.isRunning()).isFalse(); } + } diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/RestartStorageBeanTest.java b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/RestartStorageBeanTest.java similarity index 53% rename from integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/RestartStorageBeanTest.java rename to integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/RestartStorageBeanTest.java index 8b289c1e..e22beaac 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/RestartStorageBeanTest.java +++ b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/RestartStorageBeanTest.java @@ -1,4 +1,4 @@ -package org.eclipse.store.integrations.spring.boot.types; +package test.eclipse.store.integrations.spring.boot; /*- * #%L @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ @@ -17,56 +17,60 @@ import org.eclipse.store.integrations.spring.boot.types.configuration.ConfigurationPair; import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; +import org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageFoundationFactory; import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.system.ApplicationTemp; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.Profile; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.TestPropertySource; -@TestPropertySource("classpath:application-run.properties") -@SpringBootTest(classes = {EclipseStoreSpringBoot.class, RestartStorageBeanTest.class}) +import java.nio.file.Path; + + +@SpringBootTest +@TestPropertySource("classpath:application-run-test.properties") +@Import(RestartStorageBeanTest.RestartStorageBeanConfiguration.class) +@ActiveProfiles("restart_storage") public class RestartStorageBeanTest { @Autowired - EclipseStoreProvider provider; + private EmbeddedStorageFoundationFactory foundationFactory; - @Qualifier("eclipseStoreProperties") @Autowired - EclipseStoreProperties myConfiguration; + private EclipseStoreProperties myConfiguration; - static String tempFolder = null; - - @Bean - EmbeddedStorageManager injectStorageTest() - { + @Autowired + @Qualifier("restartStorageBean") + private EmbeddedStorageManager manager; - final ApplicationTemp temp = new ApplicationTemp(); - tempFolder = temp.getDir().getAbsolutePath(); - this.myConfiguration.setStorageDirectory(temp.getDir().getAbsolutePath()); - final EmbeddedStorageFoundation storageFoundation = this.provider.createStorageFoundation(this.myConfiguration); + @TempDir + static Path tempFolder; - return storageFoundation.createEmbeddedStorageManager(); - } @Test - void restartStorageTest(@Autowired final EmbeddedStorageManager manager) + void restarts_storage() { + final RestartRoot root = new RestartRoot("hello"); manager.start(); manager.setRoot(root); manager.storeRoot(); manager.shutdown(); - Assertions.assertEquals(tempFolder, manager.configuration().fileProvider().baseDirectory().toPathString()); + Assertions.assertEquals(tempFolder.toAbsolutePath().toString(), manager.configuration().fileProvider().baseDirectory().toPathString()); final ConfigurationPair pair = new ConfigurationPair("someKey", "someValue"); - final EmbeddedStorageFoundation storageFoundation = this.provider.createStorageFoundation(this.myConfiguration, pair); + final EmbeddedStorageFoundation storageFoundation = this.foundationFactory.createStorageFoundation(this.myConfiguration, pair); final RestartRoot root2 = new RestartRoot(); storageFoundation.setRoot(root2); try (EmbeddedStorageManager storage = storageFoundation.start()) @@ -76,7 +80,8 @@ void restartStorageTest(@Autowired final EmbeddedStorageManager manager) } } - static class RestartRoot { + static class RestartRoot + { private String value; public RestartRoot(final String value) @@ -98,4 +103,25 @@ public void setValue(final String value) this.value = value; } } + + @TestConfiguration + @Profile("restart_storage") + static class RestartStorageBeanConfiguration + { + + @Autowired + private EmbeddedStorageFoundationFactory foundationFactory; + + @Autowired + @Qualifier("defaultEclipseStoreProperties") + private EclipseStoreProperties myConfiguration; + + @Bean("restartStorageBean") + EmbeddedStorageManager restartStorageBean() + { + this.myConfiguration.setStorageDirectory(tempFolder.toAbsolutePath().toString()); + final EmbeddedStorageFoundation storageFoundation = this.foundationFactory.createStorageFoundation(this.myConfiguration); + return storageFoundation.createEmbeddedStorageManager(); + } + } } diff --git a/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/TestApplication.java b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/TestApplication.java new file mode 100644 index 00000000..1e9cd9c7 --- /dev/null +++ b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/TestApplication.java @@ -0,0 +1,27 @@ +package test.eclipse.store.integrations.spring.boot; + +/*- + * #%L + * EclipseStore Integrations SpringBoot + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; + +/** + * No component scan, rather configuration and enable auto configurations. + */ +@SpringBootConfiguration +@EnableAutoConfiguration +public class TestApplication +{ +} diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/root/AutostartRootTest.java b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/root/AutostartRootTest.java similarity index 74% rename from integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/root/AutostartRootTest.java rename to integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/root/AutostartRootTest.java index 3d498ba3..8b256eeb 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/root/AutostartRootTest.java +++ b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/root/AutostartRootTest.java @@ -1,4 +1,4 @@ -package org.eclipse.store.integrations.spring.boot.types.root; +package test.eclipse.store.integrations.spring.boot.root; /*- * #%L @@ -9,31 +9,34 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ -import org.eclipse.store.integrations.spring.boot.types.EclipseStoreSpringBoot; import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertTrue; @TestPropertySource("classpath:application-autostart-root.properties") -@SpringBootTest(classes = {EclipseStoreSpringBoot.class}) +@SpringBootTest public class AutostartRootTest { + @Autowired + private EmbeddedStorageManager storage; + @Test - void name(@Autowired EmbeddedStorageManager storage) + void autostarts_and_provides_root() { assertTrue(storage.isRunning() || storage.isStartingUp()); Object o = storage.root(); - assertTrue(o instanceof Root); + assertInstanceOf(Root.class, o); } } diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/root/Root.java b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/root/Root.java similarity index 83% rename from integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/root/Root.java rename to integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/root/Root.java index e768de33..ceb6eddf 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/root/Root.java +++ b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/root/Root.java @@ -1,4 +1,4 @@ -package org.eclipse.store.integrations.spring.boot.types.root; +package test.eclipse.store.integrations.spring.boot.root; /*- * #%L @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/FirstRoot.java b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/storages/FirstRoot.java similarity index 90% rename from integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/FirstRoot.java rename to integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/storages/FirstRoot.java index 42ef5b34..f35fc84f 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/FirstRoot.java +++ b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/storages/FirstRoot.java @@ -1,4 +1,4 @@ -package org.eclipse.store.integrations.spring.boot.types.storages; +package test.eclipse.store.integrations.spring.boot.storages; /*- * #%L diff --git a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/SecondRoot.java b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/storages/SecondRoot.java similarity index 91% rename from integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/SecondRoot.java rename to integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/storages/SecondRoot.java index 44c55bdf..2b1fb88f 100644 --- a/integrations/spring-boot3/src/test/java/org/eclipse/store/integrations/spring/boot/types/storages/SecondRoot.java +++ b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/storages/SecondRoot.java @@ -1,4 +1,4 @@ -package org.eclipse.store.integrations.spring.boot.types.storages; +package test.eclipse.store.integrations.spring.boot.storages; /*- * #%L @@ -9,7 +9,7 @@ * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ diff --git a/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/storages/TwoStoragesTest.java b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/storages/TwoStoragesTest.java new file mode 100644 index 00000000..0b918be6 --- /dev/null +++ b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/storages/TwoStoragesTest.java @@ -0,0 +1,110 @@ +package test.eclipse.store.integrations.spring.boot.storages; + +/*- + * #%L + * spring-boot3 + * %% + * Copyright (C) 2023 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; +import org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageFoundationFactory; +import org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageManagerFactory; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.Profile; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.TestPropertySource; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest +@TestPropertySource("classpath:application-two-storages.properties") +@ActiveProfiles("two_storages") +@Import(TwoStoragesTest.TwoBeanConfiguration.class) +public class TwoStoragesTest +{ + + @Autowired(required = false) + @Qualifier("first_storage") + private EmbeddedStorageManager firstStorage; + + @Autowired(required = false) + @Qualifier("second_storage") + private EmbeddedStorageManager secondStorage; + + @Autowired(required = false) + @Qualifier("defaultEclipseStore") + private EmbeddedStorageManager defaultEclipseStore; + + + @Test + void sets_up_two_storages() + { + assertThat(defaultEclipseStore).isNull(); // conditional will not create a default storage. + assertThat(firstStorage).isNotNull(); + assertThat(secondStorage).isNotNull(); + + assertThat(firstStorage.root().toString()).isEqualTo("FirstRoot{value='First root value'}"); + assertThat(secondStorage.root().toString()).isEqualTo("SecondRoot{intValue=50, c=c}"); + } + + @TestConfiguration + @Profile("two_storages") + static class TwoBeanConfiguration + { + + @Autowired + private EmbeddedStorageFoundationFactory foundationFactory; + @Autowired + private EmbeddedStorageManagerFactory managerFactory; + + @Bean("first_config") + @ConfigurationProperties("org.eclipse.store.first") + EclipseStoreProperties firstStoreProperties() + { + return new EclipseStoreProperties(); + } + + @Bean("second_config") + @ConfigurationProperties("org.eclipse.store.second") + EclipseStoreProperties secondStoreProperties() + { + return new EclipseStoreProperties(); + } + + @Bean + @Qualifier("first_storage") + EmbeddedStorageManager createFirstStorage(@Qualifier("first_config") final EclipseStoreProperties firstStoreProperties) + { + return managerFactory.createStorage( + foundationFactory.createStorageFoundation(firstStoreProperties), + firstStoreProperties.isAutoStart() + ); + } + + @Bean + @Qualifier("second_storage") + EmbeddedStorageManager createSecondStorage(@Qualifier("second_config") final EclipseStoreProperties secondStoreProperties) + { + return managerFactory.createStorage( + foundationFactory.createStorageFoundation(secondStoreProperties), + secondStoreProperties.isAutoStart() + ); + } + } +} diff --git a/integrations/spring-boot3/src/test/resources/application-autostart-root.properties b/integrations/spring-boot3/src/test/resources/application-autostart-root.properties index c9800b65..e2d21321 100644 --- a/integrations/spring-boot3/src/test/resources/application-autostart-root.properties +++ b/integrations/spring-boot3/src/test/resources/application-autostart-root.properties @@ -1,4 +1,4 @@ -debug=true +# debug=true org.eclipse.store.storage-directory=${java.io.tmpdir}/${random.int} org.eclipse.store.auto-start=true -org.eclipse.store.root=org.eclipse.store.integrations.spring.boot.types.root.Root +org.eclipse.store.root=test.eclipse.store.integrations.spring.boot.root.Root diff --git a/integrations/spring-boot3/src/test/resources/application-run.properties b/integrations/spring-boot3/src/test/resources/application-inject-test.properties similarity index 88% rename from integrations/spring-boot3/src/test/resources/application-run.properties rename to integrations/spring-boot3/src/test/resources/application-inject-test.properties index 92e9e479..9f570fbd 100644 --- a/integrations/spring-boot3/src/test/resources/application-run.properties +++ b/integrations/spring-boot3/src/test/resources/application-inject-test.properties @@ -1,3 +1,3 @@ -debug=true +# debug=true org.eclipse.store.storage-directory=${java.io.tmpdir}/${random.int} org.eclipse.store.auto-start=false diff --git a/integrations/spring-boot3/src/test/resources/application-run-test.properties b/integrations/spring-boot3/src/test/resources/application-run-test.properties new file mode 100644 index 00000000..9f570fbd --- /dev/null +++ b/integrations/spring-boot3/src/test/resources/application-run-test.properties @@ -0,0 +1,3 @@ +# debug=true +org.eclipse.store.storage-directory=${java.io.tmpdir}/${random.int} +org.eclipse.store.auto-start=false diff --git a/integrations/spring-boot3/src/test/resources/application-test.properties b/integrations/spring-boot3/src/test/resources/application-test.properties index fa83194e..9471cd41 100644 --- a/integrations/spring-boot3/src/test/resources/application-test.properties +++ b/integrations/spring-boot3/src/test/resources/application-test.properties @@ -1,4 +1,4 @@ -debug=true +# debug=true org.eclipse.store.storage-filesystem.sql.postgres.data-source-provider=MyDataSourceProvider org.eclipse.store.storage-filesystem.sql.postgres.password=password1 org.eclipse.store.storage-filesystem.sql.postgres.user=postgres diff --git a/integrations/spring-boot3/src/test/resources/application-two-storages.properties b/integrations/spring-boot3/src/test/resources/application-two-storages.properties index 965e1b6c..7a373969 100644 --- a/integrations/spring-boot3/src/test/resources/application-two-storages.properties +++ b/integrations/spring-boot3/src/test/resources/application-two-storages.properties @@ -1,7 +1,7 @@ org.eclipse.store.first.storage-directory=${java.io.tmpdir}/${random.int} org.eclipse.store.first.auto-start=false -org.eclipse.store.first.root=org.eclipse.store.integrations.spring.boot.types.storages.FirstRoot +org.eclipse.store.first.root=test.eclipse.store.integrations.spring.boot.storages.FirstRoot org.eclipse.store.second.storage-directory=${java.io.tmpdir}/${random.int} org.eclipse.store.second.auto-start=false -org.eclipse.store.second.root=org.eclipse.store.integrations.spring.boot.types.storages.SecondRoot +org.eclipse.store.second.root=test.eclipse.store.integrations.spring.boot.storages.SecondRoot diff --git a/integrations/spring-boot3/src/test/resources/banner.txt b/integrations/spring-boot3/src/test/resources/banner.txt index e1101d97..1ee1e0cb 100644 --- a/integrations/spring-boot3/src/test/resources/banner.txt +++ b/integrations/spring-boot3/src/test/resources/banner.txt @@ -1,9 +1,3 @@ - - _____ _ _ _____ _ _____ _ -| ___| | (_) / ___| | / ___| (_) -| |__ ___| |_ _ __ ___ ___ \ `--.| |_ ___ _ __ ___ \ `--. _ __ _ __ _ _ __ __ _ -| __|/ __| | | '_ \/ __|/ _ \ `--. \ __/ _ \| '__/ _ \ `--. \ '_ \| '__| | '_ \ / _` | -| |__| (__| | | |_) \__ \ __/ /\__/ / || (_) | | | __/ /\__/ / |_) | | | | | | | (_| | -\____/\___|_|_| .__/|___/\___| \____/ \__\___/|_| \___| \____/| .__/|_| |_|_| |_|\__, | - | | | | __/ | - |_| |_| |___/ +------------------------------------------------------------------------------- +EclipseStore SpringBoot3 I-Test, version: ${spring-boot.version} +------------------------------------------------------------------------------- diff --git a/integrations/spring-boot3/src/test/resources/logback-test.xml b/integrations/spring-boot3/src/test/resources/logback-test.xml index a79611a3..3e9fff22 100644 --- a/integrations/spring-boot3/src/test/resources/logback-test.xml +++ b/integrations/spring-boot3/src/test/resources/logback-test.xml @@ -8,7 +8,7 @@ - + diff --git a/storage/rest/client-app-standalone-assembly/LICENSE b/storage/rest/client-app-standalone-assembly/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/storage/rest/client-app-standalone-assembly/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/storage/rest/client-app-standalone-assembly/pom.xml b/storage/rest/client-app-standalone-assembly/pom.xml new file mode 100644 index 00000000..15bfb512 --- /dev/null +++ b/storage/rest/client-app-standalone-assembly/pom.xml @@ -0,0 +1,107 @@ + + + + + 4.0.0 + + + org.eclipse.store + storage-rest-parent + 1.3.0-SNAPSHOT + ../pom.xml + + + storage-restclient-app-standalone-assembly + EclipseStore Storage REST Client App Standalone Assembly + Executable Client App with Web User Interface + https://projects.eclipse.org/projects/technology.store + + + 24.2.6 + 3.2.0 + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + org.eclipse.store + storage-restclient-app + ${project.version} + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.jupiter + junit-jupiter-engine + 5.10.0 + test + + + + + spring-boot:run + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + org.eclipse.store.storage.restclient.app.standalone.types.Application + + 500 + 240 + + + + + + + + production + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + ${project.artifactId}-${project.version}-standalone + + org.eclipse.store.storage.restclient.app.standalone.types.Application + -Dvaadin.productionMode + JAR + + + + + repackage + + + + + + + + + + diff --git a/storage/rest/client-app-standalone-assembly/src/main/java/module-info.java b/storage/rest/client-app-standalone-assembly/src/main/java/module-info.java new file mode 100644 index 00000000..e747c9bf --- /dev/null +++ b/storage/rest/client-app-standalone-assembly/src/main/java/module-info.java @@ -0,0 +1,22 @@ +/*- + * #%L + * EclipseStore Storage REST Client App Standalone Assembly + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module storage.restclient.app.standalone.assembly { + opens org.eclipse.store.storage.restclient.app.standalone.types to spring.core, spring.beans, spring.context; + + requires spring.boot; + requires spring.boot.autoconfigure; + requires spring.context; + requires org.eclipse.store.storage.restclient.app; + +} diff --git a/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/types/Application.java b/storage/rest/client-app-standalone-assembly/src/main/java/org/eclipse/store/storage/restclient/app/standalone/types/Application.java similarity index 74% rename from storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/types/Application.java rename to storage/rest/client-app-standalone-assembly/src/main/java/org/eclipse/store/storage/restclient/app/standalone/types/Application.java index ad7fc8f9..e9a41d62 100644 --- a/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/types/Application.java +++ b/storage/rest/client-app-standalone-assembly/src/main/java/org/eclipse/store/storage/restclient/app/standalone/types/Application.java @@ -1,5 +1,5 @@ -package org.eclipse.store.storage.restclient.app.types; +package org.eclipse.store.storage.restclient.app.standalone.types; /*- * #%L @@ -15,15 +15,16 @@ * #L% */ +import org.eclipse.store.storage.restclient.app.types.RestClientAppAutoConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; -import com.vaadin.flow.spring.annotation.EnableVaadin; +import org.springframework.context.annotation.Import; @SpringBootApplication -@EnableVaadin("org.eclipse.store.storage.restclient.app.ui") +@Import(RestClientAppAutoConfiguration.class) public class Application extends SpringBootServletInitializer { public static void main( diff --git a/storage/rest/client-app/src/main/resources/application.properties b/storage/rest/client-app-standalone-assembly/src/main/resources/application.properties similarity index 99% rename from storage/rest/client-app/src/main/resources/application.properties rename to storage/rest/client-app-standalone-assembly/src/main/resources/application.properties index f30ced76..30d927b1 100644 --- a/storage/rest/client-app/src/main/resources/application.properties +++ b/storage/rest/client-app-standalone-assembly/src/main/resources/application.properties @@ -1,12 +1,10 @@ +logging.level.org.atmosphere = warn server.port = ${port:8080} +server.error.whitelabel.enabled = false -logging.level.org.atmosphere = warn +spring.servlet.multipart.enabled = false vaadin.productionMode = true vaadin.compatibilityMode = true vaadin.original.frontend.resources = true - -server.error.whitelabel.enabled = false - -spring.servlet.multipart.enabled = false diff --git a/storage/rest/client-app/src/main/resources/banner.txt b/storage/rest/client-app-standalone-assembly/src/main/resources/banner.txt similarity index 100% rename from storage/rest/client-app/src/main/resources/banner.txt rename to storage/rest/client-app-standalone-assembly/src/main/resources/banner.txt diff --git a/storage/rest/client-app/src/main/resources/logback.xml b/storage/rest/client-app-standalone-assembly/src/main/resources/logback.xml similarity index 100% rename from storage/rest/client-app/src/main/resources/logback.xml rename to storage/rest/client-app-standalone-assembly/src/main/resources/logback.xml diff --git a/storage/rest/client-app-standalone-assembly/src/test/java/org/eclipse/store/storage/restclient/app/standalone/types/ApplicationTest.java b/storage/rest/client-app-standalone-assembly/src/test/java/org/eclipse/store/storage/restclient/app/standalone/types/ApplicationTest.java new file mode 100644 index 00000000..abf64d16 --- /dev/null +++ b/storage/rest/client-app-standalone-assembly/src/test/java/org/eclipse/store/storage/restclient/app/standalone/types/ApplicationTest.java @@ -0,0 +1,35 @@ +package org.eclipse.store.storage.restclient.app.standalone.types; + +/*- + * #%L + * EclipseStore Storage REST Client App Standalone Assembly + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +class ApplicationTest { + + @Autowired + private ApplicationContext context; + + @Test + public void should_start_application() { + assertThat(context).isNotNull(); + } + +} diff --git a/storage/rest/client-app/pom.xml b/storage/rest/client-app/pom.xml index bb9c8306..e55e3d7d 100644 --- a/storage/rest/client-app/pom.xml +++ b/storage/rest/client-app/pom.xml @@ -16,13 +16,10 @@ storage-restclient-app EclipseStore Storage REST Client App - Executable Client App with Web User Interface + Client App with Web User Interface https://projects.eclipse.org/projects/technology.store - 17 - 17 - 17 24.2.6 3.2.0 @@ -64,31 +61,10 @@ jakarta.activation jakarta.activation-api - - org.slf4j - slf4j-api - - 2.0.9 - - spring-boot:run - - org.springframework.boot - spring-boot-maven-plugin - ${spring.boot.version} - - - org.eclipse.store.storage.restclient.app.types.Application - - 500 - 240 - - com.vaadin vaadin-maven-plugin @@ -112,24 +88,6 @@ - - org.springframework.boot - spring-boot-maven-plugin - ${spring.boot.version} - - - org.eclipse.store.storage.restclient.app.types.Application - -Dvaadin.productionMode - JAR - - - - - repackage - - - - com.vaadin vaadin-maven-plugin diff --git a/storage/rest/client-app/src/main/java/module-info.java b/storage/rest/client-app/src/main/java/module-info.java index 3af3273d..73349a81 100644 --- a/storage/rest/client-app/src/main/java/module-info.java +++ b/storage/rest/client-app/src/main/java/module-info.java @@ -17,7 +17,9 @@ provides com.vaadin.flow.server.VaadinServiceInitListener with org.eclipse.store.storage.restclient.app.types.ApplicationServiceInitListener; - + + opens org.eclipse.store.storage.restclient.app.types to spring.core, spring.beans, spring.context; + requires flow.data; requires flow.html.components; requires flow.server; diff --git a/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/types/RestClientAppAutoConfiguration.java b/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/types/RestClientAppAutoConfiguration.java new file mode 100644 index 00000000..4d1ec65b --- /dev/null +++ b/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/types/RestClientAppAutoConfiguration.java @@ -0,0 +1,25 @@ +package org.eclipse.store.storage.restclient.app.types; + +/*- + * #%L + * EclipseStore Storage REST Client App + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import com.vaadin.flow.spring.annotation.EnableVaadin; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableVaadin("org.eclipse.store.storage.restclient.app.ui") +@ComponentScan +public class RestClientAppAutoConfiguration { +} diff --git a/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/ConnectView.java b/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/ConnectView.java index cf533ef9..41da84e6 100644 --- a/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/ConnectView.java +++ b/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/ConnectView.java @@ -20,7 +20,6 @@ import java.util.Base64; import java.util.LinkedHashSet; import java.util.Set; -import java.util.stream.Collectors; import org.eclipse.store.storage.restclient.app.types.SessionData; import org.eclipse.store.storage.restclient.jersey.types.StorageRestClientJersey; @@ -63,7 +62,7 @@ public ConnectView() final Button cmdConnect = new Button(this.getTranslation("CONNECT"), event -> { String url = urlChooser.getValue(); - if(url != null && (url = url.trim()).length() > 0) + if(url != null && !(url = url.trim()).isEmpty()) { this.tryConnect(url); } @@ -151,8 +150,9 @@ private void tryConnect( private Set urls() { final Set urlSelection = new LinkedHashSet<>(); + urlSelection.add("http://localhost:8080/store-data/default/"); urlSelection.add("http://localhost:4567/store-data/"); - + final HttpServletRequest request = (HttpServletRequest) VaadinRequest.getCurrent(); final Cookie[] cookies = request.getCookies(); if(cookies != null) @@ -167,10 +167,7 @@ private Set urls() Base64.getUrlDecoder().decode(urlCookie.getValue()), StandardCharsets.UTF_8 ); - for(final String url : urls.split("\n")) - { - urlSelection.add(url); - } + urlSelection.addAll(Arrays.asList(urls.split("\n"))); } } return urlSelection; @@ -183,7 +180,7 @@ private void updateUrlCookie( final Set urls = this.urls(); if(urls.add(url)) { - final String cookieData = urls.stream().collect(Collectors.joining("\n")); + final String cookieData = String.join("\n", urls); final HttpServletResponse response = (HttpServletResponse) VaadinResponse.getCurrent(); final Cookie cookie = new Cookie( diff --git a/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/UIUtils.java b/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/UIUtils.java index a8a52d32..529e4a24 100644 --- a/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/UIUtils.java +++ b/storage/rest/client-app/src/main/java/org/eclipse/store/storage/restclient/app/ui/UIUtils.java @@ -30,7 +30,7 @@ public static L compact( public static String imagePath(String image) { - return "frontend/images/" + image; + return "/frontend/images/" + image; } diff --git a/storage/rest/pom.xml b/storage/rest/pom.xml index 8ab2cdc9..e9e10c9e 100644 --- a/storage/rest/pom.xml +++ b/storage/rest/pom.xml @@ -1,43 +1,64 @@ - - 4.0.0 - - - org.eclipse.store - storage-parent - 1.3.0-SNAPSHOT - ../pom.xml - - - storage-rest-parent - pom - - EclipseStore Storage REST Parent - EclipseStore Storage REST Project - https://projects.eclipse.org/projects/technology.store - - - adapter - client - client-jersey - service - service-sparkjava - - - - - from_java_17 - - [17,) - - - client-app - - - + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + 4.0.0 + + + org.eclipse.store + storage-parent + 1.3.0-SNAPSHOT + ../pom.xml + + + storage-rest-parent + pom + + EclipseStore Storage REST Parent + EclipseStore Storage REST Project + https://projects.eclipse.org/projects/technology.store + + + adapter + client + client-jersey + service + service-sparkjava + + + + + from_java_17 + + [17,) + + + 17 + 17 + 17 + + + service-springboot + client-app + client-app-standalone-assembly + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + 17 + + + + + + + + diff --git a/storage/rest/service-springboot/LICENSE b/storage/rest/service-springboot/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/storage/rest/service-springboot/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/storage/rest/service-springboot/pom.xml b/storage/rest/service-springboot/pom.xml new file mode 100644 index 00000000..49b4f6d3 --- /dev/null +++ b/storage/rest/service-springboot/pom.xml @@ -0,0 +1,60 @@ + + + + + 4.0.0 + + + org.eclipse.store + storage-rest-parent + 1.3.0-SNAPSHOT + ../pom.xml + + + storage-restservice-springboot + + EclipseStore Storage REST Service SpringBoot + EclipseStore Storage REST Service Implementation + https://projects.eclipse.org/projects/technology.store + + + 3.2.2 + + + + + org.eclipse.store + integrations-spring-boot3 + ${project.version} + + + org.eclipse.store + storage-restadapter + ${project.version} + + + + org.springframework.boot + spring-boot-starter-web + ${spring-boot.version} + provided + + + + org.springframework.boot + spring-boot-starter-test + ${spring-boot.version} + test + + + + org.junit.jupiter + junit-jupiter-engine + 5.10.0 + test + + + + diff --git a/storage/rest/service-springboot/src/main/java/module-info.java b/storage/rest/service-springboot/src/main/java/module-info.java new file mode 100644 index 00000000..f0382f7a --- /dev/null +++ b/storage/rest/service-springboot/src/main/java/module-info.java @@ -0,0 +1,28 @@ +/*- + * #%L + * EclipseStore Storage REST Service SpringBoot + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ +module storage.restservice.springboot { + requires com.fasterxml.jackson.annotation; + requires jakarta.annotation; + requires org.slf4j; + requires spring.boot; + requires spring.boot.autoconfigure; + requires spring.context; + requires spring.web; + requires transitive org.eclipse.store.integrations.spring.boot; + requires transitive org.eclipse.store.storage; + requires transitive org.eclipse.store.storage.embedded; + requires transitive org.eclipse.store.storage.restadapter; + + exports org.eclipse.store.storage.restservice.spring.boot.types; +} diff --git a/storage/rest/service-springboot/src/main/java/org/eclipse/store/storage/restservice/spring/boot/types/StoreDataRestAutoConfiguration.java b/storage/rest/service-springboot/src/main/java/org/eclipse/store/storage/restservice/spring/boot/types/StoreDataRestAutoConfiguration.java new file mode 100644 index 00000000..be9eb741 --- /dev/null +++ b/storage/rest/service-springboot/src/main/java/org/eclipse/store/storage/restservice/spring/boot/types/StoreDataRestAutoConfiguration.java @@ -0,0 +1,55 @@ +package org.eclipse.store.storage.restservice.spring.boot.types; + +/*- + * #%L + * integrations-spring-boot3-console + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.integrations.spring.boot.types.DefaultEclipseStoreConfiguration; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.eclipse.store.storage.restadapter.types.StorageRestAdapter; +import org.eclipse.store.storage.restservice.spring.boot.types.configuration.StoreDataRestServiceProperties; +import org.eclipse.store.storage.restservice.spring.boot.types.rest.StoreDataRestController; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Auto-configuration for the Spring Web MVC Rest Service. + */ +@Configuration +@AutoConfigureAfter({DefaultEclipseStoreConfiguration.class}) +@EnableConfigurationProperties(StoreDataRestServiceProperties.class) +public class StoreDataRestAutoConfiguration { + + @Bean + @ConditionalOnProperty(prefix = "org.eclipse.store.rest", name = "enabled", havingValue = "true") + public Map storageRestAdapters(Map storages) { + return storages.entrySet().stream().collect(Collectors.toMap( + Map.Entry::getKey, + e -> StorageRestAdapter.New(e.getValue()) + )); + } + + @Bean + @ConditionalOnProperty(prefix = "org.eclipse.store.rest", name = "enabled", havingValue = "true") + public StoreDataRestController storageDataRestController(Map storageRestAdapters, + StoreDataRestServiceProperties properties) { + return new StoreDataRestController(storageRestAdapters, properties); + } + +} diff --git a/storage/rest/service-springboot/src/main/java/org/eclipse/store/storage/restservice/spring/boot/types/configuration/StoreDataRestServiceProperties.java b/storage/rest/service-springboot/src/main/java/org/eclipse/store/storage/restservice/spring/boot/types/configuration/StoreDataRestServiceProperties.java new file mode 100644 index 00000000..a2e8ef0d --- /dev/null +++ b/storage/rest/service-springboot/src/main/java/org/eclipse/store/storage/restservice/spring/boot/types/configuration/StoreDataRestServiceProperties.java @@ -0,0 +1,53 @@ +package org.eclipse.store.storage.restservice.spring.boot.types.configuration; + +/*- + * #%L + * EclipseStore Storage REST Service SpringBoot + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Configuration of REST service. + */ +@ConfigurationProperties(prefix = "org.eclipse.store.rest") +public class StoreDataRestServiceProperties { + /** + * Default base url of the REST service. + */ + public static final String DEFAULT_BASE_URL = "/store-data"; + + /** + * Flag controlling if REST service is enabled, defaults to false. + */ + private boolean enabled = false; + /** + * Base path of the REST service. Appended to the hostname and port this forms the URL to be entered in the Console Client app. + */ + private String baseUrl = DEFAULT_BASE_URL; // add validation rules to have a better feedback and IDE support. + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public String getBaseUrl() { + return baseUrl; + } + + public void setBaseUrl(String baseUrl) { + this.baseUrl = baseUrl; + } +} diff --git a/storage/rest/service-springboot/src/main/java/org/eclipse/store/storage/restservice/spring/boot/types/rest/RouteWithMethodsDto.java b/storage/rest/service-springboot/src/main/java/org/eclipse/store/storage/restservice/spring/boot/types/rest/RouteWithMethodsDto.java new file mode 100644 index 00000000..e4450305 --- /dev/null +++ b/storage/rest/service-springboot/src/main/java/org/eclipse/store/storage/restservice/spring/boot/types/rest/RouteWithMethodsDto.java @@ -0,0 +1,32 @@ +package org.eclipse.store.storage.restservice.spring.boot.types.rest; + +/*- + * #%L + * integrations-spring-boot3-console + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * DTO to expose available routes. + * @param url path + * @param httpMethod supported method. + */ +public record RouteWithMethodsDto( + @JsonProperty("URL") + String url, + @JsonProperty("HttpMethod") + String httpMethod +) { + +} + diff --git a/storage/rest/service-springboot/src/main/java/org/eclipse/store/storage/restservice/spring/boot/types/rest/StoreDataRestController.java b/storage/rest/service-springboot/src/main/java/org/eclipse/store/storage/restservice/spring/boot/types/rest/StoreDataRestController.java new file mode 100644 index 00000000..3ac3eef5 --- /dev/null +++ b/storage/rest/service-springboot/src/main/java/org/eclipse/store/storage/restservice/spring/boot/types/rest/StoreDataRestController.java @@ -0,0 +1,144 @@ +package org.eclipse.store.storage.restservice.spring.boot.types.rest; + +/*- + * #%L + * integrations-spring-boot3-console + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import jakarta.annotation.PostConstruct; +import org.eclipse.store.storage.restadapter.types.StorageRestAdapter; +import org.eclipse.store.storage.restadapter.types.ViewerObjectDescription; +import org.eclipse.store.storage.restadapter.types.ViewerRootDescription; +import org.eclipse.store.storage.restadapter.types.ViewerStorageFileStatistics; +import org.eclipse.store.storage.restservice.spring.boot.types.configuration.StoreDataRestServiceProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Stream; + +import static org.springframework.http.ResponseEntity.notFound; +import static org.springframework.http.ResponseEntity.ok; + +/** + * Spring REST controller exposing storage data for the restclient. + */ +@RestController +@RequestMapping(path = {"${org.eclipse.store.rest.base-url:#{T(org.eclipse.store.storage.restservice.spring.boot.types.configuration.StoreDataRestServiceProperties).DEFAULT_BASE_URL}}"}, produces = {MediaType.APPLICATION_JSON_VALUE}) +public class StoreDataRestController { + private final Map adapters; + private final StoreDataRestServiceProperties properties; + private final Logger logger = LoggerFactory.getLogger(StoreDataRestController.class); + + public StoreDataRestController( + Map adapters, + StoreDataRestServiceProperties properties + ) { + if (adapters.size() == 1 && adapters.containsKey("defaultStorageManager")) { + this.adapters = Map.of("default", adapters.get("defaultStorageManager")); + } else { + this.adapters = adapters; + } + this.properties = properties; + } + + @PostConstruct + public void validateSetup() { + Objects.requireNonNull(properties.getBaseUrl(), "Base URL must not be null. "); + adapters.keySet().forEach(adapter -> + logger.info("[ECLIPSE STORE REST SERVICE]: Configured storage adapter: '{}/{}/'", properties.getBaseUrl(), adapter) + ); + } + + @GetMapping(value = "/") + public ResponseEntity> getAvailableRoutes() { + var prefix = properties.getBaseUrl(); + var routes = new ArrayList(); + adapters.keySet().forEach(storageName -> + routes.addAll( + Stream.of( + new RouteWithMethodsDto(prefix + "/" + storageName + "/", HttpMethod.GET.name().toLowerCase()), + new RouteWithMethodsDto(prefix + "/" + storageName + "/root", HttpMethod.GET.name().toLowerCase()), + new RouteWithMethodsDto(prefix + "/" + storageName + "/dictionary", HttpMethod.GET.name().toLowerCase()), + new RouteWithMethodsDto(prefix + "/" + storageName + "/object/:oid", HttpMethod.GET.name().toLowerCase()), + new RouteWithMethodsDto(prefix + "/" + storageName + "/maintenance/filesStatistics", HttpMethod.GET.name().toLowerCase()) + ).toList() + ) + ); + return ok(routes); + } + + + @GetMapping(value = "/{storageName}/root") + public ResponseEntity getRoot(@PathVariable("storageName") String storageName) { + if (adapters.containsKey(storageName)) { + var root = adapters.get(storageName).getUserRoot(); + return ok(root); + } else { + return notFound().build(); + } + } + + @GetMapping(value = "/{storageName}/dictionary") + public ResponseEntity getDictionary(@PathVariable("storageName") String storageName) { + if (adapters.containsKey(storageName)) { + var dictionary = adapters.get(storageName).getTypeDictionary(); + return ok(dictionary); + } else { + return notFound().build(); + } + } + + @GetMapping("/{storageName}/object/{oid}") + public ResponseEntity getObject( + @PathVariable("storageName") String storageName, + @PathVariable(value = "oid") Long objectId, + @RequestParam(value = "valueLength", required = false) Long valueLength, + @RequestParam(value = "fixedOffset", required = false) Long fixedOffset, + @RequestParam(value = "fixedLength", required = false) Long fixedLength, + @RequestParam(value = "variableOffset", required = false) Long variableOffset, + @RequestParam(value = "variableLength", required = false) Long variableLength, + @RequestParam(value = "references", required = false) Boolean resolveReferences + ) { + if (adapters.containsKey(storageName)) { + var storageObject = adapters.get(storageName).getObject( + objectId, + fixedOffset != null ? fixedOffset : 0L, + fixedLength != null ? fixedLength : Long.MAX_VALUE, + variableOffset != null ? variableOffset : 0L, + variableLength != null ? variableLength : Long.MAX_VALUE, + valueLength != null ? valueLength : Long.MAX_VALUE, + resolveReferences != null ? resolveReferences : false + ); + return ok(storageObject); + } else { + return notFound().build(); + } + } + + @GetMapping("/{storageName}/maintenance/filesStatistics") + public ResponseEntity getFileStatistics(@PathVariable("storageName") String storageName) { + if (adapters.containsKey(storageName)) { + var stats = adapters.get(storageName).getStorageFilesStatistics(); + return ok(stats); + } else { + return notFound().build(); + } + } +} diff --git a/storage/rest/service-springboot/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/storage/rest/service-springboot/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..dc8677d8 --- /dev/null +++ b/storage/rest/service-springboot/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.eclipse.store.storage.restservice.spring.boot.types.StoreDataRestAutoConfiguration diff --git a/storage/rest/service-springboot/src/test/java/org/eclipse/store/storage/restservice/spring/boot/types/rest/RouteWithMethodsDtoSerializationTest.java b/storage/rest/service-springboot/src/test/java/org/eclipse/store/storage/restservice/spring/boot/types/rest/RouteWithMethodsDtoSerializationTest.java new file mode 100644 index 00000000..6b3e8b24 --- /dev/null +++ b/storage/rest/service-springboot/src/test/java/org/eclipse/store/storage/restservice/spring/boot/types/rest/RouteWithMethodsDtoSerializationTest.java @@ -0,0 +1,32 @@ +package org.eclipse.store.storage.restservice.spring.boot.types.rest; + +/*- + * #%L + * integrations-spring-boot3-console + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class RouteWithMethodsDtoSerializationTest { + + private final ObjectMapper mapper = new ObjectMapper(); + + @Test + public void should_serialize_correctly_applying_jackson_annotations() throws Exception { + var dto = new RouteWithMethodsDto("/path", "get"); + var json = mapper.writeValueAsString(dto); + assertThat(json).isEqualTo("{\"URL\":\"/path\",\"HttpMethod\":\"get\"}"); + } +} From cd7c6eeab698c6eb64fe59312090284acdb84e17 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Mon, 4 Mar 2024 14:15:21 +0100 Subject: [PATCH 080/126] 141 eclipse store cdi integration (#146) CDI4 Integration, based on MicroStream integration + Examples --- examples/pom.xml | 1 + examples/wildfly-cdi4/pom.xml | 129 ++++++++ examples/wildfly-cdi4/readme.md | 44 +++ .../examples/wildfly/HelloController.java | 33 ++ .../store/examples/wildfly/Inventory.java | 101 ++++++ .../store/examples/wildfly/Product.java | 109 +++++++ .../examples/wildfly/ProductController.java | 98 ++++++ .../examples/wildfly/ProductRepository.java | 33 ++ .../wildfly/ProductRepositoryStorage.java | 61 ++++ .../wildfly/ProductRestApplication.java | 28 ++ .../src/main/resources/META-INF/MANIFEST.MF | 1 + .../META-INF/microprofile-config.properties | 5 + .../main/resources/simplelogger.properties | 36 +++ .../src/main/webapp/WEB-INF/beans.xml | 6 + .../WEB-INF/jboss-deployment-structure.xml | 11 + .../wildfly-cdi4/src/main/webapp/index.html | 32 ++ .../cdi4/types/cache/StorageCacheTest.java | 79 +++++ integrations/cdi4/LICENSE | 277 ++++++++++++++++ integrations/cdi4/pom.xml | 128 ++++++++ .../cdi/ConfigurationCoreProperties.java | 303 ++++++++++++++++++ .../store/integrations/cdi/Storage.java | 47 +++ .../cdi/exceptions/CDIException.java | 47 +++ .../cdi/exceptions/CDIExceptionStorage.java | 30 ++ .../cdi/types/cache/CacheProperties.java | 268 ++++++++++++++++ .../cache/MutableConfigurationSupplier.java | 191 +++++++++++ .../cdi/types/cache/StorageCache.java | 43 +++ .../cdi/types/cache/StorageCacheProducer.java | 116 +++++++ .../cdi/types/cache/StorageCacheProperty.java | 123 +++++++ .../EmbeddedStorageFoundationCustomizer.java | 23 ++ .../types/config/StorageManagerConverter.java | 49 +++ .../config/StorageManagerInitializer.java | 23 ++ .../types/config/StorageManagerProducer.java | 122 +++++++ .../cdi/types/config/StorageManagerProxy.java | 284 ++++++++++++++++ .../cdi/types/extension/AbstractBean.java | 107 +++++++ .../cdi/types/extension/StorageBean.java | 146 +++++++++ .../cdi/types/extension/StorageExtension.java | 165 ++++++++++ .../src/main/resources/META-INF/beans.xml | 7 + .../jakarta.enterprise.inject.spi.Extension | 2 + ....eclipse.microprofile.config.spi.Converter | 1 + .../store/integrations/cdi/types/Agenda.java | 80 +++++ .../ConfigurationCorePropertiesTest.java | 195 +++++++++++ .../integrations/cdi/types/StorageTest.java | 81 +++++ .../cdi/types/cache/CacheProducerTest.java | 58 ++++ .../cdi/types/cache/CachePropertiesTest.java | 220 +++++++++++++ .../cdi/types/cache/MockCacheWriter.java | 28 ++ .../cdi/types/cache/MockExpiryPolicy.java | 30 ++ .../cdi/types/cache/MockLoaderFactory.java | 29 ++ .../types/cache/StorageCacheProducerTest.java | 74 +++++ .../cdi/types/cache/StorageCacheTest.java | 80 +++++ .../AbstractStorageManagerConverterTest.java | 86 +++++ .../StorageManagerConverterINITest.java | 72 +++++ ...StorageManagerConverterPropertiesTest.java | 67 ++++ .../config/StorageManagerConverterTest.java | 54 ++++ .../StorageManagerConverterXMLTest.java | 62 ++++ .../StorageManagerProducerCustomizerTest.java | 142 ++++++++ ...oducerFromConfigPropertyInjectionTest.java | 102 ++++++ ...geManagerProducerNoConfigPropertyTest.java | 125 ++++++++ .../StorageManagerProducerNotStartedTest.java | 135 ++++++++ ...meEmbeddedStorageFoundationCustomizer.java | 38 +++ .../test/SomeStorageManagerInitializer.java | 47 +++ .../cdi/types/extension/Animal.java | 23 ++ .../integrations/cdi/types/extension/Cat.java | 26 ++ .../types/extension/ConstructorUtilTest.java | 63 ++++ .../cdi/types/extension/Lion.java | 34 ++ .../cdi/types/extension/Tiger.java | 26 ++ .../cdi/types/logging/TestAppender.java | 55 ++++ .../src/test/resources/META-INF/beans.xml | 7 + .../META-INF/microprofile-config.properties | 11 + .../cdi4/src/test/resources/beans.xml | 8 + .../test/resources/junit-platform.properties | 1 + .../cdi4/src/test/resources/logback-test.xml | 15 + .../cdi4/src/test/resources/storage.ini | 3 + .../src/test/resources/storage.properties | 3 + .../cdi4/src/test/resources/storage.xml | 5 + integrations/pom.xml | 4 + 75 files changed, 5398 insertions(+) create mode 100644 examples/wildfly-cdi4/pom.xml create mode 100644 examples/wildfly-cdi4/readme.md create mode 100644 examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/HelloController.java create mode 100644 examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/Inventory.java create mode 100644 examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/Product.java create mode 100644 examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/ProductController.java create mode 100644 examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/ProductRepository.java create mode 100644 examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/ProductRepositoryStorage.java create mode 100644 examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/ProductRestApplication.java create mode 100644 examples/wildfly-cdi4/src/main/resources/META-INF/MANIFEST.MF create mode 100644 examples/wildfly-cdi4/src/main/resources/META-INF/microprofile-config.properties create mode 100644 examples/wildfly-cdi4/src/main/resources/simplelogger.properties create mode 100644 examples/wildfly-cdi4/src/main/webapp/WEB-INF/beans.xml create mode 100644 examples/wildfly-cdi4/src/main/webapp/WEB-INF/jboss-deployment-structure.xml create mode 100644 examples/wildfly-cdi4/src/main/webapp/index.html create mode 100644 integrations/cdi4-lite/src/test/java/org/eclipse/store/integrations/cdi4/types/cache/StorageCacheTest.java create mode 100644 integrations/cdi4/LICENSE create mode 100644 integrations/cdi4/pom.xml create mode 100644 integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/ConfigurationCoreProperties.java create mode 100644 integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/Storage.java create mode 100644 integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/exceptions/CDIException.java create mode 100644 integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/exceptions/CDIExceptionStorage.java create mode 100644 integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/CacheProperties.java create mode 100644 integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/MutableConfigurationSupplier.java create mode 100644 integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/StorageCache.java create mode 100644 integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/StorageCacheProducer.java create mode 100644 integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/StorageCacheProperty.java create mode 100644 integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/EmbeddedStorageFoundationCustomizer.java create mode 100644 integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverter.java create mode 100644 integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerInitializer.java create mode 100644 integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducer.java create mode 100644 integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProxy.java create mode 100644 integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/extension/AbstractBean.java create mode 100644 integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/extension/StorageBean.java create mode 100644 integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/extension/StorageExtension.java create mode 100644 integrations/cdi4/src/main/resources/META-INF/beans.xml create mode 100644 integrations/cdi4/src/main/resources/META-INF/services/jakarta.enterprise.inject.spi.Extension create mode 100644 integrations/cdi4/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.Converter create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/Agenda.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/ConfigurationCorePropertiesTest.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/StorageTest.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/CacheProducerTest.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/CachePropertiesTest.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/MockCacheWriter.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/MockExpiryPolicy.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/MockLoaderFactory.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/StorageCacheProducerTest.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/StorageCacheTest.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/AbstractStorageManagerConverterTest.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverterINITest.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverterPropertiesTest.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverterTest.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverterXMLTest.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducerCustomizerTest.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducerFromConfigPropertyInjectionTest.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducerNoConfigPropertyTest.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducerNotStartedTest.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/test/SomeEmbeddedStorageFoundationCustomizer.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/test/SomeStorageManagerInitializer.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/Animal.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/Cat.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/ConstructorUtilTest.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/Lion.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/Tiger.java create mode 100644 integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/logging/TestAppender.java create mode 100644 integrations/cdi4/src/test/resources/META-INF/beans.xml create mode 100644 integrations/cdi4/src/test/resources/META-INF/microprofile-config.properties create mode 100644 integrations/cdi4/src/test/resources/beans.xml create mode 100644 integrations/cdi4/src/test/resources/junit-platform.properties create mode 100644 integrations/cdi4/src/test/resources/logback-test.xml create mode 100644 integrations/cdi4/src/test/resources/storage.ini create mode 100644 integrations/cdi4/src/test/resources/storage.properties create mode 100644 integrations/cdi4/src/test/resources/storage.xml diff --git a/examples/pom.xml b/examples/pom.xml index e2efcb49..e3c2ae00 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -36,6 +36,7 @@ loading reloader storing + wildfly-cdi4 diff --git a/examples/wildfly-cdi4/pom.xml b/examples/wildfly-cdi4/pom.xml new file mode 100644 index 00000000..9a2f9f80 --- /dev/null +++ b/examples/wildfly-cdi4/pom.xml @@ -0,0 +1,129 @@ + + + + + 4.0.0 + + + org.eclipse.store + examples-parent + 1.2.0-SNAPSHOT + ../pom.xml + + + eclipse-store-examples-wildfly-cdi4 + EclipseStore Wildfly CDI 4 Example + https://projects.eclipse.org/projects/technology.store + + war + + 11 + 11 + 31.0.0.Final + false + wildfly-example + + + + org.eclipse.microprofile + microprofile + 5.0 + pom + provided + + + org.eclipse.store + eclipse-store-integrations-cdi4 + 1.2.0-SNAPSHOT + + + org.slf4j + slf4j-simple + 2.0.9 + + + jakarta.json.bind + jakarta.json.bind-api + 2.0.0 + + + jakarta.ws.rs + jakarta.ws.rs-api + 3.1.0 + compile + + + + + wildfly-example + + + org.apache.felix + maven-bundle-plugin + + true + + + + maven-war-plugin + 3.4.0 + + false + + + + + + + wildfly + + + + org.wildfly.plugins + wildfly-jar-maven-plugin + 10.0.0.Final + + + + package + + + + + wildfly@maven(org.jboss.universe:community-universe)#${version.wildfly} + + jaxrs + observability + + + deployment-scanner + + + + + + + + org.jboss.spec.javax.ws.rs + jboss-jaxrs-api_2.0_spec + 1.0.1.Final + provided + + + + + jboss-public-repository + JBoss Public Maven Repository Group + https://repository.jboss.org/nexus/content/groups/public/ + + + Red Hat GA + Red Hat GA + https://maven.repository.redhat.com/ga/ + + + + + diff --git a/examples/wildfly-cdi4/readme.md b/examples/wildfly-cdi4/readme.md new file mode 100644 index 00000000..aa6496ee --- /dev/null +++ b/examples/wildfly-cdi4/readme.md @@ -0,0 +1,44 @@ +# MicroProfile generated Application + +## Introduction + +MicroProfile Starter has generated this MicroProfile application for you. + +The generation of the executable jar file can be performed by issuing the following command + +```shell +mvn -Pwildfly clean package +``` +This will create an executable jar file **wildfly-example-bootable.jar** within the _target_ maven folder. This can be started by executing the following command + +```shell +java -jar target/wildfly-example-bootable.jar +``` + +To launch the test page, open your browser at the following URL + +```shell +http://localhost:8080/hello +``` +To execute the tests: + +```shell +curl --location --request POST 'http://localhost:8080/products/' \ +--header 'Content-Type: application/json' \ +--data-raw '{"id": 1, "name": "banana", "description": "a fruit", "rating": 5}' +``` +```shell +curl --location --request POST 'http://localhost:8080/products/' \ +--header 'Content-Type: application/json' \ +--data-raw '{"id": 2, "name": "watermelon", "description": "watermelon sugar ahh", "rating": 4}' +``` +```shell +curl --location --request GET 'http://localhost:8080/products/' +``` +```shell +curl --location --request GET 'http://localhost:8080/products/1' +``` +```shell +curl --location --request DELETE 'http://localhost:8080/products/1' +``` + diff --git a/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/HelloController.java b/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/HelloController.java new file mode 100644 index 00000000..b65ef9a1 --- /dev/null +++ b/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/HelloController.java @@ -0,0 +1,33 @@ +package org.eclipse.store.examples.wildfly; + +/*- + * #%L + * EclipseStore Wildfly CDI 4 Example + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + + + +import jakarta.inject.Singleton; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; + +@Path("/hello") +@Singleton +public class HelloController +{ + @GET + public String sayHello() + { + return "Hello World"; + } +} diff --git a/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/Inventory.java b/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/Inventory.java new file mode 100644 index 00000000..692e110a --- /dev/null +++ b/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/Inventory.java @@ -0,0 +1,101 @@ + +package org.eclipse.store.examples.wildfly; + +/*- + * #%L + * EclipseStore Wildfly CDI 4 Example + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + + + +import jakarta.inject.Inject; +import org.eclipse.serializer.persistence.types.Persister; +import org.eclipse.store.integrations.cdi.Storage; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.function.Predicate; + + +@Storage +public class Inventory +{ + // Methods lack proper locking to access this shared data structure safely in multi-threaded environment. + @Inject + private transient Persister persister; + + private final Set products = new HashSet<>(); + + public void add(final Product product) { + Objects.requireNonNull(product, "product is required"); + this.products.add(product); + this.persister.store(this.products); + } + + public Set getProducts() + { + return Collections.unmodifiableSet(this.products); + } + + public Optional findById(final long id) + { + return this.products.stream().filter(this.isIdEquals(id)).limit(1).findFirst(); + } + + public void deleteById(final long id) { + this.products.removeIf(this.isIdEquals(id)); + this.persister.store(this.products); + + } + + private Predicate isIdEquals(final long id) + { + return p -> p.getId() == id; + } + + @Override + public boolean equals(final Object o) + { + if(this == o) + { + return true; + } + if(o == null || this.getClass() != o.getClass()) + { + return false; + } + final Inventory inventory = (Inventory)o; + return Objects.equals(this.products, inventory.products); + } + + @Override + public int hashCode() + { + return Objects.hashCode(this.products); + } + + @Override + public String toString() + { + return "Inventory{" + + + "products=" + + this.products + + + '}'; + } + +} diff --git a/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/Product.java b/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/Product.java new file mode 100644 index 00000000..d6f934e6 --- /dev/null +++ b/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/Product.java @@ -0,0 +1,109 @@ + +package org.eclipse.store.examples.wildfly; + +/*- + * #%L + * EclipseStore Wildfly CDI 4 Example + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + + +import java.util.Objects; + +import jakarta.json.bind.annotation.JsonbCreator; +import jakarta.json.bind.annotation.JsonbProperty; + + +public class Product +{ + private final long id ; + private final String name ; + private final String description; + private final int rating ; + + @JsonbCreator + public Product( + @JsonbProperty("id") final long id , + @JsonbProperty("name") final String name , + @JsonbProperty("description") final String description, + @JsonbProperty("rating") final int rating + ) + { + this.id = id ; + this.name = name ; + this.description = description; + this.rating = rating ; + } + + public long getId() + { + return this.id; + } + + public String getName() + { + return this.name; + } + + public String getDescription() + { + return this.description; + } + + public int getRating() + { + return this.rating; + } + + @Override + public boolean equals(final Object o) + { + if(this == o) + { + return true; + } + if(o == null || this.getClass() != o.getClass()) + { + return false; + } + final Product product = (Product)o; + return this.id == product.id; + } + + @Override + public int hashCode() + { + return Objects.hashCode(this.id); + } + + @Override + public String toString() + { + return "Product{" + + + "id=" + + this.id + + + ", name='" + + this.name + + '\'' + + + ", description='" + + this.description + + '\'' + + + ", rating=" + + this.rating + + + '}'; + } +} diff --git a/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/ProductController.java b/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/ProductController.java new file mode 100644 index 00000000..54aaf448 --- /dev/null +++ b/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/ProductController.java @@ -0,0 +1,98 @@ + +package org.eclipse.store.examples.wildfly; + +/*- + * #%L + * EclipseStore Wildfly CDI 4 Example + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + + +import java.util.Collection; + + +import jakarta.enterprise.context.RequestScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; +import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; +import org.eclipse.microprofile.openapi.annotations.tags.Tag; + + +@RequestScoped +@Path("products") +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +public class ProductController +{ + @Inject + private ProductRepository repository; + + // TODO don't worried about pagination + @GET + @Operation(summary = "Get all products", description = "Returns all available items at the restaurant") + @APIResponse(responseCode = "500", description = "Server unavailable") + @APIResponse(responseCode = "200", description = "The products") + @Tag(name = "BETA", description = "This API is currently in beta state") + @APIResponse(description = "The products", responseCode = "200", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = Collection.class, readOnly = true, description = "the products", required = true, name = "products"))) + public Collection getAll() + { + return this.repository.getAll(); + } + + @GET + @Path("{id}") + @Operation(summary = "Find a product by id", description = "Find a product by id") + @APIResponse(responseCode = "200", description = "The product") + @APIResponse(responseCode = "404", description = "When the id does not exist") + @APIResponse(responseCode = "500", description = "Server unavailable") + @Tag(name = "BETA", description = "This API is currently in beta state") + @APIResponse(description = "The product", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = Product.class))) + public Product findById( + @Parameter(description = "The item ID", required = true, example = "1", schema = @Schema(type = SchemaType.INTEGER)) @PathParam("id") final long id) + { + return this.repository.findById(id).orElseThrow( + () -> new WebApplicationException("There is no product with the id " + id, Response.Status.NOT_FOUND)); + } + + @POST + @Operation(summary = "Insert a product", description = "Insert a product") + @APIResponse(responseCode = "201", description = "When creates an product") + @APIResponse(responseCode = "500", description = "Server unavailable") + @Tag(name = "BETA", description = "This API is currently in beta state") + public Response insert( + @RequestBody(description = "Create a new product.", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Product.class))) final Product product) + { + return Response.status(Response.Status.CREATED).entity(this.repository.save(product)).build(); + } + + @DELETE + @Path("{id}") + @Operation(summary = "Delete a product by ID", description = "Delete a product by ID") + @APIResponse(responseCode = "200", description = "When deletes the product") + @APIResponse(responseCode = "500", description = "Server unavailable") + @Tag(name = "BETA", description = "This API is currently in beta state") + public Response delete( + @Parameter(description = "The item ID", required = true, example = "1", schema = @Schema(type = SchemaType.INTEGER)) @PathParam("id") final long id) + { + this.repository.deleteById(id); + return Response.status(Response.Status.NO_CONTENT).build(); + } + +} diff --git a/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/ProductRepository.java b/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/ProductRepository.java new file mode 100644 index 00000000..0557b5a3 --- /dev/null +++ b/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/ProductRepository.java @@ -0,0 +1,33 @@ + +package org.eclipse.store.examples.wildfly; + +/*- + * #%L + * EclipseStore Wildfly CDI 4 Example + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + + +import java.util.Collection; +import java.util.Optional; + + +public interface ProductRepository +{ + Collection getAll(); + + Product save(Product item); + + Optional findById(long id); + + void deleteById(long id); +} diff --git a/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/ProductRepositoryStorage.java b/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/ProductRepositoryStorage.java new file mode 100644 index 00000000..87a66615 --- /dev/null +++ b/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/ProductRepositoryStorage.java @@ -0,0 +1,61 @@ + +package org.eclipse.store.examples.wildfly; + +/*- + * #%L + * EclipseStore Wildfly CDI 4 Example + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + + +import java.util.Collection; +import java.util.Optional; +import java.util.logging.Logger; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + + +@ApplicationScoped +public class ProductRepositoryStorage implements ProductRepository +{ + private static final Logger LOGGER = Logger.getLogger(ProductRepositoryStorage.class.getName()); + + @Inject + private Inventory inventory; + + @Override + public Collection getAll() + { + return this.inventory.getProducts(); + } + + @Override + public Product save(final Product item) + { + this.inventory.add(item); + return item; + } + + @Override + public Optional findById(final long id) + { + LOGGER.info("Finding the item by id: " + id); + return this.inventory.findById(id); + } + + @Override + public void deleteById(final long id) + { + this.inventory.deleteById(id); + } +} diff --git a/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/ProductRestApplication.java b/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/ProductRestApplication.java new file mode 100644 index 00000000..8e95be51 --- /dev/null +++ b/examples/wildfly-cdi4/src/main/java/org/eclipse/store/examples/wildfly/ProductRestApplication.java @@ -0,0 +1,28 @@ +package org.eclipse.store.examples.wildfly; + +/*- + * #%L + * EclipseStore Wildfly CDI 4 Example + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + + + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.core.Application; + +@ApplicationPath("/") +@ApplicationScoped +public class ProductRestApplication extends Application +{ +} diff --git a/examples/wildfly-cdi4/src/main/resources/META-INF/MANIFEST.MF b/examples/wildfly-cdi4/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 00000000..9d885be5 --- /dev/null +++ b/examples/wildfly-cdi4/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1 @@ +Manifest-Version: 1.0 diff --git a/examples/wildfly-cdi4/src/main/resources/META-INF/microprofile-config.properties b/examples/wildfly-cdi4/src/main/resources/META-INF/microprofile-config.properties new file mode 100644 index 00000000..95ed5324 --- /dev/null +++ b/examples/wildfly-cdi4/src/main/resources/META-INF/microprofile-config.properties @@ -0,0 +1,5 @@ + + +#Eclipse Store Configuration +org.eclipse.store.storage.directory=target/data +org.eclipse.store.channel.count=4 diff --git a/examples/wildfly-cdi4/src/main/resources/simplelogger.properties b/examples/wildfly-cdi4/src/main/resources/simplelogger.properties new file mode 100644 index 00000000..bcc93a91 --- /dev/null +++ b/examples/wildfly-cdi4/src/main/resources/simplelogger.properties @@ -0,0 +1,36 @@ +# SLF4J's SimpleLogger configuration file + # Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err. + + # Default logging detail level for all instances of SimpleLogger. + # Must be one of ("trace", "debug", "info", "warn", or "error"). + # If not specified, defaults to "info". +org.slf4j.simpleLogger.defaultLogLevel=trace + +org.slf4j.simpleLogger.log.org.eclipse.serializer.monitoring.MonitoringManager=warn + + # Logging detail level for a SimpleLogger instance named "xxxxx". + # Must be one of ("trace", "debug", "info", "warn", or "error"). + # If not specified, the default logging detail level is used. + #org.slf4j.simpleLogger.log.xxxxx= + + # Set to true if you want the current date and time to be included in output messages. + # Default is false, and will output the number of milliseconds elapsed since startup. +org.slf4j.simpleLogger.showDateTime=true + + # The date and time format to be used in the output messages. + # The pattern describing the date and time format is the same that is used in java.text.SimpleDateFormat. + # If the format is not specified or is invalid, the default format is used. + # The default format is yyyy-MM-dd HH:mm:ss:SSS Z. +org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS Z + + # Set to true if you want to output the current thread name. + # Defaults to true. +org.slf4j.simpleLogger.showThreadName=true + + # Set to true if you want the Logger instance name to be included in output messages. + # Defaults to true. +org.slf4j.simpleLogger.showLogName=true + + # Set to true if you want the last component of the name to be included in output messages. + # Defaults to false. +org.slf4j.simpleLogger.showShortLogName=true diff --git a/examples/wildfly-cdi4/src/main/webapp/WEB-INF/beans.xml b/examples/wildfly-cdi4/src/main/webapp/WEB-INF/beans.xml new file mode 100644 index 00000000..ba9b1015 --- /dev/null +++ b/examples/wildfly-cdi4/src/main/webapp/WEB-INF/beans.xml @@ -0,0 +1,6 @@ + + + diff --git a/examples/wildfly-cdi4/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/examples/wildfly-cdi4/src/main/webapp/WEB-INF/jboss-deployment-structure.xml new file mode 100644 index 00000000..edfb4170 --- /dev/null +++ b/examples/wildfly-cdi4/src/main/webapp/WEB-INF/jboss-deployment-structure.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/wildfly-cdi4/src/main/webapp/index.html b/examples/wildfly-cdi4/src/main/webapp/index.html new file mode 100644 index 00000000..6be631e8 --- /dev/null +++ b/examples/wildfly-cdi4/src/main/webapp/index.html @@ -0,0 +1,32 @@ + + + + + Eclipse MicroProfile demo + + + +

          MicroProfile

          + +Hello JAX-RS endpoint
          + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/integrations/cdi4-lite/src/test/java/org/eclipse/store/integrations/cdi4/types/cache/StorageCacheTest.java b/integrations/cdi4-lite/src/test/java/org/eclipse/store/integrations/cdi4/types/cache/StorageCacheTest.java new file mode 100644 index 00000000..626d9e23 --- /dev/null +++ b/integrations/cdi4-lite/src/test/java/org/eclipse/store/integrations/cdi4/types/cache/StorageCacheTest.java @@ -0,0 +1,79 @@ +package org.eclipse.store.integrations.cdi4.types.cache; + +/*- + * #%L + * Eclipse Store Integrations CDI 4 - lite + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import java.util.Optional; + +import io.smallrye.config.inject.ConfigExtension; +import jakarta.inject.Inject; +import javax.cache.Cache; +import org.eclipse.store.integrations.cdi4.ConfigurationCoreProperties; +import org.eclipse.store.integrations.cdi4.types.config.StorageManagerProducer; +import org.eclipse.store.integrations.cdi4.types.extension.StorageExtension; +import org.eclipse.store.integrations.cdi4.types.logging.TestLogger; +import org.eclipse.store.storage.types.Database; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.eclipse.store.storage.types.Databases; +import org.jboss.weld.junit5.auto.AddBeanClasses; +import org.jboss.weld.junit5.auto.AddExtensions; +import org.jboss.weld.junit5.auto.EnableAutoWeld; +import org.junit.jupiter.api.*; + +@EnableAutoWeld // So that Weld container is started +@AddBeanClasses({StorageCacheProducer.class, StorageManagerProducer.class}) // For @StorageCache +@AddExtensions({StorageExtension.class, ConfigExtension.class}) +// SmallRye Config extension And MicroStream extension for StorageManager +public class StorageCacheTest +{ + + @Inject + @StorageCache("storage") + private Cache cache; + + @BeforeAll + public static void beforeAll() + { + System.setProperty(CacheProperties.STORAGE.get(), Boolean.TRUE.toString()); + System.setProperty(ConfigurationCoreProperties.STORAGE_DIRECTORY.getMicroProfile(), "target/cache"); + TestLogger.reset(); + } + + @AfterAll + public static void afterAll() + { + System.clearProperty(CacheProperties.STORAGE.get()); + System.clearProperty(ConfigurationCoreProperties.STORAGE_DIRECTORY.getMicroProfile()); + } + + @AfterEach + public void cleanup() + { + // The @Disposes (calling StorageManager.shutdown) is not picked up by Weld-Unit, + // Need to shut down it here. + Databases databases = Databases.get(); + Database generic = databases.get("Generic"); + Optional.ofNullable(generic.storage()).ifPresent(StorageManager::shutdown); + } + + @Test + public void shouldCacheValues() + { + Assertions.assertNotNull(cache); + this.cache.put(1, "one"); + Assertions.assertNotNull(cache.get(1)); + } + +} diff --git a/integrations/cdi4/LICENSE b/integrations/cdi4/LICENSE new file mode 100644 index 00000000..d3087e4c --- /dev/null +++ b/integrations/cdi4/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. diff --git a/integrations/cdi4/pom.xml b/integrations/cdi4/pom.xml new file mode 100644 index 00000000..d9ad8991 --- /dev/null +++ b/integrations/cdi4/pom.xml @@ -0,0 +1,128 @@ + + 4.0.0 + + eclipse-store-integrations-cdi4 + + + org.eclipse.store + integrations + 1.2.0-SNAPSHOT + ../pom.xml + + + EclipseStore Integrations CDI 4 + EclipseStore CDI 4 Extension + + + + jakarta.enterprise + jakarta.enterprise.cdi-api + 4.0.1 + provided + + + javax.cache + cache-api + 1.1.1 + provided + + + org.eclipse.microprofile.config + microprofile-config-api + 3.1 + provided + + + + org.eclipse.store + storage-embedded + 1.2.0-SNAPSHOT + + + org.eclipse.store + storage-embedded-configuration + 1.2.0-SNAPSHOT + + + org.eclipse.serializer + configuration + ${eclipse.serializer.version} + + + org.eclipse.store + cache + 1.2.0-SNAPSHOT + + + + + io.smallrye.config + smallrye-config + 3.1.1 + test + + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.junit.jupiter + junit-jupiter-params + test + + + org.mockito + mockito-core + test + + + org.mockito + mockito-junit-jupiter + test + + + org.jboss.weld + weld-junit5 + 4.0.1.Final + test + + + org.slf4j + slf4j-api + 2.0.9 + + + ch.qos.logback + logback-classic + 1.4.14 + test + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + + true + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + + + --illegal-access=permit + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + diff --git a/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/ConfigurationCoreProperties.java b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/ConfigurationCoreProperties.java new file mode 100644 index 00000000..b5606a46 --- /dev/null +++ b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/ConfigurationCoreProperties.java @@ -0,0 +1,303 @@ + +package org.eclipse.store.integrations.cdi; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.microprofile.config.Config; +import org.eclipse.store.storage.embedded.configuration.types.EmbeddedStorageConfigurationPropertyNames; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.StreamSupport; + + +/** + * The relation with the properties from Eclipe Store docs: + * Configuration properties + */ +public enum ConfigurationCoreProperties +{ + /** + * The base directory of the storage in the file system. Default is "storage" in the working directory. + */ + STORAGE_DIRECTORY( + Constants.PREFIX + "storage.directory", + EmbeddedStorageConfigurationPropertyNames.STORAGE_DIRECTORY + ), + + /** + * The live file system configuration. See storage targets configuration. + */ + STORAGE_FILESYSTEM( + Constants.PREFIX + "storage.filesystem", + EmbeddedStorageConfigurationPropertyNames.STORAGE_FILESYSTEM + ), + + /** + * If configured, the storage will not delete files. Instead of deleting a file it will be moved to this directory. + */ + DELETION_DIRECTORY( + Constants.PREFIX + "deletion.directory", + EmbeddedStorageConfigurationPropertyNames.DELETION_DIRECTORY + ), + + /** + * If configured, files that will get truncated are copied into this directory. + */ + TRUNCATION_DIRECTORY( + Constants.PREFIX + "truncation.directory", + EmbeddedStorageConfigurationPropertyNames.TRUNCATION_DIRECTORY + ), + + /** + * The backup directory. + */ + BACKUP_DIRECTORY( + Constants.PREFIX + "backup.directory", + EmbeddedStorageConfigurationPropertyNames.BACKUP_DIRECTORY + ), + + /** + * The backup file system configuration. See storage targets configuration. + */ + BACKUP_FILESYSTEM( + Constants.PREFIX + "backup.filesystem", + EmbeddedStorageConfigurationPropertyNames.BACKUP_FILESYSTEM + ), + + /** + * The number of threads and number of directories used by the storage engine. Every thread has exclusive access + * to its directory. Default is 1. + */ + CHANNEL_COUNT( + Constants.PREFIX + "channel.count", + EmbeddedStorageConfigurationPropertyNames.CHANNEL_COUNT + ), + + /** + * Name prefix of the subdirectories used by the channel threads. Default is "channel_". + */ + CHANNEL_DIRECTORY_PREFIX( + Constants.PREFIX + "channel.directory.prefix", + EmbeddedStorageConfigurationPropertyNames.CHANNEL_DIRECTORY_PREFIX + ), + + /** + * Name prefix of the storage files. Default is "channel_". + */ + DATA_FILE_PREFIX( + Constants.PREFIX + "data.file.prefix", + EmbeddedStorageConfigurationPropertyNames.DATA_FILE_PREFIX + ), + + /** + * Name suffix of the storage files. Default is ".dat". + */ + DATA_FILE_SUFFIX( + Constants.PREFIX + "data.file.suffix", + EmbeddedStorageConfigurationPropertyNames.DATA_FILE_SUFFIX + ), + + /** + * Name prefix of the storage transaction file. Default is "transactions_". + */ + TRANSACTION_FILE_PREFIX( + Constants.PREFIX + "transaction.file.prefix", + EmbeddedStorageConfigurationPropertyNames.TRANSACTION_FILE_PREFIX + ), + + /** + * Name suffix of the storage transaction file. Default is ".sft". + */ + TRANSACTION_FILE_SUFFIX( + Constants.PREFIX + "transaction.file.suffix", + EmbeddedStorageConfigurationPropertyNames.TRANSACTION_FILE_SUFFIX + ), + + /** + * The name of the dictionary file. Default is "PersistenceTypeDictionary.ptd". + */ + TYPE_DICTIONARY_FILE_NAME( + Constants.PREFIX + "type.dictionary.file.name", + EmbeddedStorageConfigurationPropertyNames.TYPE_DICTIONARY_FILE_NAME + ), + + /** + * Name suffix of the storage rescue files. Default is ".bak". + */ + RESCUED_FILE_SUFFIX( + Constants.PREFIX + "rescued.file.suffix", + EmbeddedStorageConfigurationPropertyNames.RESCUED_FILE_SUFFIX + ), + + /** + * Name of the lock file. Default is "used.lock". + */ + LOCK_FILE_NAME( + Constants.PREFIX + "lock.file.name", + EmbeddedStorageConfigurationPropertyNames.LOCK_FILE_NAME + ), + + /** + * Interval for the housekeeping. This is work like garbage collection or cache checking. In combination with + * houseKeepingNanoTimeBudget the maximum processor time for housekeeping work can be set. Default is 1 second. + */ + HOUSEKEEPING_INTERVAL( + Constants.PREFIX + "housekeeping.interval", + EmbeddedStorageConfigurationPropertyNames.HOUSEKEEPING_INTERVAL + ), + + /** + * Number of nanoseconds used for each housekeeping cycle. Default is 10 milliseconds = 0.01 seconds. + */ + HOUSEKEEPING_TIME_BUDGET( + Constants.PREFIX + "housekeeping.time.budget", + EmbeddedStorageConfigurationPropertyNames.HOUSEKEEPING_TIME_BUDGET + ), + + /** + * Abstract threshold value for the lifetime of entities in the cache. Default is 1000000000. + */ + ENTITY_CACHE_THRESHOLD( + Constants.PREFIX + "entity.cache.threshold", + EmbeddedStorageConfigurationPropertyNames.ENTITY_CACHE_THRESHOLD + ), + + /** + * Timeout in milliseconds for the entity cache evaluator. If an entity wasn’t + * accessed in this timespan it will be removed from the cache. Default is 1 day. + */ + ENTITY_CACHE_TIMEOUT( + Constants.PREFIX + "entity.cache.timeout", + EmbeddedStorageConfigurationPropertyNames.ENTITY_CACHE_TIMEOUT + ), + + /** + * Minimum file size for a data file to avoid cleaning it up. Default is 1024^2 = 1 MiB. + */ + DATA_FILE_MINIMUM_SIZE( + Constants.PREFIX + "data.file.minimum.size", + EmbeddedStorageConfigurationPropertyNames.DATA_FILE_MINIMUM_SIZE + ), + + /** + * Maximum file size for a data file to avoid cleaning it up. Default is 1024^2*8 = 8 MiB. + */ + DATA_FILE_MAXIMUM_SIZE( + Constants.PREFIX + "data.file.maximum.size", + EmbeddedStorageConfigurationPropertyNames.DATA_FILE_MAXIMUM_SIZE + ), + + /** + * The ratio (value in ]0.0;1.0]) of non-gap data contained in a storage file to prevent the file from being + * dissolved. Default is 0.75 (75%). + */ + DATA_FILE_MINIMUM_USE_RATIO( + Constants.PREFIX + "data.file.minimum.use.ratio", + EmbeddedStorageConfigurationPropertyNames.DATA_FILE_MINIMUM_USE_RATIO + ), + + /** + * A flag defining whether the current head file (the only file actively written to) + * shall be subjected to file cleanups as well. + */ + DATA_FILE_CLEANUP_HEAD_FILE( + Constants.PREFIX + "data.file.cleanup.head.file", + EmbeddedStorageConfigurationPropertyNames.DATA_FILE_CLEANUP_HEAD_FILE + ); + + private final String microProfile; + private final String eclipseStore; + + ConfigurationCoreProperties(final String microProfile, final String eclipseStore) + { + this.microProfile = microProfile; + this.eclipseStore = eclipseStore; + } + + public String getMicroProfile() + { + return this.microProfile; + } + + /** + * Returns the corresponding EclipseStore version of the config key. It replaces the MicroProfile part + * with the EclipseStore part. So the keys can be 'longer' as the value defined in the enum. A typical + * example is the 'storage filesystem' element. + * @param key The Key as defined in MicroProfile config + * @return The corresponding EclipseStore version of this key. + */ + public String getEclipseStore(final String key) + { + return key.replaceAll(this.microProfile, this.eclipseStore); + } + + /** + * Returns the {@code ConfigurationCoreProperties} enum entry that corresponds with the + * MicroProfile config key value. Optional.empty() when no matching entry is found. + * + * @param value The MicroProfile config key value to look for. + * @return The enum entry if there is a matching entry or {@code Optional.empty()} + */ + public static Optional get(final String value) + { + Objects.requireNonNull(value); + return Arrays.stream(ConfigurationCoreProperties.values()) + .filter(ccp -> value.startsWith(ccp.getMicroProfile())) + .findAny(); + } + + + public static Map getProperties(final Config config) + { + + final Map properties = new HashMap<>(); + + StreamSupport.stream(config.getPropertyNames() + .spliterator(), false) + .filter(n -> n.startsWith(Constants.PREFIX)) + .forEach(p -> addProperty(config, properties, p)); + + return properties; + } + + private static String asEclipseStoreConfigName(final String name) + { + final Optional coreProperty = ConfigurationCoreProperties.get(name); + return coreProperty.isEmpty() + ? name.substring(Constants.PREFIX.length()) + : coreProperty.get() + .getEclipseStore(name); + } + + private static void addProperty( + final Config config, + final Map properties, + final String configName + ) + { + config.getOptionalValue(configName, String.class) + .ifPresent(v -> properties.put(ConfigurationCoreProperties.asEclipseStoreConfigName(configName), v)) + ; + } + + public static class Constants + { + public static final String PREFIX = "org.eclipse.store."; + } +} diff --git a/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/Storage.java b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/Storage.java new file mode 100644 index 00000000..a5ffdc1d --- /dev/null +++ b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/Storage.java @@ -0,0 +1,47 @@ + +package org.eclipse.store.integrations.cdi; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import jakarta.enterprise.inject.Alternative; +import jakarta.enterprise.inject.Stereotype; + + +/** + * The Storage class in MicroStream indicates a class as a root instance. + * Object instances can be stored as simple records. + * One value after another as a trivial byte stream. + * References between objects are mapped with unique numbers, called ObjectId, or short OID. + With both combined, + * byte streams and OIDs, an object graph can be stored in a simple and quick way, + * as well as loaded, as a whole or partially. + * Ref: Root instances + *

          + * Each application must have a unique class with this annotation. + * Note: To increase performance use immutable sub-graphs as often as possible. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE}) +@Stereotype +@Alternative +public @interface Storage +{ + // marker annotation +} diff --git a/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/exceptions/CDIException.java b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/exceptions/CDIException.java new file mode 100644 index 00000000..8c489518 --- /dev/null +++ b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/exceptions/CDIException.java @@ -0,0 +1,47 @@ +package org.eclipse.store.integrations.cdi.exceptions; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import org.eclipse.serializer.exceptions.BaseException; + +public class CDIException extends BaseException +{ + public CDIException() + { + super(); + } + + public CDIException(final String message, final Throwable cause, final boolean enableSuppression, final boolean writableStackTrace) + { + super(message, cause, enableSuppression, writableStackTrace); + } + + public CDIException(final String message, final Throwable cause) + { + super(message, cause); + } + + public CDIException(final String message) + { + super(message); + } + + public CDIException(final Throwable cause) + { + super(cause); + } + +} diff --git a/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/exceptions/CDIExceptionStorage.java b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/exceptions/CDIExceptionStorage.java new file mode 100644 index 00000000..e3d12da9 --- /dev/null +++ b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/exceptions/CDIExceptionStorage.java @@ -0,0 +1,30 @@ + +package org.eclipse.store.integrations.cdi.exceptions; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class CDIExceptionStorage extends CDIException +{ + private static final String MESSAGE = "There is an incompatibility between the entity and the" + + " current root in the StorageManager. Please check the compatibility. " + + "Entity: %s and current root class %s"; + + + + public CDIExceptionStorage(final Class entity, final Class root) + { + super(String.format(MESSAGE, entity, root)); + } +} diff --git a/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/CacheProperties.java b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/CacheProperties.java new file mode 100644 index 00000000..8b8b9ec4 --- /dev/null +++ b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/CacheProperties.java @@ -0,0 +1,268 @@ + +package org.eclipse.store.integrations.cdi.types.cache; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import java.util.Objects; +import java.util.function.Supplier; + +import javax.cache.configuration.Factory; +import javax.cache.expiry.ExpiryPolicy; +import javax.cache.integration.CacheLoader; +import javax.cache.integration.CacheWriter; + +import org.eclipse.microprofile.config.Config; +import org.eclipse.serializer.reflect.XReflect; + + +/** + * The relation with the properties from EclipseStore Cache docs: + * Configuration properties + */ +public enum CacheProperties implements Supplier +{ + PREFIX("org.eclipse.store."), + /** + * cacheLoaderFactory - A CacheLoader should be configured + * for "Read Through" caches to load values when a cache miss occurs. + */ + CACHE_LOADER_FACTORY(PREFIX.get() + "cache.loader.factory"), + /** + * cacheWriterFactory - A CacheWriter is used for write-through to an external resource. + */ + CACHE_WRITER_FACTORY(PREFIX.get() + "cache.writer.factory"), + /** + * expiryPolicyFactory - Determines when cache entries will expire based on creation, + * access and modification operations. + */ + CACHE_EXPIRES_FACTORY(PREFIX.get() + "cache.expires.factory"), + /** + * readThrough - When in "read-through" mode, cache misses that occur due to cache entries not existing + * as a result of performing a "get" will appropriately cause the configured CacheLoader to be invoked. + */ + CACHE_READ_THROUGH(PREFIX.get() + "cache.read.through"), + /** + * writeThrough - When in "write-through" mode, cache updates that occur as a result + * of performing "put" operations will appropriately cause the configured CacheWriter to be invoked. + */ + CACHE_WRITE_THROUGH(PREFIX.get() + "cache.write.through"), + /** + * storeByValue - When a cache is storeByValue, + * any mutation to the key or value does not affect the key of value stored in the cache. + */ + CACHE_STORE_VALUE(PREFIX.get() + "cache.store.value"), + /** + * statisticsEnabled - Checks whether statistics collection is enabled in this cache. + */ + CACHE_STATISTICS(PREFIX.get() + "cache.statistics"), + /** + * managementEnabled - Checks whether management is enabled on this cache. + */ + CACHE_MANAGEMENT(PREFIX.get() + "cache.management"), + /** + * EclipseStore’s storage can be used as a backing store for the cache. + * It functions as a CacheWriter as well as a CacheReader, depending on the writeThrough + * and readThrough configuration. Per default, it is used for both. + */ + STORAGE(PREFIX.get() + "store"); + + private final String value; + + CacheProperties(final String value) + { + this.value = value; + } + + /** + * Loads the properties {@link CacheProperties#CACHE_STORE_VALUE} from {@link Config} + * the respective value; it will return false by default. + * + * @param config + * the Eclipse Microprofile instance + * @return the properties from {@link Config} or false + * @throws NullPointerException + * when config is null + */ + static boolean isStoreByValue(final Config config) + { + return getBoolean(config, CACHE_STORE_VALUE); + } + + /** + * Loads the properties {@link CacheProperties#CACHE_WRITE_THROUGH} from {@link Config} + * the respective value; it will return false by default. + * + * @param config + * the Eclipse Microprofile instance + * @return the properties from {@link Config} or false + * @throws NullPointerException + * when config is null + */ + static boolean isWriteThrough(final Config config) + { + return getBoolean(config, CACHE_WRITE_THROUGH); + } + + /** + * Loads the properties {@link CacheProperties#CACHE_READ_THROUGH} from {@link Config} + * the respective value; it will return false by default. + * + * @param config + * the Eclipse Microprofile instance + * @return the properties from {@link Config} or false + * @throws NullPointerException + * when config is null + */ + static boolean isReadThrough(final Config config) + { + return getBoolean(config, CACHE_READ_THROUGH); + } + + /** + * Loads the properties {@link CacheProperties#CACHE_MANAGEMENT} from {@link Config} + * the respective value; it will return false by default. + * + * @param config + * the Eclipse Microprofile instance + * @return the properties from {@link Config} or false + * @throws NullPointerException + * when config is null + */ + static boolean isManagementEnabled(final Config config) + { + return getBoolean(config, CACHE_MANAGEMENT); + } + + /** + * Loads the properties {@link CacheProperties#CACHE_STATISTICS} from {@link Config} + * the respective value; it will return false by default. + * + * @param config + * the Eclipse Microprofile instance + * @return the properties from {@link Config} or false + * @throws NullPointerException + * when config is null + */ + static boolean isStatisticsEnabled(final Config config) + { + return getBoolean(config, CACHE_STATISTICS); + } + + /** + * EclipseStore’s storage can be used as a backing store for the cache. + * + * @param config + * the Eclipse Microprofile instance + * @return the properties from {@link Config} or false + * @throws NullPointerException + * when config is null + */ + static boolean isStorage(final Config config) + { + return getBoolean(config, STORAGE); + } + + /** + * Loads the properties {@link CacheProperties#CACHE_LOADER_FACTORY} from {@link Config} + * the respective value + * + * @param config + * the Eclipse Microprofile instance + * @return the Factory from {@link Config} or null + * @throws NullPointerException + * when config is null + */ + static Factory> getLoaderFactory(final Config config) + { + Objects.requireNonNull(config, "Config is required"); + final String factoryClass = config.getOptionalValue(CACHE_LOADER_FACTORY.get(), String.class).orElse(""); + return getFactoryClass(factoryClass); + } + + /** + * Loads the properties {@link CacheProperties#CACHE_WRITER_FACTORY} from {@link Config} + * the respective value + * + * @param config + * the Eclipse Microprofile instance + * @return the Factory from {@link Config} or null + * @throws NullPointerException + * when config is null + */ + static Factory> getWriterFactory(final Config config) + { + Objects.requireNonNull(config, "Config is required"); + final String factoryClass = config.getOptionalValue(CACHE_WRITER_FACTORY.get(), String.class).orElse(""); + return getFactoryClass(factoryClass); + } + + /** + * Loads the properties {@link CacheProperties#CACHE_EXPIRES_FACTORY} from {@link Config} + * the respective value + * + * @param config + * the Eclipse Microprofile instance + * @return the Factory from {@link Config} or null + * @throws NullPointerException + * when config is null + */ + static Factory getExpiryFactory(final Config config) + { + Objects.requireNonNull(config, "Config is required"); + final String factoryClass = config.getOptionalValue(CACHE_EXPIRES_FACTORY.get(), String.class).orElse(""); + + return getFactoryClass(factoryClass); + } + + private static Boolean getBoolean(final Config config, final CacheProperties cacheStatistics) + { + Objects.requireNonNull(config, "Config is required"); + return config.getOptionalValue(cacheStatistics.get(), boolean.class).orElse(false); + } + + @SuppressWarnings("unchecked") + private static T getFactoryClass(final String className) + { + if(className.isBlank()) + { + return null; + } + try + { + final Class factory = (Class)Class.forName(className); + final T instance = XReflect.defaultInstantiate(factory); + if(instance instanceof Factory) + { + return instance; + } + throw new IllegalArgumentException( + "The instance class must be a " + + Factory.class.getName() + + " implementation, please check the class: " + + className); + } + catch(final ClassNotFoundException e) + { + throw new RuntimeException(e); + } + } + + @Override + public String get() + { + return this.value; + } +} diff --git a/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/MutableConfigurationSupplier.java b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/MutableConfigurationSupplier.java new file mode 100644 index 00000000..642af20f --- /dev/null +++ b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/MutableConfigurationSupplier.java @@ -0,0 +1,191 @@ + +package org.eclipse.store.integrations.cdi.types.cache; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.Objects; +import java.util.function.Supplier; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.cache.configuration.Factory; +import javax.cache.configuration.MutableConfiguration; +import javax.cache.expiry.ExpiryPolicy; +import javax.cache.integration.CacheLoader; +import javax.cache.integration.CacheWriter; + +import org.eclipse.microprofile.config.Config; + +import jakarta.enterprise.inject.Instance; +import org.eclipse.store.cache.types.CacheStore; +import org.eclipse.store.storage.types.StorageManager; + + +/** + * Create a Parser to explore the benefits of Eclipse MicroProfile Configuration. + * + * @param + * the key type in the cache + * @param + * the value type in the cache + */ +class MutableConfigurationSupplier implements Supplier> +{ + private static final Logger LOGGER = Logger.getLogger(MutableConfigurationSupplier.class.getName()); + + private final StorageCacheProperty cacheProperty ; + private final boolean storeByValue ; + private final boolean writeThrough ; + private final boolean readThrough ; + private final boolean managementEnabled; + private final boolean statisticsEnabled; + private final boolean storage ; + private final Factory> loaderFactory ; + private final Factory> writerFactory ; + private final Factory expiryFactory ; + + private final Instance storageManager; + + private MutableConfigurationSupplier( + final StorageCacheProperty cacheProperty , + final boolean storeByValue , + final boolean writeThrough , + final boolean readThrough , + final boolean managementEnabled, + final boolean statisticsEnabled, + final boolean storage , + final Factory> loaderFactory , + final Factory> writerFactory , + final Factory expiryFactory , + final Instance storageManager + ) + { + this.cacheProperty = cacheProperty ; + this.storeByValue = storeByValue ; + this.writeThrough = writeThrough ; + this.readThrough = readThrough ; + this.managementEnabled = managementEnabled; + this.statisticsEnabled = statisticsEnabled; + this.loaderFactory = loaderFactory ; + this.writerFactory = writerFactory ; + this.expiryFactory = expiryFactory ; + this.storage = storage ; + this.storageManager = storageManager ; + } + + public static MutableConfigurationSupplier of( + final StorageCacheProperty cacheProperty, + final Config config, + final Instance storageManager) + { + final boolean storeByValue = CacheProperties.isStoreByValue(config); + final boolean writeThrough = CacheProperties.isWriteThrough(config); + final boolean readThrough = CacheProperties.isReadThrough(config); + final boolean managementEnabled = CacheProperties.isManagementEnabled(config); + final boolean statisticsEnabled = CacheProperties.isStatisticsEnabled(config); + final boolean storage = CacheProperties.isStorage(config); + final Factory> loaderFactory = CacheProperties.getLoaderFactory(config); + final Factory> writerFactory = CacheProperties.getWriterFactory(config); + final Factory expiryFactory = CacheProperties.getExpiryFactory(config); + + return new MutableConfigurationSupplier<>( + cacheProperty, + storeByValue, + writeThrough, + readThrough, + managementEnabled, + statisticsEnabled, + storage, + loaderFactory, + writerFactory, + expiryFactory, + storageManager); + } + + @Override + public MutableConfiguration get() + { + final Class key = this.cacheProperty.getKey(); + final Class value = this.cacheProperty.getValue(); + final MutableConfiguration configuration = new MutableConfiguration<>(); + configuration.setTypes(key, value); + configuration.setStoreByValue(this.storeByValue).setWriteThrough(this.writeThrough).setReadThrough( + this.readThrough).setManagementEnabled(this.managementEnabled).setStatisticsEnabled(this.statisticsEnabled); + + if(Objects.nonNull(this.loaderFactory)) + { + configuration.setCacheLoaderFactory(this.loaderFactory); + } + if(Objects.nonNull(this.writerFactory)) + { + configuration.setCacheWriterFactory(this.writerFactory); + } + if(Objects.nonNull(this.expiryFactory)) + { + configuration.setExpiryPolicyFactory(this.expiryFactory); + } + if(this.storage) + { + LOGGER.log(Level.FINE, "Using the storage option to this cache, so it will enable write and read through"); + final StorageManager storageManager = this.storageManager.get(); + final CacheStore cacheStore = CacheStore.New(this.cacheProperty.getName(),storageManager); + configuration.setCacheLoaderFactory(() -> cacheStore); + configuration.setCacheWriterFactory(() -> cacheStore); + configuration.setWriteThrough(true); + configuration.setReadThrough(true); + + } + return configuration; + } + + @Override + public String toString() + { + return "MutableConfigurationSupplier{" + + + "cacheProperty=" + + this.cacheProperty + + + ", storeByValue=" + + this.storeByValue + + + ", writeThrough=" + + this.writeThrough + + + ", readThrough=" + + this.readThrough + + + ", managementEnabled=" + + this.managementEnabled + + + ", statisticsEnabled=" + + this.statisticsEnabled + + + ", storage=" + + this.storage + + + ", loaderFactory=" + + this.loaderFactory + + + ", writerFactory=" + + this.writerFactory + + + ", expiryFactory=" + + this.expiryFactory + + + '}'; + } + +} diff --git a/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/StorageCache.java b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/StorageCache.java new file mode 100644 index 00000000..84fde064 --- /dev/null +++ b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/StorageCache.java @@ -0,0 +1,43 @@ + +package org.eclipse.store.integrations.cdi.types.cache; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import jakarta.enterprise.util.Nonbinding; +import jakarta.inject.Qualifier; + + +/** + * Defines a cache managed by EclipseStore: + * Getting started for Cache + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Qualifier +public @interface StorageCache +{ + /** + * the name of the managed {@link javax.cache.Cache} to acquire. + * + * @return the cache name + */ + @Nonbinding + String value() default "jcache"; +} diff --git a/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/StorageCacheProducer.java b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/StorageCacheProducer.java new file mode 100644 index 00000000..b8872a71 --- /dev/null +++ b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/StorageCacheProducer.java @@ -0,0 +1,116 @@ + +package org.eclipse.store.integrations.cdi.types.cache; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.util.Objects; +import java.util.logging.Logger; + +import javax.cache.Cache; +import javax.cache.CacheManager; +import javax.cache.Caching; +import javax.cache.configuration.MutableConfiguration; +import javax.cache.spi.CachingProvider; + +import org.eclipse.microprofile.config.Config; + +import jakarta.annotation.PostConstruct; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Disposes; +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.Produces; +import jakarta.enterprise.inject.spi.InjectionPoint; +import jakarta.inject.Inject; +import org.eclipse.store.storage.types.StorageManager; + + +@ApplicationScoped +class StorageCacheProducer +{ + private static final Logger LOGGER = Logger.getLogger(StorageCacheProducer.class.getName()); + + private static final String CACHE_PROVIDER = "org.eclipse.store.cache.types.CachingProvider"; + + private CachingProvider provider; + + private CacheManager cacheManager; + + @Inject + private Config config; + + @Inject + private Instance storageManager; + + @PostConstruct + void setUp() + { + this.provider = Caching.getCachingProvider(CACHE_PROVIDER); + this.cacheManager = this.provider.getCacheManager(); + } + + @Produces + @StorageCache + @ApplicationScoped + CachingProvider getProvider() + { + return this.provider; + } + + @Produces + @StorageCache + @ApplicationScoped + CacheManager getManager() + { + return this.cacheManager; + } + + @SuppressWarnings("resource") + @Produces + @StorageCache + public Cache producer(final InjectionPoint injectionPoint) + { + final StorageCacheProperty cacheProperty = StorageCacheProperty.of(injectionPoint); + final String name = cacheProperty.getName(); + final Class key = cacheProperty.getKey(); + final Class value = cacheProperty.getValue(); + + LOGGER.info("Loading cache: " + name + " the current caches: " + this.cacheManager.getCacheNames()); + + Cache cache; + if(Objects.isNull(this.cacheManager.getCache(name, key, value))) + { + final MutableConfigurationSupplier supplier = + MutableConfigurationSupplier.of(cacheProperty, this.config, this.storageManager); + LOGGER.info("Cache " + name + " does not exist. Creating with configuration: " + supplier); + final MutableConfiguration configuration = supplier.get(); + cache = this.cacheManager.createCache(name, configuration); + } + else + { + cache = this.cacheManager.getCache(name); + } + return cache; + } + + public void close(@Disposes @StorageCache final CachingProvider provider) + { + provider.close(); + } + + public void close(@Disposes @StorageCache final CacheManager manager) + { + manager.close(); + } +} diff --git a/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/StorageCacheProperty.java b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/StorageCacheProperty.java new file mode 100644 index 00000000..f8c93016 --- /dev/null +++ b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/cache/StorageCacheProperty.java @@ -0,0 +1,123 @@ + +package org.eclipse.store.integrations.cdi.types.cache; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Objects; + +import jakarta.enterprise.inject.spi.Annotated; +import jakarta.enterprise.inject.spi.InjectionPoint; + + +/** + * Load info the belongs to the {@link StorageCache} annotation. + * + * @param + * the key property + * @param + * the value property + */ +class StorageCacheProperty +{ + private final Class key; + + private final Class value; + + private final String name; + + private StorageCacheProperty(final Class key, final Class value, final String name) + { + this.key = key; + this.value = value; + this.name = name; + } + + public Class getKey() + { + return this.key; + } + + public Class getValue() + { + return this.value; + } + + public String getName() + { + return this.name; + } + + @Override + public boolean equals(final Object o) + { + if(this == o) + { + return true; + } + if(o == null || this.getClass() != o.getClass()) + { + return false; + } + final StorageCacheProperty that = (StorageCacheProperty)o; + return Objects.equals(this.key, that.key) && Objects.equals(this.value, that.value) && Objects.equals(this.name, that.name); + } + + @Override + public int hashCode() + { + return Objects.hash(this.key, this.value, this.name); + } + + @Override + public String toString() + { + return "StorageCacheProperty{" + + + "key=" + + this.key + + + ", value=" + + this.value + + + ", name='" + + this.name + + '\'' + + + '}'; + } + + @SuppressWarnings("unchecked") + public static StorageCacheProperty of(final InjectionPoint injectionPoint) + { + final Annotated annotated = injectionPoint.getAnnotated(); + final StorageCache storageCache = annotated.getAnnotation(StorageCache.class); + final String cacheName = storageCache.value(); + final Member member = injectionPoint.getMember(); + if(member instanceof Field) + { + final Field field = (Field)member; + final ParameterizedType genericType = (ParameterizedType)field.getGenericType(); + final Type[] arguments = genericType.getActualTypeArguments(); + final Class key = (Class)arguments[0]; + final Class value = (Class)arguments[1]; + return new StorageCacheProperty<>(key, value, cacheName); + } + throw new IllegalArgumentException(""); + } +} diff --git a/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/EmbeddedStorageFoundationCustomizer.java b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/EmbeddedStorageFoundationCustomizer.java new file mode 100644 index 00000000..f6597a6a --- /dev/null +++ b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/EmbeddedStorageFoundationCustomizer.java @@ -0,0 +1,23 @@ +package org.eclipse.store.integrations.cdi.types.config; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; + +public interface EmbeddedStorageFoundationCustomizer +{ + void customize(final EmbeddedStorageFoundation embeddedStorageFoundation); +} diff --git a/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverter.java b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverter.java new file mode 100644 index 00000000..ace0c398 --- /dev/null +++ b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverter.java @@ -0,0 +1,49 @@ + +package org.eclipse.store.integrations.cdi.types.config; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.microprofile.config.spi.Converter; +import org.eclipse.store.storage.types.StorageManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + + +/** + * A Config converter to {@link StorageManager} + */ +public class StorageManagerConverter implements Converter +{ + private static final Logger LOGGER = LoggerFactory.getLogger(StorageManagerConverter.class); + + private static final Map MAP = new ConcurrentHashMap<>(); + + @Override + public StorageManager convert(final String value) throws IllegalArgumentException, NullPointerException + { + return MAP.computeIfAbsent(value, this::createStorageManager); + } + + private StorageManager createStorageManager(final String value) + { + LOGGER.info("Loading configuration to start the class StorageManager from the key: " + value); + return new StorageManagerProxy(value); + } + + +} diff --git a/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerInitializer.java b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerInitializer.java new file mode 100644 index 00000000..18790bb9 --- /dev/null +++ b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerInitializer.java @@ -0,0 +1,23 @@ +package org.eclipse.store.integrations.cdi.types.config; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.storage.types.StorageManager; + +public interface StorageManagerInitializer +{ + + void initialize(final StorageManager storageManager); +} diff --git a/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducer.java b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducer.java new file mode 100644 index 00000000..da663942 --- /dev/null +++ b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducer.java @@ -0,0 +1,122 @@ + +package org.eclipse.store.integrations.cdi.types.config; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + + +import java.util.Map; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Disposes; +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; +import org.eclipse.microprofile.config.Config; +import org.eclipse.store.integrations.cdi.ConfigurationCoreProperties; +import org.eclipse.store.integrations.cdi.types.extension.StorageExtension; +import org.eclipse.store.storage.embedded.configuration.types.EmbeddedStorageConfigurationBuilder; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.eclipse.store.storage.types.StorageManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +@ApplicationScoped +public class StorageManagerProducer +{ + private static final Logger LOGGER = LoggerFactory.getLogger(StorageManagerProducer.class); + + @Inject + private Config config; + + @Inject + private StorageExtension storageExtension; + + @Inject + private Instance customizers; + + @Inject + private Instance initializers; + + @Produces + @ApplicationScoped + public StorageManager getStorageManager() + { + + if (this.storageExtension.getStorageManagerConfigInjectionNames() + .isEmpty()) + { + return this.storageManagerFromProperties(); + } + + // StorageManager through StorageManagerConverter + final String configName = this.storageExtension.getStorageManagerConfigInjectionNames() + .iterator() + .next(); + LOGGER.info("Loading StorageManager from file indicated by MicroProfile Config key : " + configName); + + // This will succeed since it is already validated during deployment of the application. + return this.config.getValue(configName, StorageManager.class); + } + + private EmbeddedStorageManager storageManagerFromProperties() + { + final Map properties = ConfigurationCoreProperties.getProperties(this.config); + LOGGER.info("Loading default StorageManager from MicroProfile Config properties. The keys: " + properties.keySet()); + + final EmbeddedStorageConfigurationBuilder builder = EmbeddedStorageConfigurationBuilder.New(); + for (final Map.Entry entry : properties.entrySet()) + { + builder.set(entry.getKey(), entry.getValue()); + } + final EmbeddedStorageFoundation foundation = builder.createEmbeddedStorageFoundation(); + foundation.setDataBaseName("Generic"); + + this.customizers.stream() + .forEach(customizer -> customizer.customize(foundation)); + + final EmbeddedStorageManager storageManager = foundation + .createEmbeddedStorageManager(); + + if (this.isAutoStart(properties)) + { + storageManager.start(); + } + + if (!this.storageExtension.hasStorageRoot()) + { + // Only execute at this point when no storage root bean has defined with @Storage + // Initializers are called from StorageBean.create if user has defined @Storage and root is read. + this.initializers.stream() + .forEach(initializer -> initializer.initialize(storageManager)); + } + + return storageManager; + } + + private boolean isAutoStart(final Map properties) + { + return Boolean.parseBoolean(properties.getOrDefault("autoStart", "true")); + + } + + public void dispose(@Disposes final StorageManager manager) + { + LOGGER.info("Closing the default StorageManager"); + manager.close(); + } +} diff --git a/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProxy.java b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProxy.java new file mode 100644 index 00000000..5f03b0af --- /dev/null +++ b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProxy.java @@ -0,0 +1,284 @@ +package org.eclipse.store.integrations.cdi.types.config; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import java.nio.ByteBuffer; +import java.util.Optional; +import java.util.function.Predicate; + +import jakarta.enterprise.inject.spi.CDI; +import org.eclipse.microprofile.config.ConfigProvider; +import org.eclipse.serializer.afs.types.AFile; +import org.eclipse.serializer.collections.types.XGettingEnum; +import org.eclipse.serializer.configuration.types.Configuration; +import org.eclipse.serializer.persistence.binary.types.Binary; +import org.eclipse.serializer.persistence.types.PersistenceManager; +import org.eclipse.serializer.persistence.types.PersistenceRootsView; +import org.eclipse.serializer.persistence.types.PersistenceTypeDictionaryExporter; +import org.eclipse.store.integrations.cdi.ConfigurationCoreProperties; +import org.eclipse.store.storage.embedded.configuration.types.EmbeddedStorageConfiguration; +import org.eclipse.store.storage.embedded.configuration.types.EmbeddedStorageConfigurationBuilder; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.eclipse.store.storage.types.*; + + +/** + * For MicroProfile Config, at deployment time, we need to validate if @ConfigProperty is valid by + * creating the StorageManager. Since we need to look up the beans for {@link EmbeddedStorageFoundationCustomizer} + * and {@link StorageManagerInitializer} we need a fully initialised bean Manager which we do not have. + * And to avoid the creating of the StorageManager at deployment time, we have this proxy that + * delays the creation of the StorageManager until first use. + */ +public class StorageManagerProxy implements StorageManager +{ + + private static final Object LOCK = new Object(); + + private final EmbeddedStorageFoundation foundation; + + private StorageManager realStorageManager; + + public StorageManagerProxy(final String value) + { + // Already create the EmbeddedStorageFoundation to check if the config value points to a valid + // location. + final EmbeddedStorageConfigurationBuilder configurationBuilder = EmbeddedStorageConfiguration.load(value); + + final Configuration configuration = configurationBuilder.buildConfiguration(); + final String name = Optional.ofNullable(configuration.get("database-name")).orElse(value); + + this.foundation = configurationBuilder + .createEmbeddedStorageFoundation(); + + this.foundation.setDataBaseName(name); + + } + + private StorageManager getStorageManager() + { + synchronized (LOCK) + { + // Make sure this is not executed multi-threaded + + if (this.realStorageManager == null) + { + CDI.current() + .select(EmbeddedStorageFoundationCustomizer.class) + .stream() + .forEach(customizer -> customizer.customize(this.foundation)); + + final EmbeddedStorageManager storageManager = this.foundation + .createEmbeddedStorageManager(); + + if (this.isAutoStart()) + { + storageManager.start(); + } + + CDI.current() + .select(StorageManagerInitializer.class) + .stream() + .forEach(initializer -> initializer.initialize(storageManager)); + + this.realStorageManager = storageManager; + } + } + + return this.realStorageManager; + } + + private boolean isAutoStart() + { + return ConfigProvider.getConfig() + .getOptionalValue(ConfigurationCoreProperties.Constants.PREFIX + "autoStart", Boolean.class) + .orElse(Boolean.TRUE); + } + + @Override + public StorageConfiguration configuration() + { + return this.getStorageManager().configuration(); + } + + @Override + public StorageTypeDictionary typeDictionary() + { + return this.getStorageManager().typeDictionary(); + } + + @Override + public StorageManager start() + { + return this.getStorageManager().start(); + } + + @Override + public boolean shutdown() + { + return this.getStorageManager().shutdown(); + } + + @Override + public boolean isAcceptingTasks() + { + return this.getStorageManager().isAcceptingTasks(); + } + + @Override + public boolean isRunning() + { + return this.getStorageManager().isRunning(); + } + + @Override + public boolean isStartingUp() + { + return this.getStorageManager().isStartingUp(); + } + + @Override + public boolean isShuttingDown() + { + return this.getStorageManager().isShuttingDown(); + } + + @Override + public void checkAcceptingTasks() + { + this.getStorageManager().checkAcceptingTasks(); + } + + @Override + public long initializationTime() + { + return this.getStorageManager().initializationTime(); + } + + @Override + public long operationModeTime() + { + return this.getStorageManager().operationModeTime(); + } + + @Override + public StorageConnection createConnection() + { + return this.getStorageManager().createConnection(); + } + + @Override + public Object root() + { + return this.getStorageManager().root(); + } + + @Override + public Object setRoot(final Object newRoot) + { + return this.getStorageManager().setRoot(newRoot); + } + + @Override + public long storeRoot() + { + return this.getStorageManager().storeRoot(); + } + + @Override + public PersistenceRootsView viewRoots() + { + return this.getStorageManager().viewRoots(); + } + + @Override + public Database database() + { + return this.getStorageManager().database(); + } + + @Override + public boolean issueGarbageCollection(final long nanoTimeBudget) + { + return this.getStorageManager().issueGarbageCollection(nanoTimeBudget); + } + + @Override + public boolean issueFileCheck(final long nanoTimeBudget) + { + return this.getStorageManager().issueFileCheck(nanoTimeBudget); + } + + @Override + public boolean issueCacheCheck(final long nanoTimeBudget, final StorageEntityCacheEvaluator entityEvaluator) + { + return this.getStorageManager().issueCacheCheck(nanoTimeBudget, entityEvaluator); + } + + @Override + public void issueFullBackup(final StorageLiveFileProvider targetFileProvider, final PersistenceTypeDictionaryExporter typeDictionaryExporter) + { + this.getStorageManager().issueFullBackup(targetFileProvider, typeDictionaryExporter); + } + + @Override + public void issueTransactionsLogCleanup() + { + this.getStorageManager().issueTransactionsLogCleanup(); + } + + @Override + public StorageRawFileStatistics createStorageStatistics() + { + return this.getStorageManager().createStorageStatistics(); + } + + @Override + public void exportChannels(final StorageLiveFileProvider fileProvider, final boolean performGarbageCollection) + { + this.getStorageManager().exportChannels(fileProvider, performGarbageCollection); + } + + @Override + public StorageEntityTypeExportStatistics exportTypes(final StorageEntityTypeExportFileProvider exportFileProvider, final Predicate isExportType) + { + return this.getStorageManager().exportTypes(exportFileProvider, isExportType); + } + + @Override + public void importFiles(final XGettingEnum importFiles) + { + this.getStorageManager().importFiles(importFiles); + } + + @Override + public void importData(final XGettingEnum importData) + { + this.getStorageManager().importData(importData); + } + + @Override + public PersistenceManager persistenceManager() + { + return this.getStorageManager().persistenceManager(); + } + + @Override + public boolean isActive() + { + return this.getStorageManager().isActive(); + } +} diff --git a/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/extension/AbstractBean.java b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/extension/AbstractBean.java new file mode 100644 index 00000000..6b4e8045 --- /dev/null +++ b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/extension/AbstractBean.java @@ -0,0 +1,107 @@ + +package org.eclipse.store.integrations.cdi.types.extension; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import java.lang.annotation.Annotation; +import java.util.Collections; +import java.util.Set; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.spi.CreationalContext; +import jakarta.enterprise.inject.spi.AnnotatedType; +import jakarta.enterprise.inject.spi.Bean; +import jakarta.enterprise.inject.spi.BeanManager; +import jakarta.enterprise.inject.spi.CDI; +import jakarta.enterprise.inject.spi.InjectionPoint; +import jakarta.enterprise.inject.spi.PassivationCapable; + + +/** + * A template class to all the programmatic {@link Bean}s that are defined. + * + * @param the bean type + */ +public abstract class AbstractBean implements Bean, PassivationCapable +{ + protected final BeanManager beanManager; + private final Set injectionPoints; + + protected AbstractBean(final BeanManager beanManager, final Set injectionPoints) + { + this.beanManager = beanManager; + this.injectionPoints = injectionPoints; + } + + protected B getInstance(final Class clazz) + { + return CDI.current().select(clazz).get(); + } + + @SuppressWarnings("unchecked") + protected void injectDependencies(final T root) + { + final AnnotatedType type = (AnnotatedType) this.beanManager.createAnnotatedType(root.getClass()); + final CreationalContext context = this.beanManager.createCreationalContext(null); + this.beanManager.getInjectionTargetFactory(type) + .createInjectionTarget(this) + .inject(root, context); + } +// +// @Override +// public boolean isNullable() +// { +// return false; +// } + + @Override + public Set getInjectionPoints() + { + return this.injectionPoints; + } + + + @Override + public Class getScope() + { + return ApplicationScoped.class; + } + + @Override + public String getName() + { + return null; + } + + @Override + public Set> getStereotypes() + { + return Collections.emptySet(); + } + + @Override + public boolean isAlternative() + { + return false; + } + + @Override + public void destroy(final T instance, final CreationalContext context) + { + // no-op by default + } + +} diff --git a/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/extension/StorageBean.java b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/extension/StorageBean.java new file mode 100644 index 00000000..c44e44d1 --- /dev/null +++ b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/extension/StorageBean.java @@ -0,0 +1,146 @@ + +package org.eclipse.store.integrations.cdi.types.extension; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import jakarta.enterprise.context.spi.CreationalContext; +import jakarta.enterprise.inject.Any; +import jakarta.enterprise.inject.Default; +import jakarta.enterprise.inject.spi.Bean; +import jakarta.enterprise.inject.spi.BeanManager; +import jakarta.enterprise.inject.spi.InjectionPoint; +import org.eclipse.store.integrations.cdi.exceptions.CDIExceptionStorage; +import org.eclipse.store.integrations.cdi.Storage; +import org.eclipse.store.integrations.cdi.types.config.StorageManagerInitializer; +import org.eclipse.serializer.reflect.XReflect; +import org.eclipse.store.storage.types.StorageManager; + + +/** + * Storage Discovery Bean to CDI extension to register an entity with {@link Storage} + * annotation. + */ +class StorageBean extends AbstractBean +{ + private final Class type ; + private final Set types ; + private final Set qualifiers; + + protected StorageBean(final BeanManager beanManager + , final Class type + , final Set injectionPoints + ) + { + super(beanManager, injectionPoints); + this.type = type; + this.types = Collections.singleton(type); + this.qualifiers = new HashSet<>(); + this.qualifiers.add(new Default.Literal()); + this.qualifiers.add(new Any.Literal()); + } + + @Override + public Class getBeanClass() + { + return this.type; + } + + @SuppressWarnings("unchecked") + @Override + public T create(final CreationalContext context) + { + final StorageManager manager = this.getInstance(StorageManager.class); + final Object root = manager.root(); + T entity; + if (Objects.isNull(root)) + { + entity = XReflect.defaultInstantiate(this.type); + manager.setRoot(entity); + manager.storeRoot(); + } + else + { + if (this.type.isInstance(root)) + { + entity = (T) root; + } + else + { + throw new CDIExceptionStorage(this.type, root.getClass()); + } + } + this.injectDependencies(entity); + + final Set> initializerBeans = this.beanManager.getBeans(StorageManagerInitializer.class); + for (final Bean initializerBean : initializerBeans) + { + final StorageManagerInitializer initializer = (StorageManagerInitializer) this.beanManager.getReference(initializerBean + , initializerBean.getBeanClass() + , this.beanManager.createCreationalContext(initializerBean)); + + initializer.initialize(manager); + } + return entity; + } + + @Override + public Set> getStereotypes() + { + return Collections.singleton(Storage.class); + } + + @Override + public Set getTypes() + { + return this.types; + } + + @Override + public Set getQualifiers() + { + return this.qualifiers; + } + + @Override + public String getId() + { + return this.type.getName() + " @Storage"; + } + + @Override + public String toString() + { + return "StorageBean{" + + + "type=" + + this.type + + + ", types=" + + this.types + + + ", qualifiers=" + + this.qualifiers + + + '}'; + } +} diff --git a/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/extension/StorageExtension.java b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/extension/StorageExtension.java new file mode 100644 index 00000000..b231ece3 --- /dev/null +++ b/integrations/cdi4/src/main/java/org/eclipse/store/integrations/cdi/types/extension/StorageExtension.java @@ -0,0 +1,165 @@ + +package org.eclipse.store.integrations.cdi.types.extension; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.logging.Logger; + +import jakarta.enterprise.inject.spi.*; +import org.eclipse.microprofile.config.inject.ConfigProperty; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.event.Observes; +import org.eclipse.store.integrations.cdi.Storage; +import org.eclipse.store.storage.types.StorageManager; + + +/** + * This extension will look for Objects that are marked with {@link Storage}. + */ +@ApplicationScoped +public class StorageExtension implements Extension +{ + + private static final Logger LOGGER = Logger.getLogger(StorageExtension.class.getName()); + + private final Set> storageRoot = new HashSet<>(); + + private final Map, Set> storageInjectionPoints = new HashMap<>(); + + private final Set storageManagerConfigInjectionNames = new HashSet<>(); + + void beforeBeanDiscovery(@Observes BeforeBeanDiscovery bbd) { + LOGGER.info("beginning the scanning process"); + } + + void processAnnotatedType(@Observes ProcessAnnotatedType pat) { + LOGGER.info("scanning type: " + pat.getAnnotatedType().getJavaClass().getName()); + } + + void afterBeanDiscovery(@Observes AfterBeanDiscovery abd) { + LOGGER.info("finished the scanning process"); + } + + void loadEntity(@Observes @WithAnnotations({Storage.class}) final ProcessAnnotatedType target) + { + final AnnotatedType annotatedType = target.getAnnotatedType(); + if (annotatedType.isAnnotationPresent(Storage.class)) + { + + final Class javaClass = target.getAnnotatedType() + .getJavaClass(); + this.storageRoot.add(javaClass); + LOGGER.info("New class found annotated with @Storage is " + javaClass); + } + } + + void collectInjectionsFromStorageBean(@Observes final ProcessInjectionPoint pip) + { + final InjectionPoint ip = pip.getInjectionPoint(); + if (ip.getBean() != null && ip.getBean() + .getBeanClass() + .getAnnotation(Storage.class) != null) + { + this.storageInjectionPoints + .computeIfAbsent(ip.getBean() + .getBeanClass(), k -> new HashSet<>()) + .add(ip); + } + // Is @Inject @ConfigProperty on StorageManager? + if (this.isStorageManagerFromConfig(ip)) + { + this.storageManagerConfigInjectionNames.add(this.getConfigPropertyValueOf(ip)); + + } + } + + private String getConfigPropertyValueOf(final InjectionPoint ip) + { + return ip.getQualifiers() + .stream() + .filter(q -> q.annotationType() + .isAssignableFrom(ConfigProperty.class)) + .findAny() + .map(q -> ((ConfigProperty) q).name()) + .orElse(""); + } + + private boolean isStorageManagerFromConfig(final InjectionPoint ip) + { + return ip.getMember() instanceof Field + && ((Field) ip.getMember()).getType().isAssignableFrom(StorageManager.class) + && ip.getQualifiers() + .stream() + .anyMatch(q -> q.annotationType() + .isAssignableFrom(ConfigProperty.class)); + } + + void onAfterBeanDiscovery(@Observes final AfterBeanDiscovery afterBeanDiscovery, final BeanManager beanManager) + { + LOGGER.info(String.format("Processing StorageExtension: %d @Storage found", this.storageRoot.size())); + if (this.storageRoot.size() > 1) + { + throw new IllegalStateException( + "In the application must have only one class with the Storage annotation, classes: " + + this.storageRoot); + } + if (this.storageManagerConfigInjectionNames.size() > 1 && !this.storageRoot.isEmpty()) + { + throw new IllegalStateException( + "It is not supported to define multiple StorageManager's through @ConfigProperty in combination with a @Storage annotated class. Names : " + + this.storageManagerConfigInjectionNames); + + } + this.storageRoot.forEach(entity -> + { + Set injectionPoints = this.storageInjectionPoints.get(entity); + if (injectionPoints == null) + { + injectionPoints = Collections.emptySet(); + } + final StorageBean bean = new StorageBean<>(beanManager, entity, injectionPoints); + afterBeanDiscovery.addBean(bean); + }); + } + + public Set getStorageManagerConfigInjectionNames() + { + return this.storageManagerConfigInjectionNames; + } + + public boolean hasStorageRoot() + { + return !this.storageRoot.isEmpty(); + } + + @Override + public String toString() + { + return "StorageExtension{" + + + "storageRoot=" + + this.storageRoot + + + '}'; + } +} diff --git a/integrations/cdi4/src/main/resources/META-INF/beans.xml b/integrations/cdi4/src/main/resources/META-INF/beans.xml new file mode 100644 index 00000000..1a9123a0 --- /dev/null +++ b/integrations/cdi4/src/main/resources/META-INF/beans.xml @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/integrations/cdi4/src/main/resources/META-INF/services/jakarta.enterprise.inject.spi.Extension b/integrations/cdi4/src/main/resources/META-INF/services/jakarta.enterprise.inject.spi.Extension new file mode 100644 index 00000000..b6e761d9 --- /dev/null +++ b/integrations/cdi4/src/main/resources/META-INF/services/jakarta.enterprise.inject.spi.Extension @@ -0,0 +1,2 @@ + +org.eclipse.store.integrations.cdi.types.extension.StorageExtension diff --git a/integrations/cdi4/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.Converter b/integrations/cdi4/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.Converter new file mode 100644 index 00000000..d5e6d258 --- /dev/null +++ b/integrations/cdi4/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.Converter @@ -0,0 +1 @@ +org.eclipse.store.integrations.cdi.types.config.StorageManagerConverter diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/Agenda.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/Agenda.java new file mode 100644 index 00000000..d4786f10 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/Agenda.java @@ -0,0 +1,80 @@ + +package org.eclipse.store.integrations.cdi.types; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + + +import java.util.Collections; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentSkipListSet; + +import org.eclipse.store.integrations.cdi.Storage; + + +@Storage +public class Agenda +{ + + private final Set names; + + public Agenda() + { + this.names = new ConcurrentSkipListSet<>(); + } + + public void add(final String name) + { + this.names.add(name); + } + + public Set getNames() + { + return Collections.unmodifiableSet(this.names); + } + + @Override + public boolean equals(final Object o) + { + if (this == o) + { + return true; + } + if (o == null || this.getClass() != o.getClass()) + { + return false; + } + final Agenda agenda = (Agenda)o; + return Objects.equals(this.names, agenda.names); + } + + @Override + public int hashCode() + { + return Objects.hashCode(this.names); + } + + @Override + public String toString() + { + return "Agenda{" + + + "names=" + + this.names + + + '}'; + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/ConfigurationCorePropertiesTest.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/ConfigurationCorePropertiesTest.java new file mode 100644 index 00000000..4e8920d7 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/ConfigurationCorePropertiesTest.java @@ -0,0 +1,195 @@ + +package org.eclipse.store.integrations.cdi.types; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import io.smallrye.config.inject.ConfigExtension; +import org.eclipse.microprofile.config.Config; +import org.eclipse.store.integrations.cdi.ConfigurationCoreProperties; +import org.eclipse.store.integrations.cdi.types.logging.TestAppender; +import org.eclipse.store.storage.embedded.configuration.types.EmbeddedStorageConfigurationPropertyNames; +import org.jboss.weld.junit5.auto.AddExtensions; +import org.jboss.weld.junit5.auto.EnableAutoWeld; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import jakarta.inject.Inject; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +@EnableAutoWeld // So that Weld container is started +@AddExtensions(ConfigExtension.class) // SmallRye Config extension to Support MicroProfile Config within this test +class ConfigurationCorePropertiesTest +{ + // Testing the ConfigurationCoreProperties functionality. + // - convert the MicroProfile config key/values to Map entries as EclipseStore config values. + + @Inject + private Config config; + + @BeforeEach + public void setup() + { + TestAppender.events.clear(); + } + + private static final String PREFIX = "org.eclipse.store."; + + @Test + void shouldLoadFromPropertiesFile() + { + final Map properties = ConfigurationCoreProperties.getProperties(this.config); + Assertions.assertNotNull(properties); + Assertions.assertEquals(4, properties.keySet() + .size(),properties.keySet().toString()); + Assertions.assertEquals(Set.of("xml", "ini", "properties", "storage-directory"), properties.keySet()); + } + + @Test + void shouldLoadPropertiesFromConfiguration() + { + String microProfileKey = ConfigurationCoreProperties.STORAGE_DIRECTORY.getMicroProfile(); + try + { + System.setProperty(microProfileKey, "target/"); + final Map properties = ConfigurationCoreProperties.getProperties(this.config); + final String storageDirectory = properties.get(ConfigurationCoreProperties.STORAGE_DIRECTORY.getEclipseStore(microProfileKey)); + Assertions.assertNotNull(storageDirectory); + Assertions.assertEquals("target/", storageDirectory); + } finally + { + System.clearProperty(microProfileKey); + } + } + + @Test + public void shouldAddCustomConfiguration() + { + + final String customProperty = "custom.test"; + final String key = ConfigurationCoreProperties.Constants.PREFIX + customProperty; + try + { + System.setProperty(key, "random_value"); + final Map properties = ConfigurationCoreProperties.getProperties(this.config); + final String value = properties.get(customProperty); + Assertions.assertEquals("random_value", value); + } finally + { + System.clearProperty(key); + } + } + + @Test + void shouldMapStorageFileSystem() + { + final String keyMicroProfile = PREFIX + "storage.filesystem.sql.postgres.data-source-provider"; + final String keyMicroStream = "storage-filesystem.sql.postgres.data-source-provider"; + try + { + System.setProperty(keyMicroProfile, "some_value"); + + final Map properties = ConfigurationCoreProperties.getProperties(this.config); + final String value = properties.get(keyMicroStream); + Assertions.assertEquals("some_value", value); + + } finally + { + System.clearProperty(keyMicroProfile); + } + + } + + @Test + void shouldSupportMicroStreamKeys() + { + final String keyMicroProfile = PREFIX +"storage-directory"; + try + { + System.setProperty(keyMicroProfile, "/storage"); + final Map properties = ConfigurationCoreProperties.getProperties(this.config); + final String value = properties.get(EmbeddedStorageConfigurationPropertyNames.STORAGE_DIRECTORY); + Assertions.assertEquals("/storage", value, value); + + } finally + { + System.clearProperty(keyMicroProfile); + } + + } + + @Test + void shouldMapStorageFileSystem_directly() + { + // Without CDI version, testing ConfigurationCoreProperties 'directly' + + final String keyMicroProfile = PREFIX + "storage.filesystem.sql.postgres.data-source-provider"; + final String keyMicroStream = "storage-filesystem.sql.postgres.data-source-provider"; + + Optional property = ConfigurationCoreProperties.get(keyMicroProfile); + Assertions.assertTrue(property.isPresent()); + + String convertedKey = property.get().getEclipseStore(keyMicroProfile); + Assertions.assertEquals(keyMicroStream, convertedKey); + } + + @Test + void shouldMapExactMatches() + { + // Not using CDI + + final String keyMicroProfile = "org.eclipse.store.storage.directory"; + final String keyMicroStream = "storage-directory"; + + Optional property = ConfigurationCoreProperties.get(keyMicroProfile); + Assertions.assertTrue(property.isPresent()); + + String convertedKey = property.get().getEclipseStore(keyMicroProfile); + Assertions.assertEquals(keyMicroStream, convertedKey); + } + + @Test + void findEnumValue() + { + // Not using CDI + String key = PREFIX + "storage.directory"; + final Optional property = ConfigurationCoreProperties.get(key); + Assertions.assertTrue(property.isPresent()); + Assertions.assertEquals(ConfigurationCoreProperties.STORAGE_DIRECTORY, property.get()); + } + + @Test + void findEnumValue_partial() + { + // Not using CDI + String key = PREFIX + "storage.filesystem.sql.postgres.data-source-provider"; + final Optional property = ConfigurationCoreProperties.get(key); + Assertions.assertTrue(property.isPresent()); + Assertions.assertEquals(ConfigurationCoreProperties.STORAGE_FILESYSTEM, property.get()); + Assertions.assertEquals("storage-filesystem.sql.postgres.data-source-provider", property.get().getEclipseStore(key)); + } + + @Test + void findEnumValue_NotCaseSensitive() + { + // Not using CDI + String key = PREFIX + "Storage.Directory"; + final Optional property = ConfigurationCoreProperties.get(key); + Assertions.assertTrue(property.isEmpty()); + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/StorageTest.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/StorageTest.java new file mode 100644 index 00000000..f7f27188 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/StorageTest.java @@ -0,0 +1,81 @@ + +package org.eclipse.store.integrations.cdi.types; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + + + +import org.eclipse.store.integrations.cdi.types.extension.StorageExtension; +import org.eclipse.store.storage.types.StorageManager; +import org.jboss.weld.junit5.auto.AddExtensions; +import org.jboss.weld.junit5.auto.EnableAutoWeld; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.enterprise.inject.spi.Bean; +import jakarta.enterprise.inject.spi.BeanManager; +import jakarta.enterprise.inject.spi.CDI; +import jakarta.inject.Inject; +import java.util.Set; + + +@EnableAutoWeld +@AddExtensions(StorageExtension.class) +public class StorageTest +{ + // Test if a class annotated with @Storage is converted into an ApplicationScoped bean. + @Inject + private Agenda agenda; + + @Inject + private BeanManager beanManager; + + @ApplicationScoped + @Produces + // StorageBean requires a StorageManager + private StorageManager storageManagerMock = Mockito.mock(StorageManager.class); + + @Test + @DisplayName("Should check if it create an instance by annotation") + public void shouldCreateInstance() + { + Assertions.assertNotNull(this.agenda); + this.agenda.add("JUnit"); + + // Another way of testing we have only 1 instance of @Storage bean. + final Agenda instance = CDI.current() + .select(Agenda.class) + .get(); + Assertions.assertEquals("JUnit", instance.getNames() + .iterator() + .next()); + } + + @Test + public void shouldCreateApplicationScopedBean() + { + final Set> beans = this.beanManager.getBeans(Agenda.class); + Assertions.assertEquals(1, beans.size()); + final Bean storageBean = beans.iterator() + .next(); + Assertions.assertEquals(ApplicationScoped.class, storageBean.getScope()); + + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/CacheProducerTest.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/CacheProducerTest.java new file mode 100644 index 00000000..a49fd738 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/CacheProducerTest.java @@ -0,0 +1,58 @@ +package org.eclipse.store.integrations.cdi.types.cache; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import io.smallrye.config.inject.ConfigExtension; +import org.eclipse.store.integrations.cdi.types.config.StorageManagerProducer; +import org.eclipse.store.integrations.cdi.types.extension.StorageExtension; +import org.jboss.weld.junit5.auto.AddBeanClasses; +import org.jboss.weld.junit5.auto.AddExtensions; +import org.jboss.weld.junit5.auto.EnableAutoWeld; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import javax.cache.CacheManager; +import javax.cache.spi.CachingProvider; +import jakarta.inject.Inject; + + +@EnableAutoWeld +@AddBeanClasses({StorageCacheProducer.class, StorageManagerProducer.class}) // For @StorageCache +@AddExtensions({StorageExtension.class, ConfigExtension.class}) +// SmallRye Config extension And EclipseStore extension for StorageManager +public class CacheProducerTest +{ + @Inject + @StorageCache + private CachingProvider provider; + + @Inject + @StorageCache + private CacheManager cacheManager; + + @Test + public void shouldNotBeNullProvider() + { + Assertions.assertNotNull(this.provider); + } + + @Test + public void shouldNotBeNullManager() + { + Assertions.assertNotNull(this.cacheManager); + } + +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/CachePropertiesTest.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/CachePropertiesTest.java new file mode 100644 index 00000000..93039307 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/CachePropertiesTest.java @@ -0,0 +1,220 @@ +package org.eclipse.store.integrations.cdi.types.cache; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import io.smallrye.config.inject.ConfigExtension; +import org.eclipse.store.integrations.cdi.types.config.StorageManagerProducer; +import org.eclipse.store.integrations.cdi.types.extension.StorageExtension; +import org.eclipse.microprofile.config.Config; +import org.jboss.weld.junit5.auto.AddBeanClasses; +import org.jboss.weld.junit5.auto.AddExtensions; +import org.jboss.weld.junit5.auto.EnableAutoWeld; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import javax.cache.configuration.Factory; +import javax.cache.expiry.ExpiryPolicy; +import javax.cache.integration.CacheLoader; +import javax.cache.integration.CacheWriter; +import jakarta.inject.Inject; + + +@EnableAutoWeld +@AddBeanClasses({StorageCacheProducer.class, StorageManagerProducer.class}) // For @StorageCache +@AddExtensions({StorageExtension.class, ConfigExtension.class}) +// SmallRye Config extension And EclipseStore extension for StorageManager +class CachePropertiesTest +{ + @Inject + private Config config; + + @Test + @DisplayName("Should get the default value in the storeByValue") + public void shouldReturnStoreByValue() + { + final boolean storeByValue = CacheProperties.isStoreByValue(this.config); + Assertions.assertFalse(storeByValue); + } + + @Test + public void shouldReturnErrorWhenConfigIsNull() + { + Assertions.assertThrows(NullPointerException.class, () -> CacheProperties.isStoreByValue(null)); + Assertions.assertThrows(NullPointerException.class, () -> CacheProperties.isWriteThrough(null)); + Assertions.assertThrows(NullPointerException.class, () -> CacheProperties.isReadThrough(null)); + Assertions.assertThrows(NullPointerException.class, () -> CacheProperties.isManagementEnabled(null)); + Assertions.assertThrows(NullPointerException.class, () -> CacheProperties.isStatisticsEnabled(null)); + Assertions.assertThrows(NullPointerException.class, () -> CacheProperties.getLoaderFactory(null)); + Assertions.assertThrows(NullPointerException.class, () -> CacheProperties.getWriterFactory(null)); + Assertions.assertThrows(NullPointerException.class, () -> CacheProperties.getExpiryFactory(null)); + Assertions.assertThrows(NullPointerException.class, () -> CacheProperties.isStorage(null)); + } + + @Test + @DisplayName("Should get storeByValue from Eclipse MicroProfile Config") + public void shouldReturnStoreByValueConfig() + { + System.setProperty(CacheProperties.CACHE_STORE_VALUE.get(), "false"); + Assertions.assertFalse(CacheProperties.isStoreByValue(this.config)); + System.setProperty(CacheProperties.CACHE_STORE_VALUE.get(), "true"); + Assertions.assertTrue(CacheProperties.isStoreByValue(this.config)); + System.clearProperty(CacheProperties.CACHE_STORE_VALUE.get()); + } + + @Test + @DisplayName("Should get the default value in the writeThrough") + public void shouldReturnWriteThrough() + { + final boolean storeByValue = CacheProperties.isWriteThrough(this.config); + Assertions.assertFalse(storeByValue); + } + + @Test + @DisplayName("Should get writeThrough from Eclipse MicroProfile Config") + public void shouldReturnSWriteThroughConfig() + { + System.setProperty(CacheProperties.CACHE_WRITE_THROUGH.get(), "false"); + Assertions.assertFalse(CacheProperties.isWriteThrough(this.config)); + System.setProperty(CacheProperties.CACHE_WRITE_THROUGH.get(), "true"); + Assertions.assertTrue(CacheProperties.isWriteThrough(this.config)); + System.clearProperty(CacheProperties.CACHE_WRITE_THROUGH.get()); + } + + @Test + @DisplayName("Should get the default value in the readThrough") + public void shouldReturnReadThrough() + { + final boolean storeByValue = CacheProperties.isReadThrough(this.config); + Assertions.assertFalse(storeByValue); + } + + @Test + @DisplayName("Should get readThrough from Eclipse MicroProfile Config") + public void shouldReturnReadThroughConfig() + { + System.setProperty(CacheProperties.CACHE_READ_THROUGH.get(), "false"); + Assertions.assertFalse(CacheProperties.isReadThrough(this.config)); + System.setProperty(CacheProperties.CACHE_READ_THROUGH.get(), "true"); + Assertions.assertTrue(CacheProperties.isReadThrough(this.config)); + System.clearProperty(CacheProperties.CACHE_READ_THROUGH.get()); + } + + @Test + @DisplayName("Should get the default value in the managementEnabled") + public void shouldReturnManagementEnabled() + { + final boolean storeByValue = CacheProperties.isManagementEnabled(this.config); + Assertions.assertFalse(storeByValue); + } + + @Test + @DisplayName("Should get managementEnabled from Eclipse MicroProfile Config") + public void shouldReturnManagementEnabledConfig() + { + System.setProperty(CacheProperties.CACHE_MANAGEMENT.get(), "false"); + Assertions.assertFalse(CacheProperties.isManagementEnabled(this.config)); + System.setProperty(CacheProperties.CACHE_MANAGEMENT.get(), "true"); + Assertions.assertTrue(CacheProperties.isManagementEnabled(this.config)); + System.clearProperty(CacheProperties.CACHE_MANAGEMENT.get()); + } + + @Test + @DisplayName("Should get the default value in the statisticsEnabled") + public void shouldReturnStatisticsEnabled() + { + final boolean storeByValue = CacheProperties.isStatisticsEnabled(this.config); + Assertions.assertFalse(storeByValue); + } + + @Test + @DisplayName("Should get statisticsEnabled from Eclipse MicroProfile Config") + public void shouldReturnStatisticsEnabledConfig() + { + System.setProperty(CacheProperties.CACHE_STATISTICS.get(), "false"); + Assertions.assertFalse(CacheProperties.isStatisticsEnabled(this.config)); + System.setProperty(CacheProperties.CACHE_STATISTICS.get(), "true"); + Assertions.assertTrue(CacheProperties.isStatisticsEnabled(this.config)); + System.clearProperty(CacheProperties.CACHE_STATISTICS.get()); + } + + @Test + public void shouldReturnNullAsDefaultLoaderFactory() + { + Assertions.assertNull(CacheProperties.getLoaderFactory(this.config)); + } + + @Test + public void shouldReturnNullAsDefaultWriterFactory() + { + Assertions.assertNull(CacheProperties.getWriterFactory(this.config)); + } + + @Test + public void shouldReturnNullAsDefaultExpireFactory() + { + Assertions.assertNull(CacheProperties.getExpiryFactory(this.config)); + } + + @Test + public void shouldReturnErrorWhenIsNotFactoryInstance() + { + System.setProperty(CacheProperties.CACHE_LOADER_FACTORY.get(), "java.lang.String"); + Assertions.assertThrows( + IllegalArgumentException.class, + () -> Assertions.assertNull(CacheProperties.getLoaderFactory(this.config))); + System.clearProperty(CacheProperties.CACHE_LOADER_FACTORY.get()); + } + + @Test + public void shouldCreateLoaderFactory() + { + System.setProperty(CacheProperties.CACHE_LOADER_FACTORY.get(), MockLoaderFactory.class.getName()); + final Factory> loaderFactory = CacheProperties.getLoaderFactory(this.config); + Assertions.assertTrue(loaderFactory instanceof MockLoaderFactory); + System.clearProperty(CacheProperties.CACHE_LOADER_FACTORY.get()); + } + + @Test + public void shouldCreateCacheWriterFactory() + { + System.setProperty(CacheProperties.CACHE_WRITER_FACTORY.get(), MockCacheWriter.class.getName()); + final Factory> loaderFactory = CacheProperties.getWriterFactory(this.config); + Assertions.assertTrue(loaderFactory instanceof MockCacheWriter); + System.clearProperty(CacheProperties.CACHE_WRITER_FACTORY.get()); + } + + @Test + public void shouldCreateExpireFactory() + { + System.setProperty(CacheProperties.CACHE_EXPIRES_FACTORY.get(), MockExpiryPolicy.class.getName()); + final Factory loaderFactory = CacheProperties.getExpiryFactory(this.config); + Assertions.assertTrue(loaderFactory instanceof MockExpiryPolicy); + System.clearProperty(CacheProperties.CACHE_EXPIRES_FACTORY.get()); + } + + @Test + @DisplayName("Should get storage from Eclipse MicroProfile Config") + public void shouldReturnStorage() + { + System.setProperty(CacheProperties.STORAGE.get(), "false"); + Assertions.assertFalse(CacheProperties.isStorage(this.config)); + System.setProperty(CacheProperties.STORAGE.get(), "true"); + Assertions.assertTrue(CacheProperties.isStorage(this.config)); + System.clearProperty(CacheProperties.STORAGE.get()); + } + +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/MockCacheWriter.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/MockCacheWriter.java new file mode 100644 index 00000000..4856cef9 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/MockCacheWriter.java @@ -0,0 +1,28 @@ +package org.eclipse.store.integrations.cdi.types.cache; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import javax.cache.configuration.Factory; +import javax.cache.integration.CacheWriter; + + +public class MockCacheWriter implements Factory> +{ + @Override + public CacheWriter create() + { + return null; + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/MockExpiryPolicy.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/MockExpiryPolicy.java new file mode 100644 index 00000000..6319fb37 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/MockExpiryPolicy.java @@ -0,0 +1,30 @@ +package org.eclipse.store.integrations.cdi.types.cache; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import javax.cache.configuration.Factory; +import javax.cache.expiry.EternalExpiryPolicy; +import javax.cache.expiry.ExpiryPolicy; + + +public class MockExpiryPolicy implements Factory +{ + @Override + public ExpiryPolicy create() + { + return new EternalExpiryPolicy(); + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/MockLoaderFactory.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/MockLoaderFactory.java new file mode 100644 index 00000000..5a79338e --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/MockLoaderFactory.java @@ -0,0 +1,29 @@ +package org.eclipse.store.integrations.cdi.types.cache; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import javax.cache.configuration.Factory; +import javax.cache.integration.CacheLoader; + + +public class MockLoaderFactory implements Factory> +{ + @Override + public CacheLoader create() + { + return null; + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/StorageCacheProducerTest.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/StorageCacheProducerTest.java new file mode 100644 index 00000000..8dba4076 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/StorageCacheProducerTest.java @@ -0,0 +1,74 @@ +package org.eclipse.store.integrations.cdi.types.cache; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import io.smallrye.config.inject.ConfigExtension; +import org.eclipse.store.integrations.cdi.types.config.StorageManagerProducer; +import org.eclipse.store.integrations.cdi.types.extension.StorageExtension; +import org.jboss.weld.junit5.auto.AddBeanClasses; +import org.jboss.weld.junit5.auto.AddExtensions; +import org.jboss.weld.junit5.auto.EnableAutoWeld; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import javax.cache.Cache; +import jakarta.enterprise.inject.spi.Bean; +import jakarta.enterprise.inject.spi.BeanManager; +import jakarta.inject.Inject; +import java.util.Set; + + +@EnableAutoWeld +@AddBeanClasses({StorageCacheProducer.class, StorageManagerProducer.class}) // For @StorageCache +@AddExtensions({StorageExtension.class, ConfigExtension.class}) +// SmallRye Config extension And EclipseStore extension for StorageManager +public class StorageCacheProducerTest +{ + @Inject + @StorageCache + private Cache cache; + + @Inject + @StorageCache("jcache2") + private Cache cacheB; + + @Inject + private BeanManager beanManager; + + @Test + public void shouldCreateInjectCache() + { + this.cache.put(1, "one"); + Assertions.assertEquals("one", this.cache.get(1)); + } + + @Test + public void shouldNotCreateNonQualifierCache() + { + final Set> beans = this.beanManager.getBeans(Cache.class); + Assertions.assertEquals(0, beans.size()); + } + + @Test + public void shouldShouldHaveDifferentInstance() + { + this.cache.put(1, "one"); + Assertions.assertNotEquals(this.cache, this.cacheB); + Assertions.assertTrue(this.cache.containsKey(1)); + Assertions.assertFalse(this.cacheB.containsKey(1)); + } + +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/StorageCacheTest.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/StorageCacheTest.java new file mode 100644 index 00000000..eaf6935b --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/cache/StorageCacheTest.java @@ -0,0 +1,80 @@ +package org.eclipse.store.integrations.cdi.types.cache; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + + +import java.util.Optional; + +import io.smallrye.config.inject.ConfigExtension; +import jakarta.inject.Inject; +import javax.cache.Cache; +import org.eclipse.store.integrations.cdi.ConfigurationCoreProperties; +import org.eclipse.store.integrations.cdi.types.config.StorageManagerProducer; +import org.eclipse.store.integrations.cdi.types.extension.StorageExtension; +import org.eclipse.store.integrations.cdi.types.logging.TestAppender; +import org.eclipse.store.storage.types.Database; +import org.eclipse.store.storage.types.Databases; +import org.eclipse.store.storage.types.StorageManager; +import org.jboss.weld.junit5.auto.AddBeanClasses; +import org.jboss.weld.junit5.auto.AddExtensions; +import org.jboss.weld.junit5.auto.EnableAutoWeld; +import org.junit.jupiter.api.*; + +@EnableAutoWeld // So that Weld container is started +@AddBeanClasses({StorageCacheProducer.class, StorageManagerProducer.class}) // For @StorageCache +@AddExtensions({StorageExtension.class, ConfigExtension.class}) +// SmallRye Config extension And EclipseStore extension for StorageManager +public class StorageCacheTest +{ + + @Inject + @StorageCache("storage") + private Cache cache; + + @BeforeAll + public static void beforeAll() + { + System.setProperty(CacheProperties.STORAGE.get(), Boolean.TRUE.toString()); + System.setProperty(ConfigurationCoreProperties.STORAGE_DIRECTORY.getMicroProfile(), "target/cache"); + TestAppender.events.clear(); + } + + @AfterAll + public static void afterAll() + { + System.clearProperty(CacheProperties.STORAGE.get()); + System.clearProperty(ConfigurationCoreProperties.STORAGE_DIRECTORY.getMicroProfile()); + } + + @AfterEach + public void cleanup() + { + // The @Disposes (calling StorageManager.shutdown) is not picked up by Weld-Unit, + // Need to shut down it here. + Databases databases = Databases.get(); + Database generic = databases.get("Generic"); + Optional.ofNullable(generic.storage()).ifPresent(StorageManager::shutdown); + } + + @Test + public void shouldCacheValues() + { + Assertions.assertNotNull(cache); + this.cache.put(1, "one"); + Assertions.assertNotNull(cache.get(1)); + } + +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/AbstractStorageManagerConverterTest.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/AbstractStorageManagerConverterTest.java new file mode 100644 index 00000000..c23b8b18 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/AbstractStorageManagerConverterTest.java @@ -0,0 +1,86 @@ +package org.eclipse.store.integrations.cdi.types.config; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import ch.qos.logback.classic.spi.ILoggingEvent; +import org.eclipse.store.integrations.cdi.types.logging.TestAppender; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.slf4j.event.LoggingEvent; + +import java.io.File; +import java.io.FilenameFilter; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +public abstract class AbstractStorageManagerConverterTest +{ + + // We cannot clean messages in BeforeEach (that would clear the messages that are written + // during initialization of the Weld container and thus also the StorageManagerConverter. + @BeforeAll + public static void setup() + { + TestAppender.events.clear(); + } + + @AfterEach + public void cleanup() + { + TestAppender.events.clear(); + } + + protected void hasMessage(List messages, String msg) + { + final Optional loggingEvent = messages.stream() + .filter(le -> le.getMessage() + .equals(msg)) + .findAny(); + + Assertions.assertTrue(loggingEvent.isPresent()); + + } + + protected void directoryHasChannels(final File storageDirectory, final int channelCount) + { + final String[] channelDirectories = storageDirectory.list(this.channelDirectory()); + Assertions.assertNotNull(channelDirectories); + Assertions.assertEquals(channelCount, channelDirectories.length); + Arrays.stream(channelDirectories) + .forEach( + c -> + { + final String[] channelParts = c.split("_"); // It guaranteed starts with 'channel_' so split always has 2 items + final String[] dataFiles = new File(storageDirectory, c).list(this.channelDataFile(channelParts[1])); + Assertions.assertNotNull(dataFiles); + Assertions.assertEquals(1, dataFiles.length); + } + ); + + } + + private FilenameFilter channelDirectory() + { + return (current, name) -> new File(current, name).isDirectory() && name.startsWith("channel_"); + } + + private FilenameFilter channelDataFile(final String channel) + { + return (current, name) -> new File(current, name).isFile() && name.equals("channel_" + channel + "_1.dat"); + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverterINITest.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverterINITest.java new file mode 100644 index 00000000..eaa517ad --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverterINITest.java @@ -0,0 +1,72 @@ + +package org.eclipse.store.integrations.cdi.types.config; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import java.io.File; +import java.util.List; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import io.smallrye.config.inject.ConfigExtension; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.store.integrations.cdi.types.logging.TestAppender; +import org.eclipse.store.storage.types.StorageManager; +import org.jboss.weld.junit5.auto.AddExtensions; +import org.jboss.weld.junit5.auto.EnableAutoWeld; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + + +@EnableAutoWeld +@AddExtensions(ConfigExtension.class) // SmallRye Config extension to Support MicroProfile Config within this test +@DisplayName("Check if the Storage Manager will load using a INI file") +public class StorageManagerConverterINITest extends AbstractStorageManagerConverterTest +{ + @Inject + @ConfigProperty(name = "org.eclipse.store.ini") + private StorageManager manager; + + @ApplicationScoped + @Produces + // To verify if the 'manager' above comes from the StorageManagerConverter and not just injection + // of the mock. The creation of the channel directories is also an indication. + private StorageManager storageManagerMock = Mockito.mock(StorageManager.class); + + @Test + public void shouldLoadFromIni() + { + Assertions.assertNotNull(this.manager); + Assertions.assertTrue(this.manager instanceof StorageManagerProxy); + final boolean active = this.manager.isActive();// We have the proxy, need to start it to see the log messages. + // Don't use this.manager.isActive() as it is started already by the proxy. + Assertions.assertTrue(active); + + final List messages = TestAppender.getMessagesOfLevel(Level.INFO); + + hasMessage(messages, "Loading configuration to start the class StorageManager from the key: storage.ini"); + hasMessage(messages, "Embedded storage manager initialized"); + + this.directoryHasChannels(new File("target/ini"), 1); + + Assertions.assertEquals("ini-based", this.manager.databaseName()); + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverterPropertiesTest.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverterPropertiesTest.java new file mode 100644 index 00000000..1311e1c2 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverterPropertiesTest.java @@ -0,0 +1,67 @@ +package org.eclipse.store.integrations.cdi.types.config; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.io.File; +import java.util.List; +import java.util.Optional; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import io.smallrye.config.inject.ConfigExtension; +import jakarta.inject.Inject; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.store.integrations.cdi.types.logging.TestAppender; +import org.eclipse.store.storage.types.StorageManager; +import org.jboss.weld.junit5.auto.AddExtensions; +import org.jboss.weld.junit5.auto.EnableAutoWeld; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + + +@EnableAutoWeld +@AddExtensions(ConfigExtension.class) // SmallRye Config extension to Support MicroProfile Config within this test +@DisplayName("Check if the Storage Manager will load using a property file") +public class StorageManagerConverterPropertiesTest extends AbstractStorageManagerConverterTest +{ + @Inject + @ConfigProperty(name = "org.eclipse.store.properties") + private StorageManager manager; + + + @Test + public void shouldLoadFromProperties() + { + Assertions.assertNotNull(this.manager); + Assertions.assertTrue(this.manager instanceof StorageManagerProxy); + final boolean active = this.manager.isActive();// We have the proxy, need to start it to see the log messages. + // Don't use this.manager.isActive() as it is started already by the proxy. + Assertions.assertTrue(active); + + final List messages = TestAppender.getMessagesOfLevel(Level.INFO); + + Assertions.assertNotEquals(0, TestAppender.events.size()); + + hasMessage(messages, "Loading configuration to start the class StorageManager from the key: storage.properties"); + hasMessage(messages, "Embedded storage manager initialized"); + + this.directoryHasChannels(new File("target/prop"), 2); + + // No database-name defined in file so it takes the filename (value of "org.eclipse.store.properties" MP key) + Assertions.assertEquals("storage.properties", this.manager.databaseName()); + } + +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverterTest.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverterTest.java new file mode 100644 index 00000000..511b14ec --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverterTest.java @@ -0,0 +1,54 @@ +package org.eclipse.store.integrations.cdi.types.config; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import io.smallrye.config.inject.ConfigExtension; +import org.eclipse.store.integrations.cdi.types.extension.StorageExtension; +import org.eclipse.store.storage.types.StorageManager; +import org.jboss.weld.junit5.auto.AddExtensions; +import org.jboss.weld.junit5.auto.EnableAutoWeld; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; + + +@EnableAutoWeld +@AddExtensions(ConfigExtension.class) // SmallRye Config extension to Support MicroProfile Config within this test +@AddExtensions(StorageExtension.class) +@DisplayName("Check if the Storage Manager will load using the default MicroProfile Properties file") +public class StorageManagerConverterTest extends AbstractStorageManagerConverterTest +{ + @Inject + private StorageManager manager; + + @ApplicationScoped + @Produces + private StorageManager storageManagerMock = Mockito.mock(StorageManager.class); + + @Test + public void shouldBeFromProducer() + { + Assertions.assertNotNull(this.manager); + //Assertions.assertSame(this.storageManagerMock, this.manager); + //Although it is the same instance, the types are different and thus assertSame fails + Assertions.assertEquals(this.storageManagerMock.toString(), this.manager.toString()); + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverterXMLTest.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverterXMLTest.java new file mode 100644 index 00000000..8a60f450 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerConverterXMLTest.java @@ -0,0 +1,62 @@ +package org.eclipse.store.integrations.cdi.types.config; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import jakarta.inject.Inject; + +import io.smallrye.config.inject.ConfigExtension; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.store.integrations.cdi.types.logging.TestAppender; +import org.eclipse.store.storage.types.StorageManager; +import org.jboss.weld.junit5.auto.AddExtensions; +import org.jboss.weld.junit5.auto.EnableAutoWeld; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + + +import java.io.File; +import java.util.List; + + +@EnableAutoWeld +@AddExtensions(ConfigExtension.class) // SmallRye Config extension to Support MicroProfile Config within this test +@DisplayName("Check if the Storage Manager will load using a XML file") +public class StorageManagerConverterXMLTest extends AbstractStorageManagerConverterTest +{ + @Inject + @ConfigProperty(name = "org.eclipse.store.xml") + private StorageManager manager; + + @Test + public void shouldLoadFromXML() + { + Assertions.assertNotNull(this.manager); + Assertions.assertTrue(this.manager instanceof StorageManagerProxy); + final boolean active = this.manager.isActive();// We have the proxy, need to start it to see the log messages. + // Don't use this.manager.isActive() as it is started already by the proxy. + Assertions.assertTrue(active); + + final List messages = TestAppender.getMessagesOfLevel(Level.INFO); + + hasMessage(messages, "Loading configuration to start the class StorageManager from the key: storage.xml"); + hasMessage(messages, "Embedded storage manager initialized"); + + this.directoryHasChannels(new File("target/xml"), 4); + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducerCustomizerTest.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducerCustomizerTest.java new file mode 100644 index 00000000..767eb58a --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducerCustomizerTest.java @@ -0,0 +1,142 @@ +package org.eclipse.store.integrations.cdi.types.config; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.integrations.cdi.types.config.test.SomeEmbeddedStorageFoundationCustomizer; +import org.eclipse.store.integrations.cdi.types.config.test.SomeStorageManagerInitializer; +import org.eclipse.store.integrations.cdi.types.extension.StorageExtension; +import org.eclipse.microprofile.config.Config; +import org.eclipse.store.integrations.cdi.types.logging.TestAppender; +import org.eclipse.store.storage.types.Database; +import org.eclipse.store.storage.types.Databases; +import org.eclipse.store.storage.types.StorageManager; +import org.jboss.weld.junit5.EnableWeld; +import org.jboss.weld.junit5.WeldInitiator; +import org.jboss.weld.junit5.WeldSetup; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +@EnableWeld +class StorageManagerProducerCustomizerTest +{ + public static final String STORAGE_DIRECTORY = "org.eclipse.store.storage-directory"; + // Test the StorageManagerProducer + // - Support for creating a StorageManager based on configuration values (when no MicroProfile Config one used) + + @WeldSetup + public WeldInitiator weld = WeldInitiator.of(StorageManagerProducer.class + , StorageManagerProducerCustomizerTest.class + , SomeEmbeddedStorageFoundationCustomizer.class + , SomeStorageManagerInitializer.class); + + @Inject + private StorageManagerProducer storageManagerProducer; + + @Inject + private Instance customizers; + + @Inject + private Instance initializers; + + @BeforeEach + public void setup() + { + TestAppender.events.clear(); + } + + @AfterEach + public void cleanup() + { + // The @Disposes (calling StorageManager.shutdown) is not picked up by Weld-Unit, + // Need to shut down it here. + Databases databases = Databases.get(); + Database generic = databases.get("Generic"); + Optional.ofNullable(generic.storage()) + .ifPresent(StorageManager::shutdown); + } + + private static Config configMock; + + @Produces + Config produceConfigMock() + { + configMock = Mockito.mock(Config.class); + Mockito.when(configMock.getPropertyNames()) + .thenReturn(Arrays.asList(STORAGE_DIRECTORY)); + Mockito.when(configMock.getOptionalValue(STORAGE_DIRECTORY, String.class)) + .thenReturn(Optional.of("target/storage-customized")); + return configMock; + } + + + private static StorageExtension storageExtensionMock; + + @Produces + StorageExtension produceStorageExtension() + { + storageExtensionMock = Mockito.mock(StorageExtension.class); + // This means we have no @Inject @ConfigProperty StorageManager + // And thus should create StorageManger using Builder and load all Config Property keys. + final Set names = Collections.emptySet(); + Mockito.when(storageExtensionMock.getStorageManagerConfigInjectionNames()) + .thenReturn(names); + + return storageExtensionMock; + } + + @Test + void getStoreManager_customizeInitializer() + { + + StorageManager storageManager = storageManagerProducer.getStorageManager(); + Assertions.assertNotNull(storageManager); + + Mockito.verify(configMock) + .getPropertyNames(); // Test if all config property keys are used. + + final List foundationCustomizers = customizers.stream() + .map(SomeEmbeddedStorageFoundationCustomizer.class::cast) + .collect(Collectors.toList()); + Assertions.assertEquals(foundationCustomizers.size(), 1); + + Assertions.assertTrue(foundationCustomizers.get(0) + .isCustomizeCalled()); + + final List managerInitializers = initializers.stream() + .map(SomeStorageManagerInitializer.class::cast) + .collect(Collectors.toList()); + Assertions.assertEquals(managerInitializers.size(), 1); + + Assertions.assertTrue(managerInitializers.get(0) + .isInitializerCalled()); + Assertions.assertTrue(managerInitializers.get(0) + .isManagerRunning()); + + + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducerFromConfigPropertyInjectionTest.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducerFromConfigPropertyInjectionTest.java new file mode 100644 index 00000000..e9dc0c3e --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducerFromConfigPropertyInjectionTest.java @@ -0,0 +1,102 @@ +package org.eclipse.store.integrations.cdi.types.config; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import org.eclipse.store.integrations.cdi.types.extension.StorageExtension; +import org.eclipse.microprofile.config.Config; +import org.eclipse.store.integrations.cdi.types.logging.TestAppender; +import org.eclipse.store.storage.types.StorageManager; +import org.jboss.weld.junit5.EnableWeld; +import org.jboss.weld.junit5.WeldInitiator; +import org.jboss.weld.junit5.WeldSetup; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +@EnableWeld +class StorageManagerProducerFromConfigPropertyInjectionTest +{ + // Test the StorageManagerProducer + // - Use the StorageManager from MicroProfile Config Converter (which uses external files like ini or xml) + + @WeldSetup + public WeldInitiator weld = WeldInitiator.of(StorageManagerProducer.class, StorageManagerProducerFromConfigPropertyInjectionTest.class); + + @Inject + private StorageManagerProducer storageManagerProducer; + + @BeforeEach + public void setup() + { + TestAppender.events.clear(); + } + + private static Config configMock; + + @Produces + Config produceConfigMock() + { + configMock = Mockito.mock(Config.class); + return configMock; + } + + + private static StorageExtension storageExtensionMock; + + @Produces + StorageExtension produceStorageExtension() + { + storageExtensionMock = Mockito.mock(StorageExtension.class); + // This means we do have a @Inject @ConfigProperty StorageManager construct + // And thus should 'take' StorageManger from MicroProfileConfig directly. + final Set names = Set.of("org.eclipse.store.ini"); + Mockito.when(storageExtensionMock.getStorageManagerConfigInjectionNames()) + .thenReturn(names); + + return storageExtensionMock; + } + + @Test + void getStoreManager_fromConfigPropertyInjection() + { + + StorageManager storageManager = storageManagerProducer.getStorageManager(); + Assertions.assertNull(storageManager); // Since we did not mock ConfigMock.getValue() + + // + Mockito.verify(configMock) + .getValue("org.eclipse.store.ini", StorageManager.class); // Test if StorageManager from Config taken + Mockito.verifyNoMoreInteractions(configMock); + + // Another test to prove we did not create a real Storage Manager + List messages = TestAppender.getMessagesOfLevel(Level.INFO); + Optional loggingEvent = messages.stream() + .filter(le -> le.getMessage() + .equals("Embedded storage manager initialized")) + .findAny(); + + Assertions.assertFalse(loggingEvent.isPresent()); + + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducerNoConfigPropertyTest.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducerNoConfigPropertyTest.java new file mode 100644 index 00000000..9ccf19c5 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducerNoConfigPropertyTest.java @@ -0,0 +1,125 @@ +package org.eclipse.store.integrations.cdi.types.config; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import org.eclipse.store.integrations.cdi.types.extension.StorageExtension; + +import org.eclipse.microprofile.config.Config; +import org.eclipse.store.integrations.cdi.types.logging.TestAppender; +import org.eclipse.store.storage.types.Database; +import org.eclipse.store.storage.types.Databases; +import org.eclipse.store.storage.types.StorageManager; +import org.jboss.weld.junit5.EnableWeld; +import org.jboss.weld.junit5.WeldInitiator; +import org.jboss.weld.junit5.WeldSetup; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.slf4j.event.LoggingEvent; + +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +@EnableWeld +class StorageManagerProducerNoConfigPropertyTest +{ + public static final String STORAGE_DIRECTORY = "org.eclipse.store.storage-directory"; + // Test the StorageManagerProducer + // - Support for creating a StorageManager based on configuration values (when no MicroProfile Config one used) + + @WeldSetup + public WeldInitiator weld = WeldInitiator.of(StorageManagerProducer.class, StorageManagerProducerNoConfigPropertyTest.class); + + @Inject + private StorageManagerProducer storageManagerProducer; + + @BeforeEach + public void setup() + { + TestAppender.events.clear(); + } + + @AfterEach + public void cleanup() + { + // The @Disposes (calling StorageManager.shutdown) is not picked up by Weld-Unit, + // Need to shut down it here. + Databases databases = Databases.get(); + Database generic = databases.get("Generic"); + Optional.ofNullable(generic.storage()) + .ifPresent(StorageManager::shutdown); + } + + private static Config configMock; + + @Produces + Config produceConfigMock() + { + configMock = Mockito.mock(Config.class); + Mockito.when(configMock.getPropertyNames()) + .thenReturn(Arrays.asList(STORAGE_DIRECTORY)); + Mockito.when(configMock.getOptionalValue(STORAGE_DIRECTORY, String.class)) + .thenReturn(Optional.of("target/storage")); + return configMock; + } + + + private static StorageExtension storageExtensionMock; + + @Produces + StorageExtension produceStorageExtension() + { + storageExtensionMock = Mockito.mock(StorageExtension.class); + // This means we have no @Inject @ConfigProperty StorageManager + // And thus should create StorageManger using Builder and load all Config Property keys. + final Set names = Collections.emptySet(); + Mockito.when(storageExtensionMock.getStorageManagerConfigInjectionNames()) + .thenReturn(names); + + return storageExtensionMock; + } + + @Test + void getStoreManager_noConfigPropertyInjection() + { + + StorageManager storageManager = storageManagerProducer.getStorageManager(); + Assertions.assertNotNull(storageManager); + + Mockito.verify(configMock) + .getPropertyNames(); // Test if all config property keys are used. + + // Another test to prove a real StorageManager is created to have a look at the logs + List messages = TestAppender.getMessagesOfLevel(Level.INFO); + + Optional loggingEvent = messages.stream() + .filter(le -> le.getMessage() + .equals("Embedded storage manager initialized")) + .findAny(); + + Assertions.assertTrue(loggingEvent.isPresent()); + + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducerNotStartedTest.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducerNotStartedTest.java new file mode 100644 index 00000000..771e38d5 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/StorageManagerProducerNotStartedTest.java @@ -0,0 +1,135 @@ +package org.eclipse.store.integrations.cdi.types.config; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import org.eclipse.store.integrations.cdi.types.config.test.SomeStorageManagerInitializer; +import org.eclipse.store.integrations.cdi.types.extension.StorageExtension; + +import org.eclipse.microprofile.config.Config; +import org.eclipse.store.integrations.cdi.types.logging.TestAppender; +import org.eclipse.store.storage.types.Database; +import org.eclipse.store.storage.types.Databases; +import org.eclipse.store.storage.types.StorageManager; +import org.jboss.weld.junit5.EnableWeld; +import org.jboss.weld.junit5.WeldInitiator; +import org.jboss.weld.junit5.WeldSetup; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +@EnableWeld +class StorageManagerProducerNotStartedTest +{ + public static final String STORAGE_DIRECTORY = "org.eclipse.store.storage-directory"; + public static final String AUTO_START = "org.eclipse.store.autoStart"; + + // Test the StorageManagerProducer + // - Support for creating a StorageManager based on configuration values (when no MicroProfile Config one used) + + @WeldSetup + public WeldInitiator weld = WeldInitiator.of(StorageManagerProducer.class + , StorageManagerProducerNotStartedTest.class + , SomeStorageManagerInitializer.class); + + @Inject + private StorageManagerProducer storageManagerProducer; + + @Inject + private Instance initializers; + + @BeforeEach + public void setup() + { + TestAppender.events.clear(); + } + + @AfterEach + public void cleanup() + { + // The @Disposes (calling StorageManager.shutdown) is not picked up by Weld-Unit, + // Need to shut down it here. + Databases databases = Databases.get(); + Database generic = databases.get("Generic"); + Optional.ofNullable(generic.storage()) + .ifPresent(StorageManager::shutdown); + } + + private static Config configMock; + + @Produces + Config produceConfigMock() + { + configMock = Mockito.mock(Config.class); + Mockito.when(configMock.getPropertyNames()) + .thenReturn(Arrays.asList(STORAGE_DIRECTORY, AUTO_START)); + Mockito.when(configMock.getOptionalValue(STORAGE_DIRECTORY, String.class)) + .thenReturn(Optional.of("target/storage-not-started")); + Mockito.when(configMock.getOptionalValue(AUTO_START, String.class)) + .thenReturn(Optional.of("false")); + return configMock; + } + + + private static StorageExtension storageExtensionMock; + + @Produces + StorageExtension produceStorageExtension() + { + storageExtensionMock = Mockito.mock(StorageExtension.class); + // This means we have no @Inject @ConfigProperty StorageManager + // And thus should create StorageManger using Builder and load all Config Property keys. + final Set names = Collections.emptySet(); + Mockito.when(storageExtensionMock.getStorageManagerConfigInjectionNames()) + .thenReturn(names); + + return storageExtensionMock; + } + + @Test + void getStoreManager_noAutoStart() + { + + StorageManager storageManager = storageManagerProducer.getStorageManager(); + Assertions.assertNotNull(storageManager); + + Mockito.verify(configMock) + .getPropertyNames(); // Test if all config property keys are used. + + final List managerInitializers = initializers.stream() + .map(SomeStorageManagerInitializer.class::cast) + .collect(Collectors.toList()); + Assertions.assertEquals(managerInitializers.size(), 1); + + Assertions.assertTrue(managerInitializers.get(0) + .isInitializerCalled()); + Assertions.assertFalse(managerInitializers.get(0) + .isManagerRunning()); + + + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/test/SomeEmbeddedStorageFoundationCustomizer.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/test/SomeEmbeddedStorageFoundationCustomizer.java new file mode 100644 index 00000000..e6bfc21c --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/test/SomeEmbeddedStorageFoundationCustomizer.java @@ -0,0 +1,38 @@ +package org.eclipse.store.integrations.cdi.types.config.test; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import org.eclipse.store.integrations.cdi.types.config.EmbeddedStorageFoundationCustomizer; + +import jakarta.enterprise.context.ApplicationScoped; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; + +@ApplicationScoped +public class SomeEmbeddedStorageFoundationCustomizer implements EmbeddedStorageFoundationCustomizer +{ + private boolean customizeCalled; + + @Override + public void customize(final EmbeddedStorageFoundation embeddedStorageFoundation) + { + this.customizeCalled = true; + } + + public boolean isCustomizeCalled() + { + return customizeCalled; + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/test/SomeStorageManagerInitializer.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/test/SomeStorageManagerInitializer.java new file mode 100644 index 00000000..24e9d81c --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/config/test/SomeStorageManagerInitializer.java @@ -0,0 +1,47 @@ +package org.eclipse.store.integrations.cdi.types.config.test; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import org.eclipse.store.integrations.cdi.types.config.StorageManagerInitializer; + +import jakarta.enterprise.context.ApplicationScoped; +import org.eclipse.store.storage.types.StorageManager; + +@ApplicationScoped +public class SomeStorageManagerInitializer implements StorageManagerInitializer +{ + + private boolean initializerCalled; + + private boolean managerRunning; + + @Override + public void initialize(final StorageManager storageManager) + { + this.initializerCalled = true; + this.managerRunning = storageManager.isRunning(); + } + + public boolean isInitializerCalled() + { + return initializerCalled; + } + + public boolean isManagerRunning() + { + return managerRunning; + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/Animal.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/Animal.java new file mode 100644 index 00000000..9e9e0e34 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/Animal.java @@ -0,0 +1,23 @@ +package org.eclipse.store.integrations.cdi.types.extension; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + + + + +interface Animal +{ +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/Cat.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/Cat.java new file mode 100644 index 00000000..d986ad22 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/Cat.java @@ -0,0 +1,26 @@ +package org.eclipse.store.integrations.cdi.types.extension; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + + + + +public class Cat +{ + public Cat() + { + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/ConstructorUtilTest.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/ConstructorUtilTest.java new file mode 100644 index 00000000..cb6a4272 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/ConstructorUtilTest.java @@ -0,0 +1,63 @@ + +package org.eclipse.store.integrations.cdi.types.extension; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + + + + +import org.eclipse.serializer.exceptions.NoSuchMethodRuntimeException; +import org.eclipse.serializer.reflect.XReflect; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + + +class ConstructorUtilTest +{ + @Test + @DisplayName("Should return NPE when it uses") + public void shouldReturnNPEWhenThereIsNull() + { + Assertions.assertThrows(NullPointerException.class, () -> XReflect.defaultInstantiate(null)); + } + + @Test + public void shouldReturnErrorWhenThereIsInterface() + { + Assertions.assertThrows(NoSuchMethodRuntimeException.class, () -> XReflect.defaultInstantiate(Animal.class)); + } + + @Test + public void shouldReturnErrorWhenThereNoDefaultConstructor() + { + Assertions.assertThrows(NoSuchMethodRuntimeException.class, () -> XReflect.defaultInstantiate(Lion.class)); + } + + @Test + public void shouldReturnConstructor() + { + final Tiger tiger = XReflect.defaultInstantiate(Tiger.class); + Assertions.assertNotNull(tiger); + } + + @Test + public void shouldCreateDefaultConstructor() + { + final Cat cat = XReflect.defaultInstantiate(Cat.class); + Assertions.assertNotNull(cat); + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/Lion.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/Lion.java new file mode 100644 index 00000000..6a0bf160 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/Lion.java @@ -0,0 +1,34 @@ +package org.eclipse.store.integrations.cdi.types.extension; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + + + + +class Lion +{ + private final String name; + + public Lion(final String name) + { + this.name = name; + } + + public String getName() + { + return this.name; + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/Tiger.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/Tiger.java new file mode 100644 index 00000000..885266dc --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/extension/Tiger.java @@ -0,0 +1,26 @@ +package org.eclipse.store.integrations.cdi.types.extension; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + + + + +public class Tiger +{ + public Tiger() + { + } +} diff --git a/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/logging/TestAppender.java b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/logging/TestAppender.java new file mode 100644 index 00000000..72b69fc5 --- /dev/null +++ b/integrations/cdi4/src/test/java/org/eclipse/store/integrations/cdi/types/logging/TestAppender.java @@ -0,0 +1,55 @@ +package org.eclipse.store.integrations.cdi.types.logging; + +/*- + * #%L + * EclipseStore Integrations CDI 4 + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import org.slf4j.event.LoggingEvent; + +public class TestAppender extends AppenderBase +{ + public static List events = new ArrayList<>(); + + @Override + protected void append(ILoggingEvent e) { + events.add(e); + } + + /** + * Returns the logging events (messages) for a specified {@link Level} or all messages. The order is as how the + * logging events are created. + * + * @param level The {@link Level} of the messages you are interested or null if you want them all. + * @return List with logging events for the specified {@link Level} or all. + */ + public static List getMessagesOfLevel(final Level level) + { + Stream stream = Arrays.stream(events.toArray(new ILoggingEvent[0])); + if (level != null) + { + stream = stream.filter(le -> le.getLevel() + .equals(level)); + } + return stream.collect(Collectors.toList()); + } +} diff --git a/integrations/cdi4/src/test/resources/META-INF/beans.xml b/integrations/cdi4/src/test/resources/META-INF/beans.xml new file mode 100644 index 00000000..3d36ec3b --- /dev/null +++ b/integrations/cdi4/src/test/resources/META-INF/beans.xml @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/integrations/cdi4/src/test/resources/META-INF/microprofile-config.properties b/integrations/cdi4/src/test/resources/META-INF/microprofile-config.properties new file mode 100644 index 00000000..888d99f7 --- /dev/null +++ b/integrations/cdi4/src/test/resources/META-INF/microprofile-config.properties @@ -0,0 +1,11 @@ + +org.eclipse.store.xml=storage.xml +org.eclipse.store.ini=storage.ini +org.eclipse.store.properties=storage.properties + +org.eclipse.store.storage.directory=target/storage + +#eclipse store +storage-directory=target/properties +channel-count=4 +smallrye.config.log.values=true diff --git a/integrations/cdi4/src/test/resources/beans.xml b/integrations/cdi4/src/test/resources/beans.xml new file mode 100644 index 00000000..f5a21f65 --- /dev/null +++ b/integrations/cdi4/src/test/resources/beans.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/integrations/cdi4/src/test/resources/junit-platform.properties b/integrations/cdi4/src/test/resources/junit-platform.properties new file mode 100644 index 00000000..c72b2c81 --- /dev/null +++ b/integrations/cdi4/src/test/resources/junit-platform.properties @@ -0,0 +1 @@ +junit.jupiter.execution.parallel.enabled = false diff --git a/integrations/cdi4/src/test/resources/logback-test.xml b/integrations/cdi4/src/test/resources/logback-test.xml new file mode 100644 index 00000000..8539c809 --- /dev/null +++ b/integrations/cdi4/src/test/resources/logback-test.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/integrations/cdi4/src/test/resources/storage.ini b/integrations/cdi4/src/test/resources/storage.ini new file mode 100644 index 00000000..a759c0a5 --- /dev/null +++ b/integrations/cdi4/src/test/resources/storage.ini @@ -0,0 +1,3 @@ +storage-directory = target/ini +channel-count = 1 +database-name=ini-based \ No newline at end of file diff --git a/integrations/cdi4/src/test/resources/storage.properties b/integrations/cdi4/src/test/resources/storage.properties new file mode 100644 index 00000000..64929c1b --- /dev/null +++ b/integrations/cdi4/src/test/resources/storage.properties @@ -0,0 +1,3 @@ + +storage-directory = target/prop +channel-count = 2 \ No newline at end of file diff --git a/integrations/cdi4/src/test/resources/storage.xml b/integrations/cdi4/src/test/resources/storage.xml new file mode 100644 index 00000000..0df9f562 --- /dev/null +++ b/integrations/cdi4/src/test/resources/storage.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/integrations/pom.xml b/integrations/pom.xml index 99deb477..3088e9a9 100644 --- a/integrations/pom.xml +++ b/integrations/pom.xml @@ -15,6 +15,10 @@ EclipseStore Integrations Parent pom + + cdi4 + + from_java_17 From dc2eb49dba24eda0c03e7e41b8bb182c093a61cb Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Mon, 4 Mar 2024 14:22:56 +0100 Subject: [PATCH 081/126] fix versions (#161) --- examples/wildfly-cdi4/pom.xml | 4 ++-- integrations/cdi4/pom.xml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/wildfly-cdi4/pom.xml b/examples/wildfly-cdi4/pom.xml index 9a2f9f80..3cc42b81 100644 --- a/examples/wildfly-cdi4/pom.xml +++ b/examples/wildfly-cdi4/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -36,7 +36,7 @@ org.eclipse.store eclipse-store-integrations-cdi4 - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.slf4j diff --git a/integrations/cdi4/pom.xml b/integrations/cdi4/pom.xml index d9ad8991..95130a84 100644 --- a/integrations/cdi4/pom.xml +++ b/integrations/cdi4/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store integrations - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT ../pom.xml @@ -37,12 +37,12 @@ org.eclipse.store storage-embedded - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.store storage-embedded-configuration - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT org.eclipse.serializer @@ -52,7 +52,7 @@ org.eclipse.store cache - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT From 5e3e3045c0b069966947b8cc5ce481fd712ffff8 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 5 Mar 2024 07:36:59 +0100 Subject: [PATCH 082/126] update deploysnaphot scripts --- .github/workflows/maven_deploy_snapshot_dev.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/maven_deploy_snapshot_dev.yml b/.github/workflows/maven_deploy_snapshot_dev.yml index 0c7de5b1..c9175da0 100644 --- a/.github/workflows/maven_deploy_snapshot_dev.yml +++ b/.github/workflows/maven_deploy_snapshot_dev.yml @@ -97,10 +97,14 @@ jobs: run: | mvn -pl integrations/spring-boot3 clean install -am -B mvn -P production -pl storage/rest/client-app clean install -am -B + mvn -P production -pl storage/rest/client-app-standalone-assembly clean install -am -B + mvn -P production -pl storage/rest/service-springboot clean install -am -B - name: Deploy module build with java 17 run: | mvn -Pdeploy -pl integrations/spring-boot3 deploy mvn -Pdeploy -Pproduction -pl storage/rest/client-app deploy + mvn -Pdeploy -Pproduction -pl storage/rest/client-app-standalone-assembly deploy + mvn -Pdeploy -Pproduction -pl storage/rest/service-springboot deploy env: MAVEN_USERNAME: ${{ secrets.ORG_OSSRH_USERNAME }} MAVEN_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} From 6eaa6b5d62d1dc1c395d259f0758359d7980dde9 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 5 Mar 2024 07:49:20 +0100 Subject: [PATCH 083/126] update deploysnaphot scripts --- .github/workflows/maven_deploy_snapshot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/maven_deploy_snapshot.yml b/.github/workflows/maven_deploy_snapshot.yml index 6eaf0b6f..5abcc8b8 100644 --- a/.github/workflows/maven_deploy_snapshot.yml +++ b/.github/workflows/maven_deploy_snapshot.yml @@ -53,10 +53,14 @@ jobs: run: | mvn -pl integrations/spring-boot3 clean install -am -B mvn -P production -pl storage/rest/client-app clean install -am -B + mvn -P production -pl storage/rest/client-app-standalone-assembly clean install -am -B + mvn -P production -pl storage/rest/service-springboot clean install -am -B - name: Deploy module build with java 17 run: | mvn -Pdeploy -pl integrations/spring-boot3 deploy mvn -Pdeploy -Pproduction -pl storage/rest/client-app deploy + mvn -Pdeploy -Pproduction -pl storage/rest/client-app-standalone-assembly deploy + mvn -Pdeploy -Pproduction -pl storage/rest/service-springboot deploy env: MAVEN_USERNAME: ${{ secrets.ORG_OSSRH_USERNAME }} MAVEN_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} From e308cbf3df8c9eef7327e508c7b22ccaa9e205d3 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 5 Mar 2024 10:44:54 +0100 Subject: [PATCH 084/126] Zj/fix deploy 0324 (#163) * update deploysnaphot scripts * fix configuration for making standalone file --- storage/rest/client-app-standalone-assembly/pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/storage/rest/client-app-standalone-assembly/pom.xml b/storage/rest/client-app-standalone-assembly/pom.xml index 15bfb512..a7495dc6 100644 --- a/storage/rest/client-app-standalone-assembly/pom.xml +++ b/storage/rest/client-app-standalone-assembly/pom.xml @@ -85,10 +85,11 @@ spring-boot-maven-plugin ${spring.boot.version} - ${project.artifactId}-${project.version}-standalone + ${project.artifactId}-${project.version} org.eclipse.store.storage.restclient.app.standalone.types.Application -Dvaadin.productionMode + standalone JAR From 5df10eb86bd96fc1885d8e9a9e85a3404e9468cc Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 5 Mar 2024 11:39:16 +0100 Subject: [PATCH 085/126] set main dev version to 2. (#162) * set main dev version to 2. * update deploysnaphot scripts * serializer version --- afs/aws/aws/pom.xml | 4 ++-- afs/aws/dynamodb/pom.xml | 4 ++-- afs/aws/pom.xml | 2 +- afs/aws/s3/pom.xml | 4 ++-- afs/azure/pom.xml | 2 +- afs/azure/storage/pom.xml | 4 ++-- afs/blobstore/pom.xml | 2 +- afs/googlecloud/firestore/pom.xml | 2 +- afs/googlecloud/pom.xml | 4 ++-- afs/kafka/pom.xml | 4 ++-- afs/nio/pom.xml | 2 +- afs/oraclecloud/objectstorage/pom.xml | 4 ++-- afs/oraclecloud/pom.xml | 2 +- afs/pom.xml | 2 +- afs/redis/pom.xml | 4 ++-- afs/sql/pom.xml | 2 +- cache/cache/pom.xml | 6 +++--- cache/hibernate/pom.xml | 4 ++-- cache/pom.xml | 2 +- examples/blobs/pom.xml | 4 ++-- examples/custom-legacy-type-handler/pom.xml | 4 ++-- examples/custom-type-handler/pom.xml | 4 ++-- examples/deleting/pom.xml | 4 ++-- examples/eager-storing/pom.xml | 4 ++-- examples/extension-wrapper/pom.xml | 4 ++-- examples/filesystems/pom.xml | 4 ++-- examples/helloworld-ini/pom.xml | 6 +++--- examples/helloworld/pom.xml | 4 ++-- examples/items/pom.xml | 4 ++-- examples/layered-entities/pom.xml | 2 +- examples/lazy-loading/pom.xml | 4 ++-- examples/loading/pom.xml | 4 ++-- examples/pom.xml | 2 +- examples/reloader/pom.xml | 4 ++-- examples/spring-boot3-advanced/pom.xml | 6 +++--- examples/spring-boot3-simple/pom.xml | 6 +++--- examples/storing/pom.xml | 4 ++-- examples/wildfly-cdi4/pom.xml | 4 ++-- integrations/cdi4/pom.xml | 8 ++++---- integrations/itest/pom.xml | 2 +- integrations/pom.xml | 2 +- integrations/spring-boot3-console/pom.xml | 2 +- integrations/spring-boot3/pom.xml | 6 +++--- pom.xml | 4 ++-- storage/embedded-configuration/pom.xml | 4 ++-- storage/embedded-tools/pom.xml | 2 +- storage/embedded-tools/storage-converter/pom.xml | 4 ++-- storage/embedded-tools/storage-migrator/pom.xml | 2 +- storage/embedded/pom.xml | 4 ++-- storage/pom.xml | 2 +- storage/rest/adapter/pom.xml | 4 ++-- storage/rest/client-app-standalone-assembly/pom.xml | 2 +- storage/rest/client-app/pom.xml | 4 ++-- storage/rest/client-jersey/pom.xml | 4 ++-- storage/rest/client/pom.xml | 4 ++-- storage/rest/pom.xml | 2 +- storage/rest/service-sparkjava/pom.xml | 4 ++-- storage/rest/service-springboot/pom.xml | 2 +- storage/rest/service/pom.xml | 4 ++-- storage/storage/pom.xml | 4 ++-- 60 files changed, 107 insertions(+), 107 deletions(-) diff --git a/afs/aws/aws/pom.xml b/afs/aws/aws/pom.xml index a63a5edc..757e6486 100644 --- a/afs/aws/aws/pom.xml +++ b/afs/aws/aws/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-aws-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-blobstore - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/aws/dynamodb/pom.xml b/afs/aws/dynamodb/pom.xml index d61c57a4..cc9f360e 100644 --- a/afs/aws/dynamodb/pom.xml +++ b/afs/aws/dynamodb/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-aws-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-aws - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT software.amazon.awssdk diff --git a/afs/aws/pom.xml b/afs/aws/pom.xml index a2671eea..1c28882e 100644 --- a/afs/aws/pom.xml +++ b/afs/aws/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/afs/aws/s3/pom.xml b/afs/aws/s3/pom.xml index a2d9a432..a7f8eac6 100644 --- a/afs/aws/s3/pom.xml +++ b/afs/aws/s3/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-aws-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-aws - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT software.amazon.awssdk diff --git a/afs/azure/pom.xml b/afs/azure/pom.xml index 9fbb7d4e..1a97052f 100644 --- a/afs/azure/pom.xml +++ b/afs/azure/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/afs/azure/storage/pom.xml b/afs/azure/storage/pom.xml index 1310803e..0b286f34 100644 --- a/afs/azure/storage/pom.xml +++ b/afs/azure/storage/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-azure-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ org.eclipse.store afs-blobstore - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/blobstore/pom.xml b/afs/blobstore/pom.xml index 0faaeba5..9a1d2cc8 100644 --- a/afs/blobstore/pom.xml +++ b/afs/blobstore/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/afs/googlecloud/firestore/pom.xml b/afs/googlecloud/firestore/pom.xml index 2d848a96..cd2c9b68 100644 --- a/afs/googlecloud/firestore/pom.xml +++ b/afs/googlecloud/firestore/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-googlecloud-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/afs/googlecloud/pom.xml b/afs/googlecloud/pom.xml index ab30fa56..63ef9b44 100644 --- a/afs/googlecloud/pom.xml +++ b/afs/googlecloud/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -40,7 +40,7 @@ org.eclipse.store afs-blobstore - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/kafka/pom.xml b/afs/kafka/pom.xml index 0a668da0..1e805ced 100644 --- a/afs/kafka/pom.xml +++ b/afs/kafka/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ org.eclipse.store afs-blobstore - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/nio/pom.xml b/afs/nio/pom.xml index 7ea84f02..666325d3 100644 --- a/afs/nio/pom.xml +++ b/afs/nio/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/afs/oraclecloud/objectstorage/pom.xml b/afs/oraclecloud/objectstorage/pom.xml index cb660917..c821f1d9 100644 --- a/afs/oraclecloud/objectstorage/pom.xml +++ b/afs/oraclecloud/objectstorage/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-oraclecloud-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-blobstore - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/oraclecloud/pom.xml b/afs/oraclecloud/pom.xml index c5f4c457..59e21d87 100644 --- a/afs/oraclecloud/pom.xml +++ b/afs/oraclecloud/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/afs/pom.xml b/afs/pom.xml index a4e39e5f..c4c01f47 100644 --- a/afs/pom.xml +++ b/afs/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store store-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/afs/redis/pom.xml b/afs/redis/pom.xml index d3402f11..7ebc3e84 100644 --- a/afs/redis/pom.xml +++ b/afs/redis/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store afs-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-blobstore - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.serializer diff --git a/afs/sql/pom.xml b/afs/sql/pom.xml index 4d59ecef..c25366a8 100644 --- a/afs/sql/pom.xml +++ b/afs/sql/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store afs-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/cache/cache/pom.xml b/cache/cache/pom.xml index 1b89ecaa..3179886a 100644 --- a/cache/cache/pom.xml +++ b/cache/cache/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store cache-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,12 +23,12 @@ org.eclipse.store storage-embedded - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.store storage-embedded-configuration - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT javax.cache diff --git a/cache/hibernate/pom.xml b/cache/hibernate/pom.xml index 481895bd..0ce08baf 100644 --- a/cache/hibernate/pom.xml +++ b/cache/hibernate/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store cache-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store cache - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.hibernate diff --git a/cache/pom.xml b/cache/pom.xml index b6035bc1..a9709dd4 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store store-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/examples/blobs/pom.xml b/examples/blobs/pom.xml index b43d9bfe..ad192bf5 100644 --- a/examples/blobs/pom.xml +++ b/examples/blobs/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ org.eclipse.store storage-embedded - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT diff --git a/examples/custom-legacy-type-handler/pom.xml b/examples/custom-legacy-type-handler/pom.xml index 2fb19a62..cda83112 100644 --- a/examples/custom-legacy-type-handler/pom.xml +++ b/examples/custom-legacy-type-handler/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/custom-type-handler/pom.xml b/examples/custom-type-handler/pom.xml index 18eabc28..be688eb5 100644 --- a/examples/custom-type-handler/pom.xml +++ b/examples/custom-type-handler/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/deleting/pom.xml b/examples/deleting/pom.xml index c316ba00..db8de83a 100644 --- a/examples/deleting/pom.xml +++ b/examples/deleting/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT diff --git a/examples/eager-storing/pom.xml b/examples/eager-storing/pom.xml index a03f6814..49c9daa1 100644 --- a/examples/eager-storing/pom.xml +++ b/examples/eager-storing/pom.xml @@ -10,7 +10,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -24,7 +24,7 @@ org.eclipse.store storage-embedded - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT diff --git a/examples/extension-wrapper/pom.xml b/examples/extension-wrapper/pom.xml index 93a673e7..0c10ae92 100644 --- a/examples/extension-wrapper/pom.xml +++ b/examples/extension-wrapper/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ org.eclipse.store storage-embedded - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT diff --git a/examples/filesystems/pom.xml b/examples/filesystems/pom.xml index c4d28226..dd4ce9b0 100644 --- a/examples/filesystems/pom.xml +++ b/examples/filesystems/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT com.google.jimfs diff --git a/examples/helloworld-ini/pom.xml b/examples/helloworld-ini/pom.xml index 11bcd9bf..4827ef3e 100644 --- a/examples/helloworld-ini/pom.xml +++ b/examples/helloworld-ini/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,12 +23,12 @@ org.eclipse.store storage-embedded - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.store storage-embedded-configuration - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml index 4398f7a6..69a00bb4 100644 --- a/examples/helloworld/pom.xml +++ b/examples/helloworld/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT diff --git a/examples/items/pom.xml b/examples/items/pom.xml index 0c88e12b..a0753155 100644 --- a/examples/items/pom.xml +++ b/examples/items/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/layered-entities/pom.xml b/examples/layered-entities/pom.xml index a86b8332..abb01022 100644 --- a/examples/layered-entities/pom.xml +++ b/examples/layered-entities/pom.xml @@ -10,7 +10,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/examples/lazy-loading/pom.xml b/examples/lazy-loading/pom.xml index f49407c6..27c0f78e 100644 --- a/examples/lazy-loading/pom.xml +++ b/examples/lazy-loading/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/loading/pom.xml b/examples/loading/pom.xml index 38123a82..6270c642 100644 --- a/examples/loading/pom.xml +++ b/examples/loading/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/pom.xml b/examples/pom.xml index e3c2ae00..fd5072e0 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store store-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/examples/reloader/pom.xml b/examples/reloader/pom.xml index 66917dbc..c8c3f740 100644 --- a/examples/reloader/pom.xml +++ b/examples/reloader/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded-configuration - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT diff --git a/examples/spring-boot3-advanced/pom.xml b/examples/spring-boot3-advanced/pom.xml index 3877bcf8..e1017c97 100644 --- a/examples/spring-boot3-advanced/pom.xml +++ b/examples/spring-boot3-advanced/pom.xml @@ -6,7 +6,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -46,13 +46,13 @@ org.eclipse.store integrations-spring-boot3 - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.store integrations-spring-boot3-console - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT diff --git a/examples/spring-boot3-simple/pom.xml b/examples/spring-boot3-simple/pom.xml index 1ff20bb5..5307d776 100644 --- a/examples/spring-boot3-simple/pom.xml +++ b/examples/spring-boot3-simple/pom.xml @@ -6,7 +6,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -53,13 +53,13 @@ org.eclipse.store integrations-spring-boot3 - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.store integrations-spring-boot3-console - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT diff --git a/examples/storing/pom.xml b/examples/storing/pom.xml index 34b96a06..b9b6e2ef 100644 --- a/examples/storing/pom.xml +++ b/examples/storing/pom.xml @@ -10,7 +10,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -24,7 +24,7 @@ org.eclipse.store storage-embedded - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.serializer diff --git a/examples/wildfly-cdi4/pom.xml b/examples/wildfly-cdi4/pom.xml index 3cc42b81..c0af4c75 100644 --- a/examples/wildfly-cdi4/pom.xml +++ b/examples/wildfly-cdi4/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store examples-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -36,7 +36,7 @@ org.eclipse.store eclipse-store-integrations-cdi4 - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.slf4j diff --git a/integrations/cdi4/pom.xml b/integrations/cdi4/pom.xml index 95130a84..dca25ab8 100644 --- a/integrations/cdi4/pom.xml +++ b/integrations/cdi4/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store integrations - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -37,12 +37,12 @@ org.eclipse.store storage-embedded - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.store storage-embedded-configuration - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.serializer @@ -52,7 +52,7 @@ org.eclipse.store cache - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT diff --git a/integrations/itest/pom.xml b/integrations/itest/pom.xml index 51d456eb..2dd2b336 100644 --- a/integrations/itest/pom.xml +++ b/integrations/itest/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store integrations - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/integrations/pom.xml b/integrations/pom.xml index 3088e9a9..4c3661f4 100644 --- a/integrations/pom.xml +++ b/integrations/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store store-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/integrations/spring-boot3-console/pom.xml b/integrations/spring-boot3-console/pom.xml index 1efd6478..0fbbb122 100644 --- a/integrations/spring-boot3-console/pom.xml +++ b/integrations/spring-boot3-console/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store integrations - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/integrations/spring-boot3/pom.xml b/integrations/spring-boot3/pom.xml index 1ba17f20..7678ed33 100644 --- a/integrations/spring-boot3/pom.xml +++ b/integrations/spring-boot3/pom.xml @@ -7,7 +7,7 @@ org.eclipse.store integrations - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -64,7 +64,7 @@ org.eclipse.store storage-embedded - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT @@ -82,7 +82,7 @@ org.eclipse.store storage-embedded-configuration - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index 416edde5..de465946 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ org.eclipse.store store-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT pom EclipseStore @@ -47,7 +47,7 @@ ${basedir}/LICENSE 1 false - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT 2 2 diff --git a/storage/embedded-configuration/pom.xml b/storage/embedded-configuration/pom.xml index e3cdcb9e..ccbcc7bc 100644 --- a/storage/embedded-configuration/pom.xml +++ b/storage/embedded-configuration/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.serializer diff --git a/storage/embedded-tools/pom.xml b/storage/embedded-tools/pom.xml index cbd57884..6e19b5c0 100644 --- a/storage/embedded-tools/pom.xml +++ b/storage/embedded-tools/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/storage/embedded-tools/storage-converter/pom.xml b/storage/embedded-tools/storage-converter/pom.xml index d40d5814..9400101d 100644 --- a/storage/embedded-tools/storage-converter/pom.xml +++ b/storage/embedded-tools/storage-converter/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-embedded-tools-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded-configuration - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT diff --git a/storage/embedded-tools/storage-migrator/pom.xml b/storage/embedded-tools/storage-migrator/pom.xml index 036c12d5..d54c46c2 100644 --- a/storage/embedded-tools/storage-migrator/pom.xml +++ b/storage/embedded-tools/storage-migrator/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-embedded-tools-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/storage/embedded/pom.xml b/storage/embedded/pom.xml index 25ce0ada..d052ae65 100644 --- a/storage/embedded/pom.xml +++ b/storage/embedded/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.slf4j diff --git a/storage/pom.xml b/storage/pom.xml index 951722cf..eaaad6f8 100644 --- a/storage/pom.xml +++ b/storage/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store store-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/storage/rest/adapter/pom.xml b/storage/rest/adapter/pom.xml index 2c2978ac..4958fe59 100644 --- a/storage/rest/adapter/pom.xml +++ b/storage/rest/adapter/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT diff --git a/storage/rest/client-app-standalone-assembly/pom.xml b/storage/rest/client-app-standalone-assembly/pom.xml index a7495dc6..681b42d2 100644 --- a/storage/rest/client-app-standalone-assembly/pom.xml +++ b/storage/rest/client-app-standalone-assembly/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/storage/rest/client-app/pom.xml b/storage/rest/client-app/pom.xml index e55e3d7d..f764243c 100644 --- a/storage/rest/client-app/pom.xml +++ b/storage/rest/client-app/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -47,7 +47,7 @@ org.eclipse.store storage-restclient-jersey - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT com.vaadin diff --git a/storage/rest/client-jersey/pom.xml b/storage/rest/client-jersey/pom.xml index 46ef5ed7..94eb4257 100644 --- a/storage/rest/client-jersey/pom.xml +++ b/storage/rest/client-jersey/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -29,7 +29,7 @@ org.eclipse.store storage-restclient - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.glassfish.jersey.core diff --git a/storage/rest/client/pom.xml b/storage/rest/client/pom.xml index 468f9a75..efafa0c5 100644 --- a/storage/rest/client/pom.xml +++ b/storage/rest/client/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-restadapter - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT diff --git a/storage/rest/pom.xml b/storage/rest/pom.xml index e9e10c9e..a98c3acf 100644 --- a/storage/rest/pom.xml +++ b/storage/rest/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/storage/rest/service-sparkjava/pom.xml b/storage/rest/service-sparkjava/pom.xml index 628a8b4b..313f4ab1 100644 --- a/storage/rest/service-sparkjava/pom.xml +++ b/storage/rest/service-sparkjava/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -29,7 +29,7 @@ org.eclipse.store storage-restservice - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT com.sparkjava diff --git a/storage/rest/service-springboot/pom.xml b/storage/rest/service-springboot/pom.xml index 49b4f6d3..d6fe6512 100644 --- a/storage/rest/service-springboot/pom.xml +++ b/storage/rest/service-springboot/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml diff --git a/storage/rest/service/pom.xml b/storage/rest/service/pom.xml index f8c92f7c..972ccf50 100644 --- a/storage/rest/service/pom.xml +++ b/storage/rest/service/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-rest-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-restadapter - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT diff --git a/storage/storage/pom.xml b/storage/storage/pom.xml index 4a4c7d7a..01f31a34 100644 --- a/storage/storage/pom.xml +++ b/storage/storage/pom.xml @@ -9,7 +9,7 @@ org.eclipse.store storage-parent - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT ../pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-nio - 1.3.0-SNAPSHOT + 2.0.0-SNAPSHOT org.eclipse.serializer From 6c7444f507eb153708e682c5da0cc344fe9d746d Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 5 Mar 2024 14:43:56 +0100 Subject: [PATCH 086/126] add CDI docu (#164) * add CDI docu * Update cdi.adoc - use {product-name} variable - fix typos --------- Co-authored-by: Florian Habermann --- docs/modules/ROOT/nav.adoc | 1 + docs/modules/misc/pages/integrations/cdi.adoc | 116 ++++++++++++++++++ .../misc/pages/integrations/index.adoc | 1 + 3 files changed, 118 insertions(+) create mode 100644 docs/modules/misc/pages/integrations/cdi.adoc diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index c96ebe58..c9f8c578 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -85,6 +85,7 @@ ** xref:misc:integrations/index.adoc[Integrations] *** xref:misc:integrations/spring-boot.adoc[Spring-Boot] *** xref:misc:integrations/micronaut.adoc[Micronaut] +*** xref:misc:integrations/cdi.adoc[CDI] ** xref:misc:layered-entities/index.adoc[Layered Entities] *** xref:misc:layered-entities/configuration.adoc[Configuration] *** xref:misc:layered-entities/defining-entities.adoc[Defining Entities] diff --git a/docs/modules/misc/pages/integrations/cdi.adoc b/docs/modules/misc/pages/integrations/cdi.adoc new file mode 100644 index 00000000..33357b08 --- /dev/null +++ b/docs/modules/misc/pages/integrations/cdi.adoc @@ -0,0 +1,116 @@ += CDI Extension + +{product-name} comes with a CDI extension, which allows accessing the functionality of {product-name} through the usage of a few annotations. + +It is available within this artifact: + +[source, xml, title="pom.xml", subs=attributes+] +---- + + + org.eclipse.store + eclipse-store-integrations-cdi4 + {maven-version} + + +---- + +The integration requires the _javax_ namespace and requires a https://jakarta.ee/specifications/cdi/[CDI] 4.0 implementation +and an https://github.com/eclipse/microprofile-config[Eclipse MicroProfile Config] 2.0 implementation. + + +This CDI extension makes use of the `Extension` interface and the `BeanManager` functionality, so it might not work in a strict Jakarta EE 10 Core Profile product that only supports the CDI Lite functionality. + +== Configuration + +The configuration of the _StorageManager_ can be done using key/value pairs that are provided by MicroProfile Config. The configuration keys must be prefixed by `org.clipse.store` + +[source] +---- +org.eclipse.store.storage-directory=/opt/data/eclipsestore +org.eclipse.store.channel-count=2 +---- + +Since the `-` character is not supported in some sources (like the environment variables), you can also define the configuration keys using the `.` character. + +[source] +---- +org.eclipse.store.storage.directory=/opt/data/eclipsestore +org.eclipse.store.channel.count=2 +---- + +Besides that, the regular MicroProfile Config rules about keys are applied (since we are using MicroProfile Config directly, see https://github.com/eclipse/microprofile-config/blob/master/spec/src/main/asciidoc/configsources.asciidoc#environment-variables-mapping-rules[specification]). + +The configured and started _StorageManager_ is a CDI bean and thus can be injected or retrieved programmatically. + +[source, java] +---- +@Inject +private StorageManager storageManager; + +public void someMethod() { + StorageManager storageManager = CDI.current().select(StorageManager.class).get(); +} +---- + +The _StorageManager_ configuration can be customized by CDI beans that implement the interface `org.eclipse.store.integrations.cdi.types.config.EmbeddedStorageFoundationCustomizer`. +The `customize` method is called with an `EmbeddedStorageFoundation` which allows you to fully customize the _StorageManager_ that will be created. You can for example, add the specific Type Handlers for JDK 8 as described on the https://docs.eclipsestore.io/manual/storage/addendum/specialized-type-handlers.html[documentation]. + +After the _StorageManager_ is created, the CDI beans that implement `org.eclipse.store.integrations.cdi.types.config.StorageManagerInitializer` are called. +You have the opportunity to perform actions on the _StorageManager_ or root object. Following rules apply to the _StorageManager_ that is passed to the `initialize` method of the interface. + +- The _StorageManager_ is already started unless you specified the configuration value `org.eclipse.store.autoStart=false`. +- If you have used the `@Storage` annotation on a class, the _StorageManager_ is already associated with an instance of that class as the Root object. + +There is a **second option** to configure and retrieve the _StorageManager_, and it makes use of the {product-name} functionality to read the configuration from any file. + +[source, java] +---- +@Inject +@ConfigProperty(name = "org.eclipse.store.ini") +private StorageManager storageManager; +---- + +The above construct makes use of the MicroProfile Config functionality that you _convert_ the value of the key `org.eclipse.store.ini` and convert it into a _StorageManager_. The value of the key is expected to point to an existing file. The formats XML, INI, and properties are supported. + +The _StorageManager_ is also fully configured and started just as you would use it when using the first option of configuration. + +If you define it multiple times, within different beans, for example, you always receive the same instance of the _StorageManager_ when you specify the same value for the _name_ member of the `@ConfigProperty` annotation. + +This way, you can define and use multiple _StorageManager_s within your application. + +The _customizer_ and _initializer_ features described earlier as CDI beans implementing a specific interface are also available when you use the MicroProfile Config annotation (`@ConfigProperty`). Since you can define multiple _StorageManager_s this way, you can distinguish between them based on the _database name_. + +The database name can be set by using the following property within the configuration file (example makes use of the properties format, but it is also supported in the other formats) + +[source] +---- +database-name=theName +---- + +If this property is not specified, the value of the MicroProfile config key (used within the name member of `@ConfigProperty`) is used. + +Within the _customizer_ and _initializer_, you can use this to perform the required actions based on the instance you receive. + +[source, java] +---- +EmbeddedStorageFoundation.getDataBaseName(); + +StorageManager.databaseName(); +---- + + +== Root object + +The root object can be indicated by using the `@Storage` annotation on the class. This annotation converts the POJO into a CDI bean (there is no need to use any scope-defining annotation) with Application Scope. + +WARNING: This is only supported when you inject the _StorageManager_ without making use of the MicroProfile Config `@ConfigProperty` annotation. + +Besides converting it into a CDI bean, any field injection within this class is also resolved. + +The integration also defines the instance of the class that is created as the root object (`StorageManager.setRoot()`) and stores the initial value (`StorageManager.storeRoot()`) when storageManager does not have a root object assigned yet (this happens only the very first time when you start up your application and the storage doesn't contain any data yet) + +The POJO must have a (default) no-argument constructor so that the integration can create an instance of it. + +You can only annotate 1 class with the `@Storage` annotation, if you have marked multiple, the deployment of your application will fail at the CDI validation phase. + diff --git a/docs/modules/misc/pages/integrations/index.adoc b/docs/modules/misc/pages/integrations/index.adoc index 4a4548f4..9b477be2 100644 --- a/docs/modules/misc/pages/integrations/index.adoc +++ b/docs/modules/misc/pages/integrations/index.adoc @@ -5,6 +5,7 @@ Various {product-name} integrations are currently available. Currently available integrations: * xref:misc:integrations/spring-boot.adoc[Spring Boot] +* xref:misc:integrations/cdi.adoc[Jakarta EE CDI] And {product-name} is also integrated by the following vendors From 747c7f374355ab7d1c2174c9232bb301e8329f1a Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Fri, 8 Mar 2024 09:40:46 +0100 Subject: [PATCH 087/126] Typo in continuous-backup.adoc (#166) Sorage -> Storage --- .../storage/pages/configuration/backup/continuous-backup.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/modules/storage/pages/configuration/backup/continuous-backup.adoc b/docs/modules/storage/pages/configuration/backup/continuous-backup.adoc index 663d2223..0eff136a 100644 --- a/docs/modules/storage/pages/configuration/backup/continuous-backup.adoc +++ b/docs/modules/storage/pages/configuration/backup/continuous-backup.adoc @@ -36,7 +36,7 @@ With {product-name} foundation classes: NioFileSystem fileSystem = NioFileSystem.New(); StorageBackupSetup backupSetup = StorageBackupSetup.New( - Sorage.BackupFileProviderBuilder(fileSystem) + Storage.BackupFileProviderBuilder(fileSystem) .setDirectory(fileSystem.ensureDirectoryPath(BACKUPDIR)) .setTruncationDirectory(fileSystem.ensureDirectoryPath(TRUNCATIONDIR)) .setDeletionDirectory(fileSystem.ensureDirectoryPath(DELETIONDIR)) @@ -67,7 +67,7 @@ SqlFileSystem fileSystem = SqlFileSystem.New( ); StorageBackupSetup backupSetup = StorageBackupSetup.New( - Sorage.BackupFileProviderBuilder(fileSystem) + Storage.BackupFileProviderBuilder(fileSystem) .setDirectory(fileSystem.ensureDirectoryPath(BACKUPDIR)) .setTruncationDirectory(fileSystem.ensureDirectoryPath(TRUNCATIONDIR)) .setDeletionDirectory(fileSystem.ensureDirectoryPath(DELETIONDIR)) From 32f9e2f822cfa7b0c993392734b4c257853a2b66 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Fri, 8 Mar 2024 13:28:51 +0100 Subject: [PATCH 088/126] Zj/replace version with parameter 0324 (#167) * add url and change project dependency as variable * add url and change project dependency as variable --- afs/aws/aws/pom.xml | 2 +- afs/aws/dynamodb/pom.xml | 2 +- afs/aws/s3/pom.xml | 2 +- afs/azure/storage/pom.xml | 2 +- afs/googlecloud/pom.xml | 2 +- afs/kafka/pom.xml | 2 +- afs/oraclecloud/objectstorage/pom.xml | 2 +- afs/redis/pom.xml | 2 +- cache/cache/pom.xml | 4 ++-- cache/hibernate/pom.xml | 2 +- examples/blobs/pom.xml | 2 +- examples/custom-legacy-type-handler/pom.xml | 2 +- examples/custom-type-handler/pom.xml | 2 +- examples/deleting/pom.xml | 2 +- examples/eager-storing/pom.xml | 2 +- examples/extension-wrapper/pom.xml | 2 +- examples/filesystems/pom.xml | 2 +- examples/helloworld-ini/pom.xml | 4 ++-- examples/helloworld/pom.xml | 2 +- examples/items/pom.xml | 2 +- examples/lazy-loading/pom.xml | 2 +- examples/loading/pom.xml | 2 +- examples/reloader/pom.xml | 2 +- examples/spring-boot3-advanced/pom.xml | 5 +++-- examples/spring-boot3-simple/pom.xml | 5 +++-- examples/storing/pom.xml | 2 +- examples/wildfly-cdi4/pom.xml | 2 +- integrations/cdi4/pom.xml | 7 ++++--- integrations/itest/pom.xml | 1 + integrations/pom.xml | 1 + integrations/spring-boot3-console/pom.xml | 1 + integrations/spring-boot3/pom.xml | 5 +++-- storage/embedded-configuration/pom.xml | 2 +- storage/embedded-tools/storage-converter/pom.xml | 2 +- storage/embedded/pom.xml | 2 +- storage/rest/adapter/pom.xml | 2 +- storage/rest/client-app/pom.xml | 2 +- storage/rest/client-jersey/pom.xml | 2 +- storage/rest/client/pom.xml | 2 +- storage/rest/service-sparkjava/pom.xml | 2 +- storage/rest/service/pom.xml | 2 +- storage/storage/pom.xml | 2 +- 42 files changed, 53 insertions(+), 46 deletions(-) diff --git a/afs/aws/aws/pom.xml b/afs/aws/aws/pom.xml index 757e6486..1b3a095b 100644 --- a/afs/aws/aws/pom.xml +++ b/afs/aws/aws/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-blobstore - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.serializer diff --git a/afs/aws/dynamodb/pom.xml b/afs/aws/dynamodb/pom.xml index cc9f360e..bc12cd31 100644 --- a/afs/aws/dynamodb/pom.xml +++ b/afs/aws/dynamodb/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-aws - 2.0.0-SNAPSHOT + ${project.version} software.amazon.awssdk diff --git a/afs/aws/s3/pom.xml b/afs/aws/s3/pom.xml index a7f8eac6..2ddc4260 100644 --- a/afs/aws/s3/pom.xml +++ b/afs/aws/s3/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-aws - 2.0.0-SNAPSHOT + ${project.version} software.amazon.awssdk diff --git a/afs/azure/storage/pom.xml b/afs/azure/storage/pom.xml index 0b286f34..8a4fea45 100644 --- a/afs/azure/storage/pom.xml +++ b/afs/azure/storage/pom.xml @@ -21,7 +21,7 @@ org.eclipse.store afs-blobstore - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.serializer diff --git a/afs/googlecloud/pom.xml b/afs/googlecloud/pom.xml index 63ef9b44..94808b11 100644 --- a/afs/googlecloud/pom.xml +++ b/afs/googlecloud/pom.xml @@ -40,7 +40,7 @@ org.eclipse.store afs-blobstore - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.serializer diff --git a/afs/kafka/pom.xml b/afs/kafka/pom.xml index 1e805ced..8a593aca 100644 --- a/afs/kafka/pom.xml +++ b/afs/kafka/pom.xml @@ -21,7 +21,7 @@ org.eclipse.store afs-blobstore - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.serializer diff --git a/afs/oraclecloud/objectstorage/pom.xml b/afs/oraclecloud/objectstorage/pom.xml index c821f1d9..cca55201 100644 --- a/afs/oraclecloud/objectstorage/pom.xml +++ b/afs/oraclecloud/objectstorage/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-blobstore - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.serializer diff --git a/afs/redis/pom.xml b/afs/redis/pom.xml index 7ebc3e84..e152ba14 100644 --- a/afs/redis/pom.xml +++ b/afs/redis/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-blobstore - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.serializer diff --git a/cache/cache/pom.xml b/cache/cache/pom.xml index 3179886a..21de4a47 100644 --- a/cache/cache/pom.xml +++ b/cache/cache/pom.xml @@ -23,12 +23,12 @@ org.eclipse.store storage-embedded - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.store storage-embedded-configuration - 2.0.0-SNAPSHOT + ${project.version} javax.cache diff --git a/cache/hibernate/pom.xml b/cache/hibernate/pom.xml index 0ce08baf..0ef2294f 100644 --- a/cache/hibernate/pom.xml +++ b/cache/hibernate/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store cache - 2.0.0-SNAPSHOT + ${project.version} org.hibernate diff --git a/examples/blobs/pom.xml b/examples/blobs/pom.xml index ad192bf5..e96b8c16 100644 --- a/examples/blobs/pom.xml +++ b/examples/blobs/pom.xml @@ -21,7 +21,7 @@ org.eclipse.store storage-embedded - 2.0.0-SNAPSHOT + ${project.version} diff --git a/examples/custom-legacy-type-handler/pom.xml b/examples/custom-legacy-type-handler/pom.xml index cda83112..aeb2f0aa 100644 --- a/examples/custom-legacy-type-handler/pom.xml +++ b/examples/custom-legacy-type-handler/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.serializer diff --git a/examples/custom-type-handler/pom.xml b/examples/custom-type-handler/pom.xml index be688eb5..4eb60c68 100644 --- a/examples/custom-type-handler/pom.xml +++ b/examples/custom-type-handler/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.serializer diff --git a/examples/deleting/pom.xml b/examples/deleting/pom.xml index db8de83a..4b1cc77d 100644 --- a/examples/deleting/pom.xml +++ b/examples/deleting/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 2.0.0-SNAPSHOT + ${project.version} diff --git a/examples/eager-storing/pom.xml b/examples/eager-storing/pom.xml index 49c9daa1..05faa2e1 100644 --- a/examples/eager-storing/pom.xml +++ b/examples/eager-storing/pom.xml @@ -24,7 +24,7 @@ org.eclipse.store storage-embedded - 2.0.0-SNAPSHOT + ${project.version} diff --git a/examples/extension-wrapper/pom.xml b/examples/extension-wrapper/pom.xml index 0c10ae92..562dbf4c 100644 --- a/examples/extension-wrapper/pom.xml +++ b/examples/extension-wrapper/pom.xml @@ -21,7 +21,7 @@ org.eclipse.store storage-embedded - 2.0.0-SNAPSHOT + ${project.version} diff --git a/examples/filesystems/pom.xml b/examples/filesystems/pom.xml index dd4ce9b0..73f5981f 100644 --- a/examples/filesystems/pom.xml +++ b/examples/filesystems/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 2.0.0-SNAPSHOT + ${project.version} com.google.jimfs diff --git a/examples/helloworld-ini/pom.xml b/examples/helloworld-ini/pom.xml index 4827ef3e..7aaa1ef4 100644 --- a/examples/helloworld-ini/pom.xml +++ b/examples/helloworld-ini/pom.xml @@ -23,12 +23,12 @@ org.eclipse.store storage-embedded - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.store storage-embedded-configuration - 2.0.0-SNAPSHOT + ${project.version} diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml index 69a00bb4..c82cf2fd 100644 --- a/examples/helloworld/pom.xml +++ b/examples/helloworld/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 2.0.0-SNAPSHOT + ${project.version} diff --git a/examples/items/pom.xml b/examples/items/pom.xml index a0753155..2f38b66b 100644 --- a/examples/items/pom.xml +++ b/examples/items/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.serializer diff --git a/examples/lazy-loading/pom.xml b/examples/lazy-loading/pom.xml index 27c0f78e..8e3b29e0 100644 --- a/examples/lazy-loading/pom.xml +++ b/examples/lazy-loading/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.serializer diff --git a/examples/loading/pom.xml b/examples/loading/pom.xml index 6270c642..03428519 100644 --- a/examples/loading/pom.xml +++ b/examples/loading/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.serializer diff --git a/examples/reloader/pom.xml b/examples/reloader/pom.xml index c8c3f740..0234489c 100644 --- a/examples/reloader/pom.xml +++ b/examples/reloader/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded-configuration - 2.0.0-SNAPSHOT + ${project.version} diff --git a/examples/spring-boot3-advanced/pom.xml b/examples/spring-boot3-advanced/pom.xml index e1017c97..740be0f6 100644 --- a/examples/spring-boot3-advanced/pom.xml +++ b/examples/spring-boot3-advanced/pom.xml @@ -12,6 +12,7 @@ EclipseStore Example Spring Boot3 Advanced examples-spring-boot3-advanced + https://projects.eclipse.org/projects/technology.store 17 @@ -46,13 +47,13 @@ org.eclipse.store integrations-spring-boot3 - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.store integrations-spring-boot3-console - 2.0.0-SNAPSHOT + ${project.version} diff --git a/examples/spring-boot3-simple/pom.xml b/examples/spring-boot3-simple/pom.xml index 5307d776..4ce5dad7 100644 --- a/examples/spring-boot3-simple/pom.xml +++ b/examples/spring-boot3-simple/pom.xml @@ -12,6 +12,7 @@ EclipseStore Example Spring Boot3 Simple examples-spring-boot3-simple + https://projects.eclipse.org/projects/technology.store 17 @@ -53,13 +54,13 @@ org.eclipse.store integrations-spring-boot3 - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.store integrations-spring-boot3-console - 2.0.0-SNAPSHOT + ${project.version} diff --git a/examples/storing/pom.xml b/examples/storing/pom.xml index b9b6e2ef..91ebf36e 100644 --- a/examples/storing/pom.xml +++ b/examples/storing/pom.xml @@ -24,7 +24,7 @@ org.eclipse.store storage-embedded - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.serializer diff --git a/examples/wildfly-cdi4/pom.xml b/examples/wildfly-cdi4/pom.xml index c0af4c75..4d7c1df9 100644 --- a/examples/wildfly-cdi4/pom.xml +++ b/examples/wildfly-cdi4/pom.xml @@ -36,7 +36,7 @@ org.eclipse.store eclipse-store-integrations-cdi4 - 2.0.0-SNAPSHOT + ${project.version} org.slf4j diff --git a/integrations/cdi4/pom.xml b/integrations/cdi4/pom.xml index dca25ab8..844174cb 100644 --- a/integrations/cdi4/pom.xml +++ b/integrations/cdi4/pom.xml @@ -13,6 +13,7 @@ EclipseStore Integrations CDI 4 EclipseStore CDI 4 Extension + https://projects.eclipse.org/projects/technology.store @@ -37,12 +38,12 @@ org.eclipse.store storage-embedded - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.store storage-embedded-configuration - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.serializer @@ -52,7 +53,7 @@ org.eclipse.store cache - 2.0.0-SNAPSHOT + ${project.version} diff --git a/integrations/itest/pom.xml b/integrations/itest/pom.xml index 2dd2b336..f12f1ef7 100644 --- a/integrations/itest/pom.xml +++ b/integrations/itest/pom.xml @@ -13,6 +13,7 @@ integrations-spring-boot3-itest EclipseStore Integrations SpringBoot ITest + https://projects.eclipse.org/projects/technology.store 3.2.2 diff --git a/integrations/pom.xml b/integrations/pom.xml index 4c3661f4..20421c38 100644 --- a/integrations/pom.xml +++ b/integrations/pom.xml @@ -14,6 +14,7 @@ integrations EclipseStore Integrations Parent pom + https://projects.eclipse.org/projects/technology.store cdi4 diff --git a/integrations/spring-boot3-console/pom.xml b/integrations/spring-boot3-console/pom.xml index 0fbbb122..dc07777e 100644 --- a/integrations/spring-boot3-console/pom.xml +++ b/integrations/spring-boot3-console/pom.xml @@ -13,6 +13,7 @@ integrations-spring-boot3-console EclipseStore Integrations SpringBoot Console + https://projects.eclipse.org/projects/technology.store 3.2.0 diff --git a/integrations/spring-boot3/pom.xml b/integrations/spring-boot3/pom.xml index 7678ed33..696ae4d8 100644 --- a/integrations/spring-boot3/pom.xml +++ b/integrations/spring-boot3/pom.xml @@ -13,6 +13,7 @@ integrations-spring-boot3 EclipseStore Integrations SpringBoot + https://projects.eclipse.org/projects/technology.store 3.2.2 @@ -64,7 +65,7 @@ org.eclipse.store storage-embedded - 2.0.0-SNAPSHOT + ${project.version} @@ -82,7 +83,7 @@ org.eclipse.store storage-embedded-configuration - 2.0.0-SNAPSHOT + ${project.version} diff --git a/storage/embedded-configuration/pom.xml b/storage/embedded-configuration/pom.xml index ccbcc7bc..6e9a0508 100644 --- a/storage/embedded-configuration/pom.xml +++ b/storage/embedded-configuration/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.serializer diff --git a/storage/embedded-tools/storage-converter/pom.xml b/storage/embedded-tools/storage-converter/pom.xml index 9400101d..1fa621df 100644 --- a/storage/embedded-tools/storage-converter/pom.xml +++ b/storage/embedded-tools/storage-converter/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-embedded-configuration - 2.0.0-SNAPSHOT + ${project.version} diff --git a/storage/embedded/pom.xml b/storage/embedded/pom.xml index d052ae65..baa55e86 100644 --- a/storage/embedded/pom.xml +++ b/storage/embedded/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage - 2.0.0-SNAPSHOT + ${project.version} org.slf4j diff --git a/storage/rest/adapter/pom.xml b/storage/rest/adapter/pom.xml index 4958fe59..fd535800 100644 --- a/storage/rest/adapter/pom.xml +++ b/storage/rest/adapter/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage - 2.0.0-SNAPSHOT + ${project.version} diff --git a/storage/rest/client-app/pom.xml b/storage/rest/client-app/pom.xml index f764243c..9b07b8e7 100644 --- a/storage/rest/client-app/pom.xml +++ b/storage/rest/client-app/pom.xml @@ -47,7 +47,7 @@ org.eclipse.store storage-restclient-jersey - 2.0.0-SNAPSHOT + ${project.version} com.vaadin diff --git a/storage/rest/client-jersey/pom.xml b/storage/rest/client-jersey/pom.xml index 94eb4257..81f69182 100644 --- a/storage/rest/client-jersey/pom.xml +++ b/storage/rest/client-jersey/pom.xml @@ -29,7 +29,7 @@ org.eclipse.store storage-restclient - 2.0.0-SNAPSHOT + ${project.version} org.glassfish.jersey.core diff --git a/storage/rest/client/pom.xml b/storage/rest/client/pom.xml index efafa0c5..66b146a8 100644 --- a/storage/rest/client/pom.xml +++ b/storage/rest/client/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-restadapter - 2.0.0-SNAPSHOT + ${project.version} diff --git a/storage/rest/service-sparkjava/pom.xml b/storage/rest/service-sparkjava/pom.xml index 313f4ab1..49045991 100644 --- a/storage/rest/service-sparkjava/pom.xml +++ b/storage/rest/service-sparkjava/pom.xml @@ -29,7 +29,7 @@ org.eclipse.store storage-restservice - 2.0.0-SNAPSHOT + ${project.version} com.sparkjava diff --git a/storage/rest/service/pom.xml b/storage/rest/service/pom.xml index 972ccf50..4e1b1f2e 100644 --- a/storage/rest/service/pom.xml +++ b/storage/rest/service/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store storage-restadapter - 2.0.0-SNAPSHOT + ${project.version} diff --git a/storage/storage/pom.xml b/storage/storage/pom.xml index 01f31a34..6732df3a 100644 --- a/storage/storage/pom.xml +++ b/storage/storage/pom.xml @@ -23,7 +23,7 @@ org.eclipse.store afs-nio - 2.0.0-SNAPSHOT + ${project.version} org.eclipse.serializer From ff0c53ed154b043691dceb5b5f235ab5111dc0c3 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Mon, 11 Mar 2024 11:34:09 +0100 Subject: [PATCH 089/126] update maven plugins (#169) --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index de465946..f41d9b8e 100644 --- a/pom.xml +++ b/pom.xml @@ -167,7 +167,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.1 + 3.5.2 org.apache.felix @@ -345,12 +345,12 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.3 + 3.2.5 org.cyclonedx cyclonedx-maven-plugin - 2.7.10 + 2.7.11 prepare-package From a78fc42a1ad505990abd4f68500cb4652e46cf88 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 19 Mar 2024 12:14:52 +0100 Subject: [PATCH 090/126] add advance restart test (#174) --- .../spring/boot/RestartStorageBeanTest.java | 2 - .../boot/advance/AdvanceRestartRoot.java | 30 ++++++ .../boot/advance/AdvanceRestartTest.java | 94 +++++++++++++++++++ ...pplication-advance-restart-test.properties | 4 + 4 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/advance/AdvanceRestartRoot.java create mode 100644 integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/advance/AdvanceRestartTest.java create mode 100644 integrations/spring-boot3/src/test/resources/application-advance-restart-test.properties diff --git a/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/RestartStorageBeanTest.java b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/RestartStorageBeanTest.java index e22beaac..f718ba49 100644 --- a/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/RestartStorageBeanTest.java +++ b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/RestartStorageBeanTest.java @@ -71,8 +71,6 @@ void restarts_storage() final ConfigurationPair pair = new ConfigurationPair("someKey", "someValue"); final EmbeddedStorageFoundation storageFoundation = this.foundationFactory.createStorageFoundation(this.myConfiguration, pair); - final RestartRoot root2 = new RestartRoot(); - storageFoundation.setRoot(root2); try (EmbeddedStorageManager storage = storageFoundation.start()) { final RestartRoot rootFromStorage = (RestartRoot) storage.root(); diff --git a/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/advance/AdvanceRestartRoot.java b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/advance/AdvanceRestartRoot.java new file mode 100644 index 00000000..9f420147 --- /dev/null +++ b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/advance/AdvanceRestartRoot.java @@ -0,0 +1,30 @@ +package test.eclipse.store.integrations.spring.boot.advance; + +/*- + * #%L + * EclipseStore Integrations SpringBoot + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +public class AdvanceRestartRoot +{ + private String value; + + public String getValue() + { + return value; + } + + public void setValue(String value) + { + this.value = value; + } +} diff --git a/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/advance/AdvanceRestartTest.java b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/advance/AdvanceRestartTest.java new file mode 100644 index 00000000..ece8a14b --- /dev/null +++ b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/advance/AdvanceRestartTest.java @@ -0,0 +1,94 @@ +package test.eclipse.store.integrations.spring.boot.advance; + +/*- + * #%L + * EclipseStore Integrations SpringBoot + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import java.nio.file.Path; + +import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; +import org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageFoundationFactory; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Profile; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.TestPropertySource; + +@SpringBootTest +@TestPropertySource("classpath:application-advance-restart-test.properties") +@ActiveProfiles("advance_restart_storage") +public class AdvanceRestartTest +{ + @Autowired + private EmbeddedStorageManager manager; + + @Autowired + private EclipseStoreProperties myConfiguration; + + @Autowired + EmbeddedStorageFoundationFactory foundationFactory; + + @TempDir + static Path tempFolder; + + @Test + void restarts_storage() + { + + manager.start(); + AdvanceRestartRoot root = (AdvanceRestartRoot) manager.root(); + root.setValue("hello"); + manager.storeRoot(); + manager.shutdown(); + + Assertions.assertEquals(tempFolder.toAbsolutePath().toString(), manager.configuration().fileProvider().baseDirectory().toPathString()); + + final EmbeddedStorageFoundation storageFoundation = this.foundationFactory.createStorageFoundation(this.myConfiguration); + try (EmbeddedStorageManager storage = storageFoundation.start()) + { + final AdvanceRestartRoot rootFromStorage = (AdvanceRestartRoot) storage.root(); + Assertions.assertEquals("hello", rootFromStorage.getValue()); + } + } + + + @TestConfiguration + @Profile("advance_restart_storage") + static class RestartStorageBeanConfiguration + { + + @Autowired + private EmbeddedStorageFoundationFactory foundationFactory; + + @Autowired + @Qualifier("defaultEclipseStoreProperties") + private EclipseStoreProperties myConfiguration; + + @Bean("restartStorageBean") + EmbeddedStorageManager restartStorageBean() + { + this.myConfiguration.setStorageDirectory(tempFolder.toAbsolutePath().toString()); + final EmbeddedStorageFoundation storageFoundation = this.foundationFactory.createStorageFoundation(this.myConfiguration); + return storageFoundation.createEmbeddedStorageManager(); + } + } + +} diff --git a/integrations/spring-boot3/src/test/resources/application-advance-restart-test.properties b/integrations/spring-boot3/src/test/resources/application-advance-restart-test.properties new file mode 100644 index 00000000..9f04e02c --- /dev/null +++ b/integrations/spring-boot3/src/test/resources/application-advance-restart-test.properties @@ -0,0 +1,4 @@ +# debug=true +org.eclipse.store.storage-directory=${java.io.tmpdir}/${random.int} +org.eclipse.store.auto-start=false +org.eclipse.store.root=test.eclipse.store.integrations.spring.boot.advance.AdvanceRestartRoot From 56fdef7730238f38c3425b554d6ca7eca88c2c8d Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Tue, 19 Mar 2024 13:43:52 +0100 Subject: [PATCH 091/126] Add 1.3 changelog (#175) --- docs/modules/intro/pages/changelog.adoc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/modules/intro/pages/changelog.adoc b/docs/modules/intro/pages/changelog.adoc index 4d8c5837..3071c5e5 100644 --- a/docs/modules/intro/pages/changelog.adoc +++ b/docs/modules/intro/pages/changelog.adoc @@ -1,5 +1,16 @@ = Changelog +== 1.3.0 + +* Spring Boot improvements https://github.com/eclipse-store/store/pull/136[[136]] +* xref:misc:integrations/cdi.adoc[CDI Integration] + +=== Bugfixes + +* Use MethodHandles.Lookup where possible https://github.com/eclipse-serializer/serializer/issues/69[[69]] +* Fix for BinaryStorer reinizialization https://github.com/eclipse-serializer/serializer/issues/111[[111]] + + == 1.2.0 === Features From 115f93cad4fcfdb223c60296052060bd06546808 Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Tue, 19 Mar 2024 16:08:06 +0100 Subject: [PATCH 092/126] Add 1.3.1 docs (#176) * Add 1.3.1 docs * Update changelog.adoc --- docs/antora.yml | 4 ++-- docs/modules/intro/pages/changelog.adoc | 7 ++++++- storage/embedded-tools/storage-migrator/README.md | 6 +++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/antora.yml b/docs/antora.yml index 92cc3648..16391c2e 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -8,6 +8,6 @@ nav: asciidoc: attributes: product-name: 'EclipseStore' - display-version: '1.2' + display-version: '1.3.1' api-version: '1' - maven-version: '1.2.0' + maven-version: '1.3.1' diff --git a/docs/modules/intro/pages/changelog.adoc b/docs/modules/intro/pages/changelog.adoc index 3071c5e5..5ddd69ec 100644 --- a/docs/modules/intro/pages/changelog.adoc +++ b/docs/modules/intro/pages/changelog.adoc @@ -1,6 +1,6 @@ = Changelog -== 1.3.0 +== 1.3.1 * Spring Boot improvements https://github.com/eclipse-store/store/pull/136[[136]] * xref:misc:integrations/cdi.adoc[CDI Integration] @@ -11,6 +11,11 @@ * Fix for BinaryStorer reinizialization https://github.com/eclipse-serializer/serializer/issues/111[[111]] +== 1.3.0 + +Something went wrong with this release, some files are missing. Please use version 1.3.1 instead. + + == 1.2.0 === Features diff --git a/storage/embedded-tools/storage-migrator/README.md b/storage/embedded-tools/storage-migrator/README.md index 57bdab21..7597ccf6 100644 --- a/storage/embedded-tools/storage-migrator/README.md +++ b/storage/embedded-tools/storage-migrator/README.md @@ -16,17 +16,17 @@ The type dictionary migration is only done when `typeDictionaryRelativePath` is ### Migration of both, source code and type dictionary: ```` -mvn org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.eclipse.store.storage.embedded.tools.storage.migrator.ConvertProject -Drewrite.recipeArtifactCoordinates=org.eclipse.store:storage-embedded-tools-storage-migrator:1.0.0-SNAPSHOT -DeclipseStoreVersion=1.0.0-SNAPSHOT -Drewrite.plainTextMasks=**/*.ptd -DtypeDictionaryRelativeFilePath=src/main/resources/PersistenceTypeDictionary.ptd +mvn org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.eclipse.store.storage.embedded.tools.storage.migrator.ConvertProject -Drewrite.recipeArtifactCoordinates=org.eclipse.store:storage-embedded-tools-storage-migrator:1.3.1 -DeclipseStoreVersion=1.3.1 -Drewrite.plainTextMasks=**/*.ptd -DtypeDictionaryRelativeFilePath=src/main/resources/PersistenceTypeDictionary.ptd ```` ### Migration of source code only: ```` -mvn org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.eclipse.store.storage.embedded.tools.storage.migrator.ConvertProject -Drewrite.recipeArtifactCoordinates=org.eclipse.store:storage-embedded-tools-storage-migrator:1.0.0-SNAPSHOT -DeclipseStoreVersion=1.0.0-SNAPSHOT +mvn org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.eclipse.store.storage.embedded.tools.storage.migrator.ConvertProject -Drewrite.recipeArtifactCoordinates=org.eclipse.store:storage-embedded-tools-storage-migrator:1.3.1 -DeclipseStoreVersion=1.3.1 ```` ### Migration of type dictionary only: ```` -mvn org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.eclipse.store.storage.embedded.tools.storage.migrator.ConvertProject -Drewrite.recipeArtifactCoordinates=org.eclipse.store:storage-embedded-tools-storage-migrator:1.0.0-SNAPSHOT -Drewrite.plainTextMasks=**/*.ptd -DtypeDictionaryRelativeFilePath=src/main/resources/PersistenceTypeDictionary.ptd +mvn org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.eclipse.store.storage.embedded.tools.storage.migrator.ConvertProject -Drewrite.recipeArtifactCoordinates=org.eclipse.store:storage-embedded-tools-storage-migrator:1.3.1 -Drewrite.plainTextMasks=**/*.ptd -DtypeDictionaryRelativeFilePath=src/main/resources/PersistenceTypeDictionary.ptd ```` From e87d030cc3373c0d475c73f3148b43be849cd8ed Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 19 Mar 2024 16:55:08 +0100 Subject: [PATCH 093/126] fix scripts --- .github/workflows/maven_deploy_snapshot.yml | 2 ++ .github/workflows/maven_deploy_snapshot_dev.yml | 2 ++ .github/workflows/maven_release.yml | 6 ++++++ 3 files changed, 10 insertions(+) diff --git a/.github/workflows/maven_deploy_snapshot.yml b/.github/workflows/maven_deploy_snapshot.yml index 5abcc8b8..38a442a5 100644 --- a/.github/workflows/maven_deploy_snapshot.yml +++ b/.github/workflows/maven_deploy_snapshot.yml @@ -52,12 +52,14 @@ jobs: - name: Build with java 17 run: | mvn -pl integrations/spring-boot3 clean install -am -B + mvn -pl integrations/spring-boot3-console clean install -am -B mvn -P production -pl storage/rest/client-app clean install -am -B mvn -P production -pl storage/rest/client-app-standalone-assembly clean install -am -B mvn -P production -pl storage/rest/service-springboot clean install -am -B - name: Deploy module build with java 17 run: | mvn -Pdeploy -pl integrations/spring-boot3 deploy + mvn -Pdeploy -pl integrations/spring-boot3-console deploy mvn -Pdeploy -Pproduction -pl storage/rest/client-app deploy mvn -Pdeploy -Pproduction -pl storage/rest/client-app-standalone-assembly deploy mvn -Pdeploy -Pproduction -pl storage/rest/service-springboot deploy diff --git a/.github/workflows/maven_deploy_snapshot_dev.yml b/.github/workflows/maven_deploy_snapshot_dev.yml index c9175da0..98562f02 100644 --- a/.github/workflows/maven_deploy_snapshot_dev.yml +++ b/.github/workflows/maven_deploy_snapshot_dev.yml @@ -96,12 +96,14 @@ jobs: - name: Make a snapshot java 17 run: | mvn -pl integrations/spring-boot3 clean install -am -B + mvn -pl integrations/spring-boot3-console clean install -am -B mvn -P production -pl storage/rest/client-app clean install -am -B mvn -P production -pl storage/rest/client-app-standalone-assembly clean install -am -B mvn -P production -pl storage/rest/service-springboot clean install -am -B - name: Deploy module build with java 17 run: | mvn -Pdeploy -pl integrations/spring-boot3 deploy + mvn -Pdeploy -pl integrations/spring-boot3-console deploy mvn -Pdeploy -Pproduction -pl storage/rest/client-app deploy mvn -Pdeploy -Pproduction -pl storage/rest/client-app-standalone-assembly deploy mvn -Pdeploy -Pproduction -pl storage/rest/service-springboot deploy diff --git a/.github/workflows/maven_release.yml b/.github/workflows/maven_release.yml index e741191b..341c6e6b 100644 --- a/.github/workflows/maven_release.yml +++ b/.github/workflows/maven_release.yml @@ -50,11 +50,17 @@ jobs: - name: Build with java 17 run: | mvn -pl integrations/spring-boot3 clean install -am -B + mvn -pl integrations/spring-boot3-console clean install -am -B mvn -P production -pl storage/rest/client-app clean install -am -B + mvn -P production -pl storage/rest/client-app-standalone-assembly clean install -am -B + mvn -P production -pl storage/rest/service-springboot clean install -am -B - name: Deploy module build with java 17 run: | mvn -Pdeploy -pl integrations/spring-boot3 deploy + mvn -Pdeploy -pl integrations/spring-boot3-console deploy mvn -Pdeploy -Pproduction -pl storage/rest/client-app deploy + mvn -Pdeploy -Pproduction -pl storage/rest/client-app-standalone-assembly deploy + mvn -Pdeploy -Pproduction -pl storage/rest/service-springboot deploy env: MAVEN_USERNAME: ${{ secrets.ORG_OSSRH_USERNAME }} MAVEN_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} From 60bf3ea7a01b3abae3e7c50bf73567b4690c7133 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Thu, 21 Mar 2024 14:03:39 +0100 Subject: [PATCH 094/126] add dependency into documentation --- .../misc/pages/integrations/spring-boot.adoc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/modules/misc/pages/integrations/spring-boot.adoc b/docs/modules/misc/pages/integrations/spring-boot.adoc index e14fec83..6331c175 100644 --- a/docs/modules/misc/pages/integrations/spring-boot.adoc +++ b/docs/modules/misc/pages/integrations/spring-boot.adoc @@ -165,9 +165,21 @@ org.eclipse.store.second.auto-start=false org.eclipse.store.second.root=org.eclipse.store.integrations.spring.boot.types.storages.SecondRoot ---- -== Mutext Locking +== Mutex Locking {product-name} supports mutex locking. This is useful if you have multiple processes that need to access the same objects. Easiest way to use it is to use the annotation `@read` and `@write` on the methods that need to be locked. The annotation @read is used for methods that only read data and @write is used for methods that modify data. +For Activation of Mutex Locking, you need to add the following dependency to Maven pom.xml of your SpringBoot application: + +[source, xml, title="pom.xml", subs=attributes+] +---- + + org.springframework.boot + spring-boot-starter-aop + +---- + +Then you can use the Mutex Locking in your code: + [source,java] ---- @Component From 3273dbe31c5cfe229fd3a8ea92e3c73f13bb8e0f Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Thu, 21 Mar 2024 14:16:22 +0100 Subject: [PATCH 095/126] add dependency into documentation --- docs/modules/misc/pages/integrations/spring-boot.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/misc/pages/integrations/spring-boot.adoc b/docs/modules/misc/pages/integrations/spring-boot.adoc index 6331c175..4600a651 100644 --- a/docs/modules/misc/pages/integrations/spring-boot.adoc +++ b/docs/modules/misc/pages/integrations/spring-boot.adoc @@ -168,7 +168,7 @@ org.eclipse.store.second.root=org.eclipse.store.integrations.spring.boot.types.s == Mutex Locking {product-name} supports mutex locking. This is useful if you have multiple processes that need to access the same objects. Easiest way to use it is to use the annotation `@read` and `@write` on the methods that need to be locked. The annotation @read is used for methods that only read data and @write is used for methods that modify data. -For Activation of Mutex Locking, you need to add the following dependency to Maven pom.xml of your SpringBoot application: +For Mutex Locking activation, you need to add the following dependency to Maven pom.xml of your SpringBoot application: [source, xml, title="pom.xml", subs=attributes+] ---- From 6e48962ac24b1f011f74fa634d0de67c6dd572a2 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Thu, 21 Mar 2024 14:49:02 +0100 Subject: [PATCH 096/126] fix english --- docs/modules/misc/pages/integrations/spring-boot.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/misc/pages/integrations/spring-boot.adoc b/docs/modules/misc/pages/integrations/spring-boot.adoc index 4600a651..7b580e0a 100644 --- a/docs/modules/misc/pages/integrations/spring-boot.adoc +++ b/docs/modules/misc/pages/integrations/spring-boot.adoc @@ -168,7 +168,7 @@ org.eclipse.store.second.root=org.eclipse.store.integrations.spring.boot.types.s == Mutex Locking {product-name} supports mutex locking. This is useful if you have multiple processes that need to access the same objects. Easiest way to use it is to use the annotation `@read` and `@write` on the methods that need to be locked. The annotation @read is used for methods that only read data and @write is used for methods that modify data. -For Mutex Locking activation, you need to add the following dependency to Maven pom.xml of your SpringBoot application: +To activate mutex locking, you need to add the following dependency to Maven pom.xml of your SpringBoot application: [source, xml, title="pom.xml", subs=attributes+] ---- From f4add55e973393a68dd00847cab5652841cf89cb Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Tue, 2 Apr 2024 12:59:51 +0200 Subject: [PATCH 097/126] Added warning "don't share auto-incrementing contexts" (#195) --- docs/modules/misc/pages/layered-entities/versioning.adoc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/modules/misc/pages/layered-entities/versioning.adoc b/docs/modules/misc/pages/layered-entities/versioning.adoc index a3f1438e..243a873b 100644 --- a/docs/modules/misc/pages/layered-entities/versioning.adoc +++ b/docs/modules/misc/pages/layered-entities/versioning.adoc @@ -87,6 +87,12 @@ The version context can be used as a shared state object. So you can control versioning for multiple entities at once, or even for the hole entity graph. ==== +[WARNING] +==== +Do not share auto-incrementing contexts! +Use a mutable context instead. +==== + The auto-incrementing contexts take care of the key creation. If you need to control it by yourself, use the mutable context. But be aware that you have to set the version before updating any data, otherwise the current one will be overwritten. From 0051505076110a729a0e7b57966d01719287b40d Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Tue, 2 Apr 2024 13:03:33 +0200 Subject: [PATCH 098/126] updated restclient standalone download docu (#194) --- .../storage/pages/rest-interface/client-gui.adoc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/modules/storage/pages/rest-interface/client-gui.adoc b/docs/modules/storage/pages/rest-interface/client-gui.adoc index efb39487..70a95942 100644 --- a/docs/modules/storage/pages/rest-interface/client-gui.adoc +++ b/docs/modules/storage/pages/rest-interface/client-gui.adoc @@ -9,23 +9,30 @@ It is a runnable jar which starts a simple web server which then can be accessed Since {product-name} version 1.1.0 The Client GUI requires Java 17 to run! ==== -To download it use the following Maven command to download it into the current directory. +To download it into the local repository the following Maven command: [source, shell, title="CLI"] ---- -mvn dependency:get -Dartifact=org.eclipse.store:storage-restclient-app-standalone:{maven-version}:jar -Dtransitive=false -Ddest=storage.restclient.app-{maven-version}.jar +mvn dependency:get -Dartifact=org.eclipse.store:storage-restclient-app-standalone-assembly:{maven-version}:jar -Dtransitive=false -Dclassifier=standalone +---- + +To download it into the current directory use the following Maven command: + +[source, shell, title="CLI"] +---- +mvn dependency:copy -Dartifact=org.eclipse.store:storage-restclient-app-standalone-assembly:{maven-version}:jar:standalone -DoutputDirectory=./ ---- or this direct link: -https://oss.sonatype.org/content/repositories/snapshots/org/eclipse/store/storage-restclient-app/{maven-version}/storage-restclient-app-standalone-{maven-version}.jar +https://repo1.maven.org/maven2/org/eclipse/store/storage-restclient-app-standalone-assembly/{maven-version}/storage-restclient-app-standalone-assembly-{maven-version}-standalone.jar Start the client. The port parameter is optional, default port is 8080. [source, text, subs=attributes+] ---- -java -jar storage-restclient-app-standalone-{maven-version}.jar --server.port=8888 +java -jar storage-restclient-app-standalone-assembly-{maven-version}-standalone.jar --server.port=8888 ---- Then just open http://localhost:8888/ in your browser, select the base URL of the REST service and click connect. From 5cabb32675384cf59728f6f2d1688dbac12e395a Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Tue, 2 Apr 2024 14:03:41 +0200 Subject: [PATCH 099/126] fixed build? --- examples/layered-entities/pom.xml | 50 ------------------------------- 1 file changed, 50 deletions(-) diff --git a/examples/layered-entities/pom.xml b/examples/layered-entities/pom.xml index abb01022..006cede8 100644 --- a/examples/layered-entities/pom.xml +++ b/examples/layered-entities/pom.xml @@ -37,54 +37,4 @@ - - - - org.apache.maven.plugins - maven-compiler-plugin - - javac - - - - process-annotations - generate-sources - - compile - - - - org.eclipse.serializer.codegen.entity.EntityProcessor - - - -proc:only - -Amicrostream.entity.hashequalator=true - -Amicrostream.entity.appendable=true - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 3.4.0 - - - add-source - generate-sources - - add-source - - - - ${project.build.directory}/generated-sources/annotations - - - - - - - - From 485d7448561abdd16781392bace2915adc868c05 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Mon, 22 Apr 2024 13:54:14 +0200 Subject: [PATCH 100/126] remove Component annotation to prevent two beans.. --- .../spring/boot/types/converter/EclipseStoreConfigConverter.java | 1 - 1 file changed, 1 deletion(-) diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java index 42332d65..d9f0f0fa 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java @@ -33,7 +33,6 @@ * The {@code EclipseStoreConfigConverter} class is a Spring component that converts the Eclipse Store properties into a map. * This map can then be used to configure the Eclipse Store. */ -@Component public class EclipseStoreConfigConverter { From ef7fc1c48c907479a1b223bfb948c9f4f90b9063 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Mon, 22 Apr 2024 15:08:54 +0200 Subject: [PATCH 101/126] define own bean interface for StorageFoundation Supplier --- docs/modules/misc/pages/integrations/cdi.adoc | 2 +- .../src/main/java/module-info.java | 1 + .../DefaultEclipseStoreConfiguration.java | 5 ++-- .../EmbeddedStorageFoundationSupplier.java | 23 +++++++++++++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/suppliers/EmbeddedStorageFoundationSupplier.java diff --git a/docs/modules/misc/pages/integrations/cdi.adoc b/docs/modules/misc/pages/integrations/cdi.adoc index 33357b08..7c3ab7b8 100644 --- a/docs/modules/misc/pages/integrations/cdi.adoc +++ b/docs/modules/misc/pages/integrations/cdi.adoc @@ -54,7 +54,7 @@ public void someMethod() { ---- The _StorageManager_ configuration can be customized by CDI beans that implement the interface `org.eclipse.store.integrations.cdi.types.config.EmbeddedStorageFoundationCustomizer`. -The `customize` method is called with an `EmbeddedStorageFoundation` which allows you to fully customize the _StorageManager_ that will be created. You can for example, add the specific Type Handlers for JDK 8 as described on the https://docs.eclipsestore.io/manual/storage/addendum/specialized-type-handlers.html[documentation]. +The `customize` method is called with an `EmbeddedStorageFoundationSupplier` which allows you to fully customize the _StorageManager_ that will be created. You can for example, add the specific Type Handlers for JDK 8 as described on the https://docs.eclipsestore.io/manual/storage/addendum/specialized-type-handlers.html[documentation]. After the _StorageManager_ is created, the CDI beans that implement `org.eclipse.store.integrations.cdi.types.config.StorageManagerInitializer` are called. You have the opportunity to perform actions on the _StorageManager_ or root object. Following rules apply to the _StorageManager_ that is passed to the `initialize` method of the interface. diff --git a/integrations/spring-boot3/src/main/java/module-info.java b/integrations/spring-boot3/src/main/java/module-info.java index 3e719faf..f04b60e4 100644 --- a/integrations/spring-boot3/src/main/java/module-info.java +++ b/integrations/spring-boot3/src/main/java/module-info.java @@ -25,6 +25,7 @@ exports org.eclipse.store.integrations.spring.boot.types.converter; exports org.eclipse.store.integrations.spring.boot.types.factories; exports org.eclipse.store.integrations.spring.boot.types.concurrent; + exports org.eclipse.store.integrations.spring.boot.types.suppliers; requires transitive spring.beans; requires transitive spring.boot; diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java index b94ccc21..5ade57d7 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java @@ -17,6 +17,7 @@ import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; import org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageFoundationFactory; import org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageManagerFactory; +import org.eclipse.store.integrations.spring.boot.types.suppliers.EmbeddedStorageFoundationSupplier; import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; import org.springframework.beans.factory.annotation.Qualifier; @@ -57,7 +58,7 @@ public EclipseStoreProperties defaultEclipseStoreProperties() @Bean @Qualifier(DEFAULT_QUALIFIER) @ConditionalOnMissingBean - public Supplier> defaultStorageFoundationSupplier( + public EmbeddedStorageFoundationSupplier> defaultStorageFoundationSupplier( @Qualifier(DEFAULT_QUALIFIER) EclipseStoreProperties eclipseStoreProperties, EmbeddedStorageFoundationFactory foundationFactory ) @@ -80,7 +81,7 @@ public EmbeddedStorageManager defaultStorageManager( EmbeddedStorageManagerFactory embeddedStorageManagerFactory, @Qualifier(DEFAULT_QUALIFIER) EclipseStoreProperties eclipseStoreProperties, @Qualifier(DEFAULT_QUALIFIER) - Supplier> embeddedStorageFoundationSupplier + EmbeddedStorageFoundationSupplier> embeddedStorageFoundationSupplier ) { return embeddedStorageManagerFactory.createStorage( diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/suppliers/EmbeddedStorageFoundationSupplier.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/suppliers/EmbeddedStorageFoundationSupplier.java new file mode 100644 index 00000000..7d1c7292 --- /dev/null +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/suppliers/EmbeddedStorageFoundationSupplier.java @@ -0,0 +1,23 @@ +package org.eclipse.store.integrations.spring.boot.types.suppliers; + +/*- + * #%L + * EclipseStore Integrations SpringBoot + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + +import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; + +@FunctionalInterface +public interface EmbeddedStorageFoundationSupplier> +{ + T get(); +} From fb968ed7387122c8279123faf7989c626ec53c78 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Mon, 22 Apr 2024 16:17:09 +0200 Subject: [PATCH 102/126] revert configuration --- docs/modules/misc/pages/integrations/cdi.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/misc/pages/integrations/cdi.adoc b/docs/modules/misc/pages/integrations/cdi.adoc index 7c3ab7b8..33357b08 100644 --- a/docs/modules/misc/pages/integrations/cdi.adoc +++ b/docs/modules/misc/pages/integrations/cdi.adoc @@ -54,7 +54,7 @@ public void someMethod() { ---- The _StorageManager_ configuration can be customized by CDI beans that implement the interface `org.eclipse.store.integrations.cdi.types.config.EmbeddedStorageFoundationCustomizer`. -The `customize` method is called with an `EmbeddedStorageFoundationSupplier` which allows you to fully customize the _StorageManager_ that will be created. You can for example, add the specific Type Handlers for JDK 8 as described on the https://docs.eclipsestore.io/manual/storage/addendum/specialized-type-handlers.html[documentation]. +The `customize` method is called with an `EmbeddedStorageFoundation` which allows you to fully customize the _StorageManager_ that will be created. You can for example, add the specific Type Handlers for JDK 8 as described on the https://docs.eclipsestore.io/manual/storage/addendum/specialized-type-handlers.html[documentation]. After the _StorageManager_ is created, the CDI beans that implement `org.eclipse.store.integrations.cdi.types.config.StorageManagerInitializer` are called. You have the opportunity to perform actions on the _StorageManager_ or root object. Following rules apply to the _StorageManager_ that is passed to the `initialize` method of the interface. From 5555fed104463148f93acd8303984cea3f6ed347 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 23 Apr 2024 11:42:39 +0200 Subject: [PATCH 103/126] add conditional creating of beans --- .../DefaultEclipseStoreConfiguration.java | 4 +++ .../boot/DisableStorageAutoCreateTest.java | 27 +++++++++++++++++++ ...lication-storage-create-disable.properties | 1 + 3 files changed, 32 insertions(+) create mode 100644 integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/DisableStorageAutoCreateTest.java create mode 100644 integrations/spring-boot3/src/test/resources/application-storage-create-disable.properties diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java index 5ade57d7..8c62becb 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java @@ -23,8 +23,10 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import java.util.function.Supplier; @@ -58,6 +60,7 @@ public EclipseStoreProperties defaultEclipseStoreProperties() @Bean @Qualifier(DEFAULT_QUALIFIER) @ConditionalOnMissingBean + @ConditionalOnProperty(prefix = "org.eclipse.store.foundation", name = "auto-create", havingValue = "true", matchIfMissing = true) public EmbeddedStorageFoundationSupplier> defaultStorageFoundationSupplier( @Qualifier(DEFAULT_QUALIFIER) EclipseStoreProperties eclipseStoreProperties, EmbeddedStorageFoundationFactory foundationFactory @@ -77,6 +80,7 @@ public EmbeddedStorageFoundationSupplier> defaultSt @Bean @Qualifier(DEFAULT_QUALIFIER) @ConditionalOnMissingBean + @ConditionalOnProperty(prefix = "org.eclipse.store.storage", name = "auto-create", havingValue = "true", matchIfMissing = true) public EmbeddedStorageManager defaultStorageManager( EmbeddedStorageManagerFactory embeddedStorageManagerFactory, @Qualifier(DEFAULT_QUALIFIER) EclipseStoreProperties eclipseStoreProperties, diff --git a/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/DisableStorageAutoCreateTest.java b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/DisableStorageAutoCreateTest.java new file mode 100644 index 00000000..c987273b --- /dev/null +++ b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/DisableStorageAutoCreateTest.java @@ -0,0 +1,27 @@ +package test.eclipse.store.integrations.spring.boot; + +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.TestPropertySource; + +@TestPropertySource("classpath:application-storage-create-disable.properties") +@SpringBootTest +@ActiveProfiles("disable_auto_create") +public class DisableStorageAutoCreateTest +{ + + @Autowired + ApplicationContext context; + + @Test + void name() + { + Assertions.assertThrows(NoSuchBeanDefinitionException.class, () -> context.getBean(EmbeddedStorageManager.class)); + } +} diff --git a/integrations/spring-boot3/src/test/resources/application-storage-create-disable.properties b/integrations/spring-boot3/src/test/resources/application-storage-create-disable.properties new file mode 100644 index 00000000..fbcc0495 --- /dev/null +++ b/integrations/spring-boot3/src/test/resources/application-storage-create-disable.properties @@ -0,0 +1 @@ +org.eclipse.store.storage.auto-create=false From 8a2caeb55a1f9fad12b1f90e789570d8d6ecb245 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 23 Apr 2024 11:47:47 +0200 Subject: [PATCH 104/126] fix imports --- .../spring/boot/types/DefaultEclipseStoreConfiguration.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java index 8c62becb..6e745f8d 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java @@ -26,11 +26,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; -import java.util.function.Supplier; - @Configuration @AutoConfigureAfter(EclipseStoreSpringBoot.class) public class DefaultEclipseStoreConfiguration From 02576718a14f78af77cb3fa0eb23c856b9fb34e7 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Tue, 23 Apr 2024 15:12:26 +0200 Subject: [PATCH 105/126] add disable key to control auto-creation of defaults bean. --- .../DefaultEclipseStoreConfiguration.java | 4 +-- .../configuration/EclipseStoreProperties.java | 34 +++++++++++++++++++ ...lication-storage-create-disable.properties | 3 +- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java index 6e745f8d..838818c5 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/DefaultEclipseStoreConfiguration.java @@ -57,7 +57,7 @@ public EclipseStoreProperties defaultEclipseStoreProperties() @Bean @Qualifier(DEFAULT_QUALIFIER) @ConditionalOnMissingBean - @ConditionalOnProperty(prefix = "org.eclipse.store.foundation", name = "auto-create", havingValue = "true", matchIfMissing = true) + @ConditionalOnProperty(prefix = "org.eclipse.store", name = "auto-create-default-foundation", havingValue = "true", matchIfMissing = true) public EmbeddedStorageFoundationSupplier> defaultStorageFoundationSupplier( @Qualifier(DEFAULT_QUALIFIER) EclipseStoreProperties eclipseStoreProperties, EmbeddedStorageFoundationFactory foundationFactory @@ -77,7 +77,7 @@ public EmbeddedStorageFoundationSupplier> defaultSt @Bean @Qualifier(DEFAULT_QUALIFIER) @ConditionalOnMissingBean - @ConditionalOnProperty(prefix = "org.eclipse.store.storage", name = "auto-create", havingValue = "true", matchIfMissing = true) + @ConditionalOnProperty(prefix = "org.eclipse.store", name = "auto-create-default-storage", havingValue = "true", matchIfMissing = true) public EmbeddedStorageManager defaultStorageManager( EmbeddedStorageManagerFactory embeddedStorageManagerFactory, @Qualifier(DEFAULT_QUALIFIER) EclipseStoreProperties eclipseStoreProperties, diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java index 69f097d6..97b76ab9 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java @@ -202,6 +202,20 @@ public class EclipseStoreProperties */ private boolean registerJdk8Handlers; + /** + * This flag determines if a default foundation should be automatically created. + * If no user-defined bean with EmbeddedStorageFoundation exists, a default one will be created. + * To prevent this automatic creation, set this flag to false. + */ + private boolean autoCreateDefaultFoundation = true; + + /** + * This flag determines if a default storage should be automatically created. + * If no user-defined bean with EmbeddedStorage exists, a default one will be created. + * To prevent this automatic creation, set this flag to false. + */ + private boolean isAutoCreateDefaultStorage = true; + public Class getRoot() { return this.root; @@ -521,4 +535,24 @@ public void setRegisterJdk8Handlers(final boolean registerJdk8Handlers) { this.registerJdk8Handlers = registerJdk8Handlers; } + + public boolean isAutoCreateDefaultFoundation() + { + return autoCreateDefaultFoundation; + } + + public void setAutoCreateDefaultFoundation(boolean autoCreateDefaultFoundation) + { + this.autoCreateDefaultFoundation = autoCreateDefaultFoundation; + } + + public boolean isAutoCreateDefaultStorage() + { + return isAutoCreateDefaultStorage; + } + + public void setAutoCreateDefaultStorage(boolean autoCreateDefaultStorage) + { + isAutoCreateDefaultStorage = autoCreateDefaultStorage; + } } diff --git a/integrations/spring-boot3/src/test/resources/application-storage-create-disable.properties b/integrations/spring-boot3/src/test/resources/application-storage-create-disable.properties index fbcc0495..5607cc7e 100644 --- a/integrations/spring-boot3/src/test/resources/application-storage-create-disable.properties +++ b/integrations/spring-boot3/src/test/resources/application-storage-create-disable.properties @@ -1 +1,2 @@ -org.eclipse.store.storage.auto-create=false +org.eclipse.store.auto-create-default-storage=false +org.eclipse.store.auto-create-default-foundation=false From 9d633b3fb1f611d58d88b752190907bfc17039c7 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Wed, 24 Apr 2024 07:55:14 +0200 Subject: [PATCH 106/126] add docu to disable autocreate --- docs/modules/misc/pages/integrations/spring-boot.adoc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/modules/misc/pages/integrations/spring-boot.adoc b/docs/modules/misc/pages/integrations/spring-boot.adoc index 7b580e0a..cfe2b06b 100644 --- a/docs/modules/misc/pages/integrations/spring-boot.adoc +++ b/docs/modules/misc/pages/integrations/spring-boot.adoc @@ -102,6 +102,15 @@ a new `EmbeddedStorageManager` or `EmbeddedStorageFoundationFactory` to create a It is also possible to obtain the entire configuration within the `StorageManagerConfiguration` Bean, enabling you to directly create a foundation and storage manager. This can be helpful if you need to stop storage at runtime and then restart it. +== Disable Auto StorageManager creation +If the user does not define any beans of type _EmbeddedStorageFoundation_ and _EmbeddedStorageManager_, these beans are automatically created. This behavior can be changed using the following configuration. +[source,properties] +---- +org.eclipse.store.auto-create-default-storage=false +org.eclipse.store.auto-create-default-foundation=false +---- +If these configuration items are not present, these beans are created by default. + == Multiple Storage Managers You can have a more than one Storage Manager in your application. This can be useful if you want to have different storage targets for different data. For example, you might want to have a datastore for your user data and another for your product data. You can do this by creating multiple configuration classes and multiple Storage Managers. From 89ce9905f7e4f928210ef445a55591ae978165a5 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Wed, 24 Apr 2024 08:01:42 +0200 Subject: [PATCH 107/126] remove missleading sentence --- docs/modules/misc/pages/integrations/spring-boot.adoc | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/modules/misc/pages/integrations/spring-boot.adoc b/docs/modules/misc/pages/integrations/spring-boot.adoc index cfe2b06b..72267cb8 100644 --- a/docs/modules/misc/pages/integrations/spring-boot.adoc +++ b/docs/modules/misc/pages/integrations/spring-boot.adoc @@ -109,7 +109,6 @@ If the user does not define any beans of type _EmbeddedStorageFoundation_ and _E org.eclipse.store.auto-create-default-storage=false org.eclipse.store.auto-create-default-foundation=false ---- -If these configuration items are not present, these beans are created by default. == Multiple Storage Managers From bd937d2f1712171e0318a1c7ed95ae56fa8cfd86 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Wed, 24 Apr 2024 11:39:22 +0200 Subject: [PATCH 108/126] fixes after review --- .../configuration/EclipseStoreProperties.java | 6 +++--- .../EmbeddedStorageFoundationSupplier.java | 3 +-- .../spring/boot/DisableStorageAutoCreateTest.java | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java index 97b76ab9..1eacf9b2 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java @@ -214,7 +214,7 @@ public class EclipseStoreProperties * If no user-defined bean with EmbeddedStorage exists, a default one will be created. * To prevent this automatic creation, set this flag to false. */ - private boolean isAutoCreateDefaultStorage = true; + private boolean autoCreateDefaultStorage = true; public Class getRoot() { @@ -548,11 +548,11 @@ public void setAutoCreateDefaultFoundation(boolean autoCreateDefaultFoundation) public boolean isAutoCreateDefaultStorage() { - return isAutoCreateDefaultStorage; + return autoCreateDefaultStorage; } public void setAutoCreateDefaultStorage(boolean autoCreateDefaultStorage) { - isAutoCreateDefaultStorage = autoCreateDefaultStorage; + this.autoCreateDefaultStorage = autoCreateDefaultStorage; } } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/suppliers/EmbeddedStorageFoundationSupplier.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/suppliers/EmbeddedStorageFoundationSupplier.java index 7d1c7292..a91fd453 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/suppliers/EmbeddedStorageFoundationSupplier.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/suppliers/EmbeddedStorageFoundationSupplier.java @@ -17,7 +17,6 @@ import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; @FunctionalInterface -public interface EmbeddedStorageFoundationSupplier> +public interface EmbeddedStorageFoundationSupplier> extends java.util.function.Supplier { - T get(); } diff --git a/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/DisableStorageAutoCreateTest.java b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/DisableStorageAutoCreateTest.java index c987273b..ed312644 100644 --- a/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/DisableStorageAutoCreateTest.java +++ b/integrations/spring-boot3/src/test/java/test/eclipse/store/integrations/spring/boot/DisableStorageAutoCreateTest.java @@ -1,5 +1,19 @@ package test.eclipse.store.integrations.spring.boot; +/*- + * #%L + * EclipseStore Integrations SpringBoot + * %% + * Copyright (C) 2023 - 2024 MicroStream Software + * %% + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * #L% + */ + import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; From c1907119dbcafb1a47090aa5a3e2e33f4700377f Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Fri, 26 Apr 2024 09:17:24 +0200 Subject: [PATCH 109/126] fixing docu issues issue 207 and 208 (#209) fixes #207 fixes #208 --- .../pages/layered-entities/configuration.adoc | 2 +- .../storage/pages/storing-data/deep-copy.adoc | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/modules/misc/pages/layered-entities/configuration.adoc b/docs/modules/misc/pages/layered-entities/configuration.adoc index 4f581bad..49cd807f 100644 --- a/docs/modules/misc/pages/layered-entities/configuration.adoc +++ b/docs/modules/misc/pages/layered-entities/configuration.adoc @@ -9,7 +9,7 @@ The maven configuration looks like this: org.eclipse.serializer - entity-codegen + codegen-entity {maven-version} diff --git a/docs/modules/storage/pages/storing-data/deep-copy.adoc b/docs/modules/storage/pages/storing-data/deep-copy.adoc index 10914474..fadfef5a 100644 --- a/docs/modules/storage/pages/storing-data/deep-copy.adoc +++ b/docs/modules/storage/pages/storing-data/deep-copy.adoc @@ -24,6 +24,23 @@ What is actually needed at this point is a deep copy. You need to create a compl == Deep Copy Utility (ObjectCopier) {product-name} provides full support for a deep copy. It can be relatively easily called and a deep copy of the data will be created. +== Prerequisites +The ObjectCopier is part of the eclipse serializer. + +[source, xml, title="pom.xml", subs=attributes+] +---- + + + org.eclipse.serializer + serializer + {maven-version} + + +---- + +== Usage +To create a deep copy just create a ObjectCopier and use its copy method. + [source, java] ---- ObjectCopier objectCopier = ObjectCopier.New(); From 18ca0de06e3e942ddcd1d9004d084fe521ed910d Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Fri, 3 May 2024 11:57:30 +0200 Subject: [PATCH 110/126] Adapt to PersistenceStorer.Creator methods change (#215) --- .../PersistenceStorerExtension.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceStorerExtension.java b/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceStorerExtension.java index 41a3aa2d..7d7e6971 100644 --- a/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceStorerExtension.java +++ b/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceStorerExtension.java @@ -20,6 +20,7 @@ import org.eclipse.serializer.persistence.types.PersistenceStorer; import org.eclipse.serializer.persistence.types.PersistenceTarget; import org.eclipse.serializer.persistence.types.PersistenceTypeHandlerManager; +import org.eclipse.serializer.persistence.types.Persister; import org.eclipse.serializer.reference.ObjectSwizzling; import org.eclipse.serializer.util.BufferSizeProviderIncremental; @@ -79,18 +80,19 @@ public Creator(PersistenceStorer.Creator delegate) super(); this.delegate = delegate; } - + @Override public PersistenceStorer createLazyStorer( final PersistenceTypeHandlerManager typeManager , final PersistenceObjectManager objectManager , final ObjectSwizzling objectRetriever , final PersistenceTarget target , - final BufferSizeProviderIncremental bufferSizeProvider + final BufferSizeProviderIncremental bufferSizeProvider, + final Persister persister ) { return new PersistenceStorerExtension( - this.delegate.createLazyStorer(typeManager, objectManager, objectRetriever, target, bufferSizeProvider) + this.delegate.createLazyStorer(typeManager, objectManager, objectRetriever, target, bufferSizeProvider, persister) ); } @@ -100,11 +102,12 @@ public PersistenceStorer createEagerStorer( final PersistenceObjectManager objectManager , final ObjectSwizzling objectRetriever , final PersistenceTarget target , - final BufferSizeProviderIncremental bufferSizeProvider + final BufferSizeProviderIncremental bufferSizeProvider, + final Persister persister ) { return new PersistenceStorerExtension( - this.delegate.createEagerStorer(typeManager, objectManager, objectRetriever, target, bufferSizeProvider) + this.delegate.createEagerStorer(typeManager, objectManager, objectRetriever, target, bufferSizeProvider, persister) ); } From 7d8897b085c687d759202e1c1d2d4b8bdb3a5ef5 Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Fri, 3 May 2024 12:54:04 +0200 Subject: [PATCH 111/126] Replaced XDebug console output by logger (#214) --- .../java/org/eclipse/store/storage/types/StorageSystem.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageSystem.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageSystem.java index 118f2117..39376ab9 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageSystem.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageSystem.java @@ -21,7 +21,6 @@ import java.util.concurrent.atomic.AtomicLong; import org.eclipse.serializer.afs.types.AFileSystem; -import org.eclipse.serializer.meta.XDebug; import org.eclipse.serializer.monitoring.MonitoringManager; import org.eclipse.serializer.persistence.types.ObjectIdsSelector; import org.eclipse.serializer.persistence.types.Persistence; @@ -533,7 +532,7 @@ private void internalShutdown() throws InterruptedException // note: this method is already entered under a lock protection, so there can't be a race condition here. if(this.taskbroker == null) { - XDebug.println("taskbroker is null"); + logger.debug("taskbroker is null"); // storage not started in the first place return; } From 20fd94f28919495ad30a4ddc697dd40039677812 Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Mon, 6 May 2024 12:08:23 +0200 Subject: [PATCH 112/126] Follow S3 batch delete limit (#213) --- .../store/afs/aws/s3/types/S3Connector.java | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3Connector.java b/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3Connector.java index 1d5001a6..8644c7da 100644 --- a/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3Connector.java +++ b/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3Connector.java @@ -20,14 +20,15 @@ import java.io.BufferedInputStream; import java.io.IOException; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import java.util.stream.Stream; -import org.eclipse.store.afs.blobstore.types.BlobStoreConnector; -import org.eclipse.store.afs.blobstore.types.BlobStorePath; import org.eclipse.serializer.exceptions.IORuntimeException; import org.eclipse.serializer.io.ByteBufferInputStream; +import org.eclipse.store.afs.blobstore.types.BlobStoreConnector; +import org.eclipse.store.afs.blobstore.types.BlobStorePath; import software.amazon.awssdk.core.ResponseBytes; import software.amazon.awssdk.core.internal.util.Mimetype; @@ -227,6 +228,31 @@ protected boolean internalDeleteBlobs( final BlobStorePath file, final List blobs ) + { + final int limit = 1000; + if(blobs.size() <= limit) + { + return this.internalDeleteBlobs0(file, blobs); + } + + boolean success = true; + final List toDelete = new ArrayList<>(blobs); + while(!toDelete.isEmpty()) + { + final List subList = toDelete.subList(0, Math.min(limit, toDelete.size())); + toDelete.removeAll(subList); + if(!this.internalDeleteBlobs0(file, subList)) + { + success = false; + } + } + return success; + } + + protected boolean internalDeleteBlobs0( + final BlobStorePath file, + final List blobs + ) { final List objects = blobs.stream() .map(obj -> ObjectIdentifier.builder().key(obj.key()).build()) From 2493ed40850ae0f0d0da97afe7b755343c401dd0 Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Mon, 6 May 2024 12:09:20 +0200 Subject: [PATCH 113/126] Adjust code to ensure Minio compatibility (#197) --- .../org/eclipse/store/afs/aws/s3/types/S3Connector.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3Connector.java b/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3Connector.java index 8644c7da..2f4ff07c 100644 --- a/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3Connector.java +++ b/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3Connector.java @@ -39,7 +39,6 @@ import software.amazon.awssdk.services.s3.model.DeleteObjectsResponse; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.GetObjectResponse; -import software.amazon.awssdk.services.s3.model.HeadObjectRequest; import software.amazon.awssdk.services.s3.model.ListObjectsV2Request; import software.amazon.awssdk.services.s3.model.NoSuchBucketException; import software.amazon.awssdk.services.s3.model.NoSuchKeyException; @@ -178,12 +177,14 @@ protected boolean internalDirectoryExists( { try { - final HeadObjectRequest request = HeadObjectRequest.builder() + final PutObjectRequest request = PutObjectRequest + .builder() .bucket(directory.container()) .key(toContainerKey(directory)) .build() ; - this.s3.headObject(request); + this.s3.putObject(request, RequestBody.empty()); + return true; } catch(final NoSuchKeyException e) From 45897a8109487e7ff3b9c2b26fe9a452912627ab Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Mon, 6 May 2024 14:43:41 +0200 Subject: [PATCH 114/126] 1.3.2 docs (#216) --- docs/antora.yml | 4 ++-- docs/modules/intro/pages/changelog.adoc | 11 +++++++++++ storage/embedded-tools/storage-migrator/README.md | 6 +++--- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/docs/antora.yml b/docs/antora.yml index 16391c2e..016c1d50 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -8,6 +8,6 @@ nav: asciidoc: attributes: product-name: 'EclipseStore' - display-version: '1.3.1' + display-version: '1.3.2' api-version: '1' - maven-version: '1.3.1' + maven-version: '1.3.2' diff --git a/docs/modules/intro/pages/changelog.adoc b/docs/modules/intro/pages/changelog.adoc index 5ddd69ec..bbea355a 100644 --- a/docs/modules/intro/pages/changelog.adoc +++ b/docs/modules/intro/pages/changelog.adoc @@ -1,5 +1,16 @@ = Changelog +== 1.3.2 + +* Spring Boot improvements https://github.com/eclipse-store/store/pull/206[[206]] +* Ensure Minio compatibility https://github.com/eclipse-store/store/pull/197[[197]] + +=== Bugfixes + +* Fix wrong entity layer service config https://github.com/eclipse-serializer/serializer/pull/123[[123]] +* Follow S3 batch delete limit https://github.com/eclipse-store/store/pull/213[[213]] + + == 1.3.1 * Spring Boot improvements https://github.com/eclipse-store/store/pull/136[[136]] diff --git a/storage/embedded-tools/storage-migrator/README.md b/storage/embedded-tools/storage-migrator/README.md index 7597ccf6..651e922b 100644 --- a/storage/embedded-tools/storage-migrator/README.md +++ b/storage/embedded-tools/storage-migrator/README.md @@ -16,17 +16,17 @@ The type dictionary migration is only done when `typeDictionaryRelativePath` is ### Migration of both, source code and type dictionary: ```` -mvn org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.eclipse.store.storage.embedded.tools.storage.migrator.ConvertProject -Drewrite.recipeArtifactCoordinates=org.eclipse.store:storage-embedded-tools-storage-migrator:1.3.1 -DeclipseStoreVersion=1.3.1 -Drewrite.plainTextMasks=**/*.ptd -DtypeDictionaryRelativeFilePath=src/main/resources/PersistenceTypeDictionary.ptd +mvn org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.eclipse.store.storage.embedded.tools.storage.migrator.ConvertProject -Drewrite.recipeArtifactCoordinates=org.eclipse.store:storage-embedded-tools-storage-migrator:1.3.2 -DeclipseStoreVersion=1.3.2 -Drewrite.plainTextMasks=**/*.ptd -DtypeDictionaryRelativeFilePath=src/main/resources/PersistenceTypeDictionary.ptd ```` ### Migration of source code only: ```` -mvn org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.eclipse.store.storage.embedded.tools.storage.migrator.ConvertProject -Drewrite.recipeArtifactCoordinates=org.eclipse.store:storage-embedded-tools-storage-migrator:1.3.1 -DeclipseStoreVersion=1.3.1 +mvn org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.eclipse.store.storage.embedded.tools.storage.migrator.ConvertProject -Drewrite.recipeArtifactCoordinates=org.eclipse.store:storage-embedded-tools-storage-migrator:1.3.2 -DeclipseStoreVersion=1.3.2 ```` ### Migration of type dictionary only: ```` -mvn org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.eclipse.store.storage.embedded.tools.storage.migrator.ConvertProject -Drewrite.recipeArtifactCoordinates=org.eclipse.store:storage-embedded-tools-storage-migrator:1.3.1 -Drewrite.plainTextMasks=**/*.ptd -DtypeDictionaryRelativeFilePath=src/main/resources/PersistenceTypeDictionary.ptd +mvn org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.eclipse.store.storage.embedded.tools.storage.migrator.ConvertProject -Drewrite.recipeArtifactCoordinates=org.eclipse.store:storage-embedded-tools-storage-migrator:1.3.2 -Drewrite.plainTextMasks=**/*.ptd -DtypeDictionaryRelativeFilePath=src/main/resources/PersistenceTypeDictionary.ptd ```` From 082679fd4e3481900b8380a8c6b698df366f5f6c Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Tue, 25 Jun 2024 12:55:50 +0200 Subject: [PATCH 115/126] Commit listener registration (#228) --- .../extensionwrapper/PersistenceStorerWrapper.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceStorerWrapper.java b/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceStorerWrapper.java index 53bb3e32..ea72527c 100644 --- a/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceStorerWrapper.java +++ b/examples/extension-wrapper/src/main/java/org/eclipse/store/examples/extensionwrapper/PersistenceStorerWrapper.java @@ -4,16 +4,17 @@ * #%L * EclipseStore Example Extension Wrapper * %% - * Copyright (C) 2023 MicroStream Software + * Copyright (C) 2023 - 2024 MicroStream Software * %% * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * #L% */ +import org.eclipse.serializer.persistence.types.PersistenceCommitListener; import org.eclipse.serializer.persistence.types.PersistenceStorer; /** @@ -120,7 +121,11 @@ public long maximumCapacity() return this.delegate.maximumCapacity(); } - + @Override + public void registerCommitListener(final PersistenceCommitListener listener) + { + this.delegate.registerCommitListener(listener); + } } From f346ab1bc64c99faac37544c0e36ee4898bfe3fb Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Fri, 5 Jul 2024 13:57:36 +0200 Subject: [PATCH 116/126] Tooling Documentation (#237) * Create README.md * Typos * Add tools doc --------- Co-authored-by: Florian Habermann --- docs/modules/ROOT/nav.adoc | 1 + .../modules/storage/pages/addendum/tools.adoc | 13 +++++++ .../storage-converter/README.md | 38 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 docs/modules/storage/pages/addendum/tools.adoc create mode 100644 storage/embedded-tools/storage-converter/README.md diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index c9f8c578..5fdbb1a5 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -68,6 +68,7 @@ ** Addendum *** xref:storage:addendum/supported-java-features.adoc[Supported Java Features] *** xref:storage:addendum/specialized-type-handlers.adoc[Specialized Type Handlers] +*** xref:storage:addendum/tools.adoc[Tools] *** xref:storage:addendum/examples-and-demo-projects.adoc[Examples and Demo Projects] * xref:serializer:index.adoc[Serializer] * xref:cache:index.adoc[Cache] diff --git a/docs/modules/storage/pages/addendum/tools.adoc b/docs/modules/storage/pages/addendum/tools.adoc new file mode 100644 index 00000000..7f5a4926 --- /dev/null +++ b/docs/modules/storage/pages/addendum/tools.adoc @@ -0,0 +1,13 @@ += Tools + +== Storage Migrator + +With this utility you can easily migrate MicroStream projects to EclipseStore. + +For more information see the https://github.com/eclipse-store/store/tree/main/storage/embedded-tools/storage-migrator[readme file]. + +== Storage Converter + +The storage converter provides an option to copy a storage to another storage target, for example to change the channel count or move the storage from the local disk to the cloud. + +For more information see the https://github.com/eclipse-store/store/tree/main/storage/embedded-tools/storage-converter[readme file]. diff --git a/storage/embedded-tools/storage-converter/README.md b/storage/embedded-tools/storage-converter/README.md new file mode 100644 index 00000000..8682f732 --- /dev/null +++ b/storage/embedded-tools/storage-converter/README.md @@ -0,0 +1,38 @@ + +# EclipseStore Storage Converter + +Main purpose of the EclipseStore Storage converter is providing an option to copy a storage to another storage target. + +The converter will not copy redundant older persisted objects. It only copies the objects latest version. +It is possible to define a different channel count for the target than the source storage has. + +## Building the storage converter standalone jar + +To build the converter standalone jar using Maven you need to active the profile **converter-standalone**. + +```console +mvn -Pconverter-standalone clean package +``` + + +## Usage + +### standalone jar + +To configure the input and output storage an [external configuration](https://docs.eclipsestore.io/manual/storage/configuration/index.html#external-configuration) file for each storage is required. + +```console +java -jar storage-embedded-tools-storage-converter-1.3.2.jar sourceCongig.xml targetConfig.xml +``` + +### StorageConverter.java + +Instead of the standalone-jar you may utilize the java class + +``` +org.eclipse.store.storage.embedded.tools.storage.converter.StorageConverter.StorageConverter(StorageConfiguration, StorageConfiguration) +``` + +which gives you some more control on the storage's configurations. + + From f25a5149c3fd2f33218cfe6a2fb75a577732e76c Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Tue, 9 Jul 2024 12:03:57 +0200 Subject: [PATCH 117/126] S3 enhancements (#242) * Prevent "/" folder creation Fixes #234 * Update AWS dependencies * Add loop for fetching more objects * Move path resolution to file system * Add support for S3 directory buckets * Doc update * Fix property propagation --------- Co-authored-by: Zdenek Jonas --- afs/aws/aws/src/main/java/module-info.java | 1 + .../types/DynamoDbFileSystemCreator.java | 2 +- afs/aws/pom.xml | 2 +- .../store/afs/aws/s3/types/S3Connector.java | 135 +++++++++++++++--- .../afs/aws/s3/types/S3FileSystemCreator.java | 16 ++- .../types/AzureStorageFileSystemCreator.java | 2 +- ...GoogleCloudFirestoreFileSystemCreator.java | 2 +- .../kafka/types/KafkaFileSystemCreator.java | 2 +- .../store/afs/nio/types/NioFileSystem.java | 11 ++ ...leCloudObjectStorageFileSystemCreator.java | 2 +- .../redis/types/RedisFileSystemCreator.java | 10 +- .../afs/sql/types/SqlFileSystemCreator.java | 2 +- .../blob-stores/aws-dynamodb.adoc | 3 + .../storage-targets/blob-stores/aws-s3.adoc | 69 ++++++++- .../storage/pages/storage-targets/index.adoc | 4 +- .../aws/AbstractAwsProperties.java | 16 +++ .../boot/types/configuration/aws/S3.java | 19 +++ .../boot/types/converter/ConfigKeys.java | 8 +- .../EclipseStoreConfigConverter.java | 10 +- ...geFoundationCreatorConfigurationBased.java | 29 ++-- 20 files changed, 282 insertions(+), 63 deletions(-) diff --git a/afs/aws/aws/src/main/java/module-info.java b/afs/aws/aws/src/main/java/module-info.java index 2129246e..59a8f767 100644 --- a/afs/aws/aws/src/main/java/module-info.java +++ b/afs/aws/aws/src/main/java/module-info.java @@ -20,6 +20,7 @@ requires transitive software.amazon.awssdk.auth; requires transitive software.amazon.awssdk.awscore; requires transitive software.amazon.awssdk.core; + requires transitive software.amazon.awssdk.identity.spi; requires transitive software.amazon.awssdk.regions; requires transitive software.amazon.awssdk.utils; } diff --git a/afs/aws/dynamodb/src/main/java/org/eclipse/store/afs/aws/dynamodb/types/DynamoDbFileSystemCreator.java b/afs/aws/dynamodb/src/main/java/org/eclipse/store/afs/aws/dynamodb/types/DynamoDbFileSystemCreator.java index ac628a85..607bf2b3 100644 --- a/afs/aws/dynamodb/src/main/java/org/eclipse/store/afs/aws/dynamodb/types/DynamoDbFileSystemCreator.java +++ b/afs/aws/dynamodb/src/main/java/org/eclipse/store/afs/aws/dynamodb/types/DynamoDbFileSystemCreator.java @@ -44,7 +44,7 @@ public AFileSystem create( this.populateBuilder(clientBuilder, dynamoConfiguration); final DynamoDbClient client = clientBuilder.build(); - final boolean cache = configuration.optBoolean("cache").orElse(true); + final boolean cache = dynamoConfiguration.optBoolean("cache").orElse(true); final DynamoDbConnector connector = cache ? DynamoDbConnector.Caching(client) : DynamoDbConnector.New(client) diff --git a/afs/aws/pom.xml b/afs/aws/pom.xml index 1c28882e..07c0ecf5 100644 --- a/afs/aws/pom.xml +++ b/afs/aws/pom.xml @@ -31,7 +31,7 @@ software.amazon.awssdk bom - 2.17.272 + 2.26.14 pom import diff --git a/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3Connector.java b/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3Connector.java index 2f4ff07c..1f770948 100644 --- a/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3Connector.java +++ b/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3Connector.java @@ -40,6 +40,7 @@ import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.awssdk.services.s3.model.ListObjectsV2Request; +import software.amazon.awssdk.services.s3.model.ListObjectsV2Response; import software.amazon.awssdk.services.s3.model.NoSuchBucketException; import software.amazon.awssdk.services.s3.model.NoSuchKeyException; import software.amazon.awssdk.services.s3.model.ObjectIdentifier; @@ -57,13 +58,15 @@ * ); * * - * + *

          + * If you are using general purpose buckets, create a connector with {@link #New(S3Client)} or {@link #Caching(S3Client)}, + * if you want to use directory buckets, like Express One Zone, use {@link #NewDirectory(S3Client)} or {@link #CachingDirectory(S3Client)}. * */ public interface S3Connector extends BlobStoreConnector { /** - * Pseudo-constructor method which creates a new {@link S3Connector}. + * Pseudo-constructor method which creates a new {@link S3Connector} for general purpose buckets. * * @param s3 connection to the S3 storage * @return a new {@link S3Connector} @@ -79,7 +82,7 @@ public static S3Connector New( } /** - * Pseudo-constructor method which creates a new {@link S3Connector} with cache. + * Pseudo-constructor method which creates a new {@link S3Connector} with cache for general purpose buckets. * * @param s3 connection to the S3 storage * @return a new {@link S3Connector} @@ -93,13 +96,44 @@ public static S3Connector Caching( true ); } + /** + * Pseudo-constructor method which creates a new {@link S3Connector} for directory buckets. + * + * @param s3 connection to the S3 storage + * @return a new {@link S3Connector} + */ + public static S3Connector NewDirectory( + final S3Client s3 + ) + { + return new S3Connector.Directory( + notNull(s3), + false + ); + } + + /** + * Pseudo-constructor method which creates a new {@link S3Connector} with cache for directory buckets. + * + * @param s3 connection to the S3 storage + * @return a new {@link S3Connector} + */ + public static S3Connector CachingDirectory( + final S3Client s3 + ) + { + return new S3Connector.Directory( + notNull(s3), + true + ); + } public static class Default extends BlobStoreConnector.Abstract implements S3Connector { - private final S3Client s3; + protected final S3Client s3; Default( final S3Client s3 , @@ -118,16 +152,28 @@ public static class Default @Override protected Stream blobs(final BlobStorePath file) { - final String prefix = toBlobKeyPrefix(file); - final Pattern pattern = Pattern.compile(blobKeyRegex(prefix)); - final ListObjectsV2Request request = ListObjectsV2Request - .builder() - .bucket(file.container()) - .prefix(prefix) - .build(); - return this.s3.listObjectsV2(request) - .contents() - .stream() + final String prefix = toBlobKeyPrefix(file); + final Pattern pattern = Pattern.compile(blobKeyRegex(prefix)); + final List blobs = new ArrayList<>(); + String continuationToken = null; + do + { + final ListObjectsV2Request request = ListObjectsV2Request + .builder() + .bucket(file.container()) + .prefix(prefix) + .continuationToken(continuationToken) + .build(); + final ListObjectsV2Response response = this.s3.listObjectsV2(request); + blobs.addAll(response.contents()); + continuationToken = response.isTruncated() + ? response.nextContinuationToken() + : null + ; + } + while(continuationToken != null); + + return blobs.stream() .filter(obj -> pattern.matcher(obj.key()).matches()) .sorted(this.blobComparator()) ; @@ -177,10 +223,16 @@ protected boolean internalDirectoryExists( { try { + final String containerKey = toContainerKey(directory); + if(containerKey.isBlank() || BlobStorePath.SEPARATOR.equals(containerKey)) + { + return true; + } + final PutObjectRequest request = PutObjectRequest .builder() .bucket(directory.container()) - .key(toContainerKey(directory)) + .key(containerKey) .build() ; this.s3.putObject(request, RequestBody.empty()); @@ -213,9 +265,15 @@ protected boolean internalCreateDirectory( final BlobStorePath directory ) { + final String containerKey = toContainerKey(directory); + if(containerKey.isBlank() || BlobStorePath.SEPARATOR.equals(containerKey)) + { + return true; + } + final PutObjectRequest request = PutObjectRequest.builder() .bucket(directory.container()) - .key(toContainerKey(directory)) + .key(containerKey) .build() ; final RequestBody body = RequestBody.empty(); @@ -304,5 +362,50 @@ protected long internalWriteData( } } + + + public static class Directory extends Default + { + + Directory(final S3Client s3, final boolean useCache) + { + super(s3, useCache); + } + + /* + * Needs to load all objects in a "directory" and filter afterwards, + * because directory buckets only support listing with prefixes ending in '/'. + */ + @Override + protected Stream blobs(final BlobStorePath file) + { + final String prefix = toChildKeysPrefix(file.parentPath()); + final Pattern pattern = Pattern.compile(blobKeyRegex(toBlobKeyPrefix(file))); + final List blobs = new ArrayList<>(); + String continuationToken = null; + do + { + final ListObjectsV2Request request = ListObjectsV2Request + .builder() + .bucket(file.container()) + .prefix(prefix) + .continuationToken(continuationToken) + .build(); + final ListObjectsV2Response response = this.s3.listObjectsV2(request); + blobs.addAll(response.contents()); + continuationToken = response.isTruncated() + ? response.nextContinuationToken() + : null + ; + } + while(continuationToken != null); + + return blobs.stream() + .filter(obj -> pattern.matcher(obj.key()).matches()) + .sorted(this.blobComparator()) + ; + } + + } } diff --git a/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3FileSystemCreator.java b/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3FileSystemCreator.java index fb548ad4..5c5a07ca 100644 --- a/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3FileSystemCreator.java +++ b/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3FileSystemCreator.java @@ -45,10 +45,18 @@ public AFileSystem create( this.populateBuilder(clientBuilder, s3Configuration); final S3Client client = clientBuilder.build(); - final boolean cache = configuration.optBoolean("cache").orElse(true); - final S3Connector connector = cache - ? S3Connector.Caching(client) - : S3Connector.New(client) + final boolean cache = s3Configuration.optBoolean("cache").orElse(true); + final boolean directory = s3Configuration.optBoolean("directory-bucket").orElse(false); + final S3Connector connector = + directory + ? (cache + ? S3Connector.CachingDirectory(client) + : S3Connector.NewDirectory(client) + ) + : (cache + ? S3Connector.Caching(client) + : S3Connector.New(client) + ) ; return BlobStoreFileSystem.New(connector); } diff --git a/afs/azure/storage/src/main/java/org/eclipse/store/afs/azure/storage/types/AzureStorageFileSystemCreator.java b/afs/azure/storage/src/main/java/org/eclipse/store/afs/azure/storage/types/AzureStorageFileSystemCreator.java index b60b9d8b..f86db942 100644 --- a/afs/azure/storage/src/main/java/org/eclipse/store/afs/azure/storage/types/AzureStorageFileSystemCreator.java +++ b/afs/azure/storage/src/main/java/org/eclipse/store/afs/azure/storage/types/AzureStorageFileSystemCreator.java @@ -101,7 +101,7 @@ public AFileSystem create( } final BlobServiceClient client = clientBuilder.buildClient(); - final boolean cache = configuration.optBoolean("cache").orElse(true); + final boolean cache = azureConfiguration.optBoolean("cache").orElse(true); final AzureStorageConnector connector = cache ? AzureStorageConnector.Caching(client) : AzureStorageConnector.New(client) diff --git a/afs/googlecloud/firestore/src/main/java/org/eclipse/store/afs/googlecloud/firestore/types/GoogleCloudFirestoreFileSystemCreator.java b/afs/googlecloud/firestore/src/main/java/org/eclipse/store/afs/googlecloud/firestore/types/GoogleCloudFirestoreFileSystemCreator.java index 54bbb8f0..11f039e0 100644 --- a/afs/googlecloud/firestore/src/main/java/org/eclipse/store/afs/googlecloud/firestore/types/GoogleCloudFirestoreFileSystemCreator.java +++ b/afs/googlecloud/firestore/src/main/java/org/eclipse/store/afs/googlecloud/firestore/types/GoogleCloudFirestoreFileSystemCreator.java @@ -84,7 +84,7 @@ public AFileSystem create( ); final Firestore firestore = optionsBuilder.build().getService(); - final boolean cache = configuration.optBoolean("cache").orElse(true); + final boolean cache = firestoreConfiguration.optBoolean("cache").orElse(true); final GoogleCloudFirestoreConnector connector = cache ? GoogleCloudFirestoreConnector.Caching(firestore) : GoogleCloudFirestoreConnector.New(firestore) diff --git a/afs/kafka/src/main/java/org/eclipse/store/afs/kafka/types/KafkaFileSystemCreator.java b/afs/kafka/src/main/java/org/eclipse/store/afs/kafka/types/KafkaFileSystemCreator.java index d3d2e909..59cf795e 100644 --- a/afs/kafka/src/main/java/org/eclipse/store/afs/kafka/types/KafkaFileSystemCreator.java +++ b/afs/kafka/src/main/java/org/eclipse/store/afs/kafka/types/KafkaFileSystemCreator.java @@ -42,7 +42,7 @@ public AFileSystem create( final Properties kafkaProperties = new Properties(); kafkaProperties.putAll(kafkaConfiguration.coalescedMap()); - final boolean cache = configuration.optBoolean("cache").orElse(true); + final boolean cache = kafkaConfiguration.optBoolean("cache").orElse(true); final KafkaConnector connector = cache ? KafkaConnector.Caching(kafkaProperties) : KafkaConnector.New(kafkaProperties) diff --git a/afs/nio/src/main/java/org/eclipse/store/afs/nio/types/NioFileSystem.java b/afs/nio/src/main/java/org/eclipse/store/afs/nio/types/NioFileSystem.java index ac9fa958..152b4cf3 100644 --- a/afs/nio/src/main/java/org/eclipse/store/afs/nio/types/NioFileSystem.java +++ b/afs/nio/src/main/java/org/eclipse/store/afs/nio/types/NioFileSystem.java @@ -18,6 +18,7 @@ import java.nio.file.FileSystem; import java.nio.file.Path; +import java.nio.file.Paths; import org.eclipse.serializer.afs.types.ADirectory; import org.eclipse.serializer.afs.types.AFile; @@ -41,6 +42,16 @@ public interface NioFileSystem extends AFileSystem, AResolver */ @Override public ADirectory ensureDefaultRoot(); + + @Override + public default String[] resolvePath(final String fullPath) + { + final String resolved = fullPath.startsWith("~/") || fullPath.startsWith("~\\") + ? Paths.get(System.getProperty("user.home"), fullPath.substring(2)).toString() + : fullPath + ; + return AFileSystem.super.resolvePath(resolved); + } public interface Defaults diff --git a/afs/oraclecloud/objectstorage/src/main/java/org/eclipse/store/afs/oraclecloud/objectstorage/types/OracleCloudObjectStorageFileSystemCreator.java b/afs/oraclecloud/objectstorage/src/main/java/org/eclipse/store/afs/oraclecloud/objectstorage/types/OracleCloudObjectStorageFileSystemCreator.java index d6e6ace8..3156b329 100644 --- a/afs/oraclecloud/objectstorage/src/main/java/org/eclipse/store/afs/oraclecloud/objectstorage/types/OracleCloudObjectStorageFileSystemCreator.java +++ b/afs/oraclecloud/objectstorage/src/main/java/org/eclipse/store/afs/oraclecloud/objectstorage/types/OracleCloudObjectStorageFileSystemCreator.java @@ -107,7 +107,7 @@ public AFileSystem create( value -> client.setEndpoint(value) ); - final boolean cache = configuration.optBoolean("cache").orElse(true); + final boolean cache = objectStorageConfiguration.optBoolean("cache").orElse(true); final OracleCloudObjectStorageConnector connector = cache ? OracleCloudObjectStorageConnector.Caching(client) : OracleCloudObjectStorageConnector.New(client) diff --git a/afs/redis/src/main/java/org/eclipse/store/afs/redis/types/RedisFileSystemCreator.java b/afs/redis/src/main/java/org/eclipse/store/afs/redis/types/RedisFileSystemCreator.java index 4c7774da..1b861f2b 100644 --- a/afs/redis/src/main/java/org/eclipse/store/afs/redis/types/RedisFileSystemCreator.java +++ b/afs/redis/src/main/java/org/eclipse/store/afs/redis/types/RedisFileSystemCreator.java @@ -33,13 +33,19 @@ public AFileSystem create( final Configuration configuration ) { - final String redisUri = configuration.get("redis.uri"); + final Configuration redisConfiguration = configuration.child("redis"); + if(redisConfiguration == null) + { + return null; + } + + final String redisUri = redisConfiguration.get("uri"); if(XChars.isEmpty(redisUri)) { return null; } - final boolean cache = configuration.optBoolean("cache").orElse(true); + final boolean cache = redisConfiguration.optBoolean("cache").orElse(true); final RedisConnector connector = cache ? RedisConnector.Caching(redisUri) : RedisConnector.New(redisUri) diff --git a/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreator.java b/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreator.java index 21ed2862..9d3e0928 100644 --- a/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreator.java +++ b/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreator.java @@ -66,7 +66,7 @@ public AFileSystem create( sqlConfiguration, dataSourceProvider.provideDataSource(sqlConfiguration.detach()) ); - final boolean cache = configuration.optBoolean("cache").orElse(true); + final boolean cache = sqlConfiguration.optBoolean("cache").orElse(true); return SqlFileSystem.New(cache ? SqlConnector.Caching(sqlProvider) : SqlConnector.New(sqlProvider) diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/aws-dynamodb.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/aws-dynamodb.adoc index 58ae34bd..5a9cc37e 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/aws-dynamodb.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/aws-dynamodb.adoc @@ -45,6 +45,9 @@ storage-filesystem.aws.dynamodb.credentials.region=us-east-1 |endpoint-override |The endpoint with which the SDK should communicate. +|cache +|Defines if the DynamoDbConnector should use caching. + |region |Configure the region with which the SDK should communicate. If this is not specified, the SDK will attempt to identify the endpoint automatically using the following logic: diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/aws-s3.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/aws-s3.adoc index 85f9de1f..e4428226 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/aws-s3.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/aws-s3.adoc @@ -10,29 +10,77 @@ software.amazon.awssdk s3 - 2.17.272 + 2.26.14 ---- +== General Purpose Buckets + +For general purpose buckets you can create a S3Connector handing over a S3Client. +Please refer to the official https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/home.html[AWS SDK Documentation] for details. + [source, java] ---- -S3Client client = ...; +S3Client client = S3Client.builder() + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create(ACCESS_KEY, SECRET_ACCESS_KEY) + )) + .region(Region.EU_NORTH_1) + .build() +; BlobStoreFileSystem fileSystem = BlobStoreFileSystem.New( S3Connector.Caching(client) ); -EmbeddedStorage.start(fileSystem.ensureDirectoryPath("storage")); +EmbeddedStorage.start(fileSystem.ensureDirectoryPath("bucket-name", "folder", "subfolder")); +---- + +=== Configuration + +When using xref:configuration/index.adoc#external-configuration[external configuration], the properties can be set as follows. + +[source, text, title="eclipsestore.properties"] +---- +storage-directory=bucket-name/folder/subfolder +storage-filesystem.aws.s3.credentials.type=static +storage-filesystem.aws.s3.credentials.access-key-id=my-access-key-id +storage-filesystem.aws.s3.credentials.secret-access-key=my-secret-access-key +storage-filesystem.aws.s3.region=us-east-1 +---- + +== Directory Buckets + +If you want to use https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-overview.html[directory buckets] just create a S3Connector with a different factory method. +Additionally you have to specify the https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-networking.html#s3-express-endpoints[zonal endpoint]. + +[source, java] +---- +S3Client client = S3Client.builder() + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create(ACCESS_KEY, SECRET_ACCESS_KEY) + )) + .region(Region.EU_NORTH_1) + .endpointOverride(new URI("https://s3express-eun1-az1.eu-north-1.amazonaws.com")) + .build() +; +BlobStoreFileSystem fileSystem = BlobStoreFileSystem.New( + S3Connector.CachingDirectory(client) +); +EmbeddedStorage.start(fileSystem.ensureDirectoryPath("bucket-name", "folder", "subfolder")); ---- -== Configuration +=== Configuration -When using xref:configuration/index.adoc#external-configuration[external configuration] AWS S3 can be set as follows. +When using xref:configuration/index.adoc#external-configuration[external configuration], the properties can be set as follows. [source, text, title="eclipsestore.properties"] ---- +storage-directory=bucket-name/folder/subfolder +storage-filesystem.aws.s3.directory-bucket=true storage-filesystem.aws.s3.credentials.type=static storage-filesystem.aws.s3.credentials.access-key-id=my-access-key-id -storage-filesystem.aws.s3.credentials.secret-acces-key=my-secret-access-key -storage-filesystem.aws.s3.credentials.region=us-east-1 +storage-filesystem.aws.s3.credentials.secret-access-key=my-secret-access-key +storage-filesystem.aws.s3.region=eu-north-1 +storage-filesystem.aws.s3.endpoint-override=https://s3express-eun1-az1.eu-north-1.amazonaws.com ---- == Supported properties @@ -44,6 +92,13 @@ storage-filesystem.aws.s3.credentials.region=us-east-1 |endpoint-override |The endpoint with which the SDK should communicate. +|cache +|Defines if the S3Connector should use caching. + +|directory-bucket +|true if a directory bucket is used, false for general purpose buckets. +For details see the official AWS documentation https://aws.amazon.com/s3/storage-classes/[[1]] https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-overview.html[[2]] + |region |Configure the region with which the SDK should communicate. If this is not specified, the SDK will attempt to identify the endpoint automatically using the following logic: diff --git a/docs/modules/storage/pages/storage-targets/index.adoc b/docs/modules/storage/pages/storage-targets/index.adoc index a1491a6f..f0951246 100644 --- a/docs/modules/storage/pages/storage-targets/index.adoc +++ b/docs/modules/storage/pages/storage-targets/index.adoc @@ -21,7 +21,7 @@ NioFileSystem fileSystem = NioFileSystem.New(); EmbeddedStorage.start(fileSystem.ensureDirectoryPath("path", "to", "storage")); ---- -The file system API is the same for all connectors, like for S3. + +The file system API is the same for all connectors, like for xref:storage-targets/blob-stores/aws-s3.adoc[S3]. This is part of another module. [source, xml, subs=attributes+] @@ -43,5 +43,5 @@ BlobStoreFileSystem fileSystem = BlobStoreFileSystem.New( // use caching connector S3Connector.Caching(client) ); -EmbeddedStorage.start(fileSystem.ensureDirectoryPath("path", "to", "storage")); +EmbeddedStorage.start(fileSystem.ensureDirectoryPath("bucket-name", "folder", "subfolder")); ---- diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/AbstractAwsProperties.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/AbstractAwsProperties.java index cd978116..7991cfd0 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/AbstractAwsProperties.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/AbstractAwsProperties.java @@ -37,6 +37,11 @@ public abstract class AbstractAwsProperties * */ private String region; + + /** + * Defines if the S3Connector should use caching. + */ + private boolean cache = true; public Credentials getCredentials() @@ -68,4 +73,15 @@ public void setRegion(final String region) { this.region = region; } + + public boolean isCache() + { + return this.cache; + } + + public void setCache(final boolean cache) + { + this.cache = cache; + } + } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/S3.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/S3.java index 2ce17819..42caf60b 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/S3.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/aws/S3.java @@ -16,4 +16,23 @@ public class S3 extends AbstractAwsProperties { + /** + * true if a directory bucket (e.g. Express One Zone) is used, + * false for general purpose buckets (e.g. Standard) + * + * @see https://aws.amazon.com/s3/storage-classes/ + * @see https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-overview.html + */ + private boolean directoryBucket = false; + + public boolean isDirectoryBucket() + { + return this.directoryBucket; + } + + public void setDirectoryBucket(final boolean directoryBucket) + { + this.directoryBucket = directoryBucket; + } + } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java index 66ad6a26..266972fb 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java @@ -28,7 +28,10 @@ public enum ConfigKeys ORACLE("oracle"), POSTGRES("postgres"), SQLITE("sqlite"), - + + // commons + CACHE("cache"), + //aws AWS("aws"), DYNAMODB("dynamodb"), @@ -36,8 +39,9 @@ public enum ConfigKeys AWS_CREDENTIALS_TYPE("credentials.type"), AWS_CREDENTIALS_ACCESS_KEY_ID("credentials.access-key-id"), AWS_CREDENTIALS_SECRET_ACCESS_KEY("credentials.secret-access-key"), - AWS_ENDPOINT_OVERRIDE("endpointOverride"), + AWS_ENDPOINT_OVERRIDE("endpoint-override"), AWS_REGION("region"), + AWS_DIRECTORY_BUCKET("directory-bucket"), //azure AZURE("azure"), diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java index d9f0f0fa..9c527cad 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java @@ -22,12 +22,12 @@ import org.eclipse.store.integrations.spring.boot.types.configuration.StorageFilesystem; import org.eclipse.store.integrations.spring.boot.types.configuration.aws.AbstractAwsProperties; import org.eclipse.store.integrations.spring.boot.types.configuration.aws.Aws; +import org.eclipse.store.integrations.spring.boot.types.configuration.aws.S3; import org.eclipse.store.integrations.spring.boot.types.configuration.azure.Azure; import org.eclipse.store.integrations.spring.boot.types.configuration.oraclecloud.Oraclecloud; import org.eclipse.store.integrations.spring.boot.types.configuration.sql.AbstractSqlConfiguration; import org.eclipse.store.integrations.spring.boot.types.configuration.sql.Sql; import org.eclipse.store.storage.embedded.configuration.types.EmbeddedStorageConfigurationPropertyNames; -import org.springframework.stereotype.Component; /** * The {@code EclipseStoreConfigConverter} class is a Spring component that converts the Eclipse Store properties into a map. @@ -202,9 +202,12 @@ private Map prepareAws(final Aws aws, final String key) { values.putAll(this.prepareAwsProperties(aws.getDynamodb(), this.composeKey(key, ConfigKeys.DYNAMODB.value()))); } - if (aws.getS3() != null) + final S3 s3 = aws.getS3(); + if (s3 != null) { - values.putAll(this.prepareAwsProperties(aws.getS3(), this.composeKey(key, ConfigKeys.S3.value()))); + final String s3Key = this.composeKey(key, ConfigKeys.S3.value()); + values.putAll(this.prepareAwsProperties(s3, s3Key)); + values.put(this.composeKey(s3Key, ConfigKeys.AWS_DIRECTORY_BUCKET.value()), Boolean.toString(s3.isDirectoryBucket())); } return values; } @@ -213,6 +216,7 @@ private Map prepareAws(final Aws aws, final String key) private Map prepareAwsProperties(final AbstractAwsProperties awsProperties, final String key) { final Map values = new HashMap<>(); + values.put(this.composeKey(key, ConfigKeys.CACHE.value()), Boolean.toString(awsProperties.isCache())); values.put(this.composeKey(key, ConfigKeys.AWS_ENDPOINT_OVERRIDE.value()), awsProperties.getEndpointOverride()); values.put(this.composeKey(key, ConfigKeys.AWS_REGION.value()), awsProperties.getRegion()); values.put(this.composeKey(key, ConfigKeys.AWS_CREDENTIALS_TYPE.value()), awsProperties.getCredentials().getType()); diff --git a/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageFoundationCreatorConfigurationBased.java b/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageFoundationCreatorConfigurationBased.java index 99bf0fe9..2ce6d5d9 100644 --- a/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageFoundationCreatorConfigurationBased.java +++ b/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageFoundationCreatorConfigurationBased.java @@ -16,10 +16,16 @@ import static org.eclipse.serializer.util.X.notNull; -import java.nio.file.Paths; import java.time.Duration; import java.util.function.Supplier; +import org.eclipse.serializer.afs.types.ADirectory; +import org.eclipse.serializer.afs.types.AFileSystem; +import org.eclipse.serializer.chars.XChars; +import org.eclipse.serializer.configuration.exceptions.ConfigurationException; +import org.eclipse.serializer.configuration.types.ByteSize; +import org.eclipse.serializer.configuration.types.Configuration; +import org.eclipse.serializer.configuration.types.ConfigurationBasedCreator; import org.eclipse.store.afs.nio.types.NioFileSystem; import org.eclipse.store.storage.embedded.types.EmbeddedStorage; import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; @@ -31,13 +37,6 @@ import org.eclipse.store.storage.types.StorageFileNameProvider; import org.eclipse.store.storage.types.StorageHousekeepingController; import org.eclipse.store.storage.types.StorageLiveFileProvider; -import org.eclipse.serializer.afs.types.ADirectory; -import org.eclipse.serializer.afs.types.AFileSystem; -import org.eclipse.serializer.chars.XChars; -import org.eclipse.serializer.configuration.exceptions.ConfigurationException; -import org.eclipse.serializer.configuration.types.ByteSize; -import org.eclipse.serializer.configuration.types.Configuration; -import org.eclipse.serializer.configuration.types.ConfigurationBasedCreator; /** @@ -112,7 +111,7 @@ private EmbeddedStorageFoundation internalCreateEmbeddedStorageFoundation() this.configuration.opt(BACKUP_DIRECTORY) .filter(backupDirectory -> !XChars.isEmpty(backupDirectory)) - .map(this::createDirectoryPath) + .map(fileSystem::resolvePath) .ifPresent(backupDirectory -> { final AFileSystem backupFileSystem = this.createFileSystem( @@ -155,7 +154,7 @@ private AFileSystem createFileSystem( private StorageLiveFileProvider createFileProvider(final AFileSystem fileSystem) { final ADirectory baseDirectory = fileSystem.ensureDirectoryPath( - this.createDirectoryPath( + fileSystem.resolvePath( this.configuration.opt(STORAGE_DIRECTORY) .orElse(StorageLiveFileProvider.Defaults.defaultStorageDirectory()) ) @@ -271,16 +270,6 @@ private StorageEntityCacheEvaluator createEntityCacheEvaluator() ); } - private String createDirectoryPath( - final String path - ) - { - return path.startsWith("~/") || path.startsWith("~\\") - ? Paths.get(System.getProperty("user.home"), path.substring(2)).toString() - : path - ; - } - } } From 313bce423a357943920c23ebf3d25257059c010e Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Tue, 9 Jul 2024 14:05:36 +0200 Subject: [PATCH 118/126] Xio transfer rework (#238) * Retry Housekeeping data transfer if not all bytes had been written * temp change serializer version to branch snapshot * language fixes * Revert "temp change serializer version to branch snapshot" This reverts commit 8f89db8aaa02d097fdda17c2222882665cda9c28. --------- Co-authored-by: Zdenek Jonas --- .../store/storage/types/StorageFileManager.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFileManager.java b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFileManager.java index 346079d9..ddf1a029 100644 --- a/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFileManager.java +++ b/storage/storage/src/main/java/org/eclipse/store/storage/types/StorageFileManager.java @@ -444,8 +444,21 @@ private void appendBytesToHeadFile( final StorageLiveDataFile.Default headFile = this.headFile; + long headFileLength = headFile.totalLength(); + // do the actual file-level copying in one go at the end and validate the byte count to be sure - this.writer.writeTransfer(sourceFile, copyStart, copyLength, headFile); + long bytes = this.writer.writeTransfer(sourceFile, copyStart, copyLength, headFile); + if(copyLength != bytes) { + + logger.error("Data transfer error! Expected {} bytes transferred to head file but only {} bytes had been transferred! Trying again.", copyLength, bytes); + headFile.truncate(headFileLength); + + bytes = this.writer.writeTransfer(sourceFile, copyStart, copyLength, headFile); + if(copyLength != bytes) { + logger.error("Data transfer retry error! Expected {} bytes transferred to head file but only {} bytes had been transferred! Aborting!", copyLength, bytes); + throw new StorageExceptionIoWriting("Transfer to head file failed, only " + bytes + " of " + copyLength + " bytes transferred."); + } + } // increase content length by length of chain // (15.02.2019 TM)NOTE: changed from arithmetic inside #addChainToTail to directly using copyLength in here. From 3fa77a15627b6c34b0bf8e889624c695f28b1b4e Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Wed, 10 Jul 2024 07:44:57 +0200 Subject: [PATCH 119/126] release script - release direct from main branch --- .github/workflows/maven_release.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/maven_release.yml b/.github/workflows/maven_release.yml index 341c6e6b..f6e142ff 100644 --- a/.github/workflows/maven_release.yml +++ b/.github/workflows/maven_release.yml @@ -28,6 +28,10 @@ jobs: server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD gpg-passphrase: PASSPHRASE + - name: Maven change version + run: mvn versions:set -DnewVersion=${{ github.event.release.tag_name }} --batch-mode + - name: Maven change serializer version + run: mvn versions:set-property -Dproperty=eclipse.serializer.version -DnewVersion=${{ github.event.release.tag_name }} - name: Make a release run: mvn -Pdeploy -Pproduction --no-transfer-progress --batch-mode clean deploy env: @@ -47,6 +51,10 @@ jobs: server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD gpg-passphrase: PASSPHRASE + - name: Maven change version + run: mvn versions:set -DnewVersion=${{ github.event.release.tag_name }} --batch-mode + - name: Maven change serializer version + run: mvn versions:set-property -Dproperty=eclipse.serializer.version -DnewVersion=${{ github.event.release.tag_name }} - name: Build with java 17 run: | mvn -pl integrations/spring-boot3 clean install -am -B From cf550ee04b0ff68629990905c8afbe2eb54da7cb Mon Sep 17 00:00:00 2001 From: hg-ms <53219833+hg-ms@users.noreply.github.com> Date: Wed, 10 Jul 2024 09:30:07 +0200 Subject: [PATCH 120/126] Feature/type dictionary import export docu (#245) Typos and grammar --------- Co-authored-by: Florian Habermann --- docs/modules/serializer/pages/index.adoc | 48 ++++++++++++++++++------ 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/docs/modules/serializer/pages/index.adoc b/docs/modules/serializer/pages/index.adoc index ae144d6e..5e9a2acf 100644 --- a/docs/modules/serializer/pages/index.adoc +++ b/docs/modules/serializer/pages/index.adoc @@ -1,7 +1,7 @@ = Serializer -{product-name}'s serialization engine, which is used by the storage, can be used standalone as well. -It is usable as as replacement for the default Java serialization to convert objects to a binary format and vice versa. This API is part of the persistence-binary module: +{product-name}'s serialization engine, which is used by the storage, can also be used standalone. +It is usable as a replacement for the default Java serialization to convert objects to a binary format and vice versa. This API is part of the persistence-binary module: == Prerequisites @@ -18,7 +18,7 @@ It is usable as as replacement for the default Java serialization to convert obj == Usage -You can use any medium type, but for most purposes the byte array version should be sufficient, to transfer the serialized form over the transport layer of your choice. +You can use any medium type, but for most purposes, the byte array version should be sufficient to transfer the serialized form over the transport layer of your choice. Simply create a serializer instance, optionally based on a foundation, and call the serialize and deserialize methods. [source, java] @@ -36,11 +36,37 @@ The `SerializerFoundation` provides an API like the MicroStream storage to confi [IMPORTANT] The default Serializer implementation does not include type information in the serialized output! -If you want to deserialize that with another serializer instance you must register all classes using the `SerializerFoundation` before you create the serializer or use a `TypedSerializer`! +If you want to deserialize that with another serializer instance, you must register all classes using the `SerializerFoundation` before you create the serializer or use a `TypedSerializer`! + +== TypeDictionary +The serializer internally generates a dictionary that describes all serialized types. This dictionary can be exported and imported to exchange those type informations between different serializer instances. + +=== Exporting the type dictionary +The current type information can be obtained as Sting using the serializers exportTypeDictionay() method: +[source, java] +---- +final String typeDictionaryString = serializer.exportTypeDictionay(); +---- + +=== Importing the type dictionary +To import an initial type dictionary, it must be supplied as a String. The SerializerFoundation offers methods to import that type dictionary string before the serializer instance is generated: + +.Using the static New(String typeDictionaryString) Method: +[source, java] +---- +final SerializerFoundation foundation = SerializerFoundation.New(typeDictionaryString); +---- + +.Using the setInitialTypeDictionary(String typeDictionaryString) method: +[source, java] +---- +final SerializerFoundation foundation = SerializerFoundation.New(); +foundation.setInitialTypeDictionary(typeDictionaryString); +---- == TypedSerializer The `TypedSerializer` implementation includes type information into the serialized output. -By default the complete set of type information is included in all serialized output. +By default, the complete set of type information is included in all serialized output. [source, java] ---- @@ -50,7 +76,7 @@ Customer restored = serializer.deserialize(data); ---- === Configuring the included type information -To reduce the serialized data it is possible to configure the included type information by suppling a `SerializerTypeInfoStrategyCreator` to the `SerializerFoundation`. +To reduce the serialized data, it is possible to configure the included type information by supplying a `SerializerTypeInfoStrategyCreator` to the `SerializerFoundation`. [source, java] ---- final SerializerFoundation foundation = SerializerFoundation.New() @@ -67,14 +93,14 @@ return TypedSerializer.Bytes(foundation); |Description //------------- |TypeDictionary -|Includes type information for all types currently known to the serializer including those registered during the setup. +|Includes type information for all types currently known to the serializer, including those registered during the setup. |Diff -|Includes type information for all types currently known to the serializer including those registered during the setup. +|Includes type information for all types currently known to the serializer, including those registered during the setup. |IncrementalDiff -|Includes only type information for types added to the serializers type registry in the current serialization. Types that are registered during the serializers setup are never included. +|Includes only type information for types added to the serializers type registry in the current serialization. Types that are registered during the serializer's setup are never included. |=== ==== The `includeTypeInfoOnce` parameter: -All three serializer type handling strategies allow to specify that the type information gets included only once if it has not changed by setting the parameter `includeTypeInfoOnce = true`. -If so, the type information is only included if there where new types registered during the current serialization. +All three serializer type handling strategies allow specifying that the type information gets included only once if it has not changed by setting the parameter `includeTypeInfoOnce = true`. +If so, the type information is only included if new types are registered during the current serialization. From a796525e5fd528716b403b8d76cd245006e66e4f Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Wed, 10 Jul 2024 11:06:26 +0200 Subject: [PATCH 121/126] Documentation update (#244) * Add type column to property descriptions * Update java-features.adoc Fixes #186 * Update language of property source blocks * fix key --------- Co-authored-by: Zdenek Jonas --- .../modules/cache/pages/configuration/storage.adoc | 8 ++++---- .../use-cases/hibernate-second-level-cache.adoc | 2 +- docs/modules/storage/pages/faq/java-features.adoc | 2 +- .../storage-targets/blob-stores/aws-dynamodb.adoc | 13 ++++++++++--- .../pages/storage-targets/blob-stores/aws-s3.adoc | 14 +++++++++++--- .../storage-targets/blob-stores/azure-storage.adoc | 13 +++++++++++-- .../blob-stores/google-cloud-firestore.adoc | 12 +++++++++--- .../pages/storage-targets/blob-stores/kafka.adoc | 2 +- .../blob-stores/oracle-cloud-object-storage.adoc | 13 +++++++++++-- .../pages/storage-targets/blob-stores/redis.adoc | 6 ++++-- .../storage-targets/sql-databases/mariadb.adoc | 2 +- .../storage-targets/sql-databases/oracle.adoc | 2 +- .../storage-targets/sql-databases/postgresql.adoc | 2 +- .../storage-targets/sql-databases/sqlite.adoc | 2 +- 14 files changed, 67 insertions(+), 26 deletions(-) diff --git a/docs/modules/cache/pages/configuration/storage.adoc b/docs/modules/cache/pages/configuration/storage.adoc index d23be80e..431eddd8 100644 --- a/docs/modules/cache/pages/configuration/storage.adoc +++ b/docs/modules/cache/pages/configuration/storage.adoc @@ -17,7 +17,7 @@ Cache cache = cacheManager.createCache("jCache", configuration) If you prefer an external configuration, you can link the xref:storage:configuration/index.adoc#external-configuration[storage configuration]: -[source, text, title="cache-config.properties"] +[source, properties, title="cache-config.properties"] ---- key-type = java.lang.Integer value-type = java.lang.String @@ -28,7 +28,7 @@ write-through = true storage-configuration-resource-name = eclipsestore-storage.properties ---- -[source, text, title="eclipsestore-storage.properties"] +[source, properties, title="eclipsestore-storage.properties"] ---- storage-directory = ~/cache-data channel-count = 4 @@ -36,7 +36,7 @@ channel-count = 4 Or you can embed the storage configuration within the cache configuration using the `storage.` prefix: -[source, text, title="cache-config.properties"] +[source, properties, title="cache-config.properties"] ---- key-type = java.lang.Integer value-type = java.lang.String @@ -62,7 +62,7 @@ This means that even if the entry was already created more than 1 minute ago (ev == Spring example -[source, text, title="application.properties"] +[source, properties, title="application.properties"] ---- spring.jpa.properties.hibernate.cache.eclipsestore.missing_cache_strategy = create spring.jpa.properties.hibernate.cache.eclipsestore.readThrough = true diff --git a/docs/modules/cache/pages/use-cases/hibernate-second-level-cache.adoc b/docs/modules/cache/pages/use-cases/hibernate-second-level-cache.adoc index e8ec998a..b3e27dac 100644 --- a/docs/modules/cache/pages/use-cases/hibernate-second-level-cache.adoc +++ b/docs/modules/cache/pages/use-cases/hibernate-second-level-cache.adoc @@ -42,7 +42,7 @@ If you use a good old persistence.xml, set the property there: == Spring Example -[source, text, title="application.properties"] +[source, properties, title="application.properties"] ---- spring.jpa.properties.hibernate.cache.eclipsestore.missing_cache_strategy=create spring.jpa.properties.hibernate.cache.region.factory_class=org.eclipse.store.cache.hibernate.types.CacheRegionFactory diff --git a/docs/modules/storage/pages/faq/java-features.adoc b/docs/modules/storage/pages/faq/java-features.adoc index 5e2493d1..5b6d01cc 100644 --- a/docs/modules/storage/pages/faq/java-features.adoc +++ b/docs/modules/storage/pages/faq/java-features.adoc @@ -11,5 +11,5 @@ Yes, but due to reflection restrictions of records introduced in Java 15 an expo [source, text] ---- ---add-exports java.base/jdk.internal.misc=ALL-UNNAMED +--add-exports java.base/jdk.internal.misc=org.eclipse.serializer.base ---- diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/aws-dynamodb.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/aws-dynamodb.adoc index 5a9cc37e..2ae32ada 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/aws-dynamodb.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/aws-dynamodb.adoc @@ -27,26 +27,29 @@ EmbeddedStorage.start(fileSystem.ensureDirectoryPath("storage")); When using xref:configuration/index.adoc#external-configuration[external configuration] AWS DynamoDB can be set as follows. -[source, text, title="eclipsestore.properties"] +[source, properties, title="eclipsestore.properties"] ---- storage-filesystem.aws.dynamodb.credentials.type=static storage-filesystem.aws.dynamodb.credentials.access-key-id=my-access-key-id -storage-filesystem.aws.dynamodb.credentials.secret-acces-key=my-secret-access-key +storage-filesystem.aws.dynamodb.credentials.secret-access-key=my-secret-access-key storage-filesystem.aws.dynamodb.credentials.region=us-east-1 ---- == Supported properties -[options="header", cols="1,2a"] +[options="header", cols="1,2a,3"] |=== |Property |Description +|Type //------------- |endpoint-override |The endpoint with which the SDK should communicate. +|String |cache |Defines if the DynamoDbConnector should use caching. +|Boolean |region |Configure the region with which the SDK should communicate. @@ -56,6 +59,7 @@ If this is not specified, the SDK will attempt to identify the endpoint automati . Check the 'AWS_REGION' environment variable for the region. . Check the {user.home}/.aws/credentials and {user.home}/.aws/config files for the region. . If running in EC2, check the EC2 metadata service for the region. +|String |credentials.type |The type of the credentials provider. Supported values are: @@ -73,12 +77,15 @@ Credentials provider chain that looks for credentials in this order: . Credential profiles file at the default location (~/.aws/credentials) shared by all AWS SDKs and the AWS CLI . Credentials delivered through the Amazon EC2 container service if AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" environment variable is set and security manager has permission to access the variable, . Instance profile credentials delivered through the Amazon EC2 metadata service +|String |credentials.access-key-id |The access key id, used when "credentials.type" is "static". +|String |credentials.secret-access-key |The secret access key, used when "credentials.type" is "static". +|String |=== CAUTION: Depending on the amount of data and transactions, charges may apply depending on service usage. Please check with your service provider for details. diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/aws-s3.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/aws-s3.adoc index e4428226..1b802003 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/aws-s3.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/aws-s3.adoc @@ -38,7 +38,7 @@ EmbeddedStorage.start(fileSystem.ensureDirectoryPath("bucket-name", "folder", "s When using xref:configuration/index.adoc#external-configuration[external configuration], the properties can be set as follows. -[source, text, title="eclipsestore.properties"] +[source, properties, title="eclipsestore.properties"] ---- storage-directory=bucket-name/folder/subfolder storage-filesystem.aws.s3.credentials.type=static @@ -72,7 +72,7 @@ EmbeddedStorage.start(fileSystem.ensureDirectoryPath("bucket-name", "folder", "s When using xref:configuration/index.adoc#external-configuration[external configuration], the properties can be set as follows. -[source, text, title="eclipsestore.properties"] +[source, properties, title="eclipsestore.properties"] ---- storage-directory=bucket-name/folder/subfolder storage-filesystem.aws.s3.directory-bucket=true @@ -84,20 +84,24 @@ storage-filesystem.aws.s3.endpoint-override=https://s3express-eun1-az1.eu-north- ---- == Supported properties -[options="header", cols="1,2a"] +[options="header", cols="1,2a,3"] |=== |Property |Description +|Type //------------- |endpoint-override |The endpoint with which the SDK should communicate. +|String |cache |Defines if the S3Connector should use caching. +|Boolean |directory-bucket |true if a directory bucket is used, false for general purpose buckets. For details see the official AWS documentation https://aws.amazon.com/s3/storage-classes/[[1]] https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-overview.html[[2]] +|Boolean |region |Configure the region with which the SDK should communicate. @@ -107,6 +111,7 @@ If this is not specified, the SDK will attempt to identify the endpoint automati . Check the 'AWS_REGION' environment variable for the region. . Check the {user.home}/.aws/credentials and {user.home}/.aws/config files for the region. . If running in EC2, check the EC2 metadata service for the region. +|String |credentials.type |The type of the credentials provider. Supported values are: @@ -124,12 +129,15 @@ Credentials provider chain that looks for credentials in this order: . Credential profiles file at the default location (~/.aws/credentials) shared by all AWS SDKs and the AWS CLI . Credentials delivered through the Amazon EC2 container service if AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" environment variable is set and security manager has permission to access the variable, . Instance profile credentials delivered through the Amazon EC2 metadata service +|String |credentials.access-key-id |The access key id, used when "credentials.type" is "static". +|String |credentials.secret-access-key |The secret access key, used when "credentials.type" is "static". +|String |=== CAUTION: Depending on the amount of data and transactions, charges may apply depending on service usage. Please check with your service provider for details. diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/azure-storage.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/azure-storage.adoc index 0e7390aa..8ebc4122 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/azure-storage.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/azure-storage.adoc @@ -28,7 +28,7 @@ EmbeddedStorage.start(fileSystem.ensureDirectoryPath("storage")); When using xref:configuration/index.adoc#external-configuration[external configuration] Azure Storage can be set as follows. -[source, text, title="eclipsestore.properties"] +[source, properties, title="eclipsestore.properties"] ---- storage-filesystem.azure.storage.credentials.type=basic storage-filesystem.azure.storage.credentials.username=user @@ -37,19 +37,23 @@ storage-filesystem.azure.storage.credentials.password=secret == Supported properties -[options="header",cols="1,2a"] +[options="header",cols="1,2a,3"] |=== |Property |Description +|Type //------------- |endpoint |Sets the blob service endpoint, additionally parses it for information (SAS token). +|String |connection-string |Sets the connection string to connect to the service. +|String |encryption-scope |Sets the encryption scope that is used to encrypt blob contents on the server. +|String |credentials.type |The type of the credentials provider. Supported values are: @@ -58,18 +62,23 @@ storage-filesystem.azure.storage.credentials.password=secret Credentials will be loaded from the credentials.username and credentials.password properties. * "shared-key" + Credentials will be loaded from the credentials.account-name and credentials.account-key properties. +|String |credentials.username |The username, used when "credentials.type" is "basic". +|String |credentials.password |The password, used when "credentials.type" is "basic". +|String |credentials.account-name |The account name, used when "credentials.type" is "shared-key". +|String |credentials.account-key |The account key, used when "credentials.type" is "shared-key". +|String |=== CAUTION: Depending on the amount of data and transactions, charges may apply depending on service usage. Please check with your service provider for details. diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/google-cloud-firestore.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/google-cloud-firestore.adoc index c55cd225..3928bc6d 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/google-cloud-firestore.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/google-cloud-firestore.adoc @@ -27,7 +27,7 @@ EmbeddedStorage.start(fileSystem.ensureDirectoryPath("storage")); When using xref:configuration/index.adoc#external-configuration[external configuration] Google Cloud Firestore can be set as follows. -[source, text, title="eclipsestore.properties"] +[source, properties, title="eclipsestore.properties"] ---- storage-filesystem.googlecloud.firestore.credentials.type=default storage-filesystem.googlecloud.firestore.database-id=my-database-id @@ -35,25 +35,31 @@ storage-filesystem.googlecloud.firestore.project-id=my-project-id ---- == Supported properties -[options="header", cols="1,2a"] +[options="header", cols="1,2a,3"] |=== |Property |Description +|Type //------------- |database-id |The database ID to use with this Firestore client. +|String |emulator-host |The emulator host to use with this Firestore client. +|String |host |The service host. +|String |project-id |The project ID. If no project ID is set, the project ID from the environment will be used. +|String |quota-project-id |The project ID that specifies the project used for quota and billing purposes. +|String |credentials.type |The type of the credentials provider. Supported values are: @@ -71,7 +77,7 @@ Returns the Application Default Credentials which are used to identify and autho . Google App Engine built-in credentials . Google Cloud Shell built-in credentials . Google Compute Engine built-in credentials - +|String |=== CAUTION: Depending on the amount of data and transactions, charges may apply depending on service usage. Please check with your service provider for details. diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/kafka.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/kafka.adoc index fd3a9afd..794bc56c 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/kafka.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/kafka.adoc @@ -31,7 +31,7 @@ EmbeddedStorage.start(fileSystem.ensureDirectoryPath("storage")); When using xref:configuration/index.adoc#external-configuration[external configuration] Kafka can be set as follows. -[source, text, title="eclipsestore.properties"] +[source, properties, title="eclipsestore.properties"] ---- storage-filesystem.kafka-properties.bootstrap.servers=localhost:9093 ---- diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/oracle-cloud-object-storage.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/oracle-cloud-object-storage.adoc index 993c24bc..4cf2cd2e 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/oracle-cloud-object-storage.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/oracle-cloud-object-storage.adoc @@ -27,40 +27,49 @@ EmbeddedStorage.start(fileSystem.ensureDirectoryPath("storage")); When using xref:configuration/index.adoc#external-configuration[external configuration] Oracle Cloud Object Storage can be set as follows. -[source, text, title="eclipsestore.properties"] +[source, properties, title="eclipsestore.properties"] ---- storage-filesystem.oraclecloud.object-storage.config-file.profile=production storage-filesystem.oraclecloud.object-storage.region=us-phoenix-1 ---- -[options="header",cols="1,2a"] +[options="header",cols="1,2a,3"] |=== |Property |Description +|Type //------------- |config-file.path |The path of the config file, if not set the default is used: "~/.oci/config" +|String |config-file.profile |The configuration profile to use, if not set "DEFAULT" is used. +|String |config-file.charset |The encoding of the config file. +|String |client.connection-timeout-millis |The max time to wait for a connection, in millis. Default is 10000. +|Integer |client.read-timeout-millis |The max time to wait for data, in millis. Default is 60000. +|Integer |client.max-async-threads |The max number of async threads to use. Default is 50. +|Integer |region |Sets the region to call (ex, 'us-phoenix-1'). +|String |endpoint |Sets the endpoint to call (ex, https://www.example.com). +|String |=== CAUTION: Depending on the amount of data and transactions, charges may apply depending on service usage. Please check with your service provider for details. diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/redis.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/redis.adoc index 733500da..cac40009 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/redis.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/redis.adoc @@ -27,18 +27,20 @@ EmbeddedStorage.start(fileSystem.ensureDirectoryPath("storage")); When using xref:configuration/index.adoc#external-configuration[external configuration] Redis can be set as follows. -[source, text, title="eclipsestore.properties"] +[source, properties, title="eclipsestore.properties"] ---- storage-filesystem.redis.uri=redis://localhost:6379/0 ---- -[options="header",cols="1,2a"] +[options="header",cols="1,2a,3"] |=== |Property |Description +|Type //------------- |redis.uri |The RedisURI contains the host/port and can carry authentication/database details. On a successful connect you get authenticated, and the database is selected afterward. This applies also after re-establishing a connection after a connection loss. +|String |=== CAUTION: Depending on the amount of data and transactions, charges may apply depending on service usage. Please check with your service provider for details. diff --git a/docs/modules/storage/pages/storage-targets/sql-databases/mariadb.adoc b/docs/modules/storage/pages/storage-targets/sql-databases/mariadb.adoc index 04db93f6..4ca4c8ed 100644 --- a/docs/modules/storage/pages/storage-targets/sql-databases/mariadb.adoc +++ b/docs/modules/storage/pages/storage-targets/sql-databases/mariadb.adoc @@ -35,7 +35,7 @@ EmbeddedStorage.start(fileSystem.ensureDirectoryPath("storage")); When using xref:configuration/index.adoc#external-configuration[external configuration] MariaDB can be set as follows. Please note that you have to define a data source provider. -[source, text, title="eclipsestore.properties"] +[source, properties, title="eclipsestore.properties"] ---- storage-filesystem.sql.mariadb.data-source-provider=com.sample.MyDataSourceProvider storage-filesystem.sql.mariadb.catalog=mycatalog diff --git a/docs/modules/storage/pages/storage-targets/sql-databases/oracle.adoc b/docs/modules/storage/pages/storage-targets/sql-databases/oracle.adoc index 3c15e9ee..642a99b1 100644 --- a/docs/modules/storage/pages/storage-targets/sql-databases/oracle.adoc +++ b/docs/modules/storage/pages/storage-targets/sql-databases/oracle.adoc @@ -35,7 +35,7 @@ EmbeddedStorage.start(fileSystem.ensureDirectoryPath("storage")); When using xref:configuration/index.adoc#external-configuration[external configuration] Oracle can be set as follows. Please note that you have to define a data source provider. -[source, text, title="eclipsestore.properties"] +[source, properties, title="eclipsestore.properties"] ---- storage-filesystem.sql.oracle.data-source-provider=com.sample.MyDataSourceProvider storage-filesystem.sql.oracle.catalog=mycatalog diff --git a/docs/modules/storage/pages/storage-targets/sql-databases/postgresql.adoc b/docs/modules/storage/pages/storage-targets/sql-databases/postgresql.adoc index 51847a82..0d216894 100644 --- a/docs/modules/storage/pages/storage-targets/sql-databases/postgresql.adoc +++ b/docs/modules/storage/pages/storage-targets/sql-databases/postgresql.adoc @@ -35,7 +35,7 @@ EmbeddedStorage.start(fileSystem.ensureDirectoryPath("storage")); When using xref:configuration/index.adoc#external-configuration[external configuration] PostgreSQL can be set as follows. Please note that you have to define a data source provider. -[source, text, title="eclipsestore.properties"] +[source, properties, title="eclipsestore.properties"] ---- storage-filesystem.sql.postgres.data-source-provider=com.sample.MyDataSourceProvider storage-filesystem.sql.postgres.catalog=mycatalog diff --git a/docs/modules/storage/pages/storage-targets/sql-databases/sqlite.adoc b/docs/modules/storage/pages/storage-targets/sql-databases/sqlite.adoc index bad47787..233a08de 100644 --- a/docs/modules/storage/pages/storage-targets/sql-databases/sqlite.adoc +++ b/docs/modules/storage/pages/storage-targets/sql-databases/sqlite.adoc @@ -33,7 +33,7 @@ EmbeddedStorage.start(fileSystem.ensureDirectoryPath("storage")); When using xref:configuration/index.adoc#external-configuration[external configuration] SQLite can be set as follows. Please note that you have to define a data source provider. -[source, text, title="eclipsestore.properties"] +[source, properties, title="eclipsestore.properties"] ---- storage-filesystem.sql.sqlite.data-source-provider=com.sample.MyDataSourceProvider storage-filesystem.sql.sqlite.catalog=mycatalog From f77afb5a77a528f0fa0115e949111d0059747cef Mon Sep 17 00:00:00 2001 From: fh-ms Date: Wed, 10 Jul 2024 12:21:25 +0200 Subject: [PATCH 122/126] Update .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index d952bf7d..75b68e0c 100644 --- a/.gitignore +++ b/.gitignore @@ -88,3 +88,6 @@ profile jokes_storage/ storage/rest/client-app/src/main/dev-bundle/ + +node_modules/ + From ff50bb003d290de510e9bfd987fb86b261cc0d21 Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Wed, 10 Jul 2024 15:29:44 +0200 Subject: [PATCH 123/126] Add file system target property (#247) --- .../afs/aws/types/AwsFileSystemCreator.java | 4 +- .../types/DynamoDbFileSystemCreator.java | 16 +- .../afs/aws/s3/types/S3FileSystemCreator.java | 18 +- .../types/AzureStorageFileSystemCreator.java | 28 +-- ...GoogleCloudFirestoreFileSystemCreator.java | 28 +-- .../kafka/types/KafkaFileSystemCreator.java | 12 +- ...leCloudObjectStorageFileSystemCreator.java | 24 +-- .../redis/types/RedisFileSystemCreator.java | 19 +- .../afs/sql/types/SqlFileSystemCreator.java | 36 +--- .../sql/types/SqlFileSystemCreatorHana.java | 4 +- .../types/SqlFileSystemCreatorMariaDb.java | 6 +- .../sql/types/SqlFileSystemCreatorOracle.java | 6 +- .../types/SqlFileSystemCreatorPostgres.java | 6 +- .../sql/types/SqlFileSystemCreatorSqlite.java | 6 +- .../blob-stores/aws-dynamodb.adoc | 3 + .../storage-targets/blob-stores/aws-s3.adoc | 3 + .../blob-stores/azure-storage.adoc | 3 + .../blob-stores/google-cloud-firestore.adoc | 3 + .../storage-targets/blob-stores/kafka.adoc | 5 +- .../oracle-cloud-object-storage.adoc | 3 + .../storage-targets/blob-stores/redis.adoc | 3 + .../sql-databases/mariadb.adoc | 3 + .../storage-targets/sql-databases/oracle.adoc | 3 + .../sql-databases/postgresql.adoc | 3 + .../storage-targets/sql-databases/sqlite.adoc | 3 + .../configuration/EclipseStoreProperties.java | 10 +- .../configuration/StorageFilesystem.java | 203 ++++++++++-------- .../boot/types/converter/ConfigKeys.java | 1 + .../EclipseStoreConfigConverter.java | 7 + ...geFoundationCreatorConfigurationBased.java | 22 +- 30 files changed, 249 insertions(+), 242 deletions(-) diff --git a/afs/aws/aws/src/main/java/org/eclipse/store/afs/aws/types/AwsFileSystemCreator.java b/afs/aws/aws/src/main/java/org/eclipse/store/afs/aws/types/AwsFileSystemCreator.java index 0e8f3856..3165eb65 100644 --- a/afs/aws/aws/src/main/java/org/eclipse/store/afs/aws/types/AwsFileSystemCreator.java +++ b/afs/aws/aws/src/main/java/org/eclipse/store/afs/aws/types/AwsFileSystemCreator.java @@ -32,9 +32,9 @@ public abstract class AwsFileSystemCreator extends ConfigurationBasedCreator.Abstract { - protected AwsFileSystemCreator() + protected AwsFileSystemCreator(final String key) { - super(AFileSystem.class); + super(AFileSystem.class, key); } protected void populateBuilder( diff --git a/afs/aws/dynamodb/src/main/java/org/eclipse/store/afs/aws/dynamodb/types/DynamoDbFileSystemCreator.java b/afs/aws/dynamodb/src/main/java/org/eclipse/store/afs/aws/dynamodb/types/DynamoDbFileSystemCreator.java index 607bf2b3..f45ced83 100644 --- a/afs/aws/dynamodb/src/main/java/org/eclipse/store/afs/aws/dynamodb/types/DynamoDbFileSystemCreator.java +++ b/afs/aws/dynamodb/src/main/java/org/eclipse/store/afs/aws/dynamodb/types/DynamoDbFileSystemCreator.java @@ -26,25 +26,17 @@ public class DynamoDbFileSystemCreator extends AwsFileSystemCreator { public DynamoDbFileSystemCreator() { - super(); + super("aws.dynamodb"); } @Override - public AFileSystem create( - final Configuration configuration - ) + public AFileSystem create(final Configuration configuration) { - final Configuration dynamoConfiguration = configuration.child("aws.dynamodb"); - if(dynamoConfiguration == null) - { - return null; - } - final DynamoDbClientBuilder clientBuilder = DynamoDbClient.builder(); - this.populateBuilder(clientBuilder, dynamoConfiguration); + this.populateBuilder(clientBuilder, configuration); final DynamoDbClient client = clientBuilder.build(); - final boolean cache = dynamoConfiguration.optBoolean("cache").orElse(true); + final boolean cache = configuration.optBoolean("cache").orElse(true); final DynamoDbConnector connector = cache ? DynamoDbConnector.Caching(client) : DynamoDbConnector.New(client) diff --git a/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3FileSystemCreator.java b/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3FileSystemCreator.java index 5c5a07ca..4032c1af 100644 --- a/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3FileSystemCreator.java +++ b/afs/aws/s3/src/main/java/org/eclipse/store/afs/aws/s3/types/S3FileSystemCreator.java @@ -27,26 +27,18 @@ public class S3FileSystemCreator extends AwsFileSystemCreator { public S3FileSystemCreator() { - super(); + super("aws.s3"); } @Override - public AFileSystem create( - final Configuration configuration - ) + public AFileSystem create(final Configuration configuration) { - final Configuration s3Configuration = configuration.child("aws.s3"); - if(s3Configuration == null) - { - return null; - } - final S3ClientBuilder clientBuilder = S3Client.builder(); - this.populateBuilder(clientBuilder, s3Configuration); + this.populateBuilder(clientBuilder, configuration); final S3Client client = clientBuilder.build(); - final boolean cache = s3Configuration.optBoolean("cache").orElse(true); - final boolean directory = s3Configuration.optBoolean("directory-bucket").orElse(false); + final boolean cache = configuration.optBoolean("cache").orElse(true); + final boolean directory = configuration.optBoolean("directory-bucket").orElse(false); final S3Connector connector = directory ? (cache diff --git a/afs/azure/storage/src/main/java/org/eclipse/store/afs/azure/storage/types/AzureStorageFileSystemCreator.java b/afs/azure/storage/src/main/java/org/eclipse/store/afs/azure/storage/types/AzureStorageFileSystemCreator.java index f86db942..ec33aac7 100644 --- a/afs/azure/storage/src/main/java/org/eclipse/store/afs/azure/storage/types/AzureStorageFileSystemCreator.java +++ b/afs/azure/storage/src/main/java/org/eclipse/store/afs/azure/storage/types/AzureStorageFileSystemCreator.java @@ -29,7 +29,7 @@ public class AzureStorageFileSystemCreator extends ConfigurationBasedCreator.Abs { public AzureStorageFileSystemCreator() { - super(AFileSystem.class); + super(AFileSystem.class, "azure.storage"); } @Override @@ -37,27 +37,21 @@ public AFileSystem create( final Configuration configuration ) { - final Configuration azureConfiguration = configuration.child("azure.storage"); - if(azureConfiguration == null) - { - return null; - } - final BlobServiceClientBuilder clientBuilder = new BlobServiceClientBuilder(); - azureConfiguration.opt("endpoint").ifPresent( + configuration.opt("endpoint").ifPresent( value -> clientBuilder.endpoint(value) ); - azureConfiguration.opt("connection-string").ifPresent( + configuration.opt("connection-string").ifPresent( value -> clientBuilder.connectionString(value) ); - azureConfiguration.opt("encryption-scope").ifPresent( + configuration.opt("encryption-scope").ifPresent( value -> clientBuilder.encryptionScope(value) ); - azureConfiguration.opt("credentials.type").ifPresent(credentialsType -> + configuration.opt("credentials.type").ifPresent(credentialsType -> { switch(credentialsType) { @@ -65,8 +59,8 @@ public AFileSystem create( { clientBuilder.credential( new BasicAuthenticationCredential( - azureConfiguration.get("credentials.username"), - azureConfiguration.get("credentials.password") + configuration.get("credentials.username"), + configuration.get("credentials.password") ) ); } @@ -76,8 +70,8 @@ public AFileSystem create( { clientBuilder.credential( new StorageSharedKeyCredential( - azureConfiguration.get("credentials.account-name"), - azureConfiguration.get("credentials.account-key") + configuration.get("credentials.account-name"), + configuration.get("credentials.account-key") ) ); } @@ -88,7 +82,7 @@ public AFileSystem create( } }); - final Configuration furtherConfiguration = azureConfiguration.child("configuration"); + final Configuration furtherConfiguration = configuration.child("configuration"); if(furtherConfiguration != null) { final com.azure.core.util.Configuration config = new com.azure.core.util.Configuration(); @@ -101,7 +95,7 @@ public AFileSystem create( } final BlobServiceClient client = clientBuilder.buildClient(); - final boolean cache = azureConfiguration.optBoolean("cache").orElse(true); + final boolean cache = configuration.optBoolean("cache").orElse(true); final AzureStorageConnector connector = cache ? AzureStorageConnector.Caching(client) : AzureStorageConnector.New(client) diff --git a/afs/googlecloud/firestore/src/main/java/org/eclipse/store/afs/googlecloud/firestore/types/GoogleCloudFirestoreFileSystemCreator.java b/afs/googlecloud/firestore/src/main/java/org/eclipse/store/afs/googlecloud/firestore/types/GoogleCloudFirestoreFileSystemCreator.java index 11f039e0..d8804e69 100644 --- a/afs/googlecloud/firestore/src/main/java/org/eclipse/store/afs/googlecloud/firestore/types/GoogleCloudFirestoreFileSystemCreator.java +++ b/afs/googlecloud/firestore/src/main/java/org/eclipse/store/afs/googlecloud/firestore/types/GoogleCloudFirestoreFileSystemCreator.java @@ -38,53 +38,45 @@ public class GoogleCloudFirestoreFileSystemCreator extends ConfigurationBasedCre public GoogleCloudFirestoreFileSystemCreator() { - super(AFileSystem.class); + super(AFileSystem.class, "googlecloud.firestore"); } @Override - public AFileSystem create( - final Configuration configuration - ) + public AFileSystem create(final Configuration configuration) { - final Configuration firestoreConfiguration = configuration.child("googlecloud.firestore"); - if(firestoreConfiguration == null) - { - return null; - } - final FirestoreOptions.Builder optionsBuilder = FirestoreOptions.getDefaultInstance().toBuilder(); - firestoreConfiguration.opt("client-lib-token").ifPresent( + configuration.opt("client-lib-token").ifPresent( value -> optionsBuilder.setClientLibToken(value) ); - firestoreConfiguration.opt("database-id").ifPresent( + configuration.opt("database-id").ifPresent( value -> optionsBuilder.setDatabaseId(value) ); - firestoreConfiguration.opt("emulator-host").ifPresent( + configuration.opt("emulator-host").ifPresent( value -> optionsBuilder.setEmulatorHost(value) ); - firestoreConfiguration.opt("host").ifPresent( + configuration.opt("host").ifPresent( value -> optionsBuilder.setHost(value) ); - firestoreConfiguration.opt("project-id").ifPresent( + configuration.opt("project-id").ifPresent( value -> optionsBuilder.setProjectId(value) ); - firestoreConfiguration.opt("quota-project-id").ifPresent( + configuration.opt("quota-project-id").ifPresent( value -> optionsBuilder.setQuotaProjectId(value) ); this.createCredentials( - firestoreConfiguration, + configuration, optionsBuilder ); final Firestore firestore = optionsBuilder.build().getService(); - final boolean cache = firestoreConfiguration.optBoolean("cache").orElse(true); + final boolean cache = configuration.optBoolean("cache").orElse(true); final GoogleCloudFirestoreConnector connector = cache ? GoogleCloudFirestoreConnector.Caching(firestore) : GoogleCloudFirestoreConnector.New(firestore) diff --git a/afs/kafka/src/main/java/org/eclipse/store/afs/kafka/types/KafkaFileSystemCreator.java b/afs/kafka/src/main/java/org/eclipse/store/afs/kafka/types/KafkaFileSystemCreator.java index 59cf795e..08482786 100644 --- a/afs/kafka/src/main/java/org/eclipse/store/afs/kafka/types/KafkaFileSystemCreator.java +++ b/afs/kafka/src/main/java/org/eclipse/store/afs/kafka/types/KafkaFileSystemCreator.java @@ -26,7 +26,7 @@ public class KafkaFileSystemCreator extends ConfigurationBasedCreator.Abstract client.setRegion(value) ); - objectStorageConfiguration.opt("endpoint").ifPresent( + configuration.opt("endpoint").ifPresent( value -> client.setEndpoint(value) ); - final boolean cache = objectStorageConfiguration.optBoolean("cache").orElse(true); + final boolean cache = configuration.optBoolean("cache").orElse(true); final OracleCloudObjectStorageConnector connector = cache ? OracleCloudObjectStorageConnector.Caching(client) : OracleCloudObjectStorageConnector.New(client) @@ -116,7 +108,7 @@ public AFileSystem create( } catch(final IOException e) { - throw new ConfigurationException(objectStorageConfiguration, e); + throw new ConfigurationException(configuration, e); } } diff --git a/afs/redis/src/main/java/org/eclipse/store/afs/redis/types/RedisFileSystemCreator.java b/afs/redis/src/main/java/org/eclipse/store/afs/redis/types/RedisFileSystemCreator.java index 1b861f2b..a741eca5 100644 --- a/afs/redis/src/main/java/org/eclipse/store/afs/redis/types/RedisFileSystemCreator.java +++ b/afs/redis/src/main/java/org/eclipse/store/afs/redis/types/RedisFileSystemCreator.java @@ -16,6 +16,7 @@ import org.eclipse.serializer.afs.types.AFileSystem; import org.eclipse.serializer.chars.XChars; +import org.eclipse.serializer.configuration.exceptions.ConfigurationException; import org.eclipse.serializer.configuration.types.Configuration; import org.eclipse.serializer.configuration.types.ConfigurationBasedCreator; import org.eclipse.store.afs.blobstore.types.BlobStoreFileSystem; @@ -25,27 +26,19 @@ public class RedisFileSystemCreator extends ConfigurationBasedCreator.Abstract { - private final String name; - - protected SqlFileSystemCreator( - final String name - ) + protected SqlFileSystemCreator(final String name) { - super(AFileSystem.class); - this.name = notEmpty(name); + super(AFileSystem.class, "sql." + notEmpty(name)); } @Override - public AFileSystem create( - final Configuration configuration - ) + public AFileSystem create(final Configuration configuration) { - final String configurationKey = "sql." + this.name; - final Configuration sqlConfiguration = configuration.child(configurationKey); - if(sqlConfiguration == null) - { - return null; - } - - final String dataSourceProviderClassName = sqlConfiguration.get("data-source-provider"); + final String dataSourceProviderClassName = configuration.get("data-source-provider"); if(dataSourceProviderClassName == null) { throw new ConfigurationException( - sqlConfiguration, - configurationKey + ".data-source-provider must be set" + configuration, + this.key() + ".data-source-provider must be set" ); } try @@ -63,10 +49,10 @@ public AFileSystem create( Class.forName(dataSourceProviderClassName).getDeclaredConstructor().newInstance() ; final SqlProvider sqlProvider = this.createSqlProvider( - sqlConfiguration, - dataSourceProvider.provideDataSource(sqlConfiguration.detach()) + configuration, + dataSourceProvider.provideDataSource(configuration.detach()) ); - final boolean cache = sqlConfiguration.optBoolean("cache").orElse(true); + final boolean cache = configuration.optBoolean("cache").orElse(true); return SqlFileSystem.New(cache ? SqlConnector.Caching(sqlProvider) : SqlConnector.New(sqlProvider) @@ -78,12 +64,12 @@ public AFileSystem create( SecurityException e ) { - throw new ConfigurationException(sqlConfiguration, e); + throw new ConfigurationException(configuration, e); } } protected abstract SqlProvider createSqlProvider( - Configuration sqlConfiguration, + Configuration configuration, DataSource dataSource ); diff --git a/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorHana.java b/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorHana.java index 7a6e9ece..1d2c8cc1 100644 --- a/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorHana.java +++ b/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorHana.java @@ -28,11 +28,11 @@ public SqlFileSystemCreatorHana() @Override protected SqlProvider createSqlProvider( - final Configuration sqlConfiguration, + final Configuration configuration, final DataSource dataSource ) { - final SqlProviderHana.StoreType storeType = sqlConfiguration.opt("store-type") + final SqlProviderHana.StoreType storeType = configuration.opt("store-type") .map(name -> SqlProviderHana.StoreType.valueOf(name.toUpperCase())) .orElse(SqlProviderHana.StoreType.ROW) ; diff --git a/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorMariaDb.java b/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorMariaDb.java index 80eb4383..b9703dd9 100644 --- a/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorMariaDb.java +++ b/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorMariaDb.java @@ -28,13 +28,13 @@ public SqlFileSystemCreatorMariaDb() @Override protected SqlProvider createSqlProvider( - final Configuration sqlConfiguration, + final Configuration configuration, final DataSource dataSource ) { return SqlProviderMariaDb.New( - sqlConfiguration.get("catalog"), - sqlConfiguration.get("schema") , + configuration.get("catalog"), + configuration.get("schema") , dataSource ); } diff --git a/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorOracle.java b/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorOracle.java index 4963026b..ce6dab65 100644 --- a/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorOracle.java +++ b/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorOracle.java @@ -28,13 +28,13 @@ public SqlFileSystemCreatorOracle() @Override protected SqlProvider createSqlProvider( - final Configuration sqlConfiguration, + final Configuration configuration, final DataSource dataSource ) { return SqlProviderOracle.New( - sqlConfiguration.get("catalog"), - sqlConfiguration.get("schema") , + configuration.get("catalog"), + configuration.get("schema") , dataSource ); } diff --git a/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorPostgres.java b/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorPostgres.java index 15e35bcb..c4723070 100644 --- a/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorPostgres.java +++ b/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorPostgres.java @@ -28,13 +28,13 @@ public SqlFileSystemCreatorPostgres() @Override protected SqlProvider createSqlProvider( - final Configuration sqlConfiguration, + final Configuration configuration, final DataSource dataSource ) { return SqlProviderPostgres.New( - sqlConfiguration.get("catalog"), - sqlConfiguration.get("schema") , + configuration.get("catalog"), + configuration.get("schema") , dataSource ); } diff --git a/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorSqlite.java b/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorSqlite.java index 81e68c6a..d5443022 100644 --- a/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorSqlite.java +++ b/afs/sql/src/main/java/org/eclipse/store/afs/sql/types/SqlFileSystemCreatorSqlite.java @@ -28,13 +28,13 @@ public SqlFileSystemCreatorSqlite() @Override protected SqlProvider createSqlProvider( - final Configuration sqlConfiguration, + final Configuration configuration, final DataSource dataSource ) { return SqlProviderSqlite.New( - sqlConfiguration.get("catalog"), - sqlConfiguration.get("schema") , + configuration.get("catalog"), + configuration.get("schema") , dataSource ); } diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/aws-dynamodb.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/aws-dynamodb.adoc index 2ae32ada..f77eba68 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/aws-dynamodb.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/aws-dynamodb.adoc @@ -29,6 +29,9 @@ When using xref:configuration/index.adoc#external-configuration[external configu [source, properties, title="eclipsestore.properties"] ---- +# optional, enforces checks +storage-filesystem.target=aws.dynamodb + storage-filesystem.aws.dynamodb.credentials.type=static storage-filesystem.aws.dynamodb.credentials.access-key-id=my-access-key-id storage-filesystem.aws.dynamodb.credentials.secret-access-key=my-secret-access-key diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/aws-s3.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/aws-s3.adoc index 1b802003..2fb13d36 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/aws-s3.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/aws-s3.adoc @@ -40,6 +40,9 @@ When using xref:configuration/index.adoc#external-configuration[external configu [source, properties, title="eclipsestore.properties"] ---- +# optional, enforces checks +storage-filesystem.target=aws.s3 + storage-directory=bucket-name/folder/subfolder storage-filesystem.aws.s3.credentials.type=static storage-filesystem.aws.s3.credentials.access-key-id=my-access-key-id diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/azure-storage.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/azure-storage.adoc index 8ebc4122..8def4a63 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/azure-storage.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/azure-storage.adoc @@ -30,6 +30,9 @@ When using xref:configuration/index.adoc#external-configuration[external configu [source, properties, title="eclipsestore.properties"] ---- +# optional, enforces checks +storage-filesystem.target=azure.storage + storage-filesystem.azure.storage.credentials.type=basic storage-filesystem.azure.storage.credentials.username=user storage-filesystem.azure.storage.credentials.password=secret diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/google-cloud-firestore.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/google-cloud-firestore.adoc index 3928bc6d..ddf622e8 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/google-cloud-firestore.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/google-cloud-firestore.adoc @@ -29,6 +29,9 @@ When using xref:configuration/index.adoc#external-configuration[external configu [source, properties, title="eclipsestore.properties"] ---- +# optional, enforces checks +storage-filesystem.target=googlecloud.firestore + storage-filesystem.googlecloud.firestore.credentials.type=default storage-filesystem.googlecloud.firestore.database-id=my-database-id storage-filesystem.googlecloud.firestore.project-id=my-project-id diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/kafka.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/kafka.adoc index 794bc56c..916772f7 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/kafka.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/kafka.adoc @@ -33,7 +33,10 @@ When using xref:configuration/index.adoc#external-configuration[external configu [source, properties, title="eclipsestore.properties"] ---- -storage-filesystem.kafka-properties.bootstrap.servers=localhost:9093 +# optional, enforces checks +storage-filesystem.target=kafka + +storage-filesystem.kafka.bootstrap.servers=localhost:9093 ---- == Supported properties diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/oracle-cloud-object-storage.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/oracle-cloud-object-storage.adoc index 4cf2cd2e..58578101 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/oracle-cloud-object-storage.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/oracle-cloud-object-storage.adoc @@ -29,6 +29,9 @@ When using xref:configuration/index.adoc#external-configuration[external configu [source, properties, title="eclipsestore.properties"] ---- +# optional, enforces checks +storage-filesystem.target=oraclecloud.object-storage + storage-filesystem.oraclecloud.object-storage.config-file.profile=production storage-filesystem.oraclecloud.object-storage.region=us-phoenix-1 ---- diff --git a/docs/modules/storage/pages/storage-targets/blob-stores/redis.adoc b/docs/modules/storage/pages/storage-targets/blob-stores/redis.adoc index cac40009..2c6a5c8c 100644 --- a/docs/modules/storage/pages/storage-targets/blob-stores/redis.adoc +++ b/docs/modules/storage/pages/storage-targets/blob-stores/redis.adoc @@ -29,6 +29,9 @@ When using xref:configuration/index.adoc#external-configuration[external configu [source, properties, title="eclipsestore.properties"] ---- +# optional, enforces checks +storage-filesystem.target=redis + storage-filesystem.redis.uri=redis://localhost:6379/0 ---- diff --git a/docs/modules/storage/pages/storage-targets/sql-databases/mariadb.adoc b/docs/modules/storage/pages/storage-targets/sql-databases/mariadb.adoc index 4ca4c8ed..809521e6 100644 --- a/docs/modules/storage/pages/storage-targets/sql-databases/mariadb.adoc +++ b/docs/modules/storage/pages/storage-targets/sql-databases/mariadb.adoc @@ -37,6 +37,9 @@ Please note that you have to define a data source provider. [source, properties, title="eclipsestore.properties"] ---- +# optional, enforces checks +storage-filesystem.target=sql.mariadb + storage-filesystem.sql.mariadb.data-source-provider=com.sample.MyDataSourceProvider storage-filesystem.sql.mariadb.catalog=mycatalog storage-filesystem.sql.mariadb.schema=myschema diff --git a/docs/modules/storage/pages/storage-targets/sql-databases/oracle.adoc b/docs/modules/storage/pages/storage-targets/sql-databases/oracle.adoc index 642a99b1..b51cb701 100644 --- a/docs/modules/storage/pages/storage-targets/sql-databases/oracle.adoc +++ b/docs/modules/storage/pages/storage-targets/sql-databases/oracle.adoc @@ -37,6 +37,9 @@ Please note that you have to define a data source provider. [source, properties, title="eclipsestore.properties"] ---- +# optional, enforces checks +storage-filesystem.target=sql.oracle + storage-filesystem.sql.oracle.data-source-provider=com.sample.MyDataSourceProvider storage-filesystem.sql.oracle.catalog=mycatalog storage-filesystem.sql.oracle.schema=myschema diff --git a/docs/modules/storage/pages/storage-targets/sql-databases/postgresql.adoc b/docs/modules/storage/pages/storage-targets/sql-databases/postgresql.adoc index 0d216894..1907b037 100644 --- a/docs/modules/storage/pages/storage-targets/sql-databases/postgresql.adoc +++ b/docs/modules/storage/pages/storage-targets/sql-databases/postgresql.adoc @@ -37,6 +37,9 @@ Please note that you have to define a data source provider. [source, properties, title="eclipsestore.properties"] ---- +# optional, enforces checks +storage-filesystem.target=sql.postgres + storage-filesystem.sql.postgres.data-source-provider=com.sample.MyDataSourceProvider storage-filesystem.sql.postgres.catalog=mycatalog storage-filesystem.sql.postgres.schema=myschema diff --git a/docs/modules/storage/pages/storage-targets/sql-databases/sqlite.adoc b/docs/modules/storage/pages/storage-targets/sql-databases/sqlite.adoc index 233a08de..3ddc4d15 100644 --- a/docs/modules/storage/pages/storage-targets/sql-databases/sqlite.adoc +++ b/docs/modules/storage/pages/storage-targets/sql-databases/sqlite.adoc @@ -35,6 +35,9 @@ Please note that you have to define a data source provider. [source, properties, title="eclipsestore.properties"] ---- +# optional, enforces checks +storage-filesystem.target=sql.sqlite + storage-filesystem.sql.sqlite.data-source-provider=com.sample.MyDataSourceProvider storage-filesystem.sql.sqlite.catalog=mycatalog storage-filesystem.sql.sqlite.schema=myschema diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java index 1eacf9b2..9e68a4db 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/EclipseStoreProperties.java @@ -42,7 +42,7 @@ public class EclipseStoreProperties */ @NestedConfigurationProperty private StorageFilesystem storageFilesystem; - + /** * If configured, the storage will not delete files. Instead of deleting a file it will be moved to this directory. */ @@ -538,20 +538,20 @@ public void setRegisterJdk8Handlers(final boolean registerJdk8Handlers) public boolean isAutoCreateDefaultFoundation() { - return autoCreateDefaultFoundation; + return this.autoCreateDefaultFoundation; } - public void setAutoCreateDefaultFoundation(boolean autoCreateDefaultFoundation) + public void setAutoCreateDefaultFoundation(final boolean autoCreateDefaultFoundation) { this.autoCreateDefaultFoundation = autoCreateDefaultFoundation; } public boolean isAutoCreateDefaultStorage() { - return autoCreateDefaultStorage; + return this.autoCreateDefaultStorage; } - public void setAutoCreateDefaultStorage(boolean autoCreateDefaultStorage) + public void setAutoCreateDefaultStorage(final boolean autoCreateDefaultStorage) { this.autoCreateDefaultStorage = autoCreateDefaultStorage; } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/StorageFilesystem.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/StorageFilesystem.java index 84fe67c4..656b6cc2 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/StorageFilesystem.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/configuration/StorageFilesystem.java @@ -25,100 +25,115 @@ import org.eclipse.store.integrations.spring.boot.types.configuration.sql.Sql; import org.springframework.boot.context.properties.NestedConfigurationProperty; + public class StorageFilesystem { - - @NestedConfigurationProperty - private Sql sql; - - @NestedConfigurationProperty - private Aws aws; - - @NestedConfigurationProperty - private Azure azure; - - /** - * Supported properties - * All supported properties of Kafka, see ... - */ - private Map kafkaProperties; - - @NestedConfigurationProperty - private Oraclecloud oraclecloud; - - @NestedConfigurationProperty - private Googlecloud googlecloud; - - @NestedConfigurationProperty - private Redis redis; - - public Sql getSql() - { - return this.sql; - } - - public void setSql(final Sql sql) - { - this.sql = sql; - } - - public Aws getAws() - { - return this.aws; - } - - public void setAws(final Aws aws) - { - this.aws = aws; - } - - public Map getKafkaProperties() - { - return this.kafkaProperties; - } - - public void setKafkaProperties(final Map kafkaProperties) - { - this.kafkaProperties = kafkaProperties; - } - - public Oraclecloud getOraclecloud() - { - return this.oraclecloud; - } - - public void setOraclecloud(final Oraclecloud oraclecloud) - { - this.oraclecloud = oraclecloud; - } - - public Redis getRedis() - { - return this.redis; - } - - public void setRedis(final Redis redis) - { - this.redis = redis; - } - - public Azure getAzure() - { - return this.azure; - } - - public void setAzure(final Azure azure) - { - this.azure = azure; - } - - public Googlecloud getGooglecloud() - { - return this.googlecloud; - } - - public void setGooglecloud(final Googlecloud googlecloud) - { - this.googlecloud = googlecloud; - } + /** + * The target type of the file system + */ + private String target; + + @NestedConfigurationProperty + private Sql sql; + + @NestedConfigurationProperty + private Aws aws; + + @NestedConfigurationProperty + private Azure azure; + + /** + * Supported properties + * All supported properties of Kafka, see ... + */ + private Map kafkaProperties; + + @NestedConfigurationProperty + private Oraclecloud oraclecloud; + + @NestedConfigurationProperty + private Googlecloud googlecloud; + + @NestedConfigurationProperty + private Redis redis; + + public String getTarget() + { + return this.target; + } + + public void setTarget(final String target) + { + this.target = target; + } + + public Sql getSql() + { + return this.sql; + } + + public void setSql(final Sql sql) + { + this.sql = sql; + } + + public Aws getAws() + { + return this.aws; + } + + public void setAws(final Aws aws) + { + this.aws = aws; + } + + public Map getKafkaProperties() + { + return this.kafkaProperties; + } + + public void setKafkaProperties(final Map kafkaProperties) + { + this.kafkaProperties = kafkaProperties; + } + + public Oraclecloud getOraclecloud() + { + return this.oraclecloud; + } + + public void setOraclecloud(final Oraclecloud oraclecloud) + { + this.oraclecloud = oraclecloud; + } + + public Redis getRedis() + { + return this.redis; + } + + public void setRedis(final Redis redis) + { + this.redis = redis; + } + + public Azure getAzure() + { + return this.azure; + } + + public void setAzure(final Azure azure) + { + this.azure = azure; + } + + public Googlecloud getGooglecloud() + { + return this.googlecloud; + } + + public void setGooglecloud(final Googlecloud googlecloud) + { + this.googlecloud = googlecloud; + } } diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java index 266972fb..e727e127 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/ConfigKeys.java @@ -31,6 +31,7 @@ public enum ConfigKeys // commons CACHE("cache"), + TARGET("target"), //aws AWS("aws"), diff --git a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java index 9c527cad..0b5a2a18 100644 --- a/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java +++ b/integrations/spring-boot3/src/main/java/org/eclipse/store/integrations/spring/boot/types/converter/EclipseStoreConfigConverter.java @@ -142,6 +142,13 @@ public Map convertConfigurationToMap(final EclipseStorePropertie private Map prepareFileSystem(final StorageFilesystem properties, final String key) { final Map values = new HashMap<>(); + + final String target = properties.getTarget(); + if(target != null) + { + values.put(this.composeKey(key, ConfigKeys.TARGET.value()), target); + } + if (properties.getSql() != null) { values.putAll(this.prepareSql(properties.getSql(), this.composeKey(key, ConfigKeys.SQL.value()))); diff --git a/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageFoundationCreatorConfigurationBased.java b/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageFoundationCreatorConfigurationBased.java index 2ce6d5d9..c9986207 100644 --- a/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageFoundationCreatorConfigurationBased.java +++ b/storage/embedded-configuration/src/main/java/org/eclipse/store/storage/embedded/configuration/types/EmbeddedStorageFoundationCreatorConfigurationBased.java @@ -137,15 +137,31 @@ private AFileSystem createFileSystem( final Configuration configuration = this.configuration.child(configurationKey); if(configuration != null) { + final String fileSystemTypeKey = this.configuration.opt(configurationKey + ".target").orElse(null); + final boolean fileSystemTypeSet = !XChars.isEmpty(fileSystemTypeKey); for(final ConfigurationBasedCreator creator : ConfigurationBasedCreator.registeredCreators(AFileSystem.class)) { - final AFileSystem fileSystem = creator.create(configuration); - if(fileSystem != null) + if(!fileSystemTypeSet || creator.key().equals(fileSystemTypeKey)) { - return fileSystem; + final Configuration child = configuration.child(creator.key()); + if(child != null) + { + final AFileSystem fileSystem = creator.create(child); + if(fileSystem != null) + { + return fileSystem; + } + } } } + if(fileSystemTypeSet) + { + throw new IllegalStateException( + "No " + configurationKey + " provider found for '" + fileSystemTypeKey + + "'. Please ensure that all required dependencies are present." + ); + } } return defaultFileSystemSupplier.get(); From 733039c46c1d3a09903a2120e7f48c978b9acdc9 Mon Sep 17 00:00:00 2001 From: Zdenek Jonas Date: Mon, 22 Jul 2024 10:10:54 +0200 Subject: [PATCH 124/126] update plugins, always check new snapshot --- pom.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f41d9b8e..72d8030d 100644 --- a/pom.xml +++ b/pom.xml @@ -86,6 +86,7 @@ true + always @@ -275,7 +276,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.1.0 + 3.2.4 sign-artifacts @@ -296,7 +297,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.1 + 3.1.2 org.apache.maven.plugins From c0fc57d269774ac32ae9201b16839ee5f77b8702 Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Mon, 22 Jul 2024 16:18:37 +0200 Subject: [PATCH 125/126] 1.4.0 docs (#252) --- docs/antora.yml | 4 ++-- docs/modules/intro/pages/changelog.adoc | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/antora.yml b/docs/antora.yml index 016c1d50..3f6299bd 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -8,6 +8,6 @@ nav: asciidoc: attributes: product-name: 'EclipseStore' - display-version: '1.3.2' + display-version: '1.4.0' api-version: '1' - maven-version: '1.3.2' + maven-version: '1.4.0' diff --git a/docs/modules/intro/pages/changelog.adoc b/docs/modules/intro/pages/changelog.adoc index bbea355a..c63cf731 100644 --- a/docs/modules/intro/pages/changelog.adoc +++ b/docs/modules/intro/pages/changelog.adoc @@ -1,7 +1,23 @@ = Changelog +== 1.4.0 + +=== Features + +* S3 Express One Zone integration https://github.com/eclipse-store/store/issues/224[[224]] +* S3 Enhancements https://github.com/eclipse-store/store/issues/233[[233]] https://github.com/eclipse-store/store/pull/242[[242]] +* Type Dictionary Import and Export for Serializer https://github.com/eclipse-serializer/serializer/pull/128[[128]] + +=== Bugfixes + +* S3 Fixes https://github.com/eclipse-store/store/issues/234[[234]] +* NIO Transfer Workaround https://github.com/eclipse-store/store/pull/238[[238]] + + == 1.3.2 +=== Features + * Spring Boot improvements https://github.com/eclipse-store/store/pull/206[[206]] * Ensure Minio compatibility https://github.com/eclipse-store/store/pull/197[[197]] @@ -13,6 +29,8 @@ == 1.3.1 +=== Features + * Spring Boot improvements https://github.com/eclipse-store/store/pull/136[[136]] * xref:misc:integrations/cdi.adoc[CDI Integration] From 1cde90257daf5befae313debc5aad07f79aca940 Mon Sep 17 00:00:00 2001 From: Florian Habermann Date: Thu, 10 Oct 2024 14:11:18 +0200 Subject: [PATCH 126/126] Update antora.yml --- docs/antora.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/antora.yml b/docs/antora.yml index 3f6299bd..5743be2e 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -1,6 +1,6 @@ name: manual title: EclipseStore Reference Manual -version: master +version: '1' display_version: 'V1' start_page: intro:welcome.adoc nav: