//
// 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.
//
// Modifications:
//
// 2008 May 10: In processErrors, when we throw exceptions or notify of errors,
// state that the OID shown is the *previous* OID. - dj@opennms.org
//
// 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.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang.builder.CompareToBuilder;
public class TableTracker extends CollectionTracker implements RowCallback, RowResultFactory {
private final SnmpTableResult m_tableResult;
private final List<ColumnTracker> m_columnTrackers;
public TableTracker(SnmpObjId... ids) {
this(null, ids);
}
public TableTracker(RowCallback rc, SnmpObjId... ids) {
this(rc, 2, ids);
}
public TableTracker(RowCallback rc, int maxRepetitions, SnmpObjId... columns) {
m_tableResult = new SnmpTableResult(rc == null ? this : rc, this, columns);
m_columnTrackers = new ArrayList<ColumnTracker>(columns.length);
for (SnmpObjId id : columns) {
m_columnTrackers.add(new ColumnTracker(this, id, maxRepetitions));
}
}
@Override
public void setMaxRepetitions(int maxRepetitions) {
for(ColumnTracker child : m_columnTrackers) {
child.setMaxRepetitions(maxRepetitions);
}
}
@Override
public boolean isFinished() {
if (super.isFinished()) {
return true;
}
for (ColumnTracker ct : m_columnTrackers) {
if (!ct.isFinished()) {
return false;
}
}
m_tableResult.tableFinished();
setFinished(true);
return true;
}
@Override
public ResponseProcessor buildNextPdu(PduBuilder pduBuilder) {
if (pduBuilder.getMaxVarsPerPdu() < 1) {
throw new IllegalArgumentException("maxVarsPerPdu < 1");
}
List<ResponseProcessor> processors = new ArrayList<ResponseProcessor>(pduBuilder.getMaxVarsPerPdu());
for (ColumnTracker ct : getNextColumnTrackers(pduBuilder.getMaxVarsPerPdu())) {
processors.add(ct.buildNextPdu(pduBuilder));
}
return new CombinedColumnResponseProcessor(processors);
}
public void storeResult(SnmpResult res) {
System.err.println(String.format("storeResult: %s", res));
m_tableResult.storeResult(res);
}
public void rowCompleted(SnmpRowResult row) {
// the default implementation just forwards this to the super class
// like the defaults for other CollectionTrackers except this does it
// from the rowCompleted method rather than from storeResult
for(SnmpResult result : row.getResults()) {
super.storeResult(result);
}
}
public SnmpRowResult createRowResult(int columnCount, SnmpInstId instance) {
return m_tableResult.createRowResult(columnCount, instance);
}
private List<ColumnTracker> getNextColumnTrackers(int maxVarsPerPdu) {
List<ColumnTracker> trackers = new ArrayList<ColumnTracker>(maxVarsPerPdu);
List<ColumnTracker> sortedTrackerList = new ArrayList<ColumnTracker>(m_columnTrackers);
Collections.sort(sortedTrackerList, new Comparator<ColumnTracker>() {
public int compare(ColumnTracker o1, ColumnTracker o2) {
return new CompareToBuilder()
.append(o1.getLastInstance(), o2.getLastInstance())
.toComparison();
}
});
for(Iterator<ColumnTracker> it = sortedTrackerList.iterator(); it.hasNext() && trackers.size() < maxVarsPerPdu; ) {
ColumnTracker tracker = it.next();
if (!tracker.isFinished()) {
trackers.add(tracker);
}
}
return trackers;
}
static private class CombinedColumnResponseProcessor implements ResponseProcessor {
private final List<ResponseProcessor> m_processors;
private int m_currentIndex = 0;
public CombinedColumnResponseProcessor(List<ResponseProcessor> processors) {
m_processors = processors;
}
public void processResponse(SnmpObjId responseObjId, SnmpValue val) {
try {
ResponseProcessor rp = m_processors.get(m_currentIndex);
if (++m_currentIndex == m_processors.size()) {
m_currentIndex = 0;
}
rp.processResponse(responseObjId, val);
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean processErrors(int errorStatus, int errorIndex) {
/*
* errorIndex is varBind index (1 based array of vars)
*
*
*/
int columnIndex = (errorIndex - 1) % m_processors.size();
ResponseProcessor rp = m_processors.get(columnIndex);
return rp.processErrors(errorStatus, 1);
}
}
}