Code format hawkbit-rest-core (#1944)

Signed-off-by: Marinov Avgustin <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2024-11-05 11:32:28 +02:00
committed by GitHub
parent b863fdb337
commit 4b460d8e68
24 changed files with 315 additions and 398 deletions

View File

@@ -20,83 +20,84 @@ import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnProperty(
value="hawkbit.server.swagger.enabled",
havingValue = "true",
matchIfMissing = true)
value = "hawkbit.server.swagger.enabled",
havingValue = "true",
matchIfMissing = true)
public class OpenApiConfiguration {
private static final String API_TITLE = "hawkBit REST APIs";
private static final String API_VERSION = "v1";
private static final String DESCRIPTION = """
Eclipse hawkBit™ is a domain-independent back-end framework for rolling out software updates to constrained edge devices as well as more powerful controllers and gateways connected to IP based networking infrastructure.
""";
private static final String API_TITLE = "hawkBit REST APIs";
private static final String API_VERSION = "v1";
private static final String DESCRIPTION = """
Eclipse hawkBit™ is a domain-independent back-end framework for rolling out software updates to constrained edge devices as well as more powerful controllers and gateways connected to IP based networking infrastructure.
""";
private static final String BASIC_AUTH_SEC_SCHEME_NAME = "Basic Authentication";
private static final String BEARER_AUTH_SEC_SCHEME_NAME = "Bearer Authentication";
private static final String DDI_TOKEN_SEC_SCHEME_NAME = "DDI Target/GatewayToken Authentication";
private static final String BASIC_AUTH_SEC_SCHEME_NAME = "Basic Authentication";
private static final String BEARER_AUTH_SEC_SCHEME_NAME = "Bearer Authentication";
private static final String DDI_TOKEN_SEC_SCHEME_NAME = "DDI Target/GatewayToken Authentication";
@Bean
public OpenAPI openApi() {
return new OpenAPI().info(new Info().title(API_TITLE).version(API_VERSION).description(DESCRIPTION));
}
@Bean
public OpenAPI openApi() {
return new OpenAPI().info(new Info().title(API_TITLE).version(API_VERSION).description(DESCRIPTION));
}
@Bean
@ConditionalOnProperty(
value="hawkbit.server.swagger.mgmt.api.group.enabled",
havingValue = "true",
matchIfMissing = true)
public GroupedOpenApi mgmtApi() {
return GroupedOpenApi
.builder()
.group("Management API")
.pathsToMatch("/rest/v1/**")
.addOpenApiCustomizer(openApi -> {
openApi
.addSecurityItem(new SecurityRequirement()
.addList(BASIC_AUTH_SEC_SCHEME_NAME)
.addList(BEARER_AUTH_SEC_SCHEME_NAME))
.components(
@Bean
@ConditionalOnProperty(
value = "hawkbit.server.swagger.mgmt.api.group.enabled",
havingValue = "true",
matchIfMissing = true)
public GroupedOpenApi mgmtApi() {
return GroupedOpenApi
.builder()
.group("Management API")
.pathsToMatch("/rest/v1/**")
.addOpenApiCustomizer(openApi -> {
openApi
.getComponents()
.addSecuritySchemes(BASIC_AUTH_SEC_SCHEME_NAME,
new SecurityScheme()
.name(BASIC_AUTH_SEC_SCHEME_NAME)
.type(SecurityScheme.Type.HTTP)
.in(SecurityScheme.In.HEADER)
.scheme("basic"))
.addSecuritySchemes(BEARER_AUTH_SEC_SCHEME_NAME,
new SecurityScheme()
.name(BEARER_AUTH_SEC_SCHEME_NAME)
.type(SecurityScheme.Type.HTTP)
.in(SecurityScheme.In.HEADER)
.bearerFormat("JWT")
.scheme("bearer")));
})
.build();
}
@Bean
@ConditionalOnProperty(
value="hawkbit.server.swagger.ddi.api.group.enabled",
havingValue = "true",
matchIfMissing = true)
public GroupedOpenApi ddiApi() {
return GroupedOpenApi
.builder()
.group("Direct Device Integration API")
.pathsToMatch("/{tenant}/controller/**")
.addOpenApiCustomizer(openApi -> {
openApi
.addSecurityItem(new SecurityRequirement().addList(DDI_TOKEN_SEC_SCHEME_NAME))
.components(
.addSecurityItem(new SecurityRequirement()
.addList(BASIC_AUTH_SEC_SCHEME_NAME)
.addList(BEARER_AUTH_SEC_SCHEME_NAME))
.components(
openApi
.getComponents()
.addSecuritySchemes(BASIC_AUTH_SEC_SCHEME_NAME,
new SecurityScheme()
.name(BASIC_AUTH_SEC_SCHEME_NAME)
.type(SecurityScheme.Type.HTTP)
.in(SecurityScheme.In.HEADER)
.scheme("basic"))
.addSecuritySchemes(BEARER_AUTH_SEC_SCHEME_NAME,
new SecurityScheme()
.name(BEARER_AUTH_SEC_SCHEME_NAME)
.type(SecurityScheme.Type.HTTP)
.in(SecurityScheme.In.HEADER)
.bearerFormat("JWT")
.scheme("bearer")));
})
.build();
}
@Bean
@ConditionalOnProperty(
value = "hawkbit.server.swagger.ddi.api.group.enabled",
havingValue = "true",
matchIfMissing = true)
public GroupedOpenApi ddiApi() {
return GroupedOpenApi
.builder()
.group("Direct Device Integration API")
.pathsToMatch("/{tenant}/controller/**")
.addOpenApiCustomizer(openApi -> {
openApi
.getComponents()
.addSecuritySchemes(DDI_TOKEN_SEC_SCHEME_NAME,
new SecurityScheme()
.name("Authorization")
.type(SecurityScheme.Type.APIKEY)
.in(SecurityScheme.In.HEADER)
.description("Format: (Target|Gateway)Token &lt;token&gt;")));
})
.build();
}
.addSecurityItem(new SecurityRequirement().addList(DDI_TOKEN_SEC_SCHEME_NAME))
.components(
openApi
.getComponents()
.addSecuritySchemes(DDI_TOKEN_SEC_SCHEME_NAME,
new SecurityScheme()
.name("Authorization")
.type(SecurityScheme.Type.APIKEY)
.in(SecurityScheme.In.HEADER)
.description("Format: (Target|Gateway)Token &lt;token&gt;")));
})
.build();
}
}

View File

@@ -9,8 +9,6 @@
*/
package org.eclipse.hawkbit.rest;
import jakarta.servlet.http.HttpServletResponse;
import org.eclipse.hawkbit.rest.exception.ResponseExceptionHandler;
import org.eclipse.hawkbit.rest.filter.ExcludePathAwareShallowETagFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
@@ -20,7 +18,6 @@ import org.springframework.hateoas.config.EnableHypermediaSupport;
import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.WebApplicationContext;
/**
* Configuration for Rest api.

View File

@@ -18,7 +18,7 @@ import org.springframework.hateoas.RepresentationModel;
/**
* List that extends RepresentationModel to ensure that links in content are in HAL format.
*
*
* @param <T> of the response content
*/
public class ResponseList<T> extends RepresentationModel<ResponseList<T>> implements List<T> {
@@ -26,8 +26,7 @@ public class ResponseList<T> extends RepresentationModel<ResponseList<T>> implem
private final List<T> content;
/**
* @param content
* to delegate
* @param content to delegate
*/
public ResponseList(final List<T> content) {
this.content = content;
@@ -103,16 +102,6 @@ public class ResponseList<T> extends RepresentationModel<ResponseList<T>> implem
content.clear();
}
@Override
public boolean equals(final Object o) {
return content.equals(o);
}
@Override
public int hashCode() {
return content.hashCode();
}
@Override
public T get(final int index) {
return content.get(index);
@@ -163,4 +152,14 @@ public class ResponseList<T> extends RepresentationModel<ResponseList<T>> implem
return "ResponseList [content=" + content + "]";
}
@Override
public boolean equals(final Object o) {
return content.equals(o);
}
@Override
public int hashCode() {
return content.hashCode();
}
}

View File

@@ -26,12 +26,10 @@ public enum SortDirection {
/**
* Returns the sort direction for the given name.
*
* @param name
* the name of the enum
*
* @param name the name of the enum
* @return the corresponding enum
* @throws SortParameterUnsupportedDirectionException
* if there is no matching enum for the specified name
* @throws SortParameterUnsupportedDirectionException if there is no matching enum for the specified name
*/
public static SortDirection getByName(final String name) {
try {

View File

@@ -9,11 +9,11 @@
*/
package org.eclipse.hawkbit.rest.exception;
import java.io.Serial;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
import java.io.Serial;
/**
* Exception which is thrown in case an request body is not well formatted and
* cannot be parsed.

View File

@@ -14,15 +14,13 @@ import org.eclipse.hawkbit.exception.SpServerError;
/**
* Thrown if a multi part exception occurred.
*
*/
public final class MultiPartFileUploadException extends AbstractServerRtException {
private static final long serialVersionUID = 1L;
/**
* @param cause
* for the exception
* @param cause for the exception
*/
public MultiPartFileUploadException(final Throwable cause) {
super(cause.getMessage(), SpServerError.SP_ARTIFACT_UPLOAD_FAILED, cause);

View File

@@ -99,19 +99,12 @@ public class ResponseExceptionHandler {
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_STOP_ROLLOUT_FAILED, HttpStatus.LOCKED);
}
private static HttpStatus getStatusOrDefault(final SpServerError error) {
return ERROR_TO_HTTP_STATUS.getOrDefault(error, DEFAULT_RESPONSE_STATUS);
}
/**
* method for handling exception of type AbstractServerRtException. Called
* by the Spring-Framework for exception handling.
*
* @param request
* the Http request
* @param ex
* the exception which occurred
*
* @param request the Http request
* @param ex the exception which occurred
* @return the entity to be responded containing the exception information
* as entity.
*/
@@ -137,10 +130,8 @@ public class ResponseExceptionHandler {
* ResponseStatus 500 is returned. Called by the Spring-Framework for
* exception handling.
*
* @param request
* the Http request
* @param ex
* the exception which occurred
* @param request the Http request
* @param ex the exception which occurred
* @return the entity to be responded containing the response status 500
*/
@ExceptionHandler(FileStreamingFailedException.class)
@@ -158,10 +149,8 @@ public class ResponseExceptionHandler {
* cannot be deserialized. Called by the Spring-Framework for exception
* handling.
*
* @param request
* the Http request
* @param ex
* the exception which occurred
* @param request the Http request
* @param ex the exception which occurred
* @return the entity to be responded containing the exception information
* as entity.
*/
@@ -181,10 +170,8 @@ public class ResponseExceptionHandler {
* is thrown in case the request is rejected due to a constraint violation.
* Called by the Spring-Framework for exception handling.
*
* @param request
* the Http request
* @param ex
* the exception which occurred
* @param request the Http request
* @param ex the exception which occurred
* @return the entity to be responded containing the exception information
* as entity.
*/
@@ -195,7 +182,7 @@ public class ResponseExceptionHandler {
final ExceptionInfo response = new ExceptionInfo();
response.setMessage(ex.getConstraintViolations().stream().map(
violation -> violation.getPropertyPath() + MESSAGE_FORMATTER_SEPARATOR + violation.getMessage() + ".")
violation -> violation.getPropertyPath() + MESSAGE_FORMATTER_SEPARATOR + violation.getMessage() + ".")
.collect(Collectors.joining(MESSAGE_FORMATTER_SEPARATOR)));
response.setExceptionClass(ex.getClass().getName());
response.setErrorCode(SpServerError.SP_REPO_CONSTRAINT_VIOLATION.getKey());
@@ -208,10 +195,8 @@ public class ResponseExceptionHandler {
* in case the request is rejected due to invalid requests. Called by the
* Spring-Framework for exception handling.
*
* @param request
* the Http request
* @param ex
* the exception which occurred
* @param request the Http request
* @param ex the exception which occurred
* @return the entity to be responded containing the exception information
* as entity.
*/
@@ -233,10 +218,8 @@ public class ResponseExceptionHandler {
* thrown in case the request body is not well formed and cannot be
* deserialized. Called by the Spring-Framework for exception handling.
*
* @param request
* the Http request
* @param ex
* the exception which occurred
* @param request the Http request
* @param ex the exception which occurred
* @return the entity to be responded containing the exception information
* as entity.
*/
@@ -258,6 +241,10 @@ public class ResponseExceptionHandler {
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
}
private static HttpStatus getStatusOrDefault(final SpServerError error) {
return ERROR_TO_HTTP_STATUS.getOrDefault(error, DEFAULT_RESPONSE_STATUS);
}
private void logRequest(final HttpServletRequest request, final Exception ex) {
log.debug("Handling exception {} of request {}", ex.getClass().getName(), request.getRequestURL());
}

View File

@@ -14,16 +14,12 @@ import org.eclipse.hawkbit.exception.SpServerError;
/**
* Exception used by the REST API in case of invalid sort parameter syntax.
*
*
*
*
*/
public class SortParameterSyntaxErrorException extends AbstractServerRtException {
/**
*
*/
*
*/
private static final long serialVersionUID = 1L;
/**

View File

@@ -15,16 +15,12 @@ import org.eclipse.hawkbit.exception.SpServerError;
/**
* Exception used by the REST API in case of invalid sort parameter direction
* name.
*
*
*
*
*/
public class SortParameterUnsupportedDirectionException extends AbstractServerRtException {
/**
*
*/
*
*/
private static final long serialVersionUID = 1L;
/**
@@ -37,11 +33,10 @@ public class SortParameterUnsupportedDirectionException extends AbstractServerRt
/**
* Creates a new SortParameterSyntaxErrorException with
* {@link SpServerError#SP_REST_SORT_PARAM_INVALID_DIRECTION} error.
*
* @param cause
* the cause (which is saved for later retrieval by the
* getCause() method). (A null value is permitted, and indicates
* that the cause is nonexistent or unknown.)
*
* @param cause the cause (which is saved for later retrieval by the
* getCause() method). (A null value is permitted, and indicates
* that the cause is nonexistent or unknown.)
*/
public SortParameterUnsupportedDirectionException(final Throwable cause) {
super(SpServerError.SP_REST_SORT_PARAM_INVALID_DIRECTION, cause);

View File

@@ -15,16 +15,12 @@ import org.eclipse.hawkbit.exception.SpServerError;
/**
* Exception used by the REST API in case of invalid field name in the sort
* parameter.
*
*
*
*
*/
public class SortParameterUnsupportedFieldException extends AbstractServerRtException {
/**
*
*/
*
*/
private static final long serialVersionUID = 1L;
/**
@@ -38,11 +34,10 @@ public class SortParameterUnsupportedFieldException extends AbstractServerRtExce
/**
* Creates a new SortParameterSyntaxErrorException with
* {@link SpServerError#SP_REST_SORT_PARAM_INVALID_FIELD} error.
*
* @param cause
* the cause (which is saved for later retrieval by the
* getCause() method). (A null value is permitted, and indicates
* that the cause is nonexistent or unknown.)
*
* @param cause the cause (which is saved for later retrieval by the
* getCause() method). (A null value is permitted, and indicates
* that the cause is nonexistent or unknown.)
*/
public SortParameterUnsupportedFieldException(final Throwable cause) {
super(SpServerError.SP_REST_SORT_PARAM_INVALID_FIELD, cause);

View File

@@ -29,9 +29,8 @@ public final class FileStreamingFailedException extends AbstractServerRtExceptio
/**
* Constructor with Throwable.
*
* @param cause
* for the exception
*
* @param cause for the exception
*/
public FileStreamingFailedException(final Throwable cause) {
super(SpServerError.SP_ARTIFACT_LOAD_FAILED, cause);
@@ -39,9 +38,8 @@ public final class FileStreamingFailedException extends AbstractServerRtExceptio
/**
* Constructor with error string.
*
* @param message
* of the error
*
* @param message of the error
*/
public FileStreamingFailedException(final String message) {
super(message, SpServerError.SP_ARTIFACT_LOAD_FAILED);
@@ -49,11 +47,9 @@ public final class FileStreamingFailedException extends AbstractServerRtExceptio
/**
* Constructor with error string and cause.
*
* @param message
* of the error
* @param cause
* for the exception
*
* @param message of the error
* @param cause for the exception
*/
public FileStreamingFailedException(final String message, final Throwable cause) {
super(message, SpServerError.SP_ARTIFACT_LOAD_FAILED, cause);

View File

@@ -11,20 +11,16 @@ package org.eclipse.hawkbit.rest.util;
/**
* Listener for progress on artifact file streaming.
*
*/
@FunctionalInterface
public interface FileStreamingProgressListener {
/**
* Called multiple times during streaming.
*
* @param requestedBytes
* requested bytes of the request
* @param shippedBytesSinceLast
* since the last report
* @param shippedBytesOverall
* during the request
*
* @param requestedBytes requested bytes of the request
* @param shippedBytesSinceLast since the last report
* @param shippedBytesOverall during the request
*/
void progress(long requestedBytes, long shippedBytesSinceLast, long shippedBytesOverall);
}

View File

@@ -12,7 +12,6 @@ package org.eclipse.hawkbit.rest.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
@@ -46,19 +45,15 @@ public final class FileStreamingUtil {
*/
public static final String ARTIFACT_MD5_DWNL_SUFFIX = ".MD5SUM";
private static final int BUFFER_SIZE = 0x2000; // 8k
/**
* Write a md5 file response.
*
* @param response
* the response
* @param md5Hash
* of the artifact
* @param filename
* as provided by the client
* @param response the response
* @param md5Hash of the artifact
* @param filename as provided by the client
* @return the response
* @throws IOException
* cannot write output stream
* @throws IOException cannot write output stream
*/
public static ResponseEntity<Void> writeMD5FileResponse(final HttpServletResponse response, final String md5Hash,
final String filename) throws IOException {
@@ -94,26 +89,16 @@ public final class FileStreamingUtil {
* The request supports RFC7233 range requests.
* </p>
*
* @param artifact
* the artifact
* @param filename
* to be written to the client response
* @param lastModified
* unix timestamp of the artifact
* @param response
* to be sent back to the requesting client
* @param request
* from the client
* @param progressListener
* to write progress updates to
*
* @param artifact the artifact
* @param filename to be written to the client response
* @param lastModified unix timestamp of the artifact
* @param response to be sent back to the requesting client
* @param request from the client
* @param progressListener to write progress updates to
* @return http response
*
* @throws FileStreamingFailedException if streaming fails
* @see <a href="https://tools.ietf.org/html/rfc7233">https://tools.ietf.org
* /html/rfc7233</a>
*
* @throws FileStreamingFailedException
* if streaming fails
* /html/rfc7233</a>
*/
public static ResponseEntity<InputStream> writeFileResponse(final DbArtifact artifact, final String filename,
final long lastModified, final HttpServletResponse response, final HttpServletRequest request,
@@ -187,7 +172,7 @@ public final class FileStreamingUtil {
return result;
}
private static void resetResponseExceptHeaders(final HttpServletResponse response){
private static void resetResponseExceptHeaders(final HttpServletResponse response) {
// do backup the current headers (like CORS related)
final Map<String, String> storedHeaders = new HashMap<>();
for (final String header : response.getHeaderNames()) {
@@ -359,7 +344,7 @@ public final class FileStreamingUtil {
}
if (progressListener != null) {
final int newPercent = (int)Math.floor(total * 100.0 / length);
final int newPercent = (int) Math.floor(total * 100.0 / length);
// every 10 percent an event
if (newPercent == 100 || newPercent > progressPercent + 10) {
@@ -383,6 +368,7 @@ public final class FileStreamingUtil {
}
private static final class ByteRange {
private static final String MULTIPART_BOUNDARY = "THIS_STRING_SEPARATES_MULTIPART";
private final long start;
@@ -397,22 +383,6 @@ public final class FileStreamingUtil {
this.total = total;
}
private long getStart() {
return start;
}
private long getEnd() {
return end;
}
private long getLength() {
return length;
}
private long getTotal() {
return total;
}
@Override
// Generated code
@SuppressWarnings("squid:S864")
@@ -455,6 +425,22 @@ public final class FileStreamingUtil {
return true;
}
private long getStart() {
return start;
}
private long getEnd() {
return end;
}
private long getLength() {
return length;
}
private long getTotal() {
return total;
}
}
}

View File

@@ -23,11 +23,8 @@ public final class HttpUtil {
/**
* Checks given CSV string for defined match value or wildcard.
*
* @param matchHeader
* to search through
* @param toMatch
* to search for
*
* @param matchHeader to search through
* @param toMatch to search for
* @return <code>true</code> if string matches.
*/
public static boolean matchesHttpHeader(final String matchHeader, final String toMatch) {

View File

@@ -9,6 +9,8 @@
*/
package org.eclipse.hawkbit.rest.util;
import java.util.Objects;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@@ -16,8 +18,6 @@ import lombok.NoArgsConstructor;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.Objects;
/**
* Gives access to the request and response for the rest resources.
*/

View File

@@ -23,9 +23,6 @@ import org.springframework.data.domain.Sort.Order;
/**
* A utility class for parsing query parameters which define the sorting of
* elements.
*
*
*
*/
public final class SortUtility {
@@ -47,25 +44,19 @@ public final class SortUtility {
* of sorting: http://localhost/entity?s=field1:ASC, field2:DESC The fields
* will be split into the keys of the returned map. The direction of the
* sorting will be mapped into the {@link Direction} enum.
*
* @param enumType
* the class of the enum which the fields in the sort string
* should be related to.
* @param <T>
* the type of the enumeration which must be derived from
* {@link RsqlQueryField}
* @param sortString
* the string representation of the query parameters. Might be
* {@code null} or an empty string.
*
* @param enumType the class of the enum which the fields in the sort string
* should be related to.
* @param <T> the type of the enumeration which must be derived from
* {@link RsqlQueryField}
* @param sortString the string representation of the query parameters. Might be
* {@code null} or an empty string.
* @return a list which holds the {@link RsqlQueryField} and the specific
* {@link Direction} for them as a tuple. Never {@code null}. In
* case of no sorting parameters an empty map will be returned.
* @throws SortParameterSyntaxErrorException
* if the sorting query parameter is not well-formed
* @throws SortParameterUnsupportedFieldException
* if a field name cannot be mapped to the enum type
* @throws SortParameterUnsupportedDirectionException
* if the given direction is not "ASC" or "DESC"
* @throws SortParameterSyntaxErrorException if the sorting query parameter is not well-formed
* @throws SortParameterUnsupportedFieldException if a field name cannot be mapped to the enum type
* @throws SortParameterUnsupportedDirectionException if the given direction is not "ASC" or "DESC"
*/
public static <T extends Enum<T> & RsqlQueryField> List<Order> parse(final Class<T> enumType,
final String sortString) throws SortParameterSyntaxErrorException {
@@ -95,18 +86,14 @@ public final class SortUtility {
/**
* Returns the attribute identifier for the given name.
*
* @param enumType
* the class of the enum which the fields in the sort string
* should be related to.
* @param name
* the name of the enum
* @param <T>
* the type of the enumeration which must be derived from
* {@link RsqlQueryField}
*
* @param enumType the class of the enum which the fields in the sort string
* should be related to.
* @param name the name of the enum
* @param <T> the type of the enumeration which must be derived from
* {@link RsqlQueryField}
* @return the corresponding enum
* @throws SortParameterUnsupportedFieldException
* if there is no matching enum for the specified name
* @throws SortParameterUnsupportedFieldException if there is no matching enum for the specified name
*/
private static <T extends Enum<T> & RsqlQueryField> T getAttributeIdentifierByName(final Class<T> enumType,
final String name) {