alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  
* <TR> * <TR> * <TR> * <TR> * </TABLE> * <p> * The <CODE>STARTING state marks the transition * from <CODE>OFFLINE to ONLINE. * <p> * The <CODE>STOPPING state marks the transition from * <CODE>ONLINE to OFFLINE. This occurs when the * <CODE>CommunicatorServer is finishing or interrupting active * requests. * <p> * When a <CODE>CommunicatorServer is unregistered from the MBeanServer, * it is stopped automatically. * <p> * When the value of the <CODE>State attribute changes the * <CODE>CommunicatorServer sends a * <tt>{@link javax.management.AttributeChangeNotification} to the * registered listeners, if any. * * <p>This API is a Sun Microsystems internal API and is subject * to change without notice.</b>

*/ public abstract class CommunicatorServer implements Runnable, MBeanRegistration, NotificationBroadcaster, CommunicatorServerMBean { // // States of a CommunicatorServer // /** * Represents an <CODE>ONLINE state. */ public static final int ONLINE = 0 ; /** * Represents an <CODE>OFFLINE state. */ public static final int OFFLINE = 1 ; /** * Represents a <CODE>STOPPING state. */ public static final int STOPPING = 2 ; /** * Represents a <CODE>STARTING state. */ public static final int STARTING = 3 ; // // Types of connectors. // /** * Indicates that it is an RMI connector type. */ //public static final int RMI_TYPE = 1 ; /** * Indicates that it is an HTTP connector type. */ //public static final int HTTP_TYPE = 2 ; /** * Indicates that it is an HTML connector type. */ //public static final int HTML_TYPE = 3 ; /** * Indicates that it is an SNMP connector type. */ public static final int SNMP_TYPE = 4 ; /** * Indicates that it is an HTTPS connector type. */ //public static final int HTTPS_TYPE = 5 ; // // Package variables // /** * The state of the connector server. */ transient volatile int state = OFFLINE ; /** * The object name of the connector server. * @serial */ ObjectName objectName ; MBeanServer topMBS; MBeanServer bottomMBS; /** */ transient String dbgTag = null ; /** * The maximum number of clients that the CommunicatorServer can * process concurrently. * @serial */ int maxActiveClientCount = 1 ; /** */ transient int servedClientCount = 0 ; /** * The host name used by this CommunicatorServer. * @serial */ String host = null ; /** * The port number used by this CommunicatorServer. * @serial */ int port = -1 ; // // Private fields // /* This object controls access to the "state" and "interrupted" variables. If held at the same time as the lock on "this", the "this" lock must be taken first. */ private transient Object stateLock = new Object(); private transient Vector<ClientHandler> clientHandlerVector = new Vector<>() ; private transient Thread mainThread = null ; private volatile boolean stopRequested = false ; private boolean interrupted = false; private transient Exception startException = null; // Notifs count, broadcaster and info private transient long notifCount = 0; private transient NotificationBroadcasterSupport notifBroadcaster = new NotificationBroadcasterSupport(); private transient MBeanNotificationInfo[] notifInfos = null; /** * Instantiates a <CODE>CommunicatorServer. * * @param connectorType Indicates the connector type. Possible values are: * SNMP_TYPE. * * @exception <CODE>java.lang.IllegalArgumentException * This connector type is not correct. */ public CommunicatorServer(int connectorType) throws IllegalArgumentException { switch (connectorType) { case SNMP_TYPE : //No op. int Type deciding debugging removed. break; default: throw new IllegalArgumentException("Invalid connector Type") ; } dbgTag = makeDebugTag() ; } protected Thread createMainThread() { return new Thread (this, makeThreadName()); } /** * Starts this <CODE>CommunicatorServer. * <p> * Has no effect if this <CODE>CommunicatorServer is * <CODE>ONLINE or STOPPING. * @param timeout Time in ms to wait for the connector to start. * If <code>timeout is positive, wait for at most * the specified time. An infinite timeout can be specified * by passing a <code>timeout value equals * <code>Long.MAX_VALUE. In that case the method * will wait until the connector starts or fails to start. * If timeout is negative or zero, returns as soon as possible * without waiting. * @exception CommunicationException if the connectors fails to start. * @exception InterruptedException if the thread is interrupted or the * timeout expires. */ public void start(long timeout) throws CommunicationException, InterruptedException { boolean start; synchronized (stateLock) { if (state == STOPPING) { // Fix for bug 4352451: // "java.net.BindException: Address in use". waitState(OFFLINE, 60000); } start = (state == OFFLINE); if (start) { changeState(STARTING); stopRequested = false; interrupted = false; startException = null; } } if (!start) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "start","Connector is not OFFLINE"); } return; } if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "start","--> Start connector "); } mainThread = createMainThread(); mainThread.start() ; if (timeout > 0) waitForStart(timeout); } /** * Starts this <CODE>CommunicatorServer. * <p> * Has no effect if this <CODE>CommunicatorServer is * <CODE>ONLINE or STOPPING. */ @Override public void start() { try { start(0); } catch (InterruptedException x) { // cannot happen because of `0' if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "start","interrupted", x); } } } /** * Stops this <CODE>CommunicatorServer. * <p> * Has no effect if this <CODE>CommunicatorServer is * <CODE>OFFLINE or STOPPING. */ @Override public void stop() { synchronized (stateLock) { if (state == OFFLINE || state == STOPPING) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "stop","Connector is not ONLINE"); } return; } changeState(STOPPING); // // Stop the connector thread // if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "stop","Interrupt main thread"); } stopRequested = true ; if (!interrupted) { interrupted = true; mainThread.interrupt(); } } // // Call terminate on each active client handler // if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "stop","terminateAllClient"); } terminateAllClient() ; // ---------------------- // changeState // ---------------------- synchronized (stateLock) { if (state == STARTING) changeState(OFFLINE); } } /** * Tests whether the <CODE>CommunicatorServer is active. * * @return True if connector is <CODE>ONLINE; false otherwise. */ @Override public boolean isActive() { synchronized (stateLock) { return (state == ONLINE); } } /** * <p>Waits until either the State attribute of this MBean equals the * specified <VAR>wantedState parameter, * or the specified <VAR>timeOut has elapsed. * The method <CODE>waitState returns with a boolean value * indicating whether the specified <VAR>wantedState parameter * equals the value of this MBean's State attribute at the time the method * terminates.</p> * * <p>Two special cases for the timeOut parameter value are:

* <UL>
  • if timeOut is negative then waitState * returns immediately (i.e. does not wait at all),</LI> * <LI> if timeOut equals zero then waitState * waits untill the value of this MBean's State attribute * is the same as the <VAR>wantedState parameter (i.e. will wait * indefinitely if this condition is never met).</LI> * * @param wantedState The value of this MBean's State attribute to wait * for. <VAR>wantedState can be one of: * <ul> * <li>CommunicatorServer.OFFLINE,
  • * <li>CommunicatorServer.ONLINE, * <li>CommunicatorServer.STARTING, * <li>CommunicatorServer.STOPPING. * </ul> * @param timeOut The maximum time to wait for, in milliseconds, * if positive. * Infinite time out if 0, or no waiting at all if negative. * * @return true if the value of this MBean's State attribute is the * same as the <VAR>wantedState parameter; false otherwise. */ @Override public boolean waitState(int wantedState, long timeOut) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "waitState", wantedState + "(0on,1off,2st) TO=" + timeOut + " ; current state = " + getStateString()); } long endTime = 0; if (timeOut > 0) endTime = System.currentTimeMillis() + timeOut; synchronized (stateLock) { while (state != wantedState) { if (timeOut < 0) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "waitState", "timeOut < 0, return without wait"); } return false; } else { try { if (timeOut > 0) { long toWait = endTime - System.currentTimeMillis(); if (toWait <= 0) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "waitState", "timed out"); } return false; } stateLock.wait(toWait); } else { // timeOut == 0 stateLock.wait(); } } catch (InterruptedException e) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "waitState", "wait interrupted"); } return (state == wantedState); } } } if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "waitState","returning in desired state"); } return true; } } /** * <p>Waits until the communicator is started or timeout expires. * * @param timeout Time in ms to wait for the connector to start. * If <code>timeout is positive, wait for at most * the specified time. An infinite timeout can be specified * by passing a <code>timeout value equals * <code>Long.MAX_VALUE. In that case the method * will wait until the connector starts or fails to start. * If timeout is negative or zero, returns as soon as possible * without waiting. * * @exception CommunicationException if the connectors fails to start. * @exception InterruptedException if the thread is interrupted or the * timeout expires. * */ private void waitForStart(long timeout) throws CommunicationException, InterruptedException { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "waitForStart", "Timeout=" + timeout + " ; current state = " + getStateString()); } final long startTime = System.currentTimeMillis(); synchronized (stateLock) { while (state == STARTING) { // Time elapsed since startTime... // final long elapsed = System.currentTimeMillis() - startTime; // wait for timeout - elapsed. // A timeout of Long.MAX_VALUE is equivalent to something // like 292271023 years - which is pretty close to // forever as far as we are concerned ;-) // final long remainingTime = timeout-elapsed; // If remainingTime is negative, the timeout has elapsed. // if (remainingTime < 0) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "waitForStart", "timeout < 0, return without wait"); } throw new InterruptedException("Timeout expired"); } // We're going to wait until someone notifies on the // the stateLock object, or until the timeout expires, // or until the thread is interrupted. // try { stateLock.wait(remainingTime); } catch (InterruptedException e) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "waitForStart", "wait interrupted"); } // If we are now ONLINE, then no need to rethrow the // exception... we're simply going to exit the while // loop. Otherwise, throw the InterruptedException. // if (state != ONLINE) throw e; } } // We're no longer in STARTING state // if (state == ONLINE) { // OK, we're started, everything went fine, just return // if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "waitForStart", "started"); } return; } else if (startException instanceof CommunicationException) { // There was some exception during the starting phase. // Cast and throw... // throw (CommunicationException)startException; } else if (startException instanceof InterruptedException) { // There was some exception during the starting phase. // Cast and throw... // throw (InterruptedException)startException; } else if (startException != null) { // There was some exception during the starting phase. // Wrap and throw... // throw new CommunicationException(startException, "Failed to start: "+ startException); } else { // We're not ONLINE, and there's no exception... // Something went wrong but we don't know what... // throw new CommunicationException("Failed to start: state is "+ getStringForState(state)); } } } /** * Gets the state of this <CODE>CommunicatorServer as an integer. * * @return <CODE>ONLINE, OFFLINE, * <CODE>STARTING or STOPPING. */ @Override public int getState() { synchronized (stateLock) { return state ; } } /** * Gets the state of this <CODE>CommunicatorServer as a string. * * @return One of the strings "ONLINE", "OFFLINE", "STARTING" or * "STOPPING". */ @Override public String getStateString() { return getStringForState(state) ; } /** * Gets the host name used by this <CODE>CommunicatorServer. * * @return The host name used by this <CODE>CommunicatorServer. */ @Override public String getHost() { try { host = InetAddress.getLocalHost().getHostName(); } catch (Exception e) { host = "Unknown host"; } return host ; } /** * Gets the port number used by this <CODE>CommunicatorServer. * * @return The port number used by this <CODE>CommunicatorServer. */ @Override public int getPort() { synchronized (stateLock) { return port ; } } /** * Sets the port number used by this <CODE>CommunicatorServer. * * @param port The port number used by this * <CODE>CommunicatorServer. * * @exception java.lang.IllegalStateException This method has been invoked * while the communicator was ONLINE or STARTING. */ @Override public void setPort(int port) throws java.lang.IllegalStateException { synchronized (stateLock) { if ((state == ONLINE) || (state == STARTING)) throw new IllegalStateException("Stop server before " + "carrying out this operation"); this.port = port; dbgTag = makeDebugTag(); } } /** * Gets the protocol being used by this <CODE>CommunicatorServer. * @return The protocol as a string. */ @Override public abstract String getProtocol(); /** * Gets the number of clients that have been processed by this * <CODE>CommunicatorServer since its creation. * * @return The number of clients handled by this * <CODE>CommunicatorServer * since its creation. This counter is not reset by the * <CODE>stop method. */ int getServedClientCount() { return servedClientCount ; } /** * Gets the number of clients currently being processed by this * <CODE>CommunicatorServer. * * @return The number of clients currently being processed by this * <CODE>CommunicatorServer. */ int getActiveClientCount() { int result = clientHandlerVector.size() ; return result ; } /** * Gets the maximum number of clients that this * <CODE>CommunicatorServer can process concurrently. * * @return The maximum number of clients that this * <CODE>CommunicatorServer can * process concurrently. */ int getMaxActiveClientCount() { return maxActiveClientCount ; } /** * Sets the maximum number of clients this * <CODE>CommunicatorServer can process concurrently. * * @param c The number of clients. * * @exception java.lang.IllegalStateException This method has been invoked * while the communicator was ONLINE or STARTING. */ void setMaxActiveClientCount(int c) throws java.lang.IllegalStateException { synchronized (stateLock) { if ((state == ONLINE) || (state == STARTING)) { throw new IllegalStateException( "Stop server before carrying out this operation"); } maxActiveClientCount = c ; } } /** * For SNMP Runtime internal use only. */ void notifyClientHandlerCreated(ClientHandler h) { clientHandlerVector.addElement(h) ; } /** * For SNMP Runtime internal use only. */ synchronized void notifyClientHandlerDeleted(ClientHandler h) { clientHandlerVector.removeElement(h); notifyAll(); } /** * The number of times the communicator server will attempt * to bind before giving up. **/ protected int getBindTries() { return 50; } /** * The delay, in ms, during which the communicator server will sleep before * attempting to bind again. **/ protected long getBindSleepTime() { return 100; } /** * For SNMP Runtime internal use only. * <p> * The <CODE>run method executed by this connector's main thread. */ @Override public void run() { // Fix jaw.00667.B // It seems that the init of "i" and "success" // need to be done outside the "try" clause... // A bug in Java 2 production release ? // int i = 0; boolean success = false; // ---------------------- // Bind // ---------------------- try { // Fix for bug 4352451: "java.net.BindException: Address in use". // final int bindRetries = getBindTries(); final long sleepTime = getBindSleepTime(); while (i < bindRetries && !success) { try { // Try socket connection. // doBind(); success = true; } catch (CommunicationException ce) { i++; try { Thread.sleep(sleepTime); } catch (InterruptedException ie) { throw ie; } } } // Retry last time to get correct exception. // if (!success) { // Try socket connection. // doBind(); } } catch(Exception x) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "run", "Got unexpected exception", x); } synchronized(stateLock) { startException = x; changeState(OFFLINE); } if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "run","State is OFFLINE"); } doError(x); return; } try { // ---------------------- // State change // ---------------------- changeState(ONLINE) ; if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "run","State is ONLINE"); } // ---------------------- // Main loop // ---------------------- while (!stopRequested) { servedClientCount++; doReceive() ; waitIfTooManyClients() ; doProcess() ; } if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "run","Stop has been requested"); } } catch(InterruptedException x) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "run","Interrupt caught"); } changeState(STOPPING); } catch(Exception x) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "run","Got unexpected exception", x); } changeState(STOPPING); } finally { synchronized (stateLock) { interrupted = true; Thread.interrupted(); } // ---------------------- // unBind // ---------------------- try { doUnbind() ; waitClientTermination() ; changeState(OFFLINE); if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "run","State is OFFLINE"); } } catch(Exception x) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "run","Got unexpected exception", x); } changeState(OFFLINE); } } } /** */ protected abstract void doError(Exception e) throws CommunicationException; // // To be defined by the subclass. // // Each method below is called by run() and must be subclassed. // If the method sends an exception (Communication or Interrupt), this // will end up the run() method and switch the connector offline. // // If it is a CommunicationException, run() will call // Debug.printException(). // // All these methods should propagate the InterruptedException to inform // run() that the connector must be switch OFFLINE. // // // // doBind() should do all what is needed before calling doReceive(). // If doBind() throws an exception, doUnbind() is not to be called // and run() ends up. // /** */ protected abstract void doBind() throws CommunicationException, InterruptedException ; /** * <CODE>doReceive() should block until a client is available. * If this method throws an exception, <CODE>doProcess() is not * called but <CODE>doUnbind() is called then run() * stops. */ protected abstract void doReceive() throws CommunicationException, InterruptedException ; /** * <CODE>doProcess() is called after doReceive(): * it should process the requests of the incoming client. * If it throws an exception, <CODE>doUnbind() is called and * <CODE>run() stops. */ protected abstract void doProcess() throws CommunicationException, InterruptedException ; /** * <CODE>doUnbind() is called whenever the connector goes * <CODE>OFFLINE, except if doBind() has thrown an * exception. */ protected abstract void doUnbind() throws CommunicationException, InterruptedException ; /** * Get the <code>MBeanServer object to which incoming requests are * sent. This is either the MBean server in which this connector is * registered, or an <code>MBeanServerForwarder leading to that * server. */ public synchronized MBeanServer getMBeanServer() { return topMBS; } /** * Set the <code>MBeanServer object to which incoming * requests are sent. This must be either the MBean server in * which this connector is registered, or an * <code>MBeanServerForwarder leading to that server. An * <code>MBeanServerForwarder mbsf leads to an * MBean server <code>mbs if * <code>mbsf.getMBeanServer() is either mbs * or an <code>MBeanServerForwarder leading to * <code>mbs. * * @exception IllegalArgumentException if <code>newMBS is neither * the MBean server in which this connector is registered nor an * <code>MBeanServerForwarder leading to that server. * * @exception IllegalStateException This method has been invoked * while the communicator was ONLINE or STARTING. */ public synchronized void setMBeanServer(MBeanServer newMBS) throws IllegalArgumentException, IllegalStateException { synchronized (stateLock) { if (state == ONLINE || state == STARTING) throw new IllegalStateException("Stop server before " + "carrying out this operation"); } final String error = "MBeanServer argument must be MBean server where this " + "server is registered, or an MBeanServerForwarder " + "leading to that server"; Vector<MBeanServer> seenMBS = new Vector<>(); for (MBeanServer mbs = newMBS; mbs != bottomMBS; mbs = ((MBeanServerForwarder) mbs).getMBeanServer()) { if (!(mbs instanceof MBeanServerForwarder)) throw new IllegalArgumentException(error); if (seenMBS.contains(mbs)) throw new IllegalArgumentException("MBeanServerForwarder " + "loop"); seenMBS.addElement(mbs); } topMBS = newMBS; } // // To be called by the subclass if needed // /** * For internal use only. */ ObjectName getObjectName() { return objectName ; } /** * For internal use only. */ void changeState(int newState) { int oldState; synchronized (stateLock) { if (state == newState) return; oldState = state; state = newState; stateLock.notifyAll(); } sendStateChangeNotification(oldState, newState); } /** * Returns the string used in debug traces. */ String makeDebugTag() { return "CommunicatorServer["+ getProtocol() + ":" + getPort() + "]" ; } /** * Returns the string used to name the connector thread. */ String makeThreadName() { String result ; if (objectName == null) result = "CommunicatorServer" ; else result = objectName.toString() ; return result ; } /** * This method blocks if there are too many active clients. * Call to <CODE>wait() is terminated when a client handler * thread calls <CODE>notifyClientHandlerDeleted(this) ; */ private synchronized void waitIfTooManyClients() throws InterruptedException { while (getActiveClientCount() >= maxActiveClientCount) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "waitIfTooManyClients","Waiting for a client to terminate"); } wait(); } } /** * This method blocks until there is no more active client. */ private void waitClientTermination() { int s = clientHandlerVector.size() ; if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { if (s >= 1) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "waitClientTermination","waiting for " + s + " clients to terminate"); } } // The ClientHandler will remove themselves from the // clientHandlerVector at the end of their run() method, by // calling notifyClientHandlerDeleted(). // Since the clientHandlerVector is modified by the ClientHandler // threads we must avoid using Enumeration or Iterator to loop // over this array. We must also take care of NoSuchElementException // which could be thrown if the last ClientHandler removes itself // between the call to clientHandlerVector.isEmpty() and the call // to clientHandlerVector.firstElement(). // What we *MUST NOT DO* is locking the clientHandlerVector, because // this would most probably cause a deadlock. // while (! clientHandlerVector.isEmpty()) { try { clientHandlerVector.firstElement().join(); } catch (NoSuchElementException x) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "waitClientTermination","No elements left", x); } } } if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { if (s >= 1) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "waitClientTermination","Ok, let's go..."); } } } /** * Call <CODE>interrupt() on each pending client. */ private void terminateAllClient() { final int s = clientHandlerVector.size() ; if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { if (s >= 1) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "terminateAllClient","Interrupting " + s + " clients"); } } // The ClientHandler will remove themselves from the // clientHandlerVector at the end of their run() method, by // calling notifyClientHandlerDeleted(). // Since the clientHandlerVector is modified by the ClientHandler // threads we must avoid using Enumeration or Iterator to loop // over this array. // We cannot use the same logic here than in waitClientTermination() // because there is no guarantee that calling interrupt() on the // ClientHandler will actually terminate the ClientHandler. // Since we do not want to wait for the actual ClientHandler // termination, we cannot simply loop over the array until it is // empty (this might result in calling interrupt() endlessly on // the same client handler. So what we do is simply take a snapshot // copy of the vector and loop over the copy. // What we *MUST NOT DO* is locking the clientHandlerVector, because // this would most probably cause a deadlock. // final ClientHandler[] handlers = clientHandlerVector.toArray(new ClientHandler[0]); for (ClientHandler h : handlers) { try { h.interrupt() ; } catch (Exception x) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "terminateAllClient", "Failed to interrupt pending request. " + "Ignore the exception.", x); } } } } /** * Controls the way the CommunicatorServer service is deserialized. */ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { // Call the default deserialization of the object. // stream.defaultReadObject(); // Call the specific initialization for the CommunicatorServer service. // This is for transient structures to be initialized to specific // default values. // stateLock = new Object(); state = OFFLINE; stopRequested = false; servedClientCount = 0; clientHandlerVector = new Vector<>(); mainThread = null; notifCount = 0; notifInfos = null; notifBroadcaster = new NotificationBroadcasterSupport(); dbgTag = makeDebugTag(); } // // NotificationBroadcaster // /** * Adds a listener for the notifications emitted by this * CommunicatorServer. * There is only one type of notifications sent by the CommunicatorServer: * they are <tt>{@link javax.management.AttributeChangeNotification}, * sent when the <tt>State attribute of this CommunicatorServer * changes. * * @param listener The listener object which will handle the emitted * notifications. * @param filter The filter object. If filter is null, no filtering * will be performed before handling notifications. * @param handback An object which will be sent back unchanged to the * listener when a notification is emitted. * * @exception IllegalArgumentException Listener parameter is null. */ @Override public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws java.lang.IllegalArgumentException { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "addNotificationListener","Adding listener "+ listener + " with filter "+ filter + " and handback "+ handback); } notifBroadcaster.addNotificationListener(listener, filter, handback); } /** * Removes the specified listener from this CommunicatorServer. * Note that if the listener has been registered with different * handback objects or notification filters, all entries corresponding * to the listener will be removed. * * @param listener The listener object to be removed. * * @exception ListenerNotFoundException The listener is not registered. */ @Override public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "removeNotificationListener","Removing listener "+ listener); } notifBroadcaster.removeNotificationListener(listener); } /** * Returns an array of MBeanNotificationInfo objects describing * the notification types sent by this CommunicatorServer. * There is only one type of notifications sent by the CommunicatorServer: * it is <tt>{@link javax.management.AttributeChangeNotification}, * sent when the <tt>State attribute of this CommunicatorServer * changes. */ @Override public MBeanNotificationInfo[] getNotificationInfo() { // Initialize notifInfos on first call to getNotificationInfo() // if (notifInfos == null) { notifInfos = new MBeanNotificationInfo[1]; String[] notifTypes = { AttributeChangeNotification.ATTRIBUTE_CHANGE}; notifInfos[0] = new MBeanNotificationInfo( notifTypes, AttributeChangeNotification.class.getName(), "Sent to notify that the value of the State attribute "+ "of this CommunicatorServer instance has changed."); } return notifInfos.clone(); } /** * */ private void sendStateChangeNotification(int oldState, int newState) { String oldStateString = getStringForState(oldState); String newStateString = getStringForState(newState); String message = new StringBuffer().append(dbgTag) .append(" The value of attribute State has changed from ") .append(oldState).append(" (").append(oldStateString) .append(") to ").append(newState).append(" (") .append(newStateString).append(").").toString(); notifCount++; AttributeChangeNotification notif = new AttributeChangeNotification(this, // source notifCount, // sequence number System.currentTimeMillis(), // time stamp message, // message "State", // attribute name "int", // attribute type new Integer(oldState), // old value new Integer(newState) ); // new value if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "sendStateChangeNotification","Sending AttributeChangeNotification #" + notifCount + " with message: "+ message); } notifBroadcaster.sendNotification(notif); } /** * */ private static String getStringForState(int s) { switch (s) { case ONLINE: return "ONLINE"; case STARTING: return "STARTING"; case OFFLINE: return "OFFLINE"; case STOPPING: return "STOPPING"; default: return "UNDEFINED"; } } // // MBeanRegistration // /** * Preregister method of connector. * *@param server The <CODE>MBeanServer in which the MBean will * be registered. *@param name The object name of the MBean. * *@return The name of the MBean registered. * *@exception java.langException This exception should be caught by * the <CODE>MBeanServer and re-thrown * as an <CODE>MBeanRegistrationException. */ @Override public ObjectName preRegister(MBeanServer server, ObjectName name) throws java.lang.Exception { objectName = name; synchronized (this) { if (bottomMBS != null) { throw new IllegalArgumentException("connector already " + "registered in an MBean " + "server"); } topMBS = bottomMBS = server; } dbgTag = makeDebugTag(); return name; } /** * *@param registrationDone Indicates whether or not the MBean has been * successfully registered in the <CODE>MBeanServer. * The value false means that the registration phase has failed. */ @Override public void postRegister(Boolean registrationDone) { if (!registrationDone.booleanValue()) { synchronized (this) { topMBS = bottomMBS = null; } } } /** * Stop the connector. * * @exception java.langException This exception should be caught by * the <CODE>MBeanServer and re-thrown * as an <CODE>MBeanRegistrationException. */ @Override public void preDeregister() throws java.lang.Exception { synchronized (this) { topMBS = bottomMBS = null; } objectName = null ; final int cstate = getState(); if ((cstate == ONLINE) || ( cstate == STARTING)) { stop() ; } } /** * Do nothing. */ @Override public void postDeregister(){ } }

    Other Java examples (source code examples)

    Here is a short list of links related to this Java CommunicatorServer.java source code file:

    Java example source code file (CommunicatorServer.java)

    This example Java source code file (CommunicatorServer.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

    Learn more about this Java project at its project page.

    Java - Java tags/keywords

    communicationexception, communicatorserver, illegalargumentexception, interruptedexception, log, logging, management, mbeanserver, net, network, object, offline, online, override, starting, state, stopping, string, util, vector

    The CommunicatorServer.java Java example source code

    /*
     * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     *
     * This code is free software; you can redistribute it and/or modify it
     * under the terms of the GNU General Public License version 2 only, as
     * published by the Free Software Foundation.  Oracle designates this
     * particular file as subject to the "Classpath" exception as provided
     * by Oracle in the LICENSE file that accompanied this code.
     *
     * This code 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 General Public License
     * version 2 for more details (a copy is included in the LICENSE file that
     * accompanied this code).
     *
     * You should have received a copy of the GNU General Public License version
     * 2 along with this work; if not, write to the Free Software Foundation,
     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     *
     * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     * or visit www.oracle.com if you need additional information or have any
     * questions.
     */
    
    
    package com.sun.jmx.snmp.daemon;
    
    
    
    // java import
    //
    import java.io.ObjectInputStream;
    import java.io.IOException;
    import java.net.InetAddress;
    import java.util.logging.Level;
    import java.util.Vector;
    import java.util.NoSuchElementException;
    
    // jmx import
    //
    import javax.management.MBeanServer;
    import javax.management.MBeanRegistration;
    import javax.management.ObjectName;
    import javax.management.NotificationListener;
    import javax.management.NotificationFilter;
    import javax.management.NotificationBroadcaster;
    import javax.management.NotificationBroadcasterSupport;
    import javax.management.MBeanNotificationInfo;
    import javax.management.AttributeChangeNotification;
    import javax.management.ListenerNotFoundException;
    
    import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER;
    
    // JSR 160 import
    //
    // XXX Revisit:
    //   used to import com.sun.jmx.snmp.MBeanServerForwarder
    // Now using JSR 160 instead. => this is an additional
    // dependency to JSR 160.
    //
    import javax.management.remote.MBeanServerForwarder;
    
    /**
     * Defines generic behavior for the server part of a connector or an adaptor.
     * Most connectors or adaptors extend <CODE>CommunicatorServer
     * and inherit this behavior. Connectors or adaptors that do not fit into
     * this model do not extend <CODE>CommunicatorServer.
     * <p>
     * A <CODE>CommunicatorServer is an active object, it listens for
     * client requests  and processes them in its own thread. When necessary, a
     * <CODE>CommunicatorServer creates other threads to process multiple
     * requests concurrently.
     * <p>
     * A <CODE>CommunicatorServer object can be stopped by calling the
     * <CODE>stop method. When it is stopped, the
     * <CODE>CommunicatorServer no longer listens to client requests and
     * no longer holds any thread or communication resources.
     * It can be started again by calling the <CODE>start method.
     * <p>
     * A <CODE>CommunicatorServer has a State attribute
     * which reflects its  activity.
     * <p>
     * <TABLE>
     * <TR>
    CommunicatorServer State
    stopped OFFLINE
    starting STARTING
    running ONLINE
    stopping STOPPING
    ... this post is sponsored by my books ...

    #1 New Release!

    FP Best Seller

     

    new blog posts

     

    Copyright 1998-2021 Alvin Alexander, alvinalexander.com
    All Rights Reserved.

    A percentage of advertising revenue from
    pages under the /java/jwarehouse URI on this website is
    paid back to open source projects.