Package jade.mtp.http

Source Code of jade.mtp.http.KeepAlive$KAConnection

/*****************************************************************
* JADE - Java Agent DEvelopment Framework is a framework to develop
* multi-agent systems in compliance with the FIPA specifications.
* Copyright (C) 2000 CSELT S.p.A.
*
* The updating of this file to JADE 2.0 has been partially supported by the
* IST-1999-10211 LEAP Project
*
* This file refers to parts of the FIPA 99/00 Agent Message Transport
* Implementation Copyright (C) 2000, Laboratoire d'Intelligence
* Artificielle, Ecole Polytechnique Federale de Lausanne
*
* GNU Lesser General Public License
*
* This library is free software; you can redistribute it sand/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation,
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA  02111-1307, USA.
*****************************************************************/

/**
* KeepAlive.java
*
* @author Jose Antonio Exposito
* @author MARISM-A Development group ( marisma-info@ccd.uab.es )
* @version 0.1
* @author Nicolas Lhuillier (Motorola Labs)
* @version 1.0
*/


package jade.mtp.http;

import jade.mtp.MTPException;
import jade.util.leap.HashMap;
import jade.util.Logger;

import java.io.*;
import java.util.Vector;
import java.net.Socket;
import java.net.InetAddress;
import java.net.UnknownHostException;


/**
* This class represents a connection to a remote server
*/
public class KeepAlive {
 
  private static Logger logger = Logger.getMyLogger(KeepAlive.class.getName());
 
  /*
   * Inner structure to contain all connection information
   */
  public static class KAConnection {
    private OutputStream   out;
    private InputStream    in;
    private HTTPAddress    address;
    private Vector         connections;
    private int outPort;
   
    KAConnection(HTTPAddress a, int outPort) {
      address = a;
      this.outPort = outPort;
    }
   
    public void open() throws IOException {
      // The address is new or the KA connection was closed
      //HTTPAddress is new or cached missed;
      // Open a new connection
      Socket client;
      //#PJAVA_EXCLUDE_BEGIN
      HTTPSocketFactory sfac = HTTPSocketFactory.getInstance();
      if (outPort > 0) {
        client = sfac.createSocket(address.getHost(),address.getPortNo(),InetAddress.getLocalHost(),outPort);
      } else {
        client = sfac.createSocket(address.getHost(),address.getPortNo());
      }
     
      //#PJAVA_EXCLUDE_END
      /*#PJAVA_INCLUDE_BEGIN
      if (outPort > 0)
      {
        client = new Socket(address.getHost(),address.getPortNo(),InetAddress.getLocalHost(),outPort);
      }
      else {
        client = new Socket(address.getHost(),address.getPortNo());
      }
      #PJAVA_INCLUDE_END*/
      out = new BufferedOutputStream(client.getOutputStream());
      in = new BufferedInputStream(client.getInputStream());
    }
   
    OutputStream getOut() {
      return out;
    }
   
    InputStream getIn() {
      return in;
    }
   
    public HTTPAddress getAddress() {
      return address;
    }
   
    public boolean equals(HTTPAddress a) {
      return address.equals(a);
    }
   
   
    void close() {
      if (isOpen()) {
        try {
          in.close();
          out.close();
        } catch(IOException ioe) {
          if(logger.isLoggable(Logger.WARNING))
            logger.log(Logger.WARNING,"Exception while closing KA connection: "+ioe);
        }
        in = null;
        out = null;
      }
    }
   
    boolean isOpen() {
      return in != null;
    }
   
    void send(byte[] req) throws MTPException {
      try {
        if(logger.isLoggable(Logger.FINER))
          logger.log(Logger.FINER,"Sending HTTP message to: "+ address);
        HTTPIO.writeAll(out,req);
        //Capture the HTTPresponse
        StringBuffer typeConnection = new StringBuffer();
        int code = HTTPIO.getResponseCode(in, typeConnection);
        if (!HTTPIO.KA.equals(typeConnection.toString())) {
          // Close the connection
          if(logger.isLoggable(Logger.FINER))
            logger.log(Logger.FINER,"Closing " + typeConnection +" connection to " + address);
          close();
        }
        if (code != 200) {
          if(logger.isLoggable(Logger.FINER))
            logger.log(Logger.FINER,"Not OK: " + code +", Closing connection to " + address);
          close();
          throw new MTPException("Description: ResponseMessage is not OK");
        }
      } catch (IOException e) {
        close();
        throw new MTPException(e.getMessage(), e);
      }
    }
   
   
   
  } // End of KAConnection inner class
 
  private final Vector   connections;
  private final int      dim;
  private final int      outPort;
  private final boolean  agressive;
  private final HashMap locks = new HashMap();
 
  /** Constructor */
  public KeepAlive(int dim, int outPort, boolean agressive) {
    connections = new Vector(dim);
    this.dim = dim;
    this.outPort = outPort;
    this.agressive = agressive;
  }
 
  /** add a new connection */
  public synchronized void add(KAConnection c) {
    try {
      //The vectors are full.
      if (connections.size() == dim) {
        remove(0); //Remove the first element of vectors, is the older element
      }
      connections.addElement(c);
      //System.out.println("DEBUG: Added Ka conn: "+connections.size()+"/"+dim+" with "+c.getAddress().getPortNo());
    } catch(Exception ioe) {
      if(logger.isLoggable(Logger.WARNING))
        logger.log(Logger.WARNING,ioe.getMessage());
    }
  }
 
  /** delete an exisiting connection, based on position */
  private void remove(int pos) {
    try {
      KAConnection old = getConnection(pos);
      connections.removeElementAt(pos);
      old.close();
    } catch(Exception ioe) {
      if(logger.isLoggable(Logger.WARNING))
        logger.log(Logger.WARNING,ioe.getMessage());
    }
  }
 
  /** delete an exisiting connection, based on its address */
  public synchronized void remove(HTTPAddress addr) {
    connections.removeElement(search(addr));
  }
 
  /** delete an exisiting connection*/
  public synchronized void remove(KAConnection ka) {
    connections.removeElement(ka);
  }
 
 
 
  /** get the socket of the connection when addr make matching */
  private KAConnection getConnection(int pos) {
    return (KAConnection)connections.elementAt(pos);
  }
 
  private KAConnection search(HTTPAddress addr) {
    if (addr != null) {
      KAConnection c;
      for(int i=(connections.size()-1); i >= 0; i--) {
        if ((c=(KAConnection)getConnection(i)).equals(addr)) {
          return c;
        }
      }
    }
    return null;
  }
 
  /** get the socket of the connection when addr make matching */
  public KAConnection getConnection(HTTPAddress addr) {
    return search(addr);
  }
 
  private KAConnection createConnection(final HTTPAddress url) throws MTPException {
    KeepAlive.KAConnection kac = null;
    try {
      kac = new KAConnection(url, outPort);
      kac.open();
      return kac;
    } catch (IOException e) {
      //Remove the inputs of KA object for the current address
      if (kac != null) {
        kac.close();
      }
      throw new MTPException(e.getMessage(), e);
    }
  }
 
  /** get the dimension of Vectors */
  public  int getDim(){
    return dim;
  }
 
  /** get the capacity of Vectors */
  public int capacity() {
    //System.out.println("DIMENSION: "+dim+"  "+"TAMVECT: "+addresses.size());
    return (dim - connections.size());
  }
 
  public synchronized void swap(KAConnection c) {
    try {
      //if only have 1 socket isn't necessary make swap function
      if ((dim > 1)&&(!(connections.indexOf(c)==(connections.size()-1)))) {
        //remove the elements at former position
        connections.removeElement(c);
        //put the elements at the end
        connections.addElement(c);
      }
    } catch(Exception ioe) {
      if(logger.isLoggable(Logger.WARNING))
        logger.log(Logger.WARNING,ioe.getMessage());
    }
  }
 
 
  public void send(HTTPAddress url, byte[] request) throws MTPException {
    Object lock = getLock(url);
    synchronized(lock) {
      KeepAlive.KAConnection kac = null;
      // Try to re-use an existing socket
      if (dim > 0) {
        //Search the address in Keep-Alive object
        kac = getConnection(url);
        if (kac != null) {
          try {
            if(logger.isLoggable(Logger.FINER))
              logger.log(Logger.FINER,"Reusing keepAlive for " + url);
            kac.send(request);
            if (kac.isOpen()) {
              //change the priority of socket & another components of keep-alive object
              //Only the policy == AGGRESSIVE
              //HTTPAddress is cached;
              if (agressive) {
                swap(kac);
              }
            } else {
              if(logger.isLoggable(Logger.FINER))
                logger.log(Logger.FINER,"Removing keepAlive for " + url);
              remove(kac);
            }
          } catch (MTPException e) {
            if(logger.isLoggable(Logger.FINER))
              logger.log(Logger.FINER,"Removing keepAlive for " + url);
            remove(kac);
            // retry with new connection
            kac = null;
          }
        }
      }
      if (kac == null) {
        if(logger.isLoggable(Logger.FINER))
          logger.log(Logger.FINER,"Creating connection to " + url);
        kac = createConnection(url);
        // Send out and check response code
        kac.send(request);
        if (kac.isOpen()) {
          if (dim > 0) {
            // Store the new connection
            if(logger.isLoggable(Logger.FINER))
              logger.log(Logger.FINER,"Adding keepAlive for " + url);
            add(kac);
          } else {
            if(logger.isLoggable(Logger.FINER))
              logger.log(Logger.FINER,"Closing open connection for " + url);
            kac.close();
          }
        }
      }
    }
  }
 
  private Object getLock(final HTTPAddress url) {
    Object lock = locks.get(url.getHost());
    if (lock == null) {
      synchronized(this) {
        lock = locks.get(url.getHost());
        if (lock == null) {
          lock = new Object();
          locks.put(url.getHost(), lock);
        }
      }
    }
    return lock;
  }
 
} //End of class KeepAlive
TOP

Related Classes of jade.mtp.http.KeepAlive$KAConnection

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.