package org.vafer.jmx2snmp.jmx;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Iterator;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicReference;
/**
* The JmxMib represents a walk-able SNMP OID tree. The tree is loaded and
* constructed from a load(Reader). The expect format include a definition
* for the root node as "<oid>" and all other nodes.
*
* 1.3.6.1.4.1.27305 = <oid>
* 1.3.6.1.4.1.27305.12 = bean1
* 1.3.6.1.4.1.27305.12.1 = AnotherInt
* 1.3.6.1.4.1.27305.12.2 = SomeColor
* 1.3.6.1.4.1.27305.12.3 = TheBoolean
*
* @threadsafe yes
*/
public final class JmxMib {
private final AtomicReference<Node> root = new AtomicReference<Node>(new Node(null, 0, null));
public static class Bean {
public boolean leaf;
public String relativePath;
public String absolutePath;
};
private static class Node {
public final Node parent;
public final int idx;
public String value;
public final SortedMap<Integer, Node> childs = new TreeMap<Integer, Node>();
public Node(Node parent, int idx, String value) {
this.parent = parent;
this.idx = idx;
this.value = value;
}
public String getOid() {
if (parent == null) {
return null;
}
final String parentOid = parent.getOid();
if (parentOid == null) {
return "" + idx;
}
return parentOid + '.' + idx;
}
public String getPath() {
if (parent == null) {
return null;
}
final String parentPath = parent.getPath();
if (parentPath == null) {
return value;
}
return parentPath + '.' + value;
}
public Node getNext() {
Node leaf = this;
while(leaf.childs.size() > 0) {
leaf = leaf.childs.get(leaf.childs.firstKey());
}
if (leaf != this) {
return leaf;
}
Node n = leaf;
while(n != null) {
final Node p = n.parent;
if (p == null) {
return null;
}
final Node sibling = p.childAfter(n.idx);
if (sibling != null) {
if (sibling.childs.size() > 0) {
return sibling.getNext();
}
return sibling;
}
n = p;
}
return null;
}
public Node childAfter(int index) {
Iterator<Integer> iterator = childs.keySet().iterator();
while (iterator.hasNext()) {
Integer key = iterator.next();
if (key > index) {
return childs.get(key);
}
}
return null;
}
public int getNodeCount() {
int count = 1;
for(Node node : childs.values()) {
count += node.getNodeCount();
}
return count;
}
}
private Node createNode( Node root, String oid ) {
final String[] indexes = oid.split("\\.");
Node node = root;
for (int i = 0; i < indexes.length; i++) {
final Integer idx = Integer.parseInt(indexes[i]);
Node n = node.childs.get(idx);
if (n == null) {
n = new Node(node, idx, null);
node.childs.put(idx, n);
}
node = n;
}
return node;
}
private Node lookupNode( Node root, String oid ) {
final String[] indexes = oid.split("\\.");
Node node = root;
for (int i = 0; i < indexes.length; i++) {
final Integer idx = Integer.parseInt(indexes[i]);
Node n = node.childs.get(idx);
if (n == null) {
return null;
}
node = n;
}
return node;
}
public synchronized void load(Reader pConfigReader) throws IOException {
final BufferedReader br = new BufferedReader(pConfigReader);
final Node newRoot = new Node(null, 0, null);
while(true) {
final String line = br.readLine();
if (line == null) {
break;
}
final String[] tokens = line.split("=");
final String key = tokens[0].trim();
final String value = tokens[1].trim();
final Node node = createNode(newRoot, key);
node.value = value;
}
br.close();
root.set(newRoot);
}
public String getPathFromOid(String oid) {
final Node node = lookupNode(root.get(), oid);
if (node == null) {
return null;
}
return node.getPath();
}
public String getNextOidFromOid(String oid) {
final Node node = lookupNode(root.get(), oid);
if (node == null) {
return null;
}
final Node nextNode = node.getNext();
if (nextNode == null) {
return null;
}
return nextNode.getOid();
}
public int getNodeCount() {
return root.get().getNodeCount() - 1;
}
private void fillMapping(Node node, TreeMap<String,Bean> map) {
if (node.value != null) {
Bean bean = new Bean();
bean.leaf = node.childs.size() == 0;
bean.relativePath = node.value;
bean.absolutePath = node.getPath();
map.put(node.getOid(), bean);
}
for(Node child : node.childs.values()) {
fillMapping(child, map);
}
}
public TreeMap<String,Bean> getMapping() {
final TreeMap<String,Bean> map = new TreeMap<String,Bean>();
final Node node = root.get();
fillMapping(node, map);
return map;
}
}