KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > snmp4j > PDU


1 /*_############################################################################
2   _##
3   _## SNMP4J - PDU.java
4   _##
5   _## Copyright 2003-2007 Frank Fock and Jochen Katz (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
22
23 package org.snmp4j;
24
25 import org.snmp4j.smi.*;
26 import org.snmp4j.asn1.*;
27 import java.io.IOException JavaDoc;
28 import java.io.OutputStream JavaDoc;
29 import java.util.Vector JavaDoc;
30 import org.snmp4j.smi.Integer32;
31 import org.snmp4j.mp.SnmpConstants;
32 import java.io.Serializable JavaDoc;
33
34 /**
35  * The <code>PDU</code> class represents a SNMP protocol data unit. The PDU
36  * version supported by the BER decoding and encoding methods of this class
37  * is v2.
38  * <p>
39  * The default PDU type is GET.
40  *
41  * @author Frank Fock
42  * @version 1.1
43  * @see PDUv1
44  * @see ScopedPDU
45  */

46 public class PDU implements BERSerializable, Serializable JavaDoc {
47
48   private static final long serialVersionUID = 7607672475629607472L;
49
50   /**
51    * Denotes a get PDU.
52    */

53   public static final int GET = (BER.ASN_CONTEXT | BER.ASN_CONSTRUCTOR | 0x0);
54   /**
55    * Denotes a getnext (search) PDU.
56    */

57   public static final int GETNEXT = (BER.ASN_CONTEXT | BER.ASN_CONSTRUCTOR | 0x1);
58   /**
59    * Denotes a response PDU.
60    */

61   public static final int RESPONSE = (BER.ASN_CONTEXT | BER.ASN_CONSTRUCTOR | 0x2);
62   /**
63    * Denotes a set PDU.
64    */

65   public static final int SET = (BER.ASN_CONTEXT | BER.ASN_CONSTRUCTOR | 0x3);
66   /**
67    * Denotes a SNMPv1 trap PDU. This type can only be used with instances of the
68    * {@link PDUv1} class.
69    */

70   public static final int V1TRAP = (BER.ASN_CONTEXT | BER.ASN_CONSTRUCTOR | 0x4);
71   /**
72    * Denotes a SNMPv2c/v3 getbulk PDU.
73    */

74   public static final int GETBULK = (BER.ASN_CONTEXT | BER.ASN_CONSTRUCTOR | 0x5);
75   /**
76    * Denotes a SNMPv2c/v3 inform PDU (unprecisely also known as a confirmed
77    * notification).
78    */

79   public static final int INFORM = (BER.ASN_CONTEXT | BER.ASN_CONSTRUCTOR | 0x6);
80   /**
81    * Denotes a SNMPv2c/v3 notification PDU (undistinguishable from
82    * {@link #TRAP}).
83    */

84   public static final int TRAP = (BER.ASN_CONTEXT | BER.ASN_CONSTRUCTOR | 0x7);
85   /**
86    * Denotes a SNMPv2c/v3 notification PDU (undistinguishable from
87    * {@link #NOTIFICATION}).
88    */

89   public static final int NOTIFICATION = TRAP;
90   /**
91    * Denotes a SNMPv3 report PDU.
92    */

93   public static final int REPORT = (BER.ASN_CONTEXT | BER.ASN_CONSTRUCTOR | 0x8);
94
95
96   // Error status constants
97

98   /**
99    * Operation success (no error).
100    */

101   public static final int noError = SnmpConstants.SNMP_ERROR_SUCCESS;
102
103   /**
104    * PDU encoding is too big for the transport used.
105    */

106   public static final int tooBig = SnmpConstants.SNMP_ERROR_TOO_BIG;
107
108   /**
109    * No such variable binding name, see error index.
110    */

111   public static final int noSuchName = SnmpConstants.SNMP_ERROR_NO_SUCH_NAME;
112
113   /**
114    * Bad value in variable binding, see error index.
115    */

116   public static final int badValue = SnmpConstants.SNMP_ERROR_BAD_VALUE;
117
118   /**
119    * The variable binding is read-only, see error index.
120    */

121   public static final int readOnly = SnmpConstants.SNMP_ERROR_READ_ONLY;
122
123   /**
124    * An unspecific error caused by a variable binding, see error index.
125    */

126   public static final int genErr = SnmpConstants.SNMP_ERROR_GENERAL_ERROR;
127
128   /**
129    * The variable binding is not accessible by the current MIB view, see error
130    * index.
131    */

132   public static final int noAccess = SnmpConstants.SNMP_ERROR_NO_ACCESS;
133
134   /**
135    * The variable binding's value has the wrong type, see error index.
136    */

137   public static final int wrongType = SnmpConstants.SNMP_ERROR_WRONG_TYPE;
138
139   /**
140    * The variable binding's value has the wrong length, see error index.
141    */

142   public static final int wrongLength = SnmpConstants.SNMP_ERROR_WRONG_LENGTH;
143
144   /**
145    * The variable binding's value has a value that could under no circumstances
146    * be assigned, see error index.
147    */

148   public static final int wrongValue = SnmpConstants.SNMP_ERROR_WRONG_VALUE;
149
150   /**
151    * The variable binding's value has the wrong encoding, see error index.
152    */

153   public static final int wrongEncoding =
154       SnmpConstants.SNMP_ERROR_WRONG_ENCODING;
155
156   /**
157    * The specified object does not exists and cannot be created,
158    * see error index.
159    */

160   public static final int noCreation = SnmpConstants.SNMP_ERROR_NO_CREATION;
161
162   /**
163    * The variable binding's value is presently inconsistent with the current
164    * state of the target object, see error index.
165    */

166   public static final int inconsistentValue =
167       SnmpConstants.SNMP_ERROR_INCONSISTENT_VALUE;
168
169   /**
170    * The resource needed to assign a variable binding's value is presently
171    * unavailable, see error index.
172    */

173   public static final int resourceUnavailable =
174       SnmpConstants.SNMP_ERROR_RESOURCE_UNAVAILABLE;
175
176   /**
177    * Unable to commit a value, see error index.
178    */

179   public static final int commitFailed = SnmpConstants.SNMP_ERROR_COMMIT_FAILED;
180
181   /**
182    * Unable to undo a committed value, see error index.
183    */

184   public static final int undoFailed = SnmpConstants.SNMP_ERROR_UNDO_FAILED;
185
186   /**
187    * Unauthorized access, see error index.
188    */

189   public static final int authorizationError =
190       SnmpConstants.SNMP_ERROR_AUTHORIZATION_ERROR;
191
192   /**
193    * The variable's value cannot be modified, see error index.
194    */

195   public static final int notWritable = SnmpConstants.SNMP_ERROR_NOT_WRITEABLE;
196
197   /**
198    * The specified object does not exists and presently it cannot be created,
199    * see error index.
200    */

201   public static final int inconsistentName =
202       SnmpConstants.SNMP_ERROR_INCONSISTENT_NAME;
203
204   protected Vector JavaDoc variableBindings = new Vector JavaDoc();
205   protected Integer32 errorStatus = new Integer32();
206   protected Integer32 errorIndex = new Integer32();
207   protected Integer32 requestID = new Integer32();
208   protected int type = GET;
209
210   /**
211    * Default constructor.
212    */

213   public PDU() {
214   }
215
216   /**
217    * Copy constructor.
218    * @param other
219    * the <code>PDU</code> to copy from.
220    */

221   public PDU(PDU other) {
222     variableBindings = (Vector JavaDoc) other.variableBindings.clone();
223     errorIndex = (Integer32) other.errorIndex.clone();
224     errorStatus = (Integer32) other.errorStatus.clone();
225     type = other.type;
226     requestID = (Integer32) other.requestID.clone();
227   }
228
229   /**
230    * Adds a variable binding to this PDU. A <code>NullPointerException</code>
231    * is thrown if <code>VariableBinding</code> or its <code>Variable</code> is
232    * <code>null</code>.
233    * <p>
234    * The added <code>VariableBinding</code> is cloned before the clone is added
235    * when the {@link Variable} is a dynamic one (see
236    * {@link Variable#isDynamic()}).
237    * @param vb
238    * a <code>VariableBinding</code> instance.
239    */

240   public void add(VariableBinding vb) {
241     if (vb.getVariable().isDynamic()) {
242       VariableBinding cvb = (VariableBinding) vb.clone();
243       variableBindings.add(cvb);
244     }
245     else {
246       variableBindings.add(vb);
247     }
248   }
249
250   /**
251    * Adds a new variable binding to this PDU by using the OID of the supplied
252    * <code>VariableBinding</code>. The value portion is thus set to
253    * <code>null</code>.
254    * <p>
255    * This method should be used for GET type requests. For SET, TRAP and INFORM
256    * requests, the {@link #add} method should be used instead.
257    * @param vb
258    * a <code>VariableBinding</code> instance.
259    * @since 1.8
260    */

261   public void addOID(VariableBinding vb) {
262     VariableBinding cvb = new VariableBinding(vb.getOid());
263     variableBindings.add(cvb);
264   }
265
266   /**
267    * Adds an array of variable bindings to this PDU (see
268    * {@link #add(VariableBinding vb)}).
269    * @param vbs
270    * an array of <code>VariableBinding</code> instances. The instances in the
271    * array will be appended to the current list of variable bindings in the
272    * PDU.
273    */

274   public void addAll(VariableBinding[] vbs) {
275     variableBindings.ensureCapacity(variableBindings.size()+vbs.length);
276     for (int i=0; i<vbs.length; i++) {
277       add(vbs[i]);
278     }
279   }
280
281   /**
282    * Adds new <code>VariableBindings</code> each with the OID of the
283    * corresponding variable binding of the supplied array to this PDU (see
284    * {@link #addOID(VariableBinding vb)}).
285    * @param vbs
286    * an array of <code>VariableBinding</code> instances. For each instance
287    * in the supplied array, a new VariableBinding created by
288    * <code>new VariableBinding(OID)</code> will be appended to the current
289    * list of variable bindings in the PDU.
290    * @since 1.8
291    */

292   public void addAllOIDs(VariableBinding[] vbs) {
293     variableBindings.ensureCapacity(variableBindings.size()+vbs.length);
294     for (int i=0; i<vbs.length; i++) {
295       addOID(vbs[i]);
296     }
297   }
298
299
300
301   /**
302    * Gets the variable binding at the specified position.
303    * @param index
304    * a zero based positive integer (<code>0 <= index < {@link #size()}</code>)
305    * @return
306    * a VariableBinding instance. If <code>index</code> is out of bounds
307    * an exception is thrown.
308    */

309   public VariableBinding get(int index) {
310     return (VariableBinding)variableBindings.get(index);
311   }
312
313   /**
314    * Sets the variable binding at the specified position.
315    * @param index
316    * a zero based positive integer (<code>0 <= index < {@link #size()}</code>)
317    * If <code>index</code> is out of bounds
318    * an exception is thrown.
319    * @param vb
320    * a VariableBinding instance (<code>null</code> is not allowed).
321    * @return
322    * the variable binding that has been replaced.
323    */

324   public VariableBinding set(int index, VariableBinding vb) {
325     if (vb == null) {
326       throw new NullPointerException JavaDoc("Variable binding must not be null");
327     }
328     return (VariableBinding)variableBindings.set(index, vb);
329   }
330
331   /**
332    * Removes the variable binding at the supplied position.
333    * @param index
334    * a position >= 0 and < {@link #size()}.
335    */

336   public void remove(int index) {
337     variableBindings.remove(index);
338   }
339
340   /**
341    * Gets the number of variable bindings in the PDU.
342    * @return
343    * the size of the PDU.
344    */

345   public int size() {
346     return variableBindings.size();
347   }
348
349   /**
350    * Gets the variable binding vector.
351    * @return
352    * the internal <code>Vector</code> containing the PDU's variable bindings.
353    */

354   public Vector JavaDoc getVariableBindings() {
355     return variableBindings;
356   }
357
358   /**
359    * Remove the last variable binding from the PDU, if such an element exists.
360    */

361   public void trim() {
362     if (variableBindings.size() > 0) {
363       variableBindings.remove(variableBindings.size() - 1);
364     }
365   }
366
367   /**
368    * Sets the error status of the PDU.
369    * @param errorStatus
370    * a SNMP error status.
371    * @see SnmpConstants
372    */

373   public void setErrorStatus(int errorStatus) {
374     this.errorStatus.setValue(errorStatus);
375   }
376
377   /**
378    * Gets the error status of the PDU.
379    * @return
380    * a SNMP error status.
381    * @see SnmpConstants
382    */

383   public int getErrorStatus() {
384     return errorStatus.getValue();
385   }
386
387   /**
388    * Gets a textual description of the error status.
389    * @return
390    * a String containing an element of the
391    * {@link SnmpConstants#SNMP_ERROR_MESSAGES} array for a valid error status.
392    * "Unknown error: <errorStatusNumber>" is returned for any other value.
393    */

394   public String JavaDoc getErrorStatusText() {
395     return toErrorStatusText(errorStatus.getValue());
396   }
397
398   /**
399    * Returns textual description for the supplied error status value.
400    * @param errorStatus
401    * an error status.
402    * @return
403    * a String containing an element of the
404    * {@link SnmpConstants#SNMP_ERROR_MESSAGES} array for a valid error status.
405    * "Unknown error: <errorStatusNumber>" is returned for any other value.
406    * @since 1.7
407    */

408   public static final String JavaDoc toErrorStatusText(int errorStatus) {
409     try {
410       return SnmpConstants.SNMP_ERROR_MESSAGES[errorStatus];
411     }
412     catch (ArrayIndexOutOfBoundsException JavaDoc iobex) {
413       return "Unknown error: "+errorStatus;
414     }
415   }
416
417   /**
418    * Sets the error index.
419    * @param errorIndex
420    * an integer value >= 0 where 1 denotes the first variable binding.
421    */

422   public void setErrorIndex(int errorIndex) {
423     this.errorIndex.setValue(errorIndex);
424   }
425
426   /**
427    * Gets the error index.
428    * @return
429    * an integer value >= 0 where 1 denotes the first variable binding.
430    */

431   public int getErrorIndex() {
432     return errorIndex.getValue();
433   }
434
435   /**
436    * Checks whether this PDU is a confirmed class PDU.
437    * @return boolean
438    */

439   public boolean isConfirmedPdu() {
440     return ((type != PDU.REPORT) && (type != PDU.RESPONSE) &&
441             (type != PDU.TRAP) && (type != PDU.V1TRAP));
442   }
443
444   public int getBERLength() {
445     // header for data_pdu
446
int length = getBERPayloadLengthPDU();
447     length += BER.getBERLengthOfLength(length) + 1;
448     // assume maxmimum length here
449
return length;
450   }
451
452   public int getBERPayloadLength() {
453     return getBERPayloadLengthPDU();
454   }
455
456   public void decodeBER(BERInputStream inputStream) throws IOException JavaDoc {
457     BER.MutableByte pduType = new BER.MutableByte();
458     int length = BER.decodeHeader(inputStream, pduType);
459     int pduStartPos = (int)inputStream.getPosition();
460     switch (pduType.getValue()) {
461       case PDU.SET:
462       case PDU.GET:
463       case PDU.GETNEXT:
464       case PDU.GETBULK:
465       case PDU.INFORM:
466       case PDU.REPORT:
467       case PDU.TRAP:
468       case PDU.RESPONSE:
469         break;
470       default:
471         throw new IOException JavaDoc("Unsupported PDU type: "+pduType.getValue());
472     }
473     this.type = pduType.getValue();
474     requestID.decodeBER(inputStream);
475     errorStatus.decodeBER(inputStream);
476     errorIndex.decodeBER(inputStream);
477
478     pduType = new BER.MutableByte();
479     int vbLength = BER.decodeHeader(inputStream, pduType);
480     if (pduType.getValue() != BER.SEQUENCE) {
481       throw new IOException JavaDoc("Encountered invalid tag, SEQUENCE expected: "+
482                             pduType.getValue());
483     }
484     // rest read count
485
int startPos = (int)inputStream.getPosition();
486     variableBindings = new Vector JavaDoc();
487     while (inputStream.getPosition() - startPos < vbLength) {
488       VariableBinding vb = new VariableBinding();
489       vb.decodeBER(inputStream);
490       variableBindings.add(vb);
491     }
492     if (inputStream.getPosition() - startPos != vbLength) {
493       throw new IOException JavaDoc("Length of VB sequence ("+vbLength+
494                             ") does not match real length: "+
495                             ((int)inputStream.getPosition()-startPos));
496     }
497     if (BER.isCheckSequenceLength()) {
498       BER.checkSequenceLength(length,
499                               (int) inputStream.getPosition() - pduStartPos,
500                               this);
501     }
502   }
503
504   protected int getBERPayloadLengthPDU() {
505     int length = 0;
506
507     // length for all vbs
508
for (int i = 0; i < variableBindings.size(); i++) {
509       length += ((VariableBinding)variableBindings.get(i)).getBERLength();
510     }
511
512     length += BER.getBERLengthOfLength(length) + 1;
513
514     // req id, error status, error index
515
Integer32 i32 = new Integer32(requestID.getValue());
516     length += i32.getBERLength();
517     i32 = errorStatus;
518     length += i32.getBERLength();
519     i32 = errorIndex;
520     length += i32.getBERLength();
521     i32 = null;
522     return length;
523   }
524
525   public void encodeBER(OutputStream JavaDoc outputStream) throws IOException JavaDoc {
526     BER.encodeHeader(outputStream, type, getBERPayloadLengthPDU());
527
528     requestID.encodeBER(outputStream);
529     errorStatus.encodeBER(outputStream);
530     errorIndex.encodeBER(outputStream);
531
532     int vbLength = 0;
533     for (int i=0; i<variableBindings.size(); i++) {
534       vbLength += ((VariableBinding)variableBindings.get(i)).getBERLength();
535     }
536     BER.encodeHeader(outputStream, BER.SEQUENCE, vbLength);
537     for (int i=0; i<variableBindings.size(); i++) {
538       ((VariableBinding)variableBindings.get(i)).encodeBER(outputStream);
539     }
540   }
541
542   /**
543    * Removes all variable bindings from the PDU and sets the request ID to zero.
544    * This can be used to reuse a PDU for another request.
545    */

546   public void clear() {
547     variableBindings.clear();
548     setRequestID(new Integer32(0));
549   }
550
551   /**
552    * Sets the PDU type.
553    * @param type
554    * the type of the PDU (e.g. GETNEXT, SET, etc.)
555    */

556   public void setType(int type) {
557     this.type = type;
558   }
559
560   /**
561    * Gets the PDU type. The default is {@link PDU#GETNEXT}.
562    * @return
563    * the PDU's type.
564    */

565   public int getType() {
566     return type;
567   }
568
569   public Object JavaDoc clone() {
570     return new PDU(this);
571   }
572
573   /**
574    * Gets the request ID associated with this PDU.
575    * @return
576    * an <code>Integer32</code> instance.
577    */

578   public Integer32 getRequestID() {
579     return requestID;
580   }
581
582   /**
583    * Sets the request ID for this PDU. When the request ID is not set or set to
584    * zero, the message processing model will generate a unique request ID for
585    * the <code>PDU</code> when sent.
586    * @param requestID
587    * a unique request ID.
588    */

589   public void setRequestID(Integer32 requestID) {
590     this.requestID = requestID;
591   }
592
593   /**
594    * Gets a string representation of the supplied PDU type.
595    * @param type
596    * a PDU type.
597    * @return
598    * a string representation of <code>type</code>, for example "GET".
599    */

600   public static String JavaDoc getTypeString(int type) {
601     switch (type) {
602       case PDU.GET:
603         return "GET";
604       case PDU.SET:
605         return "SET";
606       case PDU.GETNEXT:
607         return "GETNEXT";
608       case PDU.GETBULK:
609         return "GETBULK";
610       case PDU.INFORM:
611         return "INFORM";
612       case PDU.RESPONSE:
613         return "RESPONSE";
614       case PDU.REPORT:
615         return "REPORT";
616       case PDU.TRAP:
617         return "TRAP";
618       case PDU.V1TRAP:
619         return "V1TRAP";
620     }
621     return "unknown";
622   }
623
624   /**
625    * Gets the PDU type identifier for a string representation of the type.
626    * @param type
627    * the string representation of a PDU type: <code>GET, GETNEXT, GETBULK,
628    * SET, INFORM, RESPONSE, REPORT, TRAP, V1TRAP)</code>.
629    * @return
630    * the corresponding PDU type constant, or <code>Integer.MIN_VALUE</code>
631    * of the supplied type is unknown.
632    */

633   public static int getTypeFromString(String JavaDoc type) {
634     if (type.equals("GET")) {
635       return PDU.GET;
636     }
637     else if (type.equals("SET")) {
638       return PDU.SET;
639     }
640     else if (type.equals("GETNEXT")) {
641       return PDU.GETNEXT;
642     }
643     else if (type.equals("GETBULK")) {
644       return PDU.GETBULK;
645     }
646     else if (type.equals("INFORM")) {
647       return PDU.INFORM;
648     }
649     else if (type.equals("RESPONSE")) {
650       return PDU.RESPONSE;
651     }
652     else if (type.equals("TRAP")) {
653       return PDU.TRAP;
654     }
655     else if (type.equals("V1TRAP")) {
656       return PDU.V1TRAP;
657     }
658     else if (type.equals("REPORT")) {
659       return PDU.REPORT;
660     }
661     return Integer.MIN_VALUE;
662   }
663
664   /**
665    * Returns a string representation of the object.
666    *
667    * @return a string representation of the object.
668    */

669   public String JavaDoc toString() {
670     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
671     buf.append(getTypeString(type));
672     buf.append("[requestID=");
673     buf.append(requestID);
674     buf.append(", errorStatus=");
675     buf.append(getErrorStatusText()+"("+errorStatus+")");
676     buf.append(", errorIndex=");
677     buf.append(errorIndex);
678     buf.append(", VBS[");
679     for (int i=0; i<variableBindings.size(); i++) {
680       buf.append(variableBindings.get(i));
681       if (i+1 < variableBindings.size()) {
682         buf.append("; ");
683       }
684     }
685     buf.append("]]");
686     return buf.toString();
687   }
688
689   /**
690    * Gets the maximum repetitions of repeatable variable bindings in GETBULK
691    * requests.
692    * @return
693    * an integer value >= 0.
694    */

695   public int getMaxRepetitions() {
696     return errorIndex.getValue();
697   }
698
699   /**
700    * Sets the maximum repetitions of repeatable variable bindings in GETBULK
701    * requests.
702    * @param maxRepetitions
703    * an integer value >= 0.
704    */

705   public void setMaxRepetitions(int maxRepetitions) {
706     this.errorIndex.setValue(maxRepetitions);
707   }
708
709   /**
710    * Gets the number of non repeater variable bindings in a GETBULK PDU.
711    * @return
712    * an integer value >= 0 and <= {@link #size()}
713    */

714   public int getNonRepeaters() {
715     return errorStatus.getValue();
716   }
717
718   /**
719    * Sets the number of non repeater variable bindings in a GETBULK PDU.
720    * @param nonRepeaters
721    * an integer value >= 0 and <= {@link #size()}
722    */

723   public void setNonRepeaters(int nonRepeaters) {
724     this.errorStatus.setValue(nonRepeaters);
725   }
726
727   /**
728    * Returns an array with the variable bindings of this PDU.
729    * @return
730    * an array of <code>VariableBinding</code> instances of this PDU in the
731    * same order as in the PDU.
732    */

733   public VariableBinding[] toArray() {
734     VariableBinding[] vbs = new VariableBinding[this.variableBindings.size()];
735     this.variableBindings.toArray(vbs);
736     return vbs;
737   }
738 }
739
740
Popular Tags