KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > snmp4j > agent > request > SnmpRequest


1 /*_############################################################################
2   _##
3   _## SNMP4J-Agent - SnmpRequest.java
4   _##
5   _## Copyright (C) 2005-2007 Frank Fock (SNMP4J.org)
6   _##
7   _## Licensed under the Apache License, Version 2.0 (the "License");
8   _## you may not use this file except in compliance with the License.
9   _## You may obtain a copy of the License at
10   _##
11   _## http://www.apache.org/licenses/LICENSE-2.0
12   _##
13   _## Unless required by applicable law or agreed to in writing, software
14   _## distributed under the License is distributed on an "AS IS" BASIS,
15   _## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   _## See the License for the specific language governing permissions and
17   _## limitations under the License.
18   _##
19   _##########################################################################*/

20
21 package org.snmp4j.agent.request;
22
23 import java.util.*;
24
25 import org.snmp4j.*;
26 import org.snmp4j.agent.security.*;
27 import org.snmp4j.mp.*;
28 import org.snmp4j.smi.*;
29 import org.snmp4j.agent.DefaultMOContextScope;
30 import org.snmp4j.agent.MOScope;
31 import org.snmp4j.agent.ManagedObject;
32 import org.snmp4j.log.LogAdapter;
33 import org.snmp4j.log.LogFactory;
34 import org.snmp4j.agent.mo.snmp.CoexistenceInfo;
35 import org.snmp4j.agent.MOQuery;
36
37 /**
38  * The <code>SnmpRequest</code> class implements requests from a SNMP source.
39  *
40  * @author Frank Fock
41  * @version 1.0
42  */

43 public class SnmpRequest extends AbstractRequest {
44
45   private static final LogAdapter logger =
46       LogFactory.getLogger(SnmpRequest.class);
47
48   public static final OctetString DEFAULT_CONTEXT = new OctetString();
49
50   private CommandResponderEvent requestEvent;
51   private CoexistenceInfo coexistenceInfo;
52
53   private PDU response;
54   private OctetString viewName;
55
56   private static int nextTransactionID = 0;
57
58   public SnmpRequest(CommandResponderEvent request, CoexistenceInfo cinfo) {
59     this.requestEvent = request;
60     this.coexistenceInfo = cinfo;
61     correctRequestValues();
62     this.transactionID = nextTransactionID();
63   }
64
65   public static int nextTransactionID() {
66     return nextTransactionID++;
67   }
68
69   protected synchronized void setupSubRequests() {
70     int capacity = requestEvent.getPDU().size();
71     int totalRepetitions = (requestEvent.getPDU() instanceof PDUv1) ? 0 :
72         repeaterRowSize*requestEvent.getPDU().getMaxRepetitions();
73     subrequests = new ArrayList(capacity + totalRepetitions);
74     if (response == null) {
75       response = createResponse();
76     }
77     for (int i=0; i<requestEvent.getPDU().size(); i++) {
78       SnmpSubRequest subReq =
79           new SnmpSubRequest(requestEvent.getPDU().get(i), i);
80       addSubRequest(subReq);
81     }
82     if (logger.isDebugEnabled()) {
83       logger.debug("SnmpSubRequests initialized: "+subrequests);
84     }
85   }
86
87   /**
88    * Returns the number of repetitions that are complete.
89    * @return
90    * the minimum <code>r</code> for which all
91    * <code>i&lt;r*(pduSize-nonRepeaters)</code> {@link SubRequest}s
92    * returned by {@link #get(int i)} return true on
93    * {@link SubRequest#isComplete()}.
94    */

95   public synchronized int getCompleteRepetitions() {
96     int i = 0;
97     for (Iterator it = subrequests.iterator(); it.hasNext(); i++) {
98       SnmpSubRequest sreq = (SnmpSubRequest) it.next();
99       if (!sreq.isComplete()) {
100         return i/getRepeaterCount();
101       }
102     }
103     return i/getRepeaterCount();
104   }
105
106   public int getMaxRepetitions() {
107     return requestEvent.getPDU().getMaxRepetitions();
108   }
109
110   public int getNonRepeaters() {
111     return requestEvent.getPDU().getNonRepeaters();
112   }
113
114   private void addSubRequest(SubRequest subReq) {
115     subrequests.add(subReq);
116     response.add(subReq.getVariableBinding());
117   }
118
119   protected int getMaxPhase() {
120     return (is2PC()) ? PHASE_2PC_CLEANUP : PHASE_1PC;
121   }
122
123 /*
124   public int indexOf(OID oid) {
125     /**@todo Diese org.snmp4j.agent.request.Request-Methode implementieren/
126     throw new java.lang.UnsupportedOperationException("Methode indexOf() noch nicht implementiert.");
127   }
128
129   public int indexOf(OID oid, int startFrom) {
130
131   }
132 */

133
134   public int size() {
135     return requestEvent.getPDU().size();
136   }
137
138   public Object JavaDoc getSource() {
139     return requestEvent;
140   }
141
142   public CommandResponderEvent getInitiatingEvent() {
143     return requestEvent;
144   }
145
146   public void setRequestEvent(CommandResponderEvent requestEvent) {
147     this.requestEvent = requestEvent;
148   }
149
150   protected void assignErrorStatus2Response() {
151     int errStatus = getErrorStatus();
152     if (requestEvent.getMessageProcessingModel() == MessageProcessingModel.MPv1) {
153       switch (errStatus) {
154         case SnmpConstants.SNMP_ERROR_NOT_WRITEABLE:
155         case SnmpConstants.SNMP_ERROR_NO_ACCESS:
156         case SnmpConstants.SNMP_ERROR_NO_CREATION:
157         case SnmpConstants.SNMP_ERROR_INCONSISTENT_NAME: {
158           response.setErrorStatus(SnmpConstants.SNMP_ERROR_NO_SUCH_NAME);
159           break;
160         }
161         case SnmpConstants.SNMP_ERROR_AUTHORIZATION_ERROR:
162         case SnmpConstants.SNMP_ERROR_RESOURCE_UNAVAILABLE:
163         case SnmpConstants.SNMP_ERROR_COMMIT_FAILED:
164         case SnmpConstants.SNMP_ERROR_UNDO_FAILED: {
165           response.setErrorStatus(SnmpConstants.SNMP_ERROR_GENERAL_ERROR);
166           break;
167         }
168         case SnmpConstants.SNMP_ERROR_WRONG_VALUE:
169         case SnmpConstants.SNMP_ERROR_WRONG_LENGTH:
170         case SnmpConstants.SNMP_ERROR_INCONSISTENT_VALUE:
171         case SnmpConstants.SNMP_ERROR_WRONG_TYPE: {
172           response.setErrorStatus(SnmpConstants.SNMP_ERROR_BAD_VALUE);
173           break;
174         }
175         default: {
176           response.setErrorStatus(errStatus);
177         }
178       }
179       for (int i=0; i<response.size(); i++) {
180         VariableBinding vb = response.get(i);
181         if (vb.isException()) {
182           response.setErrorStatus(PDU.noSuchName);
183           response.setErrorIndex(i+1);
184           response.set(i, new VariableBinding(vb.getOid()));
185           return;
186         }
187       }
188     }
189     else {
190       response.setErrorStatus(errStatus);
191     }
192     response.setErrorIndex(getErrorIndex());
193   }
194
195   private PDU createResponse() {
196     PDU resp = (PDU) requestEvent.getPDU().clone();
197     resp.clear();
198     resp.setType(PDU.RESPONSE);
199     resp.setRequestID(requestEvent.getPDU().getRequestID());
200     resp.setErrorIndex(0);
201     resp.setErrorStatus(PDU.noError);
202     return resp;
203   }
204
205   private void correctRequestValues() {
206     PDU request = requestEvent.getPDU();
207     if (!(request instanceof PDUv1)) {
208       if (request.getMaxRepetitions() < 0) {
209         request.setMaxRepetitions(0);
210       }
211       if (request.getNonRepeaters() < 0) {
212         request.setNonRepeaters(0);
213       }
214       repeaterStartIndex = request.getNonRepeaters();
215       repeaterRowSize =
216           Math.max(request.size() - repeaterStartIndex, 0);
217     }
218     else {
219       repeaterStartIndex = 0;
220       repeaterRowSize = request.size();
221     }
222   }
223
224   public PDU getResponsePDU() {
225     return (PDU) getResponse();
226   }
227
228   public Object JavaDoc getResponse() {
229     if (response == null) {
230       response = createResponse();
231     }
232     assignErrorStatus2Response();
233     return response;
234   }
235
236   /**
237    * iterator
238    *
239    * @return Iterator
240    */

241   public Iterator iterator() {
242     initSubRequests();
243     return new SnmpSubRequestIterator();
244   }
245
246   protected boolean is2PC() {
247     return (requestEvent.getPDU().getType() == PDU.SET);
248   }
249
250   public OctetString getContext() {
251     if (coexistenceInfo != null) {
252       return coexistenceInfo.getContextName();
253     }
254     else if (requestEvent.getPDU() instanceof ScopedPDU) {
255       return ((ScopedPDU)requestEvent.getPDU()).getContextName();
256     }
257     return DEFAULT_CONTEXT;
258   }
259
260   public OctetString getViewName() {
261     return viewName;
262   }
263
264   public void setViewName(OctetString viewName) {
265     this.viewName = viewName;
266   }
267
268   public int getSecurityLevel() {
269     return requestEvent.getSecurityLevel();
270   }
271
272   public int getSecurityModel() {
273     return requestEvent.getSecurityModel();
274   }
275
276   public OctetString getSecurityName() {
277     if (coexistenceInfo != null) {
278       return coexistenceInfo.getSecurityName();
279     }
280     return new OctetString(requestEvent.getSecurityName());
281   }
282
283   public int getViewType() {
284     return getViewType(requestEvent.getPDU().getType());
285   }
286
287   /**
288    * Returns the VACM view type for the supplied PDU type.
289    * @param pduType
290    * a PDU type.
291    * @return
292    * the corresponding VACM view type.
293    */

294   public static final int getViewType(int pduType) {
295     switch (pduType) {
296       case PDU.GETNEXT:
297       case PDU.GET:
298       case PDU.GETBULK: {
299         return VACM.VIEW_READ;
300       }
301       case PDU.INFORM:
302       case PDU.TRAP:
303       case PDU.V1TRAP: {
304         return VACM.VIEW_NOTIFY;
305       }
306       default: {
307         return VACM.VIEW_WRITE;
308       }
309     }
310   }
311
312   protected synchronized void addRepeaterSubRequest() {
313     int predecessorIndex = subrequests.size() - repeaterRowSize;
314     SnmpSubRequest sreq =
315         new SnmpSubRequest((SnmpSubRequest)subrequests.get(predecessorIndex),
316                            subrequests.size());
317     addSubRequest(sreq);
318   }
319
320   public int getErrorIndex() {
321     if (errorStatus == SnmpConstants.SNMP_ERROR_SUCCESS) {
322       return 0;
323     }
324     initSubRequests();
325     int index = 1;
326     for (Iterator it = subrequests.iterator(); it.hasNext(); index++) {
327       SubRequest sreq = (SubRequest) it.next();
328       if (sreq.getStatus().getErrorStatus() != SnmpConstants.SNMP_ERROR_SUCCESS) {
329         return index;
330       }
331     }
332     return 0;
333   }
334
335
336   public int getTransactionID() {
337     return transactionID;
338   }
339
340   public CoexistenceInfo getCoexistenceInfo() {
341     return coexistenceInfo;
342   }
343
344   /**
345    * Returns the last repetition row that is complete (regarding the number
346    * of elements in the row) before the given subrequest index.
347    * @param upperBoundIndex
348    * the maximum sub-request index within the row to return.
349    * @return
350    * a sub list of the sub-requests list that contains the row's elements.
351    * If no such row exists <code>null</code> is returned.
352    */

353   private List lastRow(int upperBoundIndex) {
354     if ((repeaterRowSize == 0) || (upperBoundIndex <= repeaterStartIndex)) {
355       return null;
356     }
357     int rows = (upperBoundIndex - repeaterStartIndex) / repeaterRowSize;
358     int startIndex = repeaterStartIndex + (repeaterRowSize*(rows-1));
359     int endIndex = repeaterStartIndex + (repeaterRowSize*rows);
360     if ((startIndex < repeaterStartIndex) || (endIndex > subrequests.size())) {
361       return null;
362     }
363     return subrequests.subList(startIndex, endIndex);
364   }
365
366   public int getMessageProcessingModel() {
367     return this.requestEvent.getMessageProcessingModel();
368   }
369
370   public int getRepeaterCount() {
371     PDU reqPDU = requestEvent.getPDU();
372     return Math.max(reqPDU.size() - reqPDU.getNonRepeaters(), 0);
373   }
374
375   public boolean isPhaseComplete() {
376     if (errorStatus == SnmpConstants.SNMP_ERROR_SUCCESS) {
377       initSubRequests();
378       for (Iterator it = subrequests.iterator(); it.hasNext(); ) {
379         SubRequest subreq = (SubRequest) it.next();
380         RequestStatus status = subreq.getStatus();
381         if (status.getErrorStatus() != SnmpConstants.SNMP_ERROR_SUCCESS) {
382           return true;
383         }
384         else if (!status.isPhaseComplete()) {
385           return false;
386         }
387       }
388     }
389     if (requestEvent.getPDU().getType() == PDU.GETBULK) {
390       SnmpSubRequestIterator it =
391           new SnmpSubRequestIterator(subrequests.size(), 1);
392       return !it.hasNext();
393     }
394     return true;
395   }
396
397   public boolean isBulkRequest() {
398     return (requestEvent.getPDU().getType() == PDU.GETBULK);
399   }
400
401   /**
402    *
403    * @author Frank Fock
404    * @version 1.0
405    */

406   public class SnmpSubRequestIterator implements SubRequestIterator {
407
408     private int cursor = 0;
409     private int increment = 1;
410     private boolean noAppending;
411
412     protected SnmpSubRequestIterator() {
413       this.cursor = 0;
414     }
415
416     protected SnmpSubRequestIterator(int offset, int increment) {
417       this.cursor = offset;
418       this.increment = increment;
419     }
420
421     protected void setNoAppending(boolean noAppending) {
422       this.noAppending = noAppending;
423     }
424
425     /**
426      * hasNext
427      *
428      * @return boolean
429      */

430     public boolean hasNext() {
431       synchronized (SnmpRequest.this) {
432         PDU reqPDU = requestEvent.getPDU();
433         if (reqPDU.getType() == PDU.GETBULK) {
434           if (noAppending && (cursor >= subrequests.size())) {
435             return false;
436           }
437           if (cursor < Math.min(reqPDU.size(), reqPDU.getNonRepeaters())) {
438             return true;
439           }
440           else {
441             if (cursor < reqPDU.getNonRepeaters() +
442                 reqPDU.getMaxRepetitions() * getRepeaterCount()) {
443               List lastRow = lastRow(cursor);
444               if (lastRow != null) {
445                 boolean allEndOfMibView = true;
446                 SubRequest sreq = null;
447                 for (Iterator it = lastRow.iterator(); it.hasNext(); ) {
448                   sreq = (SubRequest) it.next();
449                   if (sreq.getVariableBinding().getSyntax() !=
450                       SMIConstants.EXCEPTION_END_OF_MIB_VIEW) {
451                     allEndOfMibView = false;
452                     break;
453                   }
454                 }
455                 if (allEndOfMibView) {
456                   // truncate request if already more elements are there
457
if ((sreq != null) &&
458                       (sreq.getIndex() < subrequests.size())) {
459                     int lastElementIndex = sreq.getIndex();
460                     List tail = subrequests.subList(lastElementIndex + 1,
461                         subrequests.size());
462                     tail.clear();
463                     tail = response.getVariableBindings().
464                         subList(lastElementIndex + 1, response.size());
465                     tail.clear();
466                   }
467                   return false;
468                 }
469               }
470               return (response.getBERLength() <
471                       requestEvent.getMaxSizeResponsePDU());
472             }
473           }
474           return false;
475         }
476         return (cursor < reqPDU.size());
477       }
478     }
479
480     public SubRequest nextSubRequest() {
481       if (!hasNext()) {
482         throw new NoSuchElementException();
483       }
484       if ((requestEvent.getPDU().getType() == PDU.GETBULK) &&
485           (cursor >= subrequests.size())) {
486         while (cursor >= subrequests.size()) {
487           addRepeaterSubRequest();
488         }
489       }
490       SubRequest sreq = (SubRequest) subrequests.get(cursor);
491       cursor += increment;
492       return sreq;
493     }
494
495     public void remove() {
496       throw new UnsupportedOperationException JavaDoc("Remove is not supported "+
497                                               "on sub-requests");
498     }
499
500     public Object JavaDoc next() {
501       return nextSubRequest();
502     }
503
504     public boolean equals(Object JavaDoc other) {
505       if (other instanceof Request) {
506         return ((Request)other).getTransactionID() == getTransactionID();
507       }
508       return false;
509     }
510
511     public int hashCode() {
512       return getTransactionID();
513     }
514   }
515
516
517   /**
518    *
519    * @author Frank Fock
520    * @version 1.0
521    */

522   public class SnmpSubRequest
523       implements org.snmp4j.agent.request.SnmpSubRequest, RequestStatusListener {
524
525     private RequestStatus status;
526     private VariableBinding vb;
527     private Object JavaDoc undoValue;
528     private MOScope scope;
529     private ManagedObject targetMO;
530     private MOQuery query;
531     private int index;
532
533     private volatile Object JavaDoc userObject;
534
535     protected SnmpSubRequest(VariableBinding subrequest, int index) {
536       this.vb = subrequest;
537       this.index = index;
538       switch (requestEvent.getPDU().getType()) {
539         case PDU.GETBULK:
540         case PDU.GETNEXT: {
541           this.scope = getNextScope(this.vb.getOid());
542           break;
543         }
544         default: {
545           OID oid = this.vb.getOid();
546           this.scope = new DefaultMOContextScope(getContext(),
547                                                  oid, true, oid, true);
548         }
549       }
550       status = new RequestStatus();
551       status.addRequestStatusListener(this);
552       if (logger.isDebugEnabled()) {
553         logger.debug("Created subrequest "+index+" with scope "+scope+
554                      " from "+subrequest);
555       }
556     }
557
558     protected MOScope getNextScope(OID previousOID) {
559       return new DefaultMOContextScope(getContext(), previousOID, false,
560                                        null, false);
561     }
562
563     protected SnmpSubRequest(SnmpSubRequest predecessor, int index) {
564       this((VariableBinding)predecessor.getVariableBinding().clone(), index);
565 // Do not copy queries because they need to be updated externally only!
566
// this.query = predecessor.getQuery();
567
}
568
569     public Request getRequest() {
570       return SnmpRequest.this;
571     }
572
573     public RequestStatus getStatus() {
574       return status;
575     }
576
577     public VariableBinding getVariableBinding() {
578       return vb;
579     }
580
581     public void setStatus(RequestStatus status) {
582       this.status = status;
583     }
584
585     public Object JavaDoc getUndoValue() {
586       return undoValue;
587     }
588
589     public void setUndoValue(Object JavaDoc undoInformation) {
590       this.undoValue = undoInformation;
591     }
592
593     public void requestStatusChanged(RequestStatusEvent event) {
594       int newStatus = event.getStatus().getErrorStatus();
595       setErrorStatus(newStatus);
596       if (logger.isDebugEnabled() &&
597           (newStatus != SnmpConstants.SNMP_ERROR_SUCCESS)) {
598         new Exception JavaDoc("Error '"+
599                       PDU.toErrorStatusText(event.getStatus().getErrorStatus())+
600                       "' generated at: "+vb).printStackTrace();
601       }
602     }
603
604     public MOScope getScope() {
605       return scope;
606     }
607
608     public void completed() {
609       status.setPhaseComplete(true);
610     }
611
612     public boolean hasError() {
613       return getStatus().getErrorStatus() != SnmpConstants.SNMP_ERROR_SUCCESS;
614     }
615
616     public boolean isComplete() {
617       return status.isPhaseComplete();
618     }
619
620     public void setTargetMO(ManagedObject managedObject) {
621       this.targetMO = managedObject;
622     }
623
624     public ManagedObject getTargetMO() {
625       return targetMO;
626     }
627
628     public SnmpRequest getSnmpRequest() {
629       return SnmpRequest.this;
630     }
631
632     public void setErrorStatus(int errorStatus) {
633       SnmpRequest.this.setErrorStatus(errorStatus);
634     }
635
636     public int getIndex() {
637       return index;
638     }
639
640     public void setQuery(MOQuery query) {
641       this.query = query;
642     }
643
644     public MOQuery getQuery() {
645       return query;
646     }
647
648     public String JavaDoc toString() {
649       return getClass().getName()+"[scope="+scope+
650           ",vb="+vb+",status="+status+",query="+query+",index="+index+
651           ",targetMO="+targetMO+"]";
652     }
653
654     public SubRequestIterator repetitions() {
655       return repetitions(false);
656     }
657
658     private SubRequestIterator repetitions(boolean noAppending) {
659       initSubRequests();
660       if (isBulkRequest()) {
661         int repeaters = requestEvent.getPDU().size() -
662             requestEvent.getPDU().getNonRepeaters();
663         SnmpSubRequestIterator it =
664             new SnmpSubRequestIterator(getIndex(), repeaters);
665         it.setNoAppending(noAppending);
666         return it;
667       }
668       return new SubRequestIteratorSupport(Collections.EMPTY_LIST.iterator());
669     }
670
671     public void updateNextRepetition() {
672       if (!isBulkRequest()) {
673         return;
674       }
675       this.query = null;
676       SubRequestIterator repetitions = repetitions(true);
677       // skip this one
678
repetitions.next();
679       while (repetitions.hasNext()) {
680         SnmpSubRequest nsreq = (SnmpSubRequest) repetitions.nextSubRequest();
681         if ((getStatus().getErrorStatus() == PDU.noError) &&
682             (!this.vb.isException())) {
683           nsreq.query = null;
684           nsreq.scope = getNextScope(this.vb.getOid());
685           nsreq.getVariableBinding().setOid(this.vb.getOid());
686         }
687         else if (this.vb.isException()) {
688             nsreq.query = null;
689             nsreq.getVariableBinding().setOid(this.vb.getOid());
690             nsreq.getVariableBinding().setVariable(this.vb.getVariable());
691             nsreq.getStatus().setPhaseComplete(true);
692         }
693       }
694     }
695
696     public final int getErrorStatus() {
697       return getStatus().getErrorStatus();
698     }
699
700     public Object JavaDoc getUserObject() {
701       return userObject;
702     }
703
704     public void setUserObject(Object JavaDoc userObject) {
705       this.userObject = userObject;
706     }
707
708   }
709
710 }
711
712
Popular Tags