use of org.haiku.haikudepotserver.pkg.model.BadPkgScreenshotException in project haikudepotserver by haiku.
the class PkgScreenshotController method handleAdd.
/**
* <p>This handler will take-up an HTTP POST that provides a new screenshot for the package.</p>
*/
@RequestMapping(value = "/{" + KEY_PKGNAME + "}/add", method = RequestMethod.POST)
public void handleAdd(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = KEY_FORMAT) String format, @PathVariable(value = KEY_PKGNAME) String pkgName) throws IOException {
if (Strings.isNullOrEmpty(pkgName) || !Pkg.PATTERN_NAME.matcher(pkgName).matches()) {
throw new MissingPkgName();
}
if (Strings.isNullOrEmpty(format) || !"png".equals(format)) {
throw new MissingOrBadFormat();
}
ObjectContext context = serverRuntime.newContext();
Pkg pkg = Pkg.tryGetByName(context, pkgName).orElseThrow(PkgNotFound::new);
// check the authorization
Optional<User> user = tryObtainAuthenticatedUser(context);
if (!permissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(), pkg, Permission.PKG_EDITSCREENSHOT)) {
LOGGER.warn("attempt to add a pkg screenshot, but there is no user present or that user is not able to edit the pkg");
throw new PkgAuthorizationFailure();
}
String screenshotCode;
try {
screenshotCode = pkgScreenshotService.storePkgScreenshotImage(request.getInputStream(), context, pkg.getPkgSupplement(), null).getCode();
} catch (SizeLimitReachedException sizeLimit) {
LOGGER.warn("attempt to load in a screenshot larger than the size limit");
throw new MissingOrBadFormat();
} catch (BadPkgScreenshotException badIcon) {
throw new MissingOrBadFormat();
}
context.commitChanges();
// trigger optimization of the screenshot image.
jobService.submit(new PkgScreenshotOptimizationJobSpecification(screenshotCode), JobSnapshot.COALESCE_STATUSES_QUEUED_STARTED);
response.setHeader(HEADER_SCREENSHOTCODE, screenshotCode);
response.setStatus(HttpServletResponse.SC_OK);
}
use of org.haiku.haikudepotserver.pkg.model.BadPkgScreenshotException in project haikudepotserver by haiku.
the class PkgScreenshotOptimizationJobRunner method run.
@Override
public void run(JobService jobService, PkgScreenshotOptimizationJobSpecification specification) throws JobRunnerException {
Preconditions.checkArgument(null != jobService);
Preconditions.checkArgument(null != specification);
long startMs = System.currentTimeMillis();
LOGGER.info("will optimize {} screenshot images", specification.getPkgScreenshotCodes().size());
for (String pkgScreenshotCode : specification.getPkgScreenshotCodes()) {
ObjectContext context = serverRuntime.newContext();
Optional<PkgScreenshot> pkgScreenshotOptional = PkgScreenshot.tryGetByCode(context, pkgScreenshotCode);
if (pkgScreenshotOptional.isPresent()) {
try {
if (screenshotService.optimizeScreenshot(context, pkgScreenshotOptional.get())) {
context.commitChanges();
}
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
} catch (BadPkgScreenshotException bpse) {
throw new JobRunnerException("unable to process a screenshot image", bpse);
}
}
LOGGER.info("did optimize {} screenshot images in {}ms", specification.getPkgScreenshotCodes().size(), System.currentTimeMillis() - startMs);
}
}
use of org.haiku.haikudepotserver.pkg.model.BadPkgScreenshotException in project haikudepotserver by haiku.
the class PkgScreenshotServiceImpl method storePkgScreenshotImage.
/**
* <p>Note that if the screenshot is already stored then this method will simply return that screenshot.</p>
*
* @param ordering can be NULL; in which case the screenshot will come at the end.
*/
@Override
public PkgScreenshot storePkgScreenshotImage(InputStream input, ObjectContext context, PkgSupplement pkgSupplement, Integer ordering) throws IOException, BadPkgScreenshotException {
Preconditions.checkArgument(null != input, "the input must be provided");
Preconditions.checkArgument(null != context, "the context must be provided");
Preconditions.checkArgument(null != pkgSupplement, "the pkg supplement must be provided");
byte[] pngData = ByteStreams.toByteArray(new BoundedInputStream(input, SCREENSHOT_SIZE_LIMIT));
ImageHelper.Size size = imageHelper.derivePngSize(pngData);
String hashSha256 = HASH_FUNCTION.hashBytes(pngData).toString();
if (null == size) {
LOGGER.warn("attempt to store a screenshot image that is not a png");
throw new BadPkgScreenshotException();
}
if (size.height > SCREENSHOT_SIDE_LIMIT || size.width > SCREENSHOT_SIDE_LIMIT) {
LOGGER.warn("attempt to store a screenshot image that is too large; " + size.toString());
throw new BadPkgScreenshotException();
}
for (PkgScreenshot pkgScreenshot : pkgSupplement.getPkgScreenshots()) {
if (pkgScreenshot.getHashSha256().equals(hashSha256)) {
LOGGER.warn("attempt to store a screenshot image that is already stored for this package");
return pkgScreenshot;
}
}
MediaType png = MediaType.tryGetByCode(context, com.google.common.net.MediaType.PNG.toString()).get();
// now we need to know the largest ordering so we can add this one at the end of the orderings
// such that it is the next one in the list.
int actualOrdering = null == ordering ? pkgSupplement.getHighestPkgScreenshotOrdering().orElse(0) + 1 : ordering;
PkgScreenshot screenshot = context.newObject(PkgScreenshot.class);
screenshot.setCode(UUID.randomUUID().toString());
screenshot.setOrdering(actualOrdering);
screenshot.setHeight(size.height);
screenshot.setWidth(size.width);
screenshot.setLength(pngData.length);
screenshot.setHashSha256(hashSha256);
pkgSupplement.addToManyTarget(PkgSupplement.PKG_SCREENSHOTS.getName(), screenshot, true);
PkgScreenshotImage screenshotImage = context.newObject(PkgScreenshotImage.class);
screenshotImage.setMediaType(png);
screenshotImage.setData(pngData);
screenshot.addToManyTarget(PkgScreenshot.PKG_SCREENSHOT_IMAGES.getName(), screenshotImage, true);
pkgSupplement.setModifyTimestamp();
LOGGER.info("a screenshot #{} has been added to package [{}] ({})", actualOrdering, pkgSupplement.getBasePkgName(), screenshot.getCode());
return screenshot;
}
use of org.haiku.haikudepotserver.pkg.model.BadPkgScreenshotException in project haikudepotserver by haiku.
the class PkgScreenshotImportArchiveJobRunner method importScreenshotsFromArchiveAndReport.
/**
* <p>If this screenshot coming in from the archive does not exist persisted then load it in.</p>
*/
private void importScreenshotsFromArchiveAndReport(CSVWriter writer, ScreenshotImportMetadatas data, ArchiveInputStream archiveInputStream, ArchiveEntry archiveEntry, String pkgName, int order) {
String[] row = { // path
archiveEntry.getName(), // pkg
pkgName, // action
"", // message
"", // code
"" };
if (data.isNotFound()) {
row[CSV_COLUMN_ACTION] = Action.NOTFOUND.name();
} else {
FromArchiveScreenshotMetadata fromArchiveScreenshotMetadata = data.getFromArchiveScreenshots().stream().filter((as) -> as.getLength() == archiveEntry.getSize()).filter((as) -> as.getOrder() == order).findAny().orElseThrow(() -> new IllegalStateException("unable to find the from-archive screenshot metadata"));
Optional<ExistingScreenshotMetadata> existingScreenshotMetadata = data.getExistingScreenshots().stream().filter((es) -> archiveEntry.getSize() == es.getLength()).filter((es) -> fromArchiveScreenshotMetadata.getDataHash().equals(es.getDataHash())).findAny();
if (existingScreenshotMetadata.isPresent()) {
row[CSV_COLUMN_ACTION] = Action.PRESENT.name();
row[CSV_COLUMN_CODE] = existingScreenshotMetadata.get().getCode();
} else {
ObjectContext context = serverRuntime.newContext();
try {
PkgScreenshot screenshot = pkgScreenshotService.storePkgScreenshotImage(archiveInputStream, context, Pkg.getByName(context, pkgName).getPkgSupplement(), fromArchiveScreenshotMetadata.getDerivedOrder());
row[CSV_COLUMN_CODE] = screenshot.getCode();
row[CSV_COLUMN_ACTION] = Action.ADDED.name();
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
} catch (BadPkgScreenshotException e) {
row[CSV_COLUMN_ACTION] = Action.INVALID.name();
row[CSV_COLUMN_MESSAGE] = e.getMessage();
}
context.commitChanges();
}
}
writer.writeNext(row);
}
Aggregations