/**
* Copyright 2007-2010 非也
* All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License v3 as published by the Free Software
* Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with this library; if not, see http://www.gnu.org/licenses/lgpl.html.
*
*/
package org.fireflow.console.servlet.repository;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.fireflow.client.WorkflowQuery;
import org.fireflow.client.WorkflowSession;
import org.fireflow.client.WorkflowSessionFactory;
import org.fireflow.client.WorkflowStatement;
import org.fireflow.client.query.Order;
import org.fireflow.client.query.Restrictions;
import org.fireflow.demo.fireflow_ext.WorkflowUtil;
import org.fireflow.engine.context.RuntimeContext;
import org.fireflow.engine.entity.repository.ProcessDescriptor;
import org.fireflow.engine.entity.repository.ProcessDescriptorProperty;
import org.fireflow.engine.entity.repository.ProcessRepository;
import org.fireflow.engine.entity.repository.impl.ProcessDescriptorImpl;
import org.fireflow.model.InvalidModelException;
import org.fireflow.model.io.DeserializerException;
import org.fireflow.pdl.fpdl.io.FPDLDeserializer;
import org.fireflow.pdl.fpdl.misc.FpdlConstants;
import org.fireflow.pdl.fpdl.process.WorkflowProcess;
import org.fireflow.web_client.util.Constants;
import org.fireflow.web_client.util.Utils;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
*
* @author 非也 nychen2000@163.com Fire Workflow 官方网站:www.firesoa.com 或者
* www.fireflow.org
*
*/
public class UploadDefinitionsServlet extends HttpServlet {
public static final String SINGLE_DEF_STEP1 = "SINGLE_DEF_STEP1";
public static final String SINGLE_DEF_STEP2 = "SINGLE_DEF_STEP2";
public static final String PROCESS_DEFINITION = "PROCESS_DEFINITION";
protected WebApplicationContext springCtx = null;
protected RuntimeContext fireContext = null;
protected TransactionTemplate transactionTemplate = null;
public void init() throws ServletException {
//准备相关参数及相关spring bean
springCtx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
fireContext = (RuntimeContext)springCtx.getBean(RuntimeContext.Fireflow_Runtime_Context_Name);
transactionTemplate = (TransactionTemplate)springCtx.getBean("demoTransactionTemplate");
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
this.doPost(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String actionType = req.getParameter(Constants.ACTION_TYPE);
if (SINGLE_DEF_STEP1.equals(actionType)) {
uploadSingleDefStep1(req, resp);
}
else if (SINGLE_DEF_STEP2.equals(actionType)){
uploadSingleDefStep2(req,resp);
}
}
protected void uploadSingleDefStep2(final HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//1、首先获得发布参数
String _publishState = req.getParameter("publishState");
String _validDateFrom = req.getParameter("validDateFrom");
String _validDateTo = req.getParameter("validDateTo");
final String updateLog = req.getParameter("updateLog");
String _version = req.getParameter("version");
boolean publishStateTmp = false;
if (_publishState!=null && !_publishState.trim().equals("")){
try{
publishStateTmp = Boolean.parseBoolean(_publishState);
}catch(Exception e){
publishStateTmp = false;
}
}
final boolean publishState = publishStateTmp;
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date validDateFromTmp = new Date();
if (_validDateFrom!=null && !_validDateFrom.trim().equals("")){
try{
validDateFromTmp = format.parse(_validDateFrom);
}catch(Exception e){
validDateFromTmp = new Date();
}
}
final Date validDateFrom = validDateFromTmp;
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2099);
cal.set(Calendar.MONTH, 12);
cal.set(Calendar.DATE, 31);
Date validDateToTmp = cal.getTime();
if (_validDateTo!=null && !_validDateTo.trim().equals("")){
try{
validDateToTmp = format.parse(_validDateTo);
}catch(Exception e){
validDateToTmp = cal.getTime();
}
}
final Date validDateTo = validDateToTmp;
int versionTmp = 0;
if (_version!=null && !_version.trim().equals("")){
try{
versionTmp = Integer.parseInt(_version);
}catch(Exception e){
versionTmp = 0;
}
}
final int version = versionTmp;
// 2、获得当前用户,建议该用户实现Fireflow的用户接口
final org.fireflow.engine.modules.ousystem.User currentUser =
WorkflowUtil.getCurrentWorkflowUser(req.getSession());
ProcessDescriptor processDescriptor = (ProcessDescriptor) transactionTemplate
.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
// a、首先创建Fire WorkflowSession
WorkflowSession session = WorkflowSessionFactory
.createWorkflowSession(fireContext, currentUser);
WorkflowStatement stmt = session
.createWorkflowStatement();
//b、发布流程到流程库
ProcessDescriptor processDescriptor = null;
try {
WorkflowProcess inStream =(WorkflowProcess) req.getSession().getAttribute(PROCESS_DEFINITION);
processDescriptor = stmt.uploadProcessObject(
inStream, version);
((ProcessDescriptorImpl) processDescriptor)
.setPublishState(publishState);
((ProcessDescriptorImpl) processDescriptor).setValidDateFrom(validDateFrom);
((ProcessDescriptorImpl) processDescriptor).setValidDateTo(validDateTo);
((ProcessDescriptorImpl) processDescriptor).setUpdateLog(updateLog);
stmt.updateProcessDescriptor(processDescriptor);
} catch (InvalidModelException e) {
throw new RuntimeException(e);
}
return processDescriptor;
}
});
// 4、查询出本次上传的流程,显示在结果页面上
WorkflowSession session = WorkflowSessionFactory.createWorkflowSession(
fireContext, currentUser);
WorkflowQuery<ProcessRepository> processQuery = session
.createWorkflowQuery(ProcessRepository.class);
processQuery
.add(Restrictions.eq(ProcessDescriptorProperty.PROCESS_ID,
processDescriptor.getProcessId()))
.add(Restrictions.eq(ProcessDescriptorProperty.PROCESS_TYPE,
processDescriptor.getProcessType()))
.add(Restrictions.eq(ProcessDescriptorProperty.VERSION,
processDescriptor.getVersion()));
ProcessRepository repository = processQuery.unique();// 该查询也可以用如下方式实现:ProcessRepository
// repository =
// processQuery.get(processDescriptor.getId());
req.setAttribute("process_repository", repository);
// 5、导航到结果页面
RequestDispatcher dispatcher = req
.getRequestDispatcher("/fireflow_console/repository/upload_definition_result.jsp");
dispatcher.forward(req, resp);
}
/**
* 上传单个流程定义文件,步骤1<br>
* 该步骤首先将上传流程定义文件保存在Session中(实际业务系统需要改进一下);然后打开步骤2页面;待操作员补充完信息后,将流程定义保存到流程库。
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void uploadSingleDefStep1(HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException {
// 1、从request中取得流程定义,将其暂存在session中(实际业务系统需要改进一下)
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> fileItems = null;
try {
fileItems = upload.parseRequest(req);
} catch (FileUploadException e) {
e.printStackTrace();
}
InputStream inStreamTmp = null;// 流程文件
String fileName = null;
Iterator<FileItem> i = fileItems.iterator();
while (i.hasNext()) {
FileItem item = (FileItem) i.next();
if (!item.isFormField()) {
inStreamTmp = item.getInputStream();
fileName = item.getName();
} else {
// 其他字段忽略
// System.out.println("==="+item.getFieldName());
}
}
// 2、解析该流程定义
FPDLDeserializer des = new FPDLDeserializer();
WorkflowProcess process = null;
try {
process = des.deserialize(inStreamTmp);
} catch (DeserializerException e) {
req.setAttribute(Constants.ERROR_MESSAGE, "解析流程文件时报错,流程文件名是"
+ fileName);
req.setAttribute(Constants.ERROR_STACK,
Utils.exceptionStackToString(e));
RequestDispatcher dispatcher = req
.getRequestDispatcher("/common/error_message.jsp");
dispatcher.forward(req, resp);
return;
} catch (InvalidModelException e) {
req.setAttribute(Constants.ERROR_MESSAGE, "非法的流程定义文件,流程文件名是"
+ fileName);
req.setAttribute(Constants.ERROR_STACK,
Utils.exceptionStackToString(e));
RequestDispatcher dispatcher = req
.getRequestDispatcher("/common/error_message");
dispatcher.forward(req, resp);
return;
}
if (process==null){
req.setAttribute(Constants.ERROR_MESSAGE, "非法的流程定义文件,流程文件名是"
+ fileName);
req.setAttribute(Constants.ERROR_STACK,"流程定义文件解析后得到的WorkflowProcess对象为null");
RequestDispatcher dispatcher = req
.getRequestDispatcher("/common/error_message");
dispatcher.forward(req, resp);
return;
}
req.getSession().setAttribute(PROCESS_DEFINITION,process);
// 3、查找同一ID的其他版本的流程
final org.fireflow.engine.modules.ousystem.User currentUser =
WorkflowUtil.getCurrentWorkflowUser(req.getSession());
WorkflowSession fireSession = WorkflowSessionFactory.createWorkflowSession(fireContext, currentUser);
WorkflowQuery<ProcessDescriptor> query = fireSession.createWorkflowQuery(ProcessDescriptor.class);
List<ProcessDescriptor> existingProcessList = query.add(Restrictions.eq(ProcessDescriptorProperty.PROCESS_ID, process.getId()))
.add(Restrictions.eq(ProcessDescriptorProperty.PROCESS_TYPE, FpdlConstants.PROCESS_TYPE_FPDL20))
.addOrder(Order.asc(ProcessDescriptorProperty.VERSION))
.list();
req.setAttribute("EXISTING_PROCESS_LIST", existingProcessList);
req.setAttribute(PROCESS_DEFINITION, process);
// 5、导航到step2页面
RequestDispatcher dispatcher = req
.getRequestDispatcher("/fireflow_console/repository/upload_definition_step2.jsp");
dispatcher.forward(req, resp);
}
}