// // This file is part of the OpenNMS(R) Application. // // OpenNMS(R) is Copyright (C) 2005 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. // // 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/ // package org.infosec.ismp.snmp; import java.io.IOException; import java.net.InetAddress; import org.infosec.ismp.util.ThreadCategory; import org.infosec.ismp.util.concurrent.BarrierSignaler; public abstract class SnmpWalker { protected static abstract class WalkerPduBuilder extends PduBuilder { protected WalkerPduBuilder(int maxVarsPerPdu) { super(maxVarsPerPdu); } abstract public void reset(); } private final String m_name; private final CollectionTracker m_tracker; private final BarrierSignaler m_signal; private InetAddress m_address; private WalkerPduBuilder m_pduBuilder; private ResponseProcessor m_responseProcessor; private final int m_maxVarsPerPdu; private boolean m_error = false; private String m_errorMessage; private Throwable m_errorThrowable; protected SnmpWalker(InetAddress address, String name, int maxVarsPerPdu, int maxRepititions, CollectionTracker tracker) { m_address = address; m_signal = new BarrierSignaler(1); m_name = name; m_tracker = tracker; m_tracker.setMaxRepetitions(maxRepititions); m_maxVarsPerPdu = maxVarsPerPdu; } protected abstract WalkerPduBuilder createPduBuilder(int maxVarsPerPdu); public void start() { m_pduBuilder = createPduBuilder(m_maxVarsPerPdu); try { buildAndSendNextPdu(); } catch (Throwable e) { handleFatalError(e); } } public int getMaxVarsPerPdu() { return (m_pduBuilder == null ? m_maxVarsPerPdu : m_pduBuilder .getMaxVarsPerPdu()); } protected void buildAndSendNextPdu() throws IOException { if (m_tracker.isFinished()) { handleDone(); } else { m_pduBuilder.reset(); m_responseProcessor = m_tracker.buildNextPdu(m_pduBuilder); sendNextPdu(m_pduBuilder); } } protected abstract void sendNextPdu(WalkerPduBuilder pduBuilder) throws IOException; protected void handleDone() { finish(); } /** * <P> * Returns the success or failure code for collection of the data. * </P> */ public boolean failed() { return m_error; } public boolean timedOut() { return m_tracker.timedOut(); } protected void handleAuthError(String msg) { m_tracker.setFailed(true); processError("Authentication error processing", msg, null); } protected void handleError(String msg) { // XXX why do we set timedOut to false here? should we be doing this // everywhere? m_tracker.setTimedOut(false); processError("Error retrieving", msg, null); } protected void handleFatalError(Throwable e) { m_tracker.setFailed(true); processError("Unexpected error occurred processing", e.toString(), e); } protected void handleTimeout(String msg) { m_tracker.setTimedOut(true); processError("Timeout retrieving", msg, null); } private void processError(String reason, String cause, Throwable t) { String logMessage = reason + " " + getName() + " for " + m_address + ": " + cause; m_error = true; m_errorMessage = logMessage; m_errorThrowable = t; finish(); } private void finish() { signal(); try { close(); } catch (IOException e) { log().error( getName() + ": Unexpected Error occured closing snmp session for: " + m_address, e); } } protected abstract void close() throws IOException; public String getName() { return m_name; } private void signal() { synchronized (this) { notifyAll(); } if (m_signal != null) { m_signal.signalAll(); } } private final ThreadCategory log() { return ThreadCategory.getInstance(SnmpWalker.class); } public void waitFor() throws InterruptedException { m_signal.waitFor(); } public void waitFor(long timeout) throws InterruptedException { m_signal.waitFor(timeout); } protected boolean processErrors(int errorStatus, int errorIndex) { return m_responseProcessor.processErrors(errorStatus, errorIndex); } protected void processResponse(SnmpObjId receivedOid, SnmpValue val) { m_responseProcessor.processResponse(receivedOid, val); } protected void setAddress(InetAddress address) { m_address = address; } protected InetAddress getAddress() { return m_address; } public String getErrorMessage() { return m_errorMessage; } public Throwable getErrorThrowable() { return m_errorThrowable; } }