This is an automated email from the ASF dual-hosted git repository.
jbonofre pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/karaf.git
The following commit(s) were added to refs/heads/main by this push:
new 737eab789f KARAF-6538 - add commands for executing groovy code
new 62289e8909 Merge pull request #1712 from awrb/KARAF-6538
737eab789f is described below
commit 737eab789f4fedb36d3aafb02ef02f7eee97694d
Author: Aleksy Wróblewski <[email protected]>
AuthorDate: Tue Feb 7 00:02:55 2023 +0100
KARAF-6538 - add commands for executing groovy code
---
.../features/specs/src/main/feature/feature.xml | 44 ++++++-------
.../features/standard/src/main/feature/feature.xml | 4 ++
.../src/test/filtered-resources/etc/feature.xml | 4 ++
.../java/org/apache/karaf/itests/GroovyTest.java | 66 +++++++++++++++++++
.../org/apache/karaf/itests/groovy/script.groovy | 22 +++++++
.../developer-guide/developer-commands.adoc | 48 ++++++++++++++
pom.xml | 1 +
shell/groovy/pom.xml | 74 ++++++++++++++++++++++
.../groovy/commands/ExecGroovyCodeAction.java | 69 ++++++++++++++++++++
.../groovy/commands/ExecGroovyFileAction.java | 41 ++++++++++++
.../org.apache.karaf.shell.groovy/commands | 18 ++++++
shell/pom.xml | 1 +
12 files changed, 370 insertions(+), 22 deletions(-)
diff --git a/assemblies/features/specs/src/main/feature/feature.xml
b/assemblies/features/specs/src/main/feature/feature.xml
index 2dd39d631e..3134ad9484 100644
--- a/assemblies/features/specs/src/main/feature/feature.xml
+++ b/assemblies/features/specs/src/main/feature/feature.xml
@@ -150,29 +150,29 @@
</feature>
<!-- groovy -->
- <feature name="groovy" version="3.0.3">
+ <feature name="groovy" version="${groovy.version}">
<feature prerequisite="true">spifly</feature>
- <bundle>mvn:org.codehaus.groovy/groovy/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-ant/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-cli-commons/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-cli-picocli/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-console/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-datetime/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-docgenerator/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-groovydoc/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-groovysh/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-jmx/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-json/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-macro/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-nio/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-servlet/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-sql/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-swing/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-templates/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-test/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-test-junit5/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-testng/3.0.3</bundle>
- <bundle>mvn:org.codehaus.groovy/groovy-xml/3.0.3</bundle>
+ <bundle>mvn:org.codehaus.groovy/groovy/${groovy.version}</bundle>
+ <bundle>mvn:org.codehaus.groovy/groovy-ant/${groovy.version}</bundle>
+
<bundle>mvn:org.codehaus.groovy/groovy-cli-commons/${groovy.version}</bundle>
+
<bundle>mvn:org.codehaus.groovy/groovy-cli-picocli/${groovy.version}</bundle>
+
<bundle>mvn:org.codehaus.groovy/groovy-console/${groovy.version}</bundle>
+
<bundle>mvn:org.codehaus.groovy/groovy-datetime/${groovy.version}</bundle>
+
<bundle>mvn:org.codehaus.groovy/groovy-docgenerator/${groovy.version}</bundle>
+
<bundle>mvn:org.codehaus.groovy/groovy-groovydoc/${groovy.version}</bundle>
+
<bundle>mvn:org.codehaus.groovy/groovy-groovysh/${groovy.version}</bundle>
+ <bundle>mvn:org.codehaus.groovy/groovy-jmx/${groovy.version}</bundle>
+ <bundle>mvn:org.codehaus.groovy/groovy-json/${groovy.version}</bundle>
+ <bundle>mvn:org.codehaus.groovy/groovy-macro/${groovy.version}</bundle>
+ <bundle>mvn:org.codehaus.groovy/groovy-nio/${groovy.version}</bundle>
+
<bundle>mvn:org.codehaus.groovy/groovy-servlet/${groovy.version}</bundle>
+ <bundle>mvn:org.codehaus.groovy/groovy-sql/${groovy.version}</bundle>
+ <bundle>mvn:org.codehaus.groovy/groovy-swing/${groovy.version}</bundle>
+
<bundle>mvn:org.codehaus.groovy/groovy-templates/${groovy.version}</bundle>
+ <bundle>mvn:org.codehaus.groovy/groovy-test/${groovy.version}</bundle>
+
<bundle>mvn:org.codehaus.groovy/groovy-test-junit5/${groovy.version}</bundle>
+
<bundle>mvn:org.codehaus.groovy/groovy-testng/${groovy.version}</bundle>
+ <bundle>mvn:org.codehaus.groovy/groovy-xml/${groovy.version}</bundle>
</feature>
</features>
diff --git a/assemblies/features/standard/src/main/feature/feature.xml
b/assemblies/features/standard/src/main/feature/feature.xml
index 0d07990190..512cdd0ada 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -379,6 +379,10 @@ disableEofExit = false
<feature>jline</feature>
<bundle
start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.core/${project.version}</bundle>
<bundle
start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.commands/${project.version}</bundle>
+ <conditional>
+ <condition>groovy</condition>
+ <bundle
start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.groovy/${project.version}</bundle>
+ </conditional>
</feature>
<feature name="jline" version="${jline.version}" hidden="true">
diff --git a/itests/test/src/test/filtered-resources/etc/feature.xml
b/itests/test/src/test/filtered-resources/etc/feature.xml
index f827ff6184..66bd2da93a 100644
--- a/itests/test/src/test/filtered-resources/etc/feature.xml
+++ b/itests/test/src/test/filtered-resources/etc/feature.xml
@@ -254,6 +254,10 @@
<bundle dependency="true"
start-level="30">mvn:org.jline/jline/${jline.version}</bundle>
<bundle
start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.core/${project.version}</bundle>
<bundle
start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.commands/${project.version}</bundle>
+ <conditional>
+ <condition>groovy</condition>
+ <bundle
start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.groovy/${project.version}</bundle>
+ </conditional>
</feature>
<feature name="shell-compat" description="Karaf Shell Compatibility"
version="${project.version}">
diff --git a/itests/test/src/test/java/org/apache/karaf/itests/GroovyTest.java
b/itests/test/src/test/java/org/apache/karaf/itests/GroovyTest.java
new file mode 100644
index 0000000000..ebee38ca81
--- /dev/null
+++ b/itests/test/src/test/java/org/apache/karaf/itests/GroovyTest.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.itests;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import static
org.ops4j.pax.exam.karaf.options.KarafDistributionOption.replaceConfigurationFile;
+
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class GroovyTest extends BaseTest {
+
+ @Configuration
+ public Option[] config() {
+ List<Option> result = new LinkedList<>(Arrays.asList(super.config()));
+ result.add(replaceConfigurationFile("script.groovy",
+
getConfigFile("/org/apache/karaf/itests/groovy/script.groovy")));
+ return result.toArray(new Option[result.size()]);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ installAndAssertFeature("groovy");
+ }
+
+ @Test
+ public void execGroovyCodeCommand() throws Exception {
+ String resultNoArgs = executeCommand("groovy:exec \""
+ + "def add(x, y) {\n"
+ + " return x + y \n"
+ + "}\n"
+ + "println add(1, 2)\"");
+ assertContains("3", resultNoArgs);
+
+ String resultTwoArgs = executeCommand("groovy:exec \"(x as int) + (y
as int)\" x=1 y=2");
+ assertContains("3", resultTwoArgs);
+ }
+
+ @Test
+ public void execGroovyFileCommand() throws Exception {
+ String result = executeCommand("groovy:exec-file script.groovy");
+ assertContains("3", result);
+ }
+}
diff --git
a/itests/test/src/test/resources/org/apache/karaf/itests/groovy/script.groovy
b/itests/test/src/test/resources/org/apache/karaf/itests/groovy/script.groovy
new file mode 100644
index 0000000000..bcc58bdd54
--- /dev/null
+++
b/itests/test/src/test/resources/org/apache/karaf/itests/groovy/script.groovy
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+def add(x, y) {
+ return x + y
+}
+
+println add(1, 2)
diff --git a/manual/src/main/asciidoc/developer-guide/developer-commands.adoc
b/manual/src/main/asciidoc/developer-guide/developer-commands.adoc
index 75863d4e1e..7d795d6bcd 100644
--- a/manual/src/main/asciidoc/developer-guide/developer-commands.adoc
+++ b/manual/src/main/asciidoc/developer-guide/developer-commands.adoc
@@ -241,3 +241,51 @@ karaf@root()> bundle:watch *
----
will monitor all bundles that have a location matching mvn:* and '-SNAPSHOT'
in their URL.
+
+==== Groovy
+With the `groovy` feature installed, you can execute Groovy script files or
code directly in the shell:
+----
+karaf@root()> groovy:exec--help
+DESCRIPTION
+ groovy:exec
+
+ Executes Groovy code
+
+SYNTAX
+ groovy:exec script [args]
+
+ARGUMENTS
+ script
+ Groovy code
+ (required)
+ args
+ Arguments in the format of key=value
+
+karaf@root()> groovy:exec-file --help
+DESCRIPTION
+ groovy:exec-file
+
+ Executes Groovy file
+
+SYNTAX
+ groovy:exec-file path
+
+ARGUMENTS
+ path
+ Groovy script file path
+ (required)
+
+
+karaf@root()> groovy:exec "1+1"
+2
+karaf@root()> groovy:exec "(x as int) + (y as int)" x=1 y=2
+3
+karaf@root()> cat /foo/bar/test.groovy
+def add(x, y) {
+ return x + y
+}
+
+add(1,2)
+karaf@root()> groovy:exec-file /foo/bar/test.groovy
+3
+----
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index a86a9c89c2..f104ba2221 100644
--- a/pom.xml
+++ b/pom.xml
@@ -192,6 +192,7 @@
<servlet.spec.groupId>javax.servlet</servlet.spec.groupId>
<servlet.spec.artifactId>javax.servlet-api</servlet.spec.artifactId>
<servlet.spec.version>3.1.0</servlet.spec.version>
+ <groovy.version>3.0.3</groovy.version>
<geronimo.jms-spec.version>1.1.1</geronimo.jms-spec.version>
<geronimo.jta-spec.version>1.1.1</geronimo.jta-spec.version>
diff --git a/shell/groovy/pom.xml b/shell/groovy/pom.xml
new file mode 100644
index 0000000000..57f43fe88f
--- /dev/null
+++ b/shell/groovy/pom.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>shell</artifactId>
+ <version>4.4.4-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>org.apache.karaf.shell.groovy</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Karaf :: Shell :: Groovy</name>
+ <description>This bundle provides Groovy support to the Karaf
console.</description>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.karaf</groupId>
+ <artifactId>karaf-bom</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy-all</artifactId>
+ <version>${groovy.version}</version>
+ <type>pom</type>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.karaf.tooling</groupId>
+ <artifactId>karaf-services-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git
a/shell/groovy/src/main/java/org/apache/karaf/shell/groovy/commands/ExecGroovyCodeAction.java
b/shell/groovy/src/main/java/org/apache/karaf/shell/groovy/commands/ExecGroovyCodeAction.java
new file mode 100644
index 0000000000..1a0c4c0b6b
--- /dev/null
+++
b/shell/groovy/src/main/java/org/apache/karaf/shell/groovy/commands/ExecGroovyCodeAction.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.karaf.shell.groovy.commands;
+
+import groovy.lang.Binding;
+import groovy.lang.GroovyShell;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+import java.util.List;
+
+@Command(scope = "groovy",
+ name = "exec",
+ description = "Executes Groovy code")
+@Service
+public class ExecGroovyCodeAction implements Action {
+
+ @Argument(index = 0, name = "script", description = "Groovy code",
required = true)
+ private String groovyCode;
+
+
+ @Argument(index = 1, name = "args", description = "Arguments in the format
of key=value", multiValued = true)
+ private List<String> args;
+
+ @Override
+ public Object execute() throws Exception {
+ Binding binding = new Binding();
+
+ if (args != null)
+ {
+ for (String arg : args)
+ {
+ int splitAt = arg.indexOf("=");
+ if (splitAt <= 0)
+ {
+ throw new IllegalArgumentException("Invalid argument " +
arg);
+ }
+ else
+ {
+ String key = arg.substring(0, splitAt);
+ String value = arg.substring(splitAt + 1);
+ binding.setVariable(key, value);
+ }
+ }
+ }
+
+ GroovyShell sh = new GroovyShell(binding);
+ System.out.println(sh.evaluate(groovyCode));
+
+ return null;
+ }
+}
diff --git
a/shell/groovy/src/main/java/org/apache/karaf/shell/groovy/commands/ExecGroovyFileAction.java
b/shell/groovy/src/main/java/org/apache/karaf/shell/groovy/commands/ExecGroovyFileAction.java
new file mode 100644
index 0000000000..7f4e62c375
--- /dev/null
+++
b/shell/groovy/src/main/java/org/apache/karaf/shell/groovy/commands/ExecGroovyFileAction.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.karaf.shell.groovy.commands;
+
+import groovy.lang.GroovyShell;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+import java.io.File;
+
+@Command(scope = "groovy", name = "exec-file", description = "Executes Groovy
file")
+@Service
+public class ExecGroovyFileAction implements Action {
+
+ @Argument(index = 0, name = "path", description = "Groovy script file
path", required = true)
+ private String filePath;
+
+ @Override
+ public Object execute() throws Exception {
+ GroovyShell sh = new GroovyShell();
+ System.out.println(sh.evaluate(new File(filePath)));
+ return null;
+ }
+}
diff --git
a/shell/groovy/src/main/resources/META-INF/services/org.apache.karaf.shell.groovy/commands
b/shell/groovy/src/main/resources/META-INF/services/org.apache.karaf.shell.groovy/commands
new file mode 100644
index 0000000000..7b44a57512
--- /dev/null
+++
b/shell/groovy/src/main/resources/META-INF/services/org.apache.karaf.shell.groovy/commands
@@ -0,0 +1,18 @@
+##---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements. See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##---------------------------------------------------------------------------
+org.apache.karaf.shell.groovy.commands.ExecGroovyCodeAction
+org.apache.karaf.shell.groovy.commands.ExecGroovyFileAction
diff --git a/shell/pom.xml b/shell/pom.xml
index 4fe3f398ab..6b4c2bc9c9 100644
--- a/shell/pom.xml
+++ b/shell/pom.xml
@@ -39,6 +39,7 @@
<module>console</module>
<module>table</module>
<module>ssh</module>
+ <module>groovy</module>
</modules>
</project>