2323import io .serverlessworkflow .impl .WorkflowApplication ;
2424import io .serverlessworkflow .impl .WorkflowContext ;
2525import io .serverlessworkflow .impl .WorkflowDefinition ;
26+ import io .serverlessworkflow .impl .WorkflowError ;
27+ import io .serverlessworkflow .impl .WorkflowException ;
2628import io .serverlessworkflow .impl .WorkflowModel ;
2729import io .serverlessworkflow .impl .WorkflowModelFactory ;
2830import io .serverlessworkflow .impl .WorkflowUtils ;
2931import io .serverlessworkflow .impl .expressions .ExpressionUtils ;
3032import java .io .ByteArrayOutputStream ;
33+ import java .util .Arrays ;
3134import java .util .HashMap ;
3235import java .util .Map ;
33- import java .util .Set ;
3436import java .util .concurrent .CompletableFuture ;
3537import java .util .concurrent .ExecutorService ;
3638import org .graalvm .polyglot .Context ;
39+ import org .graalvm .polyglot .PolyglotException ;
3740import org .graalvm .polyglot .Value ;
3841
3942public class RunScriptExecutor implements RunnableTask <RunScript > {
4043
41- private static final Set <String > SUPPORTED_LANGUAGES = Set .of ("js" , "python" );
44+ enum ScriptLanguage {
45+ JS ("js" ),
46+ PYTHON ("python" );
47+
48+ private final String lang ;
49+
50+ ScriptLanguage (String lang ) {
51+ this .lang = lang ;
52+ }
53+
54+ public String getLang () {
55+ return lang ;
56+ }
57+
58+ public static boolean isSupported (String lang ) {
59+ for (ScriptLanguage l : ScriptLanguage .values ()) {
60+ if (l .getLang ().equalsIgnoreCase (lang )) {
61+ return true ;
62+ }
63+ }
64+ return false ;
65+ }
66+ }
4267
4368 @ FunctionalInterface
4469 private interface FnExecutor {
@@ -55,19 +80,21 @@ public void init(RunScript taskConfiguration, WorkflowDefinition definition) {
5580 boolean isAwait = taskConfiguration .isAwait ();
5681
5782 WorkflowApplication application = definition .application ();
58- if (language == null || ! SUPPORTED_LANGUAGES . contains (language . toLowerCase () )) {
83+ if (language == null || ScriptLanguage . isSupported (language )) {
5984 throw new IllegalArgumentException (
6085 "Unsupported script language: "
6186 + language
6287 + ". Supported languages are: "
63- + SUPPORTED_LANGUAGES );
88+ + Arrays . toString ( ScriptLanguage . values ()) );
6489 }
6590
6691 fnExecutor =
6792 (workflowContext , taskContext ) -> {
6893 ByteArrayOutputStream stderr = new ByteArrayOutputStream ();
6994 ByteArrayOutputStream stdout = new ByteArrayOutputStream ();
7095
96+ String lowerLang = language .toLowerCase ();
97+
7198 Map <String , String > envs = new HashMap <>();
7299 if (script .getEnvironment () != null ) {
73100 for (Map .Entry <String , Object > entry :
@@ -101,7 +128,7 @@ public void init(RunScript taskConfiguration, WorkflowDefinition definition) {
101128 }
102129
103130 try (Context context =
104- Context .newBuilder (language . toLowerCase () )
131+ Context .newBuilder (lowerLang )
105132 .err (stderr )
106133 .out (stdout )
107134 .environment (envs )
@@ -114,11 +141,11 @@ public void init(RunScript taskConfiguration, WorkflowDefinition definition) {
114141
115142 args .forEach (
116143 (arg , val ) -> {
117- context .getBindings (language . toLowerCase () ).putMember (arg , val );
144+ context .getBindings (lowerLang ).putMember (arg , val );
118145 });
119146
120- // configure process.env for js
121- if (language .equalsIgnoreCase ("js" )) {
147+ // configure process.env for js environment variables
148+ if (language .equalsIgnoreCase (ScriptLanguage . JS . lang )) {
122149 configureProcessEnv (context , envs );
123150 }
124151
@@ -135,23 +162,38 @@ public void init(RunScript taskConfiguration, WorkflowDefinition definition) {
135162 context .eval (
136163 scriptUnion .getInlineScript ().getLanguage (),
137164 scriptUnion .getInlineScript ().getCode ());
165+
138166 WorkflowModelFactory modelFactory = application .modelFactory ();
139167
168+ int statusCode =
169+ 0 ; // GraalVM does not provide exit code, assuming 0 for successful execution
170+
140171 return switch (taskConfiguration .getReturn ()) {
141172 case ALL ->
142- modelFactory .fromAny (new ProcessResult (0 , stdout .toString (), stderr .toString ()));
173+ modelFactory .fromAny (
174+ new ProcessResult (statusCode , stdout .toString (), stderr .toString ()));
143175 case NONE -> modelFactory .fromNull ();
144- case CODE -> modelFactory .from (0 );
176+ case CODE -> modelFactory .from (statusCode );
145177 case STDOUT -> modelFactory .from (stdout .toString ().trim ());
146178 case STDERR -> modelFactory .from (stderr .toString ().trim ());
147179 };
180+ } catch (PolyglotException e ) {
181+ throw new WorkflowException (WorkflowError .runtime (taskContext , e ).build ());
148182 }
149183 };
150184 }
151185
152- private void configureProcessEnv (Context jsCtx , Map <String , String > envs ) {
153- Value bindings = jsCtx .getBindings ("js" );
154- Value process = jsCtx .eval ("js" , "({ env: {} })" );
186+ /**
187+ * Configures the process.env object in the JavaScript context with the provided environment
188+ * variables.
189+ *
190+ * @param context the GraalVM context
191+ * @param envs the environment variables to set
192+ */
193+ private void configureProcessEnv (Context context , Map <String , String > envs ) {
194+ String js = ScriptLanguage .JS .lang ;
195+ Value bindings = context .getBindings (js );
196+ Value process = context .eval (js , "({ env: {} })" );
155197
156198 for (var entry : envs .entrySet ()) {
157199 process .getMember ("env" ).putMember (entry .getKey (), entry .getValue ());
0 commit comments