use of org.sagebionetworks.bridge.exceptions.BridgeServiceException in project BridgeServer2 by Sage-Bionetworks.
the class UploadArchiveService method unzip.
/**
* <p>
* Unzips the given stream. For each individual zip entry, this method will call entryNameToOutputStream, passing
* in the zip entry file name and expecting an OutputStream in which to write the unzipped bytes. It will then call
* outputStreamFinalizer, allowing the caller to finalize the stream, for example, closing the stream.
* </p>
* <p>
* The caller is responsible for closing any and all streams involved.
* </p>
*
* @param source
* input stream of zipped data to unzip
* @param entryNameToOutpuStream
* arg is the zip entry file name, return value is the OutputStream in which to write the unzipped bytes
* @param outputStreamFinalizer
* args are the zip entry file name and the corresponding OutputStream returned by entryNameToOutputStream;
* this is where you finalize the stream, eg closing the stream
*/
public void unzip(InputStream source, Function<String, OutputStream> entryNameToOutpuStream, BiConsumer<String, OutputStream> outputStreamFinalizer) {
// Validate input
checkNotNull(source);
checkNotNull(entryNameToOutpuStream);
checkNotNull(outputStreamFinalizer);
// Unzip
Set<String> zipEntryNameSet = new HashSet<>();
try (ZipInputStream zis = new ZipInputStream(source)) {
ZipEntry zipEntry = zis.getNextEntry();
while (zipEntry != null) {
if (zipEntryNameSet.size() >= maxNumZipEntries) {
throw new ZipOverflowException("The number of zip entries is over the max allowed");
}
final String entryName = zipEntry.getName();
if (zipEntryNameSet.contains(entryName)) {
throw new DuplicateZipEntryException("Duplicate filename " + entryName);
}
final long entrySize = zipEntry.getSize();
if (entrySize > maxZipEntrySize) {
throw new ZipOverflowException("Zip entry size is over the max allowed size. The entry " + entryName + " has size " + entrySize + ". The max allowed size is" + maxZipEntrySize + ".");
}
zipEntryNameSet.add(entryName);
OutputStream outputStream = entryNameToOutpuStream.apply(entryName);
toByteArray(entryName, zis, outputStream);
outputStreamFinalizer.accept(entryName, outputStream);
zipEntry = zis.getNextEntry();
}
} catch (DuplicateZipEntryException | ZipOverflowException ex) {
throw new BadRequestException(ex);
} catch (IOException ex) {
throw new BridgeServiceException(ex);
}
}
use of org.sagebionetworks.bridge.exceptions.BridgeServiceException in project BridgeServer2 by Sage-Bionetworks.
the class UploadArchiveService method decrypt.
/**
* Decrypts the specified data stream, using the encryption materials for the specified app, and returns the a
* stream of decrypted data. The caller is responsible for closing both streams.
*/
public InputStream decrypt(String appId, InputStream source) {
// validate
checkNotNull(appId);
checkArgument(StringUtils.isNotBlank(appId));
checkNotNull(source);
// get encryptor from cache
CmsEncryptor encryptor = getEncryptorForApp(appId);
// decrypt
try {
return encryptor.decrypt(source);
} catch (CertificateEncodingException | CMSException | IOException ex) {
throw new BridgeServiceException(ex);
}
}
use of org.sagebionetworks.bridge.exceptions.BridgeServiceException in project BridgeServer2 by Sage-Bionetworks.
the class UploadCertificateService method createCmsKeyPair.
/**
* Creates a CMS key pair for a particular app and save it in permanent storage.
*/
public void createCmsKeyPair(final String appId) {
checkNotNull(appId);
String pemFilename = getPemFilename(appId);
if (!s3CmsClient.doesObjectExist(PRIVATE_KEY_BUCKET, pemFilename) || !s3CmsClient.doesObjectExist(CERT_BUCKET, pemFilename)) {
final KeyPair keyPair = KeyPairFactory.newRsa2048();
final CertificateInfo certInfo = new CertificateInfo.Builder().country(CONFIG.getProperty("upload.cms.certificate.country")).state(CONFIG.getProperty("upload.cms.certificate.state")).city(CONFIG.getProperty("upload.cms.certificate.city")).organization(CONFIG.getProperty("upload.cms.certificate.organization")).team(CONFIG.getProperty("upload.cms.certificate.team")).email(CONFIG.getProperty("upload.cms.certificate.email")).fqdn(CONFIG.getWebservicesURL()).build();
final X509Certificate cert = certificateFactory.newCertificate(keyPair, certInfo);
try {
s3Put(PRIVATE_KEY_BUCKET, pemFilename, PemUtils.toPem(keyPair.getPrivate()));
s3Put(CERT_BUCKET, pemFilename, PemUtils.toPem(cert));
} catch (CertificateEncodingException e) {
throw new BridgeServiceException(e);
}
}
}
use of org.sagebionetworks.bridge.exceptions.BridgeServiceException in project BridgeServer2 by Sage-Bionetworks.
the class UploadService method uploadComplete.
public void uploadComplete(String appId, UploadCompletionClient completedBy, Upload upload, boolean redrive) {
String uploadId = upload.getUploadId();
// We don't want to kick off upload validation on an upload that already has upload validation.
if (!upload.canBeValidated() && !redrive) {
logger.info(String.format("uploadComplete called for upload %s, which is already complete", uploadId));
return;
}
final String objectId = upload.getObjectId();
ObjectMetadata obj;
try {
Stopwatch stopwatch = Stopwatch.createStarted();
obj = s3Client.getObjectMetadata(uploadBucket, objectId);
logger.info("Finished getting S3 metadata for bucket " + uploadBucket + " key " + objectId + " in " + stopwatch.elapsed(TimeUnit.MILLISECONDS) + " ms");
} catch (AmazonS3Exception ex) {
if (ex.getStatusCode() == 404) {
throw new NotFoundException(ex);
} else {
// Only S3 404s are mapped to 404s. Everything else is an internal server error.
throw new BridgeServiceException(ex);
}
}
String sse = obj.getSSEAlgorithm();
if (!AES_256_SERVER_SIDE_ENCRYPTION.equals(sse)) {
logger.error("Missing S3 server-side encryption (SSE) for presigned upload " + uploadId + ".");
}
try {
uploadDao.uploadComplete(completedBy, upload);
} catch (ConcurrentModificationException ex) {
// The old workflow is the app calls uploadComplete. The new workflow has an S3 trigger to call
// uploadComplete. During the transition, it's very likely that this will be called twice, sometimes
// concurrently. As such, we should log and squelch the ConcurrentModificationException.
logger.info("Concurrent modification of upload " + uploadId + " while marking upload complete");
// and duplicate records.
return;
}
// kick off upload validation
App app = appService.getApp(appId);
if (BridgeUtils.isExporter3Configured(app)) {
exporter3Service.completeUpload(app, upload);
}
// For backwards compatibility, always call Legacy Exporter 2.0. In the future, we may introduce a setting to
// disable this for new apps.
uploadValidationService.validateUpload(appId, upload);
}
use of org.sagebionetworks.bridge.exceptions.BridgeServiceException in project BridgeServer2 by Sage-Bionetworks.
the class UploadService method pollUploadValidationStatusUntilComplete.
/**
* Polls for validation status for a given upload ID. Polls until validation is complete or otherwise is in a state
* where further polling won't get any results (like validation failed, or upload is requested but not yet
* uploaded), or until it times out. See getUploadValidationStatus() for more details.
*/
public UploadValidationStatus pollUploadValidationStatusUntilComplete(String uploadId) {
// Loop logic is a little wonky. (Loop-and-a-half problem.) Use an infinite loop here and rely on tests to make
// sure we don't go infinite.
int numIters = 0;
while (true) {
UploadValidationStatus validationStatus = getUploadValidationStatus(uploadId);
if (validationStatus.getStatus() != UploadStatus.VALIDATION_IN_PROGRESS) {
// Return the answer we have now.
return validationStatus;
}
// Short-circuit: If we've elapsed our timeout, just exit now. Don't wait for a sleep.
numIters++;
if (numIters >= pollValidationStatusMaxIterations) {
throw new BridgeServiceException("Timeout polling validation status for upload " + uploadId);
}
// Sleep and try again.
try {
Thread.sleep(pollValidationStatusSleepMillis);
} catch (InterruptedException ex) {
logger.error("Interrupted while polling for validation status: " + ex.getMessage());
}
}
}
Aggregations