/* * JacORB - a free Java ORB * * Copyright (C) 1999-2014 Gerald Brose / The JacORB Team. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ package org.jacorb.orb.etf; import java.util.ArrayList; import java.util.List; import org.jacorb.config.Configurable; import org.jacorb.config.Configuration; import org.jacorb.config.ConfigurationException; import org.jacorb.orb.ORB; import org.omg.CORBA.NO_RESOURCES; import org.omg.ETF.Connection; import org.omg.ETF.Handle; import org.omg.ETF.Profile; import org.omg.ETF._ListenerLocalBase; import org.slf4j.Logger; /** * @author Andre Spiegel */ public abstract class ListenerBase extends _ListenerLocalBase implements Configurable { /** * The ORB. */ protected ORB orb = null; /** * The profile of this listener's endpoint. */ protected Profile profile = null; /** * The primary acceptor of this listener. */ protected Acceptor acceptor = null; /** * The configuration. */ protected org.jacorb.config.Configuration configuration = null; /** * The logger. */ protected Logger logger = null; /** * Reference to the ORB, for delivering * incoming connections via upcalls. */ protected org.omg.ETF.Handle up = null; /** * Queue of incoming connections, which will be * delivered via calls to the accept() method. * Connections will only be put into this list * if no Handle has been set. */ protected final List<Connection> incoming_connections = new ArrayList<Connection>(); private boolean terminated = false; protected ListenEndpoint listenEndpoint = null; public ListenerBase() { super(); } public ListenerBase(ListenEndpoint listenEndpoint) { super(); this.setListenEndpoint(listenEndpoint); } public void configure(Configuration config) throws ConfigurationException { configuration = config; orb = configuration.getORB(); logger = configuration.getLogger(getClass().getName()); } /** * This call establishes the link between the ORB (i.e. the Handle * instance) and a server endpoint of the plugged-in transport. * All calls upwards into the ORB shall use the given instance. */ public void set_handle(Handle up) { this.up = up; } /** * It is possible that connection requests arrive <i>after</i> the * initial creation of the Listener instance but <i>before</i> the * conclusion of the configuration of the specific endpoint in this * plugin. In order to provide a clear end of this configuration state, * we added the listen() method. It is called by the ORB when it ready * for incoming connection and thus signals the Listener instance to * start processing the incoming connection requests. Therefore, * a Listener instance shall not deliver incoming connections to the * ORB before this method was called. */ public void listen() { if (acceptor != null) { acceptor.start(); } } /** * Method the Acceptor implementation should call to pass * an opened connection to the ORB. */ protected void deliverConnection(Connection connection) { if (up != null) { if(!up.add_input(connection)) { connection.close(); throw new NO_RESOURCES("Maximum number of server connections reached"); } } else { synchronized (incoming_connections) { incoming_connections.add(connection); incoming_connections.notifyAll(); } } } /** * This call is an alternative to using set_handle() to initiate the * callback-style of accepting new connections. This call blocks until * a client connects to the server. Then a new Connection instance is * returned. The transport plug-in must ensure that a thread blocked * in accept() returns when destroy() is called with a null object * reference. The transport plug-in must raise the CORBA::BAD_INV_ORDER * with minor code {TBD} if the ORB calls this operation and set_handle() * has ever been called previously on the same listener instance. */ public Connection accept() { if (up != null) { throw new org.omg.CORBA.BAD_INV_ORDER ("Must not call accept() when a Handle has been set"); } synchronized (incoming_connections) { while (!terminated && incoming_connections.isEmpty()) { try { incoming_connections.wait(); } catch (InterruptedException ex) { // ignore } } if (!terminated) { return incoming_connections.remove (0); } return null; } } /** * The connection instance is returned to the Listener. It now shall * signal any incoming data to the Handle. */ public void completed_data (Connection conn) { throw new org.omg.CORBA.NO_IMPLEMENT(); } /** * The Listener is instructed to close its endpoint. It shall no * longer accept any connection requests and shall close all * connections opened by it. */ public void destroy() { if (acceptor != null) { acceptor.terminate(); } synchronized (incoming_connections) { terminated = true; if (up == null) { incoming_connections.notifyAll(); } } } /** * Returns a copy of the profile describing the endpoint * of this instance. */ public Profile endpoint() { return profile.copy(); } protected abstract class Acceptor extends Thread { protected abstract void init(); public abstract void run(); public abstract void terminate(); } /** * Assigns a listen end point to this listener * @param listenEndpoint */ public void setListenEndpoint (ListenEndpoint listenEndpoint) { this.listenEndpoint = listenEndpoint; } }