Cleanup file streaming utilities (#559)

* Cleanup file streaming.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Added missing comments.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Fix typo.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Split utility class.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Dependency cleanup.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Add missing dependency,

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Remove repository api dependency from rest core.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Fix build and sonar issues.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Remove custom ConstraintViolationException

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* RequestMapping should be public.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Fix errors.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Removed dead code.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Not null

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Fix nullpointer.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Code cleanup.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
Kai Zimmermann
2017-07-19 12:43:07 +02:00
committed by GitHub
parent 66feae2756
commit 09b24fa97d
59 changed files with 911 additions and 908 deletions

View File

@@ -12,7 +12,7 @@ import java.io.InputStream;
import javax.servlet.http.HttpServletRequest;
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDownloadArtifactRestApi;
import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
@@ -20,14 +20,17 @@ import org.eclipse.hawkbit.repository.exception.ArtifactBinaryNotFoundException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.rest.util.FileStreamingUtil;
import org.eclipse.hawkbit.rest.util.HttpUtil;
import org.eclipse.hawkbit.rest.util.RequestResponseContextHolder;
import org.eclipse.hawkbit.rest.util.RestResourceConversionHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
@@ -37,7 +40,6 @@ import org.springframework.web.context.WebApplicationContext;
@RestController
@Scope(value = WebApplicationContext.SCOPE_REQUEST)
public class MgmtDownloadArtifactResource implements MgmtDownloadArtifactRestApi {
@Autowired
private SoftwareModuleManagement softwareModuleManagement;
@@ -58,25 +60,25 @@ public class MgmtDownloadArtifactResource implements MgmtDownloadArtifactRestApi
* @return responseEntity with status ok if successful
*/
@Override
@ResponseBody
public ResponseEntity<InputStream> downloadArtifact(@PathVariable("softwareModuleId") final Long softwareModuleId,
@PathVariable("artifactId") final Long artifactId) {
final SoftwareModule module = softwareModuleManagement.findSoftwareModuleById(softwareModuleId)
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId));
final Artifact artifact = module.getArtifact(artifactId)
.orElseThrow(() -> new EntityNotFoundException(Artifact.class, artifactId));
final DbArtifact file = artifactManagement.loadArtifactBinary(artifact.getSha1Hash())
final AbstractDbArtifact file = artifactManagement.loadArtifactBinary(artifact.getSha1Hash())
.orElseThrow(() -> new ArtifactBinaryNotFoundException(artifact.getSha1Hash()));
final HttpServletRequest request = requestResponseContextHolder.getHttpServletRequest();
final String ifMatch = request.getHeader("If-Match");
if (ifMatch != null && !RestResourceConversionHelper.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) {
final String ifMatch = request.getHeader(HttpHeaders.IF_MATCH);
if (ifMatch != null && !HttpUtil.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) {
return new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED);
}
return RestResourceConversionHelper.writeFileResponse(artifact,
requestResponseContextHolder.getHttpServletResponse(), request, file);
return FileStreamingUtil.writeFileResponse(file, artifact.getFilename(),
artifact.getLastModifiedAt() != null ? artifact.getLastModifiedAt() : artifact.getCreatedAt(),
requestResponseContextHolder.getHttpServletResponse(), request, null);
}
}

View File

@@ -8,33 +8,26 @@
*/
package org.eclipse.hawkbit.mgmt.rest.resource;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.hawkbit.artifact.repository.ArtifactRepository;
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact;
import org.eclipse.hawkbit.cache.DownloadArtifactCache;
import org.eclipse.hawkbit.cache.DownloadIdCache;
import org.eclipse.hawkbit.cache.DownloadType;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDownloadRestApi;
import org.eclipse.hawkbit.rest.util.FileStreamingUtil;
import org.eclipse.hawkbit.rest.util.RequestResponseContextHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import com.google.common.io.ByteStreams;
import com.google.common.net.HttpHeaders;
/**
* A resource for download artifacts.
*/
@@ -55,8 +48,9 @@ public class MgmtDownloadResource implements MgmtDownloadRestApi {
@Override
@ResponseBody
public ResponseEntity<Void> downloadArtifactByDownloadId(@PathVariable("tenant") final String tenant,
public ResponseEntity<InputStream> downloadArtifactByDownloadId(@PathVariable("tenant") final String tenant,
@PathVariable("downloadId") final String downloadId) {
try {
final DownloadArtifactCache artifactCache = downloadIdCache.get(downloadId);
if (artifactCache == null) {
@@ -64,7 +58,7 @@ public class MgmtDownloadResource implements MgmtDownloadRestApi {
return ResponseEntity.notFound().build();
}
DbArtifact artifact = null;
AbstractDbArtifact artifact = null;
if (DownloadType.BY_SHA1.equals(artifactCache.getDownloadType())) {
artifact = artifactRepository.getArtifactBySha1(tenant, artifactCache.getId());
@@ -78,24 +72,12 @@ public class MgmtDownloadResource implements MgmtDownloadRestApi {
return ResponseEntity.notFound().build();
}
final HttpServletResponse response = requestResponseContextHolder.getHttpServletResponse();
final String etag = artifact.getHashes().getSha1();
final long length = artifact.getSize();
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + downloadId);
response.setHeader(HttpHeaders.ETAG, etag);
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setContentLengthLong(length);
return FileStreamingUtil.writeFileResponse(artifact, downloadId, null,
requestResponseContextHolder.getHttpServletResponse(),
requestResponseContextHolder.getHttpServletRequest(), null);
try (InputStream inputstream = artifact.getFileInputStream()) {
ByteStreams.copy(inputstream, requestResponseContextHolder.getHttpServletResponse().getOutputStream());
} catch (final IOException e) {
LOGGER.error("Cannot copy streams", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
} finally {
downloadIdCache.evict(downloadId);
}
return ResponseEntity.ok().build();
}
}

View File

@@ -11,6 +11,8 @@ package org.eclipse.hawkbit.mgmt.rest.resource;
import java.util.List;
import java.util.stream.Collectors;
import javax.validation.ValidationException;
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutResponseBody;
import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutRestRequestBody;
@@ -26,7 +28,6 @@ import org.eclipse.hawkbit.repository.RolloutManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.builder.RolloutCreate;
import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate;
import org.eclipse.hawkbit.repository.exception.ConstraintViolationException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Rollout;
@@ -122,7 +123,7 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi {
rolloutGroupConditions);
} else {
throw new ConstraintViolationException("Either 'amountGroups' or 'groups' must be defined in the request");
throw new ValidationException("Either 'amountGroups' or 'groups' must be defined in the request");
}
return ResponseEntity.status(HttpStatus.CREATED).body(MgmtRolloutMapper.toResponseRollout(rollout, true));

View File

@@ -13,6 +13,8 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.validation.ValidationException;
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
import org.eclipse.hawkbit.mgmt.json.model.action.MgmtAction;
import org.eclipse.hawkbit.mgmt.json.model.action.MgmtActionRequestBodyPut;
@@ -29,7 +31,6 @@ import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.exception.ConstraintViolationException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
@@ -293,7 +294,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
}
if (!MgmtActionType.FORCED.equals(actionUpdate.getForceType())) {
throw new ConstraintViolationException("Resource supports only switch to FORCED.");
throw new ValidationException("Resource supports only switch to FORCED.");
}
action = deploymentManagement.forceTargetAction(actionId);

View File

@@ -32,12 +32,13 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.validation.ConstraintViolationException;
import org.apache.commons.lang3.RandomStringUtils;
import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.ActionFields;
import org.eclipse.hawkbit.repository.exception.ConstraintViolationException;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType;