KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jmx > snmp > daemon > SnmpSubRequestHandler


1 /*
2  * @(#)file SnmpSubRequestHandler.java
3  * @(#)author Sun Microsystems, Inc.
4  * @(#)version 4.37
5  * @(#)date 08/02/09
6  *
7  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
8  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
9  *
10  */

11
12
13 package com.sun.jmx.snmp.daemon;
14
15
16
17 // java import
18
//
19
import java.util.Vector JavaDoc;
20
21 // jmx imports
22
//
23
import com.sun.jmx.snmp.SnmpPdu;
24 import com.sun.jmx.snmp.SnmpVarBind;
25 import com.sun.jmx.snmp.SnmpDefinitions;
26 import com.sun.jmx.snmp.SnmpStatusException;
27 import com.sun.jmx.snmp.SnmpEngine;
28
29 // RI imports
30
//
31
import com.sun.jmx.trace.Trace;
32
33 // SNMP Runtime import
34
//
35
import com.sun.jmx.snmp.agent.SnmpMibAgent;
36 import com.sun.jmx.snmp.agent.SnmpMibRequest;
37 import com.sun.jmx.snmp.ThreadContext;
38 import com.sun.jmx.snmp.internal.SnmpIncomingRequest;
39
40 class SnmpSubRequestHandler implements SnmpDefinitions, Runnable JavaDoc {
41     
42     protected SnmpIncomingRequest incRequest = null;
43     protected SnmpEngine engine = null;
44     /**
45      * V3 enabled Adaptor. Each Oid is added using updateRequest method.
46      */

47     protected SnmpSubRequestHandler(SnmpEngine engine,
48                     SnmpIncomingRequest incRequest,
49                     SnmpMibAgent agent,
50                     SnmpPdu req) {
51         this(agent, req);
52     init(engine, incRequest);
53     }
54     
55     /**
56      * V3 enabled Adaptor.
57      */

58     protected SnmpSubRequestHandler(SnmpEngine engine,
59                     SnmpIncomingRequest incRequest,
60                     SnmpMibAgent agent,
61                     SnmpPdu req,
62                     boolean nouse) {
63         this(agent, req, nouse);
64     init(engine, incRequest);
65     }
66     /**
67      * SNMP V1/V2 . To be called with updateRequest.
68      */

69     protected SnmpSubRequestHandler(SnmpMibAgent agent, SnmpPdu req) {
70         
71         dbgTag = makeDebugTag();
72         if (isTraceOn()) {
73             trace("constructor", "creating instance for request " + String.valueOf(req.requestId));
74         }
75     
76         version= req.version;
77         type= req.type;
78         this.agent= agent;
79     
80     // We get a ref on the pdu in order to pass it to SnmpMibRequest.
81
reqPdu = req;
82     
83         //Pre-allocate room for storing varbindlist and translation table.
84
//
85
int length= req.varBindList.length;
86         translation= new int[length];
87         varBind= new NonSyncVector(length);
88     }
89
90     /**
91      * SNMP V1/V2 The constuctor initialize the subrequest with the whole varbind list contained
92      * in the original request.
93      */

94     protected SnmpSubRequestHandler(SnmpMibAgent agent,
95                     SnmpPdu req,
96                     boolean nouse) {
97         this(agent,req);
98     
99         // The translation table is easy in this case ...
100
//
101
int max= translation.length;
102         SnmpVarBind[] list= req.varBindList;
103         for(int i=0; i < max; i++) {
104             translation[i]= i;
105             ((NonSyncVector)varBind).addNonSyncElement(list[i]);
106         }
107     }
108
109     SnmpMibRequest createMibRequest(Vector JavaDoc vblist,
110                     int protocolVersion,
111                     Object JavaDoc userData) {
112
113     // This is an optimization:
114
// The SnmpMibRequest created in the check() phase is
115
// reused in the set() phase.
116
//
117
if (type == pduSetRequestPdu && mibRequest != null)
118         return mibRequest;
119     
120     //This is a request comming from an SnmpV3AdaptorServer.
121
//Full power.
122
SnmpMibRequest result = null;
123     if(incRequest != null) {
124         result = SnmpMibAgent.newMibRequest(engine,
125                         reqPdu,
126                         vblist,
127                         protocolVersion,
128                         userData,
129                         incRequest.getPrincipal(),
130                         incRequest.getSecurityLevel(),
131                         incRequest.getSecurityModel(),
132                         incRequest.getContextName(),
133                         incRequest.getAccessContext());
134     } else {
135         result = SnmpMibAgent.newMibRequest(reqPdu,
136                         vblist,
137                         protocolVersion,
138                         userData);
139     }
140     // If we're doing the check() phase, we store the SnmpMibRequest
141
// so that we can reuse it in the set() phase.
142
//
143
if (type == pduWalkRequest)
144         mibRequest = result;
145
146     return result;
147     }
148
149     void setUserData(Object JavaDoc userData) {
150     data = userData;
151     }
152
153     public void run() {
154     
155         try {
156         final ThreadContext oldContext =
157         ThreadContext.push("SnmpUserData",data);
158         try {
159         switch(type) {
160         case pduGetRequestPdu:
161             // Invoke a get operation
162
//
163
if (isTraceOn()) {
164             trace("run", "[" + Thread.currentThread() +
165                   "]:get operation on " + agent.getMibName());
166             }
167         
168             agent.get(createMibRequest(varBind,version,data));
169             break;
170     
171         case pduGetNextRequestPdu:
172             if (isTraceOn()) {
173             trace("run", "[" + Thread.currentThread() +
174                   "]:getNext operation on " + agent.getMibName());
175             }
176             //#ifdef DEBUG
177
agent.getNext(createMibRequest(varBind,version,data));
178             break;
179             
180         case pduSetRequestPdu:
181             if (isTraceOn()) {
182             trace("run", "[" + Thread.currentThread() +
183                   "]:set operation on " + agent.getMibName());
184             }
185             agent.set(createMibRequest(varBind,version,data));
186             break;
187             
188         case pduWalkRequest:
189             if (isTraceOn()) {
190             trace("run", "[" + Thread.currentThread() +
191                   "]:check operation on " + agent.getMibName());
192             }
193             agent.check(createMibRequest(varBind,version,data));
194             break;
195             
196         default:
197             if (isDebugOn()) {
198             debug("run", "[" + Thread.currentThread() +
199                   "]:unknown operation (" + type + ") on " +
200                   agent.getMibName());
201             }
202             errorStatus= snmpRspGenErr;
203             errorIndex= 1;
204             break;
205             
206         }// end of switch
207

208         } finally {
209         ThreadContext.restore(oldContext);
210         }
211     } catch(SnmpStatusException x) {
212         errorStatus = x.getStatus() ;
213         errorIndex= x.getErrorIndex();
214         if (isDebugOn()) {
215         debug("run", "[" + Thread.currentThread() +
216               "]:an Snmp error occured during the operation");
217         debug("run", x);
218         }
219     }
220     catch(Exception JavaDoc x) {
221         errorStatus = SnmpDefinitions.snmpRspGenErr ;
222         if (isTraceOn()) {
223         trace("run", "[" + Thread.currentThread() +
224               "]:a generic error occured during the operation");
225         }
226         if (isDebugOn()) {
227         debug("run", "Error is: " + x);
228         debug("run", x);
229         }
230     }
231     if (isTraceOn()) {
232         trace("run", "[" + Thread.currentThread() +
233           "]:operation completed");
234     }
235     }
236     
237     // -------------------------------------------------------------
238
//
239
// This function does a best-effort to map global error status
240
// to SNMP v1 valid global error status.
241
//
242
// An SnmpStatusException can contain either:
243
// <li> v2 local error codes (that should be stored in the varbind)</li>
244
// <li> v2 global error codes </li>
245
// <li> v1 global error codes </li>
246
//
247
// v2 local error codes (noSuchInstance, noSuchObject) are
248
// transformed in a global v1 snmpRspNoSuchName error.
249
//
250
// v2 global error codes are transformed in the following way:
251
//
252
// If the request was a GET/GETNEXT then either
253
// snmpRspNoSuchName or snmpRspGenErr is returned.
254
//
255
// Otherwise:
256
// snmpRspNoAccess, snmpRspInconsistentName
257
// => snmpRspNoSuchName
258
// snmpRspAuthorizationError, snmpRspNotWritable, snmpRspNoCreation
259
// => snmpRspReadOnly (snmpRspNoSuchName for GET/GETNEXT)
260
// snmpRspWrong*
261
// => snmpRspBadValue (snmpRspNoSuchName for GET/GETNEXT)
262
// snmpRspResourceUnavailable, snmpRspRspCommitFailed,
263
// snmpRspUndoFailed
264
// => snmpRspGenErr
265
//
266
// -------------------------------------------------------------
267
//
268
static final int mapErrorStatusToV1(int errorStatus, int reqPduType) {
269     // Map v2 codes onto v1 codes
270
//
271
if (errorStatus == SnmpDefinitions.snmpRspNoError)
272             return SnmpDefinitions.snmpRspNoError;
273
274         if (errorStatus == SnmpDefinitions.snmpRspGenErr)
275             return SnmpDefinitions.snmpRspGenErr;
276
277         if (errorStatus == SnmpDefinitions.snmpRspNoSuchName)
278             return SnmpDefinitions.snmpRspNoSuchName;
279     
280     if ((errorStatus == SnmpStatusException.noSuchInstance) ||
281         (errorStatus == SnmpStatusException.noSuchObject) ||
282         (errorStatus == SnmpDefinitions.snmpRspNoAccess) ||
283         (errorStatus == SnmpDefinitions.snmpRspInconsistentName) ||
284         (errorStatus == SnmpDefinitions.snmpRspAuthorizationError)){
285         
286         return SnmpDefinitions.snmpRspNoSuchName;
287         
288     } else if ((errorStatus ==
289             SnmpDefinitions.snmpRspAuthorizationError) ||
290            (errorStatus == SnmpDefinitions.snmpRspNotWritable)) {
291         
292         if (reqPduType == SnmpDefinitions.pduWalkRequest)
293         return SnmpDefinitions.snmpRspReadOnly;
294         else
295         return SnmpDefinitions.snmpRspNoSuchName;
296         
297     } else if ((errorStatus == SnmpDefinitions.snmpRspNoCreation)) {
298         
299         return SnmpDefinitions.snmpRspNoSuchName;
300
301     } else if ((errorStatus == SnmpDefinitions.snmpRspWrongType) ||
302            (errorStatus == SnmpDefinitions.snmpRspWrongLength) ||
303            (errorStatus == SnmpDefinitions.snmpRspWrongEncoding) ||
304            (errorStatus == SnmpDefinitions.snmpRspWrongValue) ||
305            (errorStatus == SnmpDefinitions.snmpRspWrongLength) ||
306            (errorStatus ==
307             SnmpDefinitions.snmpRspInconsistentValue)) {
308         
309         if ((reqPduType == SnmpDefinitions.pduSetRequestPdu) ||
310         (reqPduType == SnmpDefinitions.pduWalkRequest))
311         return SnmpDefinitions.snmpRspBadValue;
312         else
313         return SnmpDefinitions.snmpRspNoSuchName;
314         
315     } else if ((errorStatus ==
316             SnmpDefinitions.snmpRspResourceUnavailable) ||
317            (errorStatus ==
318             SnmpDefinitions.snmpRspCommitFailed) ||
319            (errorStatus == SnmpDefinitions.snmpRspUndoFailed)) {
320         
321         return SnmpDefinitions.snmpRspGenErr;
322         
323     }
324
325     // At this point we should have a V1 error code
326
//
327
if (errorStatus == SnmpDefinitions.snmpRspTooBig)
328         return SnmpDefinitions.snmpRspTooBig;
329
330     if( (errorStatus == SnmpDefinitions.snmpRspBadValue) ||
331         (errorStatus == SnmpDefinitions.snmpRspReadOnly)) {
332         if ((reqPduType == SnmpDefinitions.pduSetRequestPdu) ||
333         (reqPduType == SnmpDefinitions.pduWalkRequest))
334         return errorStatus;
335         else
336         return SnmpDefinitions.snmpRspNoSuchName;
337     }
338
339     // We have a snmpRspGenErr, or something which is not defined
340
// in RFC1905 => return a snmpRspGenErr
341
//
342
return SnmpDefinitions.snmpRspGenErr;
343
344     }
345
346     // -------------------------------------------------------------
347
//
348
// This function does a best-effort to map global error status
349
// to SNMP v2 valid global error status.
350
//
351
// An SnmpStatusException can contain either:
352
// <li> v2 local error codes (that should be stored in the varbind)</li>
353
// <li> v2 global error codes </li>
354
// <li> v1 global error codes </li>
355
//
356
// v2 local error codes (noSuchInstance, noSuchObject)
357
// should not raise this level: they should have been stored in the
358
// varbind earlier. If they, do there is nothing much we can do except
359
// to transform them into:
360
// <li> a global snmpRspGenErr (if the request is a GET/GETNEXT) </li>
361
// <li> a global snmpRspNoSuchName otherwise. </li>
362
//
363
// v2 global error codes are transformed in the following way:
364
//
365
// If the request was a GET/GETNEXT then snmpRspGenErr is returned.
366
// (snmpRspGenErr is the only global error that is expected to be
367
// raised by a GET/GETNEXT request).
368
//
369
// Otherwise the v2 code itself is returned
370
//
371
// v1 global error codes are transformed in the following way:
372
//
373
// snmpRspNoSuchName
374
// => snmpRspNoAccess (snmpRspGenErr for GET/GETNEXT)
375
// snmpRspReadOnly
376
// => snmpRspNotWritable (snmpRspGenErr for GET/GETNEXT)
377
// snmpRspBadValue
378
// => snmpRspWrongValue (snmpRspGenErr for GET/GETNEXT)
379
//
380
// -------------------------------------------------------------
381
//
382
static final int mapErrorStatusToV2(int errorStatus, int reqPduType) {
383     // Map v1 codes onto v2 codes
384
//
385
if (errorStatus == SnmpDefinitions.snmpRspNoError)
386             return SnmpDefinitions.snmpRspNoError;
387
388         if (errorStatus == SnmpDefinitions.snmpRspGenErr)
389             return SnmpDefinitions.snmpRspGenErr;
390
391         if (errorStatus == SnmpDefinitions.snmpRspTooBig)
392             return SnmpDefinitions.snmpRspTooBig;
393
394     // For get / getNext / getBulk the only global error
395
// (PDU-level) possible is genErr.
396
//
397
if ((reqPduType != SnmpDefinitions.pduSetRequestPdu) &&
398         (reqPduType != SnmpDefinitions.pduWalkRequest)) {
399         if(errorStatus == SnmpDefinitions.snmpRspAuthorizationError)
400         return errorStatus;
401         else
402         return SnmpDefinitions.snmpRspGenErr;
403     }
404
405     // Map to noSuchName
406
// if ((errorStatus == SnmpDefinitions.snmpRspNoSuchName) ||
407
// (errorStatus == SnmpStatusException.noSuchInstance) ||
408
// (errorStatus == SnmpStatusException.noSuchObject))
409
// return SnmpDefinitions.snmpRspNoSuchName;
410

411     // SnmpStatusException.noSuchInstance and
412
// SnmpStatusException.noSuchObject can't happen...
413

414     if (errorStatus == SnmpDefinitions.snmpRspNoSuchName)
415         return SnmpDefinitions.snmpRspNoAccess;
416
417     // Map to notWritable
418
if (errorStatus == SnmpDefinitions.snmpRspReadOnly)
419         return SnmpDefinitions.snmpRspNotWritable;
420
421     // Map to wrongValue
422
if (errorStatus == SnmpDefinitions.snmpRspBadValue)
423         return SnmpDefinitions.snmpRspWrongValue;
424     
425     // Other valid V2 codes
426
if ((errorStatus == SnmpDefinitions.snmpRspNoAccess) ||
427         (errorStatus == SnmpDefinitions.snmpRspInconsistentName) ||
428         (errorStatus == SnmpDefinitions.snmpRspAuthorizationError) ||
429         (errorStatus == SnmpDefinitions.snmpRspNotWritable) ||
430         (errorStatus == SnmpDefinitions.snmpRspNoCreation) ||
431         (errorStatus == SnmpDefinitions.snmpRspWrongType) ||
432         (errorStatus == SnmpDefinitions.snmpRspWrongLength) ||
433         (errorStatus == SnmpDefinitions.snmpRspWrongEncoding) ||
434         (errorStatus == SnmpDefinitions.snmpRspWrongValue) ||
435         (errorStatus == SnmpDefinitions.snmpRspWrongLength) ||
436         (errorStatus == SnmpDefinitions.snmpRspInconsistentValue) ||
437         (errorStatus == SnmpDefinitions.snmpRspResourceUnavailable) ||
438         (errorStatus == SnmpDefinitions.snmpRspCommitFailed) ||
439         (errorStatus == SnmpDefinitions.snmpRspUndoFailed))
440         return errorStatus;
441
442     // Ivalid V2 code => genErr
443
return SnmpDefinitions.snmpRspGenErr;
444     }
445     
446     static final int mapErrorStatus(int errorStatus,
447                     int protocolVersion,
448                     int reqPduType) {
449         if (errorStatus == SnmpDefinitions.snmpRspNoError)
450             return SnmpDefinitions.snmpRspNoError;
451     
452         // Too bad, an error occurs ... we need to translate it ...
453
//
454
if (protocolVersion == SnmpDefinitions.snmpVersionOne)
455         return mapErrorStatusToV1(errorStatus,reqPduType);
456         if (protocolVersion == SnmpDefinitions.snmpVersionTwo ||
457         protocolVersion == SnmpDefinitions.snmpVersionThree)
458         return mapErrorStatusToV2(errorStatus,reqPduType);
459     
460         return SnmpDefinitions.snmpRspGenErr;
461     }
462
463     /**
464      * The method returns the error status of the operation.
465      * The method takes into account the protocol version.
466      */

467     protected int getErrorStatus() {
468         if (errorStatus == snmpRspNoError)
469             return snmpRspNoError;
470         
471         return mapErrorStatus(errorStatus,version,type);
472     }
473     
474     /**
475      * The method returns the error index as a position in the var bind list.
476      * The value returned by the method corresponds to the index in the original
477      * var bind list as received by the SNMP protocol adaptor.
478      */

479     protected int getErrorIndex() {
480         if (errorStatus == snmpRspNoError)
481             return -1;
482     
483         // An error occurs. We need to be carefull because the index
484
// we are getting is a valid SNMP index (so range starts at 1).
485
// FIX ME: Shall we double-check the range here ?
486
// The response is : YES :
487
if ((errorIndex == 0) || (errorIndex == -1))
488             errorIndex = 1;
489     
490         return translation[errorIndex -1];
491     }
492   
493     /**
494      * The method updates the varbind list of the subrequest.
495      */

496     protected void updateRequest(SnmpVarBind var, int pos) {
497         int size= varBind.size();
498         translation[size]= pos;
499         varBind.addElement(var);
500     }
501   
502     /**
503      * The method updates a given var bind list with the result of a
504      * previsouly invoked operation.
505      * Prior to calling the method, one must make sure that the operation was
506      * successful. As such the method getErrorIndex or getErrorStatus should be
507      * called.
508      */

509     protected void updateResult(SnmpVarBind[] result) {
510   
511     if (result == null) return;
512         final int max=varBind.size();
513     final int len=result.length;
514         for(int i= 0; i< max ; i++) {
515         // bugId 4641694: must check position in order to avoid
516
// ArrayIndexOutOfBoundException
517
final int pos=translation[i];
518         if (pos < len) {
519         result[pos] =
520             (SnmpVarBind)((NonSyncVector)varBind).elementAtNonSync(i);
521         } else {
522         debug("updateResult","Position `"+pos+"' is out of bound...");
523         }
524         }
525     }
526
527     private void init(SnmpEngine engine,
528               SnmpIncomingRequest incRequest) {
529     this.incRequest = incRequest;
530     this.engine = engine;
531     }
532     
533     protected boolean isTraceOn() {
534         return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_ADAPTOR_SNMP);
535     }
536
537     protected void trace(String JavaDoc clz, String JavaDoc func, String JavaDoc info) {
538         Trace.send(Trace.LEVEL_TRACE, Trace.INFO_ADAPTOR_SNMP, clz, func, info);
539     }
540
541     protected void trace(String JavaDoc func, String JavaDoc info) {
542         trace(dbgTag, func, info);
543     }
544     
545     protected boolean isDebugOn() {
546         return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP);
547     }
548
549     protected void debug(String JavaDoc clz, String JavaDoc func, String JavaDoc info) {
550         Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP, clz, func, info);
551     }
552
553     protected void debug(String JavaDoc func, Throwable JavaDoc t) {
554         Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP, dbgTag, func, t);
555     }
556
557     protected void debug(String JavaDoc func, String JavaDoc info) {
558         debug(dbgTag, func, info);
559     }
560     
561     protected String JavaDoc makeDebugTag() {
562         return "SnmpSubRequestHandler";
563     }
564     
565     // PRIVATE VARIABLES
566
//------------------
567

568     protected String JavaDoc dbgTag = null;
569     
570     /**
571      * Store the protocol version to handle
572      */

573     protected int version= snmpVersionOne;
574
575     /**
576      * Store the operation type. Remember if the type is Walk, it means
577      * that we have to invoke the check method ...
578      */

579     protected int type= 0;
580
581     /**
582      * Agent directly handled by the sub-request handler.
583      */

584     protected SnmpMibAgent agent;
585
586     /**
587      * Error status.
588      */

589     protected int errorStatus= snmpRspNoError;
590   
591     /**
592      * Index of error.
593      * A value of -1 means no error.
594      */

595     protected int errorIndex= -1;
596   
597     /**
598      * The varbind list specific to the current sub request.
599      * The vector must contain object of type SnmpVarBind.
600      */

601     protected Vector JavaDoc varBind;
602   
603     /**
604      * The array giving the index translation between the content of
605      * <VAR>varBind</VAR> and the varbind list as specified in the request.
606      */

607     protected int[] translation;
608
609     /**
610      * Contextual object allocated by the SnmpUserDataFactory.
611      **/

612     protected Object JavaDoc data;
613
614     /**
615      * The SnmpMibRequest that will be passed to the agent.
616      *
617      **/

618     private SnmpMibRequest mibRequest = null;
619     
620     /**
621      * The SnmpPdu that will be passed to the request.
622      *
623      **/

624     private SnmpPdu reqPdu = null;
625     
626     // All the methods of the Vector class are synchronized.
627
// Synchronization is a very expensive operation. In our case it is not always
628
// required...
629
//
630
class NonSyncVector extends Vector JavaDoc {
631     
632         public NonSyncVector(int size) {
633             super(size);
634         }
635     
636         final void addNonSyncElement(Object JavaDoc obj) {
637             ensureCapacity(elementCount + 1);
638             elementData[elementCount++] = obj;
639         }
640     
641         final Object JavaDoc elementAtNonSync(int index) {
642             return elementData[index];
643         }
644     };
645 }
646
Popular Tags