2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 Change History (most recent first):
27 $Log: TXTRecord.java,v $
28 Revision 1.2 2004/04/30 21:48:27 rpantos
29 Change line endings for CVS.
31 Revision 1.1 2004/04/30 16:29:35 rpantos
36 - fix set() to replace existing values
40 package com
.apple
.dnssd
;
44 Object used to construct and parse DNS-SD format TXT records.
45 For more info see <a href="http://www.zeroconf.org/Rendezvous/txtrecords.html">DNS-SD TXT record format</a>.
48 public class TXTRecord
51 DNS-SD specifies that a TXT record corresponding to an SRV record consist of
52 a packed array of bytes, each preceded by a length byte. Each string
53 is an attribute-value pair.
55 The TXTRecord object stores the entire TXT data as a single byte array, traversing it
56 as need be to implement its various methods.
59 static final protected byte kAttrSep
= '=';
61 protected byte[] fBytes
;
63 /** Constructs a new, empty TXT record. */
65 { fBytes
= new byte[0]; }
67 /** Constructs a new TXT record from a byte array in the standard format. */
68 public TXTRecord( byte[] initBytes
)
69 { fBytes
= (byte[]) initBytes
.clone(); }
71 /** Set a key/value pair in the TXT record. Setting an existing key will replace its value.<P>
73 The key name. Must be ASCII, with no '=' characters.
76 Value to be encoded into bytes using the default platform character set.
78 public void set( String key
, String value
)
80 byte[] valBytes
= (value
!= null) ? value
.getBytes() : null;
81 this.set( key
, valBytes
);
84 /** Set a key/value pair in the TXT record. Setting an existing key will replace its value.<P>
86 The key name. Must be ASCII, with no '=' characters.
89 Binary representation of the value.
91 public void set( String key
, byte[] value
)
93 byte[] oldBytes
= fBytes
;
95 int valLen
= (value
!= null) ? value
.length
: 0;
99 keyBytes
= key
.getBytes( "US-ASCII");
101 catch ( java
.io
.UnsupportedEncodingException uee
) {
102 throw new IllegalArgumentException();
105 for ( int i
=0; i
< keyBytes
.length
; i
++)
106 if ( keyBytes
[i
] == '=')
107 throw new IllegalArgumentException();
109 if ( keyBytes
.length
+ valLen
>= 255)
110 throw new ArrayIndexOutOfBoundsException();
111 newLen
= (byte) ( keyBytes
.length
+ valLen
+ (valLen
> 0 ?
1 : 0));
113 fBytes
= new byte[ oldBytes
.length
+ newLen
+ 1];
114 System
.arraycopy( oldBytes
, 0, fBytes
, 0, oldBytes
.length
);
115 fBytes
[ oldBytes
.length
] = newLen
;
116 System
.arraycopy( keyBytes
, 0, fBytes
, oldBytes
.length
+ 1, keyBytes
.length
);
119 fBytes
[ oldBytes
.length
+ 1 + keyBytes
.length
] = kAttrSep
;
120 System
.arraycopy( value
, 0, fBytes
, oldBytes
.length
+ keyBytes
.length
+ 2, value
.length
);
124 /** Return the number of keys in the TXT record. */
129 for ( i
=0, avStart
=0; avStart
< fBytes
.length
; i
++)
130 avStart
+= fBytes
[ avStart
] + 1;
134 /** Return true if key is present in the TXT record, false if not. */
135 public boolean contains( String key
)
139 for ( int i
=0; null != ( s
= this.getKey( i
)); i
++)
140 if ( 0 == key
.compareToIgnoreCase( s
))
145 /** Return a key in the TXT record by zero-based index. Returns null if index exceeds the total number of keys. */
146 public String
getKey( int index
)
150 for ( int i
=0; i
< index
&& avStart
< fBytes
.length
; i
++)
151 avStart
+= fBytes
[ avStart
] + 1;
153 if ( avStart
< fBytes
.length
)
155 int avLen
= fBytes
[ avStart
];
158 for ( aLen
=0; aLen
< avLen
; aLen
++)
159 if ( fBytes
[ avStart
+ aLen
+ 1] == kAttrSep
)
161 return new String( fBytes
, avStart
+ 1, aLen
);
167 Look up a key in the TXT record by zero-based index and return its value. <P>
168 Returns null if index exceeds the total number of keys.
169 Returns null if the key is present with no value.
171 public byte[] getValue( int index
)
176 for ( int i
=0; i
< index
&& avStart
< fBytes
.length
; i
++)
177 avStart
+= fBytes
[ avStart
] + 1;
179 if ( avStart
< fBytes
.length
)
181 int avLen
= fBytes
[ avStart
];
184 for ( aLen
=0; aLen
< avLen
; aLen
++)
186 if ( fBytes
[ avStart
+ aLen
+ 1] == kAttrSep
)
188 value
= new byte[ avLen
- aLen
- 1];
189 System
.arraycopy( fBytes
, avStart
+ aLen
+ 2, value
, 0, avLen
- aLen
- 1);
196 /** Converts the result of getValue() to a string in the platform default character set. */
197 public String
getValueAsString( int index
)
199 byte[] value
= this.getValue( index
);
200 return value
!= null ?
new String( value
) : null;
203 /** Get the value associated with a key. Will be null if the key is not defined.
204 Array will have length 0 if the key is defined with an = but no value.<P>
207 The left-hand side of the key-value pair.
209 @return The binary representation of the value.
211 public byte[] getValue( String forKey
)
216 for ( i
=0; null != ( s
= this.getKey( i
)); i
++)
217 if ( 0 == forKey
.compareToIgnoreCase( s
))
218 return this.getValue( i
);
222 /** Converts the result of getValue() to a string in the platform default character set.<P>
225 The left-hand side of the key-value pair.
227 @return The value represented in the default platform character set.
229 public String
getValueAsString( String forKey
)
231 byte[] val
= this.getValue( forKey
);
232 return val
!= null ?
new String( val
) : null;
235 /** Return the contents of the TXT record as raw bytes. */
236 public byte[] getRawBytes() { return (byte[]) fBytes
.clone(); }