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
27
28
29
30
31
32
33
34
35 package org.marre.wap.wbxml;
36
37 import java.io.ByteArrayOutputStream;
38 import java.io.IOException;
39 import java.io.OutputStream;
40 import java.util.HashMap;
41 import java.util.Map;
42
43 import org.marre.util.StringUtil;
44 import org.marre.wap.WapConstants;
45 import org.marre.wap.WspUtil;
46 import org.marre.xml.XmlAttribute;
47 import org.marre.xml.XmlWriter;
48
49 public class WbxmlWriter implements XmlWriter
50 {
51 private Map myStringTable;
52 private ByteArrayOutputStream myStringTableBuf;
53
54 private OutputStream myOs;
55 private ByteArrayOutputStream myWbxmlBody;
56
57 private String[] myTagTokens;
58 private String[] myAttrStartTokens;
59 private String[] myAttrValueTokens;
60
61 private String myPublicID;
62
63 public WbxmlWriter(OutputStream os, String[] theTagTokens, String[] theAttrStrartTokens, String[] theAttrValueTokens)
64 {
65 myWbxmlBody = new ByteArrayOutputStream();
66 myStringTableBuf = new ByteArrayOutputStream();
67 myStringTable = new HashMap();
68 myOs = os;
69
70 setTagTokens(theTagTokens);
71 setAttrStartTokens(theAttrStrartTokens);
72 setAttrValueTokens(theAttrValueTokens);
73 }
74
75 public WbxmlWriter(OutputStream os)
76 {
77 this(os, null, null, null);
78 }
79
80 /***
81 * Writes the wbxml to stream.
82 *
83 * @throws IOException
84 */
85 public void flush() throws IOException
86 {
87
88 WspUtil.writeUint8(myOs, 0x01);
89
90 writePublicIdentifier(myOs, myPublicID);
91
92 WspUtil.writeUintvar(myOs, WapConstants.MIB_ENUM_UTF_8);
93
94 writeStringTable(myOs);
95
96
97 myWbxmlBody.close();
98 myWbxmlBody.writeTo(myOs);
99
100 myOs.flush();
101 }
102
103
104
105 public void setDoctype(String name, String systemURI)
106 {
107 myPublicID = null;
108 }
109
110 public void setDoctype(String name, String publicID, String publicURI)
111 {
112 myPublicID = publicID;
113 }
114
115 public void setDoctype(String publicID)
116 {
117 myPublicID = publicID;
118 }
119
120 public void addStartElement(String tag) throws IOException
121 {
122 int tagIndex = StringUtil.findString(myTagTokens, tag);
123 if (tagIndex >= 0)
124 {
125
126 tagIndex += 0x05;
127 myWbxmlBody.write(WbxmlConstants.TOKEN_KNOWN_C | tagIndex);
128 }
129 else
130 {
131
132 myWbxmlBody.write(WbxmlConstants.TOKEN_LITERAL_C);
133 writeStrT(myWbxmlBody, tag);
134 }
135 }
136
137 public void addStartElement(String tag, XmlAttribute[] attribs) throws IOException
138 {
139 int tagIndex = StringUtil.findString(myTagTokens, tag);
140 if (tagIndex >= 0)
141 {
142
143 tagIndex += 0x05;
144 myWbxmlBody.write(WbxmlConstants.TOKEN_KNOWN_AC | tagIndex);
145 }
146 else if (tag != null)
147 {
148
149 myWbxmlBody.write(WbxmlConstants.TOKEN_LITERAL_AC);
150 writeStrT(myWbxmlBody, tag);
151 }
152
153
154 writeAttributes(myWbxmlBody, attribs);
155 }
156
157 public void addEmptyElement(String tag) throws IOException
158 {
159 int tagIndex = StringUtil.findString(myTagTokens, tag);
160 if (tagIndex >= 0)
161 {
162
163 tagIndex += 0x05;
164 myWbxmlBody.write(WbxmlConstants.TOKEN_KNOWN | tagIndex);
165 }
166 else if (tag != null)
167 {
168
169 myWbxmlBody.write(WbxmlConstants.TOKEN_LITERAL);
170 writeStrT(myWbxmlBody, tag);
171 }
172 }
173
174 public void addEmptyElement(String tag, XmlAttribute[] attribs) throws IOException
175 {
176 int tagIndex = StringUtil.findString(myTagTokens, tag);
177
178 if (tagIndex >= 0)
179 {
180
181 tagIndex += 0x05;
182 myWbxmlBody.write(WbxmlConstants.TOKEN_KNOWN_A | tagIndex);
183 }
184 else
185 {
186
187 myWbxmlBody.write(WbxmlConstants.TOKEN_LITERAL_A);
188 writeStrT(myWbxmlBody, tag);
189 }
190
191
192 writeAttributes(myWbxmlBody, attribs);
193 }
194
195 public void addEndElement() throws IOException
196 {
197 myWbxmlBody.write(WbxmlConstants.TOKEN_END);
198 }
199
200 public void addCharacters(char[] ch, int start, int length) throws IOException
201 {
202 addCharacters(new String(ch, start, length));
203 }
204
205 public void addCharacters(String str) throws IOException
206 {
207 myWbxmlBody.write(WbxmlConstants.TOKEN_STR_I);
208 writeStrI(myWbxmlBody, str);
209 }
210
211
212
213 public void addOpaqueData(byte[] buff) throws IOException
214 {
215 addOpaqueData(buff, 0, buff.length);
216 }
217
218 public void addOpaqueData(byte[] buff, int off, int len) throws IOException
219 {
220 myWbxmlBody.write(WbxmlConstants.TOKEN_OPAQ);
221 WspUtil.writeUintvar(myWbxmlBody, buff.length);
222 myWbxmlBody.write(buff, off, len);
223 }
224
225 /***
226 * Sets the tag tokens.
227 *
228 * @param theTagTokens
229 * first element in this array defines tag #5
230 */
231 public void setTagTokens(String[] theTagTokens)
232 {
233 if (theTagTokens != null)
234 {
235 myTagTokens = new String[theTagTokens.length];
236 System.arraycopy(theTagTokens, 0, myTagTokens, 0, theTagTokens.length);
237 }
238 else
239 {
240 myTagTokens = null;
241 }
242 }
243
244 /***
245 * Sets the attribute start tokens.
246 *
247 * @param theAttrStrartTokens
248 * first element in this array defines attribute #85
249 */
250 public void setAttrStartTokens(String[] theAttrStrartTokens)
251 {
252 if (theAttrStrartTokens != null)
253 {
254 myAttrStartTokens = new String[theAttrStrartTokens.length];
255 System.arraycopy(theAttrStrartTokens, 0, myAttrStartTokens, 0, theAttrStrartTokens.length);
256 }
257 else
258 {
259 myAttrStartTokens = null;
260 }
261 }
262
263 /***
264 * Sets the attribute value tokens.
265 *
266 * @param theAttrValueTokens
267 * first element in this array defines attribute #05
268 */
269 public void setAttrValueTokens(String[] theAttrValueTokens)
270 {
271 if (theAttrValueTokens != null)
272 {
273 myAttrValueTokens = new String[theAttrValueTokens.length];
274 System.arraycopy(theAttrValueTokens, 0, myAttrValueTokens, 0, theAttrValueTokens.length);
275 }
276 else
277 {
278 myAttrValueTokens = null;
279 }
280 }
281
282
283
284 private void writePublicIdentifier(OutputStream os, String publicID) throws IOException
285 {
286 if (publicID == null)
287 {
288
289 WspUtil.writeUintvar(os, 0x01);
290 }
291 else
292 {
293 int idx = StringUtil.findString(WbxmlConstants.KNOWN_PUBLIC_DOCTYPES, publicID);
294 if (idx != -1)
295 {
296
297 idx += 2;
298 WspUtil.writeUintvar(os, idx);
299 }
300 else
301 {
302
303 WspUtil.writeUintvar(os, 0x00);
304 writeStrT(os, publicID);
305 }
306 }
307 }
308
309 private void writeStrI(OutputStream theOs, String str) throws IOException
310 {
311
312 if (str != null)
313 {
314 theOs.write(str.getBytes("UTF-8"));
315 theOs.write(0x00);
316 }
317 }
318
319 private void writeStrT(OutputStream theOs, String str) throws IOException
320 {
321 Integer index = (Integer) myStringTable.get(str);
322
323 if (index == null)
324 {
325 index = new Integer(myStringTableBuf.size());
326 myStringTable.put(str, index);
327 writeStrI(myStringTableBuf, str);
328 }
329
330 WspUtil.writeUintvar(theOs, index.intValue());
331 }
332
333 private void writeStringTable(OutputStream theOs) throws IOException
334 {
335
336 WspUtil.writeUintvar(theOs, myStringTableBuf.size());
337
338 myStringTableBuf.writeTo(theOs);
339 }
340
341
342
343 private void writeAttributes(OutputStream os, XmlAttribute[] attribs) throws IOException
344 {
345 int idx;
346
347 for (int i = 0; i < attribs.length; i++)
348 {
349
350 String typeValue = attribs[i].getType() + "=" + attribs[i].getValue();
351 idx = StringUtil.findString(myAttrStartTokens, typeValue);
352 if (idx >= 0)
353 {
354
355 idx += 0x05;
356 myWbxmlBody.write(idx);
357 }
358 else
359 {
360
361
362
363 idx = StringUtil.findString(myAttrStartTokens, attribs[i].getType());
364 if (idx >= 0)
365 {
366 idx += 0x05;
367 myWbxmlBody.write(idx);
368 }
369 else
370 {
371 myWbxmlBody.write(WbxmlConstants.TOKEN_LITERAL);
372 writeStrT(myWbxmlBody, attribs[i].getType());
373 }
374
375
376 String attrValue = attribs[i].getValue();
377 if (attrValue != null && (!attrValue.equals("")))
378 {
379 idx = StringUtil.findString(myAttrValueTokens, attrValue);
380 if (idx >= 0)
381 {
382 idx += 0x85;
383 myWbxmlBody.write(idx);
384 }
385 else
386 {
387 myWbxmlBody.write(WbxmlConstants.TOKEN_STR_I);
388 writeStrI(myWbxmlBody, attrValue);
389 }
390 }
391 }
392 }
393
394
395 myWbxmlBody.write(WbxmlConstants.TOKEN_END);
396 }
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415 }