Skip to content

Commit b753424

Browse files
committed
Merge branch steve-community/steve 'master' into feature/ocpp16-security
# Conflicts: # src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_Service.java # src/test/java/de/rwth/idsg/steve/utils/__DatabasePreparer__.java
2 parents 81ba853 + dea4bbd commit b753424

File tree

63 files changed

+1229
-772
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1229
-772
lines changed

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<parent>
1010
<groupId>org.springframework.boot</groupId>
1111
<artifactId>spring-boot-starter-parent</artifactId>
12-
<version>3.5.6</version>
12+
<version>3.5.7</version>
1313
<relativePath/> <!-- lookup parent from repository -->
1414
</parent>
1515

@@ -170,7 +170,7 @@
170170
<plugin>
171171
<groupId>com.github.spotbugs</groupId>
172172
<artifactId>spotbugs-maven-plugin</artifactId>
173-
<version>4.9.4.2</version>
173+
<version>4.9.8.1</version>
174174
<configuration>
175175
<failOnError>false</failOnError>
176176
<onlyAnalyze>de.rwth.idsg.steve.-</onlyAnalyze>

src/main/java/de/rwth/idsg/steve/NotificationFeature.java

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@
2121
import lombok.Getter;
2222
import lombok.RequiredArgsConstructor;
2323

24+
import java.util.Arrays;
25+
import java.util.List;
26+
import java.util.stream.Collectors;
27+
28+
import static de.rwth.idsg.steve.utils.StringUtils.joinByComma;
29+
import static de.rwth.idsg.steve.utils.StringUtils.splitByComma;
30+
2431
/**
2532
* @author Sevket Goekay <[email protected]>
2633
* @since 22.01.2016
@@ -30,17 +37,31 @@ public enum NotificationFeature {
3037

3138
// Ocpp related
3239
//
33-
OcppStationBooted(" a charging station sends a boot notification (Note: This activates notifications about failed connection attempts for unregistered JSON stations, as well)"),
34-
OcppStationStatusFailure(" a connector gets faulted"),
35-
OcppStationWebSocketConnected(" a JSON charging station connects"),
36-
OcppStationWebSocketDisconnected(" a JSON charging station disconnects"),
37-
OcppTransactionStarted(" a charging station starts a transaction"),
38-
OcppTransactionEnded(" a charging station ends a transaction");
40+
OcppStationBooted(false, " a charging station sends a boot notification (Note: This activates notifications about failed connection attempts for unregistered JSON stations, as well)"),
41+
OcppStationStatusFailure(true, " a connector gets faulted"),
42+
OcppStationWebSocketConnected(false, " a JSON charging station connects"),
43+
OcppStationWebSocketDisconnected(false, " a JSON charging station disconnects"),
44+
OcppTransactionStarted(true, " a charging station starts a transaction"),
45+
OcppStationStatusSuspendedEV(true, " a EV suspended charging"),
46+
OcppTransactionEnded(true, " a charging station ends a transaction");
3947

48+
private static final List<NotificationFeature> userNotificationFeatures = Arrays.stream(NotificationFeature.values())
49+
.filter(NotificationFeature::isForUser)
50+
.collect(Collectors.toList());
51+
52+
/**
53+
* Whether this notification type is intended for end-users as well.
54+
*/
55+
@Getter
56+
private final boolean forUser;
4057

4158
@Getter
4259
private final String text;
4360

61+
public static List<NotificationFeature> getUserValues() {
62+
return userNotificationFeatures;
63+
}
64+
4465
public static NotificationFeature fromName(String v) {
4566
for (NotificationFeature c: NotificationFeature.values()) {
4667
if (c.name().equalsIgnoreCase(v)) {
@@ -49,4 +70,14 @@ public static NotificationFeature fromName(String v) {
4970
}
5071
throw new IllegalArgumentException(v);
5172
}
73+
74+
public static List<NotificationFeature> splitFeatures(String str) {
75+
return splitByComma(str).stream()
76+
.map(NotificationFeature::fromName)
77+
.collect(Collectors.toList());
78+
}
79+
80+
public static String joinFeatures(List<NotificationFeature> enablesFeatures) {
81+
return joinByComma(enablesFeatures);
82+
}
5283
}

src/main/java/de/rwth/idsg/steve/config/BeanConfiguration.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.springframework.format.support.FormattingConversionService;
4444
import org.springframework.http.converter.HttpMessageConverter;
4545
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
46+
import org.springframework.scheduling.annotation.EnableAsync;
4647
import org.springframework.scheduling.annotation.EnableScheduling;
4748
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
4849
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@@ -67,6 +68,7 @@
6768
@Configuration
6869
@EnableWebMvc
6970
@EnableScheduling
71+
@EnableAsync
7072
@ComponentScan("de.rwth.idsg.steve")
7173
public class BeanConfiguration implements WebMvcConfigurer {
7274

@@ -130,28 +132,29 @@ public DSLContext dslContext(DataSource dataSource,
130132
return DSL.using(conf);
131133
}
132134

133-
@Bean(destroyMethod = "close")
134-
public DelegatingTaskScheduler asyncTaskScheduler() {
135+
@Bean
136+
public ThreadPoolTaskScheduler taskScheduler() {
135137
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
136138
scheduler.setPoolSize(5);
137139
scheduler.setThreadNamePrefix("SteVe-TaskScheduler-");
138140
scheduler.setWaitForTasksToCompleteOnShutdown(true);
139141
scheduler.setAwaitTerminationSeconds(30);
140142
scheduler.initialize();
141143

142-
return new DelegatingTaskScheduler(scheduler);
144+
return scheduler;
143145
}
144146

145-
@Bean(destroyMethod = "close")
146-
public DelegatingTaskExecutor asyncTaskExecutor() {
147+
@Bean
148+
@Primary
149+
public ThreadPoolTaskExecutor taskExecutor() {
147150
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
148151
executor.setCorePoolSize(5);
149152
executor.setThreadNamePrefix("SteVe-TaskExecutor-");
150153
executor.setWaitForTasksToCompleteOnShutdown(true);
151154
executor.setAwaitTerminationSeconds(30);
152155
executor.initialize();
153156

154-
return new DelegatingTaskExecutor(executor);
157+
return executor;
155158
}
156159

157160
/**

src/main/java/de/rwth/idsg/steve/config/DelegatingTaskScheduler.java

Lines changed: 0 additions & 51 deletions
This file was deleted.

src/main/java/de/rwth/idsg/steve/config/WebSocketConfiguration.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import de.rwth.idsg.steve.ocpp.ws.ocpp12.Ocpp12WebSocketEndpoint;
2424
import de.rwth.idsg.steve.ocpp.ws.ocpp15.Ocpp15WebSocketEndpoint;
2525
import de.rwth.idsg.steve.ocpp.ws.ocpp16.Ocpp16WebSocketEndpoint;
26-
import de.rwth.idsg.steve.service.ChargePointRegistrationService;
26+
import de.rwth.idsg.steve.service.ChargePointService;
2727
import de.rwth.idsg.steve.web.validation.ChargeBoxIdValidator;
2828
import lombok.RequiredArgsConstructor;
2929
import lombok.extern.slf4j.Slf4j;
@@ -48,7 +48,7 @@
4848
@Slf4j
4949
public class WebSocketConfiguration implements WebSocketConfigurer {
5050

51-
private final ChargePointRegistrationService chargePointRegistrationService;
51+
private final ChargePointService chargePointService;
5252
private final ChargeBoxIdValidator chargeBoxIdValidator;
5353
private final Ocpp12WebSocketEndpoint ocpp12WebSocketEndpoint;
5454
private final Ocpp15WebSocketEndpoint ocpp15WebSocketEndpoint;
@@ -65,7 +65,7 @@ public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
6565
chargeBoxIdValidator,
6666
handshakeHandler(),
6767
Lists.newArrayList(ocpp16WebSocketEndpoint, ocpp15WebSocketEndpoint, ocpp12WebSocketEndpoint),
68-
chargePointRegistrationService
68+
chargePointService
6969
);
7070

7171
registry.addHandler(handshakeHandler.getDummyWebSocketHandler(), PATH_INFIX + "*")

src/main/java/de/rwth/idsg/steve/ocpp/soap/MessageHeaderInterceptor.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,10 @@
1818
*/
1919
package de.rwth.idsg.steve.ocpp.soap;
2020

21-
import de.rwth.idsg.steve.config.DelegatingTaskExecutor;
2221
import de.rwth.idsg.steve.ocpp.OcppProtocol;
2322
import de.rwth.idsg.steve.repository.OcppServerRepository;
2423
import de.rwth.idsg.steve.repository.impl.ChargePointRepositoryImpl;
25-
import de.rwth.idsg.steve.service.ChargePointRegistrationService;
24+
import de.rwth.idsg.steve.service.ChargePointService;
2625
import lombok.extern.slf4j.Slf4j;
2726
import ocpp.cs._2015._10.RegistrationStatus;
2827
import org.apache.cxf.binding.soap.Soap12;
@@ -37,6 +36,7 @@
3736
import org.apache.cxf.ws.addressing.AddressingProperties;
3837
import org.apache.cxf.ws.addressing.ContextUtils;
3938
import org.apache.cxf.ws.addressing.EndpointReferenceType;
39+
import org.springframework.core.task.TaskExecutor;
4040
import org.springframework.stereotype.Component;
4141

4242
import javax.xml.namespace.QName;
@@ -50,7 +50,7 @@
5050
* 2. Intercepts incoming OCPP messages to update the endpoint address ("From" field of the WS-A header) in DB.
5151
* And the absence of the field is not a deal breaker anymore. But, as a side effect, the user will not be able
5252
* to send commands to the charging station, since the DB call to list the charge points will filter it out. See
53-
* {@link ChargePointRepositoryImpl#getChargePointSelect(OcppProtocol, java.util.List)}.
53+
* {@link ChargePointRepositoryImpl#getChargePointSelect(OcppProtocol, java.util.List, java.util.List)}.
5454
*
5555
* @author Sevket Goekay <[email protected]>
5656
* @since 15.06.2015
@@ -60,19 +60,19 @@
6060
public class MessageHeaderInterceptor extends AbstractPhaseInterceptor<Message> {
6161

6262
private final OcppServerRepository ocppServerRepository;
63-
private final ChargePointRegistrationService chargePointRegistrationService;
64-
private final DelegatingTaskExecutor asyncTaskExecutor;
63+
private final ChargePointService chargePointService;
64+
private final TaskExecutor taskExecutor;
6565

6666
private static final String BOOT_OPERATION_NAME = "BootNotification";
6767
private static final String CHARGEBOX_ID_HEADER = "ChargeBoxIdentity";
6868

6969
public MessageHeaderInterceptor(OcppServerRepository ocppServerRepository,
70-
ChargePointRegistrationService chargePointRegistrationService,
71-
DelegatingTaskExecutor asyncTaskExecutor) {
70+
ChargePointService chargePointService,
71+
TaskExecutor taskExecutor) {
7272
super(Phase.PRE_INVOKE);
7373
this.ocppServerRepository = ocppServerRepository;
74-
this.chargePointRegistrationService = chargePointRegistrationService;
75-
this.asyncTaskExecutor = asyncTaskExecutor;
74+
this.chargePointService = chargePointService;
75+
this.taskExecutor = taskExecutor;
7676
}
7777

7878
@Override
@@ -86,7 +86,7 @@ public void handleMessage(Message message) throws Fault {
8686
QName opName = message.getExchange().getBindingOperationInfo().getOperationInfo().getName();
8787

8888
if (!BOOT_OPERATION_NAME.equals(opName.getLocalPart())) {
89-
Optional<RegistrationStatus> status = chargePointRegistrationService.getRegistrationStatus(chargeBoxId);
89+
Optional<RegistrationStatus> status = chargePointService.getRegistrationStatus(chargeBoxId);
9090
boolean allow = status.isPresent() && status.get() != RegistrationStatus.REJECTED;
9191
if (!allow) {
9292
throw createAuthFault(opName);
@@ -97,7 +97,7 @@ public void handleMessage(Message message) throws Fault {
9797
// 2. update endpoint
9898
// -------------------------------------------------------------------------
9999

100-
asyncTaskExecutor.execute(() -> {
100+
taskExecutor.execute(() -> {
101101
try {
102102
String endpointAddress = getEndpointAddress(message);
103103
if (endpointAddress != null) {

src/main/java/de/rwth/idsg/steve/ocpp/ws/AbstractWebSocketEndpoint.java

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,21 @@
1919
package de.rwth.idsg.steve.ocpp.ws;
2020

2121
import com.google.common.base.Strings;
22-
import de.rwth.idsg.steve.config.DelegatingTaskScheduler;
23-
import de.rwth.idsg.steve.config.SteveProperties;
2422
import de.rwth.idsg.steve.config.WebSocketConfiguration;
2523
import de.rwth.idsg.steve.ocpp.OcppTransport;
2624
import de.rwth.idsg.steve.ocpp.OcppVersion;
2725
import de.rwth.idsg.steve.ocpp.ws.data.CommunicationContext;
28-
import de.rwth.idsg.steve.ocpp.ws.data.SessionContext;
29-
import de.rwth.idsg.steve.ocpp.ws.pipeline.OcppCallHandler;
3026
import de.rwth.idsg.steve.ocpp.ws.pipeline.Deserializer;
3127
import de.rwth.idsg.steve.ocpp.ws.pipeline.IncomingPipeline;
28+
import de.rwth.idsg.steve.ocpp.ws.pipeline.OcppCallHandler;
3229
import de.rwth.idsg.steve.repository.OcppServerRepository;
3330
import de.rwth.idsg.steve.service.notification.OcppStationWebSocketConnected;
3431
import de.rwth.idsg.steve.service.notification.OcppStationWebSocketDisconnected;
3532
import org.joda.time.DateTime;
3633
import org.slf4j.Logger;
3734
import org.slf4j.LoggerFactory;
3835
import org.springframework.context.ApplicationEventPublisher;
36+
import org.springframework.scheduling.TaskScheduler;
3937
import org.springframework.web.socket.BinaryMessage;
4038
import org.springframework.web.socket.CloseStatus;
4139
import org.springframework.web.socket.PongMessage;
@@ -47,9 +45,7 @@
4745
import java.time.Instant;
4846
import java.util.ArrayList;
4947
import java.util.Collections;
50-
import java.util.Deque;
5148
import java.util.List;
52-
import java.util.Map;
5349
import java.util.concurrent.ScheduledFuture;
5450
import java.util.function.Consumer;
5551

@@ -61,7 +57,7 @@ public abstract class AbstractWebSocketEndpoint extends ConcurrentWebSocketHandl
6157

6258
public static final String CHARGEBOX_ID_KEY = "CHARGEBOX_ID_KEY";
6359

64-
private final DelegatingTaskScheduler asyncTaskScheduler;
60+
private final TaskScheduler taskScheduler;
6561
private final OcppServerRepository ocppServerRepository;
6662
private final FutureResponseContextStore futureResponseContextStore;
6763
private final IncomingPipeline pipeline;
@@ -72,17 +68,17 @@ public abstract class AbstractWebSocketEndpoint extends ConcurrentWebSocketHandl
7268
private final List<Consumer<String>> disconnectedCallbackList = new ArrayList<>();
7369
private final Object sessionContextLock = new Object();
7470

75-
public AbstractWebSocketEndpoint(DelegatingTaskScheduler asyncTaskScheduler,
71+
public AbstractWebSocketEndpoint(TaskScheduler taskScheduler,
7672
OcppServerRepository ocppServerRepository,
7773
FutureResponseContextStore futureResponseContextStore,
7874
ApplicationEventPublisher applicationEventPublisher,
79-
SteveProperties steveProperties,
75+
SessionContextStoreHolder sessionContextStoreHolder,
8076
AbstractTypeStore typeStore) {
81-
this.asyncTaskScheduler = asyncTaskScheduler;
77+
this.taskScheduler = taskScheduler;
8278
this.ocppServerRepository = ocppServerRepository;
8379
this.futureResponseContextStore = futureResponseContextStore;
8480
this.pipeline = new IncomingPipeline(new Deserializer(futureResponseContextStore, typeStore), this);
85-
this.sessionContextStore = new SessionContextStoreImpl(steveProperties.getOcpp().getWsSessionSelectStrategy());
81+
this.sessionContextStore = sessionContextStoreHolder.getOrCreate(getVersion());
8682

8783
connectedCallbackList.add((chargeBoxId) -> applicationEventPublisher.publishEvent(new OcppStationWebSocketConnected(chargeBoxId)));
8884
disconnectedCallbackList.add((chargeBoxId) -> applicationEventPublisher.publishEvent(new OcppStationWebSocketDisconnected(chargeBoxId)));
@@ -148,7 +144,7 @@ public void onOpen(WebSocketSession session) throws Exception {
148144

149145
// Just to keep the connection alive, such that the servers do not close
150146
// the connection because of a idle timeout, we ping-pong at fixed intervals.
151-
ScheduledFuture pingSchedule = asyncTaskScheduler.scheduleAtFixedRate(
147+
ScheduledFuture pingSchedule = taskScheduler.scheduleAtFixedRate(
152148
new PingTask(chargeBoxId, session),
153149
Instant.now().plus(WebSocketConfiguration.PING_INTERVAL),
154150
WebSocketConfiguration.PING_INTERVAL
@@ -210,28 +206,4 @@ protected String getChargeBoxId(WebSocketSession session) {
210206
return (String) session.getAttributes().get(CHARGEBOX_ID_KEY);
211207
}
212208

213-
protected void registerConnectedCallback(Consumer<String> consumer) {
214-
connectedCallbackList.add(consumer);
215-
}
216-
217-
protected void registerDisconnectedCallback(Consumer<String> consumer) {
218-
disconnectedCallbackList.add(consumer);
219-
}
220-
221-
public List<String> getChargeBoxIdList() {
222-
return sessionContextStore.getChargeBoxIdList();
223-
}
224-
225-
public int getNumberOfChargeBoxes() {
226-
return sessionContextStore.getNumberOfChargeBoxes();
227-
}
228-
229-
public Map<String, Deque<SessionContext>> getACopy() {
230-
return sessionContextStore.getACopy();
231-
}
232-
233-
public WebSocketSession getSession(String chargeBoxId) {
234-
return sessionContextStore.getSession(chargeBoxId);
235-
}
236-
237209
}

0 commit comments

Comments
 (0)