/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.rest.util;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import java.util.Date;
import org.activiti.engine.FormService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineInfo;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.rest.Config;
import org.springframework.extensions.webscripts.AbstractWebScript;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;
/**
* Helper class that wrapps the webscript request to perform methods upon it.
*
* @author Erik Winlof and Nils Preusker
*/
public class ActivitiStreamingWebScript extends AbstractWebScript {
/**
* The activiti config bean
*/
protected Config config;
/**
* Setter for the activiti config bean
*
* @param config The activiti config bean
*/
public void setConfig(Config config) {
this.config = config;
}
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException {
try {
// Create activiti request to add heler methods
ActivitiRequest ar = new ActivitiRequest(req);
// Set logged in web user as current user in engine api
getIdentityService().setAuthenticatedUserId(ar.getCurrentUserId());
// Let implementing webscript do something useful
executeStreamingWebScript(new ActivitiRequest(req), res);
}
finally {
// Reset the current engine api user
getIdentityService().setAuthenticatedUserId(null);
}
}
/**
* Override this method to implement the unique functionality for this webscript
*
* @param req The activiti request
* @param res The webscript response
*/
protected void executeStreamingWebScript(ActivitiRequest req, WebScriptResponse res) throws IOException {
// Override to make something useful
}
public String getMimeType(InputStream inputStream) {
return config.getMimeType(inputStream);
}
/**
* Streams an input stream to the webscript response
*
* @param res The response to stream the response to
* @param inputStream The input stream conatining the data
* @param modified The date and time when the streamed data was modified
* @param eTag The cache eTag to use for the data
* @param attachFileName Will if provided be used as a attach file name header to improve the chances of
* being opened by an external program
* @param mimetype The mimetype of the contents
* @throws IOException
*/
protected void streamResponse(WebScriptResponse res, InputStream inputStream,
Date modified, String eTag,
boolean attach, String attachFileName,
String mimetype) throws IOException {
if (attach) {
String headerValue = "attachment";
if (attachFileName != null && attachFileName.length() > 0) {
headerValue += "; filename=" + attachFileName;
}
/**
* set header based on filename - will force a Save As from the browse if
* it doesn't recognize it
* this is better than the default response of the browser trying to
* display the contents
*/
res.setHeader("Content-Disposition", headerValue);
}
if (mimetype != null) {
res.setContentType(mimetype);
}
// res.setContentEncoding(...);
// res.setHeader("Content-Length", ...);
// Set caching
Cache cache = new Cache();
cache.setNeverCache(false);
cache.setMustRevalidate(true);
cache.setMaxAge(0L);
cache.setLastModified(modified);
if (eTag != null) {
cache.setETag(eTag);
}
res.setCache(cache);
/**
* get the content and stream directly to the response output stream assuming
* the repository is capable of streaming in chunks, this should allow large files
* to be streamed directly to the browser response stream.
*/
try {
byte[] buffer = new byte[0xFFFF];
for (int len; (len = inputStream.read(buffer)) != -1;)
res.getOutputStream().write(buffer, 0, len);
} catch (SocketException e) {
// TODO: client cut the connection, log the message?
}
}
/**
* Returns the process engine info.
*
* @return The process engine info
*/
protected ProcessEngineInfo getProcessEngineInfo() {
return ProcessEngines.getProcessEngineInfo(config.getEngine());
}
/**
* Returns the process engine.
*
* @return The process engine
*/
protected ProcessEngine getProcessEngine() {
return ProcessEngines.getProcessEngine(config.getEngine());
}
/**
* Returns the identity service.
*
* @return The identity service
*/
protected IdentityService getIdentityService() {
return getProcessEngine().getIdentityService();
}
/**
* Returns the management service.
*
* @return The management service.
*/
protected ManagementService getManagementService() {
return getProcessEngine().getManagementService();
}
/**
* Returns The process service.
*
* @return The process service
*/
protected RuntimeService getRuntimeService() {
return getProcessEngine().getRuntimeService();
}
/**
* Returns The repository service.
*
* @return The repository service
*/
protected RepositoryService getRepositoryService() {
return getProcessEngine().getRepositoryService();
}
/**
* Returns the task service.
*
* @return The task service
*/
protected TaskService getTaskService() {
return getProcessEngine().getTaskService();
}
/**
* Returns the form service.
*
* @return The form service
*/
protected FormService getFormService() {
return getProcessEngine().getFormService();
}
}