Skip to content

Commit 5c23fa8

Browse files
Merge pull request #29 from hmcts/static-analysis
add code analysis and various fixes
2 parents f98cb66 + 1904b9b commit 5c23fa8

File tree

8 files changed

+104
-24
lines changed

8 files changed

+104
-24
lines changed

.github/pmd-ruleset.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ruleset name="Custom Ruleset"
3+
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0
6+
https://pmd.github.io/pmd-7.0.0/pmd-7.0.0.xsd">
7+
8+
<description>Custom ruleset including exclusions</description>
9+
10+
<rule ref="category/java/bestpractices.xml"/>
11+
<rule ref="category/java/codestyle.xml">
12+
<exclude name="AtLeastOneConstructor"/>
13+
<exclude name="LongVariable"/>
14+
</rule>
15+
<rule ref="category/java/errorprone.xml"/>
16+
<rule ref="category/java/performance.xml"/>
17+
<rule ref="category/java/security.xml"/>
18+
</ruleset>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: Code analysis
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- master
7+
- main
8+
9+
jobs:
10+
pmd-analysis:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
15+
- name: Install PMD CLI
16+
run: |
17+
curl -L -o pmd-dist-7.13.0-bin.zip https://github.com/pmd/pmd/releases/download/pmd_releases%2F7.13.0/pmd-dist-7.13.0-bin.zip
18+
unzip pmd-dist-7.13.0-bin.zip
19+
mv pmd-bin-7.13.0 /opt/pmd
20+
echo "/opt/pmd/bin" >> $GITHUB_PATH
21+
22+
- name: Run PMD CLI analysis
23+
run: |
24+
mkdir -p build/reports/pmd
25+
26+
set +e
27+
/opt/pmd/bin/pmd check \
28+
--dir src/main/java \
29+
--rulesets \
30+
.github/pmd-ruleset.xml \
31+
--format html \
32+
-r build/reports/pmd/pmd-report.html
33+
PMD_EXIT_CODE=$?
34+
set -e
35+
36+
if [[ "$PMD_EXIT_CODE" -eq 1 ]]; then
37+
echo "Unexpected internal error during PMD execution"
38+
exit 1
39+
elif [[ "$PMD_EXIT_CODE" -eq 2 ]]; then
40+
echo "PMD CLI usage error"
41+
exit 1
42+
fi
43+
echo "PMD_EXIT_CODE=$PMD_EXIT_CODE" >> $GITHUB_ENV
44+
45+
- name: Upload static analysis report on failure
46+
if: env.PMD_EXIT_CODE != '0'
47+
uses: actions/upload-artifact@v4
48+
with:
49+
name: pmd-report
50+
path: build/reports/pmd/pmd-report.html
51+
52+
- name: Check for static code analysis violations
53+
run: |
54+
if [[ "$PMD_EXIT_CODE" -eq 0 ]]; then
55+
echo "No PMD violations"
56+
else
57+
echo "PMD violations found"
58+
exit 1
59+
fi

src/main/java/uk/gov/hmcts/cp/config/OpenAPIConfiguration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
@Configuration
88
public class OpenAPIConfiguration {
99

10-
private OpenAPIConfigurationLoader openAPIConfigLoader = new OpenAPIConfigurationLoader();
10+
private final OpenAPIConfigurationLoader openAPIConfigLoader = new OpenAPIConfigurationLoader();
1111

1212
@Bean
1313
public OpenAPI openAPI() {

src/main/java/uk/gov/hmcts/cp/controllers/CourtScheduleController.java

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,32 +14,34 @@
1414

1515
@RestController
1616
public class CourtScheduleController implements CourtScheduleApi {
17-
private static final Logger log = LoggerFactory.getLogger(CourtScheduleController.class);
17+
private static final Logger LOG = LoggerFactory.getLogger(CourtScheduleController.class);
1818
private final CourtScheduleService courtScheduleService;
1919

20-
public CourtScheduleController(CourtScheduleService courtScheduleService) {
20+
public CourtScheduleController(final CourtScheduleService courtScheduleService) {
2121
this.courtScheduleService = courtScheduleService;
2222
}
2323

2424
@Override
25-
public ResponseEntity<CourtScheduleResponse> getCourtScheduleByCaseUrn(String caseUrn) {
26-
String sanitizedCaseUrn;
27-
CourtScheduleResponse courtScheduleResponse;
25+
public ResponseEntity<CourtScheduleResponse> getCourtScheduleByCaseUrn(final String caseUrn) {
26+
final String sanitizedCaseUrn;
27+
final CourtScheduleResponse courtScheduleResponse;
2828
try {
2929
sanitizedCaseUrn = sanitizeCaseUrn(caseUrn);
3030
courtScheduleResponse = courtScheduleService.getCourtScheduleByCaseUrn(sanitizedCaseUrn);
3131
} catch (ResponseStatusException e) {
32-
log.error(e.getMessage());
32+
LOG.atError().log(e.getMessage());
3333
throw e;
3434
}
35-
log.debug("Found court schedule for caseUrn: {}", sanitizedCaseUrn);
35+
LOG.atDebug().log("Found court schedule for caseUrn: {}", sanitizedCaseUrn);
3636
return ResponseEntity.ok()
3737
.contentType(MediaType.APPLICATION_JSON)
3838
.body(courtScheduleResponse);
3939
}
4040

41-
private String sanitizeCaseUrn(String urn) {
42-
if (urn == null) throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "caseUrn is required");
41+
private String sanitizeCaseUrn(final String urn) {
42+
if (urn == null) {
43+
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "caseUrn is required");
44+
}
4345
return StringEscapeUtils.escapeHtml4(urn);
4446
}
4547
}

src/main/java/uk/gov/hmcts/cp/controllers/GlobalExceptionHandler.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,21 @@ public class GlobalExceptionHandler {
1616

1717
private final Tracer tracer;
1818

19-
public GlobalExceptionHandler(Tracer tracer) {
19+
public GlobalExceptionHandler(final Tracer tracer) {
2020
this.tracer = tracer;
2121
}
2222

2323
@ExceptionHandler(ResponseStatusException.class)
24-
public ResponseEntity<ErrorResponse> handleResponseStatusException(ResponseStatusException e) {
25-
ErrorResponse error = ErrorResponse.builder()
26-
.error(String.valueOf(e.getStatusCode().value()))
27-
.message(e.getReason() != null ? e.getReason() : e.getMessage())
24+
public ResponseEntity<ErrorResponse> handleResponseStatusException(final ResponseStatusException responseStatusException) {
25+
final ErrorResponse error = ErrorResponse.builder()
26+
.error(String.valueOf(responseStatusException.getStatusCode().value()))
27+
.message(responseStatusException.getReason() != null ? responseStatusException.getReason() : responseStatusException.getMessage())
2828
.timestamp(OffsetDateTime.now(ZoneOffset.UTC))
2929
.traceId(Objects.requireNonNull(tracer.currentSpan()).context().traceId())
3030
.build();
3131

3232
return ResponseEntity
33-
.status(e.getStatusCode())
33+
.status(responseStatusException.getStatusCode())
3434
.body(error);
3535
}
3636
}

src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepository.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.springframework.stereotype.Repository;
44
import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse;
55

6+
@FunctionalInterface
67
@Repository
78
public interface CourtScheduleRepository {
89

src/main/java/uk/gov/hmcts/cp/repositories/InMemoryCourtScheduleRepositoryImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
@Component
1414
public class InMemoryCourtScheduleRepositoryImpl implements CourtScheduleRepository {
1515

16-
public CourtScheduleResponse getCourtScheduleByCaseUrn(String caseUrn) {
17-
CourtScheduleResponseCourtScheduleInnerHearingsInner courtScheduleHearing = CourtScheduleResponseCourtScheduleInnerHearingsInner.builder()
16+
public CourtScheduleResponse getCourtScheduleByCaseUrn(final String caseUrn) {
17+
final CourtScheduleResponseCourtScheduleInnerHearingsInner courtScheduleHearing = CourtScheduleResponseCourtScheduleInnerHearingsInner.builder()
1818
.hearingId(UUID.randomUUID().toString())
1919
.listNote("Requires interpreter")
2020
.hearingDescription("Sentencing for theft case")

src/main/java/uk/gov/hmcts/cp/services/CourtScheduleService.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,18 @@
1414
@RequiredArgsConstructor
1515
public class CourtScheduleService {
1616

17-
private static final Logger log = LoggerFactory.getLogger(CourtScheduleService.class);
17+
private static final Logger LOG = LoggerFactory.getLogger(CourtScheduleService.class);
1818

1919
private final CourtScheduleRepository courtScheduleRepository;
2020

21-
public CourtScheduleResponse getCourtScheduleByCaseUrn(String caseUrn) throws ResponseStatusException {
21+
public CourtScheduleResponse getCourtScheduleByCaseUrn(final String caseUrn) throws ResponseStatusException {
2222
if (StringUtils.isEmpty(caseUrn)) {
23-
log.warn("No case urn provided");
23+
LOG.atWarn().log("No case urn provided");
2424
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "caseUrn is required");
2525
}
26-
log.warn("NOTE: System configured to return stubbed Court Schedule details. Ignoring provided caseUrn : {}", caseUrn);
27-
CourtScheduleResponse stubbedCourtScheduleResponse = courtScheduleRepository.getCourtScheduleByCaseUrn(caseUrn);
28-
log.debug("Court Schedule response: {}", stubbedCourtScheduleResponse);
26+
LOG.atWarn().log("NOTE: System configured to return stubbed Court Schedule details. Ignoring provided caseUrn : {}", caseUrn);
27+
final CourtScheduleResponse stubbedCourtScheduleResponse = courtScheduleRepository.getCourtScheduleByCaseUrn(caseUrn);
28+
LOG.atDebug().log("Court Schedule response: {}", stubbedCourtScheduleResponse);
2929
return stubbedCourtScheduleResponse;
3030
}
3131

0 commit comments

Comments
 (0)