// Bucket error?
throw new FetchException(FetchExceptionMode.BUCKET_ERROR, e);
}
} else {
final boolean persistent = this.persistent;
fetchArchive(false, archiveMetadata, ArchiveManager.METADATA_NAME, new ArchiveExtractCallback() {
private static final long serialVersionUID = 1L;
@Override
public void gotBucket(Bucket data, ClientContext context) {
if(logMINOR) Logger.minor(this, "gotBucket on "+SingleFileFetcher.this+" persistent="+persistent);
try {
metadata = Metadata.construct(data);
data.free();
innerWrapHandleMetadata(true, context);
} catch (MetadataParseException e) {
// Invalid metadata
onFailure(new FetchException(FetchExceptionMode.INVALID_METADATA, e), false, context);
return;
} catch (IOException e) {
// Bucket error?
onFailure(new FetchException(FetchExceptionMode.BUCKET_ERROR, e), false, context);
return;
}
}
@Override
public void notInArchive(ClientContext context) {
onFailure(new FetchException(FetchExceptionMode.INTERNAL_ERROR, "No metadata in container! Cannot happen as ArchiveManager should synthesise some!"), false, context);
}
@Override
public void onFailed(ArchiveRestartException e, ClientContext context) {
SingleFileFetcher.this.onFailure(new FetchException(e), false, context);
}
@Override
public void onFailed(ArchiveFailureException e, ClientContext context) {
SingleFileFetcher.this.onFailure(new FetchException(e), false, context);
}
}, context); // will result in this function being called again
return;
}
metadataBucket.free();
continue;
} else if(metadata.isArchiveMetadataRedirect()) {
if(logMINOR) Logger.minor(this, "Is archive-metadata");
// Fetch it from the archive
if(ah == null)
throw new FetchException(FetchExceptionMode.UNKNOWN_METADATA, "Archive redirect not in an archive manifest");
String filename = metadata.getArchiveInternalName();
if(logMINOR) Logger.minor(this, "Fetching "+filename);
Bucket dataBucket = ah.get(filename, actx, context.archiveManager);
if(dataBucket != null) {
if(logMINOR) Logger.minor(this, "Returning data");
final Metadata newMetadata;
try {
newMetadata = Metadata.construct(dataBucket);
dataBucket.free();
} catch (InsufficientDiskSpaceException e) {
throw new FetchException(FetchExceptionMode.NOT_ENOUGH_DISK_SPACE);
} catch (IOException e) {
throw new FetchException(FetchExceptionMode.BUCKET_ERROR);
}
synchronized(this) {
metadata = newMetadata;
}
continue;
} else {
if(logMINOR) Logger.minor(this, "Fetching archive (thisKey="+thisKey+ ')');
// Metadata cannot contain pointers to files which don't exist.
// We enforce this in ArchiveHandler.
// Therefore, the archive needs to be fetched.
final boolean persistent = this.persistent;
fetchArchive(true, archiveMetadata, filename, new ArchiveExtractCallback() {
private static final long serialVersionUID = 1L;
@Override
public void gotBucket(Bucket data, ClientContext context) {
if(logMINOR) Logger.minor(this, "Returning data");
final Metadata newMetadata;
try {
newMetadata = Metadata.construct(data);
synchronized(SingleFileFetcher.this) {
metadata = newMetadata;
}
innerWrapHandleMetadata(true, context);
} catch (IOException e) {
onFailure(new FetchException(FetchExceptionMode.BUCKET_ERROR), false, context);
} catch (MetadataParseException e) {
onFailure(new FetchException(FetchExceptionMode.INVALID_METADATA), false, context);
} finally {
data.free();
}
}
@Override
public void notInArchive(ClientContext context) {
onFailure(new FetchException(FetchExceptionMode.NOT_IN_ARCHIVE), false, context);
}
@Override
public void onFailed(ArchiveRestartException e, ClientContext context) {
SingleFileFetcher.this.onFailure(new FetchException(e), false, context);
}
@Override
public void onFailed(ArchiveFailureException e, ClientContext context) {
SingleFileFetcher.this.onFailure(new FetchException(e), false, context);
}
}, context);
// Will call back into this function when it has been fetched.
return;
}
} else if(metadata.isArchiveInternalRedirect()) {
if(logMINOR) Logger.minor(this, "Is archive-internal redirect");
clientMetadata.mergeNoOverwrite(metadata.getClientMetadata());
String mime = clientMetadata.getMIMEType();
if(mime != null) rcb.onExpectedMIME(clientMetadata, context);
if(metaStrings.isEmpty() && isFinal && clientMetadata.getMIMETypeNoParams() != null && ctx.allowedMIMETypes != null &&
!ctx.allowedMIMETypes.contains(clientMetadata.getMIMETypeNoParams())) {
throw new FetchException(FetchExceptionMode.WRONG_MIME_TYPE, -1, false, clientMetadata.getMIMEType());
}
// Fetch it from the archive
if(ah == null)
throw new FetchException(FetchExceptionMode.UNKNOWN_METADATA, "Archive redirect not in an archive manifest");
String filename = metadata.getArchiveInternalName();
if(logMINOR) Logger.minor(this, "Fetching "+filename);
Bucket dataBucket = ah.get(filename, actx, context.archiveManager);
if(dataBucket != null) {
if(logMINOR) Logger.minor(this, "Returning data");
final Bucket out;
try {
// Data will not be freed until client is finished with it.
if(persistent) {
out = context.persistentBucketFactory.makeBucket(dataBucket.size());
BucketTools.copy(dataBucket, out);
dataBucket.free();
} else {
out = dataBucket;
}
} catch (InsufficientDiskSpaceException e) {
throw new FetchException(FetchExceptionMode.NOT_ENOUGH_DISK_SPACE);
} catch (IOException e) {
throw new FetchException(FetchExceptionMode.BUCKET_ERROR);
}
// Return the data
onSuccess(new FetchResult(clientMetadata, out), context);
return;
} else {
if(logMINOR) Logger.minor(this, "Fetching archive (thisKey="+thisKey+ ')');
// Metadata cannot contain pointers to files which don't exist.
// We enforce this in ArchiveHandler.
// Therefore, the archive needs to be fetched.
final boolean persistent = this.persistent;
fetchArchive(true, archiveMetadata, filename, new ArchiveExtractCallback() {
private static final long serialVersionUID = 1L;
@Override
public void gotBucket(Bucket data, ClientContext context) {
if(logMINOR) Logger.minor(this, "Returning data");
// Because this will be processed immediately, and because the callback uses a StreamGenerator,