Package com.ibm.sbt.test.lib

Source Code of com.ibm.sbt.test.lib.MockSerializer

package com.ibm.sbt.test.lib;
/*
* © Copyright IBM Corp. 2013
*
* Licensed 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 java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.RandomAccessFile;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map.Entry;

import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolVersion;
import org.apache.http.conn.EofSensorInputStream;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicHttpResponse;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import com.ibm.commons.runtime.Context;
import com.ibm.commons.util.io.base64.Base64OutputStream;
import com.ibm.commons.xml.DOMUtil;
import com.ibm.commons.xml.XMLException;
import com.ibm.sbt.services.client.ClientServicesException;
import com.ibm.sbt.services.endpoints.Endpoint;

/**
*
* @author Lorenzo Boccaccia
* @author Carlos Manias
*
*/
public class MockSerializer {

  // used to know when to append and when to reset the mock file; //TODO will
  // not work if we test with multiple endpoints in the same test run
  private static final HashSet<String> seen = new HashSet<String>();
  private static final HashMap<String, Iterator<Node>> replyStream = new HashMap<String, Iterator<Node>>();
  private Endpoint endpoint;
  private String endpointName;

  public MockSerializer(Endpoint endpoint) {
    if (endpoint instanceof MockEndpoint) {
      endpointName = ((MockEndpoint) endpoint).getInnerEndpoint();
    } else {
      for (Entry e : Context.get().getSessionMap().entrySet()) {
        if (e.getValue() == endpoint)
          this.endpointName = e.getKey().toString();
      }
    }
  }

  public void writeData(String data) throws IOException {
    File file = getFile(true);
    RandomAccessFile raf = new RandomAccessFile(file, "rw");
    // Seek to end of file
    System.out.println("Writing Record @" + file.length() + " in " + file.getAbsolutePath());
    raf.seek((file.length() - "\n</responses>".length()));

    raf.write(data.getBytes("UTF-8"));
    raf.write("\n</responses>".getBytes("UTF-8"));

  }

  private Iterator<Node> getReader() throws IOException {
    String path = getResource();
    if (replyStream.containsKey(path)) {
      return replyStream.get(path);
    }
    Document doc;
    try {

      doc = DOMUtil.createDocument(getClass().getResourceAsStream(path),
          false);

      Iterator<Node> nodeIt = DOMUtil.evaluateXPath(doc, "//response")
          .getNodeIterator();
      replyStream.put(path, nodeIt);
      return nodeIt;

    } catch (XMLException e) {
      throw new IOException(e);
    }

  }

  public synchronized HttpResponse recordResponse(HttpResponse response) {
    try {
      StringWriter out = new StringWriter();
      out.write("\n<response ");

      out.write("statusCode=\"");
      int statusCode = response.getStatusLine().getStatusCode();
      out.write(String.valueOf(statusCode).trim());
      out.write("\" ");
      out.write("statusReason=\"");
      String reasonPhrase = response.getStatusLine().getReasonPhrase();
      out.write(String.valueOf(reasonPhrase).trim());
      out.write("\">\n");
      out.write("<headers>");
      Header[] allHeaders = response.getAllHeaders();
      out.write(serialize(allHeaders));
      String serializedEntity = null;
      if (response.getEntity()!=null) {
        out.write("</headers>\n<data><![CDATA[");
       serializedEntity = serialize(response.getEntity()
          .getContent());
       serializedEntity = serializedEntity.replaceAll("<!\\[CDATA\\[", "\\!\\[CDATA\\[").replaceAll("\\]\\]>", "\\]\\]");
      out.write(serializedEntity);
      out.write("]]></data>\n</response>");
      } else {
        out.write("</headers>\n</response>");
      }
      out.flush();
      out.close();
      writeData(out.toString());

      return buildResponse(allHeaders, statusCode, reasonPhrase,
          serializedEntity);

    } catch (IOException e) {
      throw new UnsupportedOperationException(e);
    }
  }
 
  private HttpResponse buildResponse(Header[] allHeaders, int statusCode,
      String reasonPhrase, String serializedEntity) {
    BasicHttpResponse r = new BasicHttpResponse(new ProtocolVersion("HTTP",
        1, 0), statusCode, reasonPhrase);
    r.setHeaders(allHeaders);

    if (serializedEntity!=null) {
    BasicHttpEntity e = new BasicHttpEntity();
    // TODO: use content-encoding header
    try {
      e.setContent(new ByteArrayInputStream(serializedEntity
          .getBytes("UTF-8")));
    } catch (UnsupportedEncodingException e1) {
      throw new UnsupportedOperationException(e1);
    }
    for (Header h : allHeaders) {
      if (h.getName().equalsIgnoreCase("Content-Type")) {
        e.setContentType(h.getValue());
      }
    }
    e.setContentLength(serializedEntity.length());
    r.setEntity(e);
    }
    return r;
  }

  private String serialize(InputStream is) throws IOException {
    ByteArrayOutputStream w = new ByteArrayOutputStream();
    IOUtils.copy(is, w);
    return w.toString("UTF-8");
  }

  private String serialize(Node o) throws IOException {
    ByteArrayOutputStream w = new ByteArrayOutputStream();
    try {
      DOMUtil.serialize(w, o, null);
    } catch (XMLException e) {
      throw new IOException(e);
    }
    return w.toString("UTF-8");

  }

  private String serialize(Header[] o) {
    StringWriter w = new StringWriter();
    for (Header h : o) {
      w.write("\n    <header>\n        <name><![CDATA[");
      w.write(h.getName());
      w.write("]]></name>\n        <value><![CDATA[");
      w.write(h.getValue());
      w.write("]]></value>\n    </header>");

    }

    return w.toString();
  }

  private String serialize(Object o) throws IOException {
    if (o instanceof EofSensorInputStream)
      return serialize((EofSensorInputStream) o);
    if (o instanceof Node)
      return serialize((Node) o);
    if (o instanceof Header[])
      return serialize((Header[]) o);
    ByteArrayOutputStream w = new ByteArrayOutputStream();
    Base64OutputStream base64OutputStream = new Base64OutputStream(w);
    ObjectOutputStream os = new ObjectOutputStream(base64OutputStream);
    os.writeObject(o);
    os.flush();
    os.close();
    base64OutputStream.flush();
    base64OutputStream.close();
    return w.toString("UTF-8");
  }

  private Object deserialize(String o) throws IOException {
    ObjectInputStream is = new ObjectInputStream(new ByteArrayInputStream(
        o.getBytes()));
    try {
      return is.readObject();
    } catch (ClassNotFoundException e) {
      throw new IOException(e);
    } finally {
      is.close();
    }
  }

  public HttpResponse replayResponse() throws ClientServicesException {
    try {
      Node r = getReader().next();

      NamedNodeMap nnm = r.getAttributes();

      String code = nnm.getNamedItem("statusCode").getTextContent();
      String reason = nnm.getNamedItem("statusReason").getTextContent();

      Node headers = (Node) DOMUtil.evaluateXPath(r, "./headers")
          .getSingleNode();
      Node data = (Node) DOMUtil.evaluateXPath(r, "./data")
          .getSingleNode();
      String entity = null;
      if (data!= null ) {
      if (data.getFirstChild() == null)
        entity = "";
      else
        entity = ((CharacterData) data.getFirstChild()).getData();
      }
      Iterator<Node> hIt = (Iterator<Node>) DOMUtil.evaluateXPath(
          headers, "./header").getNodeIterator();
      ArrayList<Header> allHeaders = new ArrayList<Header>();

      while (hIt.hasNext()) {
        Node headerNode = hIt.next();
        String name = ((Node) DOMUtil.evaluateXPath(headerNode,
            "./name").getSingleNode()).getTextContent();
        String value = ((Node) DOMUtil.evaluateXPath(headerNode,
            "./value").getSingleNode()).getTextContent();
        allHeaders.add(new BasicHeader(name, value));
      }

      return buildResponse(
          allHeaders.toArray(new Header[allHeaders.size()]),
          Integer.valueOf(code), reason, entity);

    } catch (FileNotFoundException e) {
      StackTraceElement trace = getStackTraceElement();
      String fullClassName = trace.getClassName();
      String methodName = trace.getMethodName();
      String endpointName = getEndpointName();
      throw new MockingException(e, "Mocking file missing for test: "
          + fullClassName + "." + methodName + "/" + endpointName);
    } catch (Exception e) {
      throw new MockingException(e,
          "Corrupted Mocking file, please regenerate: " + getPath());
    }
  }

  private void deserializeThrowable(Node r) {
    // TODO Auto-generated method stub

  }

  private StackTraceElement getStackTraceElement() {
    StackTraceElement last = null;
    StackTraceElement[] stackTraceElements = Thread.currentThread()
        .getStackTrace();
    for (StackTraceElement trace : stackTraceElements) {
      try {
        if (Class.forName(trace.getClassName())
            .getMethod(trace.getMethodName())
            .isAnnotationPresent(Test.class))
          last = trace;
        if (Class.forName(trace.getClassName())
            .getMethod(trace.getMethodName())
            .isAnnotationPresent(After.class))
          last = trace;
        if (Class.forName(trace.getClassName())
            .getMethod(trace.getMethodName())
            .isAnnotationPresent(Before.class))
          last = trace;
        if (Class.forName(trace.getClassName())
            .getMethod(trace.getMethodName())
            .isAnnotationPresent(AfterClass.class))
          last = trace;
        if (Class.forName(trace.getClassName())
            .getMethod(trace.getMethodName())
            .isAnnotationPresent(BeforeClass.class))
          last = trace;
      } catch (Exception e) {
      }
    }
    return last;
  }

  private File getFile(boolean write) throws IOException {
    String path = getPath();
    boolean reset = !seen.contains(path);
    seen.add(path);

    File file = new File(path);
    File parentFolder = new File(file.getParent());
    parentFolder.mkdirs();
    if (write && reset && file.exists())
      file.delete();
    if (!file.exists()) {
      file.createNewFile();
      FileOutputStream st = new FileOutputStream(file);
      st.write("<?xml version=\"1.0\"?>\n<responses>\n</responses>"
          .getBytes("UTF-8"));
      st.flush();
      st.close();
    }
    return file;
  }

  private String getEndpointName() {
    return endpointName;
  }

  private String getPath() {
    StackTraceElement trace = getStackTraceElement();
    String basePath = System.getProperty("user.dir");
    String fullClassName = trace.getClassName()
        .replace(".", File.separator);
    String className = fullClassName.substring(fullClassName
        .lastIndexOf(File.separatorChar));
    String packageName = fullClassName.substring(0,
        fullClassName.lastIndexOf(File.separatorChar));
    String methodName = trace.getMethodName();
    String endpointName = getEndpointName();
    String path = new StringBuilder(basePath).append(File.separator)
        .append("src").append(File.separator).append("test").append(File.separator).append("resources").append(File.separator).append(packageName)
        .append(File.separator).append("mockData")
        .append(File.separator).append(endpointName)
        .append(className).append("_")
        .append(methodName).append(".mock").toString();
    return path;
  }
  private String getResource() {
    StackTraceElement trace = getStackTraceElement();
    String methodName = trace.getMethodName();
   
    String fullClassName = trace.getClassName()
        .replace(".", "/");
    String packageName = fullClassName.substring(0,
        fullClassName.lastIndexOf("/"));
    String className = fullClassName.substring(fullClassName
        .lastIndexOf("/"));
    String resource = new StringBuilder("/").append(packageName)
    .append("/").append("mockData")
    .append("/").append(endpointName).append(className).append("_")
    .append(methodName).append(".mock").toString();
    return resource;
  }
}
TOP

Related Classes of com.ibm.sbt.test.lib.MockSerializer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.