| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
 | 
 | 
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</CODE>  | 
 | 
 * and inherit this behavior. Connectors or adaptors that do not fit into  | 
 | 
 * this model do not extend <CODE>CommunicatorServer</CODE>.  | 
 | 
 * <p>  | 
 | 
 * A <CODE>CommunicatorServer</CODE> is an active object, it listens for  | 
 | 
 * client requests  and processes them in its own thread. When necessary, a  | 
 | 
 * <CODE>CommunicatorServer</CODE> creates other threads to process multiple  | 
 | 
 * requests concurrently.  | 
 | 
 * <p>  | 
 | 
 * A <CODE>CommunicatorServer</CODE> object can be stopped by calling the  | 
 | 
 * <CODE>stop</CODE> method. When it is stopped, the  | 
 | 
 * <CODE>CommunicatorServer</CODE> 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</CODE> method.  | 
 | 
 * <p>  | 
 | 
 * A <CODE>CommunicatorServer</CODE> has a <CODE>State</CODE> attribute  | 
 | 
 * which reflects its  activity.  | 
 | 
 * <p>  | 
 | 
 * <TABLE>  | 
 | 
 * <TR><TH>CommunicatorServer</TH>      <TH>State</TH></TR>  | 
 | 
 * <TR><TD><CODE>stopped</CODE></TD>    <TD><CODE>OFFLINE</CODE></TD></TR>  | 
 | 
 * <TR><TD><CODE>starting</CODE></TD>    <TD><CODE>STARTING</CODE></TD></TR>  | 
 | 
 * <TR><TD><CODE>running</CODE></TD>     <TD><CODE>ONLINE</CODE></TD></TR>  | 
 | 
 * <TR><TD><CODE>stopping</CODE></TD>     <TD><CODE>STOPPING</CODE></TD></TR>  | 
 | 
 * </TABLE>  | 
 | 
 * <p>  | 
 | 
 * The <CODE>STARTING</CODE> state marks the transition  | 
 | 
 * from <CODE>OFFLINE</CODE> to <CODE>ONLINE</CODE>.  | 
 | 
 * <p>  | 
 | 
 * The <CODE>STOPPING</CODE> state marks the transition from  | 
 | 
 * <CODE>ONLINE</CODE> to <CODE>OFFLINE</CODE>. This occurs when the  | 
 | 
 * <CODE>CommunicatorServer</CODE> is finishing or interrupting active  | 
 | 
 * requests.  | 
 | 
 * <p>  | 
 | 
 * When a <CODE>CommunicatorServer</CODE> is unregistered from the MBeanServer,  | 
 | 
 * it is stopped automatically.  | 
 | 
 * <p>  | 
 | 
 * When the value of the <CODE>State</CODE> attribute changes the  | 
 | 
 * <CODE>CommunicatorServer</CODE> sends a  | 
 | 
 * <tt>{@link javax.management.AttributeChangeNotification}</tt> to the | 
 | 
 * registered listeners, if any.  | 
 | 
 *  | 
 | 
 * <p><b>This API is a Sun Microsystems internal API  and is subject  | 
 | 
 * to change without notice.</b></p>  | 
 | 
 */  | 
 | 
 | 
 | 
public abstract class CommunicatorServer  | 
 | 
    implements Runnable, MBeanRegistration, NotificationBroadcaster,  | 
 | 
               CommunicatorServerMBean { | 
 | 
 | 
 | 
    //  | 
 | 
    // States of a CommunicatorServer  | 
 | 
    //  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public static final int ONLINE = 0 ;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public static final int OFFLINE = 1 ;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public static final int STOPPING = 2 ;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    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 ;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public static final int SNMP_TYPE = 4 ;  | 
 | 
 | 
 | 
    /**  | 
 | 
     * Indicates that it is an HTTPS connector type.  | 
 | 
     */  | 
 | 
    //public static final int HTTPS_TYPE = 5 ;  | 
 | 
 | 
 | 
    //  | 
 | 
    // Package variables  | 
 | 
    //  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
     transient volatile int state = OFFLINE ;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    ObjectName objectName ;  | 
 | 
 | 
 | 
    MBeanServer topMBS;  | 
 | 
    MBeanServer bottomMBS;  | 
 | 
 | 
 | 
      | 
 | 
     */  | 
 | 
    transient String dbgTag = null ;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    int maxActiveClientCount = 1 ;  | 
 | 
 | 
 | 
      | 
 | 
     */  | 
 | 
    transient int servedClientCount = 0 ;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    String host = null ;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    int port = -1 ;  | 
 | 
 | 
 | 
 | 
 | 
    //  | 
 | 
    // Private fields  | 
 | 
    //  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
       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;  | 
 | 
 | 
 | 
      | 
 | 
    private transient long notifCount = 0;  | 
 | 
    private transient NotificationBroadcasterSupport notifBroadcaster =  | 
 | 
        new NotificationBroadcasterSupport();  | 
 | 
    private transient MBeanNotificationInfo[] notifInfos = null;  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public CommunicatorServer(int connectorType)  | 
 | 
        throws IllegalArgumentException { | 
 | 
        switch (connectorType) { | 
 | 
        case SNMP_TYPE :  | 
 | 
              | 
 | 
            break;  | 
 | 
        default:  | 
 | 
            throw new IllegalArgumentException("Invalid connector Type") ; | 
 | 
        }  | 
 | 
        dbgTag = makeDebugTag() ;  | 
 | 
    }  | 
 | 
 | 
 | 
    protected Thread createMainThread() { | 
 | 
        return new Thread (this, makeThreadName());  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public void start(long timeout)  | 
 | 
        throws CommunicationException, InterruptedException { | 
 | 
        boolean start;  | 
 | 
 | 
 | 
        synchronized (stateLock) { | 
 | 
            if (state == STOPPING) { | 
 | 
                // Fix for bug 4352451:  | 
 | 
                  | 
 | 
                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);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @Override  | 
 | 
    public void start() { | 
 | 
        try { | 
 | 
            start(0);  | 
 | 
        } catch (InterruptedException x) { | 
 | 
              | 
 | 
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { | 
 | 
                SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,  | 
 | 
                    "start","interrupted", x);  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @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);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @Override  | 
 | 
    public boolean isActive() { | 
 | 
        synchronized (stateLock) { | 
 | 
            return (state == ONLINE);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @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 {   | 
 | 
                            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;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    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));  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @Override  | 
 | 
    public int getState() { | 
 | 
        synchronized (stateLock) { | 
 | 
            return state ;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @Override  | 
 | 
    public String getStateString() { | 
 | 
        return getStringForState(state) ;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @Override  | 
 | 
    public String getHost() { | 
 | 
        try { | 
 | 
            host = InetAddress.getLocalHost().getHostName();  | 
 | 
        } catch (Exception e) { | 
 | 
            host = "Unknown host";  | 
 | 
        }  | 
 | 
        return host ;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @Override  | 
 | 
    public int getPort() { | 
 | 
        synchronized (stateLock) { | 
 | 
            return port ;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @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();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @Override  | 
 | 
    public abstract String getProtocol();  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    int getServedClientCount() { | 
 | 
        return servedClientCount ;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    int getActiveClientCount() { | 
 | 
        int result = clientHandlerVector.size() ;  | 
 | 
        return result ;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    int getMaxActiveClientCount() { | 
 | 
        return maxActiveClientCount ;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    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 ;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    void notifyClientHandlerCreated(ClientHandler h) { | 
 | 
        clientHandlerVector.addElement(h) ;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    synchronized void notifyClientHandlerDeleted(ClientHandler h) { | 
 | 
        clientHandlerVector.removeElement(h);  | 
 | 
        notifyAll();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     **/  | 
 | 
    protected int getBindTries() { | 
 | 
        return 50;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     **/  | 
 | 
    protected long getBindSleepTime() { | 
 | 
        return 100;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @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 ;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected abstract void doReceive()  | 
 | 
        throws CommunicationException, InterruptedException ;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected abstract void doProcess()  | 
 | 
        throws CommunicationException, InterruptedException ;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected abstract void doUnbind()  | 
 | 
        throws CommunicationException, InterruptedException ;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public synchronized MBeanServer getMBeanServer() { | 
 | 
        return topMBS;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    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  | 
 | 
    //  | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    ObjectName getObjectName() { | 
 | 
        return objectName ;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    void changeState(int newState) { | 
 | 
        int oldState;  | 
 | 
        synchronized (stateLock) { | 
 | 
            if (state == newState)  | 
 | 
                return;  | 
 | 
            oldState = state;  | 
 | 
            state = newState;  | 
 | 
            stateLock.notifyAll();  | 
 | 
        }  | 
 | 
        sendStateChangeNotification(oldState, newState);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    String makeDebugTag() { | 
 | 
        return "CommunicatorServer["+ getProtocol() + ":" + getPort() + "]" ;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    String makeThreadName() { | 
 | 
        String result ;  | 
 | 
 | 
 | 
        if (objectName == null)  | 
 | 
            result = "CommunicatorServer" ;  | 
 | 
        else  | 
 | 
            result = objectName.toString() ;  | 
 | 
 | 
 | 
        return result ;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    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();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    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...");  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    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);  | 
 | 
                 }  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    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  | 
 | 
    //  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @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);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @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);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @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,      | 
 | 
                         notifCount,                   | 
 | 
                         System.currentTimeMillis(),   | 
 | 
                         message,                      | 
 | 
                         "State",                      | 
 | 
                         "int",                        | 
 | 
                         new Integer(oldState),        | 
 | 
                         new Integer(newState) );      | 
 | 
        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  | 
 | 
    //  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @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;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @Override  | 
 | 
    public void postRegister(Boolean registrationDone) { | 
 | 
        if (!registrationDone.booleanValue()) { | 
 | 
            synchronized (this) { | 
 | 
                topMBS = bottomMBS = null;  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @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() ;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    @Override  | 
 | 
    public void postDeregister(){ | 
 | 
    }  | 
 | 
 | 
 | 
}  |