/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) 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 3 of the License, * or (at your option) any later version. * * OpenNMS(R) 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 OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.netmgt.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; import org.opennms.core.utils.ThreadCategory; 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)); ThreadCategory.getInstance(SnmpResult.class).debug(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); } } }