package com.x.processplatform.service.processing.processor.invoke; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import javax.script.CompiledScript; import javax.script.ScriptContext; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import com.google.gson.reflect.TypeToken; import com.x.base.core.container.EntityManagerContainer; import com.x.base.core.project.Application; import com.x.base.core.project.x_program_center; import com.x.base.core.project.config.Config; import com.x.base.core.project.config.Node; import com.x.base.core.project.connection.ActionResponse; import com.x.base.core.project.connection.CipherConnectionAction; import com.x.base.core.project.connection.ConnectionAction; import com.x.base.core.project.exception.RunningException; import com.x.base.core.project.http.ActionResult.Type; import com.x.base.core.project.logger.Logger; import com.x.base.core.project.logger.LoggerFactory; import com.x.base.core.project.scripting.JsonScriptingExecutor; import com.x.base.core.project.scripting.ScriptingFactory; import com.x.base.core.project.tools.StringTools; import com.x.processplatform.core.entity.content.Work; import com.x.processplatform.core.entity.element.Invoke; import com.x.processplatform.core.entity.element.Route; import com.x.processplatform.core.entity.log.Signal; import com.x.processplatform.service.processing.Business; import com.x.processplatform.service.processing.ThisApplication; import com.x.processplatform.service.processing.WrapScriptObject; import com.x.processplatform.service.processing.processor.AeiObjects; public class InvokeProcessor extends AbstractInvokeProcessor { private static final Logger LOGGER = LoggerFactory.getLogger(InvokeProcessor.class); public InvokeProcessor(EntityManagerContainer entityManagerContainer) throws Exception { super(entityManagerContainer); } @Override protected Work arriving(AeiObjects aeiObjects, Invoke invoke) throws Exception { // 发送ProcessingSignal aeiObjects.getProcessingAttributes().push(Signal.invokeArrive(aeiObjects.getWork().getActivityToken(), invoke)); return aeiObjects.getWork(); } @Override protected List executing(AeiObjects aeiObjects, Invoke invoke) throws Exception { // 发送ProcessingSignal aeiObjects.getProcessingAttributes() .push(Signal.invokeExecute(aeiObjects.getWork().getActivityToken(), invoke)); List results = new ArrayList<>(); boolean passThrough = false; switch (invoke.getInvokeMode()) { case jaxws: // 可以根据返回脚本判断时候流转 passThrough = this.jaxws(aeiObjects, invoke); break; case jaxrs: // 可以根据返回脚本判断时候流转 passThrough = this.jaxrs(aeiObjects, invoke); break; default: break; } if (passThrough) { results.add(aeiObjects.getWork()); } else { LOGGER.info("work title:{}, id:{} invoke return false, stay in the current activity.", () -> aeiObjects.getWork().getTitle(), () -> aeiObjects.getWork().getId()); } return results; } @Override protected List inquiring(AeiObjects aeiObjects, Invoke invoke) throws Exception { // 发送ProcessingSignal aeiObjects.getProcessingAttributes() .push(Signal.invokeInquire(aeiObjects.getWork().getActivityToken(), invoke)); List results = new ArrayList<>(); results.add(aeiObjects.getRoutes().get(0)); return results; } private boolean jaxws(AeiObjects aeiObjects, Invoke invoke) throws Exception { if (BooleanUtils.isTrue(invoke.getInternal())) { return this.jaxwsInternal(aeiObjects, invoke); } else { return this.jaxwsExternal(aeiObjects, invoke); } } private boolean jaxwsInternal(AeiObjects aeiObjects, Invoke invoke) { return true; } private boolean jaxwsExternal(AeiObjects aeiObjects, Invoke invoke) throws Exception { Object[] parameters = this.jaxwsEvalParameters(aeiObjects, invoke); JaxwsObject jaxwsObject = new JaxwsObject(); jaxwsObject.setAddress(invoke.getJaxwsAddress()); jaxwsObject.setMethod(invoke.getJaxwsMethod()); jaxwsObject.setParameters(parameters); boolean passThrough = false; if (BooleanUtils.isTrue(invoke.getAsync())) { ThisApplication.syncJaxwsInvokeQueue.send(jaxwsObject); passThrough = true; } else { InvokeExecutor executor = new InvokeExecutor(); Object[] response = executor.execute(jaxwsObject); if ((StringUtils.isNotEmpty(invoke.getJaxwsResponseScript())) || (StringUtils.isNotEmpty(invoke.getJaxwsResponseScriptText()))) { ScriptContext scriptContext = aeiObjects.scriptContext(); CompiledScript cs = aeiObjects.business().element().getCompiledScript( aeiObjects.getWork().getApplication(), aeiObjects.getActivity(), Business.EVENT_INVOKEJAXWSRESPONSE); scriptContext.getBindings(ScriptContext.ENGINE_SCOPE).put(ScriptingFactory.BINDING_NAME_JAXWSRESPONSE, response); passThrough = JsonScriptingExecutor.evalBoolean(cs, scriptContext, Boolean.TRUE); } else { passThrough = true; } } return passThrough; } private Object[] jaxwsEvalParameters(AeiObjects aeiObjects, Invoke invoke) throws Exception { List parameters = new ArrayList<>(); if ((StringUtils.isNotEmpty(invoke.getJaxwsParameterScript())) || (StringUtils.isNotEmpty(invoke.getJaxwsParameterScriptText()))) { ScriptContext scriptContext = aeiObjects.scriptContext(); CompiledScript cs = aeiObjects.business().element().getCompiledScript(aeiObjects.getWork().getApplication(), aeiObjects.getActivity(), Business.EVENT_INVOKEJAXWSPARAMETER); scriptContext.getBindings(ScriptContext.ENGINE_SCOPE).put(ScriptingFactory.BINDING_NAME_JAXWSPARAMETERS, parameters); JsonScriptingExecutor.jsonArray(cs, scriptContext, o -> { if (o.size() > 0) { parameters.clear(); parameters.addAll(gson.fromJson(o, new TypeToken>() { }.getType())); } }); } return parameters.toArray(); } private boolean jaxrs(AeiObjects aeiObjects, Invoke invoke) throws Exception { if (BooleanUtils.isTrue(invoke.getInternal())) { return this.jaxrsInternal(aeiObjects, invoke); } else { return this.jaxrsExternal(aeiObjects, invoke); } } private boolean jaxrsInternal(AeiObjects aeiObjects, Invoke invoke) throws Exception { ActionResponse resp = null; switch (StringUtils.upperCase(invoke.getJaxrsMethod())) { case ConnectionAction.METHOD_POST: resp = jaxrsInternalPost(aeiObjects, invoke); break; case ConnectionAction.METHOD_PUT: resp = jaxrsInternalPut(aeiObjects, invoke); break; case ConnectionAction.METHOD_GET: resp = jaxrsInternalGet(aeiObjects, invoke); break; case ConnectionAction.METHOD_DELETE: resp = jaxrsInternalDelete(aeiObjects, invoke); break; case "head": break; case "options": break; case "patch": break; case "trace": break; default: throw new ExceptionUnknownHttpMethod(invoke.getJaxrsMethod()); } // 同步执行状态下进行调用判断 if ((!BooleanUtils.isTrue(invoke.getAsync())) && ((null == resp) || (!Objects.equals(Type.success, resp.getType())))) { throw new RunningException("invoke not success, work:{}.", aeiObjects.getWork().getId()); } boolean passThrough = false; if (!BooleanUtils.isTrue(invoke.getAsync())) { WrapScriptObject jaxrsResponse = new WrapScriptObject(); if (null != resp) { jaxrsResponse.type(resp.getType().toString()); jaxrsResponse.set(gson.toJson(resp.getData())); } if ((StringUtils.isNotEmpty(invoke.getJaxrsResponseScript())) || (StringUtils.isNotEmpty(invoke.getJaxrsResponseScriptText()))) { ScriptContext scriptContext = aeiObjects.scriptContext(); CompiledScript cs = aeiObjects.business().element().getCompiledScript( aeiObjects.getWork().getApplication(), aeiObjects.getActivity(), Business.EVENT_INVOKEJAXRSRESPONSE); scriptContext.getBindings(ScriptContext.ENGINE_SCOPE).put(ScriptingFactory.BINDING_NAME_JAXRSRESPONSE, jaxrsResponse); passThrough = JsonScriptingExecutor.evalBoolean(cs, scriptContext, Boolean.TRUE); } else { passThrough = true; } } else { passThrough = true; } return passThrough; } private ActionResponse jaxrsInternalDelete(AeiObjects aeiObjects, Invoke invoke) throws Exception { String uri = this.jaxrsUrl(aeiObjects, invoke); if (BooleanUtils.isTrue(invoke.getAsync())) { JaxrsObject jaxrsObject = new JaxrsObject(); if (invoke.getInternalProject().equalsIgnoreCase(x_program_center.class.getSimpleName()) || invoke.getInternalProject().equalsIgnoreCase(x_program_center.class.getName())) { final Node node = Config.nodes().get(Config.resource_node_centersPirmaryNode()); if (null != node) { String prefix = ThisApplication.context().applications().urlPrefixOfCenterServer( Config.resource_node_centersPirmaryNode(), node.getCenter()); jaxrsObject .setAddress(StringTools.JoinUrl(prefix + CipherConnectionAction.trim(uri))); } } else { Application application = ThisApplication.context().applications() .randomWithWeight(invoke.getInternalProject()); jaxrsObject .setAddress( StringTools.JoinUrl(application.getUrlJaxrsRoot() + CipherConnectionAction.trim(uri))); } jaxrsObject.setInternal(invoke.getInternal()); jaxrsObject.setMethod(ConnectionAction.METHOD_DELETE); jaxrsObject.setContentType(invoke.getJaxrsContentType()); ThisApplication.syncJaxrsInvokeQueue.send(jaxrsObject); } else { return ThisApplication.context().applications().deleteQuery(invoke.getInternalProject(), uri); } return null; } private ActionResponse jaxrsInternalGet(AeiObjects aeiObjects, Invoke invoke) throws Exception { String uri = this.jaxrsUrl(aeiObjects, invoke); if (BooleanUtils.isTrue(invoke.getAsync())) { JaxrsObject jaxrsObject = new JaxrsObject(); if (invoke.getInternalProject().equalsIgnoreCase(x_program_center.class.getSimpleName()) || invoke.getInternalProject().equalsIgnoreCase(x_program_center.class.getName())) { final Node node = Config.nodes().get(Config.resource_node_centersPirmaryNode()); if (null != node) { String prefix = ThisApplication.context().applications().urlPrefixOfCenterServer( Config.resource_node_centersPirmaryNode(), node.getCenter()); jaxrsObject .setAddress(StringTools.JoinUrl(prefix + CipherConnectionAction.trim(uri))); } } else { Application application = ThisApplication.context().applications() .randomWithWeight(invoke.getInternalProject()); jaxrsObject .setAddress( StringTools.JoinUrl(application.getUrlJaxrsRoot() + CipherConnectionAction.trim(uri))); } jaxrsObject.setInternal(invoke.getInternal()); jaxrsObject.setMethod(ConnectionAction.METHOD_GET); jaxrsObject.setContentType(invoke.getJaxrsContentType()); ThisApplication.syncJaxrsInvokeQueue.send(jaxrsObject); return null; } else { return ThisApplication.context().applications().getQuery(invoke.getInternalProject(), uri); } } private ActionResponse jaxrsInternalPut(AeiObjects aeiObjects, Invoke invoke) throws Exception { String body = this.jaxrsEvalBody(aeiObjects, invoke); String uri = this.jaxrsUrl(aeiObjects, invoke); if (BooleanUtils.isTrue(invoke.getAsync())) { JaxrsObject jaxrsObject = new JaxrsObject(); if (invoke.getInternalProject().equalsIgnoreCase(x_program_center.class.getSimpleName()) || invoke.getInternalProject().equalsIgnoreCase(x_program_center.class.getName())) { final Node node = Config.nodes().get(Config.resource_node_centersPirmaryNode()); if (null != node) { String prefix = ThisApplication.context().applications().urlPrefixOfCenterServer( Config.resource_node_centersPirmaryNode(), node.getCenter()); jaxrsObject .setAddress(StringTools.JoinUrl(prefix + CipherConnectionAction.trim(uri))); } } else { Application application = ThisApplication.context().applications() .randomWithWeight(invoke.getInternalProject()); jaxrsObject .setAddress( StringTools.JoinUrl(application.getUrlJaxrsRoot() + CipherConnectionAction.trim(uri))); } jaxrsObject.setAddress(uri); jaxrsObject.setBody(body); jaxrsObject.setInternal(invoke.getInternal()); jaxrsObject.setMethod(ConnectionAction.METHOD_PUT); jaxrsObject.setContentType(invoke.getJaxrsContentType()); ThisApplication.syncJaxrsInvokeQueue.send(jaxrsObject); return null; } else { return ThisApplication.context().applications().putQuery(invoke.getInternalProject(), uri, body); } } private ActionResponse jaxrsInternalPost(AeiObjects aeiObjects, Invoke invoke) throws Exception { String body = this.jaxrsEvalBody(aeiObjects, invoke); String uri = this.jaxrsUrl(aeiObjects, invoke); if (BooleanUtils.isTrue(invoke.getAsync())) { JaxrsObject jaxrsObject = new JaxrsObject(); if (invoke.getInternalProject().equalsIgnoreCase(x_program_center.class.getSimpleName()) || invoke.getInternalProject().equalsIgnoreCase(x_program_center.class.getName())) { final Node node = Config.nodes().get(Config.resource_node_centersPirmaryNode()); if (null != node) { String prefix = ThisApplication.context().applications().urlPrefixOfCenterServer( Config.resource_node_centersPirmaryNode(), node.getCenter()); jaxrsObject .setAddress(StringTools.JoinUrl(prefix + CipherConnectionAction.trim(uri))); } } else { Application application = ThisApplication.context().applications() .randomWithWeight(invoke.getInternalProject()); jaxrsObject .setAddress( StringTools.JoinUrl(application.getUrlJaxrsRoot() + CipherConnectionAction.trim(uri))); } jaxrsObject.setBody(body); jaxrsObject.setInternal(invoke.getInternal()); jaxrsObject.setMethod(ConnectionAction.METHOD_POST); jaxrsObject.setContentType(invoke.getJaxrsContentType()); ThisApplication.syncJaxrsInvokeQueue.send(jaxrsObject); return null; } else { return ThisApplication.context().applications().postQuery(invoke.getInternalProject(), uri, body); } } private boolean jaxrsExternal(AeiObjects aeiObjects, Invoke invoke) throws Exception { String result = ""; String uri = this.jaxrsUrl(aeiObjects, invoke); JaxrsObject jaxrsObject = new JaxrsObject(); jaxrsObject.setHead(this.jaxrsEvalHeader(aeiObjects, invoke)); switch (StringUtils.upperCase(invoke.getJaxrsMethod())) { case ConnectionAction.METHOD_POST: result = jaxrsExternalPost(aeiObjects, invoke, uri, jaxrsObject); break; case ConnectionAction.METHOD_PUT: result = jaxrsExternalPut(aeiObjects, invoke, uri, jaxrsObject); break; case ConnectionAction.METHOD_GET: result = jaxrsExternalGet(aeiObjects, invoke, uri, jaxrsObject); break; case ConnectionAction.METHOD_DELETE: result = jaxrsExternalDelete(aeiObjects, invoke, uri, jaxrsObject); break; case "head": break; case "options": break; case "patch": break; case "trace": break; default: throw new ExceptionUnknownHttpMethod(invoke.getJaxrsMethod()); } // 同步执行状态下进行调用判断 if ((!BooleanUtils.isTrue(invoke.getAsync())) && (null == result)) { throw new RunningException("invoke address:{} not success, work:{}.", uri, aeiObjects.getWork().getId()); } boolean passThrough = false; if (!BooleanUtils.isTrue(invoke.getAsync())) { WrapScriptObject jaxrsResponse = new WrapScriptObject(); if (null == result) { jaxrsResponse.type(Type.connectFatal.toString()); } else { jaxrsResponse.type(Type.success.toString()); } jaxrsResponse.set(result); if ((StringUtils.isNotEmpty(invoke.getJaxrsResponseScript())) || (StringUtils.isNotEmpty(invoke.getJaxrsResponseScriptText()))) { ScriptContext scriptContext = aeiObjects.scriptContext(); CompiledScript cs = aeiObjects.business().element().getCompiledScript( aeiObjects.getWork().getApplication(), aeiObjects.getActivity(), Business.EVENT_INVOKEJAXRSRESPONSE); scriptContext.getBindings(ScriptContext.ENGINE_SCOPE).put(ScriptingFactory.BINDING_NAME_JAXRSRESPONSE, jaxrsResponse); passThrough = JsonScriptingExecutor.evalBoolean(cs, scriptContext, Boolean.TRUE); } else { passThrough = true; } } else { passThrough = true; } return passThrough; } private String jaxrsExternalDelete(AeiObjects aeiObjects, Invoke invoke, String address, JaxrsObject jaxrsObject) throws Exception { jaxrsObject.setMethod(ConnectionAction.METHOD_DELETE); jaxrsObject.setInternal(false); jaxrsObject.setAddress(address); jaxrsObject.setContentType(invoke.getJaxrsContentType()); if (BooleanUtils.isTrue(invoke.getAsync())) { ThisApplication.syncJaxrsInvokeQueue.send(jaxrsObject); return null; } else { InvokeExecutor executor = new InvokeExecutor(); return executor.execute(jaxrsObject); } } private String jaxrsExternalGet(AeiObjects aeiObjects, Invoke invoke, String address, JaxrsObject jaxrsObject) throws Exception { jaxrsObject.setMethod(ConnectionAction.METHOD_GET); jaxrsObject.setInternal(false); jaxrsObject.setAddress(address); jaxrsObject.setContentType(invoke.getJaxrsContentType()); if (BooleanUtils.isTrue(invoke.getAsync())) { ThisApplication.syncJaxrsInvokeQueue.send(jaxrsObject); return null; } else { InvokeExecutor executor = new InvokeExecutor(); return executor.execute(jaxrsObject); } } private String jaxrsExternalPut(AeiObjects aeiObjects, Invoke invoke, String address, JaxrsObject jaxrsObject) throws Exception { String body = this.jaxrsEvalBody(aeiObjects, invoke); jaxrsObject.setMethod(ConnectionAction.METHOD_PUT); jaxrsObject.setInternal(false); jaxrsObject.setAddress(address); jaxrsObject.setBody(body); jaxrsObject.setContentType(invoke.getJaxrsContentType()); if (BooleanUtils.isTrue(invoke.getAsync())) { ThisApplication.syncJaxrsInvokeQueue.send(jaxrsObject); return null; } else { InvokeExecutor executor = new InvokeExecutor(); return executor.execute(jaxrsObject); } } private String jaxrsExternalPost(AeiObjects aeiObjects, Invoke invoke, String address, JaxrsObject jaxrsObject) throws Exception { String body = this.jaxrsEvalBody(aeiObjects, invoke); jaxrsObject.setMethod(ConnectionAction.METHOD_POST); jaxrsObject.setInternal(false); jaxrsObject.setAddress(address); jaxrsObject.setBody(body); jaxrsObject.setContentType(invoke.getJaxrsContentType()); if (BooleanUtils.isTrue(invoke.getAsync())) { ThisApplication.syncJaxrsInvokeQueue.send(jaxrsObject); return null; } else { InvokeExecutor executor = new InvokeExecutor(); return executor.execute(jaxrsObject); } } private String jaxrsUrl(AeiObjects aeiObjects, Invoke invoke) throws Exception { String url = invoke.getJaxrsAddress(); Map parameters = new HashMap<>(); if ((StringUtils.isNotEmpty(invoke.getJaxrsParameterScript())) || (StringUtils.isNotEmpty(invoke.getJaxrsParameterScriptText()))) { ScriptContext scriptContext = aeiObjects.scriptContext(); CompiledScript cs = aeiObjects.business().element().getCompiledScript(aeiObjects.getWork().getApplication(), aeiObjects.getActivity(), Business.EVENT_INVOKEJAXRSPARAMETER); scriptContext.getBindings(ScriptContext.ENGINE_SCOPE).put(ScriptingFactory.BINDING_NAME_JAXRSPARAMETERS, parameters); // map有可能返回null Map map = JsonScriptingExecutor.eval(cs, scriptContext, new TypeToken>() { }.getType()); if (null != map) { parameters.putAll(map); } } for (Entry entry : parameters.entrySet()) { url = StringUtils.replace(url, "{" + entry.getKey() + "}", entry.getValue()); } return url; } private String jaxrsEvalBody(AeiObjects aeiObjects, Invoke invoke) throws Exception { JaxrsBody jaxrsBody = new JaxrsBody(); if ((StringUtils.isNotEmpty(invoke.getJaxrsBodyScript())) || (StringUtils.isNotEmpty(invoke.getJaxrsBodyScriptText()))) { ScriptContext scriptContext = aeiObjects.scriptContext(); CompiledScript cs = aeiObjects.business().element().getCompiledScript(aeiObjects.getApplication().getId(), aeiObjects.getActivity(), Business.EVENT_INVOKEJAXRSBODY); scriptContext.getBindings(ScriptContext.ENGINE_SCOPE).put(ScriptingFactory.BINDING_NAME_JAXRSBODY, jaxrsBody); JsonScriptingExecutor.jsonElement(cs, scriptContext, o -> { if (!o.isJsonNull()) { jaxrsBody.set(gson.toJson(o)); } }); } return jaxrsBody.get(); } private Map jaxrsEvalHeader(AeiObjects aeiObjects, Invoke invoke) throws Exception { Map map = new LinkedHashMap<>(); if ((StringUtils.isNotEmpty(invoke.getJaxrsHeadScript())) || (StringUtils.isNotEmpty(invoke.getJaxrsHeadScriptText()))) { ScriptContext scriptContext = aeiObjects.scriptContext(); CompiledScript cs = aeiObjects.business().element().getCompiledScript(aeiObjects.getWork().getApplication(), aeiObjects.getActivity(), Business.EVENT_INVOKEJAXRSHEAD); scriptContext.getBindings(ScriptContext.ENGINE_SCOPE).put(ScriptingFactory.BINDING_NAME_JAXRSHEADERS, map); map.putAll(JsonScriptingExecutor.eval(cs, scriptContext, new TypeToken>() { }.getType())); } return map; } public class JaxrsBody { private String value; private String get() { return Objects.toString(value, ""); } public void set(String value) { this.value = value; } } @Override protected void arrivingCommitted(AeiObjects aeiObjects, Invoke invoke) throws Exception { // nothing } @Override protected void executingCommitted(AeiObjects aeiObjects, Invoke invoke, List works) throws Exception { // nothing } @Override protected void inquiringCommitted(AeiObjects aeiObjects, Invoke invoke) throws Exception { // nothing } }