import static org.junit.Assert.*;
import org.junit.After;
import java.lang.management.*;
import java.io.*;
import java.net.*;
import javax.xml.xpath.*;
import org.xml.sax.InputSource;
import org.w3c.dom.NodeList;

public class SearchInHeap {
  String jhatPort = Integer.toString(7000 + Integer.parseInt(System.getProperty("org.gradle.test.worker")));
  String jhat;
  String hprof;
  boolean isSetup = false;
  // FIXME Change to false when we have enabled searchInHeapForByte
  boolean goDown = true;

  @After
  public void searchInHeapForChar() throws IOException, InterruptedException, XPathExpressionException {
    try {
      setupSearchInHeap();
      runOQL("select escape(a.toString()) from [C a where /really_secret_string/(a.toString())");
    }
    finally {
      tearDown();
    }
  }

  // FIXME Add @After when SecurerString.secureErase(byte[]) is implemented
  public void searchInHeapForByte() throws IOException, InterruptedException, XPathExpressionException {
    try {
      setupSearchInHeap();
      runOQL("select {" +
             "  obj:b," +
             "  value:(function(b) {" +
             "    var a = '';" +
             "    for (var i = 0; i < b.length; i++) {" +
             "      a+=String.fromCharCode(b[i]);" +
             "    }" +
             "    return escape(a);" +
             "  })(b)" +
             "} " +
             "from [B b where " +
             "(function(b) {" +
             "  var a = '';" +
             "  for (var i = 0; i < b.length; i++) {" +
             "    a+=String.fromCharCode(b[i]);" +
             "  }" +
             "  return /really_secret_string/(a);" +
             "})(b)");
    }
    finally {
      tearDown();
    }
  }

  public void setupSearchInHeap() throws IOException, InterruptedException, XPathExpressionException {
    if (isSetup) {
      return;
    }
    String pid = ManagementFactory.getRuntimeMXBean().getName().replaceAll("@.*", "");
    String tmp = System.getProperty("temporaryDir");
    hprof = tmp + "/" + pid + ".hprof";
    jhat = "jhat -port " + jhatPort + " " + hprof;
    try {
      System.out.println("Dumping heap with jmap");
      Runtime.getRuntime().exec(new String[] {"jmap", String.format("-dump:format=b,file=%s", hprof), pid}).waitFor();

      System.out.println("Starting jhat");
      Process p=Runtime.getRuntime().exec(jhat);

      BufferedReader reader=new BufferedReader(new InputStreamReader(p.getInputStream()));
      String line=reader.readLine();
      while(!line.matches("Server is ready."))
      {
        line=reader.readLine();
      }
      System.out.println("jhat ready!");
      Thread.sleep(1000);
    }
    finally {
      isSetup = true;
    }
  }

  public void runOQL(String oql) throws IOException, InterruptedException, XPathExpressionException {
    System.out.println("Running OQL query...");
    URL oqlUrl = new URL("http://localhost:" + jhatPort + "/oql/?query=" + URLEncoder.encode(oql, "UTF-8"));
    URLConnection oqlConnection = oqlUrl.openConnection();
    BufferedReader in = new BufferedReader(new InputStreamReader(oqlConnection.getInputStream()));
    String inputLine;
    String xml = "";

    while ((inputLine = in.readLine()) != null)
      xml += inputLine;
    in.close();

    NodeList nodeList;
    try {
      // What I don't do just not to add an external dependency...
      xml = xml.replaceAll("(\\w+)=([^'\"][^ ]+?)([^'\"])", "$1='$2'$3");
      String xpath = "//table[@border=1]//td";
      XPath xPath = XPathFactory.newInstance().newXPath();
      nodeList = (NodeList) xPath.evaluate(xpath, new InputSource(new StringReader(xml)), XPathConstants.NODESET);
    }
    catch (javax.xml.xpath.XPathExpressionException e) {
      System.out.println(xml);
      throw e;
    }
    theAssert(nodeList.getLength());
  }

  public void tearDown() throws IOException, InterruptedException {
    if (goDown) {
      Runtime.getRuntime().exec(new String[] {"pkill", "-f", jhat}).waitFor();
      new File(hprof).delete();
    }
    else {
      goDown = true;
    }
  }

  void theAssert(int found) {
    assertEquals("Secret not found!", 0, found);
  }
}

@@ -3269,28 +3269,16 @@
 deList;%0A
-    try %7B%0A  
     // W
@@ -3334,26 +3334,24 @@
 ency...%0A    
- 
- 
 xml = xml.re
@@ -3406,26 +3406,24 @@
 2'$3%22);%0A    
-  
 String xpath
@@ -3455,18 +3455,16 @@
 d%22;%0A    
- 
- 
 XPath xP
@@ -3504,26 +3504,24 @@
 newXPath();%0A
-  
     nodeList
@@ -3625,123 +3625,8 @@
 T);%0A
-    %7D%0A    catch (javax.xml.xpath.XPathExpressionException e) %7B%0A      System.out.println(xml);%0A      throw e;%0A    %7D%0A
     

Remove XML parsing debug code