use of org.alfresco.service.cmr.rendition.RenditionCancelledException in project alfresco-repository by Alfresco.
the class AbstractTransformationRenderingEngine method render.
/*
* (non-Javadoc)
* @see org.alfresco.repo.rendition.executer.AbstractRenderingEngine#render(org.alfresco.repo.rendition.executer.AbstractRenderingEngine.RenderingContext)
*/
@Override
protected void render(RenderingContext context) {
ContentReader contentReader = context.makeContentReader();
// There will have been an exception if there is no content data so contentReader is not null.
String contentUrl = contentReader.getContentUrl();
String sourceMimeType = contentReader.getMimetype();
String targetMimeType = getTargetMimeType(context);
// The child NodeRef gets created here
TransformationOptions transformationOptions = getTransformOptions(context);
long sourceSizeInBytes = contentReader.getSize();
Map<String, String> options = converter.getOptions(transformationOptions, sourceMimeType, targetMimeType);
NodeRef sourceNodeRef = transformationOptions.getSourceNodeRef();
if (!synchronousTransformClient.isSupported(sourceMimeType, sourceSizeInBytes, contentUrl, targetMimeType, options, null, sourceNodeRef)) {
String optionsString = TransformerDebug.toString(options);
throw new RenditionServiceException(String.format(NOT_TRANSFORMABLE_MESSAGE_PATTERN, sourceMimeType, targetMimeType, optionsString));
}
long startTime = new Date().getTime();
boolean actionCancelled = false;
boolean actionCompleted = false;
// Cache the execution summary to get details later
ExecutionSummary executionSummary = null;
try {
executionSummary = getExecutionSummary(context);
} catch (ActionServiceException e) {
if (logger.isInfoEnabled()) {
logger.info("Cancelling of multiple concurrent action instances " + "currently unsupported, this action can't be cancelled");
}
}
// Call the transform in a different thread so we can move on if cancelled
FutureTask<ContentWriter> transformTask = new FutureTask<ContentWriter>(new TransformationCallable(contentReader, targetMimeType, transformationOptions, context, AuthenticationUtil.getFullyAuthenticatedUser()));
getExecutorService().execute(transformTask);
// Start checking for cancellation or timeout
while (true) {
try {
Thread.sleep(CANCELLED_ACTION_POLLING_INTERVAL);
if (transformTask.isDone()) {
actionCompleted = true;
break;
}
// Check timeout in case transformer doesn't obey it
if (transformationOptions.getTimeoutMs() > 0 && new Date().getTime() - startTime > (transformationOptions.getTimeoutMs() + CANCELLED_ACTION_POLLING_INTERVAL)) {
// We hit a timeout, let the transform thread continue but results will be ignored
if (logger.isDebugEnabled()) {
logger.debug("Transformation did not obey timeout limit, " + "rendition action is moving on");
}
break;
}
if (executionSummary != null) {
ExecutionDetails executionDetails = actionTrackingService.getExecutionDetails(executionSummary);
if (executionDetails != null) {
actionCancelled = executionDetails.isCancelRequested();
if (actionCancelled) {
if (logger.isDebugEnabled()) {
logger.debug("Cancelling transformation");
}
transformTask.cancel(true);
break;
}
}
}
} catch (InterruptedException e) {
// entire thread was asked to stop
actionCancelled = true;
transformTask.cancel(true);
break;
}
}
if (actionCancelled) {
throw new RenditionCancelledException("Rendition action cancelled");
}
if (!actionCompleted && !actionCancelled) {
throw new RenditionServiceException("Transformation failed to obey timeout limit");
}
if (actionCompleted) {
// Copy content from temp writer to real writer
ContentWriter writer = context.makeContentWriter();
try {
// We should not need another timeout here, things should be ready for us
ContentWriter tempTarget = transformTask.get();
if (tempTarget == null) {
// We should never be in this state, but just in case
throw new RenditionServiceException("Target of transformation not present");
}
writer.putContent(tempTarget.getReader().getContentInputStream());
} catch (ExecutionException e) {
// Unwrap our cause and throw that
Throwable transformException = e.getCause();
if (transformException instanceof RuntimeException) {
throw (RuntimeException) e.getCause();
}
throw new RenditionServiceException(TRANSFORMING_ERROR_MESSAGE + e.getCause().getMessage(), e.getCause());
} catch (InterruptedException e) {
// We were asked to stop
transformTask.cancel(true);
}
}
}
use of org.alfresco.service.cmr.rendition.RenditionCancelledException in project alfresco-repository by Alfresco.
the class RenditionServiceIntegrationTest method renderPdfDocumentLongRunningTest.
protected void renderPdfDocumentLongRunningTest(AbstractNodeModifyingRunnable nodeModifyingRunnable, boolean joinNodeModifyingThread) throws Exception {
// Spawn a new thread that waits a bit then tries to modify the node
Thread nodeModifyingThread = new Thread(nodeModifyingRunnable);
nodeModifyingThread.start();
// Start the long running rendition
try {
this.renditionNode = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<NodeRef>() {
public NodeRef execute() throws Throwable {
// Initially the node that provides the content
// should not have the rn:renditioned aspect on it.
assertFalse("Source node has unexpected renditioned aspect.", nodeService.hasAspect(nodeWithDocContent, RenditionModel.ASPECT_RENDITIONED));
RenditionDefinition action = makeReformatAction(null, TEST_LONG_RUNNING_MIME_TYPE);
// Cancellation is only possible with tracking enabled
action.setTrackStatus(true);
// Render the content and put the result underneath the content node
ChildAssociationRef renditionAssoc = renditionService.render(nodeWithDocContent, action);
// Now the source content node should have the renditioned aspect
assertTrue("Source node is missing renditioned aspect.", nodeService.hasAspect(nodeWithDocContent, RenditionModel.ASPECT_RENDITIONED));
return renditionAssoc.getChildRef();
}
}, false, true);
} catch (RenditionCancelledException e) {
// expected cancellation exception
}
// Give a moment for roll back of rendition and commit of node modification to occur
Thread.sleep(3000);
if (joinNodeModifyingThread) {
nodeModifyingThread.join();
}
// be false if there was a failure
if (nodeModifyingRunnable.getModificationException() != null) {
throw new RuntimeException("Modification of node during long running rendition failed", nodeModifyingRunnable.getModificationException());
}
}
Aggregations