/**
* Copyright 2007-2010 非也
* All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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 General Public License
* along with this program. If not, see http://www.gnu.org/licenses. *
*/
package org.fireflow.service.java;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.fireflow.client.WorkflowSession;
import org.fireflow.engine.context.RuntimeContext;
import org.fireflow.engine.entity.runtime.ActivityInstance;
import org.fireflow.engine.exception.ServiceInvocationException;
import org.fireflow.engine.invocation.ServiceInvoker;
import org.fireflow.engine.invocation.impl.AbsServiceInvoker;
import org.fireflow.engine.modules.beanfactory.BeanFactory;
import org.fireflow.model.binding.ServiceBinding;
import org.fireflow.model.servicedef.ServiceDef;
/**
* java bean服务,负责调用java bean;
*
* @author 非也
* @version 2.0
*/
public class JavaInvoker extends AbsServiceInvoker implements ServiceInvoker {
private static final Log log = LogFactory.getLog(JavaInvoker.class);
@Override
public Object getServiceObject(RuntimeContext runtimeContext,
WorkflowSession session, ActivityInstance activityInstance,
ServiceBinding serviceBinding,ServiceDef svc,Object activity) throws ServiceInvocationException {
BeanFactory beanFactory = runtimeContext.getEngineModule(
BeanFactory.class, activityInstance.getProcessType());
JavaService javaService = (JavaService) svc;
String beanName = javaService.getJavaBeanName();
String javaClass = javaService.getJavaClassName();
Object bean = null;
if (!StringUtils.isEmpty(beanName)) {
bean = beanFactory.getBean(beanName);
} else if (!StringUtils.isEmpty(javaClass)) {
bean = beanFactory.createBean(javaClass);
}
if (bean == null) {
ServiceInvocationException ex = new ServiceInvocationException("无法初始化 service object,Service定义是[name="+svc.getName()+",displayName="+svc.getDisplayName()+"]");
ex.setErrorCode(ServiceInvocationException.SERVICE_OBJECT_NOT_FOUND);
ex.setActivityInstance(activityInstance);
throw ex;
} else {
return bean;
}
}
/*
* (non-Javadoc)
*
* @see
* org.fireflow.engine.invocation.AbsServiceInvoker#getParameterTypes(java
* .lang.String, java.lang.Object[])
*/
@Override
protected Class[] getParameterTypes(Class serviceClass, String methodName,
Object[] params)throws ServiceInvocationException {
Object[] _params = params;
if (_params == null) {
_params = new Object[0];
}
Class[] parameterTypes = new Class[_params.length];
boolean hasNullParam = false;
for (int i = 0; i < _params.length; i++) {
Object param = _params[i];
if (param!=null){
parameterTypes[i] = param.getClass();
}else{
parameterTypes[i] = NullClass.class;
hasNullParam = true;
}
}
if (!hasNullParam){
return parameterTypes;
}
else{
Method[] candidateMethods = getMethods(serviceClass,methodName,_params.length);
if (candidateMethods==null || candidateMethods.length==0){
ServiceInvocationException ex = new ServiceInvocationException("Java服务没有名称为"+
methodName+"的方法,Java服务的类名是[class="+serviceClass.getName()+
",输入参数类型是 "+parameterTypesToString(parameterTypes));
ex.setErrorCode(ServiceInvocationException.OPERATION_NOT_FOUND);
throw ex;
}
parameterTypes = findExactParameterTypes(serviceClass,methodName,candidateMethods,parameterTypes);
return parameterTypes;
}
}
private String parameterTypesToString(Class[] parameterTypes){
StringBuffer sBuf = new StringBuffer("[");
for (int i=0;i<parameterTypes.length;i++){
Class cls = parameterTypes[i];
if(cls!=NullClass.class){
sBuf.append(cls.getName());
}else{
sBuf.append("null");
}
if (i<parameterTypes.length-1){
sBuf.append(",");
}
}
sBuf.append("]");
return sBuf.toString();
}
private Class[] findExactParameterTypes(Class serviceClass,String methodName,Method[] candidateMethods,Class[] actInputParamTypes)throws ServiceInvocationException{
for (Method m : candidateMethods){
Class[] candidateParamTypes = m.getParameterTypes();
int paramLength = candidateParamTypes.length;
boolean isTheSameParamTypes = true;
for (int i=0;i<paramLength;i++){
if (actInputParamTypes[i].getName().equals(NullClass.class.getName())){
continue;
}else {
Class actParamClass = actInputParamTypes[i];
Class candidateParamClass = candidateParamTypes[i];
if (candidateParamClass.isAssignableFrom(actParamClass)){
isTheSameParamTypes = true;
}else{
isTheSameParamTypes = false;
break;
}
}
}
if (isTheSameParamTypes){
return m.getParameterTypes();
}
}
ServiceInvocationException ex = new ServiceInvocationException("Java服务没有名称为"+
methodName+"的方法,Java服务的类名是[class="+serviceClass.getName()+
",输入参数类型是 "+parameterTypesToString(actInputParamTypes));
ex.setErrorCode(ServiceInvocationException.OPERATION_NOT_FOUND);
throw ex;
}
/**
* 查找名字和参数数量相匹配的method
* @param methodName
* @param paramsLength
* @return
*/
private Method[] getMethods(Class serviceClass,String methodName,int paramsLength){
Method[] allMethods = serviceClass.getMethods();
List<Method> foundMethods = new ArrayList<Method>();
for (Method m : allMethods){
if (m.getName().equals(methodName)){
Class[] paramTypes = m.getParameterTypes();
int _tmpParamLength = 0;
if (paramTypes!=null){
_tmpParamLength = paramTypes.length;
}
if (_tmpParamLength == paramsLength){
foundMethods.add(m);
}
}
}
Method[] returnValue = new Method[foundMethods.size()];
for (int i=0;i<foundMethods.size();i++){
returnValue[i] = foundMethods.get(i);
}
return returnValue;
}
private class NullClass {
}
}