rabbah closed pull request #1: Adding initial sources for Ballerina runtime
URL: https://github.com/apache/incubator-openwhisk-runtime-ballerina/pull/1
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1060795
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,11 @@
+.vscode
+.idea
+.iml
+.balx
+.ballerina
+
+ballerina-internal.log
+
+.gradle/
+ballerina/proxy/build/
+tests/build
diff --git a/.scalafmt.conf b/.scalafmt.conf
new file mode 100644
index 0000000..7084efe
--- /dev/null
+++ b/.scalafmt.conf
@@ -0,0 +1,9 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more 
contributor
+# license agreements; and to You under the Apache License, Version 2.0.
+
+style = intellij
+danglingParentheses = false
+maxColumn = 120
+docstrings = JavaDoc
+rewrite.rules = [SortImports]
+project.git = true
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..1c77591
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,41 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more 
contributor
+# license agreements; and to You under the Apache License, Version 2.0.
+
+sudo: required
+group: deprecated-2017Q3
+language: scala
+scala:
+- 2.11.11
+services:
+- docker
+
+notifications:
+  email: false
+  webhooks:
+    urls:
+      # travis2slack webhook to enable DMs on openwhisk-team.slack.com to PR 
authors with TravisCI results
+      secure: 
"@@@@@@@kjsdhfksadfsnddaVN8+Shkaty+WDhjTuCbVkliH4H2yJ3GMK2cf8pxhQz1Po0qJNxuyO9jDjQRbDG95b0PueBLcK0gMZZkjoe47lg
+      
/ZqYMyEFjhKP0J4C0+thokVnM4MoT8xKktWjPyIRK2EfYEdR1UXPtmofNgkZmpwx/GARuuDhAiSo3myMZ2xWQx0ASVsWbkODBePUnnMVv4Hcm0zn9ActFBZW9aJaGjg8Qo+sertESCemWYhreErdXtXV4prlWJo2LytpUuXIAWLFnutYu6TJw2I7gBaRkbLN+4N7qSgddcfVUdBf8j6NqWwUz6BqLqDSZ031lKCIlTNpS/Yu/+9qgI/aBZ9a0l+Nv4o0V0nWTZ0aAkw3/HtZ3muDHHs7ninMq9IFgGRUR4jX4OgUV8Pu8OKEHYcUF0S0XiXbTfLIxI3OirBBlxweunMKtjyOUOLdWcmT2XQLYJGU7cdiG3SE+ONo7kR+BugUtqSzgCnRRxE4m4wkZHqOfyRI2b3RVCtEQHfewevZnDCbxYxZn+v1mMjE4zuenhu+hbtsvQbbX+x1MeDaL8RYrwjXXf+TrILhnj1xkuHTWAgKQhh6pP+ZaNqNLmmSLOqaI/v8Ysi4rSbkR2Pa3k0/ze/tPdjqoD8vFZMPrSLYOWTqZYQCFF5FA72DECFP04tnb0hz5c4joxGJpRlKs1MW8="
+    enabled: false
+
+before_install:
+- "./tools/travis/setup.sh"
+install: true
+script:
+- "./tools/travis/build.sh && ./tools/travis/test.sh"
+deploy:
+  - provider: script
+    script: "./tools/travis/publish.sh openwhisk ${TRAVIS_TAG##*@}"
+    on:
+      tags: true
+      all_branches: true
+      repo: apache/incubator-openwhisk-runtime-java
+  - provider: script
+    script: "./tools/travis/publish.sh openwhisk latest"
+    on:
+      branch: master
+      repo: apache/incubator-openwhisk-runtime-ballerina
+env:
+  global:
+  - secure: 
D4kU9O6bs63Myb4jaEgw1O2Kuy6aTAUKEX1qZ0eYMDouLnPOPnZaFWmpISKTrJyz7hJH7yY8Cj7xl5qwsLB6JZZMtqT6yj5J/jkUJjyLKdQH81PrYy22rH99xS2t5A1dsC0A/Bf39R/qNc5tx1wCMVDF4O2rFsUtn+8vE+rn0nXsiPeWhhZagk/Hrq8YbwzDJHOGHfWe1nZIcU8MORzTriX7J2VAF0AcirPandMxff4FgzNLk432DN2GvgZIlNtZGT1DWLtJV/Sp3unD9abXr5xqNDIW+fHrMq8j/JdHC6+PFtZRFrl0Vr6X8c61PkB/ELGF2MyzNgBTnEaJixl1pianr91WK4y0oLUwpSJCz4yoQGVimAAtqMgNXjEyFMcpLClzS5TjMXKaUfi9mBn9GMCwLi3VAuVtMtH2IRW03PxIPyxkbj1j8Nrd0jh408MuMpuzyECgb+E5ffbd+0YD5XUNlTkYLFi4sEh2xpzvjGrNbrTe99zFrHt3e+dbmoahmaCyDRsxD2CDI8b++HyN78z/jO9A7kFc2TAZbWa6Xygkj1nEpnR1y4TB6eqdDo7Y6W20dLjeSSF8rACw3bM3lJh+K4/nv4Nlo6pfblhvs7T53ftst+tHpxJoQy/gDC0TcuyBThrHTeI1j7k4HkQyN+NqezBdFN2ElufjQ74ds2c=
+  - secure: 
KzgDAV8O0ya6JBqSs4J4A7A+2n9Mgs5kRzhwwPdUg7ExuG2xXwWw1gafNPZwagfVOQfdqLzfF4tY8PPbTfloqEomFmYI/9PUHU8nMiMQkhEKkU3Od6HqqV9/WCf9vBrmqZHTPQNRVUvsbcOiYG1xtQr4JPHySJnk9VbgumRCT+f0xWK5mGK3CQqIo43F0TScjMONED/h7yueT+zFIJIfTiOXgtckbZdi7hErrVubbkduyzGSMek1Pfzy+m7Ek6jIaS4iD6duSRfxO9GVDTMee13cD3HuIWWfkZMkNiMlXBLmOPhb67lt/dgryxZ9zKxCzJFDW3Fx8uohoFu+sg8ZcyCeeDqMUfeML8rKAdNk72e2W9Vzedx6lxoTIhLYA3KLj7kL5wTxEq9QnSI/dMPqJUG/IA7Cr5fnJWRAlJ3IroQqBH8vNZ9zuoh/Ap4G2kXL1m4JECPhBlsX8i9RgDrFrab4My2IOHBw+ZA+cJ4h5njQUkuhMtlAhJ26jwQgYhn/sSMLgb4h5IX2iiRprsrg912vFg0ZrgHu1joIH/1XEGdArkQ7O9za4mowEmOuATux0drXTRKGe6z+/xaW35K8tQ52ToJRMN+GZBKlZoNIZd/rQ/y1Ikb6PD5Gfjk0WBnxYT5jV+ted7zCq3LskpWyvXtVTKoOqPOC/cDcY5JBPK8=
diff --git a/README.md b/README.md
index 9a5580b..cd539b5 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,117 @@
-# incubator-openwhisk-runtime-ballerina
+<!--
+#
+# 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.
+#
+-->
+
+# Apache OpenWhisk Runtime for Ballerina
+[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0)
+[![Build 
Status](https://travis-ci.com/apache/incubator-openwhisk-runtime-ballerina.svg?branch=master)](https://travis-ci.com/apache/incubator-openwhisk-runtime-ballerina)
+
+This repository contains the [Ballerina](https://ballerinalang.org) runtime 
for the Apache OpenWhisk serverless platform.
+
+### Prerequisites
+
+The following prerequisites are needed to try this out:
+
+- [Ballerina](https://ballerina.io/downloads/) >= 0.975.0
+
+### Creating a Ballerina function
+
+Create a file `hello.bal` for your Ballerina function with the following code:
+
+```ballerina
+import ballerina/io;
+function main(string... args) {
+  io:println("started");
+}
+function run(json jsonInput) returns json {
+  io:println(jsonInput);
+  json output = { "response": "hello-world"};
+  return output;
+}
+```
+
+The Ballerina file should include:
+ - `main(string... args)` and
+ - `run(json jsonInput)`.
+
+The first is necessary to compile the function but does not execute when you
+invoke the action.
+
+### Compiling your function
+
+Run the [Ballerina](https://ballerina.io/downloads) compiler to
+build your function.
+```bash
+ballerina build hello.bal
+```
+
+This generates an executable `hello.balx`. You will use this binary to create
+the OpenWhisk action.
+
+### Creating and invoking your Ballerina action
+
+Use the OpenWhisk [`wsk` 
CLI](https://github.com/apache/incubator-openwhisk/blob/master/docs/cli.md)
+to create your Ballerina action.
+
+```bash
+wsk action create hello hello.balx --docker openwhisk/balaction
+```
+
+Now you're ready to invoke the action:
+
+```bash
+wsk action invoke hello --result
+```
+```json
+{
+  "response": "hello-world"
+}
+```
+
+You can learn more about working with OpenWhisk Actions 
[here](https://github.com/apache/incubator-openwhisk/blob/master/docs/actions.md).
+
+### Developing the Ballerina runtime for OpenWhisk
+
+To build the Ballerina runtime, you need an OpenWhisk snapshot release which
+you can install as follows:
+```bash
+pushd $OPENWHISK_HOME
+./gradlew install
+podd $OPENWHISK_HOME
+```
+where `$OPENWHISK_HOME` is an environment variable that points to your
+OpenWhisk directory.
+
+The Ballerina runtime is built with the Gradle wrapper `gradlew`.
+```bash
+./gradlew distDocker
+```
+
+You can also use `gradlew` to run all the unit tests.
+```bash
+./gradlew :tests:test
+```
+
+Or to run a specific test.
+```bash
+./gradlew :tests:test --tests *ActionContainerTests*
+```
+
+This project can be imported into [IntelliJ](https://www.jetbrains.com/idea/)
+for development and testing. Import the project as a Gradle project, and make
+sure your working directory is the root directory for this repository.
diff --git a/ballerina/Dockerfile b/ballerina/Dockerfile
new file mode 100644
index 0000000..db0fb5a
--- /dev/null
+++ b/ballerina/Dockerfile
@@ -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.
+#
+
+FROM adoptopenjdk/openjdk8-openj9:jdk8u162-b12_openj9-0.8.0
+
+RUN rm -rf /var/lib/apt/lists/* && apt-get clean && apt-get update \
+       && apt-get install -y --no-install-recommends locales \
+       && rm -rf /var/lib/apt/lists/* \
+       && locale-gen en_US.UTF-8
+
+ENV LANG="en_US.UTF-8" \
+       LANGUAGE="en_US:en" \
+       LC_ALL="en_US.UTF-8" \
+       VERSION=8 \
+       UPDATE=162 \
+       BUILD=12
+
+ADD proxy /home/ballerina
+
+RUN cd /home/ballerina \
+    && rm -rf .classpath .gitignore .gradle .project .settings Dockerfile 
build \
+    && ./gradlew shadowJar \
+    && rm -rf /home/ballerina/src
+
+EXPOSE 8080
+
+CMD java -Dballerina.home=/home/ballerina/build 
-Djava.util.logging.manager=org.ballerinalang.logging.BLogManager -jar 
/home/ballerina/build/libs/ballerina-all.jar --http.port=8080
diff --git a/ballerina/build.gradle b/ballerina/build.gradle
new file mode 100644
index 0000000..b1e96aa
--- /dev/null
+++ b/ballerina/build.gradle
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+ext.dockerImageName = 'balaction'
+apply from: '../gradle/docker.gradle'
diff --git a/ballerina/hello-function.bal b/ballerina/hello-function.bal
new file mode 100644
index 0000000..6328206
--- /dev/null
+++ b/ballerina/hello-function.bal
@@ -0,0 +1,11 @@
+import ballerina/io;
+
+function main(string... args) {
+   io:println("started");
+}
+
+function run(json jsonInput) returns json {
+   io:println(jsonInput);
+   json output = { "response": "hello-world"};
+   return output;
+}
diff --git a/ballerina/hello-function.balx b/ballerina/hello-function.balx
new file mode 100644
index 0000000..a4a56b1
Binary files /dev/null and b/ballerina/hello-function.balx differ
diff --git a/ballerina/proxy/build.gradle b/ballerina/proxy/build.gradle
new file mode 100644
index 0000000..ddcc645
--- /dev/null
+++ b/ballerina/proxy/build.gradle
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+buildscript {
+    repositories {
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3'
+    }
+}
+
+apply plugin: 'maven'
+apply plugin: 'java'
+apply plugin: 'application'
+apply plugin: 'com.github.johnrengelman.shadow'
+
+mainClassName = 'org.ballerinalang.openwhisk.runtime.Application'
+
+repositories {
+    mavenCentral()
+    mavenLocal()
+    maven { url 
"https://maven.wso2.org/nexus/content/repositories/public/org/ballerinalang"; }
+    maven { url "http://maven.wso2.org/nexus/content/groups/wso2-public"; }
+}
+
+dependencies {
+    compile "org.wso2.msf4j:msf4j-service:2.4.2"
+    compile ("org.wso2.msf4j:msf4j-core:2.4.2") {
+        force = true
+    }
+    compile "org.ballerinalang:ballerina-core:0.975.0"
+    compile "org.ballerinalang:ballerina-lang:0.975.0"
+    compile "org.ballerinalang:ballerina-grpc:0.975.0"
+    compile "org.ballerinalang:protobuf-ballerina:0.975.0"
+    compile "org.ballerinalang:ballerina-builtin:0.975.0"
+    compile "org.ballerinalang:ballerina-http:0.975.0"
+    compile "org.ballerinalang:ballerina-transactions:0.975.0"
+    compile "org.ballerinalang:ballerina-logging:0.975.0"
+    compile "org.ballerinalang:ballerina-database:0.975.0"
+    compile "org.ballerinalang:ballerina-micrometer-extension:0.975.0"
+    compile "org.slf4j:slf4j-api:1.7.22"
+}
+
+configurations.all {
+    exclude group: 'org.slf4j', module: 'slf4j-simple'
+    exclude group: 'org.ops4j.pax.logging', module: 'pax-logging-api'
+}
+
+task wrapper(type: Wrapper) {
+    gradleVersion = '4.6' //version required
+}
+
+defaultTasks 'shadowJar'
+
+// Configure the shadow jar task
+shadowJar {
+    mergeServiceFiles()
+    exclude 'META-INF/*.DSA'
+    exclude 'META-INF/*.RSA'
+}
+jar {
+    manifest {
+        attributes 'Main-Class': mainClassName
+    }
+}
+
+task copyRepoDependencies() {
+    configurations.compile.resolvedConfiguration.resolvedArtifacts.each { 
artifact ->
+        if (artifact.file.name.endsWith("ballerina-binary-repo.zip")) {
+            copy {
+                from zipTree( artifact.file )
+                into ("${buildDir}/lib")
+            }
+        }
+    }
+}
+
diff --git a/ballerina/proxy/gradle/wrapper/gradle-wrapper.jar 
b/ballerina/proxy/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..91ca28c
Binary files /dev/null and b/ballerina/proxy/gradle/wrapper/gradle-wrapper.jar 
differ
diff --git a/ballerina/proxy/gradle/wrapper/gradle-wrapper.properties 
b/ballerina/proxy/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..15c07a0
--- /dev/null
+++ b/ballerina/proxy/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,8 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more 
contributor
+# license agreements; and to You under the Apache License, Version 2.0.
+
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/ballerina/proxy/gradlew b/ballerina/proxy/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/ballerina/proxy/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to 
pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 
'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; 
then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" 
\"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### 
Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### 
Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" 
"$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" 
"$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" 
"$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; 
done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and 
substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 
"\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" 
org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder 
on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/ballerina/proxy/gradlew.bat b/ballerina/proxy/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/ballerina/proxy/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS 
to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your 
PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% 
"-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" 
org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code 
instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git 
a/ballerina/proxy/src/main/java/org/ballerinalang/openwhisk/runtime/Application.java
 
b/ballerina/proxy/src/main/java/org/ballerinalang/openwhisk/runtime/Application.java
new file mode 100644
index 0000000..0d48d84
--- /dev/null
+++ 
b/ballerina/proxy/src/main/java/org/ballerinalang/openwhisk/runtime/Application.java
@@ -0,0 +1,29 @@
+/*
+ * 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.ballerinalang.openwhisk.runtime;
+
+import org.wso2.msf4j.MicroservicesRunner;
+
+/**
+ * Starts the Ballerina Runtime Proxy on port 8080
+ */
+public class Application {
+    public static void main(String[] args) {
+        new MicroservicesRunner(Constants.PROXY_PORT).deploy(new 
BallerinaProxy()).start();
+    }
+}
diff --git 
a/ballerina/proxy/src/main/java/org/ballerinalang/openwhisk/runtime/BallerinaProxy.java
 
b/ballerina/proxy/src/main/java/org/ballerinalang/openwhisk/runtime/BallerinaProxy.java
new file mode 100644
index 0000000..f03366e
--- /dev/null
+++ 
b/ballerina/proxy/src/main/java/org/ballerinalang/openwhisk/runtime/BallerinaProxy.java
@@ -0,0 +1,243 @@
+/*
+ * 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.ballerinalang.openwhisk.runtime;
+
+import com.google.gson.JsonObject;
+import org.ballerinalang.BLangProgramLoader;
+import org.ballerinalang.logging.BLogManager;
+import org.ballerinalang.model.values.BJSON;
+import org.ballerinalang.model.values.BValue;
+import org.ballerinalang.util.codegen.ProgramFile;
+import org.ballerinalang.util.exceptions.BLangRuntimeException;
+import org.ballerinalang.util.exceptions.ProgramFileFormatException;
+import org.ballerinalang.util.program.BLangFunctions;
+import org.wso2.msf4j.Request;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.logging.LogManager;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+
+/**
+ * OpenWhisk Ballerina Runtime Proxy Service
+ * Exposes /init and /run resources
+ */
+@Path("/") public class BallerinaProxy {
+    private ProgramFile programFile;
+    private String mainFunction = Constants.FUNCTION_CALLABLE_NAME;
+
+    @POST
+    @Path("init")
+    public Response init(@Context Request request) throws IOException {
+        Optional<ProgramFile> optionalValue = Optional.ofNullable(programFile);
+
+        // Check whether init being called before
+        if (optionalValue.isPresent()) {
+            System.err.println(Constants.INIT_ONCE_ERROR);
+            return buildResponse(Response.Status.BAD_GATEWAY, 
Constants.RESPONSE_ERROR, Constants.INIT_ONCE_ERROR);
+        }
+
+        InputStream balxIs = null;
+        try {
+            ((BLogManager) 
LogManager.getLogManager()).loadUserProvidedLogConfiguration();
+            JsonObject payload = BalxLoader.requestToJson(request);
+
+            if (payload.size() == 0) {
+                return buildResponse(Response.Status.INTERNAL_SERVER_ERROR, 
Constants.RESPONSE_ERROR,
+                                     Constants.FAILED_TO_LOCATE_BINARY);
+
+            }
+
+            JsonObject requestElements = 
payload.getAsJsonObject(Constants.JSON_VALUE);
+            Boolean isBinary = 
requestElements.get(Constants.BINARY).getAsBoolean();
+            String main = 
requestElements.get(Constants.FUNCTION_MAIN).getAsString();
+
+            if (!Constants.FUNCTION_MAIN.equals(main)) {
+                mainFunction = main;
+            }
+
+            // Check for binary value. .balx should be received with the 
binary parameter
+            if (isBinary) {
+                String base64Balx = 
requestElements.get(Constants.CODE).getAsString();
+
+                balxIs = new 
ByteArrayInputStream(base64Balx.getBytes(StandardCharsets.UTF_8));
+
+                java.nio.file.Path destinationPath = 
BalxLoader.saveBase64EncodedFile(balxIs);
+
+                programFile = BLangProgramLoader.read(destinationPath);
+
+                return buildResponse(Response.Status.OK, 
Constants.RESPONSE_SUCCESS, Constants.INIT_SUCCESS);
+            } else {
+                return buildResponse(Response.Status.INTERNAL_SERVER_ERROR, 
Constants.RESPONSE_ERROR,
+                                     Constants.FAILED_TO_LOCATE_BINARY);
+            }
+        } catch (ProgramFileFormatException | BLangRuntimeException e) {
+            return buildResponse(Response.Status.INTERNAL_SERVER_ERROR, 
Constants.RESPONSE_ERROR,
+                                 Constants.FAILED_TO_LOCATE_BINARY);
+        } catch (IOException e) {
+            return buildResponse(Response.Status.INTERNAL_SERVER_ERROR, 
Constants.RESPONSE_ERROR,
+                                 Constants.MISSING_MAIN_ERROR);
+        } finally {
+            if (balxIs != null) {
+                balxIs.close();
+            }
+        }
+    }
+
+    @POST
+    @Path("run")
+    public Response run(@Context Request request) {
+        Optional<ProgramFile> optionalValue = Optional.ofNullable(programFile);
+        JsonObject requestElements;
+        BValue[] result;
+
+        // Check whether init function has success and the program file is set
+        if (!optionalValue.isPresent()) {
+            return buildRunResponse(Response.Status.BAD_REQUEST, 
Constants.RESPONSE_ERROR,
+                                    Constants.FUNCTION_NOT_INITIALIZED);
+        }
+
+        requestElements = BalxLoader.requestToJson(request);
+
+        if (requestElements.size() == 0 || 
requestElements.getAsJsonObject(Constants.JSON_VALUE) == null) {
+            return buildRunResponse(Response.Status.BAD_REQUEST, 
Constants.RESPONSE_ERROR,
+                                    Constants.INVALID_INPUT_PARAMS);
+        }
+
+        //Preparing input parameters
+        BValue bJson = new 
BJSON(requestElements.getAsJsonObject(Constants.JSON_VALUE).toString());
+        BValue[] parameters = new BValue[1];
+        parameters[0] = bJson;
+
+        //Setting up runtime environment variables
+        augmentEnv(requestElements);
+
+        //Invoking the program file
+        try {
+            programFile = BalxLoader.initProgramFile(programFile);
+            result = BLangFunctions
+                    .invokeEntrypointCallable(programFile, 
programFile.getEntryPkgName(), mainFunction, parameters);
+        } catch (Exception e) {
+            return buildRunResponse(Response.Status.BAD_REQUEST, 
Constants.RESPONSE_ERROR,
+                                    Constants.FUNCTION_RUN_FAILURE);
+        }
+
+        //Preparing function response
+        StringBuilder response = new StringBuilder();
+        for (BValue bValue : result) {
+            if ("json".equals(bValue.getType().toString())) {
+                response.append(bValue.stringValue());
+            } else {
+                return buildRunResponse(Response.Status.BAD_REQUEST, 
Constants.RESPONSE_ERROR,
+                                        Constants.DICTIONARY_RETURN_FAILURE);
+            }
+        }
+        return buildResponse(Response.Status.OK, response.toString());
+    }
+
+    /**
+     * Populating the environment properties by reading the input json object
+     *
+     * @param requestElements JsonObject with request parameters
+     */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    private static void augmentEnv(JsonObject requestElements) {
+        HashMap<String, String> env = new HashMap<>();
+        for (String p : new String[] { "api_key", "namespace", "action_name", 
"activation_id", "deadline" }) {
+            try {
+                String val = 
requestElements.getAsJsonPrimitive(p).getAsString();
+                env.put(String.format("__OW_%s", p.toUpperCase()), val);
+            } catch (Exception ignored) {
+            }
+        }
+
+        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(env);
+                }
+            }
+        } catch (Exception ignored) {
+        }
+    }
+
+    /**
+     * Common response build object
+     *
+     * @param status  Response Status
+     * @param type    Response Status
+     * @param message Response Message
+     * @return Formatted Response
+     */
+    private Response buildResponse(Response.Status status, String type, String 
message) {
+        String response = responseMsgBuilder(type, message);
+        return Response.status(status).header(HttpHeaders.CONTENT_ENCODING, 
Constants.IDENTITY).entity(response)
+                       .build();
+    }
+
+    /**
+     * Build response for already formatted Strings
+     *
+     * @param status
+     * @param response
+     * @return Formatted response
+     */
+    private Response buildResponse(Response.Status status, String response) {
+        System.out.println("XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX");
+        System.err.println("XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX");
+        return Response.status(status).header(HttpHeaders.CONTENT_ENCODING, 
Constants.IDENTITY).entity(response)
+                       .build();
+    }
+
+    /**
+     * Response builder method with WHISK activation end records
+     *
+     * @param status Response Status
+     * @return Formatted Response
+     */
+    private Response buildRunResponse(Response.Status status, String type, 
String message) {
+        String response = responseMsgBuilder(type, message);
+        return buildResponse(status, response);
+    }
+
+    /**
+     * Build the response Json message
+     *
+     * @param type    response type error / success
+     * @param Message message to be sent as response
+     * @return Formatted String {\"<type>\" : \"<message>\"}
+     */
+    private String responseMsgBuilder(String type, String Message) {
+        return "{" + type + ":" + Message + "}";
+    }
+}
diff --git 
a/ballerina/proxy/src/main/java/org/ballerinalang/openwhisk/runtime/BalxLoader.java
 
b/ballerina/proxy/src/main/java/org/ballerinalang/openwhisk/runtime/BalxLoader.java
new file mode 100644
index 0000000..a85005d
--- /dev/null
+++ 
b/ballerina/proxy/src/main/java/org/ballerinalang/openwhisk/runtime/BalxLoader.java
@@ -0,0 +1,105 @@
+/*
+ * 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.ballerinalang.openwhisk.runtime;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.ballerinalang.util.codegen.ProgramFile;
+import org.ballerinalang.util.debugger.Debugger;
+import org.wso2.msf4j.Request;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.Base64;
+import java.util.List;
+
+/**
+ * Loader Utils for proxy handlers.
+ */
+public class BalxLoader {
+
+    /**
+     * Writes the received encoded input stream to function.balx file.
+     *
+     * @param encoded Base64 Encoded Input Stream
+     * @return Path to function.balx
+     * @throws IOException
+     */
+    public static Path saveBase64EncodedFile(InputStream encoded) throws 
IOException {
+        InputStream decoded = null;
+        try {
+            Base64.Decoder decoder = Base64.getDecoder();
+
+            decoded = decoder.wrap(encoded);
+
+            File destinationFile = 
File.createTempFile(Constants.FUNCTION_FILE_NAME, Constants.FUNCTION_EXTENSION);
+            destinationFile.deleteOnExit();
+            Path destinationPath = destinationFile.toPath();
+
+            Files.copy(decoded, destinationPath, 
StandardCopyOption.REPLACE_EXISTING);
+            return destinationPath;
+        } finally {
+            if (decoded != null) {
+                decoded.close();
+            }
+        }
+    }
+
+    /**
+     * Initializes the program file debugger and Global Memory area
+     *
+     * @param programFile Program File object to initialize
+     * @return Initialized program file with debugger and Global Memory
+     */
+
+    public static ProgramFile initProgramFile(ProgramFile programFile) {
+        Debugger debugger = new Debugger(programFile);
+        programFile.setDebugger(debugger);
+
+        if (debugger.isDebugEnabled()) {
+            debugger.init();
+            debugger.waitTillDebuggeeResponds();
+        }
+
+        programFile.initializeGlobalMemArea();
+        return programFile;
+    }
+
+    /**
+     * Parsing the received request object to JSON.
+     *
+     * @param request Request object received in http call
+     * @return JSON formatted request object
+     */
+    public static JsonObject requestToJson(Request request) {
+        JsonParser parser = new JsonParser();
+        List<ByteBuffer> byteBuffers = request.getFullMessageBody();
+        StringBuilder req = new StringBuilder();
+        for (ByteBuffer buffer : byteBuffers) {
+            
req.append(Charset.forName(StandardCharsets.UTF_8.name()).decode(buffer).toString());
+        }
+        return parser.parse(req.toString()).getAsJsonObject();
+    }
+}
diff --git 
a/ballerina/proxy/src/main/java/org/ballerinalang/openwhisk/runtime/Constants.java
 
b/ballerina/proxy/src/main/java/org/ballerinalang/openwhisk/runtime/Constants.java
new file mode 100644
index 0000000..aa929db
--- /dev/null
+++ 
b/ballerina/proxy/src/main/java/org/ballerinalang/openwhisk/runtime/Constants.java
@@ -0,0 +1,47 @@
+/*
+ * 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.ballerinalang.openwhisk.runtime;
+
+/**
+ * Constant variables included in
+ */
+class Constants {
+    static final int PROXY_PORT = 8080;
+    static final String JSON_VALUE = "value";
+    static final String BINARY = "binary";
+    static final String CODE = "code";
+    static final String IDENTITY = "identity";
+
+    static final String FUNCTION_CALLABLE_NAME = "run";
+    static final String FUNCTION_MAIN = "main";
+    static final String FUNCTION_FILE_NAME = "function";
+    static final String FUNCTION_EXTENSION = ".balx";
+
+    static final String RESPONSE_ERROR = "\"error\"";
+    static final String RESPONSE_SUCCESS = "\"success\"";
+
+    static final String INIT_SUCCESS = "\"Function init success\"";
+
+    static final String INIT_ONCE_ERROR = "\"Cannot initialize the action more 
than once.\"";
+    static final String FAILED_TO_LOCATE_BINARY =
+            "\"The action failed to generate or locate a binary. See logs for 
details.\"";
+    static final String MISSING_MAIN_ERROR = "\"Missing main/no code to " + 
"execute.\"";
+    static final String FUNCTION_NOT_INITIALIZED = "\"Function not 
initialized\"";
+    static final String INVALID_INPUT_PARAMS = "\"Invalid input parameters for 
action run\"";
+    static final String FUNCTION_RUN_FAILURE = "\"Running Function failed\"";
+    static final String DICTIONARY_RETURN_FAILURE = "\"The action did not 
return a dictionary.\"";
+}
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..4ebd4b8
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+buildscript {
+    repositories {
+        jcenter()
+    }
+    dependencies {
+        classpath "cz.alenkacz:gradle-scalafmt:${gradle.scalafmt.version}"
+    }
+}
+
+subprojects {
+    apply plugin: 'scalafmt'
+    scalafmt.configFilePath = gradle.scalafmt.config
+}
diff --git a/gradle/docker.gradle b/gradle/docker.gradle
new file mode 100644
index 0000000..6ad6850
--- /dev/null
+++ b/gradle/docker.gradle
@@ -0,0 +1,116 @@
+/*
+ * 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 groovy.time.*
+
+/**
+ * Utility to build docker images based in gradle projects
+ *
+ * This extends gradle's 'application' plugin logic with a 'distDocker' task 
which builds
+ * a docker image from the Dockerfile of the project that applies this file. 
The image
+ * is automatically tagged and pushed if a tag and/or a registry is given.
+ *
+ * Parameters that can be set on project level:
+ * - dockerImageName (required): The name of the image to build (e.g. 
controller)
+ * - dockerRegistry (optional): The registry to push to
+ * - dockerImageTag (optional, default 'latest'): The tag for the image
+ * - dockerImagePrefix (optional, default 'whisk'): The prefix for the image,
+ *       'controller' becomes 'whisk/controller' per default
+ * - dockerTimeout (optional, default 840): Timeout for docker operations in 
seconds
+ * - dockerRetries (optional, default 3): How many times to retry docker 
operations
+ * - dockerBinary (optional, default 'docker'): The binary to execute docker 
commands
+ * - dockerBuildArgs (options, default ''): Project specific custom docker 
build arguments
+ * - dockerHost (optional): The docker host to run commands on, default 
behaviour is
+ *       docker's own DOCKER_HOST environment variable
+ */
+
+ext {
+    dockerRegistry = project.hasProperty('dockerRegistry') ? dockerRegistry + 
'/' : ''
+    dockerImageTag = project.hasProperty('dockerImageTag') ? dockerImageTag : 
'latest'
+    dockerImagePrefix = project.hasProperty('dockerImagePrefix') ? 
dockerImagePrefix : 'whisk'
+    dockerTimeout = project.hasProperty('dockerTimeout') ? 
dockerTimeout.toInteger() : 840
+    dockerRetries = project.hasProperty('dockerRetries') ? 
dockerRetries.toInteger() : 3
+    dockerBinary = project.hasProperty('dockerBinary') ? [dockerBinary] : 
['docker']
+    dockerBuildArg = ['build']
+}
+ext.dockerTaggedImageName = dockerRegistry + dockerImagePrefix + '/' + 
dockerImageName + ':' + dockerImageTag
+
+if(project.hasProperty('dockerHost')) {
+    dockerBinary += ['--host', project.dockerHost]
+}
+
+if(project.hasProperty('dockerBuildArgs')) {
+    dockerBuildArgs.each { arg  ->
+        dockerBuildArg += ['--build-arg', arg]
+    }
+}
+
+task distDocker {
+    doLast {
+        def start = new Date()
+        def cmd = dockerBinary + dockerBuildArg + ['-t', dockerImageName, 
project.buildscript.sourceFile.getParentFile().getAbsolutePath()]
+        retry(cmd, dockerRetries, dockerTimeout)
+        println("Building '${dockerImageName}' took ${TimeCategory.minus(new 
Date(), start)}")
+    }
+}
+task tagImage {
+    doLast {
+        def versionString = (dockerBinary + ['-v']).execute().text
+        def matched = (versionString =~ /(\d+)\.(\d+)\.(\d+)/)
+
+        def major = matched[0][1] as int
+        def minor = matched[0][2] as int
+
+        def dockerCmd = ['tag']
+        if(major == 1 && minor < 12) {
+            dockerCmd += ['-f']
+        }
+        retry(dockerBinary + dockerCmd + [dockerImageName, 
dockerTaggedImageName], dockerRetries, dockerTimeout)
+    }
+}
+
+task pushImage {
+    doLast {
+        def cmd = dockerBinary + ['push', dockerTaggedImageName]
+        retry(cmd, dockerRetries, dockerTimeout)
+    }
+}
+pushImage.dependsOn tagImage
+pushImage.onlyIf { dockerRegistry != '' }
+distDocker.finalizedBy pushImage
+
+def retry(cmd, retries, timeout) {
+    println("${new Date()}: Executing '${cmd.join(" ")}'")
+    def proc = cmd.execute()
+    proc.consumeProcessOutput(System.out, System.err)
+    proc.waitForOrKill(timeout * 1000)
+    if(proc.exitValue() != 0) {
+        def message = "${new Date()}: Command '${cmd.join(" ")}' failed with 
exitCode ${proc.exitValue()}"
+        if(proc.exitValue() == 143) { // 143 means the process was killed 
(SIGTERM signal)
+            message = "${new Date()}: Command '${cmd.join(" ")}' was killed 
after ${timeout} seconds"
+        }
+
+        if(retries > 1) {
+            println("${message}, ${retries-1} retries left, retrying...")
+            retry(cmd, retries-1, timeout)
+        }
+        else {
+            println("${message}, no more retries left, aborting...")
+            throw new GradleException(message)
+        }
+    }
+}
diff --git a/gradle/wrapper/gradle-wrapper.jar 
b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..91ca28c
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties 
b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..15c07a0
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,8 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more 
contributor
+# license agreements; and to You under the Apache License, Version 2.0.
+
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to 
pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 
'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; 
then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" 
\"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### 
Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### 
Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" 
"$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" 
"$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" 
"$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; 
done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and 
substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 
"\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" 
org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder 
on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS 
to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your 
PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% 
"-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" 
org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code 
instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..e25013f
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+include 'tests'
+include 'ballerina'
+include 'ballerina:proxy'
+
+
+rootProject.name = 'incubator-openwhisk-runtime-ballerina'
+
+gradle.ext.openwhisk = [
+        version: '1.0.0-SNAPSHOT'
+]
+
+gradle.ext.scala = [
+        version: '2.11.11',
+        compileFlags: ['-feature', '-unchecked', '-deprecation', 
'-Xfatal-warnings', '-Ywarn-unused-import']
+]
+
+gradle.ext.scalafmt = [
+        version: '1.5.0',
+        config: new File(rootProject.projectDir, '.scalafmt.conf')
+]
+
+gradle.ext.ballerina = [
+        version: '0.975.0'
+]
+
+gradle.ext.msf4j = [
+        version: '2.4.2'
+]
+
diff --git a/tests/build.gradle b/tests/build.gradle
new file mode 100644
index 0000000..97e2fcd
--- /dev/null
+++ b/tests/build.gradle
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+apply plugin: 'scala'
+apply plugin: 'eclipse'
+compileTestScala.options.encoding = 'UTF-8'
+
+repositories {
+    mavenCentral()
+    mavenLocal()
+    maven { url 
"https://maven.wso2.org/nexus/content/repositories/public/org/ballerinalang"; }
+    maven { url "http://maven.wso2.org/nexus/content/groups/wso2-public"; }
+}
+
+tasks.withType(Test) {
+    testLogging {
+        events "passed", "skipped", "failed"
+        showStandardStreams = true
+        exceptionFormat = 'full'
+    }
+    outputs.upToDateWhen { false } // force tests to run every time
+}
+
+dependencies {
+    compile "org.scala-lang:scala-library:${gradle.scala.version}"
+    compile 
"org.apache.openwhisk:openwhisk-tests:${gradle.openwhisk.version}:tests"
+    compile 
"org.apache.openwhisk:openwhisk-tests:${gradle.openwhisk.version}:test-sources"
+    compile "org.ballerinalang:ballerina-core:${gradle.ballerina.version}"
+    compile "org.ballerinalang:ballerina-lang:${gradle.ballerina.version}"
+    compile "org.ballerinalang:ballerina-grpc:${gradle.ballerina.version}"
+    compile "org.ballerinalang:protobuf-ballerina:${gradle.ballerina.version}"
+    compile "org.ballerinalang:ballerina-builtin:${gradle.ballerina.version}"
+    compile "org.ballerinalang:ballerina-http:${gradle.ballerina.version}"
+    compile 
"org.ballerinalang:ballerina-transactions:${gradle.ballerina.version}"
+    compile "org.ballerinalang:ballerina-database:${gradle.ballerina.version}"
+    compile 
"org.ballerinalang:ballerina-micrometer-extension:${gradle.ballerina.version}"
+    compile "org.slf4j:slf4j-api:1.7.22"
+}
+
+tasks.withType(ScalaCompile) {
+    scalaCompileOptions.additionalParameters = gradle.scala.compileFlags
+}
diff --git a/tests/src/test/resources/echo/echo.bal 
b/tests/src/test/resources/echo/echo.bal
new file mode 100644
index 0000000..ea8f21d
--- /dev/null
+++ b/tests/src/test/resources/echo/echo.bal
@@ -0,0 +1,12 @@
+import ballerina/io;
+import ballerina/log;
+
+function main(string... args) {
+    io:println("started");
+}
+
+function run(json jsonInput) returns json {
+    io:println("hello stdout");
+    log:printError("hello stderr");
+    return jsonInput;
+}
diff --git a/tests/src/test/resources/envparams/envparams.bal 
b/tests/src/test/resources/envparams/envparams.bal
new file mode 100644
index 0000000..0cdb3ef
--- /dev/null
+++ b/tests/src/test/resources/envparams/envparams.bal
@@ -0,0 +1,17 @@
+import ballerina/io;
+import ballerina/system;
+
+function main(string... args) {
+    io:println("started");
+}
+
+function run(json jsonInput) returns json {
+    json output = {};
+    output.api_host = system:getEnv("__OW_API_HOST");
+    output.api_key = system:getEnv("__OW_API_KEY");
+    output.namespace = system:getEnv("__OW_NAMESPACE");
+    output.action_name = system:getEnv("__OW_ACTION_NAME");
+    output.activation_id = system:getEnv("__OW_ACTIVATION_ID");
+    output.deadline = system:getEnv("__OW_DEADLINE");
+    return output;
+}
diff --git a/tests/src/test/resources/fail/fail.bal 
b/tests/src/test/resources/fail/fail.bal
new file mode 100644
index 0000000..37d08a1
--- /dev/null
+++ b/tests/src/test/resources/fail/fail.bal
@@ -0,0 +1,5 @@
+import ballerina/io;
+
+function main(string... args) {
+    io:println("started");
+}
diff --git a/tests/src/test/resources/hello/hello.bal 
b/tests/src/test/resources/hello/hello.bal
new file mode 100644
index 0000000..6328206
--- /dev/null
+++ b/tests/src/test/resources/hello/hello.bal
@@ -0,0 +1,11 @@
+import ballerina/io;
+
+function main(string... args) {
+   io:println("started");
+}
+
+function run(json jsonInput) returns json {
+   io:println(jsonInput);
+   json output = { "response": "hello-world"};
+   return output;
+}
diff --git a/tests/src/test/resources/norun/norun.bal 
b/tests/src/test/resources/norun/norun.bal
new file mode 100644
index 0000000..d10f024
--- /dev/null
+++ b/tests/src/test/resources/norun/norun.bal
@@ -0,0 +1,10 @@
+import ballerina/io;
+
+function main(string... args) {
+    io:println("started");
+}
+
+function example(json jsonInput) returns json {
+    json result = {"string":"hello"};
+    return result;
+}
diff --git a/tests/src/test/resources/return-response/return-response.bal 
b/tests/src/test/resources/return-response/return-response.bal
new file mode 100644
index 0000000..47af9c2
--- /dev/null
+++ b/tests/src/test/resources/return-response/return-response.bal
@@ -0,0 +1,9 @@
+import ballerina/io;
+
+function main(string... args) {
+    io:println("started");
+}
+
+function run(json jsonInput) returns json {
+    return jsonInput;
+}
diff --git a/tests/src/test/resources/unicode/unicode.bal 
b/tests/src/test/resources/unicode/unicode.bal
new file mode 100644
index 0000000..c48dee2
--- /dev/null
+++ b/tests/src/test/resources/unicode/unicode.bal
@@ -0,0 +1,13 @@
+import ballerina/io;
+
+function main(string... args) {
+    io:println("started");
+}
+
+function run(json jsonInput) returns json {
+    string delimiter = check <string> jsonInput.delimiter;
+    string str = delimiter + " ☃ " + delimiter;
+    io:println(str);
+    jsonInput.winter = str;
+    return jsonInput;
+}
diff --git 
a/tests/src/test/scala/actionContainers/BallerinaActionContainerTests.scala 
b/tests/src/test/scala/actionContainers/BallerinaActionContainerTests.scala
new file mode 100644
index 0000000..d5ad43b
--- /dev/null
+++ b/tests/src/test/scala/actionContainers/BallerinaActionContainerTests.scala
@@ -0,0 +1,165 @@
+/*
+ * 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 actionContainers
+
+import actionContainers.ActionContainer.withContainer
+import common.WskActorSystem
+import java.nio.file.{Files, Paths}
+import java.util.Base64
+
+import org.ballerinalang.compiler.CompilerPhase
+import org.ballerinalang.compiler.CompilerOptionName.{COMPILER_PHASE, OFFLINE, 
PROJECT_DIR}
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+import org.wso2.ballerinalang.compiler.Compiler
+import org.wso2.ballerinalang.compiler.util.{CompilerContext, CompilerOptions}
+import org.wso2.ballerinalang.compiler.util.diagnotic.BLangDiagnosticLog
+import spray.json._
+
+@RunWith(classOf[JUnitRunner])
+class BallerinaActionContainerTests extends BasicActionRunnerTests with 
WskActorSystem {
+
+  lazy val ballerinaContainerImageName = "balaction"
+
+  override def withActionContainer(env: Map[String, String] = Map.empty)(code: 
ActionContainer => Unit) = {
+    withContainer(ballerinaContainerImageName, env)(code)
+  }
+
+  override val testNoSourceOrExec = {
+    TestConfig("")
+  }
+
+  override val testInitCannotBeCalledMoreThanOnce = {
+    TestConfig(buildBal("hello"))
+  }
+
+  override val testNotReturningJson = {
+    // skip this test to fix the nuller
+    TestConfig("", skipTest = true)
+  }
+
+  override val testEnv = {
+    TestConfig(buildBal("envparams"), enforceEmptyOutputStream = false, 
enforceEmptyErrorStream = false)
+  }
+
+  override val testEcho = {
+    TestConfig(buildBal("echo"), skipTest = true)
+  }
+
+  override val testUnicode = {
+    TestConfig(buildBal("unicode"))
+  }
+
+  override val testEntryPointOtherThanMain = {
+    TestConfig(buildBal("norun"), "example", enforceEmptyOutputStream = false)
+  }
+
+  override val testLargeInput = {
+    TestConfig(buildBal("return-response"))
+  }
+
+  behavior of ballerinaContainerImageName
+
+  it should "Initialize with the hello code and invoke" in {
+    val (out, err) = withActionContainer() { c =>
+      val sourceFile = buildBal("hello")
+      sourceFile should not be "Build Error"
+
+      val (initCode, _) = c.init(initPayload(sourceFile))
+      initCode should be(200)
+
+      val (runCode, runRes) = c.run(runPayload(JsObject()))
+      runRes should be(Some(JsObject("response" -> JsString("hello-world"))))
+    }
+  }
+
+  it should "Initialize with function returning the response and invoke" in {
+    val (out, err) = withActionContainer() { c =>
+      val sourceFile = buildBal("return-response")
+      sourceFile should not be "Build Error"
+
+      val (initCode, _) = c.init(initPayload(sourceFile))
+      initCode should be(200)
+
+      val (runCode, runRes) = c.run(runPayload(JsObject("response" -> 
JsString("hello-world"))))
+      runRes should be(Some(JsObject("response" -> JsString("hello-world"))))
+    }
+  }
+
+  it should "should fail for Ballerina code with no run function" in {
+    val (out, err) = withActionContainer() { c =>
+      val sourceFile = buildBal("fail")
+      sourceFile should not be "Build Error"
+
+      val (initCode, _) = c.init(initPayload(sourceFile))
+      initCode should be(200)
+
+      val (runCode, _) = c.run(runPayload(JsObject("response" -> 
JsString("hello-world"))))
+      runCode should be(400)
+    }
+  }
+
+  it should "fail to initialize with bad code" in {
+    val (out, err) = withActionContainer() { c =>
+      // This is valid zip file containing a single file, but not a valid
+      // balx file.
+      val brokenFile = 
("UEsDBAoAAAAAAPxYbkhT4iFbCgAAAAoAAAANABwAbm90YWNsYXNzZmlsZVV" +
+        "UCQADzNPmVszT5lZ1eAsAAQT1AQAABAAAAABzYXVjaXNzb24KUEsBAh4DCg" +
+        "AAAAAA/FhuSFPiIVsKAAAACgAAAA0AGAAAAAAAAQAAAKSBAAAAAG5vdGFjb" +
+        "GFzc2ZpbGVVVAUAA8zT5lZ1eAsAAQT1AQAABAAAAABQSwUGAAAAAAEAAQBT" +
+        "AAAAUQAAAAAA")
+
+      val (initCode, _) = c.init(initPayload("example.Broken", brokenFile))
+      initCode should not be (200)
+    }
+  }
+
+  it should "fail for a direct call to run response with 400" in {
+    val (out, err) = withActionContainer() { c =>
+      val (runCode, runRes) = c.run(runPayload(JsObject()))
+      runCode should be(400)
+    }
+  }
+
+  def buildBal(functionName: String): String = {
+    // Set Ballerina home path to resolve dependency libs
+    val ballerinaHome = Paths.get(System.getProperty("user.dir"), "..", 
"ballerina", "proxy", "build")
+    System.setProperty("ballerina.home", ballerinaHome.toString)
+
+    val path = getClass.getResource("/".concat(functionName)).getPath
+    val context = new CompilerContext
+    val options = CompilerOptions.getInstance(context)
+
+    options.put(PROJECT_DIR, path.toString)
+    options.put(COMPILER_PHASE, CompilerPhase.CODE_GEN.toString)
+    options.put(OFFLINE, "true")
+
+    val compiler = Compiler.getInstance(context)
+    compiler.build()
+
+    val diagnosticLog = BLangDiagnosticLog.getInstance(context)
+    if (diagnosticLog.errorCount > 0) {
+      return "Build Error"
+    }
+
+    val balxPath = Paths.get(path, functionName.concat(".balx"))
+    val encoded = Base64.getEncoder.encode(Files.readAllBytes(balxPath))
+    new String(encoded, "UTF-8")
+  }
+
+}
diff --git a/tools/travis/build.sh b/tools/travis/build.sh
new file mode 100755
index 0000000..e3aa931
--- /dev/null
+++ b/tools/travis/build.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+#
+# 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.
+#
+
+set -ex
+
+# Build script for Travis-CI.
+
+SCRIPTDIR=$(cd $(dirname "$0") && pwd)
+ROOTDIR="$SCRIPTDIR/../.."
+WHISKDIR="$ROOTDIR/../openwhisk"
+UTILDIR="$ROOTDIR/../incubator-openwhisk-utilities"
+
+export OPENWHISK_HOME=$WHISKDIR
+
+# run scancode using the ASF Release configuration
+cd $UTILDIR
+scancode/scanCode.py --config scancode/ASF-Release.cfg $ROOTDIR
+
+# Build OpenWhisk deps before we run tests
+cd $WHISKDIR
+TERM=dumb ./gradlew install
+# Mock file (works around bug upstream)
+echo "openwhisk.home=$WHISKDIR" > whisk.properties
+echo "vcap.services.file=" >> whisk.properties
+
+# Build runtime
+cd $ROOTDIR
+TERM=dumb ./gradlew distDocker
diff --git a/tools/travis/publish.sh b/tools/travis/publish.sh
new file mode 100755
index 0000000..77a19fd
--- /dev/null
+++ b/tools/travis/publish.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+#
+# 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.
+#
+
+set -eux
+
+# Build script for Travis-CI.
+
+SCRIPTDIR=$(cd $(dirname "$0") && pwd)
+ROOTDIR="$SCRIPTDIR/../.."
+WHISKDIR="$ROOTDIR/../openwhisk"
+
+export OPENWHISK_HOME=$WHISKDIR
+
+IMAGE_PREFIX=$1
+IMAGE_TAG=$2
+
+if [[ ! -z ${DOCKER_USER} ]] && [[ ! -z ${DOCKER_PASSWORD} ]]; then
+docker login -u "${DOCKER_USER}" -p "${DOCKER_PASSWORD}"
+fi
+
+TERM=dumb ./gradlew \
+:ballerina:distDocker \
+-PdockerRegistry=docker.io \
+-PdockerImagePrefix=${IMAGE_PREFIX} \
+-PdockerImageTag=${IMAGE_TAG}
diff --git a/tools/travis/setup.sh b/tools/travis/setup.sh
new file mode 100755
index 0000000..3424cdb
--- /dev/null
+++ b/tools/travis/setup.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+#
+# 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.
+#
+
+set -e
+
+# Build script for Travis-CI.
+
+SCRIPTDIR=$(cd $(dirname "$0") && pwd)
+ROOTDIR="$SCRIPTDIR/../.."
+HOMEDIR="$SCRIPTDIR/../../../"
+
+# clone OpenWhisk utilities repo. in order to run scanCode
+cd $HOMEDIR
+git clone https://github.com/apache/incubator-openwhisk-utilities.git
+
+# clone main openwhisk repo. for testing purposes
+git clone --depth=1 https://github.com/apache/incubator-openwhisk.git openwhisk
+cd openwhisk
+./tools/travis/setup.sh
diff --git a/tools/travis/test.sh b/tools/travis/test.sh
new file mode 100755
index 0000000..a5b249d
--- /dev/null
+++ b/tools/travis/test.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# 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.
+#
+
+set -ex
+
+# Build script for Travis-CI.
+
+SCRIPTDIR=$(cd $(dirname "$0") && pwd)
+ROOTDIR="$SCRIPTDIR/../.."
+WHISKDIR="$ROOTDIR/../openwhisk"
+
+export OPENWHISK_HOME=$WHISKDIR
+cd ${ROOTDIR}
+TERM=dumb ./gradlew :tests:checkScalafmtAll
+TERM=dumb ./gradlew :tests:test


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

Reply via email to