www.pudn.com > sxg.rar > ContextGetRequest.java
/*
* Copyright (c) 2003 Jens Mueller
*
* 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, 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
Data class representig get-requests on a single context / SNMP-agent.
@author Jens Mueller
*/
import java.net.InetAddress;
import java.net.SocketException;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.Iterator;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.dom4j.xpath.DefaultXPath;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.Branch;
import org.dom4j.Namespace;
import org.dom4j.QName;
import org.dom4j.XPath;
import org.dom4j.io.XMLWriter;
import org.dom4j.io.OutputFormat;
public class ContextGetRequest
{
private String _ipaddr;
private InetAddress _inetAddress;
private int _port;
private String _commString;
private boolean _caching;
/**
the part of the requeststring following the context. For example, for a get-request containing
the request "/context[@hostname="localhost"](/ifEntry|/tcpConnEntry[tcpConnState="listen"])
_xPath will contain "(/ifEntry|/tcpConnEntry[tcpConnState="listen"])". */
private String _xPath;
private Vector _GwComplexTypeVector;
private Document _resDocument;
public ContextGetRequest()
{
_caching = true;
_port = GatewayConf.DEFAULT_PORT;
_commString = GatewayConf.DEFAULT_COMM_STR;
_GwComplexTypeVector = new Vector();
_resDocument = DocumentHelper.createDocument();
}
public void setIPaddr( String addr )
{
_ipaddr = addr;
}
public void setInetAddress( InetAddress address )
{
_inetAddress = address;
}
public void setPort( int port )
{
_port = port;
}
public void setCommString( String communityString )
{
_commString = communityString;
}
public void setCaching( boolean value )
{
_caching = value;
}
public void setXPath( String defXPath )
{
_xPath = defXPath;
}
public String getIPaddr()
{
return _ipaddr;
}
public InetAddress getInetAddress()
{
return _inetAddress;
}
public int getPort()
{
return _port;
}
public String getCommString()
{
return _commString;
}
public boolean isCacheRequest()
{
return _caching;
}
public String getXPath()
{
return _xPath;
}
public Document getResultDocument()
{
return _resDocument;
}
/**
parses the private String _xPath and resolves the
corresponding GwComplexTypes calling
MibRepositoryHandler.getTypes(String name). Results are stored in
private Vector _GwComplexTypeVector
@param repHandler the MibRepositoryHandler used to create
the GwComplexTypes. */
private void resolveTypes( MibRepositoryHandler repHandler )
{
StringTokenizer strtok = new StringTokenizer( _xPath.toString(), "|");
String currToken = "";
while( strtok.hasMoreElements() )
{
currToken = strtok.nextToken().trim();
int i = 0;
while ( currToken.charAt( i ) == '(' ||
currToken.charAt( i ) == '/' )
{
i++;
}
currToken = currToken.substring( i );
i = currToken.length() - 1;
boolean charFound = false;
while ( i >= 0 && !charFound )
{
if ( currToken.charAt( i ) != ')' && currToken.charAt( i ) != ' ' )
charFound = true;
i--;
}
String singleXPath = currToken.substring( 0, i + 2 );
i = 0;
while ( i < currToken.length() )
{
if ( currToken.charAt( i ) == '/' ||
currToken.charAt( i ) == '[' ||
currToken.charAt( i ) == ')' )
{
currToken = currToken.substring( 0, i ).trim();
break;
}
i++;
}
Vector types = repHandler.getTypes( currToken );
if ( types != null )
{
Iterator iterator = types.iterator();
while ( iterator.hasNext() )
{
GwComplexType type = ( GwComplexType )iterator.next();
type.setXPath( singleXPath );
_GwComplexTypeVector.add( type );
}
}
}
}
/**
adds the XML-representation of a requested SNMP-table to the submitted XML-Element.
Values of the table-objects are requested using getnext
@param currComplexType the requested table-type @param snmpHandler handler used for SNMP-getnext-requests @param parent XML-Element to which the content is added @throws SnmpAccessException */
private void buildTable( GwComplexType currComplexType,
SnmpHandler snmpHandler,
Element parent ) throws SnmpAccessException
{
GwElement typeElement;
EnumElement enumElement;
// check if there is something to request
if ( !( currComplexType._typeElements.isEmpty()
&& currComplexType._typeAttributes.isEmpty() ) )
{
while ( true )
{
// request elements
for ( Iterator typeIter = currComplexType._typeElements.iterator(); typeIter.hasNext(); )
{
typeElement = ( GwElement )typeIter.next();
typeElement.setExecutionResult(
snmpHandler.getNextRequest( typeElement.getOid().toString() ) );
typeElement.setOid( typeElement.getExecutionResult().getOid() );
}
// request attributes
for ( Iterator typeIter = currComplexType._typeAttributes.iterator(); typeIter.hasNext(); )
{
typeElement = ( GwElement )typeIter.next();
typeElement.setExecutionResult(
snmpHandler.getNextRequest( typeElement.getOid().toString() ) );
typeElement.setOid( typeElement.getExecutionResult().getOid() );
}
// last request ran over table, do not persist it and break
if ( !currComplexType.allTypeOidsPrefixed() )
break;
// persist tablerow
else
{
Element currTableElement = parent.addElement( currComplexType.getName() );
// adding elements
for ( Iterator typeIter = currComplexType._typeElements.iterator(); typeIter.hasNext(); )
{
typeElement = ( GwElement )typeIter.next();
String data = typeElement.getEncodedExecutionResult();
Element currChild = currTableElement.addElement( typeElement.getName() );
currChild.setText( data );
}
// adding attributes
for ( Iterator typeIter = currComplexType._typeAttributes.iterator(); typeIter.hasNext(); )
{
typeElement = ( GwElement )typeIter.next();
String data = typeElement.getEncodedExecutionResult();
Element currAttr = currTableElement.addAttribute( typeElement.getName(), data );
}
}
}
}
}
/**
adds the XML-representation of a requested SNMP-scalargroup to the submitted
XML-Element. Values of the scalar-objects are requested using get.
@param currComplexType the requested scalargroup-type
@param snmpHandler handler used for SNMP-get-requests
@param context XML-Element to which the content is added
@throws SnmpAccessException
*/
private void buildSequence( GwComplexType currComplexType,
SnmpHandler snmpHandler,
Element context ) throws SnmpAccessException
{
GwElement typeElement;
EnumElement enumElement;
Element currComplexTypeElement = context.addElement( currComplexType.getName() );
for ( Iterator typeIter = currComplexType._typeElements.iterator(); typeIter.hasNext(); )
{
typeElement = ( GwElement )typeIter.next();
try
{
typeElement.setExecutionResult(
snmpHandler.getRequest( typeElement.getOid().toString()+".0" ) );
}
catch( SnmpAccessException e )
{
break;
}
Element currChild = currComplexTypeElement.addElement( typeElement.getName() );
String data = typeElement.getEncodedExecutionResult();
currChild.setText( data );
}
}
/**
adds XML-Elements >snmp-data<>context ... < to
document with proper attributes of the >context ... <
-Element. @param document the XML-document the elements are added to @return Element the reference to the >context ... <-Element */
private Element buildDataDocument( Document document )
{
Element data = document.addElement( "snmp-data" );
Element context = data.addElement( GatewayConf.GET_AGENTELEMENT );
context.addAttribute( GatewayConf.IPADDR, _ipaddr );
context.addAttribute( GatewayConf.HOSTNAME, _inetAddress.getCanonicalHostName() );
context.addAttribute( GatewayConf.PORT, Integer.toString( _port ) );
if ( _caching )
context.addAttribute( GatewayConf.CACHING, "yes" );
else
context.addAttribute( GatewayConf.CACHING, "no" );
context.addAttribute( GatewayConf.COMM_STR, _commString );
context.addAttribute( GatewayConf.TIME, GwDate.getCurrent() );
return context;
}
/**
adds an XML-Element >context ... < to
document with proper attributes of the >context ... <
-Element including the time-attribute.
@param document the XML-document the element is added to @param timeString value of the time-attribute @return Element the reference to the >context ... <-Element */
private Element buildBaseDocument( Document document, String timeString )
{
Element context = document.addElement( GatewayConf.GET_AGENTELEMENT );
context.addAttribute( GatewayConf.IPADDR, _ipaddr );
context.addAttribute( GatewayConf.HOSTNAME, _inetAddress.getCanonicalHostName() );
context.addAttribute( GatewayConf.PORT, Integer.toString( _port ) );
if ( _caching )
context.addAttribute( GatewayConf.CACHING, "yes" );
else
context.addAttribute( GatewayConf.CACHING, "no" );
context.addAttribute( GatewayConf.COMM_STR, _commString );
context.addAttribute( GatewayConf.TIME, timeString );
return context;
}
/**
Executes the represented get-request. Steps are:
1. Obtaining whole tables or scalargroups either from the cache or by calling
methods buildTable or buildSequence.
2. Adding newly requested data to the cache.
3. Executing XPath-expressions requested in requeststring.
4. Building result-document.
@param repHandler @return String debuginformation, not needed to evaluate @throws RequestExecutionException */
public String execute( MibRepositoryHandler repHandler ) throws RequestExecutionException
{
if( ! _ipaddr.equals( _inetAddress.getHostAddress() ) )
{
Element faultyContext = buildDataDocument( _resDocument );
return( "IP-Adresses do not match" );
}
resolveTypes( repHandler );
String debugstr = "";
int[] timeout = new int[ 1 ];
timeout[ 0 ] = 1000;
GwComplexType currComplexType;
SnmpHandler snmpHandler = new SnmpHandler( "Agent",
_inetAddress,
_port,
timeout,
_commString );
boolean resolvedFromCache;
try
{
snmpHandler.connect();
Element context = buildDataDocument( _resDocument );
//execute each GwComplexType
for ( Iterator iterator = _GwComplexTypeVector.iterator(); iterator.hasNext(); )
{
resolvedFromCache = false;
currComplexType = ( GwComplexType )iterator.next();
Element tempContext;
if ( _caching )
{
CacheRequestResult result = CacheHandler.getFromCache( currComplexType, this );
if ( result != null )
{
tempContext = buildBaseDocument(
currComplexType.getTempDocument(), result.getDate() );
tempContext.appendContent( result.getResult() );
resolvedFromCache = true;
}
}
if ( !resolvedFromCache )
{
tempContext = buildBaseDocument(
currComplexType.getTempDocument(), GwDate.getCurrent() );
// table
if ( currComplexType.isTable() )
{
try
{
buildTable( currComplexType, snmpHandler, tempContext );
}
catch ( SnmpAccessException e )
{
throw new RequestExecutionException( "SNMP-Communication failed" );
}
}
// scalargroup
else
{
try
{
buildSequence( currComplexType, snmpHandler, tempContext );
}
catch ( SnmpAccessException e )
{
throw new RequestExecutionException( "SNMP-Communication failed" );
}
}
}
CacheHandler.cacheIn( currComplexType, this );
// execution of XPath-Expression
XPath path = currComplexType.getTempDocument().createXPath(
"/context/"+currComplexType.getXPath() );
List requestedNodes = path.selectNodes( currComplexType.getTempDocument() );
debugstr += "requestedNodes has " + requestedNodes.size() +
"elements, executed was XPath-expression: /context/"+
currComplexType.getXPath()+"
";
Element currParent = null;
Element currComplexTypeElement = null;
Element currTypeElement = null;
for ( Iterator iter = requestedNodes.iterator(); iter.hasNext(); )
{
Object next = iter.next();
//should never happen
if ( !( next instanceof Element ) )
{
debugstr += "Object found: "+ next.toString() +" not of type Element !
";
throw new RequestExecutionException( "An error occured during processing " +
"of request. Check for valid schema-" +
"files and try again" );
}
else
{
Element currElement = ( Element )next;
Element root = context.getParent().addNamespace(
currComplexType.getNamespacePrefix(),
currComplexType.getSchemaLocation() );
// ComplexType itself selected
if ( currElement.getName().equals( currComplexType.getName() ))
{
currComplexTypeElement = addElement(currElement,
currComplexType.getNamespacePrefix(),
currComplexType.getSchemaLocation(),
context );
for (Iterator currCmplxIter = currElement.elementIterator();
currCmplxIter.hasNext(); )
{
Element currSrcTypeElement = ( Element )currCmplxIter.next();
currTypeElement = addElement(currSrcTypeElement,
currComplexType.getNamespacePrefix(),
currComplexType.getSchemaLocation(),
currComplexTypeElement );
currTypeElement.setText( currSrcTypeElement.getText() );
}
}
// scalar selected
else if ( currElement.getParent().getName().equals( currComplexType.getName() ) )
{
if ( currParent == null || !currParent.equals( currElement.getParent() ) )
{
//parentNotAppended = false;
currComplexTypeElement = addElement(
currElement.getParent(),
currComplexType.getNamespacePrefix(),
currComplexType.getSchemaLocation(),
context );
currParent = currComplexTypeElement;
}
currTypeElement = addElement(currElement,
currComplexType.getNamespacePrefix(),
currComplexType.getSchemaLocation(),
currComplexTypeElement );
currTypeElement.setText( currElement.getText() );
}
// there is no second child layer
else
{
throw new RequestExecutionException( "XPath " +
currComplexType.getXPath() +
"not computable: " +
currElement.getParent().getName() +
" != "+currComplexType.getName());
}
}
}
}
return debugstr;
}
catch (SocketException e)
{
throw new RequestExecutionException( "SocketException occured " +
"during snmp-connect " + e.getMessage() );
}
}
/**
Adds an XML-Element tp parent
@param elem the Element to be added @param namespacePrefix the prefix the added Element should have @param schemaLocation the namespaceURI beloging to namespacePrefix @param parent the element elem should be added to @return Element the reference of the added Element */
private Element addElement( Element elem,
String namespacePrefix,
String schemaLocation,
Element parent )
{
Element res = parent.addElement( QName.get( elem.getName(),
namespacePrefix,
schemaLocation ) );
res.appendAttributes( elem );
return res;
}
/**
writes textual representation of this request to writer for debugging
*/
public void dump( PrintWriter writer )
{
Iterator iterator = _GwComplexTypeVector.iterator();
GwComplexType currCmplxType;
GwElement typeElement;
EnumElement enumElement;
OutputFormat outputformat = new OutputFormat( " ", true );
XMLWriter xmlWriter = new XMLWriter( writer, outputformat );
writer.println(" parsed complex types from xpath: " + _xPath + "
");
while ( iterator.hasNext() )
{
currCmplxType = ( GwComplexType )iterator.next();
writer.println( "Name: " + currCmplxType.getName() + "
" );
writer.println( "OID: " +currCmplxType.getOid() + "
" );
writer.println( "Type: " +currCmplxType.getType() + "
" );
writer.println("ELEMENTSCOUNT: "+currCmplxType._typeElements.size() );
for ( Iterator typeIter = currCmplxType._typeElements.iterator(); typeIter.hasNext(); )
{
typeElement = (GwElement)typeIter.next();
writer.println( typeElement.dump() );
}
writer.println("ATTRIBUTESCOUNT: "+currCmplxType._typeAttributes.size() );
for ( Iterator typeIter = currCmplxType._typeAttributes.iterator(); typeIter.hasNext(); )
{
typeElement = (GwElement)typeIter.next();
writer.println( typeElement.dump() );
}
try
{
xmlWriter.write( currCmplxType.getTempDocument() );
}
catch ( Throwable th )
{
writer.println("Exc during dump-write: "+th.toString());
}
}
try
{
xmlWriter.write( _resDocument );
}
catch ( Throwable th )
{
writer.println("Exc during dump-write: "+th.toString());
}
}
}