commit e5847d637fc0df3fa41ab482586c44acd56a407e
Author: Dominik Adam Przybysz <alien11689@gmail.com>
Date:   Sun Dec 7 20:07:31 2014 +0100

    Initial commit

diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..ed657e2
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.blogspot.przybyszd.mockserver</groupId>
+    <artifactId>http-mock-server</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <maven-compiler-plugin.version>3.1</maven-compiler-plugin.version>
+        <groovy-eclipse-compiler.version>2.8.0-01</groovy-eclipse-compiler.version>
+        <groovy-eclipse-batch.version>2.1.8-01</groovy-eclipse-batch.version>
+        <groovy.version>2.3.3</groovy.version>
+        <httpclient.version>4.3.5</httpclient.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.codehaus.groovy</groupId>
+            <artifactId>groovy-all</artifactId>
+            <version>${groovy.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>${httpclient.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>${maven-compiler-plugin.version}</version>
+                <configuration>
+                    <compilerId>groovy-eclipse-compiler</compilerId>
+                </configuration>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.codehaus.groovy</groupId>
+                        <artifactId>groovy-eclipse-compiler</artifactId>
+                        <version>${groovy-eclipse-compiler.version}</version>
+                    </dependency>
+                    <dependency>
+                        <groupId>org.codehaus.groovy</groupId>
+                        <artifactId>groovy-eclipse-batch</artifactId>
+                        <version>${groovy-eclipse-batch.version}</version>
+                    </dependency>
+                </dependencies>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.groovy</groupId>
+                <artifactId>groovy-eclipse-compiler</artifactId>
+                <version>${groovy-eclipse-compiler.version}</version>
+                <extensions>true</extensions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <repositories>
+        <repository>
+            <id>sonatype-snapshots</id>
+            <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
+        </repository>
+    </repositories>
+
+</project>
\ No newline at end of file
diff --git a/src/main/groovy/com/blogspot/przybyszd/mockserver/SoapMockServer.groovy b/src/main/groovy/com/blogspot/przybyszd/mockserver/SoapMockServer.groovy
new file mode 100644
index 0000000..c48907c
--- /dev/null
+++ b/src/main/groovy/com/blogspot/przybyszd/mockserver/SoapMockServer.groovy
@@ -0,0 +1,153 @@
+package com.blogspot.przybyszd.mockserver
+
+import com.sun.net.httpserver.HttpExchange
+import com.sun.net.httpserver.HttpHandler
+import com.sun.net.httpserver.HttpServer
+import groovy.util.slurpersupport.GPathResult
+
+import java.util.concurrent.CopyOnWriteArrayList
+import java.util.concurrent.CopyOnWriteArraySet
+import java.util.concurrent.Executors
+
+class SoapMockServer {
+
+    HttpServerWraper httpServerWraper
+    List<HttpServerWraper> childServers = new CopyOnWriteArrayList<>()
+    Set<String> actionsNames = new CopyOnWriteArraySet<>()
+
+    SoapMockServer(int port = 9999){
+        httpServerWraper= new HttpServerWraper(port)
+
+        httpServerWraper.createContext('/serverControl', {
+            HttpExchange ex ->
+                ex.sendResponseHeaders(200, 0)
+                try{
+                GPathResult request = new XmlSlurper().parse(ex.requestBody)
+                if(ex.requestMethod== 'POST' && request.name() == 'addMock'){
+                    String name = request.name
+                    if(name in actionsNames){
+                        throw new RuntimeException('action already registered')
+                    }
+                    println "Adding $name"
+                    String mockPath = request.path
+                    int mockPort = Integer.valueOf(request.port as String)
+                    Closure predicate = Eval.me(request.predicate as String) as Closure
+                    Closure okResponse = Eval.me(request.response as String) as Closure
+                    Action action = new Action(name, predicate, okResponse)
+                    HttpServerWraper child = childServers.find {it.port == mockPort}
+                    if(!child){
+                        child = new HttpServerWraper(mockPort)
+                        childServers << child
+                    }
+                    child.addAction(mockPath, action)
+                    actionsNames << name
+                    ex.responseBody << '<addedAction/>'
+                    ex.responseBody.close()
+                }
+                }catch(Exception e){
+                    ex.responseBody << """<exceptionOccured>${e.message}</exceptionOccured>"""
+                    ex.responseBody.close()
+                }
+                //TODO add delete mock
+                //TODO add list mock
+        })
+    }
+
+    void stop(){
+        childServers.each {it.stop()}
+        httpServerWraper.stop()
+    }
+
+    private static final class HttpServerWraper{
+        final HttpServer httpServer
+        final int port
+
+        List<ContextExecutor> executors = []
+
+        HttpServerWraper(int port){
+            this.port = port
+            InetSocketAddress addr = new InetSocketAddress(Inet4Address.getByName("0.0.0.0"), port)
+            httpServer = HttpServer.create(addr, 0)
+            httpServer.executor = Executors.newCachedThreadPool()
+            println "Http server statrting on port $port..."
+            httpServer.start()
+            println 'Http server is started'
+        }
+
+        void createContext(String context, HttpHandler handler){
+            httpServer.createContext(context, handler)
+        }
+
+        void addAction(String path, Action action){
+            ContextExecutor executor = executors.find {it.path == path}
+            if(executor){
+                executor.actions.add(action)
+            }else {
+                executors.add(new ContextExecutor(this, path, action))
+            }
+        }
+
+        void removeAction(String name){
+            //TODO delete action by name
+        }
+
+        void stop(){
+            executors.each {httpServer.removeContext(it.path)}
+            httpServer.stop(0)
+        }
+    }
+
+    private static final class ContextExecutor{
+        final HttpServerWraper httpServerWraper
+        final String path
+        List<Action> actions
+
+        ContextExecutor(HttpServerWraper httpServerWraper, String path, Action initialAction) {
+            this.httpServerWraper = httpServerWraper
+            this.path = path
+            this.actions = new CopyOnWriteArrayList<>([initialAction])
+            httpServerWraper.createContext(path,{
+                HttpExchange ex ->
+                    ex.sendResponseHeaders(200, 0)
+                    String input = ex.requestBody.text
+                    println "Mock received input"
+                    GPathResult xml = new XmlSlurper().parseText(input)
+                    for (Action action : actions){
+                        if(action.predicate(xml)){
+                            ex.responseBody << action.responseOk(xml)
+                            ex.responseBody.close()
+                            return
+                        }
+                    }
+                    ex.responseBody << "<invalidInput/>"
+                    ex.responseBody.close()
+            })
+        }
+    }
+
+    private static final class Action{
+        final String name
+        final Closure predicate
+        final Closure responseOk
+
+        Action(String name, Closure predicate, Closure responseOk) {
+            this.name = name
+            this.predicate = predicate
+            this.responseOk = responseOk
+        }
+    }
+
+    static void main(String [] args) {
+        SoapMockServer soapMockServer = new SoapMockServer()
+
+        Runtime.runtime.addShutdownHook(new Thread({
+            println 'Http server is stopping...'
+            soapMockServer.stop()
+            println 'Http server is stopped'
+        } as Runnable))
+
+        while(true){
+            Thread.sleep(10000)
+        }
+    }
+}