/* * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * */ package com.sun.jmx.snmp.agent; // java imports // import java.util.Vector; import java.util.Enumeration; import java.util.Iterator; // jmx imports // import javax.management.AttributeList; import javax.management.Attribute; import javax.management.MBeanException; import javax.management.MBeanServer; import javax.management.ObjectName; import javax.management.ReflectionException; import javax.management.InstanceNotFoundException; import javax.management.InvalidAttributeValueException; import javax.management.InstanceAlreadyExistsException; import javax.management.MBeanRegistrationException; import javax.management.NotCompliantMBeanException; import javax.management.RuntimeOperationsException; import com.sun.jmx.snmp.SnmpOid; import com.sun.jmx.snmp.SnmpValue; import com.sun.jmx.snmp.SnmpVarBind; import com.sun.jmx.snmp.SnmpStatusException; /** *
* This class is a utility class that transforms SNMP GET / SET requests * into standard JMX getAttributes() setAttributes() requests. *
* *
* The transformation relies on the metadata information provided by the
* {@link com.sun.jmx.snmp.agent.SnmpGenericMetaServer} object which is
* passed as the first parameter to every method. This SnmpGenericMetaServer
* object is usually a Metadata object generated by mibgen
.
*
* This class is used internally by mibgen generated metadata objects and * you should never need to use it directly. *
*This API is a Sun Microsystems internal API and is subject * to change without notice.
**/ public class SnmpGenericObjectServer { // ---------------------------------------------------------------------- // // Protected variables // // ---------------------------------------------------------------------- /** * The MBean server through which the MBeans will be accessed. **/ protected final MBeanServer server; // ---------------------------------------------------------------------- // // Constructors // // ---------------------------------------------------------------------- /** * Builds a new SnmpGenericObjectServer. Usually there will be a single * object of this type per MIB. * * @param server The MBeanServer in which the MBean accessed by this * MIB are registered. **/ public SnmpGenericObjectServer(MBeanServer server) { this.server = server; } /** * Execute an SNMP GET request. * ** This method first builds the list of attributes that need to be * retrieved from the MBean and then calls getAttributes() on the * MBean server. Then it updates the SnmpMibSubRequest with the values * retrieved from the MBean. *
* *
* The SNMP metadata information is obtained through the given
* meta
object, which usually is an instance of a
* mibgen
generated class.
*
* This method is called internally by mibgen
generated
* objects and you should never need to call it directly.
*
* req.registerGetException(VariableId,SnmpStatusException)
*
**/
public void get(SnmpGenericMetaServer meta, ObjectName name,
SnmpMibSubRequest req, int depth)
throws SnmpStatusException {
// java.lang.System.out.println(">>>>>>>>> GET " + name);
final int size = req.getSize();
final Object data = req.getUserData();
final String[] nameList = new String[size];
final SnmpVarBind[] varList = new SnmpVarBind[size];
final long[] idList = new long[size];
int i = 0;
for (Enumeration e=req.getElements(); e.hasMoreElements();) {
final SnmpVarBind var= (SnmpVarBind) e.nextElement();
try {
final long id = var.oid.getOidArc(depth);
nameList[i] = meta.getAttributeName(id);
varList[i] = var;
idList[i] = id;
// Check the access rights according to the MIB.
// The MBean might be less restrictive (have a getter
// while the MIB defines the variable as AFN)
//
meta.checkGetAccess(id,data);
//java.lang.System.out.println(nameList[i] + " added.");
i++;
} catch(SnmpStatusException x) {
//java.lang.System.out.println("exception for " + nameList[i]);
//x.printStackTrace();
req.registerGetException(var,x);
}
}
AttributeList result = null;
int errorCode = SnmpStatusException.noSuchInstance;
try {
result = server.getAttributes(name,nameList);
} catch (InstanceNotFoundException f) {
//java.lang.System.out.println(name + ": instance not found.");
//f.printStackTrace();
result = new AttributeList();
} catch (ReflectionException r) {
//java.lang.System.out.println(name + ": reflexion error.");
//r.printStackTrace();
result = new AttributeList();
} catch (Exception x) {
result = new AttributeList();
}
final Iterator it = result.iterator();
for (int j=0; j < i; j++) {
if (!it.hasNext()) {
//java.lang.System.out.println(name + "variable[" + j +
// "] absent");
final SnmpStatusException x =
new SnmpStatusException(errorCode);
req.registerGetException(varList[j],x);
continue;
}
final Attribute att = (Attribute) it.next();
while ((j < i) && (! nameList[j].equals(att.getName()))) {
//java.lang.System.out.println(name + "variable[" +j +
// "] not found");
final SnmpStatusException x =
new SnmpStatusException(errorCode);
req.registerGetException(varList[j],x);
j++;
}
if ( j == i) break;
try {
varList[j].value =
meta.buildSnmpValue(idList[j],att.getValue());
} catch (SnmpStatusException x) {
req.registerGetException(varList[j],x);
}
//java.lang.System.out.println(att.getName() + " retrieved.");
}
//java.lang.System.out.println(">>>>>>>>> END GET");
}
/**
* Get the value of an SNMP variable.
*
* * You should never need to use this method directly. *
* * @param meta The impacted metadata object * @param name The ObjectName of the impacted MBean * @param id The OID arc identifying the variable we're trying to set. * @param data User contextual data allocated through the * {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory} * * @return The value of the variable. * * @exception SnmpStatusException whenever an SNMP exception must be * raised. Raising an exception will abort the request.
* req.registerGetException(VariableId,SnmpStatusException)
*
**/
public SnmpValue get(SnmpGenericMetaServer meta, ObjectName name,
long id, Object data)
throws SnmpStatusException {
final String attname = meta.getAttributeName(id);
Object result = null;
try {
result = server.getAttribute(name,attname);
} catch (MBeanException m) {
Exception t = m.getTargetException();
if (t instanceof SnmpStatusException)
throw (SnmpStatusException) t;
throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
} catch (Exception e) {
throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
}
return meta.buildSnmpValue(id,result);
}
/**
* Execute an SNMP SET request.
*
* * This method first builds the list of attributes that need to be * set on the MBean and then calls setAttributes() on the * MBean server. Then it updates the SnmpMibSubRequest with the new * values retrieved from the MBean. *
* *
* The SNMP metadata information is obtained through the given
* meta
object, which usually is an instance of a
* mibgen
generated class.
*
* This method is called internally by mibgen
generated
* objects and you should never need to call it directly.
*
* req.registerGetException(VariableId,SnmpStatusException)
*
**/
public void set(SnmpGenericMetaServer meta, ObjectName name,
SnmpMibSubRequest req, int depth)
throws SnmpStatusException {
final int size = req.getSize();
final AttributeList attList = new AttributeList(size);
final String[] nameList = new String[size];
final SnmpVarBind[] varList = new SnmpVarBind[size];
final long[] idList = new long[size];
int i = 0;
for (Enumeration e=req.getElements(); e.hasMoreElements();) {
final SnmpVarBind var= (SnmpVarBind) e.nextElement();
try {
final long id = var.oid.getOidArc(depth);
final String attname = meta.getAttributeName(id);
final Object attvalue=
meta.buildAttributeValue(id,var.value);
final Attribute att = new Attribute(attname,attvalue);
attList.add(att);
nameList[i] = attname;
varList[i] = var;
idList[i] = id;
i++;
} catch(SnmpStatusException x) {
req.registerSetException(var,x);
}
}
AttributeList result = null;
int errorCode = SnmpStatusException.noAccess;
try {
result = server.setAttributes(name,attList);
} catch (InstanceNotFoundException f) {
result = new AttributeList();
errorCode = SnmpStatusException.snmpRspInconsistentName;
} catch (ReflectionException r) {
errorCode = SnmpStatusException.snmpRspInconsistentName;
result = new AttributeList();
} catch (Exception x) {
result = new AttributeList();
}
final Iterator it = result.iterator();
for (int j=0; j < i; j++) {
if (!it.hasNext()) {
final SnmpStatusException x =
new SnmpStatusException(errorCode);
req.registerSetException(varList[j],x);
continue;
}
final Attribute att = (Attribute) it.next();
while ((j < i) && (! nameList[j].equals(att.getName()))) {
final SnmpStatusException x =
new SnmpStatusException(SnmpStatusException.noAccess);
req.registerSetException(varList[j],x);
j++;
}
if ( j == i) break;
try {
varList[j].value =
meta.buildSnmpValue(idList[j],att.getValue());
} catch (SnmpStatusException x) {
req.registerSetException(varList[j],x);
}
}
}
/**
* Set the value of an SNMP variable.
*
* * You should never need to use this method directly. *
* * @param meta The impacted metadata object * @param name The ObjectName of the impacted MBean * @param x The new requested SnmpValue * @param id The OID arc identifying the variable we're trying to set. * @param data User contextual data allocated through the * {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory} * * @return The new value of the variable after the operation. * * @exception SnmpStatusException whenever an SNMP exception must be * raised. Raising an exception will abort the request.
* req.registerSetException(VariableId,SnmpStatusException)
*
**/
public SnmpValue set(SnmpGenericMetaServer meta, ObjectName name,
SnmpValue x, long id, Object data)
throws SnmpStatusException {
final String attname = meta.getAttributeName(id);
final Object attvalue=
meta.buildAttributeValue(id,x);
final Attribute att = new Attribute(attname,attvalue);
Object result = null;
try {
server.setAttribute(name,att);
result = server.getAttribute(name,attname);
} catch(InvalidAttributeValueException iv) {
throw new
SnmpStatusException(SnmpStatusException.snmpRspWrongValue);
} catch (InstanceNotFoundException f) {
throw new
SnmpStatusException(SnmpStatusException.snmpRspInconsistentName);
} catch (ReflectionException r) {
throw new
SnmpStatusException(SnmpStatusException.snmpRspInconsistentName);
} catch (MBeanException m) {
Exception t = m.getTargetException();
if (t instanceof SnmpStatusException)
throw (SnmpStatusException) t;
throw new
SnmpStatusException(SnmpStatusException.noAccess);
} catch (Exception e) {
throw new
SnmpStatusException(SnmpStatusException.noAccess);
}
return meta.buildSnmpValue(id,result);
}
/**
* Checks whether an SNMP SET request can be successfully performed.
*
* * For each variable in the subrequest, this method calls * checkSetAccess() on the meta object, and then tries to invoke the * checkAttributeName() method on the MBean. If this method * is not defined then it is assumed that the SET won't fail. *
* *
* This method is called internally by mibgen
generated
* objects and you should never need to call it directly.
*
* req.registerCheckException(VariableId,SnmpStatusException)
*
*
**/
public void check(SnmpGenericMetaServer meta, ObjectName name,
SnmpMibSubRequest req, int depth)
throws SnmpStatusException {
final Object data = req.getUserData();
for (Enumeration e=req.getElements(); e.hasMoreElements();) {
final SnmpVarBind var= (SnmpVarBind) e.nextElement();
try {
final long id = var.oid.getOidArc(depth);
// call meta.check() here, and meta.check will call check()
check(meta,name,var.value,id,data);
} catch(SnmpStatusException x) {
req.registerCheckException(var,x);
}
}
}
/**
* Checks whether a SET operation can be performed on a given SNMP
* variable.
*
* @param meta The impacted metadata object
* @param name The ObjectName of the impacted MBean
* @param x The new requested SnmpValue
* @param id The OID arc identifying the variable we're trying to set.
* @param data User contextual data allocated through the
* {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}
*
* * This method calls checkSetAccess() on the meta object, and then * tries to invoke the checkAttributeName() method on the MBean. * If this method is not defined then it is assumed that the SET * won't fail. *
* *
* This method is called internally by mibgen
generated
* objects and you should never need to call it directly.
*
* req.registerCheckException(VariableId,SnmpStatusException)
*
*
**/
// XXX xxx ZZZ zzz Maybe we should go through the MBeanInfo here?
public void check(SnmpGenericMetaServer meta, ObjectName name,
SnmpValue x, long id, Object data)
throws SnmpStatusException {
meta.checkSetAccess(x,id,data);
try {
final String attname = meta.getAttributeName(id);
final Object attvalue= meta.buildAttributeValue(id,x);
final Object[] params = new Object[1];
final String[] signature = new String[1];
params[0] = attvalue;
signature[0] = attvalue.getClass().getName();
server.invoke(name,"check"+attname,params,signature);
} catch( SnmpStatusException e) {
throw e;
}
catch (InstanceNotFoundException i) {
throw new
SnmpStatusException(SnmpStatusException.snmpRspInconsistentName);
} catch (ReflectionException r) {
// checkXXXX() not defined => do nothing
} catch (MBeanException m) {
Exception t = m.getTargetException();
if (t instanceof SnmpStatusException)
throw (SnmpStatusException) t;
throw new SnmpStatusException(SnmpStatusException.noAccess);
} catch (Exception e) {
throw new
SnmpStatusException(SnmpStatusException.noAccess);
}
}
public void registerTableEntry(SnmpMibTable meta, SnmpOid rowOid,
ObjectName objname, Object entry)
throws SnmpStatusException {
if (objname == null)
throw new
SnmpStatusException(SnmpStatusException.snmpRspInconsistentName);
try {
if (entry != null && !server.isRegistered(objname))
server.registerMBean(entry, objname);
} catch (InstanceAlreadyExistsException e) {
throw new
SnmpStatusException(SnmpStatusException.snmpRspInconsistentName);
} catch (MBeanRegistrationException e) {
throw new SnmpStatusException(SnmpStatusException.snmpRspNoAccess);
} catch (NotCompliantMBeanException e) {
throw new SnmpStatusException(SnmpStatusException.snmpRspGenErr);
} catch (RuntimeOperationsException e) {
throw new SnmpStatusException(SnmpStatusException.snmpRspGenErr);
} catch(Exception e) {
throw new SnmpStatusException(SnmpStatusException.snmpRspGenErr);
}
}
}