/*--- formatted by Jindent 2.1, (www.c-lab.de/~jindent) ---*/ /** * *************************************************************** * The LEAP libraries, when combined with certain JADE platform components, * provide a run-time environment for enabling FIPA agents to execute on * lightweight devices running Java. LEAP and JADE teams have jointly * designed the API for ease of integration and hence to take advantage * of these dual developments and extensions so that users only see * one development platform and a * single homogeneous set of APIs. Enabling deployment to a wide range of * devices whilst still having access to the full development * environment and functionalities that JADE provides. * Copyright (C) 2001 Telecom Italia LAB S.p.A. * Copyright (C) 2001 Broadcom Eireann Research. * Copyright (C) 2001 Motorola. * * GNU Lesser General Public License * * This library is free software; you can redistribute it and/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. * ************************************************************** */ package jade.imtp.leap.JICP; //#MIDP_EXCLUDE_FILE import jade.core.Profile; import jade.mtp.TransportAddress; import jade.imtp.leap.*; import java.io.*; import java.net.*; /** * Class declaration * @author Giovanni Caire - TILAB * @author Jamie Lawrence - Broadcom Eireann Research * @author Ronnie Taib - Motorola * @author Nicolas Lhuillier - Motorola */ public class JICPPeer implements ICP, ProtocolManager { private static final int POOL_SIZE = 50; private JICPClient client; private JICPServer server; private Ticker ticker; private String myID; private int connectionTimeout = 0; public static final String CONNECTION_TIMEOUT = "jade_imtp_leap_JICP_JICPPeer_connectiontimeout"; /** * Start listening for internal platform messages on the specified port */ public TransportAddress activate(ICP.Listener l, String peerID, Profile p) throws ICPException { myID = peerID; connectionTimeout = Integer.parseInt(p.getParameter(CONNECTION_TIMEOUT, "0")); // Start the client client = new JICPClient(getProtocol(), getConnectionFactory(), POOL_SIZE); // Start the server listening for connections server = new JICPServer(p, this, l, getConnectionFactory(), POOL_SIZE); server.start(); // Start the Ticker ticker = new Ticker(60000); ticker.start(); // Creates the local transport address TransportAddress localTA = getProtocol().buildAddress(server.getLocalHost(), String.valueOf(server.getLocalPort()), null, null); return localTA; } /** * stop listening for internal platform messages */ public void deactivate() throws ICPException { if (server != null) { client.shutdown(); server.shutdown(); ticker.shutdown(); } else { throw new ICPException("No external listener was activated."); } } /** * deliver a serialized command to a given transport address */ public byte[] deliverCommand(TransportAddress ta, byte[] payload, boolean requireFreshConnection) throws ICPException { byte[] respPayload = client.send(ta, JICPProtocol.COMMAND_TYPE, payload, requireFreshConnection); return (respPayload); } final String getID() { return myID; } /** * Pings the specified transport address in order to obtain * the local hostname or IP address. * @param pingURL The <code>URL</code> to ping (usually the * main container). * @return The local IP address of the local container as a * <code>String</code>. * * @throws ICPException */ String getAddress(String pingURL) throws ICPException { byte[] respPayload = null; try { TransportAddress pingAddr = getProtocol().stringToAddr(pingURL); respPayload = client.send(pingAddr, JICPProtocol.GET_ADDRESS_TYPE, new byte[0], false); } catch (ICPException icpe) { throw new ICPException("JICP GET_ADDRESS error. Cannot retrieve local hostname: " +icpe.getMessage()); } return (new String(respPayload)); } /** Subclasses may re-define this method to return their own protocol */ public TransportProtocol getProtocol() { return JICPProtocol.getInstance(); } /** Subclasses may re-define this method to return their own ConnectionFactory */ public ConnectionFactory getConnectionFactory() { return new ConnectionFactory() { public Connection createConnection(Socket s) { return new JICPConnection(s); } public Connection createConnection(TransportAddress ta) throws IOException { JICPConnection con = new JICPConnection(ta, connectionTimeout); return con; } }; } protected ServerSocket getServerSocket(String host, int port, boolean changePortIfBusy) throws ICPException { try { return new ServerSocket(port, 50, (host != null ? InetAddress.getByName(host) : null)); } catch (SocketException be) { // HACK! We should do this only in case of a BindException. However some implementations // of the JVM (particularly that for Windows 7 64 bits) seem to have a bug and throw a // generic SocketException also in the case that the port is busy. if (changePortIfBusy) { // The specified port is busy. Let the system find a free one try { return new ServerSocket(0, 50, (host != null ? InetAddress.getByName(host) : null)); } catch (IOException ioe) { throw new ICPException("Cannot create server socket on a free port. ", ioe); } } else { throw new ICPException("Cannot bind server socket to "+(host != null ? "host "+host : "localhost")+ " port " + port); } } catch (IOException ioe2) { throw new ICPException("Cannot create server socket. ", ioe2); } } /** Inner class Ticker */ private class Ticker extends Thread { private long period; private boolean active = false; private Ticker(long period) { super(); this.period = period; } public void start() { active = true; super.start(); } public void run() { while (active) { try { Thread.sleep(period); long currentTime = System.currentTimeMillis(); client.tick(currentTime); server.tick(currentTime); } catch (InterruptedException ie) { } } } public void shutdown() { active = false; interrupt(); } } // END of inner class Ticker }