diff --git a/hawkbit-rest/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java b/hawkbit-rest/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java index be72ad8d3..ad0b3a642 100644 --- a/hawkbit-rest/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java +++ b/hawkbit-rest/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java @@ -133,9 +133,6 @@ public class DdiRootController implements DdiRootControllerRestApi { @Autowired private ArtifactUrlHandler artifactUrlHandler; - @Autowired - private RequestResponseContextHolder requestResponseContextHolder; - @Autowired private EntityFactory entityFactory; @@ -152,7 +149,7 @@ public class DdiRootController implements DdiRootControllerRestApi { return new ResponseEntity<>( DataConversionHelper.createArtifacts(target, softwareModule, artifactUrlHandler, systemManagement, - new ServletServerHttpRequest(requestResponseContextHolder.getHttpServletRequest())), + new ServletServerHttpRequest(RequestResponseContextHolder.getHttpServletRequest())), HttpStatus.OK); } @@ -162,7 +159,7 @@ public class DdiRootController implements DdiRootControllerRestApi { log.debug("getControllerBase({})", controllerId); final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotExist(controllerId, IpUtil - .getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(), securityProperties)); + .getClientIpFromRequest(RequestResponseContextHolder.getHttpServletRequest(), securityProperties)); final Action activeAction = controllerManagement.findActiveActionWithHighestWeight(controllerId).orElse(null); final Action installedAction = controllerManagement.getInstalledActionByTarget(controllerId).orElse(null); @@ -197,18 +194,18 @@ public class DdiRootController implements DdiRootControllerRestApi { .loadArtifactBinary(artifact.getSha1Hash(), module.getId(), module.isEncrypted()) .orElseThrow(() -> new ArtifactBinaryNotFoundException(artifact.getSha1Hash())); - final String ifMatch = requestResponseContextHolder.getHttpServletRequest().getHeader(HttpHeaders.IF_MATCH); + final String ifMatch = RequestResponseContextHolder.getHttpServletRequest().getHeader(HttpHeaders.IF_MATCH); if (ifMatch != null && !HttpUtil.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) { result = new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED); } else { - final ActionStatus action = checkAndLogDownload(requestResponseContextHolder.getHttpServletRequest(), + final ActionStatus action = checkAndLogDownload(RequestResponseContextHolder.getHttpServletRequest(), target, module.getId()); final Long statusId = action.getId(); result = FileStreamingUtil.writeFileResponse(file, artifact.getFilename(), artifact.getCreatedAt(), - requestResponseContextHolder.getHttpServletResponse(), - requestResponseContextHolder.getHttpServletRequest(), + RequestResponseContextHolder.getHttpServletResponse(), + RequestResponseContextHolder.getHttpServletRequest(), (length, shippedSinceLastEvent, total) -> eventPublisher.publishEvent(new DownloadProgressEvent( tenantAware.getCurrentTenant(), statusId, shippedSinceLastEvent, @@ -262,10 +259,10 @@ public class DdiRootController implements DdiRootControllerRestApi { final Artifact artifact = module.getArtifactByFilename(fileName) .orElseThrow(() -> new EntityNotFoundException(Artifact.class, fileName)); - checkAndLogDownload(requestResponseContextHolder.getHttpServletRequest(), target, module.getId()); + checkAndLogDownload(RequestResponseContextHolder.getHttpServletRequest(), target, module.getId()); try { - FileStreamingUtil.writeMD5FileResponse(requestResponseContextHolder.getHttpServletResponse(), + FileStreamingUtil.writeMD5FileResponse(RequestResponseContextHolder.getHttpServletResponse(), artifact.getMd5Hash(), fileName); } catch (final IOException e) { log.error("Failed to stream MD5 File", e); @@ -658,7 +655,7 @@ public class DdiRootController implements DdiRootControllerRestApi { private DdiDeployment generateDdiDeployment(final Target target, final Action action) { final List chunks = DataConversionHelper.createChunks(target, action, artifactUrlHandler, - systemManagement, new ServletServerHttpRequest(requestResponseContextHolder.getHttpServletRequest()), + systemManagement, new ServletServerHttpRequest(RequestResponseContextHolder.getHttpServletRequest()), controllerManagement); final HandlingType downloadType = calculateDownloadType(action); final HandlingType updateType = calculateUpdateType(action, downloadType); @@ -719,7 +716,7 @@ public class DdiRootController implements DdiRootControllerRestApi { public ResponseEntity getConfirmationBase(final String tenant, final String controllerId) { log.debug("getConfirmationBase is called [controllerId={}].", controllerId); final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotExist(controllerId, IpUtil - .getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(), securityProperties)); + .getClientIpFromRequest(RequestResponseContextHolder.getHttpServletRequest(), securityProperties)); final Action activeAction = controllerManagement.findActiveActionWithHighestWeight(controllerId).orElse(null); final DdiAutoConfirmationState autoConfirmationState = getAutoConfirmationState(controllerId); diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java index ef42b3021..9b35b8b9d 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java @@ -46,9 +46,6 @@ public class MgmtDownloadArtifactResource implements MgmtDownloadArtifactRestApi @Autowired private ArtifactManagement artifactManagement; - @Autowired - private RequestResponseContextHolder requestResponseContextHolder; - /** * Handles the GET request for downloading an artifact. * @@ -74,14 +71,13 @@ public class MgmtDownloadArtifactResource implements MgmtDownloadArtifactRestApi final DbArtifact file = artifactManagement .loadArtifactBinary(artifact.getSha1Hash(), module.getId(), module.isEncrypted()) .orElseThrow(() -> new ArtifactBinaryNotFoundException(artifact.getSha1Hash())); - final HttpServletRequest request = requestResponseContextHolder.getHttpServletRequest(); + final HttpServletRequest request = RequestResponseContextHolder.getHttpServletRequest(); final String ifMatch = request.getHeader(HttpHeaders.IF_MATCH); if (ifMatch != null && !HttpUtil.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) { return new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED); } return FileStreamingUtil.writeFileResponse(file, artifact.getFilename(), artifact.getCreatedAt(), - requestResponseContextHolder.getHttpServletResponse(), request, null); + RequestResponseContextHolder.getHttpServletResponse(), request, null); } - -} +} \ No newline at end of file diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadResource.java index ca79241fb..ff4ad83df 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadResource.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadResource.java @@ -39,13 +39,9 @@ public class MgmtDownloadResource implements MgmtDownloadRestApi { private final DownloadIdCache downloadIdCache; - private final RequestResponseContextHolder requestResponseContextHolder; - - MgmtDownloadResource(final ArtifactRepository artifactRepository, final DownloadIdCache downloadIdCache, - final RequestResponseContextHolder requestResponseContextHolder) { + MgmtDownloadResource(final ArtifactRepository artifactRepository, final DownloadIdCache downloadIdCache) { this.artifactRepository = artifactRepository; this.downloadIdCache = downloadIdCache; - this.requestResponseContextHolder = requestResponseContextHolder; } @Override @@ -77,8 +73,8 @@ public class MgmtDownloadResource implements MgmtDownloadRestApi { } return FileStreamingUtil.writeFileResponse(artifact, downloadId, 0L, - requestResponseContextHolder.getHttpServletResponse(), - requestResponseContextHolder.getHttpServletRequest(), null); + RequestResponseContextHolder.getHttpServletResponse(), + RequestResponseContextHolder.getHttpServletRequest(), null); } finally { downloadIdCache.evict(downloadId); diff --git a/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/RestConfiguration.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/RestConfiguration.java index e1531b269..4bb1ff6c0 100644 --- a/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/RestConfiguration.java +++ b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/RestConfiguration.java @@ -13,14 +13,9 @@ import jakarta.servlet.http.HttpServletResponse; import org.eclipse.hawkbit.rest.exception.ResponseExceptionHandler; import org.eclipse.hawkbit.rest.filter.ExcludePathAwareShallowETagFilter; -import org.eclipse.hawkbit.rest.util.FilterHttpResponse; -import org.eclipse.hawkbit.rest.util.HttpResponseFactoryBean; -import org.eclipse.hawkbit.rest.util.RequestResponseContextHolder; -import org.springframework.beans.factory.FactoryBean; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Scope; import org.springframework.hateoas.config.EnableHypermediaSupport; import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; import org.springframework.http.HttpStatus; @@ -34,31 +29,6 @@ import org.springframework.web.context.WebApplicationContext; @EnableHypermediaSupport(type = { HypermediaType.HAL }) public class RestConfiguration { - /** - * Create filter for {@link HttpServletResponse}. - */ - @Bean - FilterHttpResponse filterHttpResponse() { - return new FilterHttpResponse(); - } - - /** - * Create factory bean for {@link HttpServletResponse}. - */ - @Bean - FactoryBean httpResponseFactoryBean() { - return new HttpResponseFactoryBean(); - } - - /** - * Create factory bean for {@link HttpServletResponse}. - */ - @Bean - @Scope(value = WebApplicationContext.SCOPE_REQUEST) - RequestResponseContextHolder requestResponseContextHolder() { - return new RequestResponseContextHolder(); - } - /** * {@link ControllerAdvice} for mapping {@link RuntimeException}s from the * repository to {@link HttpStatus} codes. diff --git a/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FilterHttpResponse.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FilterHttpResponse.java deleted file mode 100644 index d5e0393cc..000000000 --- a/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FilterHttpResponse.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.rest.util; - -import java.io.IOException; - -import jakarta.servlet.Filter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.FilterConfig; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletResponse; - -/** - * Filter is needed to autowire the {@link HttpServletResponse}. - * - */ -public class FilterHttpResponse implements Filter { - - private ThreadLocal threadLocalResponse = new ThreadLocal<>(); - - @Override - public void init(final FilterConfig filterConfig) throws ServletException { - // not needed - } - - @Override - public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) - throws IOException, ServletException { - try { - threadLocalResponse.set((HttpServletResponse) response); - chain.doFilter(request, response); - } finally { - threadLocalResponse.remove(); - } - } - - public HttpServletResponse getHttpServletReponse() { - return threadLocalResponse.get(); - } - - @Override - public void destroy() { - threadLocalResponse = null; - } - -} diff --git a/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/HttpResponseFactoryBean.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/HttpResponseFactoryBean.java deleted file mode 100644 index 6dd5451a9..000000000 --- a/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/HttpResponseFactoryBean.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.rest.util; - -import jakarta.servlet.http.HttpServletResponse; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.NamedBean; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; - -/** - * - * Factory bean to autowire the {@link HttpServletResponse}. - * - */ -public class HttpResponseFactoryBean implements FactoryBean, ApplicationContextAware, NamedBean { - - public static final String FACTORY_BEAN_NAME = "httpResponseFactoryBean"; - - private ApplicationContext applicationContext; - - @Override - public HttpServletResponse getObject() { - return applicationContext.getBean(FilterHttpResponse.class).getHttpServletReponse(); - } - - @Override - public Class getObjectType() { - return HttpServletResponse.class; - } - - @Override - public boolean isSingleton() { - return false; - } - - @Override - public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - - @Override - public String getBeanName() { - return FACTORY_BEAN_NAME; - } - -} diff --git a/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/RequestResponseContextHolder.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/RequestResponseContextHolder.java index 23a8808f7..898a89ab3 100644 --- a/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/RequestResponseContextHolder.java +++ b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/RequestResponseContextHolder.java @@ -9,36 +9,32 @@ */ package org.eclipse.hawkbit.rest.util; -import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.util.Objects; /** - * Store the request and response for the rest resources. + * Gives access to the request and response for the rest resources. */ public class RequestResponseContextHolder { - private HttpServletRequest httpServletRequest; - - private HttpServletResponse httpServletResponse; - - public HttpServletRequest getHttpServletRequest() { - return httpServletRequest; + public static HttpServletRequest getHttpServletRequest() { + return Objects + .requireNonNull( + (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(), + "Request attribute is unavailable") + .getRequest(); } - public HttpServletResponse getHttpServletResponse() { - return httpServletResponse; + public static HttpServletResponse getHttpServletResponse() { + return Objects + .requireNonNull( + (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(), + "Request attribute is unavailable") + .getResponse(); } - - @Autowired - public void setHttpServletRequest(final HttpServletRequest httpServletRequest) { - this.httpServletRequest = httpServletRequest; - } - - @Resource(name = HttpResponseFactoryBean.FACTORY_BEAN_NAME) - public void setHttpServletResponse(final HttpServletResponse httpServletResponse) { - this.httpServletResponse = httpServletResponse; - } -} +} \ No newline at end of file diff --git a/hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/AbstractRestIntegrationTest.java b/hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/AbstractRestIntegrationTest.java index 375d0651c..bb3439468 100644 --- a/hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/AbstractRestIntegrationTest.java +++ b/hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/AbstractRestIntegrationTest.java @@ -13,7 +13,6 @@ import org.eclipse.hawkbit.repository.jpa.RepositoryApplicationConfiguration; import org.eclipse.hawkbit.repository.test.TestConfiguration; import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest; import org.eclipse.hawkbit.rest.filter.ExcludePathAwareShallowETagFilter; -import org.eclipse.hawkbit.rest.util.FilterHttpResponse; import org.junit.jupiter.api.BeforeEach; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -31,17 +30,14 @@ import org.springframework.web.filter.CharacterEncodingFilter; * Abstract Test for Rest tests. */ @WebAppConfiguration -@ContextConfiguration(classes = { RestConfiguration.class, RepositoryApplicationConfiguration.class, - TestConfiguration.class}) +@ContextConfiguration(classes = { + RestConfiguration.class, RepositoryApplicationConfiguration.class, TestConfiguration.class}) @Import(TestChannelBinderConfiguration.class) @AutoConfigureMockMvc public abstract class AbstractRestIntegrationTest extends AbstractIntegrationTest { protected MockMvc mvc; - @Autowired - private FilterHttpResponse filterHttpResponse; - @Autowired private CharacterEncodingFilter characterEncodingFilter; @@ -62,7 +58,6 @@ public abstract class AbstractRestIntegrationTest extends AbstractIntegrationTes new ExcludePathAwareShallowETagFilter("/rest/v1/softwaremodules/{smId}/artifacts/{artId}/download", "/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/**", "/api/v1/downloadserver/**")); - createMvcWebAppContext.addFilter(filterHttpResponse); return createMvcWebAppContext; } diff --git a/hawkbit-runtime/hawkbit-ddi-server/src/test/java/org/eclipse/hawkbit/app/ddi/AbstractSecurityTest.java b/hawkbit-runtime/hawkbit-ddi-server/src/test/java/org/eclipse/hawkbit/app/ddi/AbstractSecurityTest.java index 89b83b974..04b2934ef 100644 --- a/hawkbit-runtime/hawkbit-ddi-server/src/test/java/org/eclipse/hawkbit/app/ddi/AbstractSecurityTest.java +++ b/hawkbit-runtime/hawkbit-ddi-server/src/test/java/org/eclipse/hawkbit/app/ddi/AbstractSecurityTest.java @@ -10,7 +10,6 @@ package org.eclipse.hawkbit.app.ddi; import org.eclipse.hawkbit.repository.test.util.SharedSqlTestDatabaseExtension; -import org.eclipse.hawkbit.rest.util.FilterHttpResponse; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -27,8 +26,6 @@ public abstract class AbstractSecurityTest { @Autowired private WebApplicationContext context; - @Autowired - private FilterHttpResponse filterHttpResponse; protected MockMvc mvc; @@ -36,7 +33,6 @@ public abstract class AbstractSecurityTest { public void setup() { final DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(context) .apply(SecurityMockMvcConfigurers.springSecurity()).dispatchOptions(true); - builder.addFilter(filterHttpResponse); mvc = builder.build(); } }