Skip to content

Commit 2e48921

Browse files
committed
Add java11actionloop
1 parent 3faee44 commit 2e48921

7 files changed

Lines changed: 389 additions & 0 deletions

File tree

core/java11actionloop/CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<!--
2+
#
3+
# Licensed to the Apache Software Foundation (ASF) under one or more
4+
# contributor license agreements. See the NOTICE file distributed with
5+
# this work for additional information regarding copyright ownership.
6+
# The ASF licenses this file to You under the Apache License, Version 2.0
7+
# (the "License"); you may not use this file except in compliance with
8+
# the License. You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
-->
19+
20+
# Java 11 OpenWhisk Runtime Container
21+
22+
## 1.14.0
23+
- Initial release of actionloop-based Java 11 Action
24+
- adoptopenjdk/openjdk11-openj9:x86_64-ubuntu-jdk-11.0.6_10_openj9-0.18.0-slim

core/java11actionloop/Dockerfile

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one or more
3+
# contributor license agreements. See the NOTICE file distributed with
4+
# this work for additional information regarding copyright ownership.
5+
# The ASF licenses this file to You under the Apache License, Version 2.0
6+
# (the "License"); you may not use this file except in compliance with
7+
# the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
18+
# build go proxy from source
19+
FROM golang:1.12 AS builder_source
20+
RUN env CGO_ENABLED=0 go get github.com/apache/openwhisk-runtime-go/main && mv /go/bin/main /bin/proxy
21+
22+
# or build it from a release
23+
FROM golang:1.12 AS builder_release
24+
ARG GO_PROXY_RELEASE_VERSION=1.12@1.15.0
25+
RUN curl -sL \
26+
https://github.com/apache/openwhisk-runtime-go/archive/{$GO_PROXY_RELEASE_VERSION}.tar.gz\
27+
| tar xzf -\
28+
&& cd openwhisk-runtime-go-*/main\
29+
&& GO111MODULE=on go build -o /bin/proxy
30+
31+
# Use AdoptOpen JDK11, OpenJ9 release version 0.18.1
32+
FROM adoptopenjdk/openjdk11-openj9:x86_64-ubuntu-jdk-11.0.6_10_openj9-0.18.0-slim
33+
34+
# select the builder to use
35+
ARG GO_PROXY_BUILD_FROM=release
36+
37+
RUN rm -rf /var/lib/apt/lists/* && apt-get clean && apt-get update \
38+
&& apt-get install -y --no-install-recommends locales python vim \
39+
&& rm -rf /var/lib/apt/lists/* \
40+
&& locale-gen en_US.UTF-8
41+
42+
ENV LANG="en_US.UTF-8" \
43+
LANGUAGE="en_US:en" \
44+
LC_ALL="en_US.UTF-8" \
45+
VERSION=8 \
46+
UPDATE=222 \
47+
BUILD=10
48+
49+
RUN locale-gen en_US.UTF-8 ;\
50+
mkdir -p /javaAction/action /usr/java/src /usr/java/lib
51+
52+
WORKDIR /javaAction
53+
54+
COPY --from=builder_source /bin/proxy /bin/proxy_source
55+
COPY --from=builder_release /bin/proxy /bin/proxy_release
56+
RUN mv /bin/proxy_${GO_PROXY_BUILD_FROM} /bin/proxy
57+
58+
ADD https://search.maven.org/remotecontent?filepath=com/google/code/gson/gson/2.8.5/gson-2.8.5.jar /usr/java/lib/gson-2.8.5.jar
59+
ADD lib/src/Launcher.java /usr/java/src/Launcher.java
60+
RUN cd /usr/java/src ;\
61+
javac -cp /usr/java/lib/gson-2.8.5.jar Launcher.java ;\
62+
jar cvf /usr/java/lib/launcher.jar *.class
63+
ADD bin/compile /bin/compile
64+
ENV OW_COMPILER=/bin/compile
65+
ENV OW_SAVE_JAR=exec.jar
66+
ENTRYPOINT /bin/proxy

core/java11actionloop/Makefile

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one or more
3+
# contributor license agreements. See the NOTICE file distributed with
4+
# this work for additional information regarding copyright ownership.
5+
# The ASF licenses this file to You under the Apache License, Version 2.0
6+
# (the "License"); you may not use this file except in compliance with
7+
# the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
18+
IMG=actionloop-java-v11:nightly
19+
PREFIX=docker.io/openwhisk
20+
INVOKE=python ../../tools/invoke.py
21+
MAIN_JAR=../../example/main.jar
22+
23+
build:
24+
docker build -t $(IMG) .
25+
26+
push: build
27+
docker login
28+
docker tag $(IMG) $(PREFIX)/$(IMG)
29+
docker push $(PREFIX)/$(IMG)
30+
31+
clean:
32+
docker rmi -f $(IMG)
33+
34+
start: build
35+
docker run -p 8080:8080 -ti -v $(PWD):/proxy $(IMG)
36+
37+
debug: build
38+
docker run -p 8080:8080 -ti --entrypoint=/bin/bash -v $(PWD):/mnt -e OW_COMPILER=/mnt/bin/compile $(IMG)
39+
40+
.PHONY: build push clean start debug
41+
42+
$(MAIN_JAR):
43+
$(MAKE) $< -C ../../example main.jar
44+
45+
## You need to execute make start in another terminal
46+
47+
test-source:
48+
$(INVOKE) init ../../example/Main.java
49+
$(INVOKE) run '{}'
50+
$(INVOKE) run '{"name":"Mike"}'
51+
52+
test-source-hello:
53+
$(INVOKE) init action.Hello#hello ../../example/action/Hello.java
54+
$(INVOKE) run '{}'
55+
$(INVOKE) run '{"name":"Mike"}'
56+
57+
test-jar: $(MAIN_JAR)
58+
$(INVOKE) init action.Hello#hello $(MAIN_JAR)
59+
$(INVOKE) run '{}'
60+
$(INVOKE) run '{"name":"Mike"}'
61+
62+
test-src-zip:
63+
$(MAKE) -C ../../example src.zip
64+
$(INVOKE) init ../../example/src.zip
65+
$(INVOKE) run '{}'
66+
$(INVOKE) run '{"name":"Mike"}'
67+
68+
test-bin-zip:
69+
$(MAKE) -C ../../example bin.zip
70+
$(INVOKE) init ../../example/bin.zip
71+
$(INVOKE) run '{}'
72+
$(INVOKE) run '{"name":"Mike"}'

core/java11actionloop/build.gradle

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
ext.dockerImageName = 'actionloop-java-v11'
19+
apply from: '../../gradle/docker.gradle'
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import java.io.*;
19+
import java.lang.reflect.Field;
20+
import java.lang.reflect.Method;
21+
import java.lang.reflect.Modifier;
22+
import java.util.Collections;
23+
import java.util.HashMap;
24+
import java.util.Map;
25+
import com.google.gson.*;
26+
import java.security.Permission;
27+
import java.lang.reflect.InvocationTargetException;
28+
29+
class Launcher {
30+
31+
private static String mainClassName = "Main";
32+
private static String mainMethodName = "main";
33+
private static Class mainClass = null;
34+
private static Method mainMethod = null;
35+
36+
@SuppressWarnings({ "unchecked", "rawtypes" })
37+
private static void augmentEnv(Map<String, String> newEnv) {
38+
try {
39+
for (Class cl : Collections.class.getDeclaredClasses()) {
40+
if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
41+
Field field = cl.getDeclaredField("m");
42+
field.setAccessible(true);
43+
Object obj = field.get(System.getenv());
44+
Map<String, String> map = (Map<String, String>) obj;
45+
map.putAll(newEnv);
46+
}
47+
}
48+
} catch (Exception e) {}
49+
}
50+
51+
private static void initMain(String[] args) throws Exception {
52+
if(args.length > 0)
53+
mainClassName = args[0];
54+
int pos = mainClassName.indexOf("#");
55+
if(pos != -1) {
56+
if(pos + 1 != mainClassName.length())
57+
mainMethodName = args[0].substring(pos+1);
58+
mainClassName = args[0].substring(0,pos);
59+
}
60+
61+
mainClass = Class.forName(mainClassName);
62+
Method m = mainClass.getMethod(mainMethodName, new Class[] { JsonObject.class });
63+
m.setAccessible(true);
64+
int modifiers = m.getModifiers();
65+
if (m.getReturnType() != JsonObject.class || !Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers)) {
66+
throw new NoSuchMethodException(mainMethodName);
67+
}
68+
mainMethod = m;
69+
}
70+
71+
private static JsonObject invokeMain(JsonObject arg, Map<String, String> env) throws Exception {
72+
augmentEnv(env);
73+
return (JsonObject) mainMethod.invoke(null, arg);
74+
}
75+
76+
private static SecurityManager defaultSecurityManager = null;
77+
private static void installSecurityManager() {
78+
defaultSecurityManager = System.getSecurityManager();
79+
System.setSecurityManager(new SecurityManager() {
80+
@Override
81+
public void checkPermission(Permission p) {
82+
// Not throwing means accepting anything.
83+
}
84+
85+
@Override
86+
public void checkPermission(Permission p, Object ctx) {
87+
// Not throwing means accepting anything.
88+
}
89+
90+
@Override
91+
public void checkExit(int status) {
92+
super.checkExit(status);
93+
throw new SecurityException("System.exit(" + status + ") called from within an action.");
94+
}
95+
});
96+
}
97+
98+
private static void uninstallSecurityManager() {
99+
if(defaultSecurityManager != null) {
100+
System.setSecurityManager(defaultSecurityManager);
101+
}
102+
}
103+
104+
public static void main(String[] args) throws Exception {
105+
106+
initMain(args);
107+
108+
// exit after main class loading if "exit" specified
109+
// used to check healthy launch after init
110+
if(args.length >1 && args[1] == "-exit")
111+
System.exit(0);
112+
113+
// install a security manager to prevent exit
114+
installSecurityManager();
115+
116+
BufferedReader in = new BufferedReader(
117+
new InputStreamReader(System.in, "UTF-8"));
118+
PrintWriter out = new PrintWriter(
119+
new OutputStreamWriter(
120+
new FileOutputStream("/dev/fd/3"), "UTF-8"));
121+
JsonParser json = new JsonParser();
122+
JsonObject empty = json.parse("{}").getAsJsonObject();
123+
String input = "";
124+
while (true) {
125+
try {
126+
input = in.readLine();
127+
if (input == null)
128+
break;
129+
JsonElement element = json.parse(input);
130+
JsonObject payload = empty.deepCopy();
131+
HashMap<String, String> env = new HashMap<String, String>();
132+
if (element.isJsonObject()) {
133+
// collect payload and environment
134+
for (Map.Entry<String, JsonElement> entry : element.getAsJsonObject().entrySet()) {
135+
if (entry.getKey().equals("value")) {
136+
if (entry.getValue().isJsonObject())
137+
payload = entry.getValue().getAsJsonObject();
138+
} else {
139+
env.put(String.format("__OW_%s", entry.getKey().toUpperCase()),
140+
entry.getValue().getAsString());
141+
}
142+
}
143+
augmentEnv(env);
144+
}
145+
JsonElement response = invokeMain(payload, env);
146+
out.println(response.toString());
147+
} catch(NullPointerException npe) {
148+
System.out.println("the action returned null");
149+
npe.printStackTrace(System.err);
150+
JsonObject error = new JsonObject();
151+
error.addProperty("error", "the action returned null");
152+
out.println(error.toString());
153+
out.flush();
154+
} catch(InvocationTargetException ite) {
155+
Throwable ex = ite;
156+
if(ite.getCause() != null)
157+
ex = ite.getCause();
158+
ex.printStackTrace(System.err);
159+
JsonObject error = new JsonObject();
160+
error.addProperty("error", ex.getMessage());
161+
out.println(error.toString());
162+
out.flush();
163+
} catch (Exception ex) {
164+
ex.printStackTrace(System.err);
165+
JsonObject error = new JsonObject();
166+
error.addProperty("error", ex.getMessage());
167+
out.println(error.toString());
168+
out.flush();
169+
}
170+
out.flush();
171+
System.out.flush();
172+
System.err.flush();
173+
}
174+
uninstallSecurityManager();
175+
}
176+
}
177+

settings.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ include 'tests'
2020
include 'core:java8'
2121
include 'core:java8:proxy'
2222
include 'core:java8actionloop'
23+
include 'core:java11actionloop'
2324

2425
rootProject.name = 'runtime-java'
2526

0 commit comments

Comments
 (0)