diff --git a/pom.xml b/pom.xml
index 820205c66..2db17fc63 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,16 +31,15 @@
${java.version}
${java.version}
UTF-8
+ 3.5.5
1.0.0
5.0.0
4.1.3
1.18.40
- 12.1.1
9.4.0
1.3.1
- 2.0.17
3.20.7
11.12.0
4.0.10
@@ -50,6 +49,13 @@
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot.version}
+ pom
+ import
+
de.rwth.idsg
steve-core
@@ -95,20 +101,6 @@
steve-ui-jsp
${project.version}
-
- org.springframework
- spring-framework-bom
- 6.2.11
- pom
- import
-
-
- org.springframework.security
- spring-security-bom
- 6.5.3
- pom
- import
-
org.junit
junit-bom
@@ -123,20 +115,6 @@
pom
import
-
- org.eclipse.jetty
- jetty-bom
- ${jetty.version}
- pom
- import
-
-
- org.eclipse.jetty.ee10
- jetty-ee10-bom
- ${jetty.version}
- pom
- import
-
org.hibernate.validator
hibernate-validator
@@ -152,16 +130,6 @@
jakarta.mail-api
2.1.4
-
- org.slf4j
- slf4j-api
- 2.0.17
-
-
- ch.qos.logback
- logback-classic
- 1.5.18
-
io.swagger.core.v3
swagger-annotations-jakarta
@@ -225,6 +193,11 @@
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring-boot.version}
+
org.apache.maven.plugins
maven-enforcer-plugin
diff --git a/steve-api/src/main/java/de/rwth/idsg/steve/config/ApiDocsConfiguration.java b/steve-api/src/main/java/de/rwth/idsg/steve/config/ApiDocsConfiguration.java
index e4e1e80a7..f91c09493 100644
--- a/steve-api/src/main/java/de/rwth/idsg/steve/config/ApiDocsConfiguration.java
+++ b/steve-api/src/main/java/de/rwth/idsg/steve/config/ApiDocsConfiguration.java
@@ -18,7 +18,6 @@
*/
package de.rwth.idsg.steve.config;
-import de.rwth.idsg.steve.SteveConfiguration;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
@@ -74,7 +73,7 @@ public class ApiDocsConfiguration {
}
@Bean
- public OpenAPI apiDocs(SteveConfiguration config) {
+ public OpenAPI apiDocs(SteveProperties steveProperties) {
var title = "SteVe REST API Documentation";
var securityName = "basicAuth";
@@ -91,7 +90,7 @@ public OpenAPI apiDocs(SteveConfiguration config) {
.license(new License()
.name("GPL-3.0")
.url("https://github.com/steve-community/steve/blob/master/LICENSE.txt"))
- .version(config.getSteveVersion()))
+ .version(steveProperties.getVersion()))
// https://stackoverflow.com/a/68185254
.servers(List.of(new Server().url("/").description("Default Server URL")))
// define a security schema
diff --git a/steve-core/pom.xml b/steve-core/pom.xml
index 5da02874a..dafab6f32 100644
--- a/steve-core/pom.xml
+++ b/steve-core/pom.xml
@@ -10,6 +10,10 @@
steve-core
+
+ org.springframework.boot
+ spring-boot-starter
+
de.rwth.idsg
steve-ocpp-1-x
@@ -17,17 +21,6 @@
org.springframework
spring-webmvc
-
-
-
- commons-logging
- commons-logging
-
-
- org.springframework
- spring-jcl
-
-
org.springframework.security
@@ -50,10 +43,6 @@
io.swagger.core.v3
swagger-annotations-jakarta
-
- org.slf4j
- slf4j-api
-
com.google.guava
diff --git a/steve-core/src/main/java/de/rwth/idsg/steve/SteveConfiguration.java b/steve-core/src/main/java/de/rwth/idsg/steve/SteveConfiguration.java
deleted file mode 100644
index 23bd7468b..000000000
--- a/steve-core/src/main/java/de/rwth/idsg/steve/SteveConfiguration.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve;
-
-import lombok.Builder;
-import lombok.Getter;
-import org.jspecify.annotations.Nullable;
-import org.springframework.security.crypto.password.PasswordEncoder;
-
-/**
- * @author Sevket Goekay
- * @since 19.08.2014
- */
-@Builder
-@Getter
-public class SteveConfiguration {
-
- @Builder
- @Getter
- public static class Paths {
- // Root mapping for Spring
- private final String rootMapping;
- // Web frontend
- private final String managerMapping;
- // Mapping for SOAP services
- private final String soapMapping;
- // Mapping for Websocket services
- private final String websocketMapping;
- // Mapping for Web APIs
- private final String apiMapping;
- // Dummy service path
- private final String routerEndpointPath;
-
- private final @Nullable String contextPath;
- }
-
- private final Paths paths;
- // Time zone for the application and database connections
- private final String timeZoneId;
- private final String steveVersion;
- private final @Nullable String gitDescribe;
- private final ApplicationProfile profile;
- private final Ocpp ocpp;
- private final Auth auth;
- private final WebApi webApi;
- private final DB db;
- private final Jetty jetty;
-
- public String getSteveCompositeVersion() {
- if (gitDescribe == null) {
- return steveVersion;
- } else {
- return steveVersion + "-g" + gitDescribe;
- }
- }
-
- public void postConstruct() {
- if (!(jetty.httpEnabled || jetty.httpsEnabled)) {
- throw new IllegalArgumentException(
- "HTTP and HTTPS are both disabled. Well, how do you want to access the server, then?");
- }
- }
-
- // -------------------------------------------------------------------------
- // Class declarations
- // -------------------------------------------------------------------------
-
- // Jetty configuration
- @Builder
- @Getter
- public static class Jetty {
- private final String serverHost;
- private final boolean gzipEnabled;
-
- // HTTP
- private final boolean httpEnabled;
- private final int httpPort;
-
- // HTTPS
- private final boolean httpsEnabled;
- private final int httpsPort;
- private final @Nullable String keyStorePath;
- private final @Nullable String keyStorePassword;
- }
-
- // Database configuration
- @Builder
- @Getter
- public static class DB {
- private final String jdbcUrl;
- private final String userName;
- private final String password;
- private final boolean sqlLogging;
- private final String schemaSource;
- private final @Nullable String schema;
- }
-
- // Credentials for Web interface access
- @Builder
- @Getter
- public static class Auth {
- private final PasswordEncoder passwordEncoder;
- private final String userName;
- private final String encodedPassword;
- }
-
- @Builder
- @Getter
- public static class WebApi {
- private final @Nullable String headerKey;
- private final @Nullable String headerValue;
- }
-
- // OCPP-related configuration
- @Builder
- @Getter
- public static class Ocpp {
- private final boolean autoRegisterUnknownStations;
- private final @Nullable String chargeBoxIdValidationRegex;
- private final String wsSessionSelectStrategy;
- }
-}
diff --git a/steve-core/src/main/java/de/rwth/idsg/steve/config/SteveProperties.java b/steve-core/src/main/java/de/rwth/idsg/steve/config/SteveProperties.java
new file mode 100644
index 000000000..cfd69417e
--- /dev/null
+++ b/steve-core/src/main/java/de/rwth/idsg/steve/config/SteveProperties.java
@@ -0,0 +1,58 @@
+/*
+ * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
+ * Copyright (C) 2013-2025 SteVe Community Team
+ * All Rights Reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License
+ * along with this program. If not, see .
+ */
+package de.rwth.idsg.steve.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@Data
+@ConfigurationProperties("steve")
+public class SteveProperties {
+
+ private Auth auth = new Auth();
+ private WebApi webapi = new WebApi();
+ private Ocpp ocpp = new Ocpp();
+ private String version;
+ private String gitDescribe;
+
+ @Data
+ public static class Auth {
+ private String user;
+ private String password;
+ }
+
+ @Data
+ public static class WebApi {
+ private String key;
+ private String value;
+ }
+
+ @Data
+ public static class Ocpp {
+ private String wsSessionSelectStrategy;
+ private boolean autoRegisterUnknownStations;
+ private String chargeBoxIdValidationRegex;
+ private Soap soap = new Soap();
+ }
+
+ @Data
+ public static class Soap {
+ private String routerEndpointPath;
+ }
+}
diff --git a/steve-core/src/main/java/de/rwth/idsg/steve/service/WebUsersService.java b/steve-core/src/main/java/de/rwth/idsg/steve/service/WebUsersService.java
index d8a356cdd..134676995 100644
--- a/steve-core/src/main/java/de/rwth/idsg/steve/service/WebUsersService.java
+++ b/steve-core/src/main/java/de/rwth/idsg/steve/service/WebUsersService.java
@@ -22,8 +22,8 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
-import de.rwth.idsg.steve.SteveConfiguration;
import de.rwth.idsg.steve.SteveException;
+import de.rwth.idsg.steve.config.SteveProperties;
import de.rwth.idsg.steve.repository.WebUserRepository;
import de.rwth.idsg.steve.repository.dto.WebUser;
import de.rwth.idsg.steve.service.dto.WebUserOverview;
@@ -73,7 +73,7 @@ public class WebUsersService implements UserDetailsManager {
// Because Guava's cache does not accept a null value
private static final UserDetails DUMMY_USER = new User("#", "#", Collections.emptyList());
- private final SteveConfiguration config;
+ private final SteveProperties steveProperties;
private final ObjectMapper mapper;
private final WebUserRepository webUserRepository;
private final SecurityContextHolderStrategy securityContextHolderStrategy = getContextHolderStrategy();
@@ -91,8 +91,8 @@ public void afterStart(ContextRefreshedEvent event) {
}
var user = WebUser.builder()
- .login(config.getAuth().getUserName())
- .password(config.getAuth().getEncodedPassword())
+ .login(steveProperties.getAuth().getUser())
+ .password(encoder.encode(steveProperties.getAuth().getPassword()))
.enabled(true)
.authorities(EnumSet.of(WebUserAuthority.ADMIN))
.build();
diff --git a/steve-core/src/main/java/de/rwth/idsg/steve/web/dto/EndpointInfo.java b/steve-core/src/main/java/de/rwth/idsg/steve/web/dto/EndpointInfo.java
index bc60c4c4d..037edde15 100644
--- a/steve-core/src/main/java/de/rwth/idsg/steve/web/dto/EndpointInfo.java
+++ b/steve-core/src/main/java/de/rwth/idsg/steve/web/dto/EndpointInfo.java
@@ -18,7 +18,6 @@
*/
package de.rwth.idsg.steve.web.dto;
-import de.rwth.idsg.steve.SteveConfiguration;
import lombok.Getter;
import lombok.ToString;
@@ -37,15 +36,10 @@ public class EndpointInfo {
private final ItemsWithInfo ocppSoap;
private final ItemsWithInfo ocppWebSocket;
- public EndpointInfo(SteveConfiguration config) {
- this.webInterface = new ItemsWithInfo(
- "Access the web interface using", config.getPaths().getManagerMapping() + "/home");
- this.ocppSoap = new ItemsWithInfo(
- "SOAP endpoint for OCPP",
- config.getPaths().getSoapMapping() + config.getPaths().getRouterEndpointPath());
- this.ocppWebSocket = new ItemsWithInfo(
- "WebSocket/JSON endpoint for OCPP",
- config.getPaths().getWebsocketMapping() + config.getPaths().getRouterEndpointPath() + "/(chargeBoxId)");
+ public EndpointInfo() {
+ this.webInterface = new ItemsWithInfo("Access the web interface using", "/manager/home");
+ this.ocppSoap = new ItemsWithInfo("SOAP endpoint for OCPP", "/soap/services/ocpp");
+ this.ocppWebSocket = new ItemsWithInfo("WebSocket/JSON endpoint for OCPP", "/ws/ocpp/(chargeBoxId)");
}
@Getter
diff --git a/steve-jooq/pom.xml b/steve-jooq/pom.xml
index ff383699c..0f3b2d8cf 100644
--- a/steve-jooq/pom.xml
+++ b/steve-jooq/pom.xml
@@ -9,313 +9,31 @@
steve-jooq
-
- stevedb
- stevedb
- steve
- changeme
-
- jdbc:mysql://localhost:3306/${db.schema}?sslMode=PREFERRED&serverTimezone=UTC
-
-
-
-
- de.rwth.idsg
- steve-core
-
-
- org.jooq
- jooq
- ${jooq.version}
-
-
- org.flywaydb
- flyway-core
- ${flyway.version}
-
-
- org.flywaydb
- flyway-mysql
- ${flyway.version}
-
-
- com.mysql
- mysql-connector-j
- ${mysql.jdbc.version}
-
-
- com.zaxxer
- HikariCP
- 7.0.2
-
-
- org.springframework
- spring-context
-
-
- com.fasterxml.jackson.core
- jackson-databind
-
-
- com.neovisionaries
- nv-i18n
-
-
- org.slf4j
- slf4j-api
-
-
- org.projectlombok
- lombok
- ${lombok.version}
- provided
-
-
-
-
-
- useRealDatabase
-
-
-
- org.flywaydb
- flyway-maven-plugin
- ${flyway.version}
-
-
- SET default_storage_engine=InnoDB;
-
- true
-
-
-
-
- true
- com.mysql.cj.jdbc.Driver
- ${db.jdbc.url}
- ${db.user}
- ${db.password}
-
- ${db.schema}
-
-
- filesystem:src/main/resources/db/migration
-
-
-
-
- org.flywaydb
- flyway-mysql
- ${flyway.version}
-
-
- com.mysql
- mysql-connector-j
- ${mysql.jdbc.version}
-
-
-
-
-
-
- 1-flyway
-
- migrate
-
- generate-sources
-
-
-
-
-
- org.jooq
- jooq-codegen-maven
- ${jooq.version}
-
-
-
-
- com.mysql.cj.jdbc.Driver
- ${db.jdbc.url}
- ${db.user}
- ${db.password}
-
-
-
-
- org.jooq.meta.mysql.MySQLDatabase
- .*
-
- ${db.schema}
- false
-
-
-
- BOOLEAN
-
- (?i:(TINY|SMALL|MEDIUM|BIG)?INT(UNSIGNED)?\(1\))
-
-
- BOOLEAN
- .*\.OCPP_TAG_ACTIVITY\.(IN_TRANSACTION|BLOCKED)
-
-
- JSON
- .*\.WEB_USER\.(AUTHORITIES)
-
-
-
-
- true
-
-
-
- jooq.steve.db
- ${project.build.directory}/generated-sources/jooq
-
-
-
-
-
- org.jooq
- jooq-meta
- ${jooq.version}
-
-
- org.jooq
- jooq-codegen
- ${jooq.version}
-
-
- com.mysql
- mysql-connector-j
- ${mysql.jdbc.version}
-
-
-
-
-
-
- 2-jooq
-
- generate
-
- generate-sources
-
-
-
-
-
-
-
- useTestContainers
-
- true
-
-
-
-
- org.testcontainers
- testcontainers-jooq-codegen-maven-plugin
- 0.0.4
-
-
- org.testcontainers
- mysql
- ${testcontainers.version}
-
-
- com.mysql
- mysql-connector-j
- ${mysql.jdbc.version}
-
-
-
-
- generate-jooq-sources
-
- generate
-
- generate-sources
-
-
- MYSQL
- mysql:8.0
- root
-
- ${db.schema}
-
-
-
- SET default_storage_engine=InnoDB;
-
- true
-
-
-
-
- true
-
- filesystem:src/main/resources/db/migration
-
-
-
-
-
-
- org.jooq.meta.mysql.MySQLDatabase
- .*
-
-
- ${db.schema}
- false
-
-
-
- BOOLEAN
-
- (?i:(TINY|SMALL|MEDIUM|BIG)?INT(UNSIGNED)?\(1\))
-
-
- BOOLEAN
- .*\.OCPP_TAG_ACTIVITY\.(IN_TRANSACTION|BLOCKED)
-
-
- JSON
- .*\.WEB_USER\.(AUTHORITIES)
-
-
-
-
- true
-
-
- jooq.steve.db
- ${project.build.directory}/generated-sources/jooq
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.14.0
+
+
+ default-compile
+ none
+
+
+ default-testCompile
+ none
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.5.4
+
+ true
+
+
+
+
diff --git a/steve-ocpp-transport-soap/src/main/java/de/rwth/idsg/steve/config/OcppSoapConfiguration.java b/steve-ocpp-transport-soap/src/main/java/de/rwth/idsg/steve/config/OcppSoapConfiguration.java
index 426a2880c..44327ec06 100644
--- a/steve-ocpp-transport-soap/src/main/java/de/rwth/idsg/steve/config/OcppSoapConfiguration.java
+++ b/steve-ocpp-transport-soap/src/main/java/de/rwth/idsg/steve/config/OcppSoapConfiguration.java
@@ -18,7 +18,6 @@
*/
package de.rwth.idsg.steve.config;
-import de.rwth.idsg.steve.SteveConfiguration;
import de.rwth.idsg.steve.ocpp.soap.MediatorInInterceptor;
import de.rwth.idsg.steve.ocpp.soap.MessageHeaderInterceptor;
import de.rwth.idsg.steve.ocpp.soap.MessageIdInterceptor;
@@ -59,7 +58,7 @@ public class OcppSoapConfiguration {
LogUtils.setLoggerClass(Slf4jLogger.class);
}
- private final SteveConfiguration config;
+ private final SteveProperties steveProperties;
private final ocpp.cs._2010._08.CentralSystemService ocpp12Server;
private final ocpp.cs._2012._06.CentralSystemService ocpp15Server;
private final ocpp.cs._2015._10.CentralSystemService ocpp16Server;
@@ -72,9 +71,9 @@ public OcppSoapConfiguration(
ocpp.cs._2012._06.CentralSystemService ocpp15Server,
ocpp.cs._2015._10.CentralSystemService ocpp16Server,
MessageHeaderInterceptor messageHeaderInterceptor,
- SteveConfiguration config,
+ SteveProperties steveProperties,
Bus bus) {
- this.config = config;
+ this.steveProperties = steveProperties;
this.ocpp12Server = ocpp12Server;
this.ocpp15Server = ocpp15Server;
this.ocpp16Server = ocpp16Server;
@@ -94,9 +93,13 @@ public void configure() {
// Just a dummy service to route incoming messages to the appropriate service version. This should be the last
// one to be created, since in MediatorInInterceptor we go over created/registered services and build a map.
- List> mediator = singletonList(new MediatorInInterceptor(bus, config));
+ List> mediator = singletonList(new MediatorInInterceptor(bus, steveProperties));
createOcppService(
- bus, ocpp12Server, config.getPaths().getRouterEndpointPath(), mediator, Collections.emptyList());
+ bus,
+ ocpp12Server,
+ steveProperties.getOcpp().getSoap().getRouterEndpointPath(),
+ mediator,
+ Collections.emptyList());
}
@Bean(name = Bus.DEFAULT_BUS_ID, destroyMethod = "shutdown")
diff --git a/steve-ocpp-transport-soap/src/main/java/de/rwth/idsg/steve/ocpp/soap/ClientProvider.java b/steve-ocpp-transport-soap/src/main/java/de/rwth/idsg/steve/ocpp/soap/ClientProvider.java
index 90ede9ca0..2658aafc6 100644
--- a/steve-ocpp-transport-soap/src/main/java/de/rwth/idsg/steve/ocpp/soap/ClientProvider.java
+++ b/steve-ocpp-transport-soap/src/main/java/de/rwth/idsg/steve/ocpp/soap/ClientProvider.java
@@ -19,7 +19,6 @@
package de.rwth.idsg.steve.ocpp.soap;
import com.oneandone.compositejks.SslContextBuilder;
-import de.rwth.idsg.steve.SteveConfiguration;
import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.ext.logging.LoggingFeature;
@@ -28,6 +27,7 @@
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.ws.addressing.WSAddressingFeature;
import org.jspecify.annotations.Nullable;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.net.ssl.SSLContext;
@@ -43,12 +43,15 @@ public class ClientProvider {
private final @Nullable TLSClientParameters tlsClientParams;
private final LoggingFeature loggingFeature;
- public ClientProvider(SteveConfiguration config, LoggingFeature loggingFeature) {
+ public ClientProvider(
+ LoggingFeature loggingFeature,
+ @Value("${server.ssl.key-store:}") String keyStore,
+ @Value("${server.ssl.key-store-password:}") String keyStorePassword,
+ @Value("${server.ssl.enabled:false}") boolean sslEnabled) {
this.loggingFeature = loggingFeature;
- var jettyConfig = config.getJetty();
- if (shouldInitSSL(jettyConfig)) {
+ if (shouldInitSSL(sslEnabled, keyStore, keyStorePassword)) {
tlsClientParams = new TLSClientParameters();
- tlsClientParams.setSslContext(setupSSL(jettyConfig));
+ tlsClientParams.setSslContext(setupSSL(keyStore, keyStorePassword));
} else {
tlsClientParams = null;
}
@@ -77,19 +80,18 @@ private JaxWsProxyFactoryBean createBean(String endpointAddress) {
return f;
}
- private static boolean shouldInitSSL(SteveConfiguration.Jetty jettyConfig) {
- return jettyConfig.getKeyStorePath() != null
- && !jettyConfig.getKeyStorePath().isBlank()
- && jettyConfig.getKeyStorePassword() != null
- && !jettyConfig.getKeyStorePassword().isBlank();
+ private static boolean shouldInitSSL(boolean sslEnabled, String keyStore, String keyStorePassword) {
+ return sslEnabled
+ && keyStore != null
+ && !keyStore.isBlank()
+ && keyStorePassword != null
+ && !keyStorePassword.isBlank();
}
- private static SSLContext setupSSL(SteveConfiguration.Jetty jettyConfig) {
+ private static SSLContext setupSSL(String keyStore, String keyStorePassword) {
try {
- var keyStorePath = jettyConfig.getKeyStorePath();
- var keyStorePwd = jettyConfig.getKeyStorePassword();
return SslContextBuilder.builder()
- .keyStoreFromFile(keyStorePath, keyStorePwd)
+ .keyStoreFromFile(keyStore, keyStorePassword)
.usingTLS()
.usingDefaultAlgorithm()
.usingKeyManagerPasswordFromKeyStore()
diff --git a/steve-ocpp-transport-soap/src/main/java/de/rwth/idsg/steve/ocpp/soap/MediatorInInterceptor.java b/steve-ocpp-transport-soap/src/main/java/de/rwth/idsg/steve/ocpp/soap/MediatorInInterceptor.java
index deb87a99e..0e6fc4e53 100644
--- a/steve-ocpp-transport-soap/src/main/java/de/rwth/idsg/steve/ocpp/soap/MediatorInInterceptor.java
+++ b/steve-ocpp-transport-soap/src/main/java/de/rwth/idsg/steve/ocpp/soap/MediatorInInterceptor.java
@@ -18,7 +18,7 @@
*/
package de.rwth.idsg.steve.ocpp.soap;
-import de.rwth.idsg.steve.SteveConfiguration;
+import de.rwth.idsg.steve.config.SteveProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.cxf.Bus;
import org.apache.cxf.binding.soap.SoapMessage;
@@ -51,10 +51,10 @@ public class MediatorInInterceptor extends AbstractPhaseInterceptor
private final Map actualServers;
- public MediatorInInterceptor(Bus bus, SteveConfiguration config) {
+ public MediatorInInterceptor(Bus bus, SteveProperties steveProperties) {
super(Phase.POST_STREAM);
super.addBefore(StaxInInterceptor.class.getName());
- actualServers = initServerLookupMap(bus, config);
+ actualServers = initServerLookupMap(bus, steveProperties);
}
public final void handleMessage(SoapMessage message) {
@@ -104,7 +104,7 @@ public final void handleMessage(SoapMessage message) {
* redirect to the version-specific implementation according to the namespace
* of the incoming message.
*/
- private static Map initServerLookupMap(Bus bus, SteveConfiguration config) {
+ private static Map initServerLookupMap(Bus bus, SteveProperties steveProperties) {
String exceptionMsg = "The services are not created and/or registered to the bus yet.";
ServerRegistry serverRegistry = bus.getExtension(ServerRegistry.class);
@@ -123,7 +123,7 @@ private static Map initServerLookupMap(Bus bus, SteveConfigurati
String address = info.getAddress();
// exclude the 'dummy' routing server
- if (config.getPaths().getRouterEndpointPath().equals(address)) {
+ if (steveProperties.getOcpp().getSoap().getRouterEndpointPath().equals(address)) {
continue;
}
diff --git a/steve-ui-jsp/pom.xml b/steve-ui-jsp/pom.xml
index f49f23de7..f46a28c92 100644
--- a/steve-ui-jsp/pom.xml
+++ b/steve-ui-jsp/pom.xml
@@ -22,26 +22,11 @@
org.springframework
spring-webmvc
-
-
-
- commons-logging
- commons-logging
-
-
- org.springframework
- spring-jcl
-
-
org.springframework.security
spring-security-web
-
- org.hibernate.validator
- hibernate-validator
-
jakarta.servlet.jsp.jstl
jakarta.servlet.jsp.jstl-api
@@ -52,27 +37,19 @@
jakarta.servlet.jsp.jstl
3.0.1
-
- org.eclipse.jetty.ee10
- jetty-ee10-apache-jsp
-
-
-
-
-
org.owasp.encoder
encoder-jakarta-jsp
${owasp-encoder.version}
-
- ch.qos.logback
- logback-classic
-
com.neovisionaries
nv-i18n
+
+ org.apache.tomcat.embed
+ tomcat-embed-jasper
+
org.junit.jupiter
@@ -102,28 +79,5 @@
-
-
-
-
- org.eclipse.jetty.ee10
- jetty-ee10-jspc-maven-plugin
- ${jetty.version}
-
-
- jspc
-
- jspc
-
- compile
-
- ${basedir}/src/main/resources/webapp
- ${basedir}/src/main/resources/webapp/WEB-INF/web.xml
- ${basedir}/target/classes/webapp/WEB-INF/web.xml-frag
-
-
-
-
-
diff --git a/steve-ui-jsp/src/main/java/de/rwth/idsg/steve/config/JspConfiguration.java b/steve-ui-jsp/src/main/java/de/rwth/idsg/steve/config/JspConfiguration.java
deleted file mode 100644
index dcf055cf6..000000000
--- a/steve-ui-jsp/src/main/java/de/rwth/idsg/steve/config/JspConfiguration.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.Ordered;
-import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
-import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-import org.springframework.web.servlet.view.InternalResourceViewResolver;
-
-@Configuration
-public class JspConfiguration implements WebMvcConfigurer {
-
- /**
- * Resolver for JSP views/templates. Controller classes process the requests
- * and forward to JSP files for rendering.
- */
- @Bean
- public InternalResourceViewResolver urlBasedViewResolver() {
- InternalResourceViewResolver resolver = new InternalResourceViewResolver();
- resolver.setPrefix("/WEB-INF/views/");
- resolver.setSuffix(".jsp");
- return resolver;
- }
-
- /**
- * Resource path for static content of the Web interface.
- */
- @Override
- public void addResourceHandlers(final ResourceHandlerRegistry registry) {
- registry.addResourceHandler("/static/**").addResourceLocations("static/");
- }
-
- @Override
- public void addViewControllers(ViewControllerRegistry registry) {
- registry.addViewController("/manager/signin").setViewName("signin");
- registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
- }
-}
diff --git a/steve-ui-jsp/src/main/java/de/rwth/idsg/steve/web/controller/AboutSettingsController.java b/steve-ui-jsp/src/main/java/de/rwth/idsg/steve/web/controller/AboutSettingsController.java
index 60dbb2ce2..6692a2105 100644
--- a/steve-ui-jsp/src/main/java/de/rwth/idsg/steve/web/controller/AboutSettingsController.java
+++ b/steve-ui-jsp/src/main/java/de/rwth/idsg/steve/web/controller/AboutSettingsController.java
@@ -19,7 +19,7 @@
package de.rwth.idsg.steve.web.controller;
import de.rwth.idsg.steve.NotificationFeature;
-import de.rwth.idsg.steve.SteveConfiguration;
+import de.rwth.idsg.steve.config.SteveProperties;
import de.rwth.idsg.steve.repository.GenericRepository;
import de.rwth.idsg.steve.repository.SettingsRepository;
import de.rwth.idsg.steve.service.MailService;
@@ -56,7 +56,7 @@ public class AboutSettingsController {
private final SettingsRepository settingsRepository;
private final MailService mailService;
private final ReleaseCheckService releaseCheckService;
- private final SteveConfiguration config;
+ private final SteveProperties steveProperties;
private final EndpointInfo info;
// -------------------------------------------------------------------------
@@ -72,7 +72,7 @@ public class AboutSettingsController {
@GetMapping(value = ABOUT_PATH)
public String getAbout(Model model) {
- model.addAttribute("version", config.getSteveVersion());
+ model.addAttribute("version", steveProperties.getVersion());
model.addAttribute("db", genericRepository.getDBVersion().orElse(null));
model.addAttribute("logFile", logController.getLogFilePath());
model.addAttribute("systemTime", Instant.now());
diff --git a/steve/pom.xml b/steve/pom.xml
index 227c90147..6c334630e 100644
--- a/steve/pom.xml
+++ b/steve/pom.xml
@@ -41,6 +41,32 @@
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jetty
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.boot
+ spring-boot-starter-jooq
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
de.rwth.idsg
steve-jooq
@@ -85,58 +111,6 @@
5.5
-
-
- org.springframework.security
- spring-security-config
-
-
-
-
- ch.qos.logback
- logback-classic
-
-
- org.slf4j
- slf4j-api
- ${slf4j.version}
-
-
- org.slf4j
- jcl-over-slf4j
- ${slf4j.version}
-
-
-
-
- org.eclipse.jetty
- jetty-server
-
-
- org.eclipse.jetty.ee10
- jetty-ee10-webapp
-
-
- org.eclipse.jetty.ee10
- jetty-ee10-annotations
-
-
- org.eclipse.jetty
- jetty-rewrite
-
-
- org.eclipse.jetty.ee10.websocket
- jetty-ee10-websocket-jetty-server
-
-
- org.eclipse.jetty.compression
- jetty-compression-server
-
-
- org.eclipse.jetty.compression
- jetty-compression-gzip
-
-
com.mysql
@@ -151,8 +125,8 @@
- org.springframework
- spring-test
+ org.springframework.boot
+ spring-boot-starter-test
test
@@ -160,37 +134,12 @@
jetty-websocket-jetty-client
test
-
- org.junit.jupiter
- junit-jupiter-engine
- test
-
-
- org.junit.jupiter
- junit-jupiter-params
- test
-
-
- org.mockito
- mockito-junit-jupiter
- test
-
net.bytebuddy
byte-buddy
1.17.7
test
-
- org.assertj
- assertj-core
- test
-
-
- com.jayway.jsonpath
- json-path
- test
-
@@ -210,6 +159,10 @@
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
io.github.git-commit-id
git-commit-id-maven-plugin
@@ -227,38 +180,6 @@
-
-
- org.apache.maven.plugins
- maven-dependency-plugin
- 3.8.1
-
-
- copy-dependencies
-
- copy-dependencies
-
- prepare-package
-
- ${project.build.directory}/libs
- runtime
-
-
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
-
-
-
- true
- libs/
- de.rwth.idsg.steve.Application
-
-
-
-
diff --git a/steve/src/main/java/de/rwth/idsg/steve/Application.java b/steve/src/main/java/de/rwth/idsg/steve/Application.java
deleted file mode 100644
index 3640a6a52..000000000
--- a/steve/src/main/java/de/rwth/idsg/steve/Application.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve;
-
-import de.rwth.idsg.steve.utils.LogFileRetriever;
-import de.rwth.idsg.steve.utils.SteveConfigurationReader;
-import lombok.extern.slf4j.Slf4j;
-
-import java.nio.file.Path;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-import java.util.Optional;
-import java.util.TimeZone;
-
-/**
- * @author Sevket Goekay
- * @since 14.01.2015
- */
-@Slf4j
-public class Application {
-
- private final SteveConfiguration config;
- private final JettyServer server;
-
- public Application(SteveConfiguration config, LogFileRetriever logFileRetriever) {
- this.config = config;
- this.server = new JettyServer(config, logFileRetriever);
- }
-
- public static void main(String[] args) throws Exception {
- // For Hibernate validator
- System.setProperty("org.jboss.logging.provider", "slf4j");
-
- SteveConfiguration sc = SteveConfigurationReader.readSteveConfiguration("main.properties");
- log.info("Loaded the properties. Starting with the '{}' profile", sc.getProfile());
-
- var zoneId = ZoneId.of(sc.getTimeZoneId());
- TimeZone.setDefault(TimeZone.getTimeZone(zoneId));
- log.info(
- "Date/time zone of the application is set to {}. Current date/time: {}",
- sc.getTimeZoneId(),
- ZonedDateTime.now(zoneId));
-
- LogFileRetriever logFileRetriever = new LogFileRetriever();
- Optional path = logFileRetriever.getPath();
- boolean loggingToFile = path.isPresent();
- if (loggingToFile) {
- System.out.println("Log file: " + path.get().toAbsolutePath());
- }
-
- Application app = new Application(sc, logFileRetriever);
-
- try {
- app.start();
- app.join();
- } catch (Exception e) {
- log.error("Application failed to start", e);
-
- if (loggingToFile) {
- System.err.println("Application failed to start");
- e.printStackTrace();
- }
-
- app.stop();
- }
- }
-
- public void start() throws Exception {
- server.start();
- }
-
- public void join() throws Exception {
- server.join();
- }
-
- public void stop() throws Exception {
- server.stop();
- }
-}
diff --git a/steve/src/main/java/de/rwth/idsg/steve/JettyServer.java b/steve/src/main/java/de/rwth/idsg/steve/JettyServer.java
deleted file mode 100644
index 2efe1d698..000000000
--- a/steve/src/main/java/de/rwth/idsg/steve/JettyServer.java
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve;
-
-import de.rwth.idsg.steve.utils.LogFileRetriever;
-import de.rwth.idsg.steve.web.dto.EndpointInfo;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.jetty.http.HttpScheme;
-import org.eclipse.jetty.http.HttpVersion;
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.ForwardedRequestCustomizer;
-import org.eclipse.jetty.server.HttpConfiguration;
-import org.eclipse.jetty.server.HttpConnectionFactory;
-import org.eclipse.jetty.server.SecureRequestCustomizer;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.SslConnectionFactory;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-import org.eclipse.jetty.util.thread.QueuedThreadPool;
-import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
-import org.jspecify.annotations.Nullable;
-
-import java.net.DatagramSocket;
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.NetworkInterface;
-import java.net.Socket;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import java.util.function.Function;
-
-/**
- * @author Sevket Goekay
- * @since 12.12.2014
- */
-@Slf4j
-public class JettyServer {
-
- private final SteveConfiguration config;
- private final LogFileRetriever logFileRetriever;
- private final EndpointInfo info;
-
- private @Nullable Server server;
- private SteveAppContext steveAppContext;
-
- private static final int MIN_THREADS = 4;
- private static final int MAX_THREADS = 50;
-
- private static final long STOP_TIMEOUT = TimeUnit.SECONDS.toMillis(5);
- private static final long IDLE_TIMEOUT = TimeUnit.MINUTES.toMillis(1);
-
- public JettyServer(SteveConfiguration config, LogFileRetriever logFileRetriever) {
- this.config = config;
- this.logFileRetriever = logFileRetriever;
- this.info = new EndpointInfo(config);
- }
-
- /**
- * A fully configured Jetty Server instance
- */
- private void prepare() {
-
- // === jetty.xml ===
- // Setup Threadpool
- QueuedThreadPool threadPool = new QueuedThreadPool();
- threadPool.setMinThreads(MIN_THREADS);
- threadPool.setMaxThreads(MAX_THREADS);
-
- // Server
- server = new Server(threadPool);
-
- // Scheduler
- server.addBean(new ScheduledExecutorScheduler());
-
- // HTTP Configuration
- HttpConfiguration httpConfig = new HttpConfiguration();
- httpConfig.setSecureScheme(HttpScheme.HTTPS.asString());
- httpConfig.setSecurePort(config.getJetty().getHttpsPort());
- httpConfig.setOutputBufferSize(32768);
- httpConfig.setRequestHeaderSize(8192);
- httpConfig.setResponseHeaderSize(8192);
- httpConfig.setSendServerVersion(false);
- httpConfig.setSendDateHeader(false);
- httpConfig.setSendXPoweredBy(false);
-
- // make sure X-Forwarded-For headers are picked up if set (e.g. by a load balancer)
- // https://github.com/steve-community/steve/pull/570
- httpConfig.addCustomizer(new ForwardedRequestCustomizer());
-
- // Extra options
- server.setDumpAfterStart(false);
- server.setDumpBeforeStop(false);
- server.setStopAtShutdown(true);
- server.setStopTimeout(STOP_TIMEOUT);
-
- if (config.getJetty().isHttpEnabled()) {
- server.addConnector(httpConnector(httpConfig));
- }
-
- if (config.getJetty().isHttpsEnabled()) {
- server.addConnector(httpsConnector(httpConfig));
- }
-
- steveAppContext = new SteveAppContext(config, logFileRetriever, info);
- server.setHandler(steveAppContext.getHandler());
- }
-
- private ServerConnector httpConnector(HttpConfiguration httpconfig) {
- // === jetty-http.xml ===
- ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(httpconfig));
- http.setHost(config.getJetty().getServerHost());
- http.setPort(config.getJetty().getHttpPort());
- http.setIdleTimeout(IDLE_TIMEOUT);
- return http;
- }
-
- private ServerConnector httpsConnector(HttpConfiguration httpconfig) {
- // === jetty-https.xml ===
- // SSL Context Factory
- SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
- sslContextFactory.setKeyStorePath(config.getJetty().getKeyStorePath());
- sslContextFactory.setKeyStorePassword(config.getJetty().getKeyStorePassword());
- sslContextFactory.setKeyManagerPassword(config.getJetty().getKeyStorePassword());
-
- // SSL HTTP Configuration
- HttpConfiguration httpsConfig = new HttpConfiguration(httpconfig);
- httpsConfig.addCustomizer(new SecureRequestCustomizer());
-
- // SSL Connector
- ServerConnector https = new ServerConnector(
- server,
- new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
- new HttpConnectionFactory(httpsConfig));
- https.setHost(config.getJetty().getServerHost());
- https.setPort(config.getJetty().getHttpsPort());
- https.setIdleTimeout(IDLE_TIMEOUT);
- return https;
- }
-
- /**
- * Starts the Jetty Server instance
- */
- public void start() throws Exception {
- prepare();
-
- if (server != null) {
- server.start();
- steveAppContext.configureWebSocket();
- populateEndpointInfo();
- }
- }
-
- /**
- * Join the server thread with the current thread
- */
- public void join() throws Exception {
- if (server != null) {
- server.join();
- }
- }
-
- public void stop() throws Exception {
- if (server != null) {
- server.stop();
- steveAppContext.close();
- }
- }
-
- public boolean isStarted() {
- return server != null && server.isStarted();
- }
-
- public void populateEndpointInfo() {
- if (server == null) {
- return;
- }
- var list = Arrays.stream(server.getConnectors())
- .map(this::getConnectorPath)
- .flatMap(ips -> ips.entrySet().stream())
- .toList();
- setList(list, isSecured -> isSecured ? "https" : "http", info.getWebInterface(), info.getOcppSoap());
- setList(list, isSecured -> isSecured ? "wss" : "ws", info.getOcppWebSocket());
- }
-
- private Map getConnectorPath(Connector c) {
- var sc = (ServerConnector) c;
-
- var isSecure = sc.getDefaultConnectionFactory() instanceof SslConnectionFactory;
- var layout = "://%s:%d" + config.getPaths().getContextPath();
-
- return getIps(sc, config.getJetty().getServerHost()).stream()
- .map(k -> String.format(layout, k, sc.getPort()))
- .collect(HashMap::new, (m, v) -> m.put(v, isSecure), HashMap::putAll);
- }
-
- private static Set getIps(ServerConnector sc, String serverHost) {
- var ips = new HashSet();
- var host = sc.getHost();
- if (host == null || host.equals("0.0.0.0")) {
- ips.addAll(getPossibleIpAddresses(serverHost));
- } else {
- ips.add(host);
- }
- return ips;
- }
-
- private static void setList(
- List> list,
- Function prefix,
- EndpointInfo.ItemsWithInfo... items) {
- var ws = list.stream().map(e -> prefix.apply(e.getValue()) + e.getKey()).toList();
- for (EndpointInfo.ItemsWithInfo item : items) {
- item.setData(ws);
- }
- }
-
- /**
- * Uses different APIs to find out the IP of this machine.
- */
- private static List getPossibleIpAddresses(String serverHost) {
- final String host = "treibhaus.informatik.rwth-aachen.de";
- final List ips = new ArrayList<>();
-
- try {
- ips.add(InetAddress.getLocalHost().getHostAddress());
- } catch (Exception e) {
- // fail silently
- }
-
- try {
- Socket socket = new Socket();
- socket.connect(new InetSocketAddress(host, 80));
- ips.add(socket.getLocalAddress().getHostAddress());
- } catch (Exception e) {
- // fail silently
- }
-
- // https://stackoverflow.com/a/38342964
- try (DatagramSocket socket = new DatagramSocket()) {
- socket.connect(InetAddress.getByName("8.8.8.8"), 10002);
- ips.add(socket.getLocalAddress().getHostAddress());
- } catch (Exception e) {
- // fail silently
- }
-
- // https://stackoverflow.com/a/20418809
- try {
- for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces();
- ifaces.hasMoreElements(); ) {
- NetworkInterface iface = ifaces.nextElement();
- for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements(); ) {
- InetAddress inetAddr = inetAddrs.nextElement();
- if (!inetAddr.isLoopbackAddress() && (inetAddr instanceof Inet4Address)) {
- ips.add(inetAddr.getHostAddress());
- }
- }
- }
-
- } catch (Exception e) {
- // fail silently
- }
-
- ips.removeIf("0.0.0.0"::equals);
-
- if (ips.isEmpty()) {
- // Well, we failed to read from system, fall back to main.properties.
- // Better than nothing
- ips.add(serverHost);
- }
-
- return ips;
- }
-}
diff --git a/steve/src/main/java/de/rwth/idsg/steve/SteveAppContext.java b/steve/src/main/java/de/rwth/idsg/steve/SteveAppContext.java
deleted file mode 100644
index a079b9341..000000000
--- a/steve/src/main/java/de/rwth/idsg/steve/SteveAppContext.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve;
-
-import de.rwth.idsg.steve.utils.LogFileRetriever;
-import de.rwth.idsg.steve.web.dto.EndpointInfo;
-import lombok.Getter;
-import org.apache.cxf.transport.servlet.CXFServlet;
-import org.apache.tomcat.InstanceManager;
-import org.apache.tomcat.SimpleInstanceManager;
-import org.eclipse.jetty.compression.server.CompressionHandler;
-import org.eclipse.jetty.ee10.apache.jsp.JettyJasperInitializer;
-import org.eclipse.jetty.ee10.servlet.FilterHolder;
-import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
-import org.eclipse.jetty.ee10.servlet.ServletHolder;
-import org.eclipse.jetty.ee10.webapp.WebAppContext;
-import org.eclipse.jetty.ee10.websocket.server.JettyWebSocketServerContainer;
-import org.eclipse.jetty.rewrite.handler.RedirectPatternRule;
-import org.eclipse.jetty.rewrite.handler.RewriteHandler;
-import org.eclipse.jetty.server.Handler;
-import org.eclipse.jetty.util.component.AbstractLifeCycle;
-import org.eclipse.jetty.util.resource.ResourceFactory;
-import org.eclipse.jetty.websocket.core.WebSocketConstants;
-import org.springframework.context.support.GenericApplicationContext;
-import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
-import org.springframework.web.context.ContextLoaderListener;
-import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
-import org.springframework.web.filter.DelegatingFilterProxy;
-import org.springframework.web.servlet.DispatcherServlet;
-
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.Set;
-import jakarta.servlet.DispatcherType;
-
-import static de.rwth.idsg.steve.config.OcppWebSocketConfiguration.IDLE_TIMEOUT;
-import static de.rwth.idsg.steve.config.OcppWebSocketConfiguration.MAX_MSG_SIZE;
-
-/**
- * @author Sevket Goekay
- * @since 07.04.2015
- */
-public class SteveAppContext {
-
- private final SteveConfiguration config;
- private final AnnotationConfigWebApplicationContext springContext;
- private final WebAppContext webAppContext;
-
- @Getter
- private final Handler handler;
- // ClosedFileSystemException if the resource factory is linked to the context
- // https://github.com/jetty/jetty.project/issues/13592
- private final ResourceFactory.Closeable webAppResourceFactory = ResourceFactory.closeable();
-
- public SteveAppContext(SteveConfiguration config, LogFileRetriever logFileRetriever, EndpointInfo info) {
- this.config = config;
- springContext = new AnnotationConfigWebApplicationContext();
- var context = new GenericApplicationContext();
- context.registerBean(SteveConfiguration.class, () -> config);
- context.registerBean(LogFileRetriever.class, () -> logFileRetriever);
- context.registerBean(EndpointInfo.class, () -> info);
- context.refresh();
- context.setParent(springContext.getParent());
- springContext.setParent(context);
- springContext.scan("de.rwth.idsg.steve.config");
- webAppContext = createWebAppContext();
- // Run rewrite first, then dispatch to contexts
- handler = new Handler.Sequence(createRedirectHandler(config), webAppContext);
- }
-
- public void close() {
- webAppResourceFactory.close();
- }
-
- /**
- * Otherwise, defaults come from {@link WebSocketConstants}
- */
- public void configureWebSocket() {
- var container = JettyWebSocketServerContainer.getContainer(webAppContext.getServletContext());
- container.setMaxTextMessageSize(MAX_MSG_SIZE);
- container.setIdleTimeout(IDLE_TIMEOUT);
- }
-
- private WebAppContext createWebAppContext() {
- var ctx = new WebAppContext();
- ctx.setContextPath(config.getPaths().getContextPath());
- ctx.setBaseResource(webAppResourceFactory.newClassLoaderResource("webapp/"));
-
- // if during startup an exception happens, do not swallow it, throw it
- ctx.setThrowUnavailableOnStartupException(true);
-
- // Disable directory listings if no index.html is found.
- ctx.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", "false");
-
- ctx.addEventListener(new ContextLoaderListener(springContext));
-
- var web = new ServletHolder("spring-dispatcher", new DispatcherServlet(springContext));
- ctx.addServlet(web, config.getPaths().getRootMapping());
-
- var cxf = new ServletHolder("cxf", new CXFServlet());
- ctx.addServlet(cxf, config.getPaths().getSoapMapping() + "/*");
-
- // add spring security
- ctx.addFilter(
- // The bean name is not arbitrary, but is as expected by Spring
- new FilterHolder(
- new DelegatingFilterProxy(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)),
- config.getPaths().getRootMapping() + "*",
- EnumSet.allOf(DispatcherType.class));
-
- /*
- * Help by:
- * https://github.com/jetty/jetty-examples/tree/12.0.x/embedded/ee10-jsp
- * https://github.com/jetty-project/embedded-jetty-jsp
- * https://github.com/jasonish/jetty-springmvc-jsp-template
- * http://examples.javacodegeeks.com/enterprise-java/jetty/jetty-jsp-example
- */
- ctx.addBean(new EmbeddedJspStarter(ctx));
- ctx.setAttribute(InstanceManager.class.getName(), new SimpleInstanceManager());
-
- if (config.getJetty().isGzipEnabled()) {
- // Insert compression in front of the webapp handler chain, keep the context intact
- ctx.insertHandler(new CompressionHandler());
- }
-
- return ctx;
- }
-
- private static Handler createRedirectHandler(SteveConfiguration config) {
- var rewrite = new RewriteHandler();
- for (var redirect : getRedirectSet(config)) {
- var rule = new RedirectPatternRule();
- rule.setTerminating(true);
- rule.setPattern(redirect);
- rule.setLocation(
- config.getPaths().getContextPath() + config.getPaths().getManagerMapping() + "/home");
- rewrite.addRule(rule);
- }
- return rewrite;
- }
-
- private static Set getRedirectSet(SteveConfiguration config) {
- var path = config.getPaths().getContextPath();
-
- var redirectSet = HashSet.newHashSet(3);
- redirectSet.add("");
- redirectSet.add(path);
-
- // Otherwise (if path = ""), we would already be at root of the server ("/")
- // and using the redirection below would cause an infinite loop.
- if (!"".equals(path)) {
- redirectSet.add(path + "/");
- }
-
- return redirectSet;
- }
-
- /**
- * From: https://github.com/jetty/jetty-examples/blob/12.0.x/embedded/ee10-jsp/src/main/java/examples/EmbeddedJspStarter.java
- *
- * JspStarter for embedded ServletContextHandlers
- *
- * This is added as a bean that is a jetty LifeCycle on the ServletContextHandler.
- * This bean's doStart method will be called as the ServletContextHandler starts,
- * and will call the ServletContainerInitializer for the jsp engine.
- */
- public static class EmbeddedJspStarter extends AbstractLifeCycle {
-
- private final JettyJasperInitializer sci;
- private final ServletContextHandler context;
-
- public EmbeddedJspStarter(ServletContextHandler context) {
- this.sci = new JettyJasperInitializer();
- this.context = context;
-
- // we dont need all this from the example, since our JSPs are precompiled
- //
- // StandardJarScanner jarScanner = new StandardJarScanner();
- // StandardJarScanFilter jarScanFilter = new StandardJarScanFilter();
- // jarScanFilter.setTldScan("taglibs-standard-impl-*");
- // jarScanFilter.setTldSkip("apache-*,ecj-*,jetty-*,asm-*,javax.servlet-*,javax.annotation-*,taglibs-standard-spec-*");
- // jarScanner.setJarScanFilter(jarScanFilter);
- // this.context.setAttribute("org.apache.tomcat.JarScanner", jarScanner);
- }
-
- @Override
- protected void doStart() throws Exception {
- var old = Thread.currentThread().getContextClassLoader();
- Thread.currentThread().setContextClassLoader(context.getClassLoader());
- try {
- sci.onStartup(null, context.getServletContext());
- super.doStart();
- } finally {
- Thread.currentThread().setContextClassLoader(old);
- }
- }
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/ocpp/OcppProtocolTest.java b/steve/src/main/java/de/rwth/idsg/steve/SteveApplication.java
similarity index 61%
rename from steve/src/test/java/de/rwth/idsg/steve/ocpp/OcppProtocolTest.java
rename to steve/src/main/java/de/rwth/idsg/steve/SteveApplication.java
index 02b4902f4..e02562aad 100644
--- a/steve/src/test/java/de/rwth/idsg/steve/ocpp/OcppProtocolTest.java
+++ b/steve/src/main/java/de/rwth/idsg/steve/SteveApplication.java
@@ -16,20 +16,18 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package de.rwth.idsg.steve.ocpp;
+package de.rwth.idsg.steve;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
+import de.rwth.idsg.steve.config.SteveProperties;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import static org.assertj.core.api.Assertions.assertThat;
+@SpringBootApplication
+@EnableConfigurationProperties(SteveProperties.class)
+public class SteveApplication {
-public class OcppProtocolTest {
-
- @ParameterizedTest
- @EnumSource(OcppProtocol.class)
- public void testFromCompositeValue(OcppProtocol input) {
- var toTest = input.getCompositeValue();
- var inputBack = OcppProtocol.fromCompositeValue(toTest);
- assertThat(inputBack).isEqualTo(input);
+ public static void main(String[] args) {
+ SpringApplication.run(SteveApplication.class, args);
}
}
diff --git a/steve/src/main/java/de/rwth/idsg/steve/config/BeanConfiguration.java b/steve/src/main/java/de/rwth/idsg/steve/config/BeanConfiguration.java
index 1a80363cc..c57658323 100644
--- a/steve/src/main/java/de/rwth/idsg/steve/config/BeanConfiguration.java
+++ b/steve/src/main/java/de/rwth/idsg/steve/config/BeanConfiguration.java
@@ -21,7 +21,6 @@
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
-import de.rwth.idsg.steve.SteveConfiguration;
import de.rwth.idsg.steve.service.DummyReleaseCheckService;
import de.rwth.idsg.steve.service.GithubReleaseCheckService;
import de.rwth.idsg.steve.service.ReleaseCheckService;
@@ -31,19 +30,7 @@
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
-import org.springframework.format.support.FormattingConversionService;
-import org.springframework.http.converter.HttpMessageConverter;
-import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.scheduling.annotation.EnableScheduling;
-import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
-import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
-import org.springframework.web.accept.ContentNegotiationManager;
-import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
-
-import java.util.List;
/**
* Configuration and beans of Spring Framework.
@@ -53,34 +40,9 @@
*/
@Slf4j
@Configuration
-@EnableWebMvc
@EnableScheduling
@ComponentScan("de.rwth.idsg.steve")
-public class BeanConfiguration implements WebMvcConfigurer {
-
- @Bean(destroyMethod = "close")
- public DelegatingTaskScheduler asyncTaskScheduler() {
- var scheduler = new ThreadPoolTaskScheduler();
- scheduler.setPoolSize(5);
- scheduler.setThreadNamePrefix("SteVe-TaskScheduler-");
- scheduler.setWaitForTasksToCompleteOnShutdown(true);
- scheduler.setAwaitTerminationSeconds(30);
- scheduler.initialize();
-
- return new DelegatingTaskScheduler(scheduler);
- }
-
- @Bean(destroyMethod = "close")
- public DelegatingTaskExecutor asyncTaskExecutor() {
- var executor = new ThreadPoolTaskExecutor();
- executor.setCorePoolSize(5);
- executor.setThreadNamePrefix("SteVe-TaskExecutor-");
- executor.setWaitForTasksToCompleteOnShutdown(true);
- executor.setAwaitTerminationSeconds(30);
- executor.initialize();
-
- return new DelegatingTaskExecutor(executor);
- }
+public class BeanConfiguration {
/**
* There might be instances deployed in a local/closed network with no internet connection. In such situations,
@@ -89,47 +51,26 @@ public DelegatingTaskExecutor asyncTaskExecutor() {
* steps and return a "no new version" report immediately.
*/
@Bean
- public ReleaseCheckService releaseCheckService(SteveConfiguration config) {
- if (InternetChecker.isInternetAvailable(config.getSteveCompositeVersion())) {
- return new GithubReleaseCheckService(config);
- } else {
- return new DummyReleaseCheckService();
+ public ReleaseCheckService releaseCheckService(SteveProperties steveProperties) {
+ String compositeVersion = steveProperties.getVersion();
+ if (steveProperties.getGitDescribe() != null) {
+ compositeVersion += "-g" + steveProperties.getGitDescribe();
}
- }
-
- // -------------------------------------------------------------------------
- // API config
- // -------------------------------------------------------------------------
- @Override
- public void extendMessageConverters(List> converters) {
- for (var converter : converters) {
- if (converter instanceof MappingJackson2HttpMessageConverter conv) {
- ObjectMapper objectMapper = conv.getObjectMapper();
- objectMapper.findAndRegisterModules();
- // if the client sends unknown props, just ignore them instead of failing
- objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- // default is true
- objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
- break;
- }
+ if (InternetChecker.isInternetAvailable(compositeVersion)) {
+ return new GithubReleaseCheckService(steveProperties);
+ } else {
+ return new DummyReleaseCheckService();
}
}
- /**
- * Find the ObjectMapper used in MappingJackson2HttpMessageConverter and initialized by Spring automatically.
- * MappingJackson2HttpMessageConverter is not a Bean. It is created in {@link WebMvcConfigurationSupport#addDefaultHttpMessageConverters(List)}.
- * Therefore, we have to access it via proxies that reference it. RequestMappingHandlerAdapter is a Bean, created in
- * {@link WebMvcConfigurationSupport#requestMappingHandlerAdapter(ContentNegotiationManager, FormattingConversionService, org.springframework.validation.Validator)}.
- */
- @Primary
@Bean
- public ObjectMapper jacksonObjectMapper(RequestMappingHandlerAdapter requestMappingHandlerAdapter) {
- return requestMappingHandlerAdapter.getMessageConverters().stream()
- .filter(MappingJackson2HttpMessageConverter.class::isInstance)
- .findAny()
- .map(conv -> ((MappingJackson2HttpMessageConverter) conv).getObjectMapper())
- .orElseThrow(() ->
- new IllegalStateException("There is no MappingJackson2HttpMessageConverter in Spring context"));
+ @Primary
+ public ObjectMapper objectMapper() {
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.findAndRegisterModules();
+ objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+ return objectMapper;
}
}
diff --git a/steve/src/main/java/de/rwth/idsg/steve/config/PropertyConfig.java b/steve/src/main/java/de/rwth/idsg/steve/config/PropertyConfig.java
deleted file mode 100644
index edb981808..000000000
--- a/steve/src/main/java/de/rwth/idsg/steve/config/PropertyConfig.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve.config;
-
-import de.rwth.idsg.steve.SteveConfiguration;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
-
-import java.util.Properties;
-
-@Configuration
-public class PropertyConfig {
-
- // > To avoid these lifecycle issues, mark BFPP-returning @Bean methods as static
- // From [the Spring
- // documentation](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Bean.html)
- @Bean
- public static PropertySourcesPlaceholderConfigurer valueConfigurer(SteveConfiguration config) {
- var configurer = new PropertySourcesPlaceholderConfigurer();
-
- var props = new Properties();
- var chargeBoxIdValidationRegex = config.getOcpp().getChargeBoxIdValidationRegex();
- if (chargeBoxIdValidationRegex != null) {
- props.put("charge-box-id.validation.regex", chargeBoxIdValidationRegex);
- }
- var autoRegisterUnknownStations = config.getOcpp().isAutoRegisterUnknownStations();
- props.put("auto.register.unknown.stations", autoRegisterUnknownStations);
- var wsSessionSelectStrategy = config.getOcpp().getWsSessionSelectStrategy();
- props.put("ws.session.select.strategy", wsSessionSelectStrategy);
- configurer.setProperties(props);
-
- return configurer;
- }
-}
diff --git a/steve/src/main/java/de/rwth/idsg/steve/config/SecurityConfiguration.java b/steve/src/main/java/de/rwth/idsg/steve/config/SecurityConfiguration.java
index a90910c21..ee012545d 100644
--- a/steve/src/main/java/de/rwth/idsg/steve/config/SecurityConfiguration.java
+++ b/steve/src/main/java/de/rwth/idsg/steve/config/SecurityConfiguration.java
@@ -18,7 +18,6 @@
*/
package de.rwth.idsg.steve.config;
-import de.rwth.idsg.steve.SteveConfiguration;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
@@ -29,38 +28,26 @@
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
-import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.expression.WebExpressionAuthorizationManager;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.util.matcher.RequestMatcher;
-/**
- * @author Sevket Goekay
- * @since 07.01.2015
- */
@Slf4j
@RequiredArgsConstructor
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
- /**
- * Password encoding changed with spring-security 5.0.0. We either have to use a prefix before the password to
- * indicate which actual encoder {@link DelegatingPasswordEncoder} should use [1, 2] or specify the encoder as we do.
- *
- * [1] https://spring.io/blog/2017/11/01/spring-security-5-0-0-rc1-released#password-storage-format
- * [2] {@link PasswordEncoderFactories#createDelegatingPasswordEncoder()}
- */
@Bean
- public PasswordEncoder passwordEncoder(SteveConfiguration config) {
- return config.getAuth().getPasswordEncoder();
+ public PasswordEncoder passwordEncoder() {
+ return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
@Bean
- public SecurityFilterChain securityFilterChain(HttpSecurity http, SteveConfiguration config) throws Exception {
- final String prefix = config.getPaths().getManagerMapping();
+ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+ final String prefix = "/manager";
RequestMatcher toOverview = request -> {
String param = request.getParameter("backToOverview");
@@ -69,7 +56,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http, SteveConfigura
return http.authorizeHttpRequests(req -> req.requestMatchers(
"/static/**",
- config.getPaths().getSoapMapping() + "/**",
+ "/soap/**",
OcppWebSocketConfiguration.PATH_INFIX + "**",
"/WEB-INF/views/**" // https://github.com/spring-projects/spring-security/issues/13285#issuecomment-1579097065
)
@@ -124,7 +111,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http, SteveConfigura
// for
// all access, there is a global default behaviour from spring security: enable CSRF for all POSTs.
// we need to disable CSRF for SOAP paths explicitly.
- .csrf(c -> c.ignoringRequestMatchers(config.getPaths().getSoapMapping() + "/**"))
+ .csrf(c -> c.ignoringRequestMatchers("/soap/**"))
.sessionManagement(req -> req.invalidSessionUrl(prefix + "/signin"))
.formLogin(req -> req.loginPage(prefix + "/signin").permitAll())
.logout(req -> req.logoutUrl(prefix + "/signout"))
@@ -134,10 +121,9 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http, SteveConfigura
@Bean
@Order(1)
- public SecurityFilterChain apiKeyFilterChain(
- HttpSecurity http, SteveConfiguration config, ApiAuthenticationManager apiAuthenticationManager)
+ public SecurityFilterChain apiKeyFilterChain(HttpSecurity http, ApiAuthenticationManager apiAuthenticationManager)
throws Exception {
- return http.securityMatcher(config.getPaths().getApiMapping() + "/**")
+ return http.securityMatcher("/api/**")
.csrf(k -> k.disable())
.sessionManagement(k -> k.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilter(new BasicAuthenticationFilter(apiAuthenticationManager, apiAuthenticationManager))
diff --git a/steve/src/main/java/de/rwth/idsg/steve/service/GithubReleaseCheckService.java b/steve/src/main/java/de/rwth/idsg/steve/service/GithubReleaseCheckService.java
index 5d224c7ef..e8ea8bea5 100644
--- a/steve/src/main/java/de/rwth/idsg/steve/service/GithubReleaseCheckService.java
+++ b/steve/src/main/java/de/rwth/idsg/steve/service/GithubReleaseCheckService.java
@@ -23,7 +23,7 @@
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.github.zafarkhaja.semver.Version;
-import de.rwth.idsg.steve.SteveConfiguration;
+import de.rwth.idsg.steve.config.SteveProperties;
import de.rwth.idsg.steve.web.dto.ReleaseReport;
import de.rwth.idsg.steve.web.dto.ReleaseResponse;
import lombok.extern.slf4j.Slf4j;
@@ -61,9 +61,9 @@ public class GithubReleaseCheckService implements ReleaseCheckService {
private final String steveVersion;
private final RestTemplate restTemplate;
- public GithubReleaseCheckService(SteveConfiguration config) {
- this.steveVersion = config.getSteveVersion();
- this.restTemplate = createRestTemplate(createGitHubMapper(), "steve/" + config.getSteveVersion());
+ public GithubReleaseCheckService(SteveProperties steveProperties) {
+ this.steveVersion = steveProperties.getVersion();
+ this.restTemplate = createRestTemplate(createGitHubMapper(), "steve/" + steveProperties.getVersion());
}
private static RestTemplate createRestTemplate(ObjectMapper mapper, String userAgent) {
diff --git a/steve/src/main/java/de/rwth/idsg/steve/utils/SteveConfigurationReader.java b/steve/src/main/java/de/rwth/idsg/steve/utils/SteveConfigurationReader.java
deleted file mode 100644
index e3af81910..000000000
--- a/steve/src/main/java/de/rwth/idsg/steve/utils/SteveConfigurationReader.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve.utils;
-
-import de.rwth.idsg.steve.ApplicationProfile;
-import de.rwth.idsg.steve.SteveConfiguration;
-import lombok.experimental.UtilityClass;
-import org.jspecify.annotations.Nullable;
-import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
-import org.springframework.security.crypto.password.PasswordEncoder;
-
-import java.util.Locale;
-
-@UtilityClass
-public class SteveConfigurationReader {
-
- public static SteveConfiguration readSteveConfiguration(String name) {
- PropertiesFileLoader p = new PropertiesFileLoader(name);
-
- var profile = ApplicationProfile.fromName(p.getString("profile"));
- System.setProperty("spring.profiles.active", profile.name().toLowerCase(Locale.getDefault()));
-
- PasswordEncoder encoder = new BCryptPasswordEncoder();
-
- var config = SteveConfiguration.builder()
- .paths(SteveConfiguration.Paths.builder()
- .rootMapping("/")
- .managerMapping("/manager")
- .apiMapping("/api")
- .soapMapping("/services")
- .websocketMapping("/websocket")
- .routerEndpointPath("/CentralSystemService")
- .contextPath(sanitizeContextPath(
- p.getOptionalString("context.path").orElse(null)))
- .build())
- .timeZoneId("UTC")
- .steveVersion(p.getString("steve.version"))
- .gitDescribe(
- useFallbackIfNotSet(p.getOptionalString("git.describe").orElse(null), null))
- .profile(profile)
- .jetty(SteveConfiguration.Jetty.builder()
- .serverHost(p.getString("server.host"))
- .gzipEnabled(p.getBoolean("server.gzip.enabled"))
- .httpEnabled(p.getBoolean("http.enabled"))
- .httpPort(p.getInt("http.port"))
- .httpsEnabled(p.getBoolean("https.enabled"))
- .httpsPort(p.getInt("https.port"))
- .keyStorePath(p.getOptionalString("keystore.path").orElse(null))
- .keyStorePassword(
- p.getOptionalString("keystore.password").orElse(null))
- .build())
- .db(SteveConfiguration.DB
- .builder()
- .jdbcUrl(p.getString("db.jdbc.url"))
- .userName(p.getString("db.user"))
- .password(p.getString("db.password"))
- .sqlLogging(p.getBoolean("db.sql.logging"))
- .schema(p.getOptionalString("db.schema").orElse(null))
- .schemaSource(p.getOptionalString("db.schema-source").orElse("stevedb"))
- .build())
- .auth(SteveConfiguration.Auth.builder()
- .passwordEncoder(encoder)
- .userName(p.getString("auth.user"))
- .encodedPassword(encoder.encode(p.getString("auth.password")))
- .build())
- .webApi(SteveConfiguration.WebApi.builder()
- .headerKey(p.getOptionalString("webapi.key").orElse(null))
- .headerValue(p.getOptionalString("webapi.value").orElse(null))
- .build())
- .ocpp(SteveConfiguration.Ocpp.builder()
- .autoRegisterUnknownStations(p.getOptionalBoolean("auto.register.unknown.stations")
- .orElse(false))
- .chargeBoxIdValidationRegex(p.getOptionalString("charge-box-id.validation.regex")
- .orElse(null))
- .wsSessionSelectStrategy(p.getString("ws.session.select.strategy"))
- .build())
- .build();
-
- config.postConstruct();
- return config;
- }
-
- private static @Nullable String useFallbackIfNotSet(@Nullable String value, @Nullable String fallback) {
- if (value == null) {
- // if the property is optional, value will be null
- return fallback;
- } else if (value.startsWith("${")) {
- // property value variables start with "${" (if maven is not used, the value will not be set)
- return fallback;
- } else {
- return value;
- }
- }
-
- private static String sanitizeContextPath(@Nullable String s) {
- if (s == null || "/".equals(s)) {
- return "";
-
- } else if (s.startsWith("/")) {
- return s;
-
- } else {
- return "/" + s;
- }
- }
-}
diff --git a/steve/src/main/resources/application.yml b/steve/src/main/resources/application.yml
new file mode 100644
index 000000000..ce23f826d
--- /dev/null
+++ b/steve/src/main/resources/application.yml
@@ -0,0 +1,97 @@
+server:
+ port: ${PORT:8180}
+ servlet:
+ context-path: /${context.path:}
+ jetty:
+ threads:
+ min: 4
+ max: 50
+ idle-timeout: 1m
+ forward-headers-strategy: framework
+ ssl:
+ enabled: ${https.enabled:false}
+ port: ${https.port:8443}
+ key-store: ${keystore.path:}
+ key-store-password: ${keystore.password:}
+
+spring:
+ application:
+ name: steve
+ profiles:
+ active: ${profile:dev}
+ main:
+ banner-mode: "off"
+ datasource:
+ url: jdbc:mysql://${db.host:localhost}:${db.port:3306}/${db.schema:stevedb}?sslMode=PREFERRED&serverTimezone=UTC
+ username: ${db.user:steve}
+ password: ${db.password:changeme}
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ jooq:
+ sql-dialect: MYSQL
+ flyway:
+ init-sql: SET default_storage_engine=InnoDB
+ out-of-order: true
+ table: schema_version
+ clean-disabled: true
+ locations: classpath:db/migration
+ mvc:
+ view:
+ prefix: /WEB-INF/views/
+ suffix: .jsp
+
+steve:
+ auth:
+ user: ${auth.user:admin}
+ password: ${auth.password:1234}
+ webapi:
+ key: ${webapi.key:STEVE-API-KEY}
+ value: ${webapi.value:}
+ ocpp:
+ ws-session-select-strategy: ALWAYS_LAST
+ auto-register-unknown-stations: false
+ charge-box-id-validation-regex:
+ soap:
+ router-endpoint-path: /
+ version: ${project.version}
+ git-describe: ${git.commit.id.describe:}
+
+logging:
+ level:
+ de:
+ rwth:
+ idsg:
+ steve: INFO
+ org:
+ springframework: INFO
+ jooq: INFO
+ pattern:
+ console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
+ file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
+ file:
+ name: logs/steve.log
+
+---
+spring:
+ profiles: dev
+ jooq:
+ sql-dialect: MYSQL
+ flyway:
+ enabled: true
+
+logging:
+ level:
+ de.rwth.idsg.steve: DEBUG
+ org.jooq: DEBUG
+
+---
+spring:
+ profiles: prod
+ jooq:
+ sql-dialect: MYSQL
+ flyway:
+ enabled: true
+
+logging:
+ level:
+ de.rwth.idsg.steve: INFO
+ org.jooq: INFO
diff --git a/steve/src/test/java/de/rwth/idsg/steve/ApplicationJsonTest.java b/steve/src/test/java/de/rwth/idsg/steve/ApplicationJsonTest.java
deleted file mode 100644
index 7f9895f3b..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/ApplicationJsonTest.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import de.rwth.idsg.steve.ocpp.OcppVersion;
-import de.rwth.idsg.steve.ocpp.ws.JsonObjectMapper;
-import de.rwth.idsg.steve.utils.LogFileRetriever;
-import de.rwth.idsg.steve.utils.OcppJsonChargePoint;
-import de.rwth.idsg.steve.utils.SteveConfigurationReader;
-import de.rwth.idsg.steve.utils.__DatabasePreparer__;
-import lombok.extern.slf4j.Slf4j;
-import ocpp.cs._2015._10.AuthorizationStatus;
-import ocpp.cs._2015._10.AuthorizeRequest;
-import ocpp.cs._2015._10.AuthorizeResponse;
-import ocpp.cs._2015._10.BootNotificationRequest;
-import ocpp.cs._2015._10.BootNotificationResponse;
-import ocpp.cs._2015._10.HeartbeatResponse;
-import ocpp.cs._2015._10.RegistrationStatus;
-import org.eclipse.jetty.websocket.core.exception.UpgradeException;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.springframework.http.HttpStatus;
-
-import static de.rwth.idsg.steve.utils.Helpers.getRandomString;
-import static de.rwth.idsg.steve.utils.Helpers.getWsPath;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.catchThrowable;
-import static org.assertj.core.api.Assertions.fail;
-import static org.assertj.core.api.BDDAssertions.then;
-
-/**
- * @author Sevket Goekay
- * @since 21.03.2018
- */
-@Slf4j
-public class ApplicationJsonTest {
-
- private static final ObjectMapper OCPP_MAPPER = JsonObjectMapper.createObjectMapper();
-
- private static final String REGISTERED_CHARGE_BOX_ID = __DatabasePreparer__.getRegisteredChargeBoxId();
- private static final String REGISTERED_OCPP_TAG = __DatabasePreparer__.getRegisteredOcppTag();
-
- private static String path;
- private static Application app;
-
- @BeforeAll
- public static void init() throws Exception {
- var config = SteveConfigurationReader.readSteveConfiguration("main.properties");
- assertThat(config.getProfile()).isEqualTo(ApplicationProfile.TEST);
- __DatabasePreparer__.prepare(config);
-
- path = getWsPath(config);
-
- app = new Application(config, new LogFileRetriever());
- app.start();
- }
-
- @AfterAll
- public static void destroy() throws Exception {
- if (app != null) {
- app.stop();
- }
- __DatabasePreparer__.cleanUp();
- }
-
- @Test
- public void testOcpp12() {
- var chargePoint = new OcppJsonChargePoint(OCPP_MAPPER, OcppVersion.V_12, REGISTERED_CHARGE_BOX_ID, path);
- chargePoint.start();
-
- var boot = new ocpp.cs._2010._08.BootNotificationRequest()
- .withChargePointVendor(getRandomString())
- .withChargePointModel(getRandomString());
-
- chargePoint.prepare(
- boot,
- ocpp.cs._2010._08.BootNotificationResponse.class,
- bootResponse ->
- assertThat(bootResponse.getStatus()).isEqualTo(ocpp.cs._2010._08.RegistrationStatus.ACCEPTED),
- error -> fail());
-
- var auth = new ocpp.cs._2010._08.AuthorizeRequest().withIdTag(REGISTERED_OCPP_TAG);
-
- chargePoint.prepare(
- auth,
- ocpp.cs._2010._08.AuthorizeResponse.class,
- authResponse -> assertThat(authResponse.getIdTagInfo().getStatus())
- .isEqualTo(ocpp.cs._2010._08.AuthorizationStatus.ACCEPTED),
- error -> fail());
-
- chargePoint.processAndClose();
- }
-
- @Test
- public void testOcpp15() {
- var chargePoint = new OcppJsonChargePoint(OCPP_MAPPER, OcppVersion.V_15, REGISTERED_CHARGE_BOX_ID, path);
- chargePoint.start();
-
- var boot = new ocpp.cs._2012._06.BootNotificationRequest()
- .withChargePointVendor(getRandomString())
- .withChargePointModel(getRandomString());
-
- chargePoint.prepare(
- boot,
- ocpp.cs._2012._06.BootNotificationResponse.class,
- bootResponse ->
- assertThat(bootResponse.getStatus()).isEqualTo(ocpp.cs._2012._06.RegistrationStatus.ACCEPTED),
- error -> fail());
-
- var auth = new ocpp.cs._2012._06.AuthorizeRequest().withIdTag(REGISTERED_OCPP_TAG);
-
- chargePoint.prepare(
- auth,
- ocpp.cs._2012._06.AuthorizeResponse.class,
- authResponse -> assertThat(authResponse.getIdTagInfo().getStatus())
- .isEqualTo(ocpp.cs._2012._06.AuthorizationStatus.ACCEPTED),
- error -> fail());
-
- chargePoint.processAndClose();
- }
-
- @Test
- public void testOcpp16() {
- var chargePoint = new OcppJsonChargePoint(OCPP_MAPPER, OcppVersion.V_16, REGISTERED_CHARGE_BOX_ID, path);
- chargePoint.start();
-
- var boot = new BootNotificationRequest()
- .withChargePointVendor(getRandomString())
- .withChargePointModel(getRandomString());
-
- chargePoint.prepare(
- boot,
- BootNotificationResponse.class,
- bootResponse -> assertThat(bootResponse.getStatus()).isEqualTo(RegistrationStatus.ACCEPTED),
- error -> fail());
-
- var auth = new AuthorizeRequest().withIdTag(REGISTERED_OCPP_TAG);
-
- chargePoint.prepare(
- auth,
- AuthorizeResponse.class,
- authResponse ->
- assertThat(authResponse.getIdTagInfo().getStatus()).isEqualTo(AuthorizationStatus.ACCEPTED),
- error -> fail());
-
- chargePoint.processAndClose();
- }
-
- @Test
- public void testWithMissingVersion() {
- var chargePoint = new OcppJsonChargePoint(OCPP_MAPPER, (String) null, REGISTERED_CHARGE_BOX_ID, path);
- var thrown = catchThrowable(chargePoint::start);
- then(thrown)
- .isInstanceOf(RuntimeException.class)
- .hasRootCauseInstanceOf(UpgradeException.class)
- .rootCause()
- .satisfies(c -> {
- ;
- var ue = (UpgradeException) c;
- assertThat(ue.getResponseStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST.value());
- });
- }
-
- @Test
- public void testWithWrongVersion() {
- var chargePoint = new OcppJsonChargePoint(OCPP_MAPPER, "ocpp1234", REGISTERED_CHARGE_BOX_ID, path);
- var thrown = catchThrowable(chargePoint::start);
- then(thrown)
- .isInstanceOf(RuntimeException.class)
- .hasRootCauseInstanceOf(UpgradeException.class)
- .rootCause()
- .satisfies(c -> {
- var ue = (UpgradeException) c;
- assertThat(ue.getResponseStatusCode()).isEqualTo(HttpStatus.NOT_FOUND.value());
- });
- }
-
- @Test
- public void testWithUnauthorizedStation() {
- var chargePoint = new OcppJsonChargePoint(OCPP_MAPPER, OcppVersion.V_16, "unauth1234", path);
- var thrown = catchThrowable(chargePoint::start);
- then(thrown)
- .isInstanceOf(RuntimeException.class)
- .hasRootCauseInstanceOf(UpgradeException.class)
- .rootCause()
- .satisfies(c -> {
- var ue = (UpgradeException) c;
- assertThat(ue.getResponseStatusCode()).isEqualTo(HttpStatus.NOT_FOUND.value());
- });
- }
-
- /**
- * https://github.com/steve-community/steve/issues/1109
- */
- @Test
- public void testWithNullPayload() {
- var chargePoint = new OcppJsonChargePoint(OCPP_MAPPER, OcppVersion.V_16, REGISTERED_CHARGE_BOX_ID, path);
- chargePoint.start();
-
- chargePoint.prepare(
- null,
- "Heartbeat",
- HeartbeatResponse.class,
- response -> assertThat(response.getCurrentTime()).isNotNull(),
- error -> fail());
-
- chargePoint.processAndClose();
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/ApplicationTest.java b/steve/src/test/java/de/rwth/idsg/steve/ApplicationTest.java
deleted file mode 100644
index 1a0bab569..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/ApplicationTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve;
-
-import de.rwth.idsg.steve.utils.LogFileRetriever;
-import de.rwth.idsg.steve.utils.SteveConfigurationReader;
-import de.rwth.idsg.steve.utils.__DatabasePreparer__;
-import lombok.extern.slf4j.Slf4j;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-
-import jakarta.xml.ws.WebServiceException;
-
-import static de.rwth.idsg.steve.utils.Helpers.getForOcpp12;
-import static de.rwth.idsg.steve.utils.Helpers.getForOcpp15;
-import static de.rwth.idsg.steve.utils.Helpers.getForOcpp16;
-import static de.rwth.idsg.steve.utils.Helpers.getHttpPath;
-import static de.rwth.idsg.steve.utils.Helpers.getRandomString;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-
-/**
- * @author Sevket Goekay
- * @since 10.03.2018
- */
-@Slf4j
-public class ApplicationTest {
-
- private static final String REGISTERED_CHARGE_BOX_ID = __DatabasePreparer__.getRegisteredChargeBoxId();
- private static final String REGISTERED_OCPP_TAG = __DatabasePreparer__.getRegisteredOcppTag();
-
- private static String path;
- private static Application app;
-
- @BeforeAll
- public static void init() throws Exception {
- var config = SteveConfigurationReader.readSteveConfiguration("main.properties");
- assertThat(config.getProfile()).isEqualTo(ApplicationProfile.TEST);
- __DatabasePreparer__.prepare(config);
-
- path = getHttpPath(config);
-
- app = new Application(config, new LogFileRetriever());
- app.start();
- }
-
- @AfterAll
- public static void destroy() throws Exception {
- if (app != null) {
- app.stop();
- }
- __DatabasePreparer__.cleanUp();
- }
-
- @Test
- public void testOcpp12() {
- var client = getForOcpp12(path);
-
- var boot = client.bootNotification(
- new ocpp.cs._2010._08.BootNotificationRequest()
- .withChargePointVendor(getRandomString())
- .withChargePointModel(getRandomString()),
- REGISTERED_CHARGE_BOX_ID);
- assertThat(boot).isNotNull();
- assertThat(boot.getStatus()).isEqualTo(ocpp.cs._2010._08.RegistrationStatus.ACCEPTED);
-
- var auth = client.authorize(
- new ocpp.cs._2010._08.AuthorizeRequest().withIdTag(REGISTERED_OCPP_TAG), REGISTERED_CHARGE_BOX_ID);
- assertThat(auth).isNotNull();
- assertThat(auth.getIdTagInfo().getStatus()).isEqualTo(ocpp.cs._2010._08.AuthorizationStatus.ACCEPTED);
- }
-
- @Test
- public void testOcpp15() {
- var client = getForOcpp15(path);
-
- var boot = client.bootNotification(
- new ocpp.cs._2012._06.BootNotificationRequest()
- .withChargePointVendor(getRandomString())
- .withChargePointModel(getRandomString()),
- REGISTERED_CHARGE_BOX_ID);
- assertThat(boot).isNotNull();
- assertThat(boot.getStatus()).isEqualTo(ocpp.cs._2012._06.RegistrationStatus.ACCEPTED);
-
- ocpp.cs._2012._06.AuthorizeResponse auth = client.authorize(
- new ocpp.cs._2012._06.AuthorizeRequest().withIdTag(REGISTERED_OCPP_TAG), REGISTERED_CHARGE_BOX_ID);
- assertThat(auth).isNotNull();
- assertThat(auth.getIdTagInfo().getStatus()).isEqualTo(ocpp.cs._2012._06.AuthorizationStatus.ACCEPTED);
- }
-
- /**
- * WebServiceException because we are sending an AuthorizeRequest from a random/unknown station.
- */
- @Test
- public void testOcpp16() {
- var client = getForOcpp16(path);
-
- assertThatExceptionOfType(WebServiceException.class).isThrownBy(() -> {
- var boot = client.bootNotification(
- new ocpp.cs._2015._10.BootNotificationRequest()
- .withChargePointVendor(getRandomString())
- .withChargePointModel(getRandomString()),
- getRandomString());
- assertThat(boot).isNotNull();
- assertThat(boot.getStatus()).isEqualTo(ocpp.cs._2015._10.RegistrationStatus.REJECTED);
-
- var auth = client.authorize(
- new ocpp.cs._2015._10.AuthorizeRequest().withIdTag(getRandomString()), getRandomString());
- assertThat(auth).isNotNull();
- assertThat(auth.getIdTagInfo().getStatus()).isEqualTo(ocpp.cs._2015._10.AuthorizationStatus.INVALID);
- });
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/OperationalTestSoapOCPP16.java b/steve/src/test/java/de/rwth/idsg/steve/OperationalTestSoapOCPP16.java
deleted file mode 100644
index 60f609084..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/OperationalTestSoapOCPP16.java
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve;
-
-import de.rwth.idsg.steve.ocpp.OcppProtocol;
-import de.rwth.idsg.steve.ocpp.soap.MessageHeaderInterceptor;
-import de.rwth.idsg.steve.repository.ReservationStatus;
-import de.rwth.idsg.steve.service.CentralSystemService16_Service;
-import de.rwth.idsg.steve.utils.LogFileRetriever;
-import de.rwth.idsg.steve.utils.SteveConfigurationReader;
-import de.rwth.idsg.steve.utils.__DatabasePreparer__;
-import lombok.extern.slf4j.Slf4j;
-import ocpp.cs._2015._10.AuthorizationStatus;
-import ocpp.cs._2015._10.AuthorizeRequest;
-import ocpp.cs._2015._10.BootNotificationRequest;
-import ocpp.cs._2015._10.CentralSystemService;
-import ocpp.cs._2015._10.ChargePointErrorCode;
-import ocpp.cs._2015._10.ChargePointStatus;
-import ocpp.cs._2015._10.HeartbeatRequest;
-import ocpp.cs._2015._10.MeterValue;
-import ocpp.cs._2015._10.MeterValuesRequest;
-import ocpp.cs._2015._10.RegistrationStatus;
-import ocpp.cs._2015._10.SampledValue;
-import ocpp.cs._2015._10.StartTransactionRequest;
-import ocpp.cs._2015._10.StatusNotificationRequest;
-import ocpp.cs._2015._10.StopTransactionRequest;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.time.OffsetDateTime;
-import java.time.temporal.ChronoUnit;
-import java.util.Arrays;
-import java.util.List;
-import jakarta.xml.ws.WebServiceException;
-
-import static de.rwth.idsg.steve.utils.Helpers.getForOcpp16;
-import static de.rwth.idsg.steve.utils.Helpers.getHttpPath;
-import static de.rwth.idsg.steve.utils.Helpers.getRandomString;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.assertj.core.api.Assertions.byLessThan;
-
-/**
- * @author Andreas Heuvels
- * @since 22.03.18
- */
-@Slf4j
-public class OperationalTestSoapOCPP16 {
-
- private static final String REGISTERED_CHARGE_BOX_ID = __DatabasePreparer__.getRegisteredChargeBoxId();
- private static final String REGISTERED_CHARGE_BOX_ID_2 = __DatabasePreparer__.getRegisteredChargeBoxId2();
- private static final String REGISTERED_OCPP_TAG = __DatabasePreparer__.getRegisteredOcppTag();
- private static final int numConnectors = 5;
-
- private static SteveConfiguration config;
- private static String path;
- private static Application app;
-
- @BeforeAll
- public static void initClass() throws Exception {
- config = SteveConfigurationReader.readSteveConfiguration("main.properties");
- assertThat(config.getProfile()).isEqualTo(ApplicationProfile.TEST);
-
- path = getHttpPath(config);
-
- app = new Application(config, new LogFileRetriever());
- app.start();
- }
-
- @AfterAll
- public static void destroyClass() throws Exception {
- app.stop();
- }
-
- @BeforeEach
- public void init() {
- __DatabasePreparer__.prepare(config);
- }
-
- @AfterEach
- public void destroy() {
- __DatabasePreparer__.cleanUp();
- }
-
- @Test
- public void testUnregisteredCP() {
- assertThat(config.getOcpp().isAutoRegisterUnknownStations()).isFalse();
-
- var client = getForOcpp16(path);
-
- var boot = client.bootNotification(
- new BootNotificationRequest()
- .withChargePointVendor(getRandomString())
- .withChargePointModel(getRandomString()),
- getRandomString());
-
- assertThat(boot).isNotNull();
- assertThat(boot.getStatus()).isNotEqualTo(RegistrationStatus.ACCEPTED);
- }
-
- /**
- * Reason: We started to check registration status by intercepting every SOAP message other than BootNotification
- * in {@link MessageHeaderInterceptor} and throw exception if station is not registered and auto-register is
- * disabled (and therefore early-exit the processing pipeline of the message).
- *
- * In case of BootNotification, the expected behaviour is to set RegistrationStatus.REJECTED in response, as done
- * by {@link CentralSystemService16_Service#bootNotification(BootNotificationRequest, String, OcppProtocol)}.
- * Therefore, no exception. This case is tested by {@link OperationalTestSoapOCPP16#testUnregisteredCP()} already.
- *
- * WS/JSON stations cannot connect at all if they are not registered, as ensured by {@link OcppWebSocketUpgrader}.
- */
- @Test
- public void testUnregisteredCPWithInterceptor() {
- assertThat(config.getOcpp().isAutoRegisterUnknownStations()).isFalse();
- var client = getForOcpp16(path);
- var request = new AuthorizeRequest().withIdTag(REGISTERED_OCPP_TAG);
- var chargeBoxIdentity = getRandomString();
- assertThatExceptionOfType(WebServiceException.class).isThrownBy(() -> {
- client.authorize(request, chargeBoxIdentity);
- });
- }
-
- @Test
- public void testRegisteredCP() {
- var client = getForOcpp16(path);
-
- initStationWithBootNotification(client);
-
- var details = __DatabasePreparer__.getCBDetails(REGISTERED_CHARGE_BOX_ID);
- assertThat(details.getOcppProtocol()).contains("ocpp1.6");
- }
-
- @Test
- public void testRegisteredIdTag() {
- var client = getForOcpp16(path);
-
- var auth = client.authorize(new AuthorizeRequest().withIdTag(REGISTERED_OCPP_TAG), REGISTERED_CHARGE_BOX_ID);
-
- assertThat(auth).isNotNull();
- assertThat(auth.getIdTagInfo().getStatus()).isEqualTo(AuthorizationStatus.ACCEPTED);
- }
-
- @Test
- public void testUnregisteredIdTag() {
- var client = getForOcpp16(path);
-
- var auth = client.authorize(new AuthorizeRequest().withIdTag(getRandomString()), REGISTERED_CHARGE_BOX_ID);
-
- assertThat(auth).isNotNull();
- assertThat(auth.getIdTagInfo().getStatus()).isEqualTo(AuthorizationStatus.INVALID);
- }
-
- @Test
- public void testInTransactionStatusOfIdTag() {
- var client = getForOcpp16(path);
-
- var start = client.startTransaction(
- new StartTransactionRequest()
- .withConnectorId(2)
- .withIdTag(REGISTERED_OCPP_TAG)
- .withTimestamp(OffsetDateTime.now())
- .withMeterStart(0),
- REGISTERED_CHARGE_BOX_ID);
-
- assertThat(start).isNotNull();
- assertThat(start.getTransactionId()).isGreaterThan(0);
- assertThat(__DatabasePreparer__.getOcppTagRecord(REGISTERED_OCPP_TAG).getInTransaction())
- .isTrue();
-
- var stop = client.stopTransaction(
- new StopTransactionRequest()
- .withTransactionId(start.getTransactionId())
- .withTimestamp(OffsetDateTime.now())
- .withIdTag(REGISTERED_OCPP_TAG)
- .withMeterStop(30),
- REGISTERED_CHARGE_BOX_ID);
-
- assertThat(stop).isNotNull();
- assertThat(__DatabasePreparer__.getOcppTagRecord(REGISTERED_OCPP_TAG).getInTransaction())
- .isFalse();
- }
-
- /**
- * https://github.com/steve-community/steve/issues/217
- * https://github.com/steve-community/steve/issues/219
- */
- @Test
- public void testAuthorizationStatus() {
- var client = getForOcpp16(path);
-
- {
- var auth1 =
- client.authorize(new AuthorizeRequest().withIdTag(REGISTERED_OCPP_TAG), REGISTERED_CHARGE_BOX_ID);
- assertThat(auth1.getIdTagInfo().getStatus()).isEqualTo(AuthorizationStatus.ACCEPTED);
-
- var start1 = client.startTransaction(
- new StartTransactionRequest()
- .withConnectorId(2)
- .withIdTag(REGISTERED_OCPP_TAG)
- .withTimestamp(OffsetDateTime.now())
- .withMeterStart(0),
- REGISTERED_CHARGE_BOX_ID);
- assertThat(start1.getTransactionId()).isGreaterThan(0);
- assertThat(start1.getIdTagInfo().getStatus()).isEqualTo(AuthorizationStatus.ACCEPTED);
-
- var auth1Retry =
- client.authorize(new AuthorizeRequest().withIdTag(REGISTERED_OCPP_TAG), REGISTERED_CHARGE_BOX_ID);
- assertThat(auth1Retry.getIdTagInfo().getStatus()).isEqualTo(AuthorizationStatus.ACCEPTED);
- }
-
- {
- var auth2 =
- client.authorize(new AuthorizeRequest().withIdTag(REGISTERED_OCPP_TAG), REGISTERED_CHARGE_BOX_ID_2);
- assertThat(auth2.getIdTagInfo().getStatus()).isEqualTo(AuthorizationStatus.ACCEPTED);
-
- var start2 = client.startTransaction(
- new StartTransactionRequest()
- .withConnectorId(2)
- .withIdTag(REGISTERED_OCPP_TAG)
- .withTimestamp(OffsetDateTime.now())
- .withMeterStart(0),
- REGISTERED_CHARGE_BOX_ID_2);
- assertThat(start2.getTransactionId()).isGreaterThan(0);
- assertThat(start2.getIdTagInfo().getStatus()).isEqualTo(AuthorizationStatus.CONCURRENT_TX);
-
- var auth2Retry =
- client.authorize(new AuthorizeRequest().withIdTag(REGISTERED_OCPP_TAG), REGISTERED_CHARGE_BOX_ID_2);
- assertThat(auth2Retry.getIdTagInfo().getStatus()).isEqualTo(AuthorizationStatus.ACCEPTED);
- }
- }
-
- @Test
- public void testStatusNotification() {
- var client = getForOcpp16(path);
-
- // -------------------------------------------------------------------------
- // init the station and verify db connector status values
- // -------------------------------------------------------------------------
-
- initStationWithBootNotification(client);
-
- // test all status enum values
- for (ChargePointStatus chargePointStatus : ChargePointStatus.values()) {
- // status for numConnectors connectors + connector 0 (main controller of CP)
- for (var i = 0; i <= numConnectors; i++) {
- var status = client.statusNotification(
- new StatusNotificationRequest()
- .withErrorCode(ChargePointErrorCode.NO_ERROR)
- .withStatus(chargePointStatus)
- .withConnectorId(i)
- .withTimestamp(OffsetDateTime.now()),
- REGISTERED_CHARGE_BOX_ID);
- assertThat(status).isNotNull();
- }
-
- var connectorStatusList = __DatabasePreparer__.getChargePointConnectorStatus();
- for (var connectorStatus : connectorStatusList) {
- assertThat(connectorStatus.getStatus()).isEqualTo(chargePointStatus.value());
- assertThat(connectorStatus.getErrorCode()).isEqualTo(ChargePointErrorCode.NO_ERROR.value());
- }
- }
-
- // -------------------------------------------------------------------------
- // send status for faulty connector and verify db values
- // -------------------------------------------------------------------------
-
- int faultyConnectorId = 1;
-
- var statusConnectorError = client.statusNotification(
- new StatusNotificationRequest()
- .withErrorCode(ChargePointErrorCode.HIGH_TEMPERATURE)
- .withStatus(ChargePointStatus.FAULTED)
- .withConnectorId(faultyConnectorId)
- .withTimestamp(OffsetDateTime.now()),
- REGISTERED_CHARGE_BOX_ID);
- assertThat(statusConnectorError).isNotNull();
-
- var connectorStatusList = __DatabasePreparer__.getChargePointConnectorStatus();
- for (var connectorStatus : connectorStatusList) {
- if (connectorStatus.getConnectorId() == faultyConnectorId) {
- assertThat(connectorStatus.getStatus()).isEqualTo(ChargePointStatus.FAULTED.value());
- assertThat(connectorStatus.getErrorCode()).isEqualTo(ChargePointErrorCode.HIGH_TEMPERATURE.value());
- } else {
- assertThat(connectorStatus.getStatus()).isNotEqualTo(ChargePointStatus.FAULTED.value());
- assertThat(connectorStatus.getErrorCode()).isNotEqualTo(ChargePointErrorCode.HIGH_TEMPERATURE.value());
- }
- }
- }
-
- @Test
- public void testReservation() {
- int usedConnectorId = 1;
-
- var client = getForOcpp16(path);
-
- // -------------------------------------------------------------------------
- // init the station and make reservation
- // -------------------------------------------------------------------------
-
- initStationWithBootNotification(client);
- initConnectorsWithStatusNotification(client);
-
- var reservationId = __DatabasePreparer__.makeReservation(usedConnectorId);
-
- // -------------------------------------------------------------------------
- // startTransaction (invalid reservationId)
- // -------------------------------------------------------------------------
-
- var nonExistingReservationId = reservationId + 17;
-
- var startInvalid = client.startTransaction(
- new StartTransactionRequest()
- .withConnectorId(usedConnectorId)
- .withIdTag(REGISTERED_OCPP_TAG)
- .withTimestamp(OffsetDateTime.now())
- .withMeterStart(0)
- .withReservationId(nonExistingReservationId),
- REGISTERED_CHARGE_BOX_ID);
- assertThat(startInvalid).isNotNull();
-
- // validate that the transaction is written to db, even though reservation was invalid
- var transactions = __DatabasePreparer__.getTransactions();
- assertThat(transactions).hasSize(1);
- assertThat(transactions.get(0).getId()).isEqualTo(startInvalid.getTransactionId());
-
- // make sure that this invalid reservation had no side effects
- {
- var reservations = __DatabasePreparer__.getReservations();
- assertThat(reservations).hasSize(1);
- var res = reservations.get(0);
- assertThat(res.getId()).isEqualTo(reservationId);
- assertThat(res.getStatus()).isEqualTo(ReservationStatus.ACCEPTED.value());
- }
-
- // -------------------------------------------------------------------------
- // startTransaction (idtag and connectorid are not the ones from the reservation)
- // -------------------------------------------------------------------------
-
- var startWrongTag = client.startTransaction(
- new StartTransactionRequest()
- .withConnectorId(3)
- .withIdTag(getRandomString())
- .withTimestamp(OffsetDateTime.now())
- .withMeterStart(0)
- .withReservationId(reservationId),
- REGISTERED_CHARGE_BOX_ID);
- assertThat(startWrongTag).isNotNull();
-
- {
- var reservations = __DatabasePreparer__.getReservations();
- assertThat(reservations).hasSize(1);
- var res = reservations.get(0);
- assertThat(res.getStatus()).isEqualTo(ReservationStatus.ACCEPTED.value());
- assertThat(res.getTransactionId()).isNull();
- }
-
- // -------------------------------------------------------------------------
- // startTransaction (valid)
- // -------------------------------------------------------------------------
-
- var startValidId = client.startTransaction(
- new StartTransactionRequest()
- .withConnectorId(usedConnectorId)
- .withIdTag(REGISTERED_OCPP_TAG)
- .withTimestamp(OffsetDateTime.now())
- .withMeterStart(0)
- .withReservationId(reservationId),
- REGISTERED_CHARGE_BOX_ID);
- assertThat(startValidId).isNotNull();
- var transactionIdValid = startValidId.getTransactionId();
-
- {
- var reservations = __DatabasePreparer__.getReservations();
- assertThat(reservations).hasSize(1);
- var res = reservations.get(0);
- assertThat(res.getStatus()).isEqualTo(ReservationStatus.USED.value());
- assertThat(res.getTransactionId()).isEqualTo(transactionIdValid);
- }
-
- // -------------------------------------------------------------------------
- // startTransaction (valid again)
- // -------------------------------------------------------------------------
-
- var startValidIdUsedTwice = client.startTransaction(
- new StartTransactionRequest()
- .withConnectorId(usedConnectorId)
- .withIdTag(REGISTERED_OCPP_TAG)
- .withTimestamp(OffsetDateTime.now())
- .withMeterStart(0)
- .withReservationId(reservationId),
- REGISTERED_CHARGE_BOX_ID);
- assertThat(startValidIdUsedTwice).isNotNull();
-
- {
- var reservations = __DatabasePreparer__.getReservations();
- assertThat(reservations).hasSize(1);
- var res = reservations.get(0);
- assertThat(res.getStatus()).isEqualTo(ReservationStatus.USED.value());
- assertThat(res.getTransactionId()).isEqualTo(transactionIdValid);
- }
- }
-
- @Test
- public void testWithMeterValuesAndTransactionData() {
- testBody(getMeterValues(), getTransactionData());
- }
-
- @Test
- public void testWithMeterValues() {
- testBody(getMeterValues(), null);
- }
-
- @Test
- public void testWithTransactionData() {
- testBody(null, getTransactionData());
- }
-
- @Test
- public void testWithoutMeterValuesAndTransactionData() {
- testBody(null, null);
- }
-
- private void testBody(List meterValues, List transactionData) {
- final var usedConnectorId = 1;
-
- var client = getForOcpp16(path);
-
- initStationWithBootNotification(client);
- initConnectorsWithStatusNotification(client);
-
- // heartbeat
- var heartbeat = client.heartbeat(new HeartbeatRequest(), REGISTERED_CHARGE_BOX_ID);
- assertThat(heartbeat).isNotNull();
-
- // Auth
- var auth = client.authorize(new AuthorizeRequest().withIdTag(REGISTERED_OCPP_TAG), REGISTERED_CHARGE_BOX_ID);
- // Simple request, not much done here
- assertThat(auth).isNotNull();
- assertThat(auth.getIdTagInfo().getStatus()).isEqualTo(AuthorizationStatus.ACCEPTED);
-
- // startTransaction
- var startTimeStamp = OffsetDateTime.now();
- var start = client.startTransaction(
- new StartTransactionRequest()
- .withConnectorId(usedConnectorId)
- .withIdTag(REGISTERED_OCPP_TAG)
- .withTimestamp(startTimeStamp)
- .withMeterStart(0),
- REGISTERED_CHARGE_BOX_ID);
- assertThat(start).isNotNull();
-
- var transactionID = start.getTransactionId();
-
- var allTransactions = __DatabasePreparer__.getTransactionRecords();
- assertThat(allTransactions).hasSize(1);
-
- {
- var t = allTransactions.get(0);
- assertThat(t.getStartTimestamp())
- .isCloseTo(startTimeStamp.toLocalDateTime(), byLessThan(1, ChronoUnit.SECONDS));
- assertThat(t.getStartValue()).isEqualTo("0");
-
- assertThat(t.getStopTimestamp()).isNull();
- assertThat(t.getStopReason()).isNull();
- assertThat(t.getStopValue()).isNull();
- }
-
- // status
- var statusStart = client.statusNotification(
- new StatusNotificationRequest()
- .withStatus(ChargePointStatus.CHARGING)
- .withErrorCode(ChargePointErrorCode.NO_ERROR)
- .withConnectorId(0)
- .withTimestamp(OffsetDateTime.now()),
- REGISTERED_CHARGE_BOX_ID);
- assertThat(statusStart).isNotNull();
-
- // send meterValues
- if (meterValues != null) {
- var meter = client.meterValues(
- new MeterValuesRequest()
- .withConnectorId(usedConnectorId)
- .withTransactionId(transactionID)
- .withMeterValue(meterValues),
- REGISTERED_CHARGE_BOX_ID);
- assertThat(meter).isNotNull();
- checkMeterValues(meterValues, transactionID);
- }
-
- // stopTransaction
- var stopTimeStamp = OffsetDateTime.now();
- var stopValue = 30;
- var stop = client.stopTransaction(
- new StopTransactionRequest()
- .withTransactionId(transactionID)
- .withTransactionData(transactionData)
- .withTimestamp(stopTimeStamp)
- .withIdTag(REGISTERED_OCPP_TAG)
- .withMeterStop(stopValue),
- REGISTERED_CHARGE_BOX_ID);
-
- {
- assertThat(stop).isNotNull();
- var transactionsStop = __DatabasePreparer__.getTransactionRecords();
- assertThat(transactionsStop).hasSize(1);
- var t = transactionsStop.get(0);
- assertThat(t.getStopTimestamp())
- .isCloseTo(stopTimeStamp.toLocalDateTime(), byLessThan(1, ChronoUnit.SECONDS));
- assertThat(t.getStopValue()).isEqualTo(Integer.toString(stopValue));
-
- if (transactionData != null) {
- checkMeterValues(transactionData, transactionID);
- }
- }
-
- // status
- var statusStop = client.statusNotification(
- new StatusNotificationRequest()
- .withStatus(ChargePointStatus.AVAILABLE)
- .withErrorCode(ChargePointErrorCode.NO_ERROR)
- .withConnectorId(usedConnectorId)
- .withTimestamp(OffsetDateTime.now()),
- REGISTERED_CHARGE_BOX_ID);
- assertThat(statusStop).isNotNull();
- }
-
- private void initStationWithBootNotification(CentralSystemService client) {
- var boot = client.bootNotification(
- new BootNotificationRequest()
- .withChargePointVendor(getRandomString())
- .withChargePointModel(getRandomString()),
- REGISTERED_CHARGE_BOX_ID);
- assertThat(boot).isNotNull();
- assertThat(boot.getStatus()).isEqualTo(RegistrationStatus.ACCEPTED);
- }
-
- private void initConnectorsWithStatusNotification(CentralSystemService client) {
- for (var i = 0; i <= numConnectors; i++) {
- var statusBoot = client.statusNotification(
- new StatusNotificationRequest()
- .withErrorCode(ChargePointErrorCode.NO_ERROR)
- .withStatus(ChargePointStatus.AVAILABLE)
- .withConnectorId(i)
- .withTimestamp(OffsetDateTime.now()),
- REGISTERED_CHARGE_BOX_ID);
- assertThat(statusBoot).isNotNull();
- }
- }
-
- private void checkMeterValues(List meterValues, int transactionPk) {
- var details = __DatabasePreparer__.getDetails(transactionPk);
-
- // iterate over all created meter values
- for (var meterValue : meterValues) {
- var sampledValues = meterValue.getSampledValue();
- assertThat(sampledValues).isEmpty();
- var thisValueFound = false;
- // and check, if it can be found in the DB
- for (var values : details.getValues()) {
- if (values.getValue().equals(sampledValues.get(0).getValue())) {
- thisValueFound = true;
- break;
- }
- }
- assertThat(thisValueFound).isTrue();
- }
- }
-
- private List getTransactionData() {
- return Arrays.asList(
- createMeterValue("0.0"), createMeterValue("10.0"), createMeterValue("20.0"), createMeterValue("30.0"));
- }
-
- private List getMeterValues() {
- return Arrays.asList(createMeterValue("3.0"), createMeterValue("13.0"), createMeterValue("23.0"));
- }
-
- private static MeterValue createMeterValue(String val) {
- return new MeterValue().withTimestamp(OffsetDateTime.now()).withSampledValue(new SampledValue().withValue(val));
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/StressTest.java b/steve/src/test/java/de/rwth/idsg/steve/StressTest.java
deleted file mode 100644
index 70c1d87f1..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/StressTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve;
-
-import de.rwth.idsg.steve.utils.LogFileRetriever;
-import de.rwth.idsg.steve.utils.SteveConfigurationReader;
-import de.rwth.idsg.steve.utils.__DatabasePreparer__;
-import ocpp.cs._2015._10.MeterValue;
-import ocpp.cs._2015._10.SampledValue;
-
-import java.time.OffsetDateTime;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-/**
- * @author Sevket Goekay
- * @since 10.05.2018
- */
-public abstract class StressTest {
-
- // higher values -> more stress
- //
- protected static final int THREAD_COUNT = 50;
- protected static final int REPEAT_COUNT_PER_THREAD = 50;
-
- // lower values -> more stress
- //
- // reason: these only specify the size of the values "bag" from which a test picks a value randomly. if there are
- // less values to pick from, it is more likely that tests will use the same value at the same time. this produces
- // more overhead for steve (especially db) when multiple threads "fight" for inserting/updating a db row/cell.
- //
- protected static final int ID_TAG_COUNT = 50;
- protected static final int CHARGE_BOX_COUNT = THREAD_COUNT;
- protected static final int CONNECTOR_COUNT_PER_CHARGE_BOX = 25;
-
- protected void attack() throws Exception {
- var config = SteveConfigurationReader.readSteveConfiguration("main.properties");
- assertThat(config.getProfile()).isEqualTo(ApplicationProfile.TEST);
- assertThat(config.getOcpp().isAutoRegisterUnknownStations()).isTrue();
-
- __DatabasePreparer__.prepare(config);
-
- var app = new Application(config, new LogFileRetriever());
- try {
- app.start();
- attackInternal();
- } finally {
- try {
- app.stop();
- } finally {
- __DatabasePreparer__.cleanUp();
- }
- }
- }
-
- protected abstract void attackInternal() throws Exception;
-
- protected static List getMeterValues(int transactionStart, int transactionStop) {
- final var size = 4;
- var delta = (transactionStop - transactionStart) / size;
- if (delta == 0) {
- return Collections.emptyList();
- }
-
- var list = new ArrayList(size);
- for (var i = 0; i < size; i++) {
- var meterValue = transactionStart + delta * (i + 1);
- list.add(createMeterValue(meterValue));
- }
- return list;
- }
-
- protected static MeterValue createMeterValue(int val) {
- return new MeterValue()
- .withTimestamp(OffsetDateTime.now())
- .withSampledValue(new SampledValue().withValue(Integer.toString(val)));
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/StressTestJsonOCPP16.java b/steve/src/test/java/de/rwth/idsg/steve/StressTestJsonOCPP16.java
deleted file mode 100644
index 1417db13c..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/StressTestJsonOCPP16.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import de.rwth.idsg.steve.ocpp.OcppVersion;
-import de.rwth.idsg.steve.ocpp.ws.JsonObjectMapper;
-import de.rwth.idsg.steve.utils.OcppJsonChargePoint;
-import de.rwth.idsg.steve.utils.SteveConfigurationReader;
-import de.rwth.idsg.steve.utils.StressTester;
-import lombok.RequiredArgsConstructor;
-import ocpp.cs._2015._10.AuthorizationStatus;
-import ocpp.cs._2015._10.AuthorizeRequest;
-import ocpp.cs._2015._10.AuthorizeResponse;
-import ocpp.cs._2015._10.BootNotificationRequest;
-import ocpp.cs._2015._10.BootNotificationResponse;
-import ocpp.cs._2015._10.ChargePointErrorCode;
-import ocpp.cs._2015._10.ChargePointStatus;
-import ocpp.cs._2015._10.HeartbeatRequest;
-import ocpp.cs._2015._10.HeartbeatResponse;
-import ocpp.cs._2015._10.MeterValuesRequest;
-import ocpp.cs._2015._10.MeterValuesResponse;
-import ocpp.cs._2015._10.RegistrationStatus;
-import ocpp.cs._2015._10.StartTransactionRequest;
-import ocpp.cs._2015._10.StartTransactionResponse;
-import ocpp.cs._2015._10.StatusNotificationRequest;
-import ocpp.cs._2015._10.StatusNotificationResponse;
-import ocpp.cs._2015._10.StopTransactionRequest;
-import ocpp.cs._2015._10.StopTransactionResponse;
-
-import java.time.OffsetDateTime;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import static de.rwth.idsg.steve.utils.Helpers.getRandomString;
-import static de.rwth.idsg.steve.utils.Helpers.getRandomStrings;
-import static de.rwth.idsg.steve.utils.Helpers.getWsPath;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.fail;
-
-/**
- * @author Sevket Goekay
- * @since 09.05.2018
- */
-@RequiredArgsConstructor
-public class StressTestJsonOCPP16 extends StressTest {
-
- private static final OcppVersion VERSION = OcppVersion.V_16;
- private static final ObjectMapper OCPP_MAPPER = JsonObjectMapper.createObjectMapper();
-
- private final String path;
-
- public static void main(String[] args) throws Exception {
- var config = SteveConfigurationReader.readSteveConfiguration("main.properties");
- var path = getWsPath(config);
- new StressTestJsonOCPP16(path).attack();
- }
-
- protected void attackInternal() throws Exception {
- final var idTags = getRandomStrings(ID_TAG_COUNT);
- final var chargeBoxIds = getRandomStrings(CHARGE_BOX_COUNT);
-
- var runnable = new StressTester.Runnable() {
-
- private final ThreadLocal threadLocalChargePoint = new ThreadLocal<>();
-
- @Override
- public void beforeRepeat() {
- var localRandom = ThreadLocalRandom.current();
-
- var chargeBoxId = chargeBoxIds.get(localRandom.nextInt(chargeBoxIds.size()));
- threadLocalChargePoint.set(new OcppJsonChargePoint(OCPP_MAPPER, VERSION, chargeBoxId, path));
-
- var chargePoint = threadLocalChargePoint.get();
- chargePoint.start();
-
- chargePoint.prepare(
- new BootNotificationRequest()
- .withChargePointVendor(getRandomString())
- .withChargePointModel(getRandomString()),
- BootNotificationResponse.class,
- bootResponse -> assertThat(bootResponse.getStatus()).isEqualTo(RegistrationStatus.ACCEPTED),
- error -> fail());
- }
-
- @Override
- public void toRepeat() {
- var localRandom = ThreadLocalRandom.current();
-
- var chargePoint = threadLocalChargePoint.get();
-
- var idTag = idTags.get(localRandom.nextInt(idTags.size()));
- var connectorId = localRandom.nextInt(1, CONNECTOR_COUNT_PER_CHARGE_BOX + 1);
- var transactionStart = localRandom.nextInt(0, Integer.MAX_VALUE);
- var transactionStop = localRandom.nextInt(transactionStart + 1, Integer.MAX_VALUE);
-
- chargePoint.prepare(
- new HeartbeatRequest(),
- HeartbeatResponse.class,
- response -> assertThat(response).isNotNull(),
- error -> fail());
-
- for (var i = 0; i <= CONNECTOR_COUNT_PER_CHARGE_BOX; i++) {
- chargePoint.prepare(
- new StatusNotificationRequest()
- .withErrorCode(ChargePointErrorCode.NO_ERROR)
- .withStatus(ChargePointStatus.AVAILABLE)
- .withConnectorId(i)
- .withTimestamp(OffsetDateTime.now()),
- StatusNotificationResponse.class,
- response -> assertThat(response).isNotNull(),
- error -> fail());
- }
-
- chargePoint.prepare(
- new AuthorizeRequest().withIdTag(idTag),
- AuthorizeResponse.class,
- response -> assertThat(response.getIdTagInfo().getStatus())
- .isNotEqualTo(AuthorizationStatus.ACCEPTED),
- error -> fail());
-
- final var transactionId = new AtomicInteger(-1);
-
- chargePoint.prepare(
- new StartTransactionRequest()
- .withConnectorId(connectorId)
- .withIdTag(idTag)
- .withTimestamp(OffsetDateTime.now())
- .withMeterStart(transactionStart),
- StartTransactionResponse.class,
- response -> {
- assertThat(response).isNotNull();
- transactionId.set(response.getTransactionId());
- },
- error -> fail());
-
- // wait for StartTransactionResponse to arrive, since we need the transactionId from now on
- chargePoint.process();
-
- chargePoint.prepare(
- new StatusNotificationRequest()
- .withErrorCode(ChargePointErrorCode.NO_ERROR)
- .withStatus(ChargePointStatus.CHARGING)
- .withConnectorId(connectorId)
- .withTimestamp(OffsetDateTime.now()),
- StatusNotificationResponse.class,
- response -> assertThat(response).isNotNull(),
- error -> fail());
-
- chargePoint.prepare(
- new MeterValuesRequest()
- .withConnectorId(connectorId)
- .withTransactionId(transactionId.get())
- .withMeterValue(getMeterValues(transactionStart, transactionStop)),
- MeterValuesResponse.class,
- response -> assertThat(response).isNotNull(),
- error -> fail());
-
- chargePoint.prepare(
- new StopTransactionRequest()
- .withTransactionId(transactionId.get())
- .withTimestamp(OffsetDateTime.now())
- .withIdTag(idTag)
- .withMeterStop(transactionStop),
- StopTransactionResponse.class,
- response -> assertThat(response).isNotNull(),
- error -> fail());
-
- chargePoint.prepare(
- new StatusNotificationRequest()
- .withErrorCode(ChargePointErrorCode.NO_ERROR)
- .withStatus(ChargePointStatus.AVAILABLE)
- .withConnectorId(connectorId)
- .withTimestamp(OffsetDateTime.now()),
- StatusNotificationResponse.class,
- response -> assertThat(response).isNotNull(),
- error -> fail());
-
- chargePoint.process();
- }
-
- @Override
- public void afterRepeat() {
- threadLocalChargePoint.get().close();
- }
- };
-
- var tester = new StressTester(THREAD_COUNT, REPEAT_COUNT_PER_THREAD);
- tester.test(runnable);
- tester.shutDown();
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/StressTestSoapOCPP16.java b/steve/src/test/java/de/rwth/idsg/steve/StressTestSoapOCPP16.java
deleted file mode 100644
index cdda91bd5..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/StressTestSoapOCPP16.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve;
-
-import de.rwth.idsg.steve.utils.SteveConfigurationReader;
-import de.rwth.idsg.steve.utils.StressTester;
-import lombok.RequiredArgsConstructor;
-import ocpp.cs._2015._10.AuthorizationStatus;
-import ocpp.cs._2015._10.AuthorizeRequest;
-import ocpp.cs._2015._10.BootNotificationRequest;
-import ocpp.cs._2015._10.ChargePointErrorCode;
-import ocpp.cs._2015._10.ChargePointStatus;
-import ocpp.cs._2015._10.HeartbeatRequest;
-import ocpp.cs._2015._10.MeterValuesRequest;
-import ocpp.cs._2015._10.RegistrationStatus;
-import ocpp.cs._2015._10.StartTransactionRequest;
-import ocpp.cs._2015._10.StatusNotificationRequest;
-import ocpp.cs._2015._10.StopTransactionRequest;
-
-import java.time.OffsetDateTime;
-import java.util.concurrent.ThreadLocalRandom;
-
-import static de.rwth.idsg.steve.utils.Helpers.getForOcpp16;
-import static de.rwth.idsg.steve.utils.Helpers.getHttpPath;
-import static de.rwth.idsg.steve.utils.Helpers.getRandomString;
-import static de.rwth.idsg.steve.utils.Helpers.getRandomStrings;
-import static org.assertj.core.api.Assertions.assertThat;
-
-/**
- * @author Sevket Goekay
- * @since 18.04.2018
- */
-@RequiredArgsConstructor
-public class StressTestSoapOCPP16 extends StressTest {
-
- private final String path;
-
- public static void main(String[] args) throws Exception {
- var config = SteveConfigurationReader.readSteveConfiguration("main.properties");
- var path = getHttpPath(config);
- new StressTestSoapOCPP16(path).attack();
- }
-
- protected void attackInternal() throws Exception {
- final var idTags = getRandomStrings(ID_TAG_COUNT);
- final var chargeBoxIds = getRandomStrings(CHARGE_BOX_COUNT);
-
- var runnable = new StressTester.Runnable() {
-
- private final ThreadLocal threadLocalChargeBoxId = new ThreadLocal<>();
-
- @Override
- public void beforeRepeat() {
- var client = getForOcpp16(path);
- var localRandom = ThreadLocalRandom.current();
-
- threadLocalChargeBoxId.set(chargeBoxIds.get(localRandom.nextInt(chargeBoxIds.size())));
-
- var chargeBoxId = threadLocalChargeBoxId.get();
-
- // to insert threadLocalChargeBoxId into db
- var boot = client.bootNotification(
- new BootNotificationRequest()
- .withChargePointVendor(getRandomString())
- .withChargePointModel(getRandomString()),
- chargeBoxId);
- assertThat(boot.getStatus()).isEqualTo(RegistrationStatus.ACCEPTED);
- }
-
- @Override
- public void toRepeat() {
- var client = getForOcpp16(path);
- var localRandom = ThreadLocalRandom.current();
-
- var chargeBoxId = threadLocalChargeBoxId.get();
-
- var idTag = idTags.get(localRandom.nextInt(idTags.size()));
- var connectorId = localRandom.nextInt(1, CONNECTOR_COUNT_PER_CHARGE_BOX + 1);
- var transactionStart = localRandom.nextInt(0, Integer.MAX_VALUE);
- var transactionStop = localRandom.nextInt(transactionStart + 1, Integer.MAX_VALUE);
-
- var heartbeat = client.heartbeat(new HeartbeatRequest(), chargeBoxId);
- assertThat(heartbeat).isNotNull();
-
- for (var i = 0; i <= CONNECTOR_COUNT_PER_CHARGE_BOX; i++) {
- var status = client.statusNotification(
- new StatusNotificationRequest()
- .withErrorCode(ChargePointErrorCode.NO_ERROR)
- .withStatus(ChargePointStatus.AVAILABLE)
- .withConnectorId(i)
- .withTimestamp(OffsetDateTime.now()),
- chargeBoxId);
- assertThat(status).isNotNull();
- }
-
- var auth = client.authorize(new AuthorizeRequest().withIdTag(idTag), chargeBoxId);
- assertThat(auth.getIdTagInfo().getStatus()).isNotEqualTo(AuthorizationStatus.ACCEPTED);
-
- var start = client.startTransaction(
- new StartTransactionRequest()
- .withConnectorId(connectorId)
- .withIdTag(idTag)
- .withTimestamp(OffsetDateTime.now())
- .withMeterStart(transactionStart),
- chargeBoxId);
- assertThat(start).isNotNull();
-
- var statusStart = client.statusNotification(
- new StatusNotificationRequest()
- .withErrorCode(ChargePointErrorCode.NO_ERROR)
- .withStatus(ChargePointStatus.CHARGING)
- .withConnectorId(connectorId)
- .withTimestamp(OffsetDateTime.now()),
- chargeBoxId);
- assertThat(statusStart).isNotNull();
-
- var meter = client.meterValues(
- new MeterValuesRequest()
- .withConnectorId(connectorId)
- .withTransactionId(start.getTransactionId())
- .withMeterValue(getMeterValues(transactionStart, transactionStop)),
- chargeBoxId);
- assertThat(meter).isNotNull();
-
- var stop = client.stopTransaction(
- new StopTransactionRequest()
- .withTransactionId(start.getTransactionId())
- .withTimestamp(OffsetDateTime.now())
- .withIdTag(idTag)
- .withMeterStop(transactionStop),
- chargeBoxId);
- assertThat(stop).isNotNull();
-
- var statusStop = client.statusNotification(
- new StatusNotificationRequest()
- .withErrorCode(ChargePointErrorCode.NO_ERROR)
- .withStatus(ChargePointStatus.AVAILABLE)
- .withConnectorId(connectorId)
- .withTimestamp(OffsetDateTime.now()),
- chargeBoxId);
- assertThat(statusStop).isNotNull();
- }
-
- @Override
- public void afterRepeat() {}
- };
-
- var tester = new StressTester(THREAD_COUNT, REPEAT_COUNT_PER_THREAD);
- tester.test(runnable);
- tester.shutDown();
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/TypeStoreTest.java b/steve/src/test/java/de/rwth/idsg/steve/TypeStoreTest.java
deleted file mode 100644
index 1e35b41f4..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/TypeStoreTest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve;
-
-import de.rwth.idsg.steve.ocpp.ws.ocpp12.Ocpp12TypeStore;
-import de.rwth.idsg.steve.ocpp.ws.ocpp15.Ocpp15TypeStore;
-import de.rwth.idsg.steve.ocpp.ws.ocpp16.Ocpp16TypeStore;
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-/**
- * @author Sevket Goekay
- * @since 10.03.2018
- */
-public class TypeStoreTest {
-
- @Test
- public void ocpp12Test() {
- var typeStore = new Ocpp12TypeStore();
-
- var actionResponse = typeStore.findActionResponse(new ocpp.cp._2010._08.ResetRequest());
- assertThat(actionResponse).isNotNull();
- assertThat(actionResponse.getAction()).isEqualTo("Reset");
- assertThat(actionResponse.getResponseClass()).isEqualTo(ocpp.cp._2010._08.ResetResponse.class);
-
- var requestClass = typeStore.findRequestClass("BootNotification");
- assertThat(requestClass).isSameAs(ocpp.cs._2010._08.BootNotificationRequest.class);
- }
-
- @Test
- public void ocpp15Test() {
- var typeStore = new Ocpp15TypeStore();
-
- var actionResponse = typeStore.findActionResponse(new ocpp.cp._2012._06.UpdateFirmwareRequest());
- assertThat(actionResponse).isNotNull();
- assertThat(actionResponse.getAction()).isEqualTo("UpdateFirmware");
- assertThat(actionResponse.getResponseClass()).isEqualTo(ocpp.cp._2012._06.UpdateFirmwareResponse.class);
-
- var requestClass = typeStore.findRequestClass("BootNotification");
- assertThat(requestClass).isSameAs(ocpp.cs._2012._06.BootNotificationRequest.class);
- }
-
- @Test
- public void ocpp16Test() {
- var typeStore = new Ocpp16TypeStore();
-
- var actionResponse = typeStore.findActionResponse(new ocpp.cp._2015._10.UpdateFirmwareRequest());
- assertThat(actionResponse).isNotNull();
- assertThat(actionResponse.getAction()).isEqualTo("UpdateFirmware");
- assertThat(actionResponse.getResponseClass()).isEqualTo(ocpp.cp._2015._10.UpdateFirmwareResponse.class);
-
- var requestClass = typeStore.findRequestClass("BootNotification");
- assertThat(requestClass).isSameAs(ocpp.cs._2015._10.BootNotificationRequest.class);
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/issues/Issue1219.java b/steve/src/test/java/de/rwth/idsg/steve/issues/Issue1219.java
deleted file mode 100644
index 65a84041d..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/issues/Issue1219.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve.issues;
-
-import de.rwth.idsg.steve.SteveException;
-import de.rwth.idsg.steve.repository.dto.InsertTransactionParams;
-import de.rwth.idsg.steve.repository.dto.OcppTag;
-import de.rwth.idsg.steve.repository.dto.Transaction;
-import de.rwth.idsg.steve.repository.dto.TransactionStopEventActor;
-import de.rwth.idsg.steve.repository.dto.UpdateTransactionParams;
-import de.rwth.idsg.steve.repository.impl.AddressRepositoryImpl;
-import de.rwth.idsg.steve.repository.impl.ChargePointRepositoryImpl;
-import de.rwth.idsg.steve.repository.impl.OcppServerRepositoryImpl;
-import de.rwth.idsg.steve.repository.impl.OcppTagRepositoryImpl;
-import de.rwth.idsg.steve.repository.impl.ReservationRepositoryImpl;
-import de.rwth.idsg.steve.repository.impl.TransactionRepositoryImpl;
-import de.rwth.idsg.steve.web.dto.OcppTagForm;
-import de.rwth.idsg.steve.web.dto.OcppTagQueryForm;
-import de.rwth.idsg.steve.web.dto.TransactionQueryForm;
-import lombok.RequiredArgsConstructor;
-import org.jooq.DSLContext;
-import org.jooq.SQLDialect;
-import org.jooq.impl.DSL;
-import org.jooq.impl.DataSourceConnectionProvider;
-import org.jooq.impl.DefaultConfiguration;
-import org.jooq.tools.jdbc.SingleConnectionDataSource;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.time.Duration;
-import java.time.Instant;
-import java.time.temporal.ChronoUnit;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.UUID;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.stream.IntStream;
-
-@RequiredArgsConstructor
-public class Issue1219 {
-
- private static final String url = "jdbc:mysql://localhost:3306/stevedb";
- private static final String userName = "steve";
- private static final String password = "changeme";
-
- private final DSLContext ctx;
-
- public static void main(String[] args) throws Exception {
- Connection con = DriverManager.getConnection(url, userName, password);
-
- org.jooq.Configuration conf = new DefaultConfiguration()
- .set(SQLDialect.MYSQL)
- .set(new DataSourceConnectionProvider(new SingleConnectionDataSource(con)));
-
- DSLContext ctx = DSL.using(conf);
-
- Issue1219 issue1219 = new Issue1219(ctx);
-
- var ocppTags = issue1219.insertOcppTags(1_000);
- System.out.println("inserted ocppTags");
-
- var chargeBoxIds = issue1219.insertChargeBoxes(500);
- System.out.println("inserted chargeBoxIds");
-
- var transactionIds = issue1219.insertStartTransactions(10_000, ocppTags, chargeBoxIds);
- System.out.println("inserted transaction_starts");
-
- var stoppedTransactionIds = issue1219.insertStopTransactions(transactionIds);
- System.out.println("inserted transaction_stops: " + stoppedTransactionIds.size());
-
- System.out.println("-- TESTING --");
- issue1219.realTest();
- }
-
- private void realTest() {
- var repository = new OcppTagRepositoryImpl(ctx);
-
- var start = Instant.now();
- List values = repository.getOverview(new OcppTagQueryForm());
- var stop = Instant.now();
-
- System.out.println("took " + Duration.between(start, stop).toMillis() + " ms");
- }
-
- private List insertStopTransactions(List insertedTransactionIds) {
- var ocppServerRepository = new OcppServerRepositoryImpl(ctx, new ReservationRepositoryImpl(ctx));
- var transactionRepository = new TransactionRepositoryImpl(ctx);
-
- List stopped = new ArrayList<>();
- for (Integer transactionId : insertedTransactionIds) {
- if (!ThreadLocalRandom.current().nextBoolean()) {
- continue;
- }
-
- TransactionQueryForm form = new TransactionQueryForm();
- form.setTransactionPk(transactionId);
- Transaction transaction =
- transactionRepository.getTransactions(form).get(0);
-
- var stopTimestamp = transaction.getStartTimestamp().plus(1, ChronoUnit.HOURS);
- UpdateTransactionParams p = UpdateTransactionParams.builder()
- .chargeBoxId(transaction.getChargeBoxId())
- .transactionId(transaction.getId())
- .stopTimestamp(stopTimestamp)
- .eventTimestamp(stopTimestamp)
- .stopMeterValue(transaction.getStartValue() + "0")
- .eventActor(TransactionStopEventActor.STATION)
- .build();
-
- ocppServerRepository.updateTransaction(p);
- System.out.println("stopped transaction " + transactionId);
- stopped.add(transactionId);
- }
- return stopped;
- }
-
- private List insertStartTransactions(int count, List ocppTags, List chargeBoxIds) {
- var repository = new OcppServerRepositoryImpl(ctx, new ReservationRepositoryImpl(ctx));
-
- List transactionIds = new ArrayList<>();
- for (int i = 0; i < count; i++) {
- var now = Instant.now();
- InsertTransactionParams params = InsertTransactionParams.builder()
- .idTag(ocppTags.get(ThreadLocalRandom.current().nextInt(0, ocppTags.size())))
- .chargeBoxId(chargeBoxIds.get(ThreadLocalRandom.current().nextInt(0, chargeBoxIds.size())))
- .connectorId(ThreadLocalRandom.current().nextInt(4))
- .startMeterValue(String.valueOf(ThreadLocalRandom.current().nextLong(5_000, 20_000)))
- .startTimestamp(now)
- .eventTimestamp(now)
- .build();
- int transactionId = repository.insertTransaction(params);
- System.out.println("started transaction " + transactionId);
- transactionIds.add(transactionId);
- }
- return transactionIds;
- }
-
- private List insertChargeBoxes(int count) {
- var repository = new ChargePointRepositoryImpl(ctx, new AddressRepositoryImpl(ctx));
-
- List ids = IntStream.range(0, count)
- .mapToObj(val -> UUID.randomUUID().toString())
- .toList();
- repository.addChargePointList(ids);
-
- return ids;
- }
-
- private List insertOcppTags(int count) {
- var repository = new OcppTagRepositoryImpl(ctx);
-
- List idTags = IntStream.range(0, count)
- .mapToObj(val -> UUID.randomUUID().toString())
- .toList();
- List insertedTags = new ArrayList<>();
-
- for (String idTag : idTags) {
- OcppTagForm form = new OcppTagForm();
- form.setIdTag(idTag);
- form.setExpiryDate(getRandomExpiry());
- form.setParentIdTag(getRandomParentIdTag(idTag, insertedTags));
- form.setMaxActiveTransactionCount(ThreadLocalRandom.current().nextInt(1, 4));
-
- try {
- repository.addOcppTag(form);
- } catch (SteveException.AlreadyExists e) {
- // because the referenced idTag was not inserted yet. just inserted without it.
- form.setParentIdTag(null);
- repository.addOcppTag(form);
- }
- insertedTags.add(idTag);
- }
-
- return insertedTags;
- }
-
- private static String getRandomParentIdTag(String current, List source) {
- if (source.isEmpty()) {
- return null;
- }
- if (ThreadLocalRandom.current().nextBoolean()) {
- String parent = source.get(ThreadLocalRandom.current().nextInt(0, source.size()));
- if (!Objects.equals(parent, current)) {
- return parent;
- }
- }
- return null;
- }
-
- private static Instant getRandomExpiry() {
- if (ThreadLocalRandom.current().nextBoolean()) {
- return Instant.now().plus(ThreadLocalRandom.current().nextInt(1, 365), ChronoUnit.DAYS);
- }
- return null;
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/issues/Issue72.java b/steve/src/test/java/de/rwth/idsg/steve/issues/Issue72.java
deleted file mode 100644
index 4d9b2da23..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/issues/Issue72.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve.issues;
-
-import de.rwth.idsg.steve.StressTest;
-import de.rwth.idsg.steve.utils.Helpers;
-import de.rwth.idsg.steve.utils.SteveConfigurationReader;
-import de.rwth.idsg.steve.utils.StressTester;
-import de.rwth.idsg.steve.utils.__DatabasePreparer__;
-import lombok.RequiredArgsConstructor;
-import ocpp.cs._2015._10.BootNotificationRequest;
-import ocpp.cs._2015._10.CentralSystemService;
-import ocpp.cs._2015._10.MeterValue;
-import ocpp.cs._2015._10.MeterValuesRequest;
-import ocpp.cs._2015._10.RegistrationStatus;
-import ocpp.cs._2015._10.SampledValue;
-import ocpp.cs._2015._10.StartTransactionRequest;
-import ocpp.cs._2015._10.StopTransactionRequest;
-import ocpp.cs._2015._10.UnitOfMeasure;
-
-import java.time.OffsetDateTime;
-
-import static de.rwth.idsg.steve.utils.Helpers.getForOcpp16;
-import static de.rwth.idsg.steve.utils.Helpers.getHttpPath;
-import static de.rwth.idsg.steve.utils.Helpers.getRandomString;
-import static org.assertj.core.api.Assertions.assertThat;
-
-/**
- * https://github.com/steve-community/steve/issues/72
- *
- * @author Sevket Goekay
- * @since 27.06.2018
- */
-@RequiredArgsConstructor
-public class Issue72 extends StressTest {
-
- private final String path;
-
- public static void main(String[] args) throws Exception {
- var config = SteveConfigurationReader.readSteveConfiguration("main.properties");
- var path = getHttpPath(config);
- new Issue72(path).attack();
- }
-
- protected void attackInternal() throws Exception {
- var idTag = __DatabasePreparer__.getRegisteredOcppTag();
- var chargeBoxId = Helpers.getRandomString();
-
- var startDateTime = OffsetDateTime.now();
- var stopDateTime = startDateTime.plusHours(5);
-
- var connectorId = 2;
-
- var meterStart = 444;
- var meterStop = 99999;
-
- var boot = getForOcpp16(path)
- .bootNotification(
- new BootNotificationRequest()
- .withChargePointVendor(getRandomString())
- .withChargePointModel(getRandomString()),
- chargeBoxId);
- assertThat(boot.getStatus()).isEqualTo(RegistrationStatus.ACCEPTED);
-
- var start = getForOcpp16(path)
- .startTransaction(
- new StartTransactionRequest()
- .withConnectorId(connectorId)
- .withIdTag(idTag)
- .withTimestamp(startDateTime)
- .withMeterStart(meterStart),
- chargeBoxId);
- assertThat(start).isNotNull();
-
- var transactionId = start.getTransactionId();
-
- var runnable = new StressTester.Runnable() {
-
- private final ThreadLocal threadLocalClient = new ThreadLocal<>();
-
- @Override
- public void beforeRepeat() {
- threadLocalClient.set(getForOcpp16(path));
- }
-
- @Override
- public void toRepeat() {
- var mvr = threadLocalClient
- .get()
- .meterValues(
- new MeterValuesRequest()
- .withConnectorId(connectorId)
- .withTransactionId(transactionId)
- .withMeterValue(new MeterValue()
- .withTimestamp(stopDateTime)
- .withSampledValue(new SampledValue()
- .withValue("555")
- .withUnit(UnitOfMeasure.WH))),
- chargeBoxId);
- assertThat(mvr).isNotNull();
-
- var stop = threadLocalClient
- .get()
- .stopTransaction(
- new StopTransactionRequest()
- .withTransactionId(transactionId)
- .withTimestamp(stopDateTime)
- .withIdTag(idTag)
- .withMeterStop(meterStop),
- chargeBoxId);
- assertThat(stop).isNotNull();
- }
-
- @Override
- public void afterRepeat() {}
- };
-
- var tester = new StressTester(THREAD_COUNT, REPEAT_COUNT_PER_THREAD);
- tester.test(runnable);
- tester.shutDown();
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/issues/Issue72LowLevelSoap.java b/steve/src/test/java/de/rwth/idsg/steve/issues/Issue72LowLevelSoap.java
deleted file mode 100644
index e80f7ec72..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/issues/Issue72LowLevelSoap.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve.issues;
-
-import com.google.common.net.MediaType;
-import de.rwth.idsg.steve.StressTest;
-import de.rwth.idsg.steve.utils.Helpers;
-import de.rwth.idsg.steve.utils.SteveConfigurationReader;
-import de.rwth.idsg.steve.utils.StressTester;
-import de.rwth.idsg.steve.utils.__DatabasePreparer__;
-import lombok.RequiredArgsConstructor;
-import ocpp.cs._2015._10.BootNotificationRequest;
-import ocpp.cs._2015._10.CentralSystemService;
-import ocpp.cs._2015._10.Measurand;
-import ocpp.cs._2015._10.MeterValue;
-import ocpp.cs._2015._10.MeterValuesRequest;
-import ocpp.cs._2015._10.RegistrationStatus;
-import ocpp.cs._2015._10.SampledValue;
-import ocpp.cs._2015._10.StartTransactionRequest;
-import ocpp.cs._2015._10.UnitOfMeasure;
-import org.apache.http.HttpStatus;
-import org.apache.http.client.methods.RequestBuilder;
-import org.apache.http.entity.ContentType;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.impl.client.HttpClients;
-
-import java.time.OffsetDateTime;
-
-import static de.rwth.idsg.steve.utils.Helpers.getForOcpp16;
-import static de.rwth.idsg.steve.utils.Helpers.getHttpPath;
-import static de.rwth.idsg.steve.utils.Helpers.getRandomString;
-import static org.assertj.core.api.Assertions.assertThat;
-
-/**
- * https://github.com/steve-community/steve/issues/72
- *
- * @author Sevket Goekay
- * @since 27.06.2018
- */
-@RequiredArgsConstructor
-public class Issue72LowLevelSoap extends StressTest {
-
- private final String path;
-
- public static void main(String[] args) throws Exception {
- var config = SteveConfigurationReader.readSteveConfiguration("main.properties");
- var path = getHttpPath(config);
- new Issue72LowLevelSoap(path).attack();
- }
-
- protected void attackInternal() throws Exception {
- var idTag = __DatabasePreparer__.getRegisteredOcppTag();
- var chargeBoxId = Helpers.getRandomString();
-
- var startDateTime = OffsetDateTime.parse("2018-06-27T01:10:10Z");
- var stopDateTime = OffsetDateTime.parse("2018-06-27T04:10:10Z");
-
- var connectorId = 2;
-
- var meterStart = 444;
- var meterStop = 99999;
-
- var boot = getForOcpp16(path)
- .bootNotification(
- new BootNotificationRequest()
- .withChargePointVendor(getRandomString())
- .withChargePointModel(getRandomString()),
- chargeBoxId);
- assertThat(boot.getStatus()).isEqualTo(RegistrationStatus.ACCEPTED);
-
- var start = getForOcpp16(path)
- .startTransaction(
- new StartTransactionRequest()
- .withConnectorId(connectorId)
- .withIdTag(idTag)
- .withTimestamp(startDateTime)
- .withMeterStart(meterStart),
- chargeBoxId);
- assertThat(start).isNotNull();
-
- var transactionId = start.getTransactionId();
-
- var body = buildRequest(path, chargeBoxId, transactionId, idTag, stopDateTime, meterStop);
- var contentType = ContentType.create(
- MediaType.SOAP_XML_UTF_8.type(),
- MediaType.SOAP_XML_UTF_8.charset().orNull());
-
- var req = RequestBuilder.post(path)
- .addHeader("SOAPAction", "urn://Ocpp/Cs/2015/10/StopTransaction")
- .setEntity(new StringEntity(body, contentType))
- .build();
-
- var httpClient = HttpClients.createDefault();
-
- var runnable = new StressTester.Runnable() {
-
- private final ThreadLocal threadLocalClient = new ThreadLocal<>();
-
- @Override
- public void beforeRepeat() {
- threadLocalClient.set(getForOcpp16(path));
- }
-
- @Override
- public void toRepeat() {
-
- var mvr = threadLocalClient
- .get()
- .meterValues(
- new MeterValuesRequest()
- .withConnectorId(connectorId)
- .withTransactionId(transactionId)
- .withMeterValue(new MeterValue()
- .withTimestamp(stopDateTime)
- .withSampledValue(new SampledValue()
- .withMeasurand(Measurand.ENERGY_ACTIVE_IMPORT_REGISTER)
- .withValue("555")
- .withUnit(UnitOfMeasure.WH))),
- chargeBoxId);
- assertThat(mvr).isNotNull();
-
- try {
- httpClient.execute(req, httpResponse -> {
- if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
- throw new RuntimeException("Not OK");
- }
- return null;
- });
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public void afterRepeat() {}
- };
-
- try {
- var tester = new StressTester(100, 100);
- tester.test(runnable);
- tester.shutDown();
- } finally {
- httpClient.close();
- }
- }
-
- private static String buildRequest(
- String path, String chargeBoxId, int transactionId, String idTag, OffsetDateTime stop, int meterStop) {
- return ""
- + "/StopTransaction"
- + "urn:uuid:47c9e1d9-a278-4e9c-8f08-565c29d86167"
- + ""
- + path + ""
- + "http://www.w3.org/2005/08/addressing/anonymous"
- + ""
- + chargeBoxId + "" + ""
- + ""
- + transactionId + "" + ""
- + idTag + "" + ""
- + stop + "" + ""
- + meterStop + "" + "";
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/issues/Issue73Fix.java b/steve/src/test/java/de/rwth/idsg/steve/issues/Issue73Fix.java
deleted file mode 100644
index c84d48ca0..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/issues/Issue73Fix.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve.issues;
-
-import com.google.common.collect.Lists;
-import de.rwth.idsg.steve.Application;
-import de.rwth.idsg.steve.ApplicationProfile;
-import de.rwth.idsg.steve.utils.LogFileRetriever;
-import de.rwth.idsg.steve.utils.SteveConfigurationReader;
-import de.rwth.idsg.steve.utils.__DatabasePreparer__;
-import ocpp.cs._2015._10.AuthorizationStatus;
-import ocpp.cs._2015._10.AuthorizeRequest;
-import ocpp.cs._2015._10.BootNotificationRequest;
-import ocpp.cs._2015._10.CentralSystemService;
-import ocpp.cs._2015._10.RegistrationStatus;
-import ocpp.cs._2015._10.StartTransactionRequest;
-
-import java.time.OffsetDateTime;
-import java.util.List;
-
-import static de.rwth.idsg.steve.utils.Helpers.getForOcpp16;
-import static de.rwth.idsg.steve.utils.Helpers.getHttpPath;
-import static de.rwth.idsg.steve.utils.Helpers.getRandomString;
-import static org.assertj.core.api.Assertions.assertThat;
-
-/**
- * https://github.com/steve-community/steve/issues/73
- *
- * @author Sevket Goekay
- * @since 02.07.2018
- */
-public class Issue73Fix {
-
- private static final String REGISTERED_OCPP_TAG = __DatabasePreparer__.getRegisteredOcppTag();
-
- private static String path;
-
- public static void main(String[] args) throws Exception {
- var config = SteveConfigurationReader.readSteveConfiguration("main.properties");
- assertThat(config.getProfile()).isEqualTo(ApplicationProfile.TEST);
- assertThat(config.getOcpp().isAutoRegisterUnknownStations()).isTrue();
-
- __DatabasePreparer__.prepare(config);
-
- path = getHttpPath(config);
-
- var app = new Application(config, new LogFileRetriever());
- try {
- app.start();
- test();
- } finally {
- try {
- app.stop();
- } finally {
- __DatabasePreparer__.cleanUp();
- }
- }
- }
-
- private static void test() {
- var client = getForOcpp16(path);
-
- var chargeBox1 = getRandomString();
- var chargeBox2 = getRandomString();
-
- sendBoot(client, Lists.newArrayList(chargeBox1, chargeBox2));
-
- sendAuth(client, chargeBox1, AuthorizationStatus.ACCEPTED);
-
- sendStartTx(client, chargeBox1);
-
- sendAuth(client, chargeBox1, AuthorizationStatus.ACCEPTED);
-
- sendAuth(client, chargeBox2, AuthorizationStatus.CONCURRENT_TX);
- }
-
- private static void sendBoot(CentralSystemService client, List chargeBoxIdList) {
- for (var chargeBoxId : chargeBoxIdList) {
- var boot = client.bootNotification(
- new BootNotificationRequest()
- .withChargePointVendor(getRandomString())
- .withChargePointModel(getRandomString()),
- chargeBoxId);
- assertThat(boot).isNotNull();
- assertThat(boot.getStatus()).isEqualTo(RegistrationStatus.ACCEPTED);
- }
- }
-
- private static void sendAuth(CentralSystemService client, String chargeBoxId, AuthorizationStatus expected) {
- var auth = client.authorize(new AuthorizeRequest().withIdTag(REGISTERED_OCPP_TAG), chargeBoxId);
- assertThat(auth).isNotNull();
- assertThat(auth.getIdTagInfo().getStatus()).isEqualTo(expected);
- }
-
- private static void sendStartTx(CentralSystemService client, String chargeBoxId) {
- var start = client.startTransaction(
- new StartTransactionRequest()
- .withConnectorId(2)
- .withIdTag(REGISTERED_OCPP_TAG)
- .withTimestamp(OffsetDateTime.now())
- .withMeterStart(0),
- chargeBoxId);
- assertThat(start).isNotNull();
- assertThat(start.getTransactionId()).isGreaterThan(0);
- assertThat(__DatabasePreparer__.getOcppTagRecord(REGISTERED_OCPP_TAG).getInTransaction())
- .isTrue();
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/issues/Issue81.java b/steve/src/test/java/de/rwth/idsg/steve/issues/Issue81.java
deleted file mode 100644
index 5aa211159..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/issues/Issue81.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve.issues;
-
-import de.rwth.idsg.steve.StressTest;
-import de.rwth.idsg.steve.utils.Helpers;
-import de.rwth.idsg.steve.utils.SteveConfigurationReader;
-import de.rwth.idsg.steve.utils.StressTester;
-import lombok.RequiredArgsConstructor;
-import ocpp.cs._2015._10.BootNotificationRequest;
-import ocpp.cs._2015._10.CentralSystemService;
-import ocpp.cs._2015._10.RegistrationStatus;
-import ocpp.cs._2015._10.StartTransactionRequest;
-
-import java.time.OffsetDateTime;
-import java.time.ZoneOffset;
-import java.util.concurrent.ThreadLocalRandom;
-
-import static de.rwth.idsg.steve.utils.Helpers.getForOcpp16;
-import static de.rwth.idsg.steve.utils.Helpers.getHttpPath;
-import static de.rwth.idsg.steve.utils.Helpers.getRandomString;
-import static org.assertj.core.api.Assertions.assertThat;
-
-/**
- * @author Sevket Goekay
- * @since 19.07.2018
- */
-@RequiredArgsConstructor
-public class Issue81 extends StressTest {
-
- private final String path;
-
- public static void main(String[] args) throws Exception {
- var config = SteveConfigurationReader.readSteveConfiguration("main.properties");
- var path = getHttpPath(config);
- new Issue81(path).attack();
- }
-
- protected void attackInternal() throws Exception {
- var runnable = new StressTester.Runnable() {
-
- private final ThreadLocal client = new ThreadLocal<>();
- private final ThreadLocal chargeBoxId = new ThreadLocal<>();
- private final ThreadLocal txRequest = new ThreadLocal<>();
- private final ThreadLocal txId = new ThreadLocal<>();
-
- @Override
- public void beforeRepeat() {
- client.set(getForOcpp16(path));
- chargeBoxId.set(Helpers.getRandomString());
-
- var boot = getForOcpp16(path)
- .bootNotification(
- new BootNotificationRequest()
- .withChargePointVendor(getRandomString())
- .withChargePointModel(getRandomString()),
- chargeBoxId.get());
- assertThat(boot.getStatus()).isEqualTo(RegistrationStatus.ACCEPTED);
-
- var req = new StartTransactionRequest()
- .withConnectorId(ThreadLocalRandom.current().nextInt(1, 8))
- .withIdTag(Helpers.getRandomString())
- .withTimestamp(OffsetDateTime.now(ZoneOffset.UTC))
- .withMeterStart(ThreadLocalRandom.current().nextInt(0, 1_000_000));
- txRequest.set(req);
-
- Integer t1 = sendStartTx(client.get(), txRequest.get(), chargeBoxId.get());
- txId.set(t1);
- }
-
- @Override
- public void toRepeat() {
- var t2 = sendStartTx(client.get(), txRequest.get(), chargeBoxId.get());
- assertThat(t2).isEqualTo(txId.get());
- }
-
- @Override
- public void afterRepeat() {}
- };
-
- var tester = new StressTester(THREAD_COUNT, REPEAT_COUNT_PER_THREAD);
- tester.test(runnable);
- tester.shutDown();
- }
-
- private static Integer sendStartTx(CentralSystemService client, StartTransactionRequest req, String chargeBoxId) {
- var start = client.startTransaction(req, chargeBoxId);
- assertThat(start).isNotNull();
- return start.getTransactionId();
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/ocpp/OcppVersionTest.java b/steve/src/test/java/de/rwth/idsg/steve/ocpp/OcppVersionTest.java
deleted file mode 100644
index 6af1d6041..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/ocpp/OcppVersionTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve.ocpp;
-
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class OcppVersionTest {
-
- @ParameterizedTest
- @EnumSource(OcppVersion.class)
- public void testFromValue(OcppVersion input) {
- var toTest = input.getValue();
- var inputBack = OcppVersion.fromValue(toTest);
- assertThat(inputBack).isEqualTo(input);
- }
-
- @ParameterizedTest
- @EnumSource(OcppTransport.class)
- public void testToProtocol(OcppTransport transport) {
- for (var version : OcppVersion.values()) {
- var protocol = version.toProtocol(transport);
-
- assertThat(protocol.getTransport()).isEqualTo(transport);
- assertThat(protocol.getVersion()).isEqualTo(version);
- }
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/ocpp/ws/OcppWebSocketHandshakeHandlerTest.java b/steve/src/test/java/de/rwth/idsg/steve/ocpp/ws/OcppWebSocketHandshakeHandlerTest.java
deleted file mode 100644
index d44252c2b..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/ocpp/ws/OcppWebSocketHandshakeHandlerTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve.ocpp.ws;
-
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class OcppWebSocketHandshakeHandlerTest {
-
- @Test
- public void testGetLastBitFromUrl_empty() {
- var in = "";
- var out = OcppWebSocketHandshakeHandler.getLastBitFromUrl(in);
- assertThat(out).isEmpty();
- }
-
- @Test
- public void testGetLastBitFromUrl_null() {
- String in = null;
- var out = OcppWebSocketHandshakeHandler.getLastBitFromUrl(in);
- assertThat(out).isEmpty();
- }
-
- @Test
- public void testGetLastBitFromUrl_successFull() {
- var in = "https://www.google.com/steve/websocket/CentralSystemService/BBEI12";
- var out = OcppWebSocketHandshakeHandler.getLastBitFromUrl(in);
- assertThat(out).isEqualTo("BBEI12");
- }
-
- @Test
- public void testGetLastBitFromUrl_noPostfix() {
- var in = "/steve/websocket/CentralSystemService/";
- var out = OcppWebSocketHandshakeHandler.getLastBitFromUrl(in);
- assertThat(out).isEmpty();
- }
-
- @Test
- public void testGetLastBitFromUrl_successPartial() {
- var in = "/steve/websocket/CentralSystemService/BBEI12";
- var out = OcppWebSocketHandshakeHandler.getLastBitFromUrl(in);
- assertThat(out).isEqualTo("BBEI12");
- }
-
- @Test
- public void testGetLastBitFromUrl_successWithPercent() {
- var in = "/steve/websocket/CentralSystemService/BBE%I12";
- var out = OcppWebSocketHandshakeHandler.getLastBitFromUrl(in);
- assertThat(out).isEqualTo("BBE%I12");
- }
-
- @Test
- public void testGetLastBitFromUrl_successWithDash() {
- var in = "/steve/websocket/CentralSystemService/BBE-I12";
- var out = OcppWebSocketHandshakeHandler.getLastBitFromUrl(in);
- assertThat(out).isEqualTo("BBE-I12");
- }
-
- @Test
- public void testGetLastBitFromUrl_successWithSpace() {
- var in = "/steve/websocket/CentralSystemService/BBE I12";
- var out = OcppWebSocketHandshakeHandler.getLastBitFromUrl(in);
- assertThat(out).isEqualTo("BBE I12");
- }
-
- @Test
- public void testGetLastBitFromUrl_successWithExtraSlash() {
- var in = "/steve/websocket/CentralSystemService/889/BBEI12";
- var out = OcppWebSocketHandshakeHandler.getLastBitFromUrl(in);
- assertThat(out).isEqualTo("889/BBEI12");
- }
-
- @Test
- public void testGetLastBitFromUrl_successComplex() {
- var in = "/steve/websocket/CentralSystemService/%889 /BBEI12-";
- var out = OcppWebSocketHandshakeHandler.getLastBitFromUrl(in);
- assertThat(out).isEqualTo("%889 /BBEI12-");
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/utils/Helpers.java b/steve/src/test/java/de/rwth/idsg/steve/utils/Helpers.java
deleted file mode 100644
index ea585c05c..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/utils/Helpers.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve.utils;
-
-import de.rwth.idsg.steve.SteveConfiguration;
-import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
-import org.apache.cxf.ws.addressing.WSAddressingFeature;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-import jakarta.xml.ws.soap.SOAPBinding;
-
-/**
- * @author Andreas Heuvels
- * @since 06.04.18
- */
-public class Helpers {
-
- public static String getRandomString() {
- return UUID.randomUUID().toString();
- }
-
- public static List getRandomStrings(int size) {
- List list = new ArrayList<>(size);
- for (int i = 0; i < size; i++) {
- list.add(getRandomString());
- }
- return list;
- }
-
- public static String getHttpPath(SteveConfiguration config) {
- String prefix;
- int port;
-
- if (config.getJetty().isHttpEnabled()) {
- prefix = "http://";
- port = config.getJetty().getHttpPort();
- } else if (config.getJetty().isHttpsEnabled()) {
- prefix = "https://";
- port = config.getJetty().getHttpsPort();
- } else {
- throw new RuntimeException();
- }
-
- return prefix + config.getJetty().getServerHost() + ":" + port
- + config.getPaths().getContextPath()
- + config.getPaths().getSoapMapping()
- + config.getPaths().getRouterEndpointPath();
- }
-
- public static String getWsPath(SteveConfiguration config) {
- String prefix;
- int port;
-
- if (config.getJetty().isHttpEnabled()) {
- prefix = "ws://";
- port = config.getJetty().getHttpPort();
- } else if (config.getJetty().isHttpsEnabled()) {
- prefix = "wss://";
- port = config.getJetty().getHttpsPort();
- } else {
- throw new RuntimeException();
- }
-
- return prefix + config.getJetty().getServerHost() + ":" + port
- + config.getPaths().getContextPath()
- + config.getPaths().getWebsocketMapping()
- + config.getPaths().getRouterEndpointPath() + "/";
- }
-
- public static ocpp.cs._2015._10.CentralSystemService getForOcpp16(String path) {
- JaxWsProxyFactoryBean f = getBean(path);
- f.setServiceClass(ocpp.cs._2015._10.CentralSystemService.class);
- return (ocpp.cs._2015._10.CentralSystemService) f.create();
- }
-
- public static ocpp.cs._2012._06.CentralSystemService getForOcpp15(String path) {
- JaxWsProxyFactoryBean f = getBean(path);
- f.setServiceClass(ocpp.cs._2012._06.CentralSystemService.class);
- return (ocpp.cs._2012._06.CentralSystemService) f.create();
- }
-
- public static ocpp.cs._2010._08.CentralSystemService getForOcpp12(String path) {
- JaxWsProxyFactoryBean f = getBean(path);
- f.setServiceClass(ocpp.cs._2010._08.CentralSystemService.class);
- return (ocpp.cs._2010._08.CentralSystemService) f.create();
- }
-
- private static JaxWsProxyFactoryBean getBean(String endpointAddress) {
- JaxWsProxyFactoryBean f = new JaxWsProxyFactoryBean();
- f.setBindingId(SOAPBinding.SOAP12HTTP_BINDING);
- f.getFeatures().add(new WSAddressingFeature());
- f.setAddress(endpointAddress);
- return f;
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/utils/OcppJsonChargePoint.java b/steve/src/test/java/de/rwth/idsg/steve/utils/OcppJsonChargePoint.java
deleted file mode 100644
index 7215cc0f1..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/utils/OcppJsonChargePoint.java
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve.utils;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.JsonNodeFactory;
-import com.fasterxml.jackson.databind.node.NullNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import de.rwth.idsg.ocpp.jaxb.RequestType;
-import de.rwth.idsg.ocpp.jaxb.ResponseType;
-import de.rwth.idsg.steve.ocpp.OcppVersion;
-import de.rwth.idsg.steve.ocpp.ws.data.CommunicationContext;
-import de.rwth.idsg.steve.ocpp.ws.data.ErrorCode;
-import de.rwth.idsg.steve.ocpp.ws.data.MessageType;
-import de.rwth.idsg.steve.ocpp.ws.data.OcppJsonCall;
-import de.rwth.idsg.steve.ocpp.ws.data.OcppJsonError;
-import de.rwth.idsg.steve.ocpp.ws.data.OcppJsonMessage;
-import de.rwth.idsg.steve.ocpp.ws.data.OcppJsonResponse;
-import de.rwth.idsg.steve.ocpp.ws.data.OcppJsonResult;
-import de.rwth.idsg.steve.ocpp.ws.pipeline.Serializer;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.StatusCode;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
-import org.eclipse.jetty.websocket.api.annotations.WebSocket;
-import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
-import org.eclipse.jetty.websocket.client.WebSocketClient;
-
-import java.io.IOException;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CountDownLatch;
-import java.util.function.Consumer;
-
-import static java.util.Collections.synchronizedMap;
-import static org.eclipse.jetty.websocket.api.Callback.NOOP;
-
-/**
- * @author Sevket Goekay
- * @since 21.03.2018
- */
-@Slf4j
-@WebSocket
-public class OcppJsonChargePoint {
-
- private final ObjectMapper ocppMapper;
- private final String version;
- private final String chargeBoxId;
- private final String connectionPath;
- private final Map responseContextMap;
- private final Map requestContextMap;
- private final MessageDeserializer deserializer;
- private final WebSocketClient client;
- private final CountDownLatch closeHappenedSignal;
- private final Serializer serializer;
-
- private final Thread testerThread;
- private RuntimeException testerThreadInterruptReason;
-
- private CountDownLatch receivedMessagesSignal;
- private Session session;
-
- public OcppJsonChargePoint(ObjectMapper ocppMapper, OcppVersion version, String chargeBoxId, String pathPrefix) {
- this(ocppMapper, version.getValue(), chargeBoxId, pathPrefix);
- }
-
- public OcppJsonChargePoint(ObjectMapper ocppMapper, String ocppVersion, String chargeBoxId, String pathPrefix) {
- this.ocppMapper = ocppMapper;
- this.version = ocppVersion;
- this.chargeBoxId = chargeBoxId;
- this.connectionPath = pathPrefix + chargeBoxId;
- this.responseContextMap =
- synchronizedMap(new LinkedHashMap<>()); // because we want to keep the insertion order of test cases
- this.requestContextMap = new ConcurrentHashMap<>();
- this.deserializer = new MessageDeserializer();
- this.client = new WebSocketClient();
- this.closeHappenedSignal = new CountDownLatch(1);
- this.testerThread = Thread.currentThread();
- this.serializer = new Serializer(ocppMapper);
- }
-
- @OnWebSocketOpen
- public void onConnect(Session session) {
- this.session = session;
- }
-
- @OnWebSocketClose
- public void onClose(Session session, int statusCode, String reason) {
- this.session = null;
- this.closeHappenedSignal.countDown();
- }
-
- @OnWebSocketError
- public void onError(Session session, Throwable throwable) {
- log.error("Exception", throwable);
- }
-
- @OnWebSocketMessage
- public void onMessage(Session session, String msg) {
- try {
- var ocppMsg = deserializer.extract(msg);
- switch (ocppMsg) {
- case OcppJsonResult result -> {
- var ctx = responseContextMap.remove(result.getMessageId());
- ctx.responseHandler.accept(result.getPayload());
- }
- case OcppJsonError error -> {
- var ctx = responseContextMap.remove(error.getMessageId());
- ctx.errorHandler.accept(error);
- }
- case OcppJsonCall call -> {
- handleCall(call);
- }
- default -> throw new IllegalStateException("Unexpected value: " + ocppMsg);
- }
- } catch (Exception e) {
- log.error("Exception", e);
- } finally {
- if (receivedMessagesSignal != null) {
- receivedMessagesSignal.countDown();
- }
- }
- }
-
- public void start() {
- try {
- var request = new ClientUpgradeRequest();
- if (version != null) {
- request.setSubProtocols(version);
- }
-
- client.start();
-
- var connect = client.connect(this, new URI(connectionPath), request);
- connect.get(); // block until session is created
- } catch (Throwable t) {
- throw new RuntimeException(t);
- }
- }
-
- public void prepare(
- RequestType request,
- Class responseClass,
- Consumer responseHandler,
- Consumer errorHandler) {
- prepare(request, getOperationName(request), responseClass, responseHandler, errorHandler);
- }
-
- public void prepare(
- RequestType payload,
- String action,
- Class responseClass,
- Consumer responseHandler,
- Consumer errorHandler) {
- var messageId = UUID.randomUUID().toString();
-
- var call = new OcppJsonCall();
- call.setMessageId(messageId);
- call.setPayload(payload);
- call.setAction(action);
-
- // session is null, because we do not need org.springframework.web.socket.WebSocketSession
- var ctx = new CommunicationContext(null, chargeBoxId);
- ctx.setOutgoingMessage(call);
-
- serializer.accept(ctx);
-
- var resCtx = new ResponseContext(ctx.getOutgoingString(), responseClass, responseHandler, errorHandler);
- responseContextMap.put(messageId, resCtx);
- }
-
- public void process() {
- var requestCount = requestContextMap.size();
- var responseCount = responseContextMap.size();
- receivedMessagesSignal = new CountDownLatch(requestCount + responseCount);
-
- // copy the values in a new list to be iterated over, because otherwise we get a
- // ConcurrentModificationException,
- // since the onMessage(..) uses the same responseContextMap to remove an item while looping over its items here.
- var values = new ArrayList<>(responseContextMap.values());
-
- // send all messages
- for (var ctx : values) {
- try {
- session.sendText(ctx.outgoingMessage, NOOP);
- } catch (Exception e) {
- log.error("Exception", e);
- }
- }
-
- // wait for all responses to arrive and be processed
- try {
- receivedMessagesSignal.await();
- } catch (InterruptedException e) {
- if (testerThreadInterruptReason != null) {
- throw testerThreadInterruptReason;
- }
- throw new RuntimeException(e);
- }
- }
-
- public void close() {
- try {
- // "enqueue" a graceful close
- session.close(StatusCode.NORMAL, "Finished", NOOP);
-
- // wait for close to happen
- closeHappenedSignal.await();
-
- // well, stop the client
- client.stop();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- public void processAndClose() {
- process();
- close();
- }
-
- // -------------------------------------------------------------------------
- // Private helpers
- // -------------------------------------------------------------------------
-
- private static String getOperationName(RequestType requestType) {
- var s = requestType.getClass().getSimpleName();
- if (s.endsWith("Request")) {
- s = s.substring(0, s.length() - 7);
- }
- return s;
- }
-
- private void handleCall(OcppJsonCall call) {
- JsonNode responsePayload = null; // TODO
- try {
- var node = ocppMapper
- .createArrayNode()
- .add(MessageType.CALL_RESULT.getTypeNr())
- .add(call.getMessageId())
- .add(responsePayload);
-
- var str = ocppMapper.writeValueAsString(node);
- session.sendText(str, NOOP);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- private static class ResponseContext {
- private final String outgoingMessage;
- private final Class responseClass;
- private final Consumer responseHandler;
- private final Consumer errorHandler;
-
- @SuppressWarnings("unchecked")
- private ResponseContext(
- String outgoingMessage,
- Class responseClass,
- Consumer responseHandler,
- Consumer errorHandler) {
- this.outgoingMessage = outgoingMessage;
- this.responseClass = (Class) responseClass;
- this.responseHandler = (Consumer) responseHandler;
- this.errorHandler = errorHandler;
- }
- }
-
- private class MessageDeserializer {
-
- private OcppJsonMessage extract(String msg) throws Exception {
-
- try (var parser = ocppMapper.getFactory().createParser(msg)) {
- parser.nextToken(); // set cursor to '['
-
- parser.nextToken();
- var messageTypeNr = parser.getIntValue();
-
- parser.nextToken();
- var messageId = parser.getText();
-
- var messageType = MessageType.fromTypeNr(messageTypeNr);
- return switch (messageType) {
- case CALL_RESULT -> handleResult(messageId, parser);
- case CALL_ERROR -> handleError(messageId, parser);
- case CALL -> handleCall(messageId, parser);
- };
- }
- }
-
- private OcppJsonResponse handleResult(String messageId, JsonParser parser) throws Exception {
- parser.nextToken();
- var responsePayload = parser.readValueAsTree();
- var clazz = responseContextMap.get(messageId).responseClass;
- var res = ocppMapper.treeToValue(responsePayload, clazz);
-
- var result = new OcppJsonResult();
- result.setMessageId(messageId);
- result.setPayload(res);
- return result;
- }
-
- private OcppJsonResponse handleError(String messageId, JsonParser parser) throws Exception {
- parser.nextToken();
- var code = ErrorCode.fromValue(parser.getText());
-
- parser.nextToken();
- var desc = parser.getText();
- if ("".equals(desc)) {
- desc = null;
- }
-
- String details = null;
- parser.nextToken();
- var detailsNode = parser.readValueAsTree();
- if (detailsNode != null && detailsNode.size() != 0) {
- details = ocppMapper.writeValueAsString(detailsNode);
- }
-
- var error = new OcppJsonError();
- error.setMessageId(messageId);
- error.setErrorCode(code);
- error.setErrorDescription(desc);
- error.setErrorDetails(details);
- return error;
- }
-
- private OcppJsonCall handleCall(String messageId, JsonParser parser) {
- // parse action
- String action;
- try {
- parser.nextToken();
- action = parser.getText();
- } catch (IOException e) {
- throw new RuntimeException();
- }
-
- // parse request payload
- String req;
- try {
- parser.nextToken();
- JsonNode requestPayload = parser.readValueAsTree();
-
- // https://github.com/steve-community/steve/issues/1109
- if (requestPayload instanceof NullNode) {
- requestPayload = new ObjectNode(JsonNodeFactory.instance);
- }
-
- req = requestPayload.toString();
- } catch (IOException e) {
- log.error("Exception occurred", e);
- throw new RuntimeException();
- }
-
- var request = requestContextMap.get(action);
- if (request == null) {
- testerThreadInterruptReason = new RuntimeException("Unexpected message arrived: " + req);
- testerThread.interrupt();
- } else if (Objects.equals(request.toString(), req)) { // FIXME
- requestContextMap.remove(action);
- }
-
- var call = new OcppJsonCall();
- call.setAction(action);
- call.setMessageId(messageId);
- call.setPayload(request);
- return call;
- }
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/utils/StressTester.java b/steve/src/test/java/de/rwth/idsg/steve/utils/StressTester.java
deleted file mode 100644
index f6e7c9f21..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/utils/StressTester.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve.utils;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-/**
- * @author Sevket Goekay
- * @since 18.04.2018
- */
-public class StressTester {
-
- private final int threadCount;
- private final int perThreadRepeatCount;
- private final ExecutorService executorService;
-
- public StressTester(int threadCount, int perThreadRepeatCount) {
- this.threadCount = threadCount;
- this.perThreadRepeatCount = perThreadRepeatCount;
- this.executorService = Executors.newCachedThreadPool();
- }
-
- public void test(StressTester.Runnable runnable) throws InterruptedException {
- final CountDownLatch doneSignal = new CountDownLatch(threadCount);
-
- for (int i = 0; i < threadCount; i++) {
- executorService.execute(() -> {
- try {
- runnable.beforeRepeat();
- for (int j = 0; j < perThreadRepeatCount; j++) {
- runnable.toRepeat();
- }
- runnable.afterRepeat();
- } finally {
- doneSignal.countDown();
- }
- });
- }
-
- doneSignal.await();
- }
-
- public void shutDown() {
- executorService.shutdown();
- }
-
- public interface Runnable {
- void beforeRepeat();
-
- void toRepeat();
-
- void afterRepeat();
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/utils/StringUtilsTest.java b/steve/src/test/java/de/rwth/idsg/steve/utils/StringUtilsTest.java
deleted file mode 100644
index 6d0847b39..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/utils/StringUtilsTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve.utils;
-
-import de.rwth.idsg.steve.ocpp.task.CancelReservationTask;
-import de.rwth.idsg.steve.ocpp.task.ClearCacheTask;
-import de.rwth.idsg.steve.ocpp.task.GetCompositeScheduleTask;
-import de.rwth.idsg.steve.web.dto.ocpp.CancelReservationParams;
-import de.rwth.idsg.steve.web.dto.ocpp.GetCompositeScheduleParams;
-import de.rwth.idsg.steve.web.dto.ocpp.MultipleChargePointSelect;
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-/**
- * @author Sevket Goekay
- * @since 05.10.2021
- */
-public class StringUtilsTest {
-
- @Test
- public void testOperationName_ocpp12andMultiple() {
- var operationName = StringUtils.getOperationName(new ClearCacheTask(new MultipleChargePointSelect()));
- assertThat(operationName).isEqualTo("Clear Cache");
- }
-
- @Test
- public void testOperationName_ocpp15andSingle() {
- var operationName =
- StringUtils.getOperationName(new CancelReservationTask(new CancelReservationParams(), null));
- assertThat(operationName).isEqualTo("Cancel Reservation");
- }
-
- @Test
- public void testOperationName_ocpp16() {
- var operationName =
- StringUtils.getOperationName(new GetCompositeScheduleTask(new GetCompositeScheduleParams()));
- assertThat(operationName).isEqualTo("Get Composite Schedule");
- }
-
- @Test
- public void testJoinByComma_inputNull() {
- var val = StringUtils.joinByComma(null);
- assertThat(val).isNull();
- }
-
- @Test
- public void testJoinByComma_inputEmpty() {
- var val = StringUtils.joinByComma(List.of());
- assertThat(val).isNull();
- }
-
- @Test
- public void testJoinByComma_inputOneElement() {
- var val = StringUtils.joinByComma(List.of("hey"));
- assertThat(val).isEqualTo("hey");
- }
-
- @Test
- public void testJoinByComma_inputTwoElements() {
- var val = StringUtils.joinByComma(List.of("hey", "ho"));
- assertThat(val).isEqualTo("hey,ho");
- }
-
- @Test
- public void testJoinByComma_inputDuplicateElements() {
- var val = StringUtils.joinByComma(List.of("hey", "ho", "hey"));
- assertThat(val).isEqualTo("hey,ho");
- }
-
- @Test
- public void testSplitByComma_inputNull() {
- var val = StringUtils.splitByComma(null);
- assertThat(val).isNotNull().isEmpty();
- }
-
- @Test
- public void testSplitByComma_inputEmpty() {
- var val = StringUtils.splitByComma("");
- assertThat(val).isNotNull().isEmpty();
- }
-
- @Test
- public void testSplitByComma_inputOneElement() {
- var val = StringUtils.splitByComma("1one");
- assertThat(val).hasSize(1);
- assertThat(val.get(0)).isEqualTo("1one");
- }
-
- @Test
- public void testSplitByComma_inputTwoElements() {
- var val = StringUtils.splitByComma("1one,2two");
- assertThat(val).hasSize(2);
-
- var sortedVal = val.stream().sorted().toList();
- assertThat(sortedVal).containsExactly("1one", "2two");
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/utils/TransactionStopServiceHelperTest.java b/steve/src/test/java/de/rwth/idsg/steve/utils/TransactionStopServiceHelperTest.java
deleted file mode 100644
index 64664d99a..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/utils/TransactionStopServiceHelperTest.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve.utils;
-
-import de.rwth.idsg.steve.repository.dto.TransactionDetails;
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class TransactionStopServiceHelperTest {
-
- @Test
- public void testFloatingStringToIntString() {
- var actual = TransactionStopServiceHelper.floatingStringToIntString("11.01");
-
- assertThat(actual).isEqualTo("12");
- }
-
- @Test
- public void testFloatingStringToIntString2() {
- var actual = TransactionStopServiceHelper.floatingStringToIntString("234.678");
-
- assertThat(actual).isEqualTo("235");
- }
-
- @Test
- public void testKWhStringToWhString() {
- var actual = TransactionStopServiceHelper.kWhStringToWhString("12");
-
- assertThat(actual).isEqualTo("12000.0");
- }
-
- @Test
- public void testIsEnergy_empty() {
- var value = TransactionDetails.MeterValues.builder().build();
-
- assertThat(TransactionStopServiceHelper.isEnergyValue(value)).isFalse();
- }
-
- @Test
- public void testIsEnergy_onlyValue() {
- var value = TransactionDetails.MeterValues.builder().value("22").build();
-
- assertThat(TransactionStopServiceHelper.isEnergyValue(value)).isTrue();
- }
-
- @Test
- public void testIsEnergy_onlyValueDecimal() {
- var value = TransactionDetails.MeterValues.builder().value("22.5").build();
-
- assertThat(TransactionStopServiceHelper.isEnergyValue(value)).isTrue();
- }
-
- @Test
- public void testIsEnergy_signedData() {
- var value = TransactionDetails.MeterValues.builder()
- .value("some gibberish that is not an energy value")
- .format("SignedData")
- .build();
-
- assertThat(TransactionStopServiceHelper.isEnergyValue(value)).isFalse();
- }
-
- @Test
- public void testIsEnergy_notEnergyUnit() {
- var value = TransactionDetails.MeterValues.builder()
- .value("22")
- .format("Raw")
- .unit("Celsius")
- .build();
-
- assertThat(TransactionStopServiceHelper.isEnergyValue(value)).isFalse();
- }
-
- @Test
- public void testIsEnergy_notActiveImportMeasurand() {
- var value = TransactionDetails.MeterValues.builder()
- .value("22")
- .format("Raw")
- .unit("Wh")
- .measurand("Current.Export")
- .build();
-
- assertThat(TransactionStopServiceHelper.isEnergyValue(value)).isFalse();
- }
-
- @Test
- public void testIsEnergy_nullFormat() {
- var value = TransactionDetails.MeterValues.builder()
- .value("22")
- .format(null)
- .unit("Wh")
- .measurand("Energy.Active.Import.Register")
- .build();
-
- assertThat(TransactionStopServiceHelper.isEnergyValue(value)).isTrue();
- }
-
- @Test
- public void testIsEnergy_rawFormat() {
- var value = TransactionDetails.MeterValues.builder()
- .value("22")
- .format("Raw")
- .unit("Wh")
- .measurand("Energy.Active.Import.Register")
- .build();
-
- assertThat(TransactionStopServiceHelper.isEnergyValue(value)).isTrue();
- }
-
- @Test
- public void testIsEnergy_kWhUnit() {
- var value = TransactionDetails.MeterValues.builder()
- .value("22")
- .format("Raw")
- .unit("kWh")
- .measurand("Energy.Active.Import.Register")
- .build();
-
- assertThat(TransactionStopServiceHelper.isEnergyValue(value)).isTrue();
- }
-
- @Test
- public void testIsEnergy_nonNumericValue() {
- var value = TransactionDetails.MeterValues.builder()
- .value("22a819()b")
- .format("Raw")
- .unit("Wh")
- .measurand("Energy.Active.Import.Register")
- .build();
-
- assertThat(TransactionStopServiceHelper.isEnergyValue(value)).isFalse();
- }
-
- @Test
- public void testIsEnergy_valueAndUnit() {
- var value =
- TransactionDetails.MeterValues.builder().value("22").unit("Wh").build();
-
- assertThat(TransactionStopServiceHelper.isEnergyValue(value)).isTrue();
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/utils/__DatabasePreparer__.java b/steve/src/test/java/de/rwth/idsg/steve/utils/__DatabasePreparer__.java
deleted file mode 100644
index b282766de..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/utils/__DatabasePreparer__.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve.utils;
-
-import com.google.common.collect.Sets;
-import de.rwth.idsg.steve.SteveConfiguration;
-import de.rwth.idsg.steve.jooq.config.JooqConfiguration;
-import de.rwth.idsg.steve.repository.dto.ChargePoint;
-import de.rwth.idsg.steve.repository.dto.ConnectorStatus;
-import de.rwth.idsg.steve.repository.dto.InsertReservationParams;
-import de.rwth.idsg.steve.repository.dto.Reservation;
-import de.rwth.idsg.steve.repository.dto.Transaction;
-import de.rwth.idsg.steve.repository.dto.TransactionDetails;
-import de.rwth.idsg.steve.repository.impl.AddressRepositoryImpl;
-import de.rwth.idsg.steve.repository.impl.ChargePointRepositoryImpl;
-import de.rwth.idsg.steve.repository.impl.OcppTagRepositoryImpl;
-import de.rwth.idsg.steve.repository.impl.ReservationRepositoryImpl;
-import de.rwth.idsg.steve.repository.impl.TransactionRepositoryImpl;
-import de.rwth.idsg.steve.web.dto.ReservationQueryForm;
-import de.rwth.idsg.steve.web.dto.TransactionQueryForm;
-import jooq.steve.db.DefaultCatalog;
-import jooq.steve.db.tables.OcppTagActivity;
-import jooq.steve.db.tables.SchemaVersion;
-import jooq.steve.db.tables.Settings;
-import jooq.steve.db.tables.records.OcppTagActivityRecord;
-import jooq.steve.db.tables.records.TransactionRecord;
-import org.jooq.DSLContext;
-import org.jooq.impl.DSL;
-
-import java.time.Instant;
-import java.time.temporal.ChronoUnit;
-import java.util.Collections;
-import java.util.List;
-import java.util.function.Consumer;
-
-import static de.rwth.idsg.steve.utils.DateTimeUtils.toLocalDateTime;
-import static jooq.steve.db.tables.ChargeBox.CHARGE_BOX;
-import static jooq.steve.db.tables.OcppTag.OCPP_TAG;
-import static jooq.steve.db.tables.Transaction.TRANSACTION;
-
-/**
- * This is a dangerous class. It performs database operations no class should do, like truncating all tables and
- * inserting data while bypassing normal mechanisms of SteVe. However, for integration testing with reproducible
- * results we need a clean and isolated database.
- *
- * @author Sevket Goekay
- * @since 21.03.2018
- */
-public class __DatabasePreparer__ {
-
- private static final String SCHEMA_TO_TRUNCATE = "stevedb_test_2aa6a783d47d";
- private static final String REGISTERED_CHARGE_BOX_ID = "charge_box_2aa6a783d47d";
- private static final String REGISTERED_CHARGE_BOX_ID_2 = "charge_box_2aa6a783d47d_2";
- private static final String REGISTERED_OCPP_TAG = "id_tag_2aa6a783d47d";
-
- private static final JooqConfiguration jooqConfiguration = new JooqConfiguration();
-
- private static DSLContext dslContext;
-
- public static void prepare(SteveConfiguration config) {
- dslContext = jooqConfiguration.dslContext(
- JooqConfiguration.dataSource(
- config.getDb().getJdbcUrl(),
- config.getDb().getUserName(),
- config.getDb().getPassword(),
- config.getTimeZoneId()),
- config);
- runOperation(ctx -> {
- truncateTables(ctx);
- insertChargeBox(ctx);
- insertOcppIdTag(ctx);
- });
- }
-
- public static int makeReservation(int connectorId) {
- var r = new ReservationRepositoryImpl(dslContext);
- var params = InsertReservationParams.builder()
- .chargeBoxId(REGISTERED_CHARGE_BOX_ID)
- .idTag(REGISTERED_OCPP_TAG)
- .connectorId(connectorId)
- .expiryTimestamp(Instant.now().plus(1, ChronoUnit.HOURS))
- .build();
- var reservationId = r.insert(params);
- r.accepted(reservationId);
- return reservationId;
- }
-
- public static void cleanUp() {
- runOperation(__DatabasePreparer__::truncateTables);
- }
-
- public static String getRegisteredChargeBoxId() {
- return REGISTERED_CHARGE_BOX_ID;
- }
-
- public static String getRegisteredChargeBoxId2() {
- return REGISTERED_CHARGE_BOX_ID_2;
- }
-
- public static String getRegisteredOcppTag() {
- return REGISTERED_OCPP_TAG;
- }
-
- public static List getTransactions() {
- var impl = new TransactionRepositoryImpl(dslContext);
- return impl.getTransactions(new TransactionQueryForm());
- }
-
- public static List getTransactionRecords() {
- return dslContext.selectFrom(TRANSACTION).fetch();
- }
-
- public static List getReservations() {
- var impl = new ReservationRepositoryImpl(dslContext);
- return impl.getReservations(new ReservationQueryForm());
- }
-
- public static List getChargePointConnectorStatus() {
- var impl = new ChargePointRepositoryImpl(dslContext, new AddressRepositoryImpl(dslContext));
- return impl.getChargePointConnectorStatus();
- }
-
- public static TransactionDetails getDetails(int transactionPk) {
- var impl = new TransactionRepositoryImpl(dslContext);
- return impl.getDetails(transactionPk).orElseThrow();
- }
-
- public static OcppTagActivityRecord getOcppTagRecord(String idTag) {
- var impl = new OcppTagRepositoryImpl(dslContext);
- var dto = impl.getRecord(idTag).orElseThrow();
- var activity = new OcppTagActivityRecord();
- activity.setOcppTagPk(dto.getOcppTagPk());
- activity.setIdTag(dto.getIdTag());
- activity.setParentIdTag(dto.getParentIdTag());
- activity.setExpiryDate(toLocalDateTime(dto.getExpiryDate()));
- activity.setInTransaction(dto.isInTransaction());
- activity.setBlocked(dto.isBlocked());
- activity.setMaxActiveTransactionCount(dto.getMaxActiveTransactionCount());
- activity.setActiveTransactionCount(dto.getActiveTransactionCount());
- activity.setNote(dto.getNote());
- return activity;
- }
-
- public static ChargePoint.Details getCBDetails(String chargeboxID) {
- var impl = new ChargePointRepositoryImpl(dslContext, new AddressRepositoryImpl(dslContext));
- var pkMap = impl.getChargeBoxIdPkPair(Collections.singletonList(chargeboxID));
- int pk = pkMap.get(chargeboxID);
- return impl.getDetails(pk).orElseThrow();
- }
-
- private static void runOperation(Consumer consumer) {
- consumer.accept(dslContext);
- }
-
- private static void truncateTables(DSLContext ctx) {
- var skipList = Sets.newHashSet(
- SchemaVersion.SCHEMA_VERSION,
- Settings.SETTINGS,
- OcppTagActivity.OCPP_TAG_ACTIVITY, // only a view
- TRANSACTION // only a view
- );
-
- ctx.transaction(configuration -> {
- var schema = DefaultCatalog.DEFAULT_CATALOG.getSchemas().stream()
- .filter(s -> SCHEMA_TO_TRUNCATE.equals(s.getName()))
- .findFirst()
- .orElseThrow(() -> new RuntimeException("Could not find schema"));
-
- var tables = schema.getTables().stream()
- .filter(t -> !skipList.contains(t))
- .toList();
-
- if (tables.isEmpty()) {
- throw new RuntimeException("Could not find tables to truncate");
- }
-
- var internalCtx = DSL.using(configuration);
- internalCtx.execute("SET FOREIGN_KEY_CHECKS=0");
- tables.forEach(t -> internalCtx.truncate(t).execute());
- internalCtx.execute("SET FOREIGN_KEY_CHECKS=1");
- });
- }
-
- private static void insertChargeBox(DSLContext ctx) {
- ctx.insertInto(CHARGE_BOX)
- .set(CHARGE_BOX.CHARGE_BOX_ID, getRegisteredChargeBoxId())
- .execute();
-
- ctx.insertInto(CHARGE_BOX)
- .set(CHARGE_BOX.CHARGE_BOX_ID, getRegisteredChargeBoxId2())
- .execute();
- }
-
- private static void insertOcppIdTag(DSLContext ctx) {
- ctx.insertInto(OCPP_TAG).set(OCPP_TAG.ID_TAG, getRegisteredOcppTag()).execute();
- }
-}
diff --git a/steve/src/test/java/de/rwth/idsg/steve/web/validation/ChargeBoxIdValidatorTest.java b/steve/src/test/java/de/rwth/idsg/steve/web/validation/ChargeBoxIdValidatorTest.java
deleted file mode 100644
index 3bce941d4..000000000
--- a/steve/src/test/java/de/rwth/idsg/steve/web/validation/ChargeBoxIdValidatorTest.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
- * Copyright (C) 2013-2025 SteVe Community Team
- * All Rights Reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License
- * along with this program. If not, see .
- */
-package de.rwth.idsg.steve.web.validation;
-
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-/**
- * @author Sevket Goekay
- * @since 01.08.2024
- */
-public class ChargeBoxIdValidatorTest {
-
- private final ChargeBoxIdValidator validator = new ChargeBoxIdValidator();
-
- @Test
- public void testNull() {
- assertThat(validator.isValid(null)).isFalse();
- }
-
- @Test
- public void testEmpty() {
- assertThat(validator.isValid("")).isFalse();
- }
-
- @Test
- public void testSpace() {
- assertThat(validator.isValid(" ")).isFalse();
- }
-
- @Test
- public void testAllLowercaseLetters() {
- assertThat(validator.isValid("test")).isTrue();
- }
-
- @Test
- public void testAllUppercaseLetters() {
- assertThat(validator.isValid("TEST")).isTrue();
- }
-
- @Test
- public void testMixedCaseLetters() {
- assertThat(validator.isValid("TesT")).isTrue();
- assertThat(validator.isValid("tEst")).isTrue();
- }
-
- @Test
- public void testLettersAndNumbers() {
- assertThat(validator.isValid("test12")).isTrue();
- assertThat(validator.isValid("89test")).isTrue();
- assertThat(validator.isValid("te9s0t")).isTrue();
- }
-
- @Test
- public void testDot() {
- assertThat(validator.isValid(".test")).isTrue();
- assertThat(validator.isValid("test.")).isTrue();
- assertThat(validator.isValid("te..st")).isTrue();
- }
-
- @Test
- public void testDash() {
- assertThat(validator.isValid("-test")).isTrue();
- assertThat(validator.isValid("test-")).isTrue();
- assertThat(validator.isValid("te--st")).isTrue();
- }
-
- @Test
- public void testUnderscore() {
- assertThat(validator.isValid("_test")).isTrue();
- assertThat(validator.isValid("test_")).isTrue();
- assertThat(validator.isValid("te__st")).isTrue();
- }
-
- @Test
- public void testColon() {
- assertThat(validator.isValid(":test")).isTrue();
- assertThat(validator.isValid("test:")).isTrue();
- assertThat(validator.isValid("te::st")).isTrue();
- assertThat(validator.isValid("VID:00XXXXXXXXXX")).isTrue();
- }
-
- @Test
- public void testPoundSign() {
- assertThat(validator.isValid("#test")).isTrue();
- assertThat(validator.isValid("test#")).isTrue();
- assertThat(validator.isValid("te##st")).isTrue();
- assertThat(validator.isValid("#FreeCharging")).isTrue();
- }
-
- @Test
- public void testCombined() {
- assertThat(validator.isValid("1t.E-S_:t20#")).isTrue();
- }
-
- @Test
- public void testSpaceAtBeginning() {
- assertThat(validator.isValid(" test")).isFalse();
- }
-
- @Test
- public void testSpaceAtEnd() {
- assertThat(validator.isValid("test ")).isFalse();
- }
-
- @Test
- public void testSpaceInMiddle() {
- assertThat(validator.isValid("test1 test2")).isTrue();
- }
-
- @Test
- public void testOpeningParenthesis() {
- assertThat(validator.isValid("te(st")).isFalse();
- }
-
- @Test
- public void testClosingParenthesis() {
- assertThat(validator.isValid("te)st")).isFalse();
- }
-
- @Test
- public void testBiggerSymbol() {
- assertThat(validator.isValid("te>st")).isFalse();
- }
-
- @Test
- public void testSmallerSymbol() {
- assertThat(validator.isValid("te.
- */
-package de.rwth.idsg.steve.web.validation;
-
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-/**
- * @author Sevket Goekay
- * @since 22.03.2021
- */
-public class IdTagValidatorTest {
-
- private final IdTagValidator validator = new IdTagValidator();
-
- @Test
- public void testNull() {
- assertThat(validator.isValid(null, null)).isTrue();
- }
-
- @Test
- public void testAllLowercaseLetters() {
- assertThat(validator.isValid("test", null)).isTrue();
- }
-
- @Test
- public void testAllUppercaseLetters() {
- assertThat(validator.isValid("TEST", null)).isTrue();
- }
-
- @Test
- public void testMixedCaseLetters() {
- assertThat(validator.isValid("TesT", null)).isTrue();
- assertThat(validator.isValid("tEst", null)).isTrue();
- }
-
- @Test
- public void testLettersAndNumbers() {
- assertThat(validator.isValid("test12", null)).isTrue();
- assertThat(validator.isValid("89test", null)).isTrue();
- assertThat(validator.isValid("te9s0t", null)).isTrue();
- }
-
- @Test
- public void testDot() {
- assertThat(validator.isValid(".test", null)).isTrue();
- assertThat(validator.isValid("test.", null)).isTrue();
- assertThat(validator.isValid("te..st", null)).isTrue();
- }
-
- @Test
- public void testDash() {
- assertThat(validator.isValid("-test", null)).isTrue();
- assertThat(validator.isValid("test-", null)).isTrue();
- assertThat(validator.isValid("te--st", null)).isTrue();
- }
-
- @Test
- public void testUnderscore() {
- assertThat(validator.isValid("_test", null)).isTrue();
- assertThat(validator.isValid("test_", null)).isTrue();
- assertThat(validator.isValid("te__st", null)).isTrue();
- }
-
- /**
- * https://github.com/steve-community/steve/issues/475
- */
- @Test
- public void testColon() {
- assertThat(validator.isValid(":test", null)).isTrue();
- assertThat(validator.isValid("test:", null)).isTrue();
- assertThat(validator.isValid("te::st", null)).isTrue();
-
- assertThat(validator.isValid("VID:00XXXXXXXXXX", null)).isTrue();
- }
-
- @Test
- public void testPoundSign() {
- assertThat(validator.isValid("#test", null)).isTrue();
- assertThat(validator.isValid("test#", null)).isTrue();
- assertThat(validator.isValid("te##st", null)).isTrue();
-
- // Tag provided by Webasto charge points
- // https://github.com/steve-community/steve/pull/1322
- assertThat(validator.isValid("#FreeCharging", null)).isTrue();
- }
-
- @Test
- public void testCombined() {
- assertThat(validator.isValid("1t.E-S_:t20#", null)).isTrue();
- }
-}