Enterprise Integration Zone is brought to you in partnership with:

Java programmer since 1996. J2SE, J2EE Expert, Technical Leader, Team Manager. Rich experience in infrastructure and architecture of distributed applications Pavel has posted 6 posts at DZone. You can read more from them at their website. View Full User Profile

HTTP Server + Groovlet = A Back-Door Type of Trick When Using A Java App

08.13.2012
| 5118 views |
  • submit to reddit
Recently I saw an article about simple groovlet. Groovlet allows you to execute any code in your server. It looks very useful for creating a backdoor - for debugging, troubleshooting, etc.

My problem, however, is that we don't just have a server, but we also have a Swing-rich client who is unable to execute groovlets. So I tried to create something like this in a standalone application without adding to the application-embedded servlet engine (Jetty or Tomcat).

Luckily, I just read an article about a Simple HTTP server inside a standard Java library. I decided to use some of its ideas.

Let's start from Main:
public class Main {
    public static void main(String[] args) {
        // You can set port number from command line or leave it hardcoded
        HttpBackdoorRunner runner = new HttpBackdoorRunner(18999, true);
        runner.start();
    }
}
Let's continue in groovy because it is simpler :)

 

import com.sun.net.httpserver.HttpServer
import java.util.concurrent.Executors

/**
* This class starts the server with our handler (Embedded server is not Servlet container!)
*/
class HttpBackdoorRunner {

    final int port
    final boolean silent

    HttpBackdoorRunner(int port, boolean silent) {
        this.port = port
        this.silent = silent
    }


    def start() {
        try {
            InetSocketAddress addr = new InetSocketAddress(port);
            HttpServer server = HttpServer.create(addr, 0);

            server.createContext("/", new BackdoorHandler());
            server.setExecutor(Executors.newCachedThreadPool(
            ));
            server.start();
        }
        catch(Exception e) {
            if (silent) {
                // Ignore
            }
            else throw new RuntimeException(e)
        }
    }
}

 

Now - the HTTP requests handler:

 

/**
*  I need this abstraction level to reuse script running code in groovlet and standalone backdoor
* The way, you receive script text is different in those two situations
*/
class BackdoorScriptRunner {

    void runScript(script, responseBody, uri) {
        def scriptOutput = new ByteArrayOutputStream()

        if (script) {
            // Redirect output
            def saveOut = System.out

            def stream = new PrintStream(scriptOutput)
            System.out = stream
            try{
                def result = new GroovyShell().run(script, "dynamic.groovy");
            }
            catch (Throwable e) {
                e.printStackTrace(stream);
            }
            System.out = saveOut

        }
        responseBody.println createHTML(uri, script, scriptOutput)
        responseBody.close();
    }

    String createHTML(uri, script, scriptOutput) {
        """
                   < form action="${uri}" method="post">
                   < h2>BackDoor
                   Code comes here:   
< textarea cols="120" rows="5" name="groovyscript"> ${script ? script : ""}< /textarea> < br> < input type="submit" value="Go!" /> < /form> < br> ${scriptOutput.toString() ? "< h2>Output< /h2>< pre>${scriptOutput}< /pre>" : ""} """ } }

 

And now - start it up!
Published at DZone with permission of its author, Pavel Bernshtam.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)