package org.jfox.ejb.invoker.soap;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.Vector;
import java.net.HttpURLConnection;
import java.net.URL;

import org.apache.xmlrpc.XmlRpcClientLite;
import org.apache.xmlrpc.XmlRpcHandler;
import org.jfox.ejb.Invocation;
import org.jfox.ejb.invoker.ContainerRemote;

/**
 * 这个对象被SOAPContaineService绑定jndi上,然后被客户端lookup到之后用来执行 soap 调用
 * 注意:这是一个 Serializable 对象,并不是一个 Remote 对象
 * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
 */

public class SOAPContainerServiceBinder implements ContainerRemote, Serializable {
  private transient XmlRpcHandler client;
  private String soapURL;

  public SOAPContainerServiceBinder(String soapUrl) {
    this.soapURL = soapUrl;
    try {
      client = new XmlRpcClientLite(soapUrl);
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

  public Object invoke(Invocation invocation) throws RemoteException {
    Vector params = new Vector(1);
    params.add(marshelledObject(invocation));
    try {
      // handler 可以为任何字符串
      return client.execute("xmlrpc", params);
    }
    catch (Exception e) {
      throw new RemoteException(e.getMessage(), e);
    }

  }

  // lookup 之后,重新初始化 XmlRpcClient
  private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
    in.defaultReadObject();
    client = new XmlRpcClientLite(soapURL);
  }

  public void ping() throws RemoteException {
    HttpURLConnection conn = null;
    try {
       conn = (HttpURLConnection)new URL(soapURL).openConnection();
    }
    catch(Exception e){
      throw new RemoteException("can't get connection with the soap url: "+ soapURL, e);
    }
    finally {
      if(conn != null) {
        try{
          conn.disconnect();
        }
        catch(Exception e){}
      }
    }
//    System.out.println("SOAPContainerServiceBinder: I'm alive :)   " + new Date());
  }

  public static byte[] marshelledObject(Serializable obj) {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    try {
      ObjectOutputStream oos = new ObjectOutputStream(out);
      oos.writeObject(obj);
      oos.flush();
    }
    catch (IOException e) {
      e.printStackTrace();
    }
    return out.toByteArray();
  }

  public static void main(String[] args) {

  }
}