Package com.dgwave.osrs

Source Code of com.dgwave.osrs.OsrsClient

/*
* Copyright 2012, Digiwave Systems Ltd., Akber A. Choudhry,
*   and other individual contributors identified by the
*   @authors tag in each source artefact.
*
*   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.
*/

package com.dgwave.osrs;

import static com.dgwave.osrs.Config.OSRSCONFIG;
import static com.dgwave.osrs.Config.OSRSDIR;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.math.BigInteger;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.sax.SAXSource;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import com.dgwave.osrs.jaxb.Body;
import com.dgwave.osrs.jaxb.DataBlock;
import com.dgwave.osrs.jaxb.DtAssoc;
import com.dgwave.osrs.jaxb.Header;
import com.dgwave.osrs.jaxb.Item;
import com.dgwave.osrs.jaxb.OPSEnvelope;
import com.dgwave.osrs.jaxb.ObjectFactory;
import com.dgwave.osrs.req.OsrsRequest;
import com.dgwave.osrs.resp.OsrsResponse;

/**
* Singleton client that does all the low-level stuff for
* communications.
*
* @author Akber Choudhry
*/
public class OsrsClient {
 
  /**
   * Singleton instance
   */
  private static OsrsClient instance;
 
  /**
   * Fields
   */
  private static Logger logger = LoggerFactory.getLogger(OsrsClient.class);
  private DefaultHttpClient httpClient;
  private String uri;
  private final String version = "0.9";
  private final String protocol = "XCP";
  private JAXBContext jc = null; // multi-threaded
  XMLReader xmlReader = null;
  private ObjectFactory oj = null; //just factory
  private OsrsResponseFactory orf = new OsrsResponseFactory();
 
  /**
   * Get the singleton instance
   */
  public static OsrsClient getInstance(boolean newHttpClient) {
    if (newHttpClient) {
      instance = null;
    }
   
    if (instance == null) {
      instance = new OsrsClient();
    }
    return instance;
  }

 
  /**
   * This should be the only constructor called
   * It will recreate the httpClient whenever it is called, allowing
   */
  private OsrsClient() {
    logger.info("New OsrsClient instance being created");
    this.httpClient = new DefaultHttpClient(
        getConnectionManager(), getHttpParams());
    this.uri = "https://" + OsrsConfig.getValue("osrs.host") + ":" + OsrsConfig.getValue("osrs.sslPort") + "/";
    initJaxb();
  }

  /**
   * Create HttpParams from configuration
   * @return HttpParams
   */
  private HttpParams getHttpParams() {
    HttpParams params = new BasicHttpParams();
    params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 60000);
    params.setParameter(CoreConnectionPNames.SO_TIMEOUT, 60000);
    return params;
  }
 
 

  /**
   * Creates a connection manager from configuration - handles test mode
   * @return ClientConnectionManager
   * @throws OsrsException
   */
  private ClientConnectionManager getConnectionManager() throws OsrsException {

    // Create and initialize scheme registry
    SchemeRegistry schemeRegistry = new SchemeRegistry();
   
    boolean testMode = "test".equals(OsrsConfig.getValue("osrs.environment"));
    int port = Integer.parseInt(OsrsConfig.getValue("osrs.port"));
    int sslPort = Integer.parseInt(OsrsConfig.getValue("osrs.sslPort"));
    schemeRegistry.register(new Scheme("http", port, PlainSocketFactory
        .getSocketFactory()));
   
    Scheme sslScheme;
    if (testMode) {
      try {
        sslScheme = new Scheme("https", sslPort,
            new SSLSocketFactory(getTestTrustStore()));
      } catch (Exception e) {
        throw new OsrsException("Error creating test SSL scheme", e);
      }
    } else {
      sslScheme = new Scheme("https", sslPort,
          SSLSocketFactory.getSocketFactory());
    }
    schemeRegistry.register(sslScheme);
   

    // Create an HttpClient with the PoolingClientConnManager (thread-safe).
    // This connection manager must be used if more than one thread will
    // be using the HttpClient.
    ClientConnectionManager cm = new PoolingClientConnectionManager(
        schemeRegistry, 60, TimeUnit.SECONDS);
    return cm;
  }


  private KeyStore getTestTrustStore() {
    InputStream instream = null;
    try {
      KeyStore trustStore = KeyStore.getInstance("jks");
      instream = this.getClass().getClassLoader()
          .getResourceAsStream("opensrsCA.jks");
      trustStore.load(instream, "'dgwaveopensrs'".toCharArray());
      return trustStore;
    } catch (Exception e) {
      throw new OsrsException("Error with SSL root CA creation in test mode", e);
    } finally {
      try {
        instream.close();
      } catch (Exception ignore) {
      }
    }
  }

  private String bytesToHex(byte[] bytes) {
    String s = new String();
    BigInteger bi = new BigInteger(1, bytes);
    // Format to hexadecimal
    s = bi.toString(16); // 120ff0
    if (s.length() % 2 != 0) {
      // Pad with 0
      s = "0" + s;
    }
    return s;
  }

  private String getSignature(String xml) {
    String signature = new String();
    try {
      MessageDigest md5 = MessageDigest.getInstance("MD5");
      String concat = xml + OsrsConfig.getValue("osrs.key");
      concat = bytesToHex(md5.digest(concat.getBytes()));
      signature = bytesToHex(md5.digest(concat.concat(
          OsrsConfig.getValue("osrs.key")).getBytes()));
    } catch (Exception ex) {
      logger.warn("Error generating signature: ", ex);
    }
    return signature;
  }

  /**
   * Raw send receive - one of two methods that executes network operations
   *
   * @param HttpPost
   * @return String
   * @throws OsrsException
   */
  protected String sendReceive(HttpPost post) throws OsrsException {

    try {
      HttpResponse response = httpClient.execute(post);
      HttpEntity entity = response.getEntity();
      String ret =  EntityUtils.toString(entity);
      EntityUtils.consume(entity);
      return ret;
    } catch (Exception e) {
      throw new OsrsException("Error on base sendReceive", e);
    }

  }

  public OsrsResponse sendReceive(OsrsRequest request) throws OsrsException {

    String ret = sendReceive(getString(request));
    OPSEnvelope resp = createEnvelope(ret);
    OsrsResponse response = orf.createResponse(request, resp);
      return response;
  }
 
  public String sendReceive(String xml) throws OsrsException {

    String signature = getSignature(xml);

    HttpPost postRequest = new HttpPost(uri);
    postRequest.addHeader("Content-Type", "text/xml");
    postRequest.addHeader("X-Signature", signature);
    postRequest.addHeader("X-Username", OsrsConfig.getValue("osrs.userName"));

    try {
      postRequest.setEntity(new StringEntity(xml));
      String response = sendReceive(postRequest);
      return response;
    } catch (Exception ex) {
      throw new OsrsException("Sending post got exception ", ex);
    }
  }

  protected OPSEnvelope createEnvelope(String ret) throws OsrsException {
    OPSEnvelope opsEnvelope = null;
    try {

          InputSource inputSource = new InputSource(new StringReader(ret));
          SAXSource source = new SAXSource(xmlReader, inputSource);     
      Unmarshaller u = jc.createUnmarshaller();
      opsEnvelope = (OPSEnvelope)u.unmarshal(source);
    } catch (Exception e) {
      throw new OsrsException("Error parsing response: " + ret, e);
    }
    return opsEnvelope;
  }

  protected OPSEnvelope getEmptyEnvelope() throws OsrsException {
    initJaxb();
    OPSEnvelope opsEnvelope = null;

      opsEnvelope = oj.createOPSEnvelope();
      Header header = oj.createHeader();
      header.setVersion(this.version);
      opsEnvelope.setHeader(header);
     
      DataBlock dBlock = oj.createDataBlock();
     
      Body body = oj.createBody();
      body.setDataBlock(dBlock);
     
      opsEnvelope.setBody(body);
      return opsEnvelope;
  }
 
  private void initJaxb() throws OsrsException {
      if (jc != null && oj != null) return;
    try {
      this.jc = JAXBContext.newInstance("com.dgwave.osrs.jaxb");
      this.oj = new ObjectFactory();
        SAXParserFactory spf = SAXParserFactory.newInstance();
          spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
          spf.setNamespaceAware(true);
          spf.setValidating(false);
          xmlReader = spf.newSAXParser().getXMLReader();
          xmlReader.setEntityResolver(new EntityResolver() { 
        @Override
         public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
          logger.debug("Ignoring DTD");
          return new InputSource(new StringReader(""));
        }
      });     
    } catch (Exception e) {
      throw new OsrsException("JAXB Error", e);
    }
  }
 
  protected String getString(OsrsRequest request) throws OsrsException {
    OPSEnvelope envelope = getEmptyEnvelope();
    Map<String, Object> attrs = request.getAttributes();

    Item pro = oj.createItem();
    pro.setKey("protocol");
    pro.setStringValue(this.protocol);
    Item obj = oj.createItem();
    obj.setKey("object");
    obj.setStringValue(request.getObject());
    Item act = oj.createItem();
    act.setKey("action");
    act.setStringValue(request.getAction());
    Item att = oj.createItem();
    att.setKey("attributes");
    att.addDtAssoc(processAttrs(attrs));
   
    DtAssoc c = oj.createDtAssoc();
    c.addItem(pro);
    c.addItem(act);
    c.addItem(obj);
    c.addItem(att);
    ((List<Object>)envelope.getBody().getDataBlock()
      .getDtAass()).add(c);

   
    try {
    Marshaller m = jc.createMarshaller();
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);

      m.setProperty("com.sun.xml.internal.bind.xmlHeaders",
        "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" +
        "<!DOCTYPE OPS_envelope SYSTEM '" + OSRSDIR + OSRSCONFIG + "ops.dtd'>");
      //StringWriter writer = new StringWriter();
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      m.marshal(envelope, baos);

      return baos.toString();
    } catch (Exception e) {
      throw new OsrsException("Error creating envelope from request", e);
    }
  } 
 

  private DtAssoc processAttrs(Map<String, Object> attrs) {
    DtAssoc dt = oj.createDtAssoc();
    for (Iterator<String> iter = attrs.keySet().iterator(); iter.hasNext();) {
      String key = (String) iter.next();
      if (attrs.get(key) instanceof String) {
        Item one = oj.createItem();
        one.setKey(key);
        one.setStringValue((String)attrs.get(key));
        dt.addItem(one);
      }
    }
    return dt;
  }
}
TOP

Related Classes of com.dgwave.osrs.OsrsClient

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.