1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package org.metricshub.wbem.sblim.slp.internal.msg;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 import java.io.ByteArrayInputStream;
49 import java.io.IOException;
50 import java.io.InputStream;
51 import java.io.UnsupportedEncodingException;
52 import java.net.DatagramPacket;
53 import java.net.Socket;
54 import java.util.ArrayList;
55 import java.util.Collection;
56 import java.util.Iterator;
57 import java.util.List;
58 import java.util.SortedSet;
59 import java.util.StringTokenizer;
60 import java.util.TreeSet;
61 import org.metricshub.wbem.sblim.slp.ServiceLocationAttribute;
62 import org.metricshub.wbem.sblim.slp.ServiceLocationException;
63 import org.metricshub.wbem.sblim.slp.ServiceType;
64 import org.metricshub.wbem.sblim.slp.ServiceURL;
65 import org.metricshub.wbem.sblim.slp.internal.Convert;
66 import org.metricshub.wbem.sblim.slp.internal.SLPDefaults;
67 import org.metricshub.wbem.sblim.slp.internal.TRC;
68
69
70
71
72
73 public class SLPInputStream {
74 private InputStream iInStr;
75
76 private final byte[] iBBuf = new byte[4];
77
78
79
80
81
82
83 public SLPInputStream(byte[] pBytes) {
84 this(pBytes, 0, pBytes.length);
85 }
86
87
88
89
90
91
92
93 public SLPInputStream(Socket pSock) throws IOException {
94 this(pSock.getInputStream());
95 }
96
97
98
99
100
101
102 public SLPInputStream(InputStream pInStr) {
103 this.iInStr = pInStr;
104 }
105
106
107
108
109
110
111 public SLPInputStream(DatagramPacket pPacket) {
112 this(pPacket.getData(), pPacket.getOffset(), pPacket.getLength());
113 }
114
115
116
117
118
119
120
121
122 public SLPInputStream(byte[] pBytes, int pOffset, int pLength) {
123 this.iInStr = new ByteArrayInputStream(pBytes, pOffset, pLength);
124 }
125
126
127
128
129
130
131
132
133 public String readString() throws ServiceLocationException, IOException {
134 return Convert.unescape(readRawString());
135 }
136
137
138
139
140
141
142
143
144 public SortedSet<String> readStringSet() throws ServiceLocationException, IOException {
145 SortedSet<String> set = new TreeSet<String>();
146 readStringCollection(set);
147 return set;
148 }
149
150
151
152
153
154
155
156
157 public List<String> readStringList() throws ServiceLocationException, IOException {
158 ArrayList<String> strList = new ArrayList<String>();
159 readStringCollection(strList);
160 return strList;
161 }
162
163
164
165
166
167
168
169
170 public ServiceLocationAttribute readAttribute() throws ServiceLocationException, IOException {
171 String str = readRawString();
172 return str == null ? null : new ServiceLocationAttribute(str);
173 }
174
175
176
177
178
179
180
181
182 public List<ServiceLocationAttribute> readAttributeList() throws ServiceLocationException, IOException {
183 String str = readRawString();
184 return str == null ? null : new AttrListParser(str).getList();
185 }
186
187
188
189
190
191
192
193
194 public List<?> readAuthBlockList() throws ServiceLocationException, IOException {
195 Integer blockCntInt = doRead8();
196 if (blockCntInt == null) return null;
197 int blockCnt = blockCntInt.intValue();
198 if (blockCnt != 0) throw new ServiceLocationException(
199 ServiceLocationException.NOT_IMPLEMENTED,
200 "Handling of authentication blocks is not implemented! blockCount = " + blockCnt
201 );
202 return null;
203 }
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220 public ServiceURL readURL() throws ServiceLocationException, IOException {
221 if (doRead8() == null) return null;
222 Integer lifeTimeInt = doRead16();
223 if (lifeTimeInt == null) return null;
224 int lifeTime = lifeTimeInt.intValue();
225 String urlStr = readString();
226 if (urlStr == null) return null;
227 Integer numOfAuthsInt = doRead8();
228 if (numOfAuthsInt == null) return null;
229 int numOfAuths = numOfAuthsInt.intValue();
230 while (numOfAuths-- > 0) {
231 TRC.warning("readAuth");
232 readString();
233 }
234 return new ServiceURL(urlStr, lifeTime);
235 }
236
237
238
239
240
241
242
243
244
245
246
247
248
249 public List<ServiceURL> readUrlList(List<Exception> pURLExceptions) throws ServiceLocationException, IOException {
250 Integer cntInt = doRead16();
251 if (cntInt == null) return null;
252 int cnt = cntInt.intValue();
253 ArrayList<ServiceURL> urlList = new ArrayList<ServiceURL>(cnt);
254 ServiceURL url;
255 while (cnt-- > 0) {
256 try {
257 url = readURL();
258 if (url == null) break;
259 urlList.add(url);
260 } catch (IllegalArgumentException e) {
261 pURLExceptions.add(e);
262 TRC.warning("Ignoring Invalid URL : " + e.getMessage());
263 }
264 }
265 return urlList;
266 }
267
268
269
270
271
272
273
274
275 public ServiceType readServiceType() throws ServiceLocationException, IOException {
276 String str = readString();
277 return str == null ? null : new ServiceType(str);
278 }
279
280
281
282
283
284
285
286
287 public List<ServiceType> readServTypeList() throws ServiceLocationException, IOException {
288 Iterator<String> strItr = readStringList().iterator();
289 ArrayList<ServiceType> srvTypeList = new ArrayList<ServiceType>();
290 while (strItr.hasNext()) {
291 srvTypeList.add(new ServiceType(strItr.next()));
292 }
293 return srvTypeList;
294 }
295
296
297
298
299
300
301
302
303 public int read8() throws ServiceLocationException, IOException {
304 Integer res = doRead8();
305 if (res == null) throw new ServiceLocationException(
306 ServiceLocationException.PARSE_ERROR,
307 "Failed to read byte field!"
308 );
309 return res.intValue();
310 }
311
312
313
314
315
316
317
318
319 public int read16() throws ServiceLocationException, IOException {
320 Integer res = doRead16();
321 if (res == null) throw new ServiceLocationException(
322 ServiceLocationException.PARSE_ERROR,
323 "Failed to read 2-byte-long field!"
324 );
325 return res.intValue();
326 }
327
328
329
330
331
332
333
334
335 public int read24() throws ServiceLocationException, IOException {
336 Integer res = doRead24();
337 if (res == null) throw new ServiceLocationException(
338 ServiceLocationException.PARSE_ERROR,
339 "Failed to read 3-byte-long field!"
340 );
341 return res.intValue();
342 }
343
344
345
346
347
348
349
350
351 public long read32() throws ServiceLocationException, IOException {
352 Long res = doRead32();
353 if (res == null) throw new ServiceLocationException(
354 ServiceLocationException.PARSE_ERROR,
355 "Failed to read 4-byte-long field!"
356 );
357 return res.longValue();
358 }
359
360 private Integer doRead8() throws IOException {
361 int res = this.iInStr.read();
362 return res < 0 ? null : Integer.valueOf(res);
363 }
364
365 private Integer doRead16() throws IOException {
366 int cnt = this.iInStr.read(this.iBBuf, 0, 2);
367 if (cnt != 2) return null;
368 return Integer.valueOf((this.iBBuf[0] & 0xff) << 8 | this.iBBuf[1] & 0xff);
369 }
370
371 private Integer doRead24() throws IOException {
372 int cnt = this.iInStr.read(this.iBBuf, 0, 3);
373 if (cnt != 3) return null;
374 return Integer.valueOf((this.iBBuf[0] & 0xff) << 16 | (this.iBBuf[1] & 0xff) << 8 | this.iBBuf[2] & 0xff);
375 }
376
377 private Long doRead32() throws IOException {
378 int cnt = this.iInStr.read(this.iBBuf, 0, 4);
379 if (cnt != 4) return null;
380 long res = (this.iBBuf[0] & 0xff) << 8;
381 res |= (this.iBBuf[1] & 0xff) << 8;
382 res |= (this.iBBuf[2] & 0xff) << 8;
383 res |= this.iBBuf[3] & 0xff;
384 return Long.valueOf(res);
385 }
386
387 private String readRawString() throws ServiceLocationException, IOException {
388 Integer lenInt = doRead16();
389 if (lenInt == null) return null;
390 int len = lenInt.intValue();
391 if (len <= 0) return null;
392 byte[] bytes = new byte[len];
393 int read = this.iInStr.read(bytes, 0, len);
394 if (read != len) return null;
395 try {
396 return new String(bytes, SLPDefaults.ENCODING);
397 } catch (UnsupportedEncodingException e) {
398 throw new ServiceLocationException(ServiceLocationException.INTERNAL_SYSTEM_ERROR, e);
399 }
400 }
401
402 private void readStringCollection(Collection<String> pCol) throws ServiceLocationException, IOException {
403 String rawListStr = readRawString();
404 if (rawListStr == null) return;
405 StringTokenizer tokenizer = new StringTokenizer(rawListStr, ",");
406 while (tokenizer.hasMoreElements()) pCol.add(Convert.unescape(tokenizer.nextToken()));
407 }
408
409 private static class AttrListParser {
410 private int iPos = 0;
411
412 private String iAttrListStr;
413
414 private ArrayList<ServiceLocationAttribute> iList = new ArrayList<ServiceLocationAttribute>();
415
416
417
418
419
420
421
422 public AttrListParser(String pAttrListStr) throws ServiceLocationException {
423 debug("attrListStr=" + pAttrListStr);
424 this.iAttrListStr = pAttrListStr;
425 String attrStr;
426 while ((attrStr = readEntry()) != null) {
427 debug("attrStr=" + attrStr);
428 this.iList.add(new ServiceLocationAttribute(attrStr));
429 }
430 }
431
432
433
434
435
436
437 public List<ServiceLocationAttribute> getList() {
438 return this.iList;
439 }
440
441
442
443
444
445 private String readEntry() throws ServiceLocationException {
446 if (this.iAttrListStr == null) return null;
447 int lastIdx = this.iAttrListStr.length() - 1;
448 if (this.iPos == lastIdx) return null;
449 boolean inBlock = false;
450 int startPos = this.iPos;
451 while (true) {
452 char ch = this.iAttrListStr.charAt(this.iPos);
453 if (ch == '(') {
454 if (inBlock || this.iPos != startPos) throw new ServiceLocationException(
455 ServiceLocationException.PARSE_ERROR,
456 invalidChar('(')
457 );
458 inBlock = true;
459 } else if (ch == ')') {
460 if (!inBlock) throw new ServiceLocationException(ServiceLocationException.PARSE_ERROR, invalidChar(')'));
461 if (this.iPos == lastIdx) return this.iAttrListStr.substring(startPos);
462 inBlock = false;
463 } else {
464 if (inBlock) {
465 if (this.iPos == lastIdx)
466
467
468
469
470 return this.iAttrListStr.substring(startPos);
471 } else {
472 if (ch == ',') {
473 ++this.iPos;
474 return this.iAttrListStr.substring(startPos, this.iPos - 1);
475 }
476 if (this.iPos == lastIdx) {
477 return this.iAttrListStr.substring(startPos);
478 }
479 }
480 }
481 if (this.iPos == lastIdx) throw new ServiceLocationException(
482 ServiceLocationException.PARSE_ERROR,
483 "Unexpected end of Attribute list:\n" + this.iAttrListStr
484 );
485 ++this.iPos;
486 }
487 }
488
489
490
491
492 private String invalidChar(char ch) {
493 return "Invalid '(' character in Attribute list:\n" + this.iAttrListStr + "\nat position: " + this.iPos;
494 }
495 }
496
497
498
499
500 static void debug(String pMsg) {
501
502 }
503 }