├── plugin-module ├── modeler-plugin-code │ ├── .eslintignore │ ├── .npmignore │ ├── .babelrc │ ├── docs │ │ └── screencast.gif │ ├── test │ │ ├── .eslintrc │ │ ├── suite.js │ │ ├── all.js │ │ └── TestHelper.js │ ├── index.js │ ├── index.prod.js │ ├── .eslintrc │ ├── client │ │ ├── bpmn-js-extension │ │ │ ├── propertiesProvider │ │ │ │ ├── utils.js │ │ │ │ ├── descriptors │ │ │ │ │ └── data.json │ │ │ │ ├── props │ │ │ │ │ ├── ScriptProps.js │ │ │ │ │ └── ConditionalProps.js │ │ │ │ └── CodePropertiesProvider.js │ │ │ ├── index.js │ │ │ ├── executor │ │ │ │ └── EventBasedExecutor.js │ │ │ └── disableModeling │ │ │ │ └── DisableModeling.js │ │ ├── index.js │ │ ├── react │ │ │ ├── Code │ │ │ │ ├── RunPanel.js │ │ │ │ ├── CodeFragment.js │ │ │ │ ├── ContextTable.js │ │ │ │ ├── groovy-hint.js │ │ │ │ └── CodeEditor.js │ │ │ └── UI │ │ │ │ ├── EditorModal.js │ │ │ │ └── Input.js │ │ ├── assets │ │ │ └── NOTICE │ │ └── utils │ │ │ ├── editorConsole.js │ │ │ ├── EventHelper.js │ │ │ ├── executors │ │ │ ├── GroovyAPI.js │ │ │ └── JSExecutor.js │ │ │ └── fieldUtil.js │ ├── backend │ │ ├── NOTICE │ │ ├── groovy.js │ │ └── main.js │ ├── LICENSE │ ├── karma.conf.js │ ├── package.json │ ├── README.md │ ├── webpack.config.js │ ├── style │ │ └── style.css │ └── CodeMirror6.patch └── pom.xml ├── language-executor ├── src │ ├── main │ │ ├── resources │ │ │ ├── messages.properties │ │ │ ├── application.properties │ │ │ └── SandboxExtension.groovy │ │ └── java │ │ │ └── org │ │ │ └── shared │ │ │ └── code │ │ │ └── languageexecutor │ │ │ ├── exception │ │ │ ├── XmlParseException.java │ │ │ ├── JsonParseException.java │ │ │ └── VariableParserException.java │ │ │ ├── LanguageExecutorApplication.java │ │ │ ├── parser │ │ │ ├── PrimitiveParser.java │ │ │ ├── VariableParser.java │ │ │ ├── XmlParser.java │ │ │ └── JsonParser.java │ │ │ ├── dto │ │ │ ├── ContextType.java │ │ │ ├── Context.java │ │ │ ├── CodeInput.java │ │ │ └── ResultOutput.java │ │ │ ├── service │ │ │ ├── VariableParserService.java │ │ │ ├── ClassNodeParserService.java │ │ │ ├── ContextValueParserService.java │ │ │ └── GroovyExecutorService.java │ │ │ ├── rest │ │ │ ├── CodeControllerExceptionHandler.java │ │ │ └── CodeController.java │ │ │ └── configuration │ │ │ └── ApplicationConfiguration.java │ └── test │ │ ├── resources │ │ └── scripts │ │ │ ├── auctionData.json │ │ │ ├── simpleReturn.groovy │ │ │ ├── offersJson.json │ │ │ ├── MaxAcceptablePrice.groovy │ │ │ └── MaxAcceptablePriceTypes.groovy │ │ └── java │ │ └── org │ │ └── shared │ │ └── code │ │ └── languageexecutor │ │ ├── configuration │ │ └── TestConfiguration.java │ │ ├── service │ │ └── GroovyExecutorServiceTest.java │ │ └── rest │ │ └── CodeControllerTest.java ├── README.md ├── pom.xml ├── mvnw.cmd └── mvnw ├── .gitattributes ├── .gitignore ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── workflows │ └── maven.yml ├── LICENSE ├── CHANGELOG.md ├── README.md └── pom.xml /plugin-module/modeler-plugin-code/.eslintignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/.npmignore: -------------------------------------------------------------------------------- 1 | !dist 2 | client 3 | webpack.config.js -------------------------------------------------------------------------------- /language-executor/src/main/resources/messages.properties: -------------------------------------------------------------------------------- 1 | error.message.unexpected=Unexpected error while calling {0} -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "@babel/plugin-proposal-class-properties" 4 | ] 5 | } -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/docs/screencast.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharedchains/camunda-code-editor/HEAD/plugin-module/modeler-plugin-code/docs/screencast.gif -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/test/.eslintrc: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2014-present Camunda Services GmbH 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | { 7 | "extends": "plugin:bpmn-io/mocha" 8 | } -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | name: 'Code Script Editor', 5 | script: './dist/client.js', 6 | style: './dist/assets/styles/style.css', 7 | menu: './dist/backend/main.js' 8 | }; 9 | -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/index.prod.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | name: 'Code Script Editor', 5 | script: './client/client.js', 6 | style: './assets/styles/style.css', 7 | menu: './backend/main.js' 8 | }; 9 | -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/test/suite.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2014-present Camunda Services GmbH 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | var allTests = require.context('.', true, /Spec\.js$/); 7 | 8 | allTests.keys().forEach(allTests); -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "eslint:recommended", 4 | "plugin:react/recommended", 5 | "plugin:bpmn-io/es6", 6 | "plugin:bpmn-io/mocha" 7 | ], 8 | "rules": { 9 | "react/prop-types": 0 10 | }, 11 | "env": { 12 | "browser": true, 13 | "es6": true 14 | } 15 | } -------------------------------------------------------------------------------- /language-executor/src/test/resources/scripts/auctionData.json: -------------------------------------------------------------------------------- 1 | { 2 | "offeredBonds": 7000, 3 | "startString": "2019-10-29 18:21:00", 4 | "endString": "2019-10-29 18:21:10", 5 | "auctionType": "competitive", 6 | "bondsDuration": "360days", 7 | "discountMAP": 0.0025, 8 | "increaseExclusion": 0.0100, 9 | "discountAcceptedPrice": 0.001 10 | } -------------------------------------------------------------------------------- /language-executor/src/test/resources/scripts/simpleReturn.groovy: -------------------------------------------------------------------------------- 1 | //file:noinspection 2 | import org.camunda.spin.json.SpinJsonNode 3 | import static org.camunda.spin.Spin.JSON 4 | import static org.camunda.spin.Spin.* 5 | 6 | static void main (String[] args) { 7 | def offeredBonds = auctionData.prop("offeredBonds").numberValue() 8 | return offeredBonds 9 | } 10 | -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/test/all.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2014-present Camunda Services GmbH 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | var allTests = require.context('.', true, /Spec\.js$/); 7 | 8 | allTests.keys().forEach(allTests); 9 | 10 | var allSources = require.context('../lib', true, /.*\.js$/); 11 | 12 | allSources.keys().forEach(allSources); -------------------------------------------------------------------------------- /language-executor/src/main/java/org/shared/code/languageexecutor/exception/XmlParseException.java: -------------------------------------------------------------------------------- 1 | package org.shared.code.languageexecutor.exception; 2 | 3 | /** 4 | * The type Xml parse exception. 5 | */ 6 | public class XmlParseException extends RuntimeException { 7 | 8 | /** 9 | * Instantiates a new Xml parse exception. 10 | */ 11 | public XmlParseException() { 12 | super(); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /language-executor/src/main/java/org/shared/code/languageexecutor/exception/JsonParseException.java: -------------------------------------------------------------------------------- 1 | package org.shared.code.languageexecutor.exception; 2 | 3 | /** 4 | * The type Json parse exception. 5 | */ 6 | public class JsonParseException extends RuntimeException { 7 | 8 | /** 9 | * Instantiates a new Json parse exception. 10 | */ 11 | public JsonParseException() { 12 | super(); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/client/bpmn-js-extension/propertiesProvider/utils.js: -------------------------------------------------------------------------------- 1 | import { getBusinessObject, is } from 'bpmn-js/lib/util/ModelUtil'; 2 | 3 | export const getCorrectBusinessObject = function(element, isProcessDocumentation) { 4 | let businessObject = getBusinessObject(element); 5 | if (is(element, 'bpmn:Participant') && isProcessDocumentation) { 6 | businessObject = businessObject.processRef; 7 | } 8 | return businessObject; 9 | }; -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Default LF unix as eof 2 | * text eol=lf 3 | 4 | # Use LF Unix compliant as eof 5 | *.sh text eol=lf 6 | *.java text eol=lf 7 | 8 | # Use CRLF for windows file 9 | *.bat text eol=crlf 10 | *.cmd text eol=crlf 11 | 12 | # Binary files 13 | *.gif binary 14 | *.png binary 15 | *.jpg binary 16 | *.jpeg binary 17 | *.ico binary 18 | *.so binary 19 | *.dll binary 20 | *.eot binary 21 | *.ttf binary 22 | *.otf binary 23 | *.svg binary 24 | *.woff binary 25 | *.woff2 binary 26 | -------------------------------------------------------------------------------- /language-executor/src/main/java/org/shared/code/languageexecutor/LanguageExecutorApplication.java: -------------------------------------------------------------------------------- 1 | package org.shared.code.languageexecutor; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class LanguageExecutorApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(LanguageExecutorApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/client/index.js: -------------------------------------------------------------------------------- 1 | import { 2 | registerBpmnJSModdleExtension, 3 | registerBpmnJSPlugin, registerClientExtension 4 | } from 'camunda-modeler-plugin-helpers'; 5 | 6 | import BpmnExtensionModule from './bpmn-js-extension'; 7 | import CodeFragment from './react/Code/CodeFragment'; 8 | 9 | import dataModdle from './bpmn-js-extension/propertiesProvider/descriptors/data.json'; 10 | 11 | registerBpmnJSPlugin(BpmnExtensionModule); 12 | registerBpmnJSModdleExtension(dataModdle); 13 | 14 | registerClientExtension(CodeFragment); 15 | -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/client/react/Code/RunPanel.js: -------------------------------------------------------------------------------- 1 | import React from 'camunda-modeler-plugin-helpers/react'; 2 | 3 | /** 4 | * Functional component for the run/stop buttons section 5 | * @param props 6 | * @returns {JSX.Element} 7 | * @constructor 8 | */ 9 | const RunPanel = props => { 10 | 11 | return (
12 | 13 | 14 |
); 15 | }; 16 | export default RunPanel; -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/client/bpmn-js-extension/propertiesProvider/descriptors/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Data Token properties", 3 | "prefix": "data", 4 | "uri": "http://data.sh4.red", 5 | "xml": { 6 | "tagAlias": "lowerCase" 7 | }, 8 | "associations": [], 9 | "types": [ 10 | { 11 | "name": "DataScriptTask", 12 | "extends": [ 13 | "bpmn:ScriptTask" 14 | ], 15 | "properties": [ 16 | { 17 | "name": "scriptResultVariableType", 18 | "isAttr": true, 19 | "type": "String" 20 | } 21 | ] 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /language-executor/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=12421 2 | 3 | logging.level.org.springframework = INFO 4 | logging.level.org.shared = INFO 5 | 6 | spring.jackson.serialization.write-dates-as-timestamps=false 7 | spring.messages.basename=messages 8 | 9 | ## MULTIPART (MultipartProperties) 10 | # Enable multipart uploads 11 | spring.servlet.multipart.enabled=true 12 | # Threshold after which files are written to disk. 13 | spring.servlet.multipart.file-size-threshold=2KB 14 | # Max file size. 15 | spring.servlet.multipart.max-file-size=128MB 16 | # Max Request Size 17 | spring.servlet.multipart.max-request-size=200MB -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/client/assets/NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2013 Google LLC 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | https://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | **/HELP.md 3 | .history 4 | **/node/ 5 | 6 | **/node_modules/ 7 | **/dist/ 8 | **/target 9 | 10 | .mvn 11 | !.mvn/wrapper/maven-wrapper.jar 12 | !**/src/main/**/target/ 13 | !**/src/test/**/target/ 14 | 15 | ### STS ### 16 | **/.apt_generated 17 | **/.classpath 18 | **/.factorypath 19 | **/.project 20 | **/.settings 21 | **/.springBeans 22 | **/.sts4-cache 23 | 24 | ### IntelliJ IDEA ### 25 | **/.idea 26 | **/*.iws 27 | **/*.iml 28 | **/*.ipr 29 | 30 | ### NetBeans ### 31 | **/nbproject/private/ 32 | **/nbbuild/ 33 | **/nbdist/ 34 | **/.nb-gradle/ 35 | **/build/ 36 | !**/src/main/**/build/ 37 | !**/src/test/**/build/ 38 | 39 | ### VS Code ### 40 | **/.vscode/ 41 | -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/client/bpmn-js-extension/index.js: -------------------------------------------------------------------------------- 1 | import CodePropertiesProvider from './propertiesProvider/CodePropertiesProvider'; 2 | import DisableModelingCode from './disableModeling/DisableModeling'; 3 | import EventBasedExecutor from './executor/EventBasedExecutor'; 4 | 5 | /** 6 | * A bpmn-js module, defining all extension services and their dependencies. 7 | * 8 | */ 9 | export default { 10 | __init__: [ 'codePropertiesProvider', 'disableModelingCode', 'eventBasedExecutor' ], 11 | codePropertiesProvider: [ 'type', CodePropertiesProvider ], 12 | disableModelingCode: [ 'type', DisableModelingCode ], 13 | eventBasedExecutor: [ 'type', EventBasedExecutor ] 14 | }; 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /language-executor/src/main/java/org/shared/code/languageexecutor/parser/PrimitiveParser.java: -------------------------------------------------------------------------------- 1 | package org.shared.code.languageexecutor.parser; 2 | 3 | import org.camunda.bpm.engine.variable.value.PrimitiveValue; 4 | import org.camunda.bpm.engine.variable.value.TypedValue; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * The type Primitive parser. 9 | */ 10 | @Component 11 | public class PrimitiveParser implements VariableParser { 12 | @Override 13 | public boolean supportsTypedValue(TypedValue typedValue) { 14 | return typedValue instanceof PrimitiveValue; 15 | } 16 | 17 | @Override 18 | public Object parse(TypedValue variable) { 19 | return variable.getValue(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /language-executor/src/main/java/org/shared/code/languageexecutor/parser/VariableParser.java: -------------------------------------------------------------------------------- 1 | package org.shared.code.languageexecutor.parser; 2 | 3 | import org.camunda.bpm.engine.variable.value.TypedValue; 4 | 5 | /** 6 | * The interface Variable parser. 7 | */ 8 | public interface VariableParser { 9 | 10 | /** 11 | * Checks if the typed value is supported. 12 | * 13 | * @param typedValue the typed value 14 | * @return the boolean true if supported 15 | */ 16 | boolean supportsTypedValue(TypedValue typedValue); 17 | 18 | /** 19 | * Parse the object contained in the {@param variable} 20 | * 21 | * @param variable the variable 22 | * @return the object inside the {@link TypedValue} 23 | */ 24 | Object parse(TypedValue variable); 25 | } 26 | -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/test/TestHelper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2014-present Camunda Services GmbH 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | export * from 'bpmn-js/test/helper'; 8 | 9 | import { 10 | insertCSS 11 | } from 'bpmn-js/test/helper'; 12 | 13 | insertCSS('style.css', [ 14 | '@import "/base/assets/css/normalize.css";', 15 | '@import "/base/assets/css/bpmn-js-token-simulation.css"' 16 | ].join('\n')); 17 | 18 | insertCSS('diagram-js.css', require('diagram-js/assets/diagram-js.css')); 19 | 20 | insertCSS('bpmn-font.css', require('bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css')); 21 | 22 | insertCSS('diagram-js-testing.css', 23 | 'body .test-container { height: auto }' + 24 | 'body .test-container .test-content-container { height: 90vmin; }' 25 | ); -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Java CI with Maven 5 | 6 | on: 7 | push: 8 | branches: [ main, develop ] 9 | pull_request: 10 | branches: [ main, develop ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up JDK 11 20 | uses: actions/setup-java@v2 21 | with: 22 | java-version: '11' 23 | distribution: 'adopt' 24 | cache: maven 25 | - name: Build with Maven 26 | run: mvn -B package --file pom.xml 27 | -------------------------------------------------------------------------------- /language-executor/src/main/java/org/shared/code/languageexecutor/parser/XmlParser.java: -------------------------------------------------------------------------------- 1 | package org.shared.code.languageexecutor.parser; 2 | 3 | import org.camunda.bpm.engine.variable.value.TypedValue; 4 | import org.camunda.spin.Spin; 5 | import org.camunda.spin.plugin.variable.value.XmlValue; 6 | import org.camunda.spin.xml.SpinXmlElement; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * The type Xml parser. 11 | */ 12 | @Component 13 | public class XmlParser implements VariableParser { 14 | 15 | @Override 16 | public boolean supportsTypedValue(TypedValue typedValue) { 17 | return typedValue instanceof XmlValue; 18 | } 19 | 20 | @Override 21 | public SpinXmlElement parse(TypedValue variable) { 22 | return Spin.XML(variable.getValue()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/client/utils/editorConsole.js: -------------------------------------------------------------------------------- 1 | import { escape } from 'lodash'; 2 | 3 | export default function editorConsole(container) { 4 | 5 | let empty = true; 6 | const add = something => { 7 | const node = document.createElement('div'); 8 | let text = String(something); 9 | let parsed; 10 | 11 | try { 12 | parsed = String(JSON.parse(text)); 13 | } catch (error) { 14 | parsed = text; 15 | } 16 | 17 | node.innerHTML = '

' + escape(parsed) + '

'; 18 | if (empty) { 19 | container.innerHTML = ''; 20 | empty = false; 21 | } 22 | container.appendChild(node); 23 | }; 24 | 25 | return { 26 | clearConsole: function clearConsole(hintValue = '') { 27 | empty = true; 28 | container.innerHTML = hintValue; 29 | }, 30 | addToConsole: add 31 | }; 32 | } -------------------------------------------------------------------------------- /language-executor/src/main/java/org/shared/code/languageexecutor/parser/JsonParser.java: -------------------------------------------------------------------------------- 1 | package org.shared.code.languageexecutor.parser; 2 | 3 | import org.camunda.bpm.engine.variable.value.TypedValue; 4 | import org.camunda.spin.Spin; 5 | import org.camunda.spin.json.SpinJsonNode; 6 | import org.camunda.spin.plugin.variable.value.JsonValue; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * The type Json parser. 11 | */ 12 | @Component 13 | public class JsonParser implements VariableParser { 14 | 15 | @Override 16 | public boolean supportsTypedValue(TypedValue typedValue) { 17 | return (typedValue instanceof JsonValue) || typedValue instanceof org.camunda.bpm.client.variable.value.JsonValue; 18 | } 19 | 20 | @Override 21 | public SpinJsonNode parse(TypedValue variable) { 22 | return Spin.JSON(variable.getValue()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /language-executor/src/main/java/org/shared/code/languageexecutor/exception/VariableParserException.java: -------------------------------------------------------------------------------- 1 | package org.shared.code.languageexecutor.exception; 2 | 3 | import org.camunda.bpm.engine.variable.value.TypedValue; 4 | 5 | /** 6 | * The type Variable parser exception. 7 | */ 8 | public class VariableParserException extends RuntimeException { 9 | 10 | private final TypedValue variable; 11 | 12 | /** 13 | * Instantiates a new Variable parser exception. 14 | * 15 | * @param variable the variable that thrown an exception 16 | * @param message the message thrown 17 | */ 18 | public VariableParserException(TypedValue variable, String message) { 19 | super(message); 20 | this.variable = variable; 21 | } 22 | 23 | /** 24 | * Gets variable. 25 | * 26 | * @return the variable 27 | */ 28 | public TypedValue getVariable() { 29 | return variable; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /language-executor/src/main/java/org/shared/code/languageexecutor/dto/ContextType.java: -------------------------------------------------------------------------------- 1 | package org.shared.code.languageexecutor.dto; 2 | 3 | /** 4 | * The enum Context type. 5 | */ 6 | public enum ContextType { 7 | /** 8 | * Boolean context type. 9 | */ 10 | BOOLEAN, 11 | /** 12 | * Bytes context type. 13 | */ 14 | BYTES, 15 | /** 16 | * String context type. 17 | */ 18 | STRING, 19 | /** 20 | * Short context type. 21 | */ 22 | SHORT, 23 | /** 24 | * Double context type. 25 | */ 26 | DOUBLE, 27 | /** 28 | * Integer context type. 29 | */ 30 | INTEGER, 31 | /** 32 | * Long context type. 33 | */ 34 | LONG, 35 | /** 36 | * Date context type. 37 | */ 38 | DATE, 39 | /** 40 | * Datetime context type. 41 | */ 42 | DATETIME, 43 | /** 44 | * Json context type. 45 | */ 46 | JSON, 47 | /** 48 | * Xml context type. 49 | */ 50 | XML 51 | } 52 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /language-executor/src/test/resources/scripts/offersJson.json: -------------------------------------------------------------------------------- 1 | { 2 | "requestsArray": [ 3 | { "operator" : "A", "requestNum": 1, "bondsNum": 750, "price": 96.15 }, 4 | { "operator" : "B", "requestNum": 1, "bondsNum": 1500, "price": 95.90 }, 5 | { "operator" : "D", "requestNum": 1, "bondsNum": 1000, "price": 95.90 }, 6 | { "operator" : "B", "requestNum": 2, "bondsNum": 1100, "price": 95.88 }, 7 | { "operator" : "C", "requestNum": 1, "bondsNum": 1000, "price": 95.85 }, 8 | { "operator" : "D", "requestNum": 2, "bondsNum": 800, "price": 95.84 }, 9 | { "operator" : "A", "requestNum": 2, "bondsNum": 1000, "price": 95.82 }, 10 | { "operator" : "C", "requestNum": 2, "bondsNum": 700, "price": 95.82 }, 11 | { "operator" : "B", "requestNum": 3, "bondsNum": 950, "price": 95.70 }, 12 | { "operator" : "D", "requestNum": 3, "bondsNum": 800, "price": 95.65 }, 13 | { "operator" : "C", "requestNum": 3, "bondsNum": 1500, "price": 94.80 }, 14 | { "operator" : "A", "requestNum": 3, "bondsNum": 900, "price": 94.00 } 15 | ] 16 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Shared Technologies SRL 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/backend/NOTICE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 bpmn.io 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Shared Technologies SRL 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/client/react/UI/EditorModal.js: -------------------------------------------------------------------------------- 1 | import React from 'camunda-modeler-plugin-helpers/react'; 2 | import { Modal } from 'camunda-modeler-plugin-helpers/components'; 3 | 4 | import CodeEditor from '../Code/CodeEditor'; 5 | 6 | // polyfill upcoming structural components 7 | const Title = Modal.Title || (({ children }) =>

{children}

); 8 | const Body = Modal.Body || (({ children }) =>
{children}
); 9 | const Footer = Modal.Footer || (({ children }) =>
{children}
); 10 | 11 | /** 12 | * Functional component to create a modal window for Code Editor 13 | * @param props 14 | * @returns {JSX.Element} 15 | */ 16 | const editorModal = (props) => { 17 | 18 | return 19 | {props.title} 20 | 21 |
22 | 23 | 24 | 25 | 30 |
; 31 | }; 32 | 33 | export default editorModal; -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/client/bpmn-js-extension/executor/EventBasedExecutor.js: -------------------------------------------------------------------------------- 1 | import { RUN_CODE_EDITOR, GET_DATA_TYPES, DATA_TYPES } from '../../utils/EventHelper'; 2 | import GroovyAPI from '../../utils/executors/GroovyAPI'; 3 | import { encode } from 'js-base64'; 4 | 5 | /** 6 | * Implements intercommunication events between different plugins/modules 7 | * @param eventBus 8 | * @constructor 9 | */ 10 | export default function EventBasedExecutor(eventBus) { 11 | 12 | const LANGUAGE_EXECUTOR_PORT = process.env.LANGUAGE_EXECUTOR_PORT || '12421'; 13 | 14 | /** 15 | * Receives data from the UI. Encodes the code script and calls the LanguageExecutor (groovy) to run it in safe mode 16 | */ 17 | eventBus.on(RUN_CODE_EDITOR, (event, code, context) => { 18 | 19 | const groovyExecutor = new GroovyAPI(`http://localhost:${LANGUAGE_EXECUTOR_PORT}`); 20 | const base64 = encode(code); 21 | return groovyExecutor.executeGroovy({ code: base64, context: context }); 22 | }); 23 | 24 | /** 25 | * Returns the DATA_TYPES available for context variables 26 | */ 27 | eventBus.on(GET_DATA_TYPES, () => { 28 | return { 29 | dataTypes: DATA_TYPES 30 | }; 31 | }); 32 | } 33 | 34 | EventBasedExecutor.$inject = [ 'eventBus' ]; -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/client/utils/EventHelper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A list of event types called on {@link eventBus} 3 | * @type {string} 4 | */ 5 | 6 | let codePrefix = 'codeEditor'; 7 | 8 | const LOADED_CODE_EDITOR = codePrefix + '.init'; 9 | const OPEN_CODE_EDITOR = codePrefix + '.open'; 10 | const SAVE_CODE_EDITOR = codePrefix + '.saveData'; 11 | const RUN_CODE_EDITOR = codePrefix + '.run'; 12 | const STOP_CODE_EDITOR = codePrefix + '.stop'; 13 | const GET_DATA_TYPES = codePrefix + '.getTypes'; 14 | 15 | 16 | export { 17 | OPEN_CODE_EDITOR, 18 | SAVE_CODE_EDITOR, 19 | RUN_CODE_EDITOR, 20 | STOP_CODE_EDITOR, 21 | LOADED_CODE_EDITOR, 22 | GET_DATA_TYPES 23 | }; 24 | 25 | /** 26 | * Variable Data Types 27 | */ 28 | export const DATA_TYPES = [ 29 | { value: '', name: '' }, 30 | { value: 'BOOLEAN', name: 'Boolean' }, 31 | { value: 'BYTES', name: 'Byte Array' }, 32 | { value: 'STRING', name: 'String' }, 33 | { value: 'SHORT', name: 'Short' }, 34 | { value: 'DOUBLE', name: 'Double' }, 35 | { value: 'INTEGER', name: 'Integer' }, 36 | { value: 'LONG', name: 'Long' }, 37 | { value: 'DATE', name: 'Date' }, 38 | { value: 'DATETIME', name: 'Date & time' }, 39 | { value: 'JSON', name: 'JSON' }, 40 | { value: 'XML', name: 'XML' } 41 | ] 42 | ; 43 | -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/backend/groovy.js: -------------------------------------------------------------------------------- 1 | const execa = require('execa'); 2 | const path = require('path'); 3 | 4 | const LANGUAGE_EXECUTOR_PATH = process.env.LANGUAGE_EXECUTOR || path.resolve(__dirname, '../assets/language-executor.jar'); 5 | const LANGUAGE_EXECUTOR_PORT = process.env.LANGUAGE_EXECUTOR_PORT || '12421'; 6 | let groovyProcess; 7 | 8 | module.exports = { 9 | startGroovyExecutor, 10 | stopGroovyExecutor, 11 | isProcessActive 12 | }; 13 | 14 | async function startGroovyExecutor(javaPath) { 15 | 16 | try { 17 | const args = [ 18 | '-jar', 19 | LANGUAGE_EXECUTOR_PATH, 20 | `--server.port=${LANGUAGE_EXECUTOR_PORT}` 21 | ]; 22 | 23 | groovyProcess = execa(javaPath, args); 24 | console.log('Started java with PID: ' + groovyProcess.pid); 25 | groovyProcess.stdout.pipe(process.stdout); 26 | groovyProcess.stderr.pipe(process.stderr); 27 | } catch (error) { 28 | console.log(error); 29 | throw new Error('Cannot find java executable'); 30 | } 31 | } 32 | 33 | function stopGroovyExecutor() { 34 | if (!groovyProcess) { 35 | console.log('No process found. Exiting...'); 36 | return; 37 | } 38 | 39 | groovyProcess.kill(); 40 | } 41 | 42 | function isProcessActive() { 43 | return !!groovyProcess; 44 | } -------------------------------------------------------------------------------- /language-executor/README.md: -------------------------------------------------------------------------------- 1 | ## Language (Groovy) Executor 2 | 3 | A simple Spring Boot application which exposes a controller method ("/groovy/execute") to execute a single groovy script with its context variables and returns the results. 4 | 5 | At the moment, our purpose was to execute groovy scripts (one by one), but a simple refactoring could generalize the pattern for multiple languages (if needed). 6 | 7 | ### Details 8 | 9 | The application exposes a single POST mapping rest method ("/groovy/execute"), which gets two input parameters: 10 | * a String "code" variable, containing the code to execute in Base64 11 | * a List of [Context](./src/main/java/org/shared/code/languageexecutor/dto/Context.java) variables, containing the context variables needed for the execution in the form of { name : 'name', value: 'value', type: [ContextType](./src/main/java/org/shared/code/languageexecutor/dto/ContextType.java)} 12 | 13 | and returns a JSON object containing the returned **output**, println **logs** and eventually the execution **error**. 14 | 15 | ### TODOs 16 | 17 | * ~~Improve sandboxing of groovy scripts~~ 18 | * Add a "stopExecution" method to the controller to stop groovy script execution in case of error (infinite loops? strictly related to the first todo.) 19 | * Generalize controller pattern (replace "groovy" with a "language" pathVariable should do the trick) and handle different languages -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/client/utils/executors/GroovyAPI.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple API class that calls our language executor, returning its result 3 | */ 4 | export default class GroovyAPI { 5 | 6 | constructor(restEndpoint) { 7 | this.restEndpoint = restEndpoint; 8 | } 9 | 10 | async executeGroovy(payload) { 11 | const headers = { 12 | accept: 'application/json' 13 | }; 14 | 15 | let res; 16 | 17 | try { 18 | res = await fetch(this.restEndpoint + '/groovy/execute', { 19 | method: 'POST', 20 | headers, 21 | body: JSON.stringify(payload) 22 | }); 23 | if (!res.ok) { 24 | return { error: `${res.status} ${res.statusText}` }; 25 | } 26 | 27 | return res.json(); 28 | } catch (error) { 29 | return { 30 | error: `Unexpected error calling executor: ${error}` 31 | }; 32 | } 33 | } 34 | 35 | 36 | async executeGroovyVectors(payload) { 37 | const headers = { 38 | accept: 'application/json' 39 | }; 40 | 41 | let res; 42 | 43 | try { 44 | res = await fetch(this.restEndpoint + '/groovy/execute/vectors', { 45 | method: 'POST', 46 | headers, 47 | body: JSON.stringify(payload) 48 | }); 49 | if (!res.ok) { 50 | return { error: `${res.status} ${res.statusText}` }; 51 | } 52 | 53 | return res.json(); 54 | } catch (error) { 55 | return { 56 | error: `Unexpected error calling executor: ${error}` 57 | }; 58 | } 59 | } 60 | 61 | } -------------------------------------------------------------------------------- /language-executor/src/main/java/org/shared/code/languageexecutor/service/VariableParserService.java: -------------------------------------------------------------------------------- 1 | package org.shared.code.languageexecutor.service; 2 | 3 | import org.camunda.bpm.engine.variable.value.TypedValue; 4 | import org.shared.code.languageexecutor.exception.VariableParserException; 5 | import org.shared.code.languageexecutor.parser.VariableParser; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.List; 12 | import java.util.Optional; 13 | 14 | /** 15 | * The type Variable parser service. 16 | */ 17 | @Service 18 | public class VariableParserService { 19 | 20 | private static final Logger log = LoggerFactory.getLogger(VariableParserService.class); 21 | 22 | /** 23 | * The collection of Variable parsers 24 | */ 25 | @Autowired 26 | List variableParsers; 27 | 28 | /** 29 | * Parse the variable and return the correspondent object 30 | * 31 | * @param variable the variable 32 | * @return the object 33 | */ 34 | public Object parse(TypedValue variable) { 35 | log.info("Searching for a valid VariableParser"); 36 | Optional compatibleParser = variableParsers.stream().filter(p -> p.supportsTypedValue(variable)).findAny(); 37 | 38 | if (compatibleParser.isEmpty()) { 39 | throw new VariableParserException(variable, "Cannot find a compatible parser for the received variable"); 40 | } else { 41 | return compatibleParser.get().parse(variable); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /language-executor/src/main/java/org/shared/code/languageexecutor/dto/Context.java: -------------------------------------------------------------------------------- 1 | package org.shared.code.languageexecutor.dto; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * The type Context. 7 | */ 8 | public class Context implements Serializable { 9 | 10 | private String name; 11 | private String value; 12 | private ContextType type; 13 | 14 | /** 15 | * Gets name. 16 | * 17 | * @return the name 18 | */ 19 | public String getName() { 20 | return name; 21 | } 22 | 23 | /** 24 | * Sets name. 25 | * 26 | * @param name the name 27 | */ 28 | public void setName(String name) { 29 | this.name = name; 30 | } 31 | 32 | /** 33 | * Gets value. 34 | * 35 | * @return the value 36 | */ 37 | public String getValue() { 38 | return value; 39 | } 40 | 41 | /** 42 | * Sets value. 43 | * 44 | * @param value the value 45 | */ 46 | public void setValue(String value) { 47 | this.value = value; 48 | } 49 | 50 | /** 51 | * Gets type. 52 | * 53 | * @return the type 54 | */ 55 | public ContextType getType() { 56 | return type; 57 | } 58 | 59 | /** 60 | * Sets type. 61 | * 62 | * @param type the type 63 | */ 64 | public void setType(ContextType type) { 65 | this.type = type; 66 | } 67 | 68 | @Override 69 | public String toString() { 70 | return "Context{" + 71 | "name='" + name + '\'' + 72 | ", value=" + value + 73 | ", type='" + type + '\'' + 74 | '}'; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /plugin-module/modeler-plugin-code/client/react/UI/Input.js: -------------------------------------------------------------------------------- 1 | import React from 'camunda-modeler-plugin-helpers/react'; 2 | 3 | /** 4 | * Various field implementations as React functional components 5 | * @param props 6 | * @returns {JSX.Element} 7 | */ 8 | const input = (props) => { 9 | let inputElement; 10 | let validationError = null; 11 | let inputClasses = [ 'contextInput' ]; 12 | 13 | if (props.invalid) { 14 | inputClasses.push('invalid'); // Da controllare 15 | validationError =

{props.errorMessage}

; 16 | } 17 | 18 | switch (props.elementType) { 19 | case 'textarea': 20 | inputElement =