KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > sax > XMLByteStreamCompiler


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.components.sax;
17
18 import org.apache.avalon.excalibur.pool.Recyclable;
19 import org.apache.avalon.framework.CascadingRuntimeException;
20 import org.xml.sax.Attributes JavaDoc;
21 import org.xml.sax.Locator JavaDoc;
22 import org.xml.sax.SAXException JavaDoc;
23
24 import java.util.HashMap JavaDoc;
25
26 /**
27  * This a simple xml compiler which outputs a byte array.
28  *
29  * @author <a HREF="mailto:stefano@apache.org">Stefano Mazzocchi</a>
30  * @author <a HREF="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
31  * @author <a HREF="mailto:tcurdt@apache.org">Torsten Curdt</a>
32  * @version CVS $Id: XMLByteStreamCompiler.java 279385 2005-09-07 17:52:53Z cziegeler $
33  */

34
35 public final class XMLByteStreamCompiler implements XMLSerializer, Recyclable {
36
37     private HashMap JavaDoc map;
38     private int mapCount;
39
40     /** The buffer for the compile xml byte stream. */
41     private byte buf[];
42
43     /** The number of valid bytes in the buffer. */
44     private int bufCount;
45
46     private int bufCountAverage;
47
48
49     public XMLByteStreamCompiler() {
50         this.map = new HashMap JavaDoc();
51         this.bufCountAverage = 2000;
52         this.initOutput();
53     }
54
55     private void initOutput() {
56         this.mapCount = 0;
57         this.map.clear();
58         this.buf = new byte[bufCountAverage];
59         this.buf[0] = (byte)'C';
60         this.buf[1] = (byte)'X';
61         this.buf[2] = (byte)'M';
62         this.buf[3] = (byte)'L';
63         this.buf[4] = (byte)1;
64         this.buf[5] = (byte)0;
65         this.bufCount = 6;
66     }
67
68     public void recycle() {
69         bufCountAverage = (bufCountAverage + bufCount) / 2;
70         this.initOutput();
71     }
72
73     private static final int START_DOCUMENT = 0;
74     private static final int END_DOCUMENT = 1;
75     private static final int START_PREFIX_MAPPING = 2;
76     private static final int END_PREFIX_MAPPING = 3;
77     private static final int START_ELEMENT = 4;
78     private static final int END_ELEMENT = 5;
79     private static final int CHARACTERS = 6;
80     private static final int IGNORABLE_WHITESPACE = 7;
81     private static final int PROCESSING_INSTRUCTION = 8;
82     private static final int COMMENT = 9;
83     private static final int LOCATOR = 10;
84     private static final int START_DTD = 11;
85     private static final int END_DTD = 12;
86     private static final int START_CDATA = 13;
87     private static final int END_CDATA = 14;
88     private static final int SKIPPED_ENTITY = 15;
89     private static final int START_ENTITY = 16;
90     private static final int END_ENTITY = 17;
91
92
93     public Object JavaDoc getSAXFragment() {
94         if (this.bufCount == 6) { // no event arrived yet
95
return null;
96         }
97         byte newbuf[] = new byte[this.bufCount];
98         System.arraycopy(this.buf, 0, newbuf, 0, this.bufCount);
99         return newbuf;
100     }
101
102     public void startDocument() throws SAXException JavaDoc {
103         this.writeEvent(START_DOCUMENT);
104     }
105
106     public void endDocument() throws SAXException JavaDoc {
107         this.writeEvent(END_DOCUMENT);
108     }
109
110     public void startPrefixMapping(java.lang.String JavaDoc prefix, java.lang.String JavaDoc uri) throws SAXException JavaDoc {
111         this.writeEvent(START_PREFIX_MAPPING);
112         this.writeString(prefix);
113         this.writeString(uri);
114     }
115
116     public void endPrefixMapping(String JavaDoc prefix) throws SAXException JavaDoc {
117        this.writeEvent(END_PREFIX_MAPPING);
118        this.writeString(prefix);
119     }
120
121     public void startElement(String JavaDoc namespaceURI, String JavaDoc localName, String JavaDoc qName, Attributes JavaDoc atts) throws SAXException JavaDoc {
122         int length = atts.getLength();
123         this.writeEvent(START_ELEMENT);
124         this.writeAttributes(length);
125         for (int i = 0; i < length; i++) {
126             this.writeString(atts.getURI(i));
127             this.writeString(atts.getLocalName(i));
128             this.writeString(atts.getQName(i));
129             this.writeString(atts.getType(i));
130             this.writeString(atts.getValue(i));
131          }
132          this.writeString((namespaceURI == null ? "" : namespaceURI));
133          this.writeString(localName);
134          this.writeString(qName);
135      }
136
137     public void endElement(String JavaDoc namespaceURI, String JavaDoc localName, String JavaDoc qName) throws SAXException JavaDoc {
138         this.writeEvent(END_ELEMENT);
139         this.writeString((namespaceURI == null ? "" : namespaceURI));
140         this.writeString(localName);
141         this.writeString(qName);
142     }
143
144     public void characters(char[] ch, int start, int length) throws SAXException JavaDoc {
145         this.writeEvent(CHARACTERS);
146         this.writeChars(ch, start, length);
147     }
148
149     public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException JavaDoc {
150         this.writeEvent(IGNORABLE_WHITESPACE);
151         this.writeChars(ch, start, length);
152     }
153
154     public void processingInstruction(String JavaDoc target, String JavaDoc data) throws SAXException JavaDoc {
155         this.writeEvent(PROCESSING_INSTRUCTION);
156         this.writeString(target);
157         this.writeString(data);
158     }
159
160     public void setDocumentLocator(Locator JavaDoc locator) {
161         try {
162             this.writeEvent(LOCATOR);
163             String JavaDoc publicId = locator.getPublicId();
164             String JavaDoc systemId = locator.getSystemId();
165             this.writeString(publicId!=null?publicId:"");
166             this.writeString(systemId!=null?systemId:"");
167             this.write(locator.getLineNumber());
168             this.write(locator.getColumnNumber());
169         } catch (Exception JavaDoc e) {
170              throw new CascadingRuntimeException("Error while handling locator", e);
171         }
172     }
173
174     public void skippedEntity(java.lang.String JavaDoc name) throws SAXException JavaDoc {
175         this.writeEvent(SKIPPED_ENTITY);
176         this.writeString(name);
177     }
178
179     /**
180      * SAX Event Handling: LexicalHandler
181      */

182     public void startDTD(String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId) throws SAXException JavaDoc {
183         this.writeEvent(START_DTD);
184         this.writeString(name);
185         this.writeString(publicId!=null?publicId:"");
186         this.writeString(systemId!=null?systemId:"");
187     }
188
189     /**
190      * SAX Event Handling: LexicalHandler
191      */

192     public void endDTD() throws SAXException JavaDoc {
193         this.writeEvent(END_DTD);
194     }
195
196     /**
197      * SAX Event Handling: LexicalHandler
198      */

199     public void startEntity(String JavaDoc name) throws SAXException JavaDoc {
200         this.writeEvent(START_ENTITY);
201         this.writeString(name);
202     }
203
204     /**
205      * SAX Event Handling: LexicalHandler
206      */

207     public void endEntity(String JavaDoc name) throws SAXException JavaDoc {
208         this.writeEvent(END_ENTITY);
209         this.writeString(name);
210     }
211
212     /**
213      * SAX Event Handling: LexicalHandler
214      */

215     public void startCDATA() throws SAXException JavaDoc {
216         this.writeEvent(START_CDATA);
217     }
218
219     /**
220      * SAX Event Handling: LexicalHandler
221      */

222     public void endCDATA() throws SAXException JavaDoc {
223         this.writeEvent(END_CDATA);
224     }
225
226
227     /**
228      * SAX Event Handling: LexicalHandler
229      */

230     public void comment(char ary[], int start, int length) throws SAXException JavaDoc {
231         try {
232             this.writeEvent(COMMENT);
233             this.writeChars(ary, start, length);
234         } catch (Exception JavaDoc e) {
235             throw new SAXException JavaDoc(e);
236         }
237     }
238
239     public final void writeEvent( final int event) {
240         this.write(event);
241     }
242
243     public final void writeAttributes( final int attributes) throws SAXException JavaDoc {
244         if (attributes > 0xFFFF) throw new SAXException JavaDoc("Too many attributes");
245         this.write((attributes >>> 8) & 0xFF);
246         this.write((attributes >>> 0) & 0xFF);
247     }
248
249     public final void writeString( final String JavaDoc str) throws SAXException JavaDoc {
250         Integer JavaDoc index = (Integer JavaDoc) map.get(str);
251         if (index == null) {
252             map.put(str, new Integer JavaDoc(mapCount++));
253             int length = str.length();
254             this.writeChars(str.toCharArray(), 0, length);
255         }
256         else {
257             int i = index.intValue();
258
259             if (i > 0xFFFF) throw new SAXException JavaDoc("Index too large");
260
261             this.write(((i >>> 8) & 0xFF) | 0x80);
262             this.write((i >>> 0) & 0xFF);
263         }
264     }
265
266     public final void writeChars( final char[] ch, final int start, final int length) {
267         int utflen = 0;
268         int c;
269
270         for (int i = 0; i < length; i++) {
271             c = ch[i + start];
272             if ((c >= 0x0001) && (c <= 0x007F)) {
273                 utflen++;
274             }
275             else if (c > 0x07FF) {
276                 utflen += 3;
277             }
278             else {
279                 utflen += 2;
280             }
281         }
282
283         if (utflen >= 0x00007FFF) {
284             assure(bufCount + utflen + 6);
285
286             buf[bufCount++] = (byte)0x7F;
287             buf[bufCount++] = (byte)0xFF;
288
289             buf[bufCount++] = (byte) ((utflen >>> 24) & 0xFF);
290             buf[bufCount++] = (byte) ((utflen >>> 16) & 0xFF);
291             buf[bufCount++] = (byte) ((utflen >>> 8) & 0xFF);
292             buf[bufCount++] = (byte) ((utflen >>> 0) & 0xFF);
293         }
294         else {
295             assure(bufCount + utflen + 2);
296
297             buf[bufCount++] = (byte) ((utflen >>> 8) & 0xFF);
298             buf[bufCount++] = (byte) ((utflen >>> 0) & 0xFF);
299         }
300
301         for (int i = 0; i < length; i++) {
302             c = ch[i + start];
303             if ((c >= 0x0001) && (c <= 0x007F)) {
304                 buf[bufCount++] = (byte) c;
305             }
306             else if (c > 0x07FF) {
307                 buf[bufCount++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
308                 buf[bufCount++] = (byte) (0x80 | ((c >> 6) & 0x3F));
309                 buf[bufCount++] = (byte) (0x80 | ((c >> 0) & 0x3F));
310             }
311             else {
312                 buf[bufCount++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
313                 buf[bufCount++] = (byte) (0x80 | ((c >> 0) & 0x3F));
314             }
315         }
316
317
318 /*
319         if (length == 0) return;
320
321         assure( (int) (buf.length + length * utfRatioAverage) );
322
323         int utflentotal = 0;
324
325         bufCount += 2;
326         int bufStart = bufCount;
327
328         for (int i = 0; i < length; i++) {
329             int c = ch[i + start];
330             int l = bufCount-bufStart;
331
332             if (l+3 >= 0x7FFF) {
333                 buf[bufStart-2] = (byte) ((l >>> 8) & 0xFF);
334                 buf[bufStart-1] = (byte) ((l >>> 0) & 0xFF);
335                 utflentotal += l;
336                 bufCount += 2;
337                 bufStart = bufCount;
338             }
339
340             if ((c >= 0x0001) && (c <= 0x007F)) {
341                 assure(bufCount+1);
342                 buf[bufCount++] = (byte)c;
343             }
344             else if (c > 0x07FF) {
345                 assure(bufCount+3);
346                 buf[bufCount++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
347                 buf[bufCount++] = (byte) (0x80 | ((c >> 6) & 0x3F));
348                 buf[bufCount++] = (byte) (0x80 | ((c >> 0) & 0x3F));
349             }
350             else {
351                 assure(bufCount+2);
352                 buf[bufCount++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
353                 buf[bufCount++] = (byte) (0x80 | ((c >> 0) & 0x3F));
354             }
355         }
356
357         int l = bufCount-bufStart;
358         buf[bufStart-2] = (byte) ((l >>> 8) & 0xFF);
359         buf[bufStart-1] = (byte) ((l >>> 0) & 0xFF);
360         utflentotal += l;
361
362         utfRatioAverage = (utfRatioAverage + (utflentotal / length) / 2);
363 */

364     }
365
366 /* JH (2003-11-20): seems to be never used
367
368     private void write( final byte[] b ) {
369         int newcount = this.bufCount + b.length;
370         assure(newcount);
371         System.arraycopy(b, 0, this.buf, this.bufCount, b.length);
372         this.bufCount = newcount;
373     }
374 */

375
376     private void write( final int b ) {
377         int newcount = this.bufCount + 1;
378         assure(newcount);
379         this.buf[this.bufCount] = (byte)b;
380         this.bufCount = newcount;
381     }
382
383     private void assure( final int size ) {
384         if (size > this.buf.length) {
385             byte newbuf[] = new byte[Math.max(this.buf.length << 1, size)];
386             System.arraycopy(this.buf, 0, newbuf, 0, this.bufCount);
387             this.buf = newbuf;
388         }
389     }
390 }
391
392
Popular Tags