snmpportal.java

来自「opennms得相关源码 请大家看看」· Java 代码 · 共 746 行 · 第 1/2 页

JAVA
746
字号
//// This file is part of the OpenNMS(R) Application.//// OpenNMS(R) is Copyright (C) 2002-2003 The OpenNMS Group, Inc.  All rights reserved.// OpenNMS(R) is a derivative work, containing both original code, included code and modified// code that was published under the GNU General Public License. Copyrights for modified // and included code are below.//// OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.// // Modifications://// 2003 Aug 21: Added the ability to generate a new DatagramSocket on a random//		high number port if needed by setting the port to -1.//// Original code base Copyright (C) 1999-2001 Oculan Corp.  All rights reserved.//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program 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 for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//// For more information contact://      OpenNMS Licensing       <license@opennms.org>//      http://www.opennms.org///      http://www.opennms.com///// Tab Size = 8//package org.opennms.protocols.snmp;import java.io.ByteArrayOutputStream;import java.io.InterruptedIOException;import java.io.OutputStream;import java.io.PrintStream;import java.lang.reflect.Method;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.SocketException;import java.util.Date;import java.util.LinkedList;import org.opennms.protocols.snmp.asn1.ASN1;import org.opennms.protocols.snmp.asn1.AsnDecodingException;import org.opennms.protocols.snmp.asn1.AsnEncoder;/** * Abstracts the communication related details from the SnmpSession and * SnmpTrapSession. *  * @author <a href="mailto:weave@oculan.com">Brian Weaver </a> * @author <a href="mailto:sowmya@opennms.org">Sowmya Nataraj </a> * @author <a href="http://www.opennms.org">OpenNMS </a> *  * @see SnmpSession * @see SnmpTrapSession * @see java.net.DatagramSocket */public class SnmpPortal extends Object {    /**     * The packet handler that is used to process received SNMP packets and     * invalid datagrams. The handler must also process any exceptions that     * occurs in the receiving thread.     *      */    private SnmpPacketHandler m_handler;    /**     * The datagram socket used to send and receive SNMP messages.     *      */    private DatagramSocket m_comm;    /**     * the receiver thread that runs the inner class Receiver.     */    private Thread m_recvThread;    /**     * ASN.1 encoder used to decode the SNMP messages. If the decoded fails to     * decode the specific messages the is should throw and appropiate ASN.1     * exception     *      */    private AsnEncoder m_encoder;    /**     * When set the portal object's close method has been invoked. This is     * needed since the internal receiver thread will block on the communication     * channel. To "wake" the thread the close() method on the comm channel is     * performed. This will cause an exception to be genereated in the receiver     * thread. If the value of m_isClosing is true then the exception is     * ignored.     */    private volatile boolean m_isClosing;    /**     * Set to true if it is necessary to set the socket timeout value via the     * Socket.setSoTimeout() method in order to keep from blocking indefinitely     * on a socket I/O call. This value is configurable at runtime via the     * system property "org.opennms.joeSNMP.vmhacks.socketSoTimeoutRequired". If     * this property is set to 'no', the bSocketSoTimeoutRequired variable will     * be set to false and the SNMP trap socket timeout will not be set. If this     * property is set to 'yes' or the property does not exist, the     * bSocketSoTimeoutRequired variable will be set to true. and the socket     * timeout will be set. Default value is true.     */    private boolean bSocketSoTimeoutRequired = true;    /**     * Identifies the system property that may be used to specify whether or not     * a timeout value is set on the SNMP trap socket. Valid values are 'yes'     * and 'no'.     */    private static final String PROP_SOCKET_TIMEOUT_REQUIRED = "org.opennms.joeSNMP.vmhacks.socketSoTimeoutRequired";    /**     * Identifies the system property that may be used to specify the number of     * milliseconds to use for the socket timeout.     */    private static final String PROP_SOCKET_TIMEOUT_PERIOD = "org.opennms.joeSNMP.vmhacks.socketSoTimeoutPeriod";    /**     * Private constructor used to disallow the default constructor.     *      * @exception java.lang.UnsupportedOperationException     *                Always thrown!     */    private SnmpPortal() throws java.lang.UnsupportedOperationException {        throw new java.lang.UnsupportedOperationException("Illegal constructor call");    }    /**     * The SnmpPortal constructor. The constructor is used to build a portal on     * the specified port, and forward messages to the defined handler. All     * messages are decoded using the encoder specified during construction.     *      * @param handler     *            The SNMP packet handler.     * @param encoder     *            The ASN.1 codec object.     * @param port     *            The port to send and receive datagram from.     *      * @exception java.net.SocketException     *                Thrown if an error occurs setting up the communication     *                channel.     * @exception java.lang.IllegalArgumentException     *                Thrown if any of the parameters are null or invalid.     *      */    SnmpPortal(SnmpPacketHandler handler, AsnEncoder encoder, int port) throws SocketException {        if (handler == null || encoder == null)            throw new IllegalArgumentException("Invalid argument");        m_handler = handler;        if (port >= 0) {            m_comm = new DatagramSocket(port);        } else {            m_comm = new DatagramSocket();        }        //        // Determine whether or not it is necessary to use the        // socket.setSoTimeout()        // method to set the socket timeout value thereby mimic'ing non-blocking        // socket I/O.        // On platforms whose system close() is not preemptive it is necessary        // to use the socket timeout        // to keep from blocking indefinitely on any socket call that performs        // I/O.        //        bSocketSoTimeoutRequired = true; // Default is to use set the socket                                            // timeout        String strSocketSoTimeoutRequired = System.getProperty(PROP_SOCKET_TIMEOUT_REQUIRED);        String osName = System.getProperty("os.name");        if (strSocketSoTimeoutRequired != null && strSocketSoTimeoutRequired.equals("no")) {            bSocketSoTimeoutRequired = false;        }        if (bSocketSoTimeoutRequired == true) {            String strSocketSoTimeoutPeriod = System.getProperty(PROP_SOCKET_TIMEOUT_PERIOD);            int timeout = 3000; // Default socket timeout is 3 seconds            if (strSocketSoTimeoutPeriod != null) {                try {                    timeout = Integer.parseInt(strSocketSoTimeoutPeriod);                } catch (NumberFormatException e) {                    timeout = 3000;                }            }            m_comm.setSoTimeout(timeout);        } else if (osName != null && osName.equalsIgnoreCase("linux")) {            // we must force this issue because we do not know            // what VM there running in. If there running in            // Sun JDK 1.3.1 with J2SE_PREEMPTCLOSE set then            // this is unnecessary. If there not running in 1.3.1            // and the're on linux then THEY MUST have a timeout            // set of it will hang a thread.            //            m_comm.setSoTimeout(100);        }        m_isClosing = false;        m_recvThread = new Thread(new Receiver(), "SnmpPortal-" + m_comm.getPort());        m_encoder = encoder;        m_recvThread.start();    }    /**     * Defines the inner class that monitors the datagram socket and receives     * all the PDU responses. If an exception is generated then it is saved in     * m_why and can be re-generated with a call to raise().     *      */    private class Receiver implements Runnable {        /**         * Called to setup the communications channel buffers. The method         * attempts to set the received buffer size to 64k. If it fails then the         * default buffer size is recovered. If the default buffer size cannot         * be recovered then a zero is returned.         *          * @return The communications channel receive buffer size. A zero is         *         returned on error         */        private int setup() {            int bufSz = 64 * 1024;            //            // set the receiver buffer            //            try {                m_comm.setReceiveBufferSize(bufSz);            } catch (SocketException err) {                bufSz = 0;            }            if (bufSz == 0) {                try {                    bufSz = m_comm.getReceiveBufferSize();                } catch (SocketException err) {                    bufSz = 0;                }            }            return bufSz;        }        /**         * The run method is an infinite loop method that receives all datagrams         * for the session. If an unrecoverable error occurs then the m_handler         * is informed of the error         *          * If a pdu is recovered from the channel then the associated handler is         * invoked to process the pdu.         *          * @see SnmpPacketHandler         */        public void run() {            final int bufSz = setup();            if (bufSz == 0) {                return;            }            final LinkedList fastReceiverQ = new LinkedList();            final LinkedList usedBuffers = new LinkedList();            Thread fastReceiver = new Thread(new Runnable() {                public void run() {                    while (!m_isClosing && Thread.interrupted() == false) {                        byte[] buf = null;                        synchronized (usedBuffers) {                            if (!usedBuffers.isEmpty())                                buf = (byte[]) usedBuffers.removeFirst();                        }                        if (buf == null || buf.length != bufSz)                            buf = new byte[bufSz];                        try {                            DatagramPacket pkt = new DatagramPacket(buf, buf.length);                            m_comm.receive(pkt);                            synchronized (fastReceiverQ) {                                fastReceiverQ.addLast(pkt);                                fastReceiverQ.notify();                            }                        } catch (InterruptedIOException ioe) {                            synchronized (usedBuffers) {                                usedBuffers.addLast(buf);                            }                            continue;                        } catch (Exception e) {                            if (!m_isClosing) {                                boolean handled = true;                                try {                                    Class loggerC = Class.forName("org.opennms.core.utils.ThreadCategory");                                    Class[] methodParmList = { Class.class };                                    Method loggerM = loggerC.getMethod("getInstance", methodParmList);                                    Object[] parmList = { this.getClass() };                                    Object loggerI = loggerM.invoke(null, parmList);                                    methodParmList = new Class[] { Object.class, Throwable.class };                                    Method infoM = loggerC.getMethod("info", methodParmList);                                    parmList = new Object[] { "An unknown error occured decoding the packet", e };                                    infoM.invoke(loggerI, parmList);                                } catch (Throwable t) {                                    handled = false;                                }                                if (!handled) {                                    System.out.println(new Date() + " - Exception: " + e.getMessage());                                }                                m_handler.processException(e);                            }                        }                    }                }            }, Thread.currentThread().getName() + "-FastReceiver");            fastReceiver.start();            //            // get a buffer for the datagrams            //            while (!m_isClosing) {                DatagramPacket pkt = null;                try {                    //                    // reset the packet's length                    //                    synchronized (fastReceiverQ) {                        while (fastReceiverQ.isEmpty() && !m_isClosing)                            fastReceiverQ.wait(300);                        if (m_isClosing)                            continue;                        pkt = (DatagramPacket) fastReceiverQ.removeFirst();                    }                    handlePkt(pkt);                } catch (SnmpPduEncodingException err) {                    boolean handled = true;                    try {                        Class loggerC = Class.forName("org.opennms.core.utils.ThreadCategory");                        Class[] methodParmList = { Class.class };                        Method loggerM = loggerC.getMethod("getInstance", methodParmList);                        Object[] parmList = { this.getClass() };                        Object loggerI = loggerM.invoke(null, parmList);                        methodParmList = new Class[] { Object.class, Throwable.class };                        Method infoM = loggerC.getMethod("info", methodParmList);                        parmList = new Object[] { "An error occured decoding the protocol data unit", err };                        infoM.invoke(loggerI, parmList);                        methodParmList = new Class[0];                        Method debugEnabledM = loggerC.getMethod("isDebugEnabled", methodParmList);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?