From 75fe22b4626aff33907b78fa8fe066d831d35e16 Mon Sep 17 00:00:00 2001 From: latlon team <info@lat-lon.de> Date: Wed, 12 Feb 2025 12:23:51 +0000 Subject: [PATCH] Code drop - XPLANBOX-3370 - remove protocol from mapserver config (6670363d0) - XPLANBOX-3295 - fixed configuration of StorageCRS of XPlanValidatorWMS (640d8427b) - XPLANBOX-3658 - fixed mapserver url (cfecb913e) - XPLANBOX-2711 - added version command to XPlanCLI (671eb3799) - XPLANBOX-3370 - removed duplicated protocol (3e2983ae6) - XPLANBOX-3370 - fixed tests (5f722e123) - XPLANBOX-3579 - upgrade xplan-loadtests-soapui-project.xml to SoapUI 5.8.0 (c91e72275) - XPLANBOX-3658 - Fix MapServer URL in internal.map (a87abec89) - XPLANBOX-3579 - Remove obsolete variable and update documentation (603f9ac7d) - XPLANBOX-3666 - upgrade docker image to mapproxy 3.1.3 (5bb52eda4) - XPLANBOX-3658 - updated base path in soapui tests and xplan-wms remote config (e8a004a56) - XPLANBOX-3658 - set MAPSERVER_BASE_PATH=/xplan-mapserver (cc4b1f76e) - XPLANBOX-3658 - upgrade mapserevr docker image to current camptocamp/mapserver:8.4-gdal3.10 (95b9c1776) - XPLANBOX-3579 - Set version of soapui-maven-plugin to 5.8.0 (214bef3e8) - XPLANBOX-3579 - Migrate SoapUI projects to version 5.8.0 (3ac7a8df4) - XPLANBOX-3370 - added region to fix test failure (7503f901b) - XPLANBOX-3370 - harmonized s3mock tests (9bbc14a2d) - XPLANBOX-3370 - fixed/unified tests (103c48bfd) - XPLANBOX-3370 - removed diable aws sdk v1 warning (2ab100f93) - XPLANBOX-3370 - upgrade to AWS SDK v2 (93e0bdd27) Co-authored-by: Dirk Stenger <stenger@lat-lon.de> Co-authored-by: Lyn Elisa Goltz <goltz@lat-lon.de> Dropped from commit: d7e569617dec6575ca3ade3cb123cd036253cecd --- pom.xml | 10 +- xplan-cli/pom.xml | 13 +- .../latlon/xplanbox/cli/main/MainCommand.java | 5 +- .../xplanbox/cli/version/VersionCommand.java | 45 +++++ .../commons/handler/AbstractAsyncWrapper.java | 13 +- xplan-core/xplan-core-commons/pom.xml | 9 +- .../de/latlon/xplan/commons/s3/S3Storage.java | 158 ++++++++++-------- .../xplan/commons/s3/StorageException.java | 6 +- .../s3/config/AmazonS3ReadOnlyContext.java | 51 +++--- xplan-core/xplan-core-manager/pom.xml | 5 +- .../AmazonS3DocumentStorageContext.java | 4 +- .../document/s3/S3DocumentStorage.java | 4 +- .../storage/s3/S3StorageCleanUpManager.java | 19 +-- .../config/AmazonS3TransactionalContext.java | 6 +- .../raster/storage/s3/S3RasterStorage.java | 4 +- .../config/AmazonS3RasterStorageContext.java | 4 +- .../document/s3/S3DocumentStorageIT.java | 17 +- .../s3/S3StorageCleanUpManagerTest.java | 71 ++++---- .../storage/s3/S3StorageTestManual.java | 4 +- .../s3/config/S3StorageTestContext.java | 4 +- ...nS3TestContext.java => TestS3Context.java} | 60 +++---- .../storage/s3/S3RasterStorageTest.java | 97 +++++++---- .../storage/s3/S3RasterStorageTestManual.java | 4 +- .../src/test/resources/s3Mock.properties | 6 +- .../xplan-docker-volume-init/setupVolumes.sh | 6 +- .../xplan-dokumente-api/Dockerfile | 1 - xplan-dokumente/xplan-dokumente-api/pom.xml | 2 +- .../dokumente/config/S3DocumentContext.java | 4 +- .../service/s3/S3DocumentService.java | 11 +- .../api/dokumente/config/TestS3Context.java | 52 +++--- .../handler/DocumentHandlerTest.java | 72 +------- .../dokumente/v1/DokumenteApiJerseyTest.java | 1 + .../src/test/resources/s3Mock.properties | 25 +++ xplan-manager/xplan-manager-api/Dockerfile | 1 - xplan-manager/xplan-manager-api/pom.xml | 2 +- .../api/manager/ManagerApiJerseyTest.java | 2 +- .../api/manager/config/TestS3Context.java | 54 +++--- .../manager/executor/PlanImporterTest.java | 2 +- .../handler/EditBasisdatenHandlerTest.java | 2 +- .../api/manager/handler/PlanHandlerTest.java | 2 +- xplan-manager/xplan-manager-web/Dockerfile | 1 - xplan-manager/xplan-manager-web/pom.xml | 2 +- xplan-tests/xplan-tests-soapui/README.md | 3 +- .../xplan-tests-soapui/runAllSoapUiTests.sh | 1 - .../xplan-dokumente-api-soapui-project.xml | 4 +- .../xplan-loadtests-soapui-project.xml | 4 +- .../xplan-manager-api-soapui-project.xml | 2 +- .../xplan-validator-api-soapui-project.xml | 2 +- .../xplan-webservices-soapui-project.xml | 12 +- .../xplan-validator-api/Dockerfile | 1 - xplan-validator/xplan-validator-api/pom.xml | 7 +- .../api/validator/SpringBootAppTest.java | 5 +- .../api/validator/ValidatorApiJerseyTest.java | 1 + .../api/validator/config/TestS3Context.java | 55 +++--- .../validator/handler/ConfigHandlerTest.java | 5 +- .../handler/v2/ConfigHandlerV2Test.java | 5 +- .../src/test/resources/s3Mock.properties | 2 +- .../xplan-validator-executor/Dockerfile | 1 - .../validator/executor/PlanValidatorTest.java | 5 +- .../executor/config/TestS3Context.java | 54 +++--- .../handler/ValidationHandlerTest.java | 5 +- .../src/test/resources/s3Mock.properties | 25 +++ .../xplan-validator-storage/pom.xml | 4 +- .../config/AmazonS3ValidationContext.java | 4 +- .../s3/S3PlanValidationExecutionStorage.java | 19 ++- .../s3/S3ValidationExecutionStorageIT.java | 4 +- .../s3/S3ValidationExecutionStorageTest.java | 85 ++++++---- ...nS3TestContext.java => TestS3Context.java} | 55 +++--- xplan-validator/xplan-validator-web/pom.xml | 2 +- .../src/main/resources/mapproxy.yaml | 4 +- .../xplan-mapproxy-docker/Dockerfile | 4 +- .../src/main/resources/common.txt | 2 +- .../src/main/resources/internal.map | 2 +- .../xplan-mapserver-docker/Dockerfile | 9 +- .../startupWithConfiguredMapserver.sh | 4 +- .../xplan/validator/wms/libs.expected.txt | 51 +++++- .../datasources/remoteows/mapserver.xml | 2 +- 77 files changed, 751 insertions(+), 560 deletions(-) create mode 100644 xplan-cli/src/main/java/de/latlon/xplanbox/cli/version/VersionCommand.java rename xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/{AmazonS3TestContext.java => TestS3Context.java} (61%) create mode 100644 xplan-dokumente/xplan-dokumente-api/src/test/resources/s3Mock.properties create mode 100644 xplan-validator/xplan-validator-executor/src/test/resources/s3Mock.properties rename xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/{AmazonS3TestContext.java => TestS3Context.java} (60%) diff --git a/pom.xml b/pom.xml index 6a09f57cc..63a1dc196 100644 --- a/pom.xml +++ b/pom.xml @@ -620,7 +620,7 @@ <artifactId>maven-surefire-plugin</artifactId> <version>3.5.2</version> <configuration> - <argLine>-Xmx${tests.jvm.xmx} @{jacoco.argLine} -Daws.java.v1.disableDeprecationAnnouncement=true</argLine> + <argLine>-Xmx${tests.jvm.xmx} @{jacoco.argLine}</argLine> </configuration> </plugin> <plugin> @@ -716,7 +716,7 @@ <plugin> <groupId>com.smartbear.soapui</groupId> <artifactId>soapui-maven-plugin</artifactId> - <version>5.7.2</version> + <version>5.8.0</version> </plugin> <!-- asciidoc --> <plugin> @@ -1192,9 +1192,9 @@ <scope>provided</scope> </dependency> <dependency> - <groupId>com.amazonaws</groupId> - <artifactId>aws-java-sdk-bom</artifactId> - <version>1.12.780</version> + <groupId>software.amazon.awssdk</groupId> + <artifactId>bom</artifactId> + <version>2.30.10</version> <type>pom</type> <scope>import</scope> </dependency> diff --git a/xplan-cli/pom.xml b/xplan-cli/pom.xml index eed11ac01..165cf0c66 100644 --- a/xplan-cli/pom.xml +++ b/xplan-cli/pom.xml @@ -12,7 +12,7 @@ </parent> <properties> - <docker-contextTarFile.expectedSizeInMat10pct>102</docker-contextTarFile.expectedSizeInMat10pct> + <docker-contextTarFile.expectedSizeInMat10pct>115</docker-contextTarFile.expectedSizeInMat10pct> </properties> <profiles> @@ -35,6 +35,17 @@ <build> <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifest> + <addDefaultImplementationEntries>true</addDefaultImplementationEntries> + </manifest> + </archive> + </configuration> + </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>appassembler-maven-plugin</artifactId> diff --git a/xplan-cli/src/main/java/de/latlon/xplanbox/cli/main/MainCommand.java b/xplan-cli/src/main/java/de/latlon/xplanbox/cli/main/MainCommand.java index df61fbdc2..64ed8cd83 100644 --- a/xplan-cli/src/main/java/de/latlon/xplanbox/cli/main/MainCommand.java +++ b/xplan-cli/src/main/java/de/latlon/xplanbox/cli/main/MainCommand.java @@ -23,6 +23,7 @@ package de.latlon.xplanbox.cli.main; import de.latlon.xplanbox.cli.admin.AdminCommand; import de.latlon.xplanbox.cli.manage.ManageCommand; import de.latlon.xplanbox.cli.validate.ValidateCommand; +import de.latlon.xplanbox.cli.version.VersionCommand; import org.springframework.stereotype.Component; import picocli.CommandLine; @@ -30,8 +31,8 @@ import picocli.CommandLine; * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> */ @Component -@CommandLine.Command(name = "xpb", description = "XPlanCLI", - subcommands = { CommandLine.HelpCommand.class, ValidateCommand.class, ManageCommand.class, AdminCommand.class }) +@CommandLine.Command(name = "xpb", description = "XPlanCLI", subcommands = { CommandLine.HelpCommand.class, + VersionCommand.class, ValidateCommand.class, ManageCommand.class, AdminCommand.class }) public class MainCommand implements Runnable { @Override diff --git a/xplan-cli/src/main/java/de/latlon/xplanbox/cli/version/VersionCommand.java b/xplan-cli/src/main/java/de/latlon/xplanbox/cli/version/VersionCommand.java new file mode 100644 index 000000000..a49339df5 --- /dev/null +++ b/xplan-cli/src/main/java/de/latlon/xplanbox/cli/version/VersionCommand.java @@ -0,0 +1,45 @@ +/*- + * #%L + * xplan-cli - Kommandozeilenwerkzeuge fuer die xPlanBox + * %% + * Copyright (C) 2008 - 2025 Freie und Hansestadt Hamburg, developed by lat/lon gesellschaft für raumbezogene Informationssysteme mbH + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ +package de.latlon.xplanbox.cli.version; + +import picocli.CommandLine; + +/** + * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> + * @since 8.1 + */ +@CommandLine.Command(name = "version", aliases = { "-v", "-V", "v" }, + version = { "xPlanBox %s", "JVM: ${java.version} (${java.vendor} ${java.vm.name} ${java.vm.version})", + "OS: ${os.name} ${os.version} ${os.arch}" }) +public class VersionCommand implements Runnable { + + @Override + public void run() { + CommandLine commandLine = new CommandLine(new VersionCommand()); + commandLine.printVersionHelp(System.out, commandLine.getColorScheme().ansi(), parseVersion()); + } + + public String parseVersion() { + Package thisPackage = getClass().getPackage(); + return thisPackage.getImplementationVersion(); + } + +} diff --git a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/handler/AbstractAsyncWrapper.java b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/handler/AbstractAsyncWrapper.java index bc2268c7c..69f5fd32e 100644 --- a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/handler/AbstractAsyncWrapper.java +++ b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/handler/AbstractAsyncWrapper.java @@ -22,14 +22,16 @@ package de.latlon.xplanbox.api.commons.handler; import static org.slf4j.LoggerFactory.getLogger; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.Collections; import java.util.HashMap; import java.util.Map; -import de.latlon.core.validator.events.ValidationRequestedEvent; import de.latlon.core.validator.events.EventSender; +import de.latlon.core.validator.events.ValidationRequestedEvent; import de.latlon.xplanbox.api.commons.exception.AsyncTimeout; -import org.joda.time.Instant; import org.slf4j.Logger; /** @@ -54,7 +56,10 @@ public abstract class AbstractAsyncWrapper { LOG.info("Event sent. Waiting for processing of {}", uuid); waitingUuids.put(uuid, null); - long maxWaitDate = Long.MAX_VALUE; // TODO: which value would be correct? + // TODO: which value would be correct? + LocalDateTime maxWaitDateTime = Instant.ofEpochMilli(Long.MAX_VALUE) + .atZone(ZoneId.systemDefault()) + .toLocalDateTime(); boolean waitFinished = false; while (!waitFinished) { synchronized (waitingUuids) { @@ -70,7 +75,7 @@ public abstract class AbstractAsyncWrapper { LOG.info("Finished waiting for processing of {}", uuid); waitFinished = true; } - else if (Instant.now().isAfter(maxWaitDate)) { + else if (LocalDateTime.now().isAfter(maxWaitDateTime)) { throw new AsyncTimeout(uuid); } else { diff --git a/xplan-core/xplan-core-commons/pom.xml b/xplan-core/xplan-core-commons/pom.xml index 121673348..59d8f7850 100644 --- a/xplan-core/xplan-core-commons/pom.xml +++ b/xplan-core/xplan-core-commons/pom.xml @@ -116,8 +116,9 @@ <scope>test</scope> </dependency> <dependency> - <groupId>com.amazonaws</groupId> - <artifactId>aws-java-sdk-s3</artifactId> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> + <version>2.30.10</version> </dependency> <dependency> <groupId>org.springframework</groupId> @@ -128,6 +129,10 @@ <artifactId>xmlunit-matchers</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-autoconfigure</artifactId> + </dependency> </dependencies> </project> \ No newline at end of file diff --git a/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/S3Storage.java b/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/S3Storage.java index e3ff6f7f6..6c7d68d84 100644 --- a/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/S3Storage.java +++ b/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/S3Storage.java @@ -8,42 +8,50 @@ * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ package de.latlon.xplan.commons.s3; -import static com.amazonaws.services.s3.model.BucketLifecycleConfiguration.ENABLED; - -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Path; import java.util.List; -import com.amazonaws.AmazonServiceException; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.AmazonS3Exception; -import com.amazonaws.services.s3.model.Bucket; -import com.amazonaws.services.s3.model.BucketLifecycleConfiguration; -import com.amazonaws.services.s3.model.ObjectListing; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.PutObjectResult; -import com.amazonaws.services.s3.model.S3Object; -import com.amazonaws.services.s3.model.S3ObjectSummary; -import com.amazonaws.services.s3.model.lifecycle.LifecycleFilter; import de.latlon.xplan.commons.archive.ArchiveEntry; import de.latlon.xplan.commons.archive.XPlanArchiveContentAccess; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.core.ResponseInputStream; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.Bucket; +import software.amazon.awssdk.services.s3.model.BucketLifecycleConfiguration; +import software.amazon.awssdk.services.s3.model.CreateBucketRequest; +import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; +import software.amazon.awssdk.services.s3.model.ExpirationStatus; +import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.HeadBucketRequest; +import software.amazon.awssdk.services.s3.model.LifecycleExpiration; +import software.amazon.awssdk.services.s3.model.LifecycleRule; +import software.amazon.awssdk.services.s3.model.LifecycleRuleFilter; +import software.amazon.awssdk.services.s3.model.ListObjectsRequest; +import software.amazon.awssdk.services.s3.model.ListObjectsResponse; +import software.amazon.awssdk.services.s3.model.NoSuchBucketException; +import software.amazon.awssdk.services.s3.model.PutBucketLifecycleConfigurationRequest; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; +import software.amazon.awssdk.services.s3.model.PutObjectResponse; +import software.amazon.awssdk.services.s3.model.S3Exception; /** * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> @@ -53,24 +61,29 @@ public class S3Storage { private static final Logger LOG = LoggerFactory.getLogger(S3Storage.class); - private final AmazonS3 client; + private final S3Client client; private final String bucketName; - public S3Storage(AmazonS3 client, String bucketName) { + public S3Storage(S3Client client, String bucketName) { this.client = client; this.bucketName = bucketName; } public void setBucketExpirationDate(String id, int expirationInDays) throws StorageException { createBucketIfNotExists(); - BucketLifecycleConfiguration bucketLifecycleConfig = new BucketLifecycleConfiguration(); - BucketLifecycleConfiguration.Rule rule = new BucketLifecycleConfiguration.Rule().withId(id) - .withExpirationInDays(expirationInDays) - .withStatus(ENABLED) - .withFilter(new LifecycleFilter()); - bucketLifecycleConfig.withRules(rule); - client.setBucketLifecycleConfiguration(bucketName, bucketLifecycleConfig); + LifecycleRule rule = LifecycleRule.builder() + .id(id) + .expiration(LifecycleExpiration.builder().days(expirationInDays).build()) + .status(ExpirationStatus.ENABLED) + .filter(LifecycleRuleFilter.builder().build()) + .build(); + BucketLifecycleConfiguration bucketLifecycleConfig = BucketLifecycleConfiguration.builder().rules(rule).build(); + PutBucketLifecycleConfigurationRequest lifecycleRequest = PutBucketLifecycleConfigurationRequest.builder() + .bucket(bucketName) + .lifecycleConfiguration(bucketLifecycleConfig) + .build(); + client.putBucketLifecycleConfiguration(lifecycleRequest); } /** @@ -80,18 +93,17 @@ public class S3Storage { * with the passed key was not found */ public de.latlon.xplan.commons.s3.S3Object getObject(String key) throws StorageException { - S3Object object = null; + ResponseInputStream<GetObjectResponse> object = null; try { LOG.info("Get object with key {} from bucket {}.", key, bucketName); - object = client.getObject(bucketName, key); - ObjectMetadata objectMetadata = object.getObjectMetadata(); - S3Metadata s3Metadata = new S3Metadata(object.getKey(), objectMetadata.getContentType(), - objectMetadata.getContentLength()); + object = client.getObject(GetObjectRequest.builder().bucket(bucketName).key(key).build()); + GetObjectResponse response = object.response(); + S3Metadata s3Metadata = new S3Metadata(key, response.contentType(), response.contentLength()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); - object.getObjectContent().transferTo(bos); + object.transferTo(bos); return new de.latlon.xplan.commons.s3.S3Object(s3Metadata, bos.toByteArray()); } - catch (AmazonServiceException | IOException e) { + catch (AwsServiceException | IOException e) { throw new StorageException("Could not get object with key " + key + " from bucket " + bucketName + ".", e); } finally { @@ -108,18 +120,20 @@ public class S3Storage { public S3Metadata getObjectMetadata(String key) throws StorageException { try { LOG.info("Get object metadata with key {} from bucket {}.", key, bucketName); - S3Object object = client.getObject(bucketName, key); - ObjectMetadata objectMetadata = object.getObjectMetadata(); - return new S3Metadata(object.getKey(), objectMetadata.getContentType(), objectMetadata.getContentLength()); + ResponseInputStream<GetObjectResponse> object = client + .getObject(GetObjectRequest.builder().bucket(bucketName).key(key).build()); + GetObjectResponse response = object.response(); + return new S3Metadata(key, response.contentType(), response.contentLength()); } - catch (AmazonServiceException e) { + catch (AwsServiceException e) { throw new StorageException("Could not get object with key " + key + " from bucket " + bucketName + ".", e); } } - public List<S3ObjectSummary> listObjects(String prefix) { - ObjectListing objectsToDelete = client.listObjects(bucketName, prefix); - return objectsToDelete.getObjectSummaries(); + public List<software.amazon.awssdk.services.s3.model.S3Object> listObjects(String prefix) { + ListObjectsResponse objectsToDelete = client + .listObjects(ListObjectsRequest.builder().bucket(bucketName).prefix(prefix).build()); + return objectsToDelete.contents(); } public String insertObject(int planId, String entryName, XPlanArchiveContentAccess archive) @@ -132,24 +146,28 @@ public class S3Storage { String contentType = entry.getContentType(); long contentLength = entry.getContentLength(); InputStream content = archive.retrieveInputStreamFor(entryName); - ObjectMetadata metadata = new ObjectMetadata(); - metadata.setContentLength(contentLength); - metadata.setContentType(contentType); - client.putObject(bucketName, key, content, metadata); + PutObjectRequest putObjectRequest = PutObjectRequest.builder() + .bucket(bucketName) + .key(key) + .contentLength(contentLength) + .contentType(contentType) + .build(); + client.putObject(putObjectRequest, RequestBody.fromInputStream(content, contentLength)); return key; } - catch (AmazonServiceException e) { + catch (AwsServiceException e) { throw new StorageException("Could not insert object with key " + key + " in bucket " + bucketName + ".", e); } } - public PutObjectResult insertObject(String key, Path file) throws StorageException { + public PutObjectResponse insertObject(String key, Path file) throws StorageException { createBucketIfNotExists(); try { LOG.info("Insert object with key {} in bucket {}.", key, bucketName); - return client.putObject(bucketName, key, file.toFile()); + return client.putObject(PutObjectRequest.builder().bucket(bucketName).key(key).build(), + RequestBody.fromFile(file.toFile())); } - catch (AmazonServiceException e) { + catch (AwsServiceException e) { throw new StorageException("Could not insert object with key " + key + " in bucket " + bucketName + ".", e); } } @@ -159,61 +177,65 @@ public class S3Storage { String key = object.getS3Metadata().getKey(); try { LOG.info("Insert object with key {} in bucket {}.", key, bucketName); - ObjectMetadata metadata = new ObjectMetadata(); - metadata.setContentLength(object.getS3Metadata().getContentLength()); - metadata.setContentType(object.getS3Metadata().getContentType()); - ByteArrayInputStream bis = new ByteArrayInputStream(object.getContent()); - client.putObject(bucketName, key, bis, metadata); - } - catch (AmazonServiceException e) { + long contentLength = object.getS3Metadata().getContentLength(); + String contentType = object.getS3Metadata().getContentType(); + PutObjectRequest putObjectRequest = PutObjectRequest.builder() + .bucket(bucketName) + .key(key) + .contentLength(contentLength) + .contentType(contentType) + .build(); + client.putObject(putObjectRequest, RequestBody.fromBytes(object.getContent())); + } + catch (AwsServiceException e) { throw new StorageException("Could not insert object with key " + key + " in bucket " + bucketName + ".", e); } } public void deleteObjects(String prefix) { - List<S3ObjectSummary> objects = listObjects(prefix); - for (S3ObjectSummary object : objects) { + List<software.amazon.awssdk.services.s3.model.S3Object> objects = listObjects(prefix); + for (software.amazon.awssdk.services.s3.model.S3Object object : objects) { deleteObject(object); } } - public void deleteObject(S3ObjectSummary object) { - String key = object.getKey(); + public void deleteObject(software.amazon.awssdk.services.s3.model.S3Object object) { + String key = object.key(); LOG.info("Delete object with key {} from bucket {}.", key, bucketName); - client.deleteObject(bucketName, key); + client.deleteObject(DeleteObjectRequest.builder().bucket(bucketName).key(key).build()); } protected String createKey(int planId, String entry) { return planId + "_" + entry; } - protected Bucket createBucketIfNotExists() throws StorageException { - if (client.doesBucketExistV2(bucketName)) { + protected void createBucketIfNotExists() throws StorageException { + try { + client.headBucket(HeadBucketRequest.builder().bucket(bucketName).build()); LOG.info("Bucket {} already exists.", bucketName); - return getBucket(); } - else { + catch (NoSuchBucketException n) { try { LOG.info("Create bucket with name {}.", bucketName); - return client.createBucket(bucketName); + client.createBucket(CreateBucketRequest.builder().bucket(bucketName).build()); } - catch (AmazonS3Exception e) { + catch (S3Exception e) { throw new StorageException("Could not create bucket", e); } } } public Bucket getBucket() { - List<Bucket> buckets = client.listBuckets(); + List<Bucket> buckets = client.listBuckets().buckets(); for (Bucket bucket : buckets) { - if (bucket.getName().equals(bucketName)) { + if (bucket.name().equals(bucketName)) { return bucket; } } return null; } - private void closeQuietly(S3Object object) { + private void closeQuietly(ResponseInputStream<GetObjectResponse> object) { if (object != null) { try { object.close(); diff --git a/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/StorageException.java b/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/StorageException.java index c6991a3e7..975b35d62 100644 --- a/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/StorageException.java +++ b/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/StorageException.java @@ -20,7 +20,7 @@ */ package de.latlon.xplan.commons.s3; -import com.amazonaws.AmazonServiceException; +import software.amazon.awssdk.awscore.exception.AwsServiceException; /** * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> @@ -31,8 +31,8 @@ public class StorageException extends Exception { public StorageException(String message, Throwable e) { super(message, e); - if (e instanceof AmazonServiceException) - this.statusCode = ((AmazonServiceException) e).getStatusCode(); + if (e instanceof AwsServiceException) + this.statusCode = ((AwsServiceException) e).awsErrorDetails().sdkHttpResponse().statusCode(); } public StorageException(String message, int statusCode) { diff --git a/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/config/AmazonS3ReadOnlyContext.java b/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/config/AmazonS3ReadOnlyContext.java index f89d92ad9..512e200a1 100644 --- a/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/config/AmazonS3ReadOnlyContext.java +++ b/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/config/AmazonS3ReadOnlyContext.java @@ -8,18 +8,21 @@ * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ package de.latlon.xplan.commons.s3.config; +import java.net.URI; +import java.net.URISyntaxException; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -27,13 +30,11 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; - -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.client.builder.AwsClientBuilder; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; /** * Spring configuration for using AWS S3 as a storage. @@ -44,38 +45,34 @@ import com.amazonaws.services.s3.AmazonS3ClientBuilder; */ @Configuration @ComponentScan("de.latlon.xplan.manager.storage.s3.listener") -@Profile("!test") +@Profile({ "!test" }) public class AmazonS3ReadOnlyContext { private static final Logger LOG = LoggerFactory.getLogger(AmazonS3ReadOnlyContext.class); - @Bean(destroyMethod = "shutdown") - public AmazonS3 s3Client(AWSCredentials credentials, + @Bean(destroyMethod = "close") + public S3Client s3Client(AwsCredentialsProvider credentialsProvider, @Value("${xplanbox.s3.region:#{environment.XPLAN_S3_REGION}}") String region, - @Value("${xplanbox.s3.endpoint.url:#{environment.XPLAN_S3_ENDPOINT}}") String endpointUrl) { + @Value("${xplanbox.s3.endpoint.url:#{environment.XPLAN_S3_ENDPOINT}}") String endpointUrl) + throws URISyntaxException { - // TODO refactoring if/else to @ConditionalOnExpression with SpringBoot into 2 - // SpringBeans - AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard() - .withCredentials(new AWSStaticCredentialsProvider(credentials)); if (endpointUrl == null || endpointUrl.isEmpty()) { LOG.info("Using S3 region {}", region); - builder.withRegion(region); - } - else { - LOG.info("Using S3 url {} (region {})", endpointUrl); - AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration(endpointUrl, - region); - builder.withEndpointConfiguration(endpoint); + return S3Client.builder().credentialsProvider(credentialsProvider).region(Region.of(region)).build(); } - return builder.build(); + LOG.info("Using S3 url {} (region {})", endpointUrl); + return S3Client.builder() + .credentialsProvider(credentialsProvider) + .region(Region.of(region)) + .endpointOverride(new URI(endpointUrl)) + .build(); } @Bean - public AWSCredentials credentials( + public AwsCredentialsProvider credentialsProvider( @Value("${xplanbox.s3.accessKeyId:#{environment.XPLAN_S3_ACCESS_KEY}}") String accessKeyId, @Value("${xplanbox.s3.secretKey:#{environment.XPLAN_S3_SECRET_ACCESS_KEY}}") String secretKey) { - return new BasicAWSCredentials(accessKeyId, secretKey); + return StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKeyId, secretKey)); } } diff --git a/xplan-core/xplan-core-manager/pom.xml b/xplan-core/xplan-core-manager/pom.xml index fb90bc97e..338fe199b 100644 --- a/xplan-core/xplan-core-manager/pom.xml +++ b/xplan-core/xplan-core-manager/pom.xml @@ -126,8 +126,9 @@ </dependency> <!-- AWS SDK For Java --> <dependency> - <groupId>com.amazonaws</groupId> - <artifactId>aws-java-sdk-s3</artifactId> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> + <version>2.30.10</version> </dependency> <dependency> <groupId>com.github.spotbugs</groupId> diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/config/AmazonS3DocumentStorageContext.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/config/AmazonS3DocumentStorageContext.java index 8e36037cb..6d839287f 100644 --- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/config/AmazonS3DocumentStorageContext.java +++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/config/AmazonS3DocumentStorageContext.java @@ -22,7 +22,6 @@ package de.latlon.xplan.manager.document.config; import java.util.Optional; -import com.amazonaws.services.s3.AmazonS3; import de.latlon.xplan.manager.document.DocumentStorage; import de.latlon.xplan.manager.document.XPlanDocumentManager; import de.latlon.xplan.manager.document.s3.S3DocumentStorage; @@ -31,6 +30,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import software.amazon.awssdk.services.s3.S3Client; /** * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> @@ -50,7 +50,7 @@ public class AmazonS3DocumentStorageContext { } @Bean - public S3DocumentStorage documentStorage(AmazonS3 s3Client, + public S3DocumentStorage documentStorage(S3Client s3Client, @Value("${xplanbox.s3.bucketName:#{environment.XPLAN_S3_BUCKET_ATTACHMENTS}}") String bucketName) { return new S3DocumentStorage(s3Client, bucketName); } diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/s3/S3DocumentStorage.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/s3/S3DocumentStorage.java index 91ae70d8d..fb9c2b724 100644 --- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/s3/S3DocumentStorage.java +++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/s3/S3DocumentStorage.java @@ -20,10 +20,10 @@ */ package de.latlon.xplan.manager.document.s3; -import com.amazonaws.services.s3.AmazonS3; import de.latlon.xplan.commons.archive.XPlanArchive; import de.latlon.xplan.manager.document.DocumentStorage; import de.latlon.xplan.manager.storage.StorageEvent; +import software.amazon.awssdk.services.s3.S3Client; import de.latlon.xplan.commons.s3.S3Object; import de.latlon.xplan.commons.s3.S3Storage; import de.latlon.xplan.commons.s3.StorageException; @@ -40,7 +40,7 @@ import java.util.List; */ public class S3DocumentStorage extends S3Storage implements DocumentStorage { - public S3DocumentStorage(AmazonS3 client, String bucketName) { + public S3DocumentStorage(S3Client client, String bucketName) { super(client, bucketName); } diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/S3StorageCleanUpManager.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/S3StorageCleanUpManager.java index 5b12362b2..e2f838732 100644 --- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/S3StorageCleanUpManager.java +++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/S3StorageCleanUpManager.java @@ -20,15 +20,14 @@ */ package de.latlon.xplan.manager.storage.s3; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.S3ObjectSummary; +import java.util.List; + import de.latlon.xplan.commons.s3.S3Object; import de.latlon.xplan.commons.s3.S3Storage; +import de.latlon.xplan.commons.s3.StorageException; import de.latlon.xplan.manager.storage.StorageCleanUpManager; import de.latlon.xplan.manager.storage.StorageEvent; -import de.latlon.xplan.commons.s3.StorageException; - -import java.util.List; +import software.amazon.awssdk.services.s3.S3Client; /** * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> @@ -36,19 +35,19 @@ import java.util.List; */ public class S3StorageCleanUpManager extends S3Storage implements StorageCleanUpManager { - public S3StorageCleanUpManager(AmazonS3 client, String bucketName) { + public S3StorageCleanUpManager(S3Client client, String bucketName) { super(client, bucketName); } @Override public void deleteAll(String id, StorageEvent storageEvent) throws StorageException { - List<S3ObjectSummary> s3ObjectSummaries = listObjects(id + "_"); - for (S3ObjectSummary objectSummary : s3ObjectSummaries) { - String key = objectSummary.getKey(); + List<software.amazon.awssdk.services.s3.model.S3Object> s3Objects = listObjects(id + "_"); + for (software.amazon.awssdk.services.s3.model.S3Object s3object : s3Objects) { + String key = s3object.key(); S3Object object = getObject(key); if (object != null) storageEvent.addDeletedKey(object); - deleteObject(objectSummary); + deleteObject(s3object); } } diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3TransactionalContext.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3TransactionalContext.java index 03cce2384..2ff1e6b63 100644 --- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3TransactionalContext.java +++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3TransactionalContext.java @@ -20,7 +20,6 @@ */ package de.latlon.xplan.manager.storage.s3.config; -import com.amazonaws.services.s3.AmazonS3; import de.latlon.xplan.commons.s3.S3Storage; import de.latlon.xplan.commons.s3.config.AmazonS3ReadOnlyContext; import de.latlon.xplan.manager.storage.StorageCleanUpManager; @@ -29,6 +28,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import software.amazon.awssdk.services.s3.S3Client; /** * Spring configuration for using AWS S3 as a storage. @@ -42,13 +42,13 @@ import org.springframework.context.annotation.Import; public class AmazonS3TransactionalContext { @Bean - public StorageCleanUpManager storageCleanUpManager(AmazonS3 s3Client, + public StorageCleanUpManager storageCleanUpManager(S3Client s3Client, @Value("${xplanbox.s3.bucketName:#{environment.XPLAN_S3_BUCKET_ATTACHMENTS}}") String bucketName) { return new S3StorageCleanUpManager(s3Client, bucketName); } @Bean - public S3Storage rollbackStorage(AmazonS3 s3Client, + public S3Storage rollbackStorage(S3Client s3Client, @Value("${xplanbox.s3.bucketName:#{environment.XPLAN_S3_BUCKET_ATTACHMENTS}}") String bucketName) { return new S3Storage(s3Client, bucketName); } diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorage.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorage.java index 3466cb120..f53fae378 100644 --- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorage.java +++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorage.java @@ -20,7 +20,6 @@ */ package de.latlon.xplan.manager.wmsconfig.raster.storage.s3; -import com.amazonaws.services.s3.AmazonS3; import de.latlon.xplan.commons.archive.XPlanArchiveContentAccess; import de.latlon.xplan.manager.storage.StorageEvent; import de.latlon.xplan.commons.s3.S3Object; @@ -28,6 +27,7 @@ import de.latlon.xplan.commons.s3.S3Storage; import de.latlon.xplan.manager.wmsconfig.raster.storage.RasterStorage; import de.latlon.xplan.commons.s3.StorageException; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import software.amazon.awssdk.services.s3.S3Client; /** * {@link RasterStorage} implementation storing and deleting raster files in a S3 bucket. @@ -37,7 +37,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; */ public class S3RasterStorage extends S3Storage implements RasterStorage { - public S3RasterStorage(AmazonS3 client, String bucketName) { + public S3RasterStorage(S3Client client, String bucketName) { super(client, bucketName); } diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/config/AmazonS3RasterStorageContext.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/config/AmazonS3RasterStorageContext.java index 8d35767ff..6c00e40eb 100644 --- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/config/AmazonS3RasterStorageContext.java +++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/config/AmazonS3RasterStorageContext.java @@ -20,13 +20,13 @@ */ package de.latlon.xplan.manager.wmsconfig.raster.storage.s3.config; -import com.amazonaws.services.s3.AmazonS3; import de.latlon.xplan.manager.storage.s3.config.AmazonS3TransactionalContext; import de.latlon.xplan.manager.wmsconfig.raster.storage.s3.S3RasterStorage; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import software.amazon.awssdk.services.s3.S3Client; /** * Spring configuration for using AWS S3 as a storage for raster data. This requires @@ -42,7 +42,7 @@ import org.springframework.context.annotation.Import; public class AmazonS3RasterStorageContext { @Bean - public S3RasterStorage rasterStorage(AmazonS3 s3Client, + public S3RasterStorage rasterStorage(S3Client s3Client, @Value("${xplanbox.s3.bucketName:#{environment.XPLAN_S3_BUCKET_ATTACHMENTS}}") String bucketName) { return new S3RasterStorage(s3Client, bucketName); } diff --git a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/document/s3/S3DocumentStorageIT.java b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/document/s3/S3DocumentStorageIT.java index 41964afc4..b4b802832 100644 --- a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/document/s3/S3DocumentStorageIT.java +++ b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/document/s3/S3DocumentStorageIT.java @@ -29,6 +29,12 @@ import java.io.InputStream; import java.util.Collections; import java.util.List; +import de.latlon.xplan.commons.archive.XPlanArchive; +import de.latlon.xplan.commons.archive.XPlanArchiveCreator; +import de.latlon.xplan.commons.s3.StorageException; +import de.latlon.xplan.manager.document.config.AmazonS3DocumentStorageContext; +import de.latlon.xplan.manager.storage.StorageEvent; +import de.latlon.xplan.manager.storage.s3.config.TestS3Context; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -37,13 +43,6 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; -import de.latlon.xplan.commons.archive.XPlanArchive; -import de.latlon.xplan.commons.archive.XPlanArchiveCreator; -import de.latlon.xplan.commons.s3.StorageException; -import de.latlon.xplan.manager.document.config.AmazonS3DocumentStorageContext; -import de.latlon.xplan.manager.storage.StorageEvent; -import de.latlon.xplan.manager.storage.s3.config.AmazonS3TestContext; - /** * ATTENTION: Executing this test class can run up the bill for the AWS account * configured! Ensure that the S3 client is using a free account or is substituted by a @@ -55,8 +54,8 @@ import de.latlon.xplan.manager.storage.s3.config.AmazonS3TestContext; * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> * @author <a href="mailto:friebe@lat-lon.de">Torsten Friebe</a> */ -@ContextConfiguration(classes = { AmazonS3DocumentStorageContext.class, AmazonS3TestContext.class }) -@ActiveProfiles({ "mock" }) +@ContextConfiguration(classes = { AmazonS3DocumentStorageContext.class, TestS3Context.class }) +@ActiveProfiles({ "mock", "test" }) @TestPropertySource("classpath:s3Mock.properties") @ExtendWith(SpringExtension.class) class S3DocumentStorageIT { diff --git a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/S3StorageCleanUpManagerTest.java b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/S3StorageCleanUpManagerTest.java index 9caecd3db..f64b4b9ed 100644 --- a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/S3StorageCleanUpManagerTest.java +++ b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/S3StorageCleanUpManagerTest.java @@ -8,39 +8,44 @@ * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ package de.latlon.xplan.manager.storage.s3; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.ObjectListing; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.S3Object; -import com.amazonaws.services.s3.model.S3ObjectInputStream; -import com.amazonaws.services.s3.model.S3ObjectSummary; -import de.latlon.xplan.manager.storage.StorageEvent; -import org.junit.jupiter.api.Test; -import de.latlon.xplan.commons.s3.StorageException; -import org.mockito.ArgumentCaptor; - -import java.util.Collections; -import java.util.List; - import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.util.Collections; +import java.util.List; + +import de.latlon.xplan.commons.s3.StorageException; +import de.latlon.xplan.manager.storage.StorageEvent; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import software.amazon.awssdk.core.ResponseInputStream; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; +import software.amazon.awssdk.services.s3.model.DeleteObjectResponse; +import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.ListObjectsRequest; +import software.amazon.awssdk.services.s3.model.ListObjectsResponse; +import software.amazon.awssdk.services.s3.model.S3Object; + /** * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> */ @@ -50,29 +55,29 @@ class S3StorageCleanUpManagerTest { @Test void deleteRasterFiles() throws StorageException { - AmazonS3 client = spy(AmazonS3.class); - ObjectListing objectListing = mock(ObjectListing.class); - S3Object object = mock(S3Object.class); - when(object.getObjectContent()).thenReturn(mock(S3ObjectInputStream.class)); - ObjectMetadata objectMetadata = mock(ObjectMetadata.class); - when(objectMetadata.getContentType()).thenReturn("image/png"); - when(objectMetadata.getContentLength()).thenReturn(90l); - when(object.getObjectMetadata()).thenReturn(objectMetadata); - when(object.getKey()).thenReturn("1_test.png"); - when(client.listObjects(eq(BUCKET_NAME), eq("1_"))).thenReturn(objectListing); - when(client.getObject(eq(BUCKET_NAME), eq("1_test.png"))).thenReturn(object); + S3Client client = spy(S3Client.class); + ListObjectsResponse objectListing = mock(ListObjectsResponse.class); + doReturn(objectListing).when(client) + .listObjects(eq(ListObjectsRequest.builder().bucket(BUCKET_NAME).prefix("1_").build())); + ResponseInputStream<GetObjectResponse> objectStream = mock(ResponseInputStream.class); + GetObjectResponse getObjectResponse = mock(GetObjectResponse.class); + when(getObjectResponse.contentType()).thenReturn("image/png"); + when(getObjectResponse.contentLength()).thenReturn(90l); + when(objectStream.response()).thenReturn(getObjectResponse); + doReturn(objectStream).when(client).getObject(any(GetObjectRequest.class)); + doReturn(DeleteObjectResponse.builder().build()).when(client).deleteObject(any(DeleteObjectRequest.class)); - S3ObjectSummary objectToDelete = mock(S3ObjectSummary.class); - when(objectToDelete.getKey()).thenReturn("1_test.png"); - List<S3ObjectSummary> objectSummaries = Collections.singletonList(objectToDelete); - when(objectListing.getObjectSummaries()).thenReturn(objectSummaries); + S3Object objectToDelete = mock(S3Object.class); + when(objectToDelete.key()).thenReturn("1_test.png"); + List<S3Object> objectSummaries = Collections.singletonList(objectToDelete); + when(objectListing.contents()).thenReturn(objectSummaries); S3StorageCleanUpManager s3RasterStorage = new S3StorageCleanUpManager(client, BUCKET_NAME); StorageEvent storageEvent = mock(StorageEvent.class); s3RasterStorage.deleteAll("1", storageEvent); - verify(client).listObjects(BUCKET_NAME, "1_"); - verify(client).deleteObject(BUCKET_NAME, "1_test.png"); + verify(client).listObjects(ListObjectsRequest.builder().bucket(BUCKET_NAME).prefix("1_").build()); + verify(client).deleteObject(DeleteObjectRequest.builder().bucket(BUCKET_NAME).key("1_test.png").build()); ArgumentCaptor<de.latlon.xplan.commons.s3.S3Object> argument = ArgumentCaptor .forClass(de.latlon.xplan.commons.s3.S3Object.class); verify(storageEvent).addDeletedKey(argument.capture()); diff --git a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/S3StorageTestManual.java b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/S3StorageTestManual.java index fb8658f4a..372065075 100644 --- a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/S3StorageTestManual.java +++ b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/S3StorageTestManual.java @@ -40,7 +40,7 @@ import de.latlon.xplan.commons.s3.S3Metadata; import de.latlon.xplan.commons.s3.S3Object; import de.latlon.xplan.commons.s3.S3Storage; import de.latlon.xplan.commons.s3.StorageException; -import de.latlon.xplan.manager.storage.s3.config.AmazonS3TestContext; +import de.latlon.xplan.manager.storage.s3.config.TestS3Context; import de.latlon.xplan.manager.storage.s3.config.S3StorageTestContext; /** @@ -53,7 +53,7 @@ import de.latlon.xplan.manager.storage.s3.config.S3StorageTestContext; * * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> */ -@ContextConfiguration(classes = { AmazonS3TestContext.class, S3StorageTestContext.class }) +@ContextConfiguration(classes = { TestS3Context.class, S3StorageTestContext.class }) @ActiveProfiles({ "mock" }) @TestPropertySource("classpath:s3Mock.properties") @ExtendWith(SpringExtension.class) diff --git a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/S3StorageTestContext.java b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/S3StorageTestContext.java index cfbc7127d..75095c661 100644 --- a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/S3StorageTestContext.java +++ b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/S3StorageTestContext.java @@ -20,11 +20,11 @@ */ package de.latlon.xplan.manager.storage.s3.config; -import com.amazonaws.services.s3.AmazonS3; import de.latlon.xplan.commons.s3.S3Storage; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import software.amazon.awssdk.services.s3.S3Client; /** * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> @@ -33,7 +33,7 @@ import org.springframework.context.annotation.Configuration; public class S3StorageTestContext { @Bean - public S3Storage rollbackStorage(AmazonS3 s3Client, + public S3Storage rollbackStorage(S3Client s3Client, @Value("${xplanbox.s3.bucketName:#{environment.XPLAN_S3_BUCKET_ATTACHMENTS}}") String bucketName) { return new S3Storage(s3Client, bucketName); } diff --git a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3TestContext.java b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/TestS3Context.java similarity index 61% rename from xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3TestContext.java rename to xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/TestS3Context.java index 53a717590..58b21cc20 100644 --- a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3TestContext.java +++ b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/TestS3Context.java @@ -8,35 +8,36 @@ * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ package de.latlon.xplan.manager.storage.s3.config; -import jakarta.annotation.PreDestroy; +import static software.amazon.awssdk.regions.Region.EU_CENTRAL_1; + +import java.net.URI; +import java.net.URISyntaxException; -import org.springframework.beans.factory.annotation.Autowired; +import io.findify.s3mock.S3Mock; +import jakarta.annotation.PreDestroy; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Profile; import org.springframework.test.util.TestSocketUtils; - -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.AnonymousAWSCredentials; -import com.amazonaws.client.builder.AwsClientBuilder; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; - -import io.findify.s3mock.S3Mock; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.S3Configuration; +import software.amazon.awssdk.services.s3.model.CreateBucketRequest; /** * Spring Configuration to enable usage of mock objects for integration tests. @@ -45,20 +46,18 @@ import io.findify.s3mock.S3Mock; * @author <a href="mailto:friebe@lat-lon.de">Torsten Friebe</a> */ @Configuration -public class AmazonS3TestContext { +public class TestS3Context { - @Autowired(required = false) - private S3Mock s3Mock; + private final int port = TestSocketUtils.findAvailableTcpPort(); - @Autowired - private AmazonS3 s3TestClient; + private S3Client s3TestClient; - private final int port = TestSocketUtils.findAvailableTcpPort(); + private S3Mock s3Mock; @Bean @Profile("mock") public S3Mock s3Mock() { - S3Mock s3Mock = new S3Mock.Builder().withPort(port).withInMemoryBackend().build(); + this.s3Mock = new S3Mock.Builder().withPort(port).withInMemoryBackend().build(); s3Mock.start(); return s3Mock; } @@ -66,23 +65,24 @@ public class AmazonS3TestContext { @Bean @Primary @Profile("mock") - public AmazonS3 s3TestClient(@Value("${xplanbox.s3.region}") String signingRegion, - @Value("${xplanbox.s3.bucketName}") String bucketName, @Value("${xplanbox.s3.endpoint.url}") String url) { - - AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration(url + ":" + port, - signingRegion); - AmazonS3 client = AmazonS3ClientBuilder.standard() - .withPathStyleAccessEnabled(true) - .withEndpointConfiguration(endpoint) - .withCredentials(new AWSStaticCredentialsProvider(new AnonymousAWSCredentials())) + public S3Client s3Client(S3Mock s3Mock, @Value("${xplanbox.s3.bucketName}") String bucketName) + throws URISyntaxException { + URI endpoint = new URI("http://localhost:" + port); + S3Client client = S3Client.builder() + .serviceConfiguration(S3Configuration.builder().pathStyleAccessEnabled(true).build()) + .endpointOverride(endpoint) + .credentialsProvider( + StaticCredentialsProvider.create(AwsBasicCredentials.create("accessKeyId", "secretKey"))) + .region(EU_CENTRAL_1) .build(); - client.createBucket(bucketName); + client.createBucket(CreateBucketRequest.builder().bucket(bucketName).build()); + s3TestClient = client; return client; } @PreDestroy public void shutdown() { - s3TestClient.shutdown(); + s3TestClient.close(); if (s3Mock != null) { s3Mock.stop(); } diff --git a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorageTest.java b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorageTest.java index c4b52373d..3551e9671 100644 --- a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorageTest.java +++ b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorageTest.java @@ -8,12 +8,12 @@ * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% @@ -22,20 +22,39 @@ package de.latlon.xplan.manager.wmsconfig.raster.storage.s3; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; -import java.io.InputStream; +import java.io.ByteArrayInputStream; import java.util.Collections; import java.util.List; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.*; import de.latlon.xplan.commons.archive.ArchiveEntry; import de.latlon.xplan.commons.archive.XPlanArchiveContentAccess; import de.latlon.xplan.commons.s3.StorageException; import de.latlon.xplan.manager.storage.StorageEvent; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; +import software.amazon.awssdk.core.ResponseInputStream; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; +import software.amazon.awssdk.services.s3.model.DeleteObjectResponse; +import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.HeadBucketRequest; +import software.amazon.awssdk.services.s3.model.HeadBucketResponse; +import software.amazon.awssdk.services.s3.model.ListObjectsRequest; +import software.amazon.awssdk.services.s3.model.ListObjectsResponse; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; +import software.amazon.awssdk.services.s3.model.PutObjectResponse; +import software.amazon.awssdk.services.s3.model.S3Object; /** * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> @@ -46,46 +65,55 @@ class S3RasterStorageTest { @Test void testAddRasterFile() throws StorageException { - AmazonS3 client = spy(AmazonS3.class); + S3Client client = createS3ClientSpy(); S3RasterStorage s3RasterStorage = new S3RasterStorage(client, BUCKET_NAME); XPlanArchiveContentAccess archive = mockArchive(); StorageEvent storageEvent = mock(StorageEvent.class); String key = s3RasterStorage.addRasterFile(1, "test.png", "test.png.aux.xml", archive, storageEvent); - ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class); + + ArgumentCaptor<HeadBucketRequest> headBucketRequestCaptor = ArgumentCaptor.forClass(HeadBucketRequest.class); + ArgumentCaptor<PutObjectRequest> putObjectRequestCaptor = ArgumentCaptor.forClass(PutObjectRequest.class); + assertEquals("1_test.png", key); - verify(client, times(2)).doesBucketExistV2(eq(BUCKET_NAME)); - verify(client, times(2)).putObject(eq(BUCKET_NAME), captor.capture(), nullable(InputStream.class), - any(ObjectMetadata.class)); - assertThat(captor.getAllValues()).contains("1_test.png", "1_test.png.aux.xml"); + + verify(client, times(2)).headBucket(headBucketRequestCaptor.capture()); + verify(client, times(2)).putObject(putObjectRequestCaptor.capture(), any(RequestBody.class)); + assertThat(headBucketRequestCaptor.getAllValues()).map(HeadBucketRequest::bucket) + .containsExactlyInAnyOrder(BUCKET_NAME, BUCKET_NAME); + assertThat(putObjectRequestCaptor.getAllValues()).map(PutObjectRequest::bucket) + .contains(BUCKET_NAME, BUCKET_NAME); + assertThat(putObjectRequestCaptor.getAllValues()).map(PutObjectRequest::key) + .contains("1_test.png", "1_test.png.aux.xml"); verify(storageEvent).addInsertedKey(eq("1_test.png")); } @Test void testDeleteRasterFile() throws StorageException { - AmazonS3 client = spy(AmazonS3.class); - ObjectListing objectListing = mock(ObjectListing.class); - S3Object object = mock(S3Object.class); - when(object.getObjectContent()).thenReturn(mock(S3ObjectInputStream.class)); - ObjectMetadata objectMetadata = mock(ObjectMetadata.class); - when(objectMetadata.getContentType()).thenReturn("image/png"); - when(objectMetadata.getContentLength()).thenReturn(90l); - when(object.getObjectMetadata()).thenReturn(objectMetadata); - when(object.getKey()).thenReturn("1_test.png"); - when(client.listObjects(eq(BUCKET_NAME), eq("1_test.png"))).thenReturn(objectListing); - when(client.getObject(eq(BUCKET_NAME), eq("1_test.png"))).thenReturn(object); - - S3ObjectSummary objectToDelete = mock(S3ObjectSummary.class); - when(objectToDelete.getKey()).thenReturn("1_test.png"); - List<S3ObjectSummary> objectSummaries = Collections.singletonList(objectToDelete); - when(objectListing.getObjectSummaries()).thenReturn(objectSummaries); + S3Client client = spy(S3Client.class); + ListObjectsResponse objectListing = mock(ListObjectsResponse.class); + doReturn(objectListing).when(client) + .listObjects(eq(ListObjectsRequest.builder().bucket(BUCKET_NAME).prefix("1_test.png").build())); + ResponseInputStream<GetObjectResponse> objectStream = mock(ResponseInputStream.class); + GetObjectResponse getObjectResponse = mock(GetObjectResponse.class); + when(getObjectResponse.contentType()).thenReturn("image/png"); + when(getObjectResponse.contentLength()).thenReturn(90l); + when(objectStream.response()).thenReturn(getObjectResponse); + doReturn(objectStream).when(client).getObject(any(GetObjectRequest.class)); + doReturn(DeleteObjectResponse.builder().build()).when(client).deleteObject(any(DeleteObjectRequest.class)); + + S3Object objectToDelete = mock(S3Object.class); + when(objectToDelete.key()).thenReturn("1_test.png"); + List<S3Object> objectSummaries = Collections.singletonList(objectToDelete); + when(objectListing.contents()).thenReturn(objectSummaries); + S3RasterStorage s3RasterStorage = new S3RasterStorage(client, BUCKET_NAME); StorageEvent storageEvent = mock(StorageEvent.class); s3RasterStorage.deleteRasterFile(1, "test.png", storageEvent); - verify(client).deleteObject(BUCKET_NAME, "1_test.png"); + verify(client).deleteObject(DeleteObjectRequest.builder().bucket(BUCKET_NAME).key("1_test.png").build()); ArgumentCaptor<de.latlon.xplan.commons.s3.S3Object> argument = ArgumentCaptor .forClass(de.latlon.xplan.commons.s3.S3Object.class); verify(storageEvent).addDeletedKey(argument.capture()); @@ -98,12 +126,23 @@ class S3RasterStorageTest { when(referenceEntry.getContentLength()).thenReturn(90l); when(referenceEntry.getContentType()).thenReturn("image/png"); when(mock.getEntry("test.png")).thenReturn(referenceEntry); + when(mock.retrieveInputStreamFor("test.png")).thenReturn(new ByteArrayInputStream("test.png".getBytes())); ArchiveEntry georefEntry = mock(ArchiveEntry.class); when(georefEntry.getContentLength()).thenReturn(10l); when(georefEntry.getContentType()).thenReturn("application/xml"); when(mock.getEntry("test.png.aux.xml")).thenReturn(georefEntry); + when(mock.retrieveInputStreamFor("test.png.aux.xml")) + .thenReturn(new ByteArrayInputStream("test.png.aux.xml".getBytes())); return mock; } + private static S3Client createS3ClientSpy() { + S3Client client = spy(S3Client.class); + doReturn(HeadBucketResponse.builder().build()).when(client).headBucket(any(HeadBucketRequest.class)); + doReturn(PutObjectResponse.builder().build()).when(client) + .putObject(any(PutObjectRequest.class), any(RequestBody.class)); + return client; + } + } diff --git a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorageTestManual.java b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorageTestManual.java index e8fb6b114..9913c8322 100644 --- a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorageTestManual.java +++ b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorageTestManual.java @@ -42,7 +42,7 @@ import de.latlon.xplan.commons.archive.XPlanArchiveCreator; import de.latlon.xplan.commons.s3.S3Object; import de.latlon.xplan.commons.s3.StorageException; import de.latlon.xplan.manager.storage.StorageEvent; -import de.latlon.xplan.manager.storage.s3.config.AmazonS3TestContext; +import de.latlon.xplan.manager.storage.s3.config.TestS3Context; import de.latlon.xplan.manager.wmsconfig.raster.storage.s3.config.AmazonS3RasterStorageContext; /** @@ -56,7 +56,7 @@ import de.latlon.xplan.manager.wmsconfig.raster.storage.s3.config.AmazonS3Raster * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> * @author <a href="mailto:friebe@lat-lon.de">Torsten Friebe</a> */ -@ContextConfiguration(classes = { AmazonS3RasterStorageContext.class, AmazonS3TestContext.class }) +@ContextConfiguration(classes = { AmazonS3RasterStorageContext.class, TestS3Context.class }) @ActiveProfiles({ "mock" }) @TestPropertySource("classpath:s3Mock.properties") @ExtendWith(SpringExtension.class) diff --git a/xplan-core/xplan-core-manager/src/test/resources/s3Mock.properties b/xplan-core/xplan-core-manager/src/test/resources/s3Mock.properties index 22040175b..e1c35a7df 100644 --- a/xplan-core/xplan-core-manager/src/test/resources/s3Mock.properties +++ b/xplan-core/xplan-core-manager/src/test/resources/s3Mock.properties @@ -18,8 +18,8 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # #L% ### -xplanbox.s3.accessKeyId= -xplanbox.s3.secretKey= -xplanbox.s3.bucketName=latlonxpb +xplanbox.s3.accessKeyId=test +xplanbox.s3.secretKey=test +xplanbox.s3.bucketName=latlonxpbtest xplanbox.s3.region=eu-central-1 xplanbox.s3.endpoint.url=http://localhost diff --git a/xplan-docker/xplan-docker-volume-init/setupVolumes.sh b/xplan-docker/xplan-docker-volume-init/setupVolumes.sh index ad5e4587a..2f93825aa 100755 --- a/xplan-docker/xplan-docker-volume-init/setupVolumes.sh +++ b/xplan-docker/xplan-docker-volume-init/setupVolumes.sh @@ -130,10 +130,14 @@ find xplan-workspaces/xplan-manager-workspace/datasources/feature -iname *.xml - find xplan-workspaces/xplan-services-wfs-workspace/datasources/feature -iname *.xml -exec sed -i 's|<StorageCRS srid="25832"|<StorageCRS srid="'$XPLAN_SERVICES_DEFAULT_CRS_SRID'"|g' {} \; find xplan-workspaces/xplan-services-wms-workspace/datasources/feature -iname *.xml -exec sed -i 's|<StorageCRS srid="25832"|<StorageCRS srid="'$XPLAN_SERVICES_DEFAULT_CRS_SRID'"|g' {} \; find xplan-workspaces/xplan-services-wfs-syn-workspace/datasources/feature -iname *.xml -exec sed -i 's|<StorageCRS srid="25832"|<StorageCRS srid="'$XPLAN_SERVICES_DEFAULT_CRS_SRID'"|g' {} \; +find xplan-validator-workspaces/xplan-validator-workspace/datasources/feature -iname *.xml -exec sed -i 's|<StorageCRS srid="25832"|<StorageCRS srid="'$XPLAN_SERVICES_DEFAULT_CRS_SRID'"|g' {} \; +find xplan-validator-workspaces/xplan-webservices-validator-wms-workspace/datasources/feature -iname *.xml -exec sed -i 's|<StorageCRS srid="25832"|<StorageCRS srid="'$XPLAN_SERVICES_DEFAULT_CRS_SRID'"|g' {} \; find xplan-workspaces/xplan-manager-workspace/datasources/feature -iname *.xml -exec sed -i 's|EPSG:25832</StorageCRS>|'$XPLAN_SERVICES_DEFAULT_CRS'</StorageCRS>|g' {} \; find xplan-workspaces/xplan-services-wfs-workspace/datasources/feature -iname *.xml -exec sed -i 's|EPSG:25832</StorageCRS>|'$XPLAN_SERVICES_DEFAULT_CRS'</StorageCRS>|g' {} \; find xplan-workspaces/xplan-services-wms-workspace/datasources/feature -iname *.xml -exec sed -i 's|EPSG:25832</StorageCRS>|'$XPLAN_SERVICES_DEFAULT_CRS'</StorageCRS>|g' {} \; find xplan-workspaces/xplan-services-wfs-syn-workspace/datasources/feature -iname *.xml -exec sed -i 's|EPSG:25832</StorageCRS>|'$XPLAN_SERVICES_DEFAULT_CRS'</StorageCRS>|g' {} \; +find xplan-validator-workspaces/xplan-validator-workspace/datasources/feature -iname *.xml -exec sed -i 's|EPSG:25832</StorageCRS>|'$XPLAN_SERVICES_DEFAULT_CRS'</StorageCRS>|g' {} \; +find xplan-validator-workspaces/xplan-webservices-validator-wms-workspace/datasources/feature -iname *.xml -exec sed -i 's|EPSG:25832</StorageCRS>|'$XPLAN_SERVICES_DEFAULT_CRS'</StorageCRS>|g' {} \; echo "[$(date -Iseconds)] Configure XPlanWMS CRS" find xplan-workspaces/xplan-services-wms-workspace/themes -iname *.xml -exec sed -i 's/<s:CRS>EPSG:25832 EPSG:25833 EPSG:31466 EPSG:31467 EPSG:31468 EPSG:31469 EPSG:4258 EPSG:4326 CRS:84 EPSG:4839<\/s:CRS>/<s:CRS>'"$XPLAN_SERVICES_DEFAULT_CRS $( echo ${XPLAN_SERVICES_QUERY_CRS_ARR[@]} )"'<\/s:CRS>/g' {} \; find xplan-workspaces/xplan-services-wms-workspace/themes -iname *raster.xml -exec sed -i 's|<s:CRS>EPSG:25832</s:CRS>|<s:CRS>'$XPLAN_SERVICES_DEFAULT_CRS'</s:CRS>|g' {} \; @@ -184,7 +188,7 @@ find xplan-workspaces/xplan-services-wfs-syn-workspace/services -iname xplansynw # Rastertype echo "[$(date -Iseconds)] Configure rastertype mapserver" -sed -i 's|http://localhost:8080/mapserver?|'$XPLAN_MAPSERVER_URL_INTERNAL'/mapserver?map=/etc/mapserver/internal.map\&|g' xplan-workspaces/xplan-services-wms-workspace/datasources/remoteows/mapserver.xml +sed -i 's|http://localhost:8080/xplan-mapserver?|'$XPLAN_MAPSERVER_URL_INTERNAL'/xplan-mapserver?map=/etc/mapserver/internal.map\&|g' xplan-workspaces/xplan-services-wms-workspace/datasources/remoteows/mapserver.xml #copy example external codelist XPLAN_INIT_EXAMPLE_CODELIST="${XPLAN_INIT_EXAMPLE_CODELIST:-disabled}" diff --git a/xplan-dokumente/xplan-dokumente-api/Dockerfile b/xplan-dokumente/xplan-dokumente-api/Dockerfile index c208683de..b5e7237e0 100644 --- a/xplan-dokumente/xplan-dokumente-api/Dockerfile +++ b/xplan-dokumente/xplan-dokumente-api/Dockerfile @@ -32,7 +32,6 @@ COPY --from=builder $JMX_EXPORTER_DIR $JMX_EXPORTER_DIR # set environment variables ENV JAVA_ADDITIONAL_ARG_APP="-Duser.timezone=Europe/Berlin" \ JAVA_ADDITIONAL_ARG_JAVA17_EXPORTS="--add-exports=java.desktop/com.sun.imageio.spi=ALL-UNNAMED" \ - JAVA_ADDITIONAL_ARG_DISABLE_AWS_DEPRECATION="-Daws.java.v1.disableDeprecationAnnouncement=true" \ JAVA_ADDITIONAL_ARG_JMX_EXPORTER='-javaagent:$JMX_EXPORTER_DIR/jmx_prometheus_javaagent-1.0.1.jar=12345:$JMX_EXPORTER_DIR/jmx-exporter.config.yaml' \ XPLANBOX_CONFIG="/xplanbox/xplan-dokumente-config/" diff --git a/xplan-dokumente/xplan-dokumente-api/pom.xml b/xplan-dokumente/xplan-dokumente-api/pom.xml index 8a4fdff7a..9d2ebf99c 100755 --- a/xplan-dokumente/xplan-dokumente-api/pom.xml +++ b/xplan-dokumente/xplan-dokumente-api/pom.xml @@ -287,7 +287,7 @@ <id>docker</id> <properties> <docker-image.skip>false</docker-image.skip> - <docker-contextTarFile.expectedSizeInMat10pct>112</docker-contextTarFile.expectedSizeInMat10pct> + <docker-contextTarFile.expectedSizeInMat10pct>126</docker-contextTarFile.expectedSizeInMat10pct> </properties> <dependencies> <dependency> <!-- faked maven dependency to be after base docker image in the reactor build --> diff --git a/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/config/S3DocumentContext.java b/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/config/S3DocumentContext.java index c3e0e9d1c..3c463f0ab 100644 --- a/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/config/S3DocumentContext.java +++ b/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/config/S3DocumentContext.java @@ -22,7 +22,6 @@ package de.latlon.xplanbox.api.dokumente.config; import static org.slf4j.LoggerFactory.getLogger; -import com.amazonaws.services.s3.AmazonS3; import de.latlon.xplan.commons.s3.S3Storage; import de.latlon.xplan.commons.s3.config.AmazonS3ReadOnlyContext; import org.slf4j.Logger; @@ -30,6 +29,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import software.amazon.awssdk.services.s3.S3Client; /** * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> @@ -42,7 +42,7 @@ public class S3DocumentContext { private static final Logger LOG = getLogger(S3DocumentContext.class); @Bean - public S3Storage documentStorage(AmazonS3 s3Client, + public S3Storage documentStorage(S3Client s3Client, @Value("${xplanbox.s3.bucketName:#{environment.XPLAN_S3_BUCKET_ATTACHMENTS}}") String bucketName) { LOG.info("Instantiate S3Storage to manage documents"); return new S3Storage(s3Client, bucketName); diff --git a/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/service/s3/S3DocumentService.java b/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/service/s3/S3DocumentService.java index 5a6d4c04a..4851028a7 100644 --- a/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/service/s3/S3DocumentService.java +++ b/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/service/s3/S3DocumentService.java @@ -26,11 +26,6 @@ import java.io.ByteArrayInputStream; import java.util.List; import java.util.stream.Collectors; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import com.amazonaws.services.s3.model.S3ObjectSummary; - import de.latlon.xplan.commons.s3.S3Metadata; import de.latlon.xplan.commons.s3.S3Object; import de.latlon.xplan.commons.s3.S3Storage; @@ -41,6 +36,8 @@ import de.latlon.xplanbox.api.dokumente.service.DocumentHeaderWithStream; import de.latlon.xplanbox.api.dokumente.service.DocumentService; import de.latlon.xplanbox.api.dokumente.v1.model.Document; import jakarta.ws.rs.core.StreamingOutput; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; /** * Implementation of a {@link DocumentService} retrieving the documents from S3. @@ -57,9 +54,9 @@ public class S3DocumentService implements DocumentService { @Override public List<Document> listDocuments(int planId) { String prefix = planId + "_"; - List<S3ObjectSummary> s3ObjectSummaries = documentStorage.listObjects(prefix); + List<software.amazon.awssdk.services.s3.model.S3Object> s3ObjectSummaries = documentStorage.listObjects(prefix); return s3ObjectSummaries.stream() - .map(s3ObjectSummary -> new Document().fileName(s3ObjectSummary.getKey().replaceFirst(prefix, ""))) + .map(s3ObjectSummary -> new Document().fileName(s3ObjectSummary.key().replaceFirst(prefix, ""))) .collect(Collectors.toList()); } diff --git a/xplan-dokumente/xplan-dokumente-api/src/test/java/de/latlon/xplanbox/api/dokumente/config/TestS3Context.java b/xplan-dokumente/xplan-dokumente-api/src/test/java/de/latlon/xplanbox/api/dokumente/config/TestS3Context.java index 59ed360db..6ead8f656 100644 --- a/xplan-dokumente/xplan-dokumente-api/src/test/java/de/latlon/xplanbox/api/dokumente/config/TestS3Context.java +++ b/xplan-dokumente/xplan-dokumente-api/src/test/java/de/latlon/xplanbox/api/dokumente/config/TestS3Context.java @@ -8,32 +8,36 @@ * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ package de.latlon.xplanbox.api.dokumente.config; -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.AnonymousAWSCredentials; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.client.builder.AwsClientBuilder; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import static software.amazon.awssdk.regions.Region.EU_CENTRAL_1; + +import java.net.URI; +import java.net.URISyntaxException; + import io.findify.s3mock.S3Mock; import jakarta.annotation.PreDestroy; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; import org.springframework.test.util.TestSocketUtils; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.S3Configuration; +import software.amazon.awssdk.services.s3.model.CreateBucketRequest; /** * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> @@ -44,11 +48,12 @@ public class TestS3Context { private final int port = TestSocketUtils.findAvailableTcpPort(); - private AmazonS3 s3TestClient; + private S3Client s3TestClient; private S3Mock s3Mock; @Bean + @Profile("mock") public S3Mock s3Mock() { this.s3Mock = new S3Mock.Builder().withPort(port).withInMemoryBackend().build(); s3Mock.start(); @@ -57,28 +62,25 @@ public class TestS3Context { @Bean @Primary - public AmazonS3 s3Client(S3Mock s3Mock, @Value("${xplanbox.s3.bucketName}") String bucketName) { - AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration( - "http://localhost:" + port, "eu-central-1"); - AmazonS3 client = AmazonS3ClientBuilder.standard() - .withPathStyleAccessEnabled(true) - .withEndpointConfiguration(endpoint) - .withCredentials(new AWSStaticCredentialsProvider(new AnonymousAWSCredentials())) + @Profile("mock") + public S3Client s3Client(S3Mock s3Mock, @Value("${xplanbox.s3.bucketName}") String bucketName) + throws URISyntaxException { + URI endpoint = new URI("http://localhost:" + port); + S3Client client = S3Client.builder() + .serviceConfiguration(S3Configuration.builder().pathStyleAccessEnabled(true).build()) + .endpointOverride(endpoint) + .credentialsProvider( + StaticCredentialsProvider.create(AwsBasicCredentials.create("accessKeyId", "secretKey"))) + .region(EU_CENTRAL_1) .build(); - client.createBucket(bucketName); + client.createBucket(CreateBucketRequest.builder().bucket(bucketName).build()); s3TestClient = client; return client; } - @Bean - @Primary - public AWSCredentials credentials() { - return new BasicAWSCredentials("accessKeyId", "secretKey"); - } - @PreDestroy public void shutdown() { - s3TestClient.shutdown(); + s3TestClient.close(); if (s3Mock != null) { s3Mock.stop(); } diff --git a/xplan-dokumente/xplan-dokumente-api/src/test/java/de/latlon/xplanbox/api/dokumente/handler/DocumentHandlerTest.java b/xplan-dokumente/xplan-dokumente-api/src/test/java/de/latlon/xplanbox/api/dokumente/handler/DocumentHandlerTest.java index 5f8ae0141..8eae5c891 100644 --- a/xplan-dokumente/xplan-dokumente-api/src/test/java/de/latlon/xplanbox/api/dokumente/handler/DocumentHandlerTest.java +++ b/xplan-dokumente/xplan-dokumente-api/src/test/java/de/latlon/xplanbox/api/dokumente/handler/DocumentHandlerTest.java @@ -8,12 +8,12 @@ * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% @@ -39,13 +39,6 @@ import java.util.List; import java.util.Objects; import java.util.zip.GZIPOutputStream; -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.AnonymousAWSCredentials; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.client.builder.AwsClientBuilder; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; import de.latlon.xplan.commons.s3.S3Storage; import de.latlon.xplan.core.manager.db.model.Artefact; import de.latlon.xplan.core.manager.db.model.ArtefactId; @@ -57,23 +50,19 @@ import de.latlon.xplanbox.api.commons.exception.InvalidPlanId; import de.latlon.xplanbox.api.commons.exception.InvalidPlanIdSyntax; import de.latlon.xplanbox.api.dokumente.config.ApplicationContext; import de.latlon.xplanbox.api.dokumente.config.HsqlJpaContext; +import de.latlon.xplanbox.api.dokumente.config.TestS3Context; import de.latlon.xplanbox.api.dokumente.exception.InvalidDocument; import de.latlon.xplanbox.api.dokumente.service.DocumentHeader; import de.latlon.xplanbox.api.dokumente.service.DocumentHeaderWithStream; import de.latlon.xplanbox.api.dokumente.v1.model.Document; -import io.findify.s3mock.S3Mock; -import jakarta.annotation.PreDestroy; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Primary; import org.springframework.test.annotation.Commit; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.test.util.TestSocketUtils; import org.springframework.transaction.annotation.Transactional; /** @@ -81,59 +70,12 @@ import org.springframework.transaction.annotation.Transactional; * @since 7.0 */ @ExtendWith(SpringExtension.class) -@ContextConfiguration( - classes = { ApplicationContext.class, HsqlJpaContext.class, DocumentHandlerTest.TestConfig.class }) +@ContextConfiguration(classes = { ApplicationContext.class, HsqlJpaContext.class, TestS3Context.class }) @Transactional -@TestPropertySource(properties = "xplanbox.s3.bucketName=my-test-bucket") +@TestPropertySource("classpath:s3Mock.properties") +@ActiveProfiles({ "mock", "test" }) class DocumentHandlerTest { - static class TestConfig { - - private final int port = TestSocketUtils.findAvailableTcpPort(); - - private AmazonS3 s3TestClient; - - @Autowired - private S3Mock s3Mock; - - @Bean - public S3Mock s3Mock() { - S3Mock s3Mock = new S3Mock.Builder().withPort(port).withInMemoryBackend().build(); - s3Mock.start(); - return s3Mock; - } - - @Bean - @Primary - public AmazonS3 s3Client(S3Mock s3Mock, @Value("${xplanbox.s3.bucketName}") String bucketName) { - AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration( - "http://localhost:" + port, "eu-central-1"); - AmazonS3 client = AmazonS3ClientBuilder.standard() - .withPathStyleAccessEnabled(true) - .withEndpointConfiguration(endpoint) - .withCredentials(new AWSStaticCredentialsProvider(new AnonymousAWSCredentials())) - .build(); - client.createBucket(bucketName); - s3TestClient = client; - return client; - } - - @Bean - @Primary - public AWSCredentials credentials() { - return new BasicAWSCredentials("accessKeyId", "secretKey"); - } - - @PreDestroy - public void shutdown() { - s3TestClient.shutdown(); - if (s3Mock != null) { - s3Mock.stop(); - } - } - - } - @Autowired private DocumentHandler documentHandler; diff --git a/xplan-dokumente/xplan-dokumente-api/src/test/java/de/latlon/xplanbox/api/dokumente/v1/DokumenteApiJerseyTest.java b/xplan-dokumente/xplan-dokumente-api/src/test/java/de/latlon/xplanbox/api/dokumente/v1/DokumenteApiJerseyTest.java index 7656b1028..b94e813ef 100644 --- a/xplan-dokumente/xplan-dokumente-api/src/test/java/de/latlon/xplanbox/api/dokumente/v1/DokumenteApiJerseyTest.java +++ b/xplan-dokumente/xplan-dokumente-api/src/test/java/de/latlon/xplanbox/api/dokumente/v1/DokumenteApiJerseyTest.java @@ -52,6 +52,7 @@ public abstract class DokumenteApiJerseyTest<T> extends JerseyTest { Map<String, Object> map = Collections.singletonMap("xplanbox.s3.bucketName", "test-bucket"); PropertySource<?> propertySource = new MapPropertySource("dokumente-api", map); env.getPropertySources().addLast(propertySource); + env.setActiveProfiles("mock", "test"); context.setEnvironment(env); context.register(ApplicationContext.class, TestContext.class); context.refresh(); diff --git a/xplan-dokumente/xplan-dokumente-api/src/test/resources/s3Mock.properties b/xplan-dokumente/xplan-dokumente-api/src/test/resources/s3Mock.properties new file mode 100644 index 000000000..32c458100 --- /dev/null +++ b/xplan-dokumente/xplan-dokumente-api/src/test/resources/s3Mock.properties @@ -0,0 +1,25 @@ +### +# #%L +# xplan-manager-core - XPlan Manager Core Komponente +# %% +# Copyright (C) 2008 - 2025 Freie und Hansestadt Hamburg, developed by lat/lon gesellschaft für raumbezogene Informationssysteme mbH +# %% +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# #L% +### +xplanbox.s3.accessKeyId= +xplanbox.s3.secretKey= +xplanbox.s3.bucketName=latlonxpbtest +xplanbox.s3.region=eu-central-1 +xplanbox.s3.endpoint.url=http://localhost diff --git a/xplan-manager/xplan-manager-api/Dockerfile b/xplan-manager/xplan-manager-api/Dockerfile index 1214b0cbd..1e7c0d14c 100644 --- a/xplan-manager/xplan-manager-api/Dockerfile +++ b/xplan-manager/xplan-manager-api/Dockerfile @@ -32,7 +32,6 @@ COPY --from=builder $JMX_EXPORTER_DIR $JMX_EXPORTER_DIR ENV DEEGREE_WORKSPACE_ROOT=/xplanbox/deegree \ JAVA_ADDITIONAL_ARG_APP="-Djavax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl -Djts.overlay=ng -Duser.timezone=Europe/Berlin" \ JAVA_ADDITIONAL_ARG_JAVA17_EXPORTS="--add-exports=java.desktop/com.sun.imageio.spi=ALL-UNNAMED" \ - JAVA_ADDITIONAL_ARG_DISABLE_AWS_DEPRECATION="-Daws.java.v1.disableDeprecationAnnouncement=true" \ JAVA_ADDITIONAL_ARG_JMX_EXPORTER='-javaagent:$JMX_EXPORTER_DIR/jmx_prometheus_javaagent-1.0.1.jar=12345:$JMX_EXPORTER_DIR/jmx-exporter.config.yaml' \ XPLANBOX_CONFIG="/xplanbox/xplan-manager-config/" diff --git a/xplan-manager/xplan-manager-api/pom.xml b/xplan-manager/xplan-manager-api/pom.xml index 4b4dbbc6f..31284b718 100644 --- a/xplan-manager/xplan-manager-api/pom.xml +++ b/xplan-manager/xplan-manager-api/pom.xml @@ -348,7 +348,7 @@ <id>docker</id> <properties> <docker-image.skip>false</docker-image.skip> - <docker-contextTarFile.expectedSizeInMat10pct>119</docker-contextTarFile.expectedSizeInMat10pct> + <docker-contextTarFile.expectedSizeInMat10pct>133</docker-contextTarFile.expectedSizeInMat10pct> </properties> <dependencies> <dependency> <!-- faked maven dependency to be after base docker image in the reactor build --> diff --git a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/ManagerApiJerseyTest.java b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/ManagerApiJerseyTest.java index 306943a35..8f6288fe8 100644 --- a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/ManagerApiJerseyTest.java +++ b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/ManagerApiJerseyTest.java @@ -50,7 +50,7 @@ public abstract class ManagerApiJerseyTest<T> extends JerseyTest { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); PropertySourcesPlaceholderConfigurer pph = new PropertySourcesPlaceholderConfigurer(); pph.setLocations(new ClassPathResource("/application.properties"), new ClassPathResource("/s3Mock.properties")); - context.getEnvironment().setActiveProfiles("test"); + context.getEnvironment().setActiveProfiles("mock", "test"); context.addBeanFactoryPostProcessor(pph); context.register(ApplicationContext.class, HsqlJpaContext.class, TestContext.class); context.refresh(); diff --git a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/config/TestS3Context.java b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/config/TestS3Context.java index bfb6cab5d..74785187f 100644 --- a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/config/TestS3Context.java +++ b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/config/TestS3Context.java @@ -8,34 +8,40 @@ * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ package de.latlon.xplanbox.api.manager.config; -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.AnonymousAWSCredentials; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.client.builder.AwsClientBuilder; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import static software.amazon.awssdk.regions.Region.EU_CENTRAL_1; + +import java.net.URI; +import java.net.URISyntaxException; + import io.findify.s3mock.S3Mock; import jakarta.annotation.PreDestroy; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; import org.springframework.test.util.TestSocketUtils; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.S3Configuration; +import software.amazon.awssdk.services.s3.model.CreateBucketRequest; /** + * Spring Configuration to enable usage of mock objects for integration tests. + * * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> * @since 8.0 */ @@ -44,11 +50,12 @@ public class TestS3Context { private final int port = TestSocketUtils.findAvailableTcpPort(); - private AmazonS3 s3TestClient; + private S3Client s3TestClient; private S3Mock s3Mock; @Bean + @Profile("mock") public S3Mock s3Mock() { this.s3Mock = new S3Mock.Builder().withPort(port).withInMemoryBackend().build(); s3Mock.start(); @@ -57,28 +64,25 @@ public class TestS3Context { @Bean @Primary - public AmazonS3 s3Client(S3Mock s3Mock, @Value("${xplanbox.s3.bucketName}") String bucketName) { - AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration( - "http://localhost:" + port, "eu-central-1"); - AmazonS3 client = AmazonS3ClientBuilder.standard() - .withPathStyleAccessEnabled(true) - .withEndpointConfiguration(endpoint) - .withCredentials(new AWSStaticCredentialsProvider(new AnonymousAWSCredentials())) + @Profile("mock") + public S3Client s3Client(S3Mock s3Mock, @Value("${xplanbox.s3.bucketName}") String bucketName) + throws URISyntaxException { + URI endpoint = new URI("http://localhost:" + port); + S3Client client = S3Client.builder() + .serviceConfiguration(S3Configuration.builder().pathStyleAccessEnabled(true).build()) + .endpointOverride(endpoint) + .credentialsProvider( + StaticCredentialsProvider.create(AwsBasicCredentials.create("accessKeyId", "secretKey"))) + .region(EU_CENTRAL_1) .build(); - client.createBucket(bucketName); + client.createBucket(CreateBucketRequest.builder().bucket(bucketName).build()); s3TestClient = client; return client; } - @Bean - @Primary - public AWSCredentials credentials() { - return new BasicAWSCredentials("accessKeyId", "secretKey"); - } - @PreDestroy public void shutdown() { - s3TestClient.shutdown(); + s3TestClient.close(); if (s3Mock != null) { s3Mock.stop(); } diff --git a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/executor/PlanImporterTest.java b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/executor/PlanImporterTest.java index 7f906756c..e895ac979 100644 --- a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/executor/PlanImporterTest.java +++ b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/executor/PlanImporterTest.java @@ -67,7 +67,7 @@ import org.xmlunit.assertj.XmlAssert; @SpringBootTest(classes = { PlanImporter.class }) @ContextConfiguration(classes = { ApplicationContext.class, HsqlJpaContext.class, TestContext.class }) @TestPropertySource(value = "/s3Mock.properties", properties = "spring.main.allow-bean-definition-overriding=true") -@ActiveProfiles("test") +@ActiveProfiles({ "mock", "test" }) public class PlanImporterTest { @Autowired diff --git a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/handler/EditBasisdatenHandlerTest.java b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/handler/EditBasisdatenHandlerTest.java index 93da5890f..21ab786b6 100644 --- a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/handler/EditBasisdatenHandlerTest.java +++ b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/handler/EditBasisdatenHandlerTest.java @@ -41,7 +41,7 @@ import org.springframework.test.context.TestPropertySource; @SpringBootTest @ContextConfiguration(classes = { ApplicationContext.class, HsqlJpaContext.class, TestContext.class }) @TestPropertySource(value = "/s3Mock.properties", properties = "spring.main.allow-bean-definition-overriding=true") -@ActiveProfiles("test") +@ActiveProfiles({ "test", "mock" }) class EditBasisdatenHandlerTest { @Autowired diff --git a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/handler/PlanHandlerTest.java b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/handler/PlanHandlerTest.java index e07161290..e5ba8a55a 100644 --- a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/handler/PlanHandlerTest.java +++ b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/handler/PlanHandlerTest.java @@ -47,7 +47,7 @@ import org.springframework.test.context.TestPropertySource; @SpringBootTest @ContextConfiguration(classes = { ApplicationContext.class, HsqlJpaContext.class, TestContext.class }) @TestPropertySource(value = "/s3Mock.properties", properties = "spring.main.allow-bean-definition-overriding=true") -@ActiveProfiles("test") +@ActiveProfiles({ "test", "mock" }) class PlanHandlerTest { @Autowired diff --git a/xplan-manager/xplan-manager-web/Dockerfile b/xplan-manager/xplan-manager-web/Dockerfile index 128e5b1c6..3fc34ba2b 100644 --- a/xplan-manager/xplan-manager-web/Dockerfile +++ b/xplan-manager/xplan-manager-web/Dockerfile @@ -23,7 +23,6 @@ LABEL "org.opencontainers.image.created"="$BUILD_DATE" \ ENV DEEGREE_WORKSPACE_ROOT=/xplanbox/deegree \ TOMCAT_ADDITIONAL_ARG_APP="-Djavax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl -Djts.overlay=ng -Duser.timezone=Europe/Berlin" \ TOMCAT_ADDITIONAL_ARG_JAVA17_EXPORTS="--add-exports=java.desktop/com.sun.imageio.spi=ALL-UNNAMED" \ - TOMCAT_ADDITIONAL_ARG_DISABLE_AWS_DEPRECATION="-Daws.java.v1.disableDeprecationAnnouncement=true" \ XPLANBOX_CONFIG="/xplanbox/xplan-manager-config/" USER root diff --git a/xplan-manager/xplan-manager-web/pom.xml b/xplan-manager/xplan-manager-web/pom.xml index 30be0a16e..1f61700a2 100644 --- a/xplan-manager/xplan-manager-web/pom.xml +++ b/xplan-manager/xplan-manager-web/pom.xml @@ -277,7 +277,7 @@ <id>docker</id> <properties> <docker-image.skip>false</docker-image.skip> - <docker-contextTarFile.expectedSizeInMat10pct>100</docker-contextTarFile.expectedSizeInMat10pct> + <docker-contextTarFile.expectedSizeInMat10pct>112</docker-contextTarFile.expectedSizeInMat10pct> </properties> <dependencies> <dependency> <!-- faked maven dependency to be after base docker image in the reactor build --> diff --git a/xplan-tests/xplan-tests-soapui/README.md b/xplan-tests/xplan-tests-soapui/README.md index 8b083486c..40277aef6 100644 --- a/xplan-tests/xplan-tests-soapui/README.md +++ b/xplan-tests/xplan-tests-soapui/README.md @@ -21,7 +21,6 @@ Bei Nutzung der Absicherung über ein Bearer Token muss zusätzlich die URL von ``` mvn clean test -Psystem-tests -DtestFileName=xplan-manager-api-soapui-project.xml \ -DbaseUrlManagerApi=https://xplanbox.lat-lon.de -Dusername=xplanbox -Dpassword='PWD' \ - -DbaseUrlServices=https://xplanbox.lat-lon.de \ -DjdbcUrl=jdbc:postgresql://localhost:5433/xplanbox?user=xplanbox&password=xplanbox ``` @@ -89,7 +88,7 @@ docker run --env ... xplanbox/xplan-tests-soapui - `XPLAN_DIENSTE_BASE_URL` - `XPLAN_DIENSTE_USERNAME` - `XPLAN_DIENSTE_PASSWORD` -- `XPLAN_DOKUMENTE_API_BASE_URL` - optional: XPlanDokumenteAPI Tests werden geskipped, wenn die Umgebungsvariable nicht gesetzt ist. +- `XPLAN_DOKUMENTE_API_BASE_URL` - optional: XPlanDokumenteAPI Tests werden übersprungen, wenn die Umgebungsvariable nicht gesetzt ist. - `XPLAN_DOKUMENTE_API_USERNAME` - `XPLAN_DOKUMENTE_API_PASSWORD` - `XPLAN_BASE_URL_INSPIRE_PLU` diff --git a/xplan-tests/xplan-tests-soapui/runAllSoapUiTests.sh b/xplan-tests/xplan-tests-soapui/runAllSoapUiTests.sh index 50bfb8ebb..79fe31297 100755 --- a/xplan-tests/xplan-tests-soapui/runAllSoapUiTests.sh +++ b/xplan-tests/xplan-tests-soapui/runAllSoapUiTests.sh @@ -66,7 +66,6 @@ mvn test -Psystem-tests -DtestFileName=xplan-manager-api-soapui-project.xml \ -DbaseUrlManagerApi=$XPLAN_MANAGER_API_BASE_URL \ -Dusername=$XPLAN_MANAGER_API_USERNAME -Dpassword=$XPLAN_MANAGER_API_PASSWORD \ -DjwtUrl=$XPLAN_JWT_URL -DjwtClientId=$XPLAN_JWT_CLIENTID \ - -DbaseUrlServices=$XPLAN_DIENSTE_BASE_URL \ -DjdbcUrl=$JDBC_URL mvn test -Psystem-tests -DtestFileName=xplan-validator-api-soapui-project.xml \ diff --git a/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-dokumente-api-soapui-project.xml b/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-dokumente-api-soapui-project.xml index 6c7d93439..176683e0f 100644 --- a/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-dokumente-api-soapui-project.xml +++ b/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-dokumente-api-soapui-project.xml @@ -17,7 +17,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. #L%--> -<con:soapui-project id="c0330194-e671-4de1-89fb-fd5cd92eb5af" activeEnvironment="Default" name="xplan-dokumente-api" resourceRoot="" soapui-version="5.7.2" abortOnError="false" runType="SEQUENTIAL" xmlns:con="http://eviware.com/soapui/config"> +<con:soapui-project id="c0330194-e671-4de1-89fb-fd5cd92eb5af" activeEnvironment="Default" name="xplan-dokumente-api" resourceRoot="" soapui-version="5.8.0" abortOnError="false" runType="SEQUENTIAL" xmlns:con="http://eviware.com/soapui/config"> <con:description>For local execution use following property values: baseUrlManagerApi=http://localhost:8086/xplan-manager-api @@ -1789,4 +1789,4 @@ testRunner.testCase.testSuite.project.testSuiteList.each <con:oAuth2ProfileContainer/> <con:oAuth1ProfileContainer/> <con:sensitiveInformation/> -</con:soapui-project> +</con:soapui-project> \ No newline at end of file diff --git a/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-loadtests-soapui-project.xml b/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-loadtests-soapui-project.xml index 7b44ac4c6..8795facaa 100644 --- a/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-loadtests-soapui-project.xml +++ b/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-loadtests-soapui-project.xml @@ -17,7 +17,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. #L%--> -<con:soapui-project id="d87c2df2-24ee-4f03-93eb-b6af824e4cc9" activeEnvironment="Default" name="xplan-loadtests" resourceRoot="" soapui-version="5.7.2" abortOnError="false" runType="SEQUENTIAL" xmlns:con="http://eviware.com/soapui/config"> +<con:soapui-project id="d87c2df2-24ee-4f03-93eb-b6af824e4cc9" activeEnvironment="Default" name="xplan-loadtests" resourceRoot="" soapui-version="5.8.0" abortOnError="false" runType="SEQUENTIAL" xmlns:con="http://eviware.com/soapui/config"> <con:settings/> <con:testSuite id="701c0614-03fd-48eb-87a0-3bf0acbc151a" name="ImportAndPlanList"> <con:settings/> @@ -237,4 +237,4 @@ <con:oAuth2ProfileContainer/> <con:oAuth1ProfileContainer/> <con:sensitiveInformation/> -</con:soapui-project> +</con:soapui-project> \ No newline at end of file diff --git a/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-manager-api-soapui-project.xml b/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-manager-api-soapui-project.xml index 13bc028c3..825545aa5 100644 --- a/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-manager-api-soapui-project.xml +++ b/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-manager-api-soapui-project.xml @@ -17,7 +17,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. #L%--> -<con:soapui-project id="adcdfd3f-0f4e-4107-8d7e-086010676cb7" activeEnvironment="Default" name="xplan-manager-api" resourceRoot="" soapui-version="5.7.2" abortOnError="false" runType="SEQUENTIAL" xmlns:con="http://eviware.com/soapui/config"> +<con:soapui-project id="adcdfd3f-0f4e-4107-8d7e-086010676cb7" activeEnvironment="Default" name="xplan-manager-api" resourceRoot="" soapui-version="5.8.0" abortOnError="false" runType="SEQUENTIAL" xmlns:con="http://eviware.com/soapui/config"> <con:description>For local execution use following property values: baseUrlManagerApi=http://localhost:8086 diff --git a/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-validator-api-soapui-project.xml b/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-validator-api-soapui-project.xml index 0d191c639..3170c81e2 100644 --- a/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-validator-api-soapui-project.xml +++ b/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-validator-api-soapui-project.xml @@ -17,7 +17,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. #L%--> -<con:soapui-project id="45582ef9-4bae-43d8-9226-a378e02ff0b5" activeEnvironment="Default" name="xplan-validator-api" resourceRoot="" soapui-version="5.7.2" abortOnError="false" runType="SEQUENTIAL" xmlns:con="http://eviware.com/soapui/config"> +<con:soapui-project id="45582ef9-4bae-43d8-9226-a378e02ff0b5" activeEnvironment="Default" name="xplan-validator-api" resourceRoot="" soapui-version="5.8.0" abortOnError="false" runType="SEQUENTIAL" xmlns:con="http://eviware.com/soapui/config"> <con:description>Set this if Keycloak authentication shall be used locally: jwtUrl=http://localhost:8096/keycloak/realms/xplanbox/protocol/openid-connect/token diff --git a/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-webservices-soapui-project.xml b/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-webservices-soapui-project.xml index 08b620508..b5a97056b 100644 --- a/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-webservices-soapui-project.xml +++ b/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-webservices-soapui-project.xml @@ -17,7 +17,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. #L%--> -<con:soapui-project id="4497dcb6-2c5f-4d87-bcee-3913ada70576" activeEnvironment="Default" name="xplan-webservices" resourceRoot="" soapui-version="5.7.2" abortOnError="false" runType="SEQUENTIAL" defaultScriptLanguage="Groovy" xmlns:con="http://eviware.com/soapui/config"> +<con:soapui-project id="4497dcb6-2c5f-4d87-bcee-3913ada70576" activeEnvironment="Default" name="xplan-webservices" resourceRoot="" soapui-version="5.8.0" abortOnError="false" runType="SEQUENTIAL" defaultScriptLanguage="Groovy" xmlns:con="http://eviware.com/soapui/config"> <con:description>For local execution use following property values: baseUrlServices=http://localhost:8083 @@ -16150,7 +16150,7 @@ exists(/wfs:WFS_Capabilities)</path> <con:settings> <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers"><xml-fragment/></con:setting> </con:settings> - <con:endpoint>${#Project#baseUrlMapServer}/mapserver.cgi</con:endpoint> + <con:endpoint>${#Project#baseUrlMapServer}/xplan-mapserver</con:endpoint> <con:request/> <con:assertion type="Valid HTTP Status Codes" id="2b2dc1c4-d8c4-4308-8c53-f98536940634" name="Valid HTTP Status Codes"> <con:configuration> @@ -16174,7 +16174,7 @@ exists(/wms:WMS_Capabilities)</path> declare namespace xlink='http://www.w3.org/1999/xlink'; /wms:WMS_Capabilities/wms:Capability/wms:Request/wms:GetCapabilities/wms:DCPType/wms:HTTP/wms:Get/wms:OnlineResource/@xlink:href</path> - <content>${#Project#baseUrlMapServer}/mapserver.cgi?</content> + <content>${#Project#baseUrlMapServer}/xplan-mapserver?</content> <allowWildcards>false</allowWildcards> <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences> <ignoreComments>false</ignoreComments> @@ -16385,7 +16385,7 @@ declare namespace xlink='http://www.w3.org/1999/xlink'; <con:settings> <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers"><xml-fragment/></con:setting> </con:settings> - <con:endpoint>${#Project#baseUrlMapServer}/mapserver.cgi</con:endpoint> + <con:endpoint>${#Project#baseUrlMapServer}/xplan-mapserver</con:endpoint> <con:request/> <con:assertion type="Valid HTTP Status Codes" id="2b2dc1c4-d8c4-4308-8c53-f98536940634" name="Valid HTTP Status Codes"> <con:configuration> @@ -16406,7 +16406,7 @@ declare namespace xlink='http://www.w3.org/1999/xlink'; <path>declare namespace xlink='http://www.w3.org/1999/xlink'; /WMT_MS_Capabilities/Capability/Request/GetCapabilities/DCPType/HTTP/Get/OnlineResource/@xlink:href</path> - <content>${#Project#baseUrlMapServer}/mapserver.cgi?</content> + <content>${#Project#baseUrlMapServer}/xplan-mapserver?</content> <allowWildcards>false</allowWildcards> <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences> <ignoreComments>false</ignoreComments> @@ -16456,7 +16456,7 @@ declare namespace xlink='http://www.w3.org/1999/xlink'; <con:settings> <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers"><xml-fragment/></con:setting> </con:settings> - <con:endpoint>${#Project#baseUrlMapServer}/mapserver.cgi</con:endpoint> + <con:endpoint>${#Project#baseUrlMapServer}/xplan-mapserver</con:endpoint> <con:request/> <con:assertion type="Valid HTTP Status Codes" id="2b2dc1c4-d8c4-4308-8c53-f98536940634" name="Valid HTTP Status Codes"> <con:configuration> diff --git a/xplan-validator/xplan-validator-api/Dockerfile b/xplan-validator/xplan-validator-api/Dockerfile index 94b56f116..88a07d554 100644 --- a/xplan-validator/xplan-validator-api/Dockerfile +++ b/xplan-validator/xplan-validator-api/Dockerfile @@ -32,7 +32,6 @@ COPY --from=builder $JMX_EXPORTER_DIR $JMX_EXPORTER_DIR ENV DEEGREE_WORKSPACE_ROOT=/xplanbox/deegree \ JAVA_ADDITIONAL_ARG_APP="-Djavax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl -Djts.overlay=ng -Duser.timezone=Europe/Berlin" \ JAVA_ADDITIONAL_ARG_JAVA17_EXPORTS="--add-exports=java.desktop/com.sun.imageio.spi=ALL-UNNAMED" \ - JAVA_ADDITIONAL_ARG_DISABLE_AWS_DEPRECATION="-Daws.java.v1.disableDeprecationAnnouncement=true" \ JAVA_ADDITIONAL_ARG_JMX_EXPORTER='-javaagent:$JMX_EXPORTER_DIR/jmx_prometheus_javaagent-1.0.1.jar=12345:$JMX_EXPORTER_DIR/jmx-exporter.config.yaml' \ XPLANBOX_CONFIG="/xplanbox/xplan-validator-config/" diff --git a/xplan-validator/xplan-validator-api/pom.xml b/xplan-validator/xplan-validator-api/pom.xml index 1e7ef97a9..2df4838f6 100755 --- a/xplan-validator/xplan-validator-api/pom.xml +++ b/xplan-validator/xplan-validator-api/pom.xml @@ -261,8 +261,9 @@ <artifactId>xplan-core-validator-events</artifactId> </dependency> <dependency> - <groupId>com.amazonaws</groupId> - <artifactId>aws-java-sdk-s3</artifactId> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> + <version>2.30.10</version> </dependency> <dependency> <groupId>io.findify</groupId> @@ -275,7 +276,7 @@ <id>docker</id> <properties> <docker-image.skip>false</docker-image.skip> - <docker-contextTarFile.expectedSizeInMat10pct>91</docker-contextTarFile.expectedSizeInMat10pct> + <docker-contextTarFile.expectedSizeInMat10pct>101</docker-contextTarFile.expectedSizeInMat10pct> </properties> <dependencies> <dependency> <!-- to copy jmx exporter stuff from docker image --> diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/SpringBootAppTest.java b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/SpringBootAppTest.java index 4401ae5d9..147faf490 100644 --- a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/SpringBootAppTest.java +++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/SpringBootAppTest.java @@ -29,9 +29,8 @@ import org.springframework.test.context.TestPropertySource; @SpringBootTest @Import(TestContext.class) -@TestPropertySource(properties = { "spring.main.allow-bean-definition-overriding=true", - "xplanbox.s3.bucket.validation=test-bucket-validation" }) -@ActiveProfiles("test") +@ActiveProfiles({ "mock", "test" }) +@TestPropertySource(value = "/s3Mock.properties", properties = { "spring.main.allow-bean-definition-overriding=true" }) class SpringBootAppTest { @Test diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/ValidatorApiJerseyTest.java b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/ValidatorApiJerseyTest.java index f3be6da3a..87bdb7b1c 100644 --- a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/ValidatorApiJerseyTest.java +++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/ValidatorApiJerseyTest.java @@ -57,6 +57,7 @@ public abstract class ValidatorApiJerseyTest extends JerseyTest { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); PropertySourcesPlaceholderConfigurer pph = new PropertySourcesPlaceholderConfigurer(); pph.setLocations(new ClassPathResource("/application.properties"), new ClassPathResource("/s3Mock.properties")); + context.getEnvironment().setActiveProfiles("test", "mock"); context.addBeanFactoryPostProcessor(pph); context.register(ApplicationContext.class, TestContext.class); context.refresh(); diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/config/TestS3Context.java b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/config/TestS3Context.java index a28cdbfa5..1d1c74552 100644 --- a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/config/TestS3Context.java +++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/config/TestS3Context.java @@ -8,35 +8,40 @@ * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ package de.latlon.xplanbox.api.validator.config; -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.AnonymousAWSCredentials; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.client.builder.AwsClientBuilder; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import static software.amazon.awssdk.regions.Region.EU_CENTRAL_1; + +import java.net.URI; +import java.net.URISyntaxException; + import io.findify.s3mock.S3Mock; import jakarta.annotation.PreDestroy; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; import org.springframework.test.util.TestSocketUtils; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.S3Configuration; +import software.amazon.awssdk.services.s3.model.CreateBucketRequest; /** + * Spring Configuration to enable usage of mock objects for integration tests. + * * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> * @since 8.0 */ @@ -45,11 +50,12 @@ public class TestS3Context { private final int port = TestSocketUtils.findAvailableTcpPort(); - private AmazonS3 s3TestClient; + private S3Client s3TestClient; private S3Mock s3Mock; @Bean + @Profile("mock") public S3Mock s3Mock() { this.s3Mock = new S3Mock.Builder().withPort(port).withInMemoryBackend().build(); s3Mock.start(); @@ -58,28 +64,25 @@ public class TestS3Context { @Bean @Primary - public AmazonS3 s3Client(S3Mock s3Mock, @Value("${xplanbox.s3.bucket.validation}") String bucketName) { - AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration( - "http://localhost:" + port, "eu-central-1"); - AmazonS3 client = AmazonS3ClientBuilder.standard() - .withPathStyleAccessEnabled(true) - .withEndpointConfiguration(endpoint) - .withCredentials(new AWSStaticCredentialsProvider(new AnonymousAWSCredentials())) + @Profile("mock") + public S3Client s3Client(S3Mock s3Mock, @Value("${xplanbox.s3.bucketName}") String bucketName) + throws URISyntaxException { + URI endpoint = new URI("http://localhost:" + port); + S3Client client = S3Client.builder() + .serviceConfiguration(S3Configuration.builder().pathStyleAccessEnabled(true).build()) + .endpointOverride(endpoint) + .credentialsProvider( + StaticCredentialsProvider.create(AwsBasicCredentials.create("accessKeyId", "secretKey"))) + .region(EU_CENTRAL_1) .build(); - client.createBucket(bucketName); + client.createBucket(CreateBucketRequest.builder().bucket(bucketName).build()); s3TestClient = client; return client; } - @Bean - @Primary - public AWSCredentials credentials() { - return new BasicAWSCredentials("accessKeyId", "secretKey"); - } - @PreDestroy public void shutdown() { - s3TestClient.shutdown(); + s3TestClient.close(); if (s3Mock != null) { s3Mock.stop(); } diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/ConfigHandlerTest.java b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/ConfigHandlerTest.java index 7ca8d0b89..a8ea146fb 100644 --- a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/ConfigHandlerTest.java +++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/ConfigHandlerTest.java @@ -40,8 +40,9 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; */ @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = { ApplicationContext.class, TestContext.class }) -@ActiveProfiles("test") -@TestPropertySource(properties = { "xplanbox.s3.bucket.validation=test-bucket-validation" }) +@TestPropertySource(value = "/s3Mock.properties", + properties = { "xplanbox.s3.bucket.validation=test-bucket-validation" }) +@ActiveProfiles({ "mock", "test" }) class ConfigHandlerTest { @Autowired diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/v2/ConfigHandlerV2Test.java b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/v2/ConfigHandlerV2Test.java index 59956e95a..872ef076f 100644 --- a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/v2/ConfigHandlerV2Test.java +++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/v2/ConfigHandlerV2Test.java @@ -41,8 +41,9 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; */ @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = { ApplicationContext.class, TestContext.class }) -@ActiveProfiles("test") -@TestPropertySource(properties = { "xplanbox.s3.bucket.validation=test-bucket-validation" }) +@TestPropertySource(value = "/s3Mock.properties", + properties = { "xplanbox.s3.bucket.validation=test-bucket-validation" }) +@ActiveProfiles({ "mock", "test" }) class ConfigHandlerV2Test { @Autowired diff --git a/xplan-validator/xplan-validator-api/src/test/resources/s3Mock.properties b/xplan-validator/xplan-validator-api/src/test/resources/s3Mock.properties index 008ce1c39..32c458100 100644 --- a/xplan-validator/xplan-validator-api/src/test/resources/s3Mock.properties +++ b/xplan-validator/xplan-validator-api/src/test/resources/s3Mock.properties @@ -20,6 +20,6 @@ ### xplanbox.s3.accessKeyId= xplanbox.s3.secretKey= -xplanbox.s3.bucket.validation=latlonvalidationtest +xplanbox.s3.bucketName=latlonxpbtest xplanbox.s3.region=eu-central-1 xplanbox.s3.endpoint.url=http://localhost diff --git a/xplan-validator/xplan-validator-executor/Dockerfile b/xplan-validator/xplan-validator-executor/Dockerfile index 689d2596b..f0d9e7a64 100644 --- a/xplan-validator/xplan-validator-executor/Dockerfile +++ b/xplan-validator/xplan-validator-executor/Dockerfile @@ -32,7 +32,6 @@ COPY --from=builder $JMX_EXPORTER_DIR $JMX_EXPORTER_DIR ENV DEEGREE_WORKSPACE_ROOT=/xplanbox/deegree \ JAVA_ADDITIONAL_ARG_APP="-Djavax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl -Djts.overlay=ng -Duser.timezone=Europe/Berlin" \ JAVA_ADDITIONAL_ARG_JAVA17_EXPORTS="--add-exports=java.desktop/com.sun.imageio.spi=ALL-UNNAMED" \ - JAVA_ADDITIONAL_ARG_DISABLE_AWS_DEPRECATION="-Daws.java.v1.disableDeprecationAnnouncement=true" \ JAVA_ADDITIONAL_ARG_JMX_EXPORTER='-javaagent:$JMX_EXPORTER_DIR/jmx_prometheus_javaagent-1.0.1.jar=12345:$JMX_EXPORTER_DIR/jmx-exporter.config.yaml' \ XPLANBOX_CONFIG="/xplanbox/xplan-validator-config/" diff --git a/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/PlanValidatorTest.java b/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/PlanValidatorTest.java index 8fdee6dcd..8b8cac0c5 100644 --- a/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/PlanValidatorTest.java +++ b/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/PlanValidatorTest.java @@ -75,9 +75,8 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean; */ @SpringBootTest(classes = { SpringBootApp.class }) @Import(TestS3Context.class) -@TestPropertySource( - properties = { "xplanbox.s3.bucketName=test-bucket", "xplanbox.s3.bucket.validation=test-bucket-validation" }) -@ActiveProfiles("test") +@ActiveProfiles({ "mock", "test" }) +@TestPropertySource("classpath:s3Mock.properties") class PlanValidatorTest { @TestConfiguration diff --git a/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/config/TestS3Context.java b/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/config/TestS3Context.java index 6c2ba9bc7..1263347ae 100644 --- a/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/config/TestS3Context.java +++ b/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/config/TestS3Context.java @@ -8,34 +8,40 @@ * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ package de.latlon.xplanbox.validator.executor.config; -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.AnonymousAWSCredentials; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.client.builder.AwsClientBuilder; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import static software.amazon.awssdk.regions.Region.EU_CENTRAL_1; + +import java.net.URI; +import java.net.URISyntaxException; + import io.findify.s3mock.S3Mock; import jakarta.annotation.PreDestroy; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; import org.springframework.test.util.TestSocketUtils; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.S3Configuration; +import software.amazon.awssdk.services.s3.model.CreateBucketRequest; /** + * Spring Configuration to enable usage of mock objects for integration tests. + * * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> * @since 8.0 */ @@ -44,11 +50,12 @@ public class TestS3Context { private final int port = TestSocketUtils.findAvailableTcpPort(); - private AmazonS3 s3TestClient; + private S3Client s3TestClient; private S3Mock s3Mock; @Bean + @Profile("mock") public S3Mock s3Mock() { this.s3Mock = new S3Mock.Builder().withPort(port).withInMemoryBackend().build(); s3Mock.start(); @@ -57,28 +64,25 @@ public class TestS3Context { @Bean @Primary - public AmazonS3 s3Client(S3Mock s3Mock, @Value("${xplanbox.s3.bucketName}") String bucketName) { - AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration( - "http://localhost:" + port, "eu-central-1"); - AmazonS3 client = AmazonS3ClientBuilder.standard() - .withPathStyleAccessEnabled(true) - .withEndpointConfiguration(endpoint) - .withCredentials(new AWSStaticCredentialsProvider(new AnonymousAWSCredentials())) + @Profile("mock") + public S3Client s3Client(S3Mock s3Mock, @Value("${xplanbox.s3.bucketName}") String bucketName) + throws URISyntaxException { + URI endpoint = new URI("http://localhost:" + port); + S3Client client = S3Client.builder() + .serviceConfiguration(S3Configuration.builder().pathStyleAccessEnabled(true).build()) + .endpointOverride(endpoint) + .credentialsProvider( + StaticCredentialsProvider.create(AwsBasicCredentials.create("accessKeyId", "secretKey"))) + .region(EU_CENTRAL_1) .build(); - client.createBucket(bucketName); + client.createBucket(CreateBucketRequest.builder().bucket(bucketName).build()); s3TestClient = client; return client; } - @Bean - @Primary - public AWSCredentials credentials() { - return new BasicAWSCredentials("accessKeyId", "secretKey"); - } - @PreDestroy public void shutdown() { - s3TestClient.shutdown(); + s3TestClient.close(); if (s3Mock != null) { s3Mock.stop(); } diff --git a/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandlerTest.java b/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandlerTest.java index fa36103d9..51fed615b 100644 --- a/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandlerTest.java +++ b/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandlerTest.java @@ -60,9 +60,8 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean; */ @SpringBootTest(classes = { SpringBootApp.class }) @Import(TestS3Context.class) -@TestPropertySource( - properties = { "xplanbox.s3.bucketName=test-bucket", "xplanbox.s3.bucket.validation=test-bucket-validation" }) -@ActiveProfiles("test") +@ActiveProfiles({ "mock", "test" }) +@TestPropertySource("classpath:s3Mock.properties") public class ValidationHandlerTest { @MockitoBean diff --git a/xplan-validator/xplan-validator-executor/src/test/resources/s3Mock.properties b/xplan-validator/xplan-validator-executor/src/test/resources/s3Mock.properties new file mode 100644 index 000000000..32c458100 --- /dev/null +++ b/xplan-validator/xplan-validator-executor/src/test/resources/s3Mock.properties @@ -0,0 +1,25 @@ +### +# #%L +# xplan-manager-core - XPlan Manager Core Komponente +# %% +# Copyright (C) 2008 - 2025 Freie und Hansestadt Hamburg, developed by lat/lon gesellschaft für raumbezogene Informationssysteme mbH +# %% +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# #L% +### +xplanbox.s3.accessKeyId= +xplanbox.s3.secretKey= +xplanbox.s3.bucketName=latlonxpbtest +xplanbox.s3.region=eu-central-1 +xplanbox.s3.endpoint.url=http://localhost diff --git a/xplan-validator/xplan-validator-storage/pom.xml b/xplan-validator/xplan-validator-storage/pom.xml index 08221152c..2642d85aa 100644 --- a/xplan-validator/xplan-validator-storage/pom.xml +++ b/xplan-validator/xplan-validator-storage/pom.xml @@ -30,8 +30,8 @@ </dependency> <!-- aws --> <dependency> - <groupId>com.amazonaws</groupId> - <artifactId>aws-java-sdk-s3</artifactId> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> </dependency> <!-- test --> <dependency> diff --git a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/config/AmazonS3ValidationContext.java b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/config/AmazonS3ValidationContext.java index a144fc0b1..b21412457 100644 --- a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/config/AmazonS3ValidationContext.java +++ b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/config/AmazonS3ValidationContext.java @@ -20,7 +20,6 @@ */ package de.latlon.xplanbox.validator.storage.config; -import com.amazonaws.services.s3.AmazonS3; import de.latlon.xplan.commons.s3.S3Storage; import de.latlon.xplan.commons.s3.StorageException; import de.latlon.xplan.commons.s3.config.AmazonS3ReadOnlyContext; @@ -30,6 +29,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import software.amazon.awssdk.services.s3.S3Client; /** * Spring configuration for using AWS S3 as a storage. @@ -48,7 +48,7 @@ public class AmazonS3ValidationContext { } @Bean - public S3Storage s3Storage(AmazonS3 s3Client, @Value("${xplanbox.s3.bucket.validation}") String bucketName) + public S3Storage s3Storage(S3Client s3Client, @Value("${xplanbox.s3.bucket.validation}") String bucketName) throws StorageException { S3Storage s3Storage = new S3Storage(s3Client, bucketName); s3Storage.setBucketExpirationDate("deleteAfter30d", 30); diff --git a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/s3/S3PlanValidationExecutionStorage.java b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/s3/S3PlanValidationExecutionStorage.java index e60453507..ab4f0898a 100644 --- a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/s3/S3PlanValidationExecutionStorage.java +++ b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/s3/S3PlanValidationExecutionStorage.java @@ -8,12 +8,12 @@ * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% @@ -27,14 +27,13 @@ import java.nio.file.Path; import java.util.Map; import java.util.Map.Entry; -import com.amazonaws.services.s3.model.PutObjectResult; -import com.amazonaws.services.s3.model.S3ObjectSummary; import de.latlon.xplan.commons.s3.S3Metadata; import de.latlon.xplan.commons.s3.S3Object; import de.latlon.xplan.commons.s3.S3Storage; import de.latlon.xplan.commons.s3.StorageException; import de.latlon.xplanbox.validator.storage.StoredValidationReport; import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage; +import software.amazon.awssdk.services.s3.model.PutObjectResponse; /** * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> @@ -68,8 +67,10 @@ public class S3PlanValidationExecutionStorage extends ValidationExecutionStorage @Override protected void removeFromStore(Key key) { - S3ObjectSummary object = new S3ObjectSummary(); - object.setKey(key.toFileName()); + software.amazon.awssdk.services.s3.model.S3Object object = software.amazon.awssdk.services.s3.model.S3Object + .builder() + .key(key.toFileName()) + .build(); s3Storage.deleteObject(object); } @@ -88,12 +89,14 @@ public class S3PlanValidationExecutionStorage extends ValidationExecutionStorage @Override public StoredValidationReport saveValidationResult(String uuid, Map<ReportType, Path> reports) throws StorageException { - PutObjectResult lastPutObjectResult = null; + PutObjectResponse lastPutObjectResult = null; for (Entry<ReportType, Path> entry : reports.entrySet()) { String fileName = Key.report(uuid, entry.getKey()).toFileName(); lastPutObjectResult = s3Storage.insertObject(fileName, entry.getValue()); } - return new StoredValidationReport(lastPutObjectResult.getExpirationTime()); + // TODO + System.out.println(lastPutObjectResult.expiration()); + return new StoredValidationReport(null); } } diff --git a/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageIT.java b/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageIT.java index 893bda25c..47a94060b 100644 --- a/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageIT.java +++ b/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageIT.java @@ -54,8 +54,8 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; * @since 8.0 */ @ExtendWith(SpringExtension.class) -@ContextConfiguration(classes = { AmazonS3ValidationContext.class, AmazonS3TestContext.class }) -@ActiveProfiles({ "mock" }) +@ContextConfiguration(classes = { AmazonS3ValidationContext.class, TestS3Context.class }) +@ActiveProfiles({ "mock", "test" }) @TestPropertySource("classpath:s3Mock.properties") public class S3ValidationExecutionStorageIT { diff --git a/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageTest.java b/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageTest.java index b754e0001..772fd70c0 100644 --- a/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageTest.java +++ b/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageTest.java @@ -8,12 +8,12 @@ * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% @@ -25,17 +25,12 @@ import static de.latlon.xplanbox.validator.storage.ValidationExecutionStorage.Fi import static de.latlon.xplanbox.validator.storage.ValidationExecutionStorage.FileType.STATUS; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Path; @@ -44,15 +39,18 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.PutObjectResult; import de.latlon.xplan.commons.s3.S3Storage; import de.latlon.xplan.commons.s3.StorageException; import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage.Key; import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage.ReportType; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.HeadBucketRequest; +import software.amazon.awssdk.services.s3.model.HeadBucketResponse; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; +import software.amazon.awssdk.services.s3.model.PutObjectResponse; /** * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a> @@ -64,46 +62,51 @@ class S3ValidationExecutionStorageTest { @Test void testAddPlanToValidate_gml() throws IOException, URISyntaxException, StorageException { - AmazonS3 client = spy(AmazonS3.class); + S3Client client = createS3ClientSpy(); S3Storage s3Storage = new S3Storage(client, BUCKET_NAME); S3PlanValidationExecutionStorage validationExecutionStorage = new S3PlanValidationExecutionStorage(s3Storage); URL xplanGml = getClass().getResource("/xplan.gml"); String key = validationExecutionStorage.addPlanToValidate(Paths.get(xplanGml.toURI()), VALIDATION_REQUESTED); - ArgumentCaptor<String> keyCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor<HeadBucketRequest> headBucketRequestCaptor = ArgumentCaptor.forClass(HeadBucketRequest.class); + ArgumentCaptor<PutObjectRequest> putObjectRequestCaptor = ArgumentCaptor.forClass(PutObjectRequest.class); - verify(client, times(3)).doesBucketExistV2(eq(BUCKET_NAME)); - verify(client, times(2)).putObject(eq(BUCKET_NAME), keyCaptor.capture(), any(InputStream.class), - any(ObjectMetadata.class)); - verify(client).putObject(eq(BUCKET_NAME), keyCaptor.capture(), any(File.class)); + verify(client, times(3)).headBucket(headBucketRequestCaptor.capture()); + verify(client, times(3)).putObject(putObjectRequestCaptor.capture(), any(RequestBody.class)); - assertThat(keyCaptor.getAllValues()).containsExactlyInAnyOrder(key, key + DETAILS.getSuffix(), - key + STATUS.getSuffix()); + assertThat(headBucketRequestCaptor.getAllValues()).map(HeadBucketRequest::bucket) + .containsExactlyInAnyOrder(BUCKET_NAME, BUCKET_NAME, BUCKET_NAME); + assertThat(putObjectRequestCaptor.getAllValues()).map(PutObjectRequest::bucket) + .containsExactlyInAnyOrder(BUCKET_NAME, BUCKET_NAME, BUCKET_NAME); + assertThat(putObjectRequestCaptor.getAllValues()).map(PutObjectRequest::key) + .containsExactlyInAnyOrder(key, key + DETAILS.getSuffix(), key + STATUS.getSuffix()); } @Test void testAddPlanToValidate_zip() throws IOException, URISyntaxException, StorageException { - AmazonS3 client = spy(AmazonS3.class); + S3Client client = createS3ClientSpy(); S3Storage s3Storage = new S3Storage(client, BUCKET_NAME); S3PlanValidationExecutionStorage validationExecutionStorage = new S3PlanValidationExecutionStorage(s3Storage); URL xplanGml = getClass().getResource("/BPlan002_5-3.zip"); String key = validationExecutionStorage.addPlanToValidate(Paths.get(xplanGml.toURI()), VALIDATION_REQUESTED); - ArgumentCaptor<String> keyCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor<HeadBucketRequest> headBucketRequestCaptor = ArgumentCaptor.forClass(HeadBucketRequest.class); + ArgumentCaptor<PutObjectRequest> putObjectRequestCaptor = ArgumentCaptor.forClass(PutObjectRequest.class); - verify(client, times(3)).doesBucketExistV2(eq(BUCKET_NAME)); - verify(client, times(2)).putObject(eq(BUCKET_NAME), keyCaptor.capture(), any(InputStream.class), - any(ObjectMetadata.class)); - verify(client).putObject(eq(BUCKET_NAME), keyCaptor.capture(), any(File.class)); + verify(client, times(3)).headBucket(headBucketRequestCaptor.capture()); + verify(client, times(3)).putObject(putObjectRequestCaptor.capture(), any(RequestBody.class)); - assertThat(keyCaptor.getAllValues()).containsExactlyInAnyOrder(key, key + DETAILS.getSuffix(), - key + STATUS.getSuffix()); + assertThat(headBucketRequestCaptor.getAllValues()).map(HeadBucketRequest::bucket) + .containsExactlyInAnyOrder(BUCKET_NAME, BUCKET_NAME, BUCKET_NAME); + assertThat(putObjectRequestCaptor.getAllValues()).map(PutObjectRequest::bucket) + .containsExactlyInAnyOrder(BUCKET_NAME, BUCKET_NAME, BUCKET_NAME); + assertThat(putObjectRequestCaptor.getAllValues()).map(PutObjectRequest::key) + .containsExactlyInAnyOrder(key, key + DETAILS.getSuffix(), key + STATUS.getSuffix()); } @Test void testSaveValidationResult() throws URISyntaxException, StorageException { - AmazonS3 client = spy(AmazonS3.class); - when(client.putObject(anyString(), anyString(), any(File.class))).thenReturn(mock(PutObjectResult.class)); + S3Client client = createS3ClientSpy(); S3Storage s3Storage = new S3Storage(client, BUCKET_NAME); S3PlanValidationExecutionStorage validationExecutionStorage = new S3PlanValidationExecutionStorage(s3Storage); URL xplanGml = getClass().getResource("/BPlan002_5-3.zip"); @@ -114,13 +117,27 @@ class S3ValidationExecutionStorageTest { reports.put(ReportType.PDF, Paths.get(xplanGml.toURI())); validationExecutionStorage.saveValidationResult(uuid, reports); - ArgumentCaptor<String> keyCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor<HeadBucketRequest> headBucketRequestCaptor = ArgumentCaptor.forClass(HeadBucketRequest.class); + ArgumentCaptor<PutObjectRequest> putObjectRequestCaptor = ArgumentCaptor.forClass(PutObjectRequest.class); - verify(client, times(2)).doesBucketExistV2(eq(BUCKET_NAME)); - verify(client, times(2)).putObject(eq(BUCKET_NAME), keyCaptor.capture(), any(File.class)); + verify(client, times(2)).headBucket(headBucketRequestCaptor.capture()); + verify(client, times(2)).putObject(putObjectRequestCaptor.capture(), any(RequestBody.class)); - assertThat(keyCaptor.getAllValues()).containsExactlyInAnyOrder(Key.report(uuid, ReportType.PDF).toFileName(), - Key.report(uuid, ReportType.JSON).toFileName()); + assertThat(headBucketRequestCaptor.getAllValues()).map(HeadBucketRequest::bucket) + .containsExactlyInAnyOrder(BUCKET_NAME, BUCKET_NAME); + assertThat(putObjectRequestCaptor.getAllValues()).map(PutObjectRequest::bucket) + .containsExactlyInAnyOrder(BUCKET_NAME, BUCKET_NAME); + assertThat(putObjectRequestCaptor.getAllValues()).map(PutObjectRequest::key) + .containsExactlyInAnyOrder(Key.report(uuid, ReportType.PDF).toFileName(), + Key.report(uuid, ReportType.JSON).toFileName()); + } + + private static S3Client createS3ClientSpy() { + S3Client client = spy(S3Client.class); + doReturn(HeadBucketResponse.builder().build()).when(client).headBucket(any(HeadBucketRequest.class)); + doReturn(PutObjectResponse.builder().build()).when(client) + .putObject(any(PutObjectRequest.class), any(RequestBody.class)); + return client; } } diff --git a/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/AmazonS3TestContext.java b/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/TestS3Context.java similarity index 60% rename from xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/AmazonS3TestContext.java rename to xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/TestS3Context.java index c5f243cf0..a5469ce4f 100644 --- a/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/AmazonS3TestContext.java +++ b/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/TestS3Context.java @@ -8,32 +8,36 @@ * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ package de.latlon.xplanbox.validator.storage.s3; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.AnonymousAWSCredentials; -import com.amazonaws.client.builder.AwsClientBuilder; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import static software.amazon.awssdk.regions.Region.EU_CENTRAL_1; + +import java.net.URI; +import java.net.URISyntaxException; + import io.findify.s3mock.S3Mock; import jakarta.annotation.PreDestroy; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Profile; import org.springframework.test.util.TestSocketUtils; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.S3Configuration; +import software.amazon.awssdk.services.s3.model.CreateBucketRequest; /** * Spring Configuration to enable usage of mock objects for integration tests. @@ -42,20 +46,18 @@ import org.springframework.test.util.TestSocketUtils; * @author <a href="mailto:friebe@lat-lon.de">Torsten Friebe</a> */ @Configuration -public class AmazonS3TestContext { +public class TestS3Context { - @Autowired(required = false) - private S3Mock s3Mock; + private final int port = TestSocketUtils.findAvailableTcpPort(); - @Autowired - private AmazonS3 s3TestClient; + private S3Client s3TestClient; - private final int port = TestSocketUtils.findAvailableTcpPort(); + private S3Mock s3Mock; @Bean @Profile("mock") public S3Mock s3Mock() { - S3Mock s3Mock = new S3Mock.Builder().withPort(port).withInMemoryBackend().build(); + this.s3Mock = new S3Mock.Builder().withPort(port).withInMemoryBackend().build(); s3Mock.start(); return s3Mock; } @@ -63,23 +65,24 @@ public class AmazonS3TestContext { @Bean @Primary @Profile("mock") - public AmazonS3 s3TestClient(@Value("${xplanbox.s3.region}") String signingRegion, - @Value("${xplanbox.s3.bucket.validation}") String bucketName, - @Value("${xplanbox.s3.endpoint.url}") String url) { - AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration(url + ":" + port, - signingRegion); - AmazonS3 client = AmazonS3ClientBuilder.standard() - .withPathStyleAccessEnabled(true) - .withEndpointConfiguration(endpoint) - .withCredentials(new AWSStaticCredentialsProvider(new AnonymousAWSCredentials())) + public S3Client s3TestClient(S3Mock s3Mock, @Value("${xplanbox.s3.bucket.validation}") String bucketName) + throws URISyntaxException { + URI endpoint = new URI("http://localhost:" + port); + S3Client client = S3Client.builder() + .serviceConfiguration(S3Configuration.builder().pathStyleAccessEnabled(true).build()) + .endpointOverride(endpoint) + .credentialsProvider( + StaticCredentialsProvider.create(AwsBasicCredentials.create("accessKeyId", "secretKey"))) + .region(EU_CENTRAL_1) .build(); - client.createBucket(bucketName); + client.createBucket(CreateBucketRequest.builder().bucket(bucketName).build()); + s3TestClient = client; return client; } @PreDestroy public void shutdown() { - s3TestClient.shutdown(); + s3TestClient.close(); if (s3Mock != null) { s3Mock.stop(); } diff --git a/xplan-validator/xplan-validator-web/pom.xml b/xplan-validator/xplan-validator-web/pom.xml index 49997fec8..9136c48b9 100644 --- a/xplan-validator/xplan-validator-web/pom.xml +++ b/xplan-validator/xplan-validator-web/pom.xml @@ -284,7 +284,7 @@ <id>docker</id> <properties> <docker-image.skip>false</docker-image.skip> - <docker-contextTarFile.expectedSizeInMat10pct>72</docker-contextTarFile.expectedSizeInMat10pct> + <docker-contextTarFile.expectedSizeInMat10pct>86</docker-contextTarFile.expectedSizeInMat10pct> </properties> <dependencies> <dependency> <!-- faked maven dependency to be after base docker image in the reactor build --> diff --git a/xplan-webservices/xplan-webservices-mapproxy/xplan-mapproxy-config/src/main/resources/mapproxy.yaml b/xplan-webservices/xplan-webservices-mapproxy/xplan-mapproxy-config/src/main/resources/mapproxy.yaml index 64b2d3ef8..2f19f92a5 100644 --- a/xplan-webservices/xplan-webservices-mapproxy/xplan-mapproxy-config/src/main/resources/mapproxy.yaml +++ b/xplan-webservices/xplan-webservices-mapproxy/xplan-mapproxy-config/src/main/resources/mapproxy.yaml @@ -336,7 +336,7 @@ sources: xplan-mapserver: <<: *wms_cfg req: - url: ${XPLAN_MAPSERVER_URL_INTERNAL}/mapserver? + url: ${XPLAN_MAPSERVER_URL_INTERNAL}/xplan-mapserver? transparent: true bplan-wms: <<: *wms_cfg @@ -385,7 +385,7 @@ globals: lock_dir: "./cache_data/locks" tile_lock_dir: "./cache_data/tile_locks" s3: - endpoint_url: https://${XPLAN_S3_ENDPOINT} + endpoint_url: ${XPLAN_S3_ENDPOINT} bucket_name: ${XPLAN_S3_BUCKET_MAPPROXYCACHE} region_name: ${XPLAN_S3_REGION} image: diff --git a/xplan-webservices/xplan-webservices-mapproxy/xplan-mapproxy-docker/Dockerfile b/xplan-webservices/xplan-webservices-mapproxy/xplan-mapproxy-docker/Dockerfile index 5d3ecbd90..1d5bd960a 100644 --- a/xplan-webservices/xplan-webservices-mapproxy/xplan-mapproxy-docker/Dockerfile +++ b/xplan-webservices/xplan-webservices-mapproxy/xplan-mapproxy-docker/Dockerfile @@ -1,6 +1,6 @@ FROM python:3.12-slim -ARG MAPPROXY_VERSION=1.16.0 +ARG MAPPROXY_VERSION=3.1.3 ARG BUILD_DATE=? ARG DOCKER_IMAGE_NAME=? ARG GIT_REVISION=? @@ -40,7 +40,7 @@ RUN apt update && apt -y install --no-install-recommends \ apt-get clean && \ rm -rf /var/lib/apt/lists/* && \ python -m venv --system-site-packages /srv/mapproxy/venv && \ - pip install mapproxy==$MAPPROXY_VERSION uwsgi pyproj pillow pyyaml boto3==1.35.99 shapely==1.7.1 setuptools && \ + pip install mapproxy==$MAPPROXY_VERSION uwsgi riak==2.4.2 redis azure-storage-blob boto3==1.35.99 Shapely && \ pip cache purge && \ addgroup --gid 1001 mapproxy && \ adduser --uid 1001 --shell /bin/false --gid 1001 --no-create-home --disabled-login mapproxy && \ diff --git a/xplan-webservices/xplan-webservices-mapserver/xplan-mapserver-config/src/main/resources/common.txt b/xplan-webservices/xplan-webservices-mapserver/xplan-mapserver-config/src/main/resources/common.txt index 0a060d3fc..b0f7c2bf8 100644 --- a/xplan-webservices/xplan-webservices-mapserver/xplan-mapserver-config/src/main/resources/common.txt +++ b/xplan-webservices/xplan-webservices-mapserver/xplan-mapserver-config/src/main/resources/common.txt @@ -30,7 +30,7 @@ IMAGETYPE png CONFIG "AWS_ACCESS_KEY_ID" "$AWS_ACCESS_KEY_ID" CONFIG "AWS_SECRET_ACCESS_KEY" "$AWS_SECRET_ACCESS_KEY" CONFIG "AWS_REGION" "$AWS_REGION" -CONFIG "AWS_S3_ENDPOINT" "$AWS_S3_ENDPOINT" +CONFIG "AWS_S3_ENDPOINT" "$AWS_S3_ENDPOINT_WITHOUT_PROTOCOL" SHAPEPATH "/vsis3/$XPLAN_S3_BUCKET_ATTACHMENTS" OUTPUTFORMAT diff --git a/xplan-webservices/xplan-webservices-mapserver/xplan-mapserver-config/src/main/resources/internal.map b/xplan-webservices/xplan-webservices-mapserver/xplan-mapserver-config/src/main/resources/internal.map index 7f25be5a1..4e0022687 100644 --- a/xplan-webservices/xplan-webservices-mapserver/xplan-mapserver-config/src/main/resources/internal.map +++ b/xplan-webservices/xplan-webservices-mapserver/xplan-mapserver-config/src/main/resources/internal.map @@ -29,7 +29,7 @@ MAP IMAGEPATH "/ms4w/tmp/ms_tmp/" IMAGEURL "/ms_tmp/" METADATA - "wms_onlineresource" "${XPLAN_MAPSERVER_URL_INTERNAL}/mapserver?map=/etc/mapserver/internal.map" + "wms_onlineresource" "${XPLAN_MAPSERVER_URL_INTERNAL}/xplan-mapserver?map=/etc/mapserver/internal.map" "wms_title" "xPlanBox Rasterdaten" "wms_srs" "EPSG:25832" "wms_enable_request" "*" diff --git a/xplan-webservices/xplan-webservices-mapserver/xplan-mapserver-docker/Dockerfile b/xplan-webservices/xplan-webservices-mapserver/xplan-mapserver-docker/Dockerfile index 8df858e0b..22e843661 100644 --- a/xplan-webservices/xplan-webservices-mapserver/xplan-mapserver-docker/Dockerfile +++ b/xplan-webservices/xplan-webservices-mapserver/xplan-mapserver-docker/Dockerfile @@ -1,5 +1,5 @@ -# latest linux/amd64 on 21.11.23 -FROM camptocamp/mapserver@sha256:0ed39cd88641ea384f7ec3ae2cff02c841d7e20d5daea2c4d567e21e53d9c0c2 +# latest camptocamp/mapserver:8.4-gdal3.10 on 06.02.25 +FROM camptocamp/mapserver@sha256:521c49c590a3382c98e05995e921fa800b64bf901f3118c33b705d2ef096b434 ARG BUILD_DATE=? ARG DOCKER_IMAGE_NAME=? ARG GIT_REVISION=? @@ -17,9 +17,10 @@ LABEL "org.opencontainers.image.created"="$BUILD_DATE" \ "org.opencontainers.image.version"="$XPLANBOX_VERSION" \ "maintainer"="" -ENV XPLAN_SERVICES_WMS_MAXWIDTH=3840 +ENV XPLAN_SERVICES_WMS_MAXWIDTH=3840 \ + MAPSERVER_BASE_PATH=/xplan-mapserver \ + TZ=Europe/Berlin -ENV TZ=Europe/Berlin RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install tzdata gettext-base RUN mkdir -p /xplan-mapserver-docker \ diff --git a/xplan-webservices/xplan-webservices-mapserver/xplan-mapserver-docker/startupWithConfiguredMapserver.sh b/xplan-webservices/xplan-webservices-mapserver/xplan-mapserver-docker/startupWithConfiguredMapserver.sh index ce6c47bf7..f59324391 100755 --- a/xplan-webservices/xplan-webservices-mapserver/xplan-mapserver-docker/startupWithConfiguredMapserver.sh +++ b/xplan-webservices/xplan-webservices-mapserver/xplan-mapserver-docker/startupWithConfiguredMapserver.sh @@ -16,8 +16,8 @@ fi echo "[$(date -Iseconds)] Initializing mapserver config ..." echo "[$(date -Iseconds)] MapProxy config initialization..." - -defined_envs="$(printf '${%s} ' $(env | cut -d'=' -f1))" +defined_envs="$(printf '${%s} ' $(env | cut -d'=' -f1)) \${AWS_S3_ENDPOINT_WITHOUT_PROTOCOL}" +export AWS_S3_ENDPOINT_WITHOUT_PROTOCOL="$(echo $AWS_S3_ENDPOINT | sed s/'http[s]\?:\/\/'//)" TARGET_DIR="$(dirname "${MS_MAPFILE}")" for FILE in /xplan-mapserver-docker/xplan-mapserver-config/*; do diff --git a/xplan-webservices/xplan-webservices-validator-wms/src/test/resources/de/latlon/xplan/validator/wms/libs.expected.txt b/xplan-webservices/xplan-webservices-validator-wms/src/test/resources/de/latlon/xplan/validator/wms/libs.expected.txt index 7ec8d43ba..b34be6138 100644 --- a/xplan-webservices/xplan-webservices-validator-wms/src/test/resources/de/latlon/xplan/validator/wms/libs.expected.txt +++ b/xplan-webservices/xplan-webservices-validator-wms/src/test/resources/de/latlon/xplan/validator/wms/libs.expected.txt @@ -1,12 +1,16 @@ accessors-smart-2.5.1.jar aircompressor-0.27.jar angus-activation-2.0.2.jar +annotations-2.30.10.jar antlr-runtime-3.5.3.jar +apache-client-2.30.10.jar apache-mime4j-core-0.8.6.jar +arns-2.30.10.jar asm-9.6.jar -aws-java-sdk-core-1.12.780.jar -aws-java-sdk-kms-1.12.780.jar -aws-java-sdk-s3-1.12.780.jar +auth-2.30.10.jar +aws-core-2.30.10.jar +aws-query-protocol-2.30.10.jar +aws-xml-protocol-2.30.10.jar axiom-api-1.4.0.jar axiom-impl-1.4.0.jar batik-anim-1.17.jar @@ -29,6 +33,8 @@ batik-util-1.17.jar batik-xml-1.17.jar cache-api-1.1.1.jar checker-qual-3.48.3.jar +checksums-2.30.10.jar +checksums-spi-2.30.10.jar commons-beanutils-1.9.4.jar commons-cli-1.2.jar commons-codec-1.17.2.jar @@ -40,10 +46,11 @@ commons-fileupload2-core-2.0.0-M2.jar commons-fileupload2-jakarta-servlet6-2.0.0-M2.jar commons-io-2.18.0.jar commons-lang-2.6.jar -commons-logging-1.1.3.jar +commons-logging-1.2.jar commons-math-2.2.jar commons-pool2-2.12.0.jar com.sun.xml.bind-jaxb-core-4.0.5.jar +crt-core-2.30.10.jar deegree-connectionprovider-datasource-3.6.0-SNAPSHOT.jar deegree-core-annotations-3.6.0-SNAPSHOT.jar deegree-core-base-3.6.0-SNAPSHOT.jar @@ -108,14 +115,22 @@ deegree-tilestore-remotewms-3.6.0-SNAPSHOT.jar deegree-tilestore-remotewmts-3.6.0-SNAPSHOT.jar deegree-webservices-3.6.0-SNAPSHOT.jar ehcache-3.10.8-jakarta.jar +endpoints-spi-2.30.10.jar error_prone_annotations-2.27.0.jar FastInfoset-1.2.18.jar +eventstream-1.0.1.jar gdal-3.6.0.jar gson-2.11.0.jar h2-2.3.232.jar +http-auth-2.30.10.jar +http-auth-aws-2.30.10.jar +http-auth-aws-eventstream-2.30.10.jar +http-auth-spi-2.30.10.jar +http-client-spi-2.30.10.jar httpclient-4.5.13.jar httpclient-4.5.14.jar httpcore-4.4.16.jar +identity-spi-2.30.10.jar imageio-ext-geocore-1.4.14.jar imageio-ext-streams-1.4.14.jar imageio-ext-tiff-1.4.14.jar @@ -124,7 +139,6 @@ istack-commons-runtime-4.1.2.jar jackson-annotations-2.18.2.jar jackson-core-2.18.2.jar jackson-databind-2.18.2.jar -jackson-dataformat-cbor-2.18.2.jar jackson-dataformat-yaml-2.18.2.jar jai-codec-1.1.3.jar jai-core-1.1.3.jar @@ -148,11 +162,10 @@ jaxb-runtime-4.0.5.jar jaxen-2.0.0.jar jcl-over-slf4j-2.0.16.jar jgridshift-core-1.3.1.jar -jmespath-java-1.12.780.jar -joda-time-2.12.7.jar jogl-1.1.2.jar json-path-2.9.0.jar json-smart-2.5.1.jar +json-utils-2.30.10.jar jts-core-1.20.0.jar jul-to-slf4j-2.0.16.jar junidecode-0.4.1.jar @@ -162,20 +175,42 @@ log4j-layout-template-json-2.24.3.jar log4j-slf4j2-impl-2.24.3.jar log4j-web-2.24.3.jar mchange-commons-java-0.2.15.jar +metrics-spi-2.30.10.jar micrometer-commons-1.14.3.jar micrometer-observation-1.14.3.jar +netty-buffer-4.1.117.Final.jar +netty-codec-4.1.117.Final.jar +netty-codec-http2-4.1.117.Final.jar +netty-codec-http-4.1.117.Final.jar +netty-common-4.1.117.Final.jar +netty-handler-4.1.117.Final.jar +netty-nio-client-2.30.10.jar +netty-resolver-4.1.117.Final.jar +netty-transport-4.1.117.Final.jar +netty-transport-classes-epoll-4.1.117.Final.jar +netty-transport-native-unix-common-4.1.117.Final.jar org.glassfish.jaxb-jaxb-core-4.0.5.jar postgis-geometry-2023.1.0.jar postgis-jdbc-2023.1.0.jar postgresql-42.7.5.jar primefaces-14.0.7-jakarta.jar primefaces-extensions-14.0.7.1-jakarta.jar +profiles-2.30.10.jar +protocol-core-2.30.10.jar quartz-2.3.2.jar +reactive-streams-1.0.4.jar +regions-2.30.10.jar +retries-2.30.10.jar +retries-spi-2.30.10.jar Saxon-HE-9.9.1-8.jar +s3-2.30.10.jar +sdk-core-2.30.10.jar slf4j-api-2.0.16.jar snakeyaml-2.3.jar spring-aop-6.2.2.jar spring-beans-6.2.2.jar +spring-boot-3.4.2.jar +spring-boot-autoconfigure-3.4.2.jar spring-context-6.2.2.jar spring-context-support-6.2.2.jar spring-core-6.2.2.jar @@ -184,8 +219,10 @@ spring-jcl-6.2.2.jar spring-tx-6.2.2.jar stax2-api-4.2.jar staxon-1.2.jar +third-party-jackson-core-2.30.10.jar tika-core-2.9.2.jar txw2-4.0.5.jar +utils-2.30.10.jar vecmath-1.5.2.jar weld-servlet-shaded-5.1.3.Final.jar woodstox-core-5.4.0.jar diff --git a/xplan-webservices/xplan-webservices-workspaces/src/main/workspace/datasources/remoteows/mapserver.xml b/xplan-webservices/xplan-webservices-workspaces/src/main/workspace/datasources/remoteows/mapserver.xml index 858ed2dee..5392dcf37 100644 --- a/xplan-webservices/xplan-webservices-workspaces/src/main/workspace/datasources/remoteows/mapserver.xml +++ b/xplan-webservices/xplan-webservices-workspaces/src/main/workspace/datasources/remoteows/mapserver.xml @@ -20,7 +20,7 @@ --> <RemoteWMS xmlns="http://www.deegree.org/remoteows/wms"> <CapabilitiesDocumentLocation - location="http://localhost:8080/mapserver?request=GetCapabilities&service=WMS&version=1.1.1"/> + location="http://localhost:8080/xplan-mapserver?request=GetCapabilities&service=WMS&version=1.1.1"/> <ConnectionTimeout>10</ConnectionTimeout> <RequestTimeout>60</RequestTimeout> </RemoteWMS> -- GitLab