public Result execute(ResourceDescriptor descriptor,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
Result result = Result.UNSUPPORTED;
NoCloseSeekableInputStream inputStream = null;
NoCloseSeekableInputStream watermarkStream = null;
NoFlushSeekableOutputStream outputData = null;
final String resourceType = descriptor.getResourceType();
if ("image".equals(resourceType) || resourceType.startsWith("image.")) {
try {
synchronized(lock) {
if (config == null) {
config = createConfiguration();
}
}
// merge the parameters in the ICS request with those in the
// configuration file.
ICSParamBuilder icsBuilder = new ICSParamBuilder();
icsBuilder.overlayConfigurationParameters(
descriptor.getInputParameters(), config);
icsBuilder.overlayEnvironmentParameters(
descriptor.getInputParameters(), envParams);
// @todo perform check for supported operation type here.
ImageProcessor processor =
ImageProcessorFactory.getInstance().
createImageProcessor(ToolFactory.getInstance(),
ImageWriterFactory.getInstance());
Representation representation =
ImageLoader.load(descriptor.getInputParameters().getParameterValue(ParameterNames.SOURCE_URL),
retriever, request, descriptor);
inputStream = new NoCloseSeekableInputStream(representation.getSeekableInputStream());
new PreservationParamsBuilder().process(request, descriptor);
// now get the input stream for the watermark image.
// @todo later this could probably be cached.
if (descriptor.getInputParameters().containsName(
ParameterNames.WATERMARK_URL)) {
Representation watermarkRepresentation =
ImageLoader.load(descriptor.getInputParameters().getParameterValue(ParameterNames.WATERMARK_URL),
retriever, request, descriptor);
watermarkStream =
new NoCloseSeekableInputStream(watermarkRepresentation.getSeekableInputStream());
descriptor.getInputParameters().setObject(
ParameterNames.WATERMARK_INPUT_STREAM, watermarkStream);
}
outputData =
new NoFlushSeekableOutputStream(response.getOutputStream());
processor.process(new NoCloseSeekableInputStream(inputStream),
outputData,
descriptor.getInputParameters());
// Set the expiry header for the cache
setCacheData(response, representation.getCacheInfo());
// Set the content type header
response.setContentType(
descriptor.getInputParameters().getParameterValue(
ParameterNames.OUTPUT_IMAGE_MIME_TYPE));
response.setContentLength((int)outputData.getStreamPosition());
// Now we may safely flush and close the output
// yes we really do need to flush it AND close it.
outputData.flushDelegate();
outputData.closeDelegate();
return Result.SUCCESS;
} finally {
// make sure we close these streams as they could be holding
// files open
// Output stream (response) should be flushed only in case of success.
// In case of exception, we allow the container to handle response,
// therefore we must not flush nor close the output stream here.
try {
if (null != inputStream) {
inputStream.flush();
inputStream.closeDelegate();
}
} catch (IOException e) {
throw new RuntimeException(
EXCEPTION_LOCALIZER.format("processing-error", descriptor.getExternalID()), e);
}
try {
if (null != watermarkStream) {
watermarkStream.flush();
watermarkStream.closeDelegate();
}
} catch (IOException e) {
throw new RuntimeException(
EXCEPTION_LOCALIZER.format("processing-error", descriptor.getExternalID()), e);
}