KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > snmp4j > smi > OctetString


1 /*_############################################################################
2   _##
3   _## SNMP4J - OctetString.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 package org.snmp4j.smi;
22
23 import java.io.*;
24 import java.util.*;
25 import org.snmp4j.asn1.BER;
26 import org.snmp4j.asn1.BERInputStream;
27
28 /**
29  * The <code>OctetString</code> class represents the SMI type OCTET STRING.
30  *
31  * @author Frank Fock
32  * @version 1.8
33  * @since 1.0
34  */

35 public class OctetString extends AbstractVariable
36     implements AssignableFromByteArray, AssignableFromString {
37
38   private static final long serialVersionUID = 4125661211046256289L;
39
40   private static final char DEFAULT_HEX_DELIMITER = ':';
41
42   private byte[] value = new byte[0];
43
44   /**
45    * Creates a zero length octet string.
46    */

47   public OctetString() {
48   }
49
50   /**
51    * Creates an octet string from an byte array.
52    * @param rawValue
53    * an array of bytes.
54    */

55   public OctetString(byte[] rawValue) {
56     this(rawValue, 0, rawValue.length);
57   }
58
59   /**
60    * Creates an octet string from an byte array.
61    * @param rawValue
62    * an array of bytes.
63    * @param offset
64    * the position (zero based) of the first byte to be copied from
65    * <code>rawValue</code>into the new <code>OctetSring</code>.
66    * @param length
67    * the number of bytes to be copied.
68    */

69   public OctetString(byte[] rawValue, int offset, int length) {
70     value = new byte[length];
71     System.arraycopy(rawValue, offset, value, 0, length);
72   }
73
74   /**
75    * Creates an octet string from a java string.
76    *
77    * @param stringValue
78    * a Java string.
79    */

80   public OctetString(String JavaDoc stringValue) {
81     this.value = stringValue.getBytes();
82   }
83
84   /**
85    * Creates an octet string from another OctetString by cloning its value.
86    *
87    * @param other
88    * an <code>OctetString</code> instance.
89    */

90   public OctetString(OctetString other) {
91     this.value = new byte[0];
92     append(other);
93   }
94
95   /**
96    * Appends a single byte to this octet string.
97    * @param b
98    * a byte value.
99    */

100   public void append(byte b) {
101     byte[] newValue = new byte[value.length+1];
102     System.arraycopy(value, 0, newValue, 0, value.length);
103     newValue[value.length] = b;
104     value = newValue;
105   }
106
107   /**
108    * Appends an array of bytes to this octet string.
109    * @param bytes
110    * an array of bytes.
111    */

112   public void append(byte[] bytes) {
113     byte[] newValue = new byte[value.length + bytes.length];
114     System.arraycopy(value, 0, newValue, 0, value.length);
115     System.arraycopy(bytes, 0, newValue, value.length, bytes.length);
116     value = newValue;
117   }
118
119   /**
120    * Appends an octet string.
121    * @param octetString
122    * an <code>OctetString</code> to append to this octet string.
123    */

124   public void append(OctetString octetString) {
125     append(octetString.getValue());
126   }
127
128   /**
129    * Appends the supplied string to this <code>OctetString</code>. Calling this
130    * method is identical to <I>append(string.getBytes())</I>.
131    * @param string
132    * a String instance.
133    */

134   public void append(String JavaDoc string) {
135     append(string.getBytes());
136   }
137
138   /**
139    * Sets the value of the octet string to a zero length string.
140    */

141   public void clear() {
142     value = new byte[0];
143   }
144
145   public void encodeBER(OutputStream outputStream) throws java.io.IOException JavaDoc {
146     BER.encodeString(outputStream, BER.OCTETSTRING, getValue());
147   }
148
149   public void decodeBER(BERInputStream inputStream) throws java.io.IOException JavaDoc {
150     BER.MutableByte type = new BER.MutableByte();
151     byte[] v = BER.decodeString(inputStream, type);
152     if (type.getValue() != BER.OCTETSTRING) {
153       throw new IOException("Wrong type encountered when decoding OctetString: "+
154                             type.getValue());
155     }
156     setValue(v);
157   }
158
159   public int getBERLength() {
160     return value.length + BER.getBERLengthOfLength(value.length) + 1;
161   }
162
163   public int getSyntax() {
164     return SMIConstants.SYNTAX_OCTET_STRING;
165   }
166
167   /**
168    * Gets the byte at the specified index.
169    * @param index
170    * a zero-based index into the octet string.
171    * @return
172    * the byte value at the specified index.
173    * @throws ArrayIndexOutOfBoundsException
174    * if <code>index</code> &lt; 0 or &gt; {@link #length()}.
175    */

176   public final byte get(int index) {
177     return value[index];
178   }
179
180   /**
181    * Sets the byte value at the specified index.
182    * @param index
183    * an index value greater or equal 0 and less than {@link #length()}.
184    * @param b
185    * the byte value to set.
186    * @since v1.2
187    */

188   public final void set(int index, byte b) {
189     value[index] = b;
190   }
191
192   public int hashCode() {
193     int hash = 0;
194     for (int i=0; i<value.length; i++) {
195       hash += value[i]*31^((value.length-1)-i);
196     }
197     return hash;
198   }
199
200   public boolean equals(Object JavaDoc o) {
201     if (o instanceof OctetString) {
202       OctetString other = (OctetString)o;
203       return Arrays.equals(value, other.value);
204     }
205     else if (o instanceof byte[]) {
206       return Arrays.equals(value, (byte[])o);
207     }
208     return false;
209   }
210
211   public int compareTo(Object JavaDoc o) {
212     if (o instanceof OctetString) {
213       OctetString other = (OctetString)o;
214       int maxlen = Math.min(value.length, other.value.length);
215       for (int i=0; i<maxlen; i++) {
216         if (value[i] != other.value[i]) {
217           if ((value[i] & 0xFF) < (other.value[i] & 0xFF)) {
218             return -1;
219           }
220           else {
221             return 1;
222           }
223         }
224       }
225       return (value.length - other.value.length);
226     }
227     throw new ClassCastException JavaDoc(o.getClass().getName());
228   }
229
230   /**
231    * Returns a new string that is a substring of this string. The substring
232    * begins at the specified <code>beginIndex</code> and extends to the
233    * character at index <code>endIndex - 1</code>.
234    * Thus the length of the substring is <code>endIndex-beginIndex</code>.
235    * @param beginIndex
236    * the beginning index, inclusive.
237    * @param endIndex
238    * the ending index, exclusive.
239    * @return
240    * the specified substring.
241    * @since 1.3
242    */

243   public OctetString substring(int beginIndex, int endIndex) {
244     if ((beginIndex < 0) || (endIndex > length())) {
245       throw new IndexOutOfBoundsException JavaDoc();
246     }
247     byte[] substring = new byte[endIndex - beginIndex];
248     System.arraycopy(value, beginIndex, substring, 0, substring.length);
249     return new OctetString(substring);
250   }
251
252   /**
253    * Tests if this octet string starts with the specified prefix.
254    * @param prefix
255    * the prefix.
256    * @return
257    * <code>true</code> if the bytes of this octet string up to the length
258    * of <code>prefix</code> equal those of <code>prefix</code>.
259    * @since 1.2
260    */

261   public boolean startsWith(OctetString prefix) {
262     if ((prefix == null) || prefix.length() > length()) {
263       return false;
264     }
265     for (int i=0; i<prefix.length(); i++) {
266       if (prefix.get(i) != value[i]) {
267         return false;
268       }
269     }
270     return true;
271   }
272
273   /**
274    * Determines whether this octet string contains non ISO control characters
275    * only.
276    * @return
277    * <code>false</code> if this octet string contains any ISO control
278    * characters as defined by <code>Character.isISOControl(char)</code>
279    * except if these ISO control characters are all whitespace characters
280    * as defined by <code>Character.isWhitespace(char)</code>.
281    */

282   public boolean isPrintable() {
283     for (int i=0; i<value.length; i++) {
284       char c = (char)value[i];
285       if ((Character.isISOControl(c) ||
286           ((value[i] & 0xFF) >= 0x80)) && (!Character.isWhitespace(c))) {
287         return false;
288       }
289     }
290     return true;
291   }
292
293   public String JavaDoc toString() {
294     if (isPrintable()) {
295       return new String JavaDoc(value);
296     }
297     return toHexString();
298   }
299
300   public String JavaDoc toHexString() {
301     return toHexString(DEFAULT_HEX_DELIMITER);
302   }
303
304   public String JavaDoc toHexString(char separator) {
305     return toString(separator, 16);
306   }
307
308   public static OctetString fromHexString(String JavaDoc hexString) {
309     return fromHexString(hexString, DEFAULT_HEX_DELIMITER);
310   }
311
312   public static OctetString fromHexString(String JavaDoc hexString, char delimiter) {
313     return OctetString.fromString(hexString, delimiter, 16);
314   }
315
316
317   public static OctetString fromString(String JavaDoc string, char delimiter, int radix) {
318     String JavaDoc delim = "";
319     delim += delimiter;
320     StringTokenizer st = new StringTokenizer(string, delim);
321     byte[] value = new byte[st.countTokens()];
322     for (int n=0; st.hasMoreTokens(); n++) {
323       String JavaDoc s = st.nextToken();
324       value[n] = (byte)Integer.parseInt(s, radix);
325     }
326     return new OctetString(value);
327   }
328
329   /**
330    * Creates an OctetString from a string represantation in the specified
331    * radix.
332    * @param string
333    * the string representation of an octet string.
334    * @param radix
335    * the radix of the string represantion.
336    * @return
337    * the OctetString instance.
338    * @since 1.6
339    */

340   public static OctetString fromString(String JavaDoc string, int radix) {
341     int digits = (int)(Math.round((float)Math.log(256)/Math.log(radix)));
342     byte[] value = new byte[string.length()/digits];
343     for (int n=0; n<string.length(); n+=digits) {
344       String JavaDoc s = string.substring(n, n+digits);
345       value[n/digits] = (byte)Integer.parseInt(s, radix);
346     }
347     return new OctetString(value);
348   }
349
350   public String JavaDoc toString(char separator, int radix) {
351     int digits = (int)(Math.round((float)Math.log(256)/Math.log(radix)));
352     StringBuffer JavaDoc buf = new StringBuffer JavaDoc(value.length*(digits+1));
353     for (int i=0; i<value.length; i++) {
354       if (i > 0) {
355         buf.append(separator);
356       }
357       int v = (value[i] & 0xFF);
358       String JavaDoc val = Integer.toString(v, radix);
359       for (int j=0; j < digits - val.length(); j++) {
360         buf.append('0');
361       }
362       buf.append(val);
363     }
364     return buf.toString();
365   }
366
367   /**
368    * Returns a string representation of this octet string in the radix
369    * specified. There will be no separation characters, but each byte will
370    * be represented by <code>round(log(256)/log(radix))</code> digits.
371    *
372    * @param radix
373    * the radix to use in the string representation.
374    * @return
375    * a string representation of this ocetet string in the specified radix.
376    * @since 1.6
377    */

378   public String JavaDoc toString(int radix) {
379     int digits = (int)(Math.round((float)Math.log(256)/Math.log(radix)));
380     StringBuffer JavaDoc buf = new StringBuffer JavaDoc(value.length*(digits+1));
381     for (int i=0; i<value.length; i++) {
382       int v = (value[i] & 0xFF);
383       String JavaDoc val = Integer.toString(v, radix);
384       for (int j=0; j < digits - val.length(); j++) {
385         buf.append('0');
386       }
387       buf.append(val);
388     }
389     return buf.toString();
390   }
391
392
393   /**
394    * Formats the content into a ASCII string. Non-printable characters are
395    * replaced by the supplied placeholder character.
396    * @param placeholder
397    * a placeholder character, for example '.'.
398    * @return
399    * the contents of this octet string as ASCII formatted string.
400    * @since 1.6
401    */

402   public String JavaDoc toASCII(char placeholder) {
403     StringBuffer JavaDoc buf = new StringBuffer JavaDoc(value.length);
404     for (int i=0; i<value.length; i++) {
405       if ((Character.isISOControl((char)value[i])) ||
406           ((value[i] & 0xFF) >= 0x80)) {
407         buf.append(placeholder);
408       }
409       else {
410         buf.append((char) value[i]);
411       }
412     }
413     return buf.toString();
414   }
415
416   public void setValue(String JavaDoc value) {
417     setValue(value.getBytes());
418   }
419
420   public void setValue(byte[] value) {
421     if (value == null) {
422       throw new IllegalArgumentException JavaDoc(
423           "OctetString must not be assigned a null value");
424     }
425     this.value = value;
426   }
427
428   public byte[] getValue() {
429     return value;
430   }
431
432   /**
433    * Gets the length of the byte string.
434    * @return
435    * an integer >= 0.
436    */

437   public final int length() {
438     return value.length;
439   }
440
441   public Object JavaDoc clone() {
442     return new OctetString(value);
443   }
444
445   /**
446    * Returns the length of the payload of this <code>BERSerializable</code>
447    * object in bytes when encoded according to the Basic Encoding Rules (BER).
448    *
449    * @return the BER encoded length of this variable.
450    */

451   public int getBERPayloadLength() {
452     return value.length;
453   }
454
455   public int toInt() {
456     throw new UnsupportedOperationException JavaDoc();
457   }
458
459   public long toLong() {
460     throw new UnsupportedOperationException JavaDoc();
461   }
462
463   /**
464    * Returns a copy of this OctetString where each bit not set in the supplied
465    * mask zeros the corresponding bit in the returned OctetString.
466    * @param mask
467    * a mask where the n-th bit corresponds to the n-th bit in the returned
468    * OctetString.
469    * @return
470    * the masked OctetString.
471    * @since 1.7
472    */

473   public OctetString mask(OctetString mask) {
474     byte[] masked = new byte[value.length];
475     System.arraycopy(value, 0, masked, 0, value.length);
476     for (int i=0; (i<mask.length()) && (i<masked.length); i++) {
477       masked[i] = (byte)(masked[i] & mask.get(i));
478     }
479     return new OctetString(masked);
480   }
481
482   public OID toSubIndex(boolean impliedLength) {
483     int[] subIndex;
484     int offset = 0;
485     if (!impliedLength) {
486       subIndex = new int[length()+1];
487       subIndex[offset++] = length();
488     }
489     else {
490       subIndex = new int[length()];
491     }
492     for (int i=0; i<length(); i++) {
493       subIndex[offset+i] = get(i) & 0xFF;
494     }
495     return new OID(subIndex);
496   }
497
498   public void fromSubIndex(OID subIndex, boolean impliedLength) {
499     if (impliedLength) {
500       setValue(subIndex.toByteArray());
501     }
502     else {
503       OID suffix = new OID(subIndex.getValue(), 1, subIndex.size() - 1);
504       setValue(suffix.toByteArray());
505     }
506   }
507
508   /**
509    * Splits an <code>OctetString</code> using a set of delimiter characters
510    * similar to how a StringTokenizer would do it.
511    * @param octetString
512    * the input string to tokenize.
513    * @param delimOctets
514    * a set of delimiter octets.
515    * @return
516    * a Collection of OctetString instances that contain the tokens.
517    */

518   public static final Collection split(OctetString octetString,
519                                        OctetString delimOctets) {
520     List parts = new LinkedList();
521     int maxDelim = -1;
522     for (int i = 0; i<delimOctets.length(); i++) {
523       int delim = delimOctets.get(i) & 0xFF;
524       if (delim > maxDelim) {
525         maxDelim = delim;
526       }
527     }
528     int startPos = 0;
529     for (int i = 0; i<octetString.length(); i++) {
530       int c = octetString.value[i] & 0xFF;
531       boolean isDelim = false;
532       if (c <= maxDelim) {
533         for (int j=0; j<delimOctets.length(); j++) {
534           if (c == (delimOctets.get(j) & 0xFF)) {
535             if ((startPos >= 0) && (i > startPos)) {
536               parts.add(new OctetString(octetString.value,
537                                         startPos, i - startPos));
538             }
539             startPos = -1;
540             isDelim = true;
541           }
542         }
543       }
544       if (!isDelim && (startPos < 0)) {
545         startPos = i;
546       }
547     }
548     if (startPos >= 0) {
549       parts.add(new OctetString(octetString.value, startPos,
550                                 octetString.length() - startPos));
551     }
552     return parts;
553   }
554
555   /**
556    * Creates an <code>OctetString</code> from an byte array.
557    * @param value
558    * a byte array that is copied into the value of the created
559    * <code>OctetString</code> or <code>null</code>.
560    * @return
561    * an OctetString or <code>null</code> if <code>value</code>
562    * is <code>null</code>.
563    * @since 1.7
564    */

565   public static OctetString fromByteArray(byte[] value) {
566     if (value == null) {
567       return null;
568     }
569     return new OctetString(value);
570   }
571
572   public byte[] toByteArray() {
573     return getValue();
574   }
575 }
576
577
578
Popular Tags