blob: ef571e973cec06361bb9d8185e6174d953fa8b85 [file] [log] [blame]
/*
* 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.
*/
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import com.google.gson.*;
import java.security.Permission;
import java.lang.reflect.InvocationTargetException;
class Launcher {
private static String mainClassName = "Main";
private static String mainMethodName = "main";
private static Class mainClass = null;
private static Method mainMethod = null;
@SuppressWarnings({ "unchecked", "rawtypes" })
private static void augmentEnv(Map<String, String> newEnv) {
try {
for (Class cl : Collections.class.getDeclaredClasses()) {
if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
Field field = cl.getDeclaredField("m");
field.setAccessible(true);
Object obj = field.get(System.getenv());
Map<String, String> map = (Map<String, String>) obj;
map.putAll(newEnv);
}
}
} catch (Exception e) {}
}
private static void initMain(String[] args) throws Exception {
if(args.length > 0)
mainClassName = args[0];
int pos = mainClassName.indexOf("#");
if(pos != -1) {
if(pos + 1 != mainClassName.length())
mainMethodName = args[0].substring(pos+1);
mainClassName = args[0].substring(0,pos);
}
mainClass = Class.forName(mainClassName);
Method m = mainClass.getMethod(mainMethodName, new Class[] { JsonObject.class });
m.setAccessible(true);
int modifiers = m.getModifiers();
if (m.getReturnType() != JsonObject.class || !Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers)) {
throw new NoSuchMethodException(mainMethodName);
}
mainMethod = m;
}
private static JsonObject invokeMain(JsonObject arg, Map<String, String> env) throws Exception {
augmentEnv(env);
return (JsonObject) mainMethod.invoke(null, arg);
}
private static SecurityManager defaultSecurityManager = null;
private static void installSecurityManager() {
defaultSecurityManager = System.getSecurityManager();
System.setSecurityManager(new SecurityManager() {
@Override
public void checkPermission(Permission p) {
// Not throwing means accepting anything.
}
@Override
public void checkPermission(Permission p, Object ctx) {
// Not throwing means accepting anything.
}
@Override
public void checkExit(int status) {
super.checkExit(status);
throw new SecurityException("System.exit(" + status + ") called from within an action.");
}
});
}
private static void uninstallSecurityManager() {
if(defaultSecurityManager != null) {
System.setSecurityManager(defaultSecurityManager);
}
}
public static void main(String[] args) throws Exception {
initMain(args);
// exit after main class loading if "exit" specified
// used to check healthy launch after init
if(args.length >1 && args[1] == "-exit")
System.exit(0);
// install a security manager to prevent exit
installSecurityManager();
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in, "UTF-8"));
PrintWriter out = new PrintWriter(
new OutputStreamWriter(
new FileOutputStream("/dev/fd/3"), "UTF-8"));
JsonParser json = new JsonParser();
JsonObject empty = json.parse("{}").getAsJsonObject();
String input = "";
while (true) {
try {
input = in.readLine();
if (input == null)
break;
JsonElement element = json.parse(input);
JsonObject payload = empty.deepCopy();
HashMap<String, String> env = new HashMap<String, String>();
if (element.isJsonObject()) {
// collect payload and environment
for (Map.Entry<String, JsonElement> entry : element.getAsJsonObject().entrySet()) {
if (entry.getKey().equals("value")) {
if (entry.getValue().isJsonObject())
payload = entry.getValue().getAsJsonObject();
} else {
env.put(String.format("__OW_%s", entry.getKey().toUpperCase()),
entry.getValue().getAsString());
}
}
augmentEnv(env);
}
JsonElement response = invokeMain(payload, env);
out.println(response.toString());
} catch(NullPointerException npe) {
System.out.println("the action returned null");
npe.printStackTrace(System.err);
JsonObject error = new JsonObject();
error.addProperty("error", "the action returned null");
out.println(error.toString());
out.flush();
} catch(InvocationTargetException ite) {
Throwable ex = ite;
if(ite.getCause() != null)
ex = ite.getCause();
ex.printStackTrace(System.err);
JsonObject error = new JsonObject();
error.addProperty("error", ex.getMessage());
out.println(error.toString());
out.flush();
} catch (Exception ex) {
ex.printStackTrace(System.err);
JsonObject error = new JsonObject();
error.addProperty("error", ex.getMessage());
out.println(error.toString());
out.flush();
}
out.flush();
System.out.flush();
System.err.flush();
}
uninstallSecurityManager();
}
}