package org.wso2.carbon.esb.mediators.cache;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.util.AXIOMUtil;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.lang3.CharEncoding;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.apache.http.impl.client.DefaultHttpClient;
import org.wso2.esb.integration.common.utils.ESBIntegrationTest;

import java.util.HashMap;
import java.util.Map;

/**
 * This test can be used make sure cache mediator can cache payloads with Processing instructions (PIs).
 */
public class ESBJAVA4318Testcase extends ESBIntegrationTest {

    private final DefaultHttpClient httpClient = new DefaultHttpClient();
    private final Map<String, String> headers = new HashMap<String, String>(1);

    @BeforeClass(alwaysRun = true)
    protected void init() throws Exception {
        super.init();

        String proxy = "<proxy xmlns=\"http://ws.apache.org/ns/synapse\"\n"
                + "       name=\"PF\"\n"
                + "       transports=\"https http\"\n" + "       startOnLoad=\"true\"\n" + "       trace=\"disable\">\n"
                + "    <description/>\n" + "    <target>\n" + "        <inSequence>\n"
                + "            <cache scope=\"per-host\"\n" + "                   collector=\"false\"\n"
                + "                   hashGenerator=\"org.wso2.carbon.mediator.cache.digest.DOMHASHGenerator\"\n"
                + "                   timeout=\"60\">\n" + "                <onCacheHit>\n"
                + "                    <log level=\"full\"/>\n"
                + "                    <property name=\"messageType\" value=\"application/xml\" scope=\"axis2\"/>\n"
                + "                    <respond/>\n" + "                </onCacheHit>\n"
                + "                <implementation type=\"memory\" maxSize=\"100\"/>\n" + "            </cache>\n"
                + "            <send>\n" + "                <endpoint>\n"
                + "                    <address uri=\"http://localhost:9000/services/SimpleStockQuoteService\"/>\n"
                + "                </endpoint>\n" + "            </send>\n" + "        </inSequence>\n"
                + "        <outSequence>\n" + "            <payloadFactory media-type=\"xml\">\n"
                + "                <format>\n" + "                    <b>\n"
                + "                        <?xml-multiple array?>\n" + "                        <xyz>\n"
                + "                            <a xmlns=\"\">after cache</a>\n" + "                        </xyz>\n"
                + "                    </b>\n" + "                </format>\n" + "                <args/>\n"
                + "            </payloadFactory>\n" + "            <cache scope=\"per-host\" collector=\"true\"/>\n"
                + "            <property name=\"messageType\" value=\"application/xml\" scope=\"axis2\"/>\n"
                + "            <send>\n" + "                <endpoint>\n" + "                    <default/>\n"
                + "                </endpoint>\n" + "            </send>\n" + "        </outSequence>\n"
                + "    </target>\n" + "</proxy>";

        OMElement omProxy = AXIOMUtil.stringToOM(proxy);
        addProxyService(omProxy);
        isProxyDeployed("PF");
    }
    @Test(groups = "wso2.esb", description = "cache meditor with payloads including Processing Insturctions")
    public void testCacheMediatorWithPIs() throws Exception {

        String requestXml = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ser=\"http://services.samples\" xmlns:xsd=\"http://services.samples/xsd\">\n"
                + "   <soapenv:Header>\n"
                + "      <m:Trans xmlns:m=\"http://www.w3schools.com/transaction/\">234</m:Trans>\n"
                + "   </soapenv:Header>\n" + "   <soapenv:Body>\n" + "      <ser:getFullQuote>\n"
                + "         <ser:request>\n" + "            <xsd:symbol>IBM</xsd:symbol>\n"
                + "         </ser:request>\n" + "      </ser:getFullQuote>\n" + "   </soapenv:Body>\n"
                + "</soapenv:Envelope>";

        final String expectedValue = "<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope " +
                "xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><soapenv:Body><b xmlns=\"http://ws" +
                ".apache.org/ns/synapse\"><?xml-multiple  array?><xyz><a xmlns=\"\">after " +
                "cache</a></xyz></b></soapenv:Body></soapenv:Envelope>";

        DefaultHttpClient httpclient = new DefaultHttpClient();

        // this is to populate the cache mediator
        HttpPost httpPost = new HttpPost(getProxyServiceURLHttp("PF"));
        httpPost.addHeader("SOAPAction", "urn:getFullQuote");
        httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "text/xml;charset=UTF-8");
        HttpEntity stringEntity = new StringEntity(requestXml, CharEncoding.UTF_8);
        httpPost.setEntity(stringEntity);
        //call to the backend
        httpclient.execute(httpPost);

        // this is to get the actual cached response
        HttpResponse cachedResponse = httpclient.execute(httpPost);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        cachedResponse.getEntity().writeTo(baos);
        String actualValue = baos.toString();
        Assert.assertEquals(actualValue, expectedValue);
    }
}
@@ -5265,37 +5265,31 @@
     
-//call to the backend%0A       
+HttpResponse response =
  htt
@@ -5308,32 +5308,189 @@
 ute(httpPost);%0A%0A
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();%0A        response.getEntity().writeTo(baos);%0A        String actualValue = baos.toString();%0A%0A
         // this 
@@ -5515,17 +5515,16 @@
 al cache
-d
  respons
@@ -5541,31 +5541,372 @@
 Http
-Response cachedResponse
+Post httpPost2 = new HttpPost(getProxyServiceURLHttp(%22PF%22));%0A        httpPost2.addHeader(%22SOAPAction%22, %22urn:getFullQuote%22);%0A        httpPost2.setHeader(HttpHeaders.CONTENT_TYPE, %22text/xml;charset=UTF-8%22);%0A        HttpEntity stringEntity2 = new StringEntity(requestXml, CharEncoding.UTF_8);%0A        httpPost2.setEntity(stringEntity2);%0A        HttpResponse response2
  = h
@@ -5961,32 +5961,33 @@
 utputStream baos
+2
  = new ByteArray
@@ -6014,22 +6014,17 @@
     
-cachedR
+r
 esponse
+2
 .get
@@ -6036,32 +6036,33 @@
 y().writeTo(baos
+2
 );%0A        Strin
@@ -6066,39 +6066,41 @@
 ring actualValue
+2
  = baos
+2
 .toString();%0A   
@@ -6135,16 +6135,17 @@
 ualValue
+2
 , expect

Fix test failure due to inccorect use of BasicClientConnManager (#1444)