1 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 ; 21 import org.xml.sax.Locator ; 22 import org.xml.sax.SAXException ; 23 24 import java.util.HashMap ; 25 26 34 35 public final class XMLByteStreamCompiler implements XMLSerializer, Recyclable { 36 37 private HashMap map; 38 private int mapCount; 39 40 41 private byte buf[]; 42 43 44 private int bufCount; 45 46 private int bufCountAverage; 47 48 49 public XMLByteStreamCompiler() { 50 this.map = new HashMap (); 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 getSAXFragment() { 94 if (this.bufCount == 6) { 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 { 103 this.writeEvent(START_DOCUMENT); 104 } 105 106 public void endDocument() throws SAXException { 107 this.writeEvent(END_DOCUMENT); 108 } 109 110 public void startPrefixMapping(java.lang.String prefix, java.lang.String uri) throws SAXException { 111 this.writeEvent(START_PREFIX_MAPPING); 112 this.writeString(prefix); 113 this.writeString(uri); 114 } 115 116 public void endPrefixMapping(String prefix) throws SAXException { 117 this.writeEvent(END_PREFIX_MAPPING); 118 this.writeString(prefix); 119 } 120 121 public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { 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 namespaceURI, String localName, String qName) throws SAXException { 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 { 145 this.writeEvent(CHARACTERS); 146 this.writeChars(ch, start, length); 147 } 148 149 public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { 150 this.writeEvent(IGNORABLE_WHITESPACE); 151 this.writeChars(ch, start, length); 152 } 153 154 public void processingInstruction(String target, String data) throws SAXException { 155 this.writeEvent(PROCESSING_INSTRUCTION); 156 this.writeString(target); 157 this.writeString(data); 158 } 159 160 public void setDocumentLocator(Locator locator) { 161 try { 162 this.writeEvent(LOCATOR); 163 String publicId = locator.getPublicId(); 164 String 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 e) { 170 throw new CascadingRuntimeException("Error while handling locator", e); 171 } 172 } 173 174 public void skippedEntity(java.lang.String name) throws SAXException { 175 this.writeEvent(SKIPPED_ENTITY); 176 this.writeString(name); 177 } 178 179 182 public void startDTD(String name, String publicId, String systemId) throws SAXException { 183 this.writeEvent(START_DTD); 184 this.writeString(name); 185 this.writeString(publicId!=null?publicId:""); 186 this.writeString(systemId!=null?systemId:""); 187 } 188 189 192 public void endDTD() throws SAXException { 193 this.writeEvent(END_DTD); 194 } 195 196 199 public void startEntity(String name) throws SAXException { 200 this.writeEvent(START_ENTITY); 201 this.writeString(name); 202 } 203 204 207 public void endEntity(String name) throws SAXException { 208 this.writeEvent(END_ENTITY); 209 this.writeString(name); 210 } 211 212 215 public void startCDATA() throws SAXException { 216 this.writeEvent(START_CDATA); 217 } 218 219 222 public void endCDATA() throws SAXException { 223 this.writeEvent(END_CDATA); 224 } 225 226 227 230 public void comment(char ary[], int start, int length) throws SAXException { 231 try { 232 this.writeEvent(COMMENT); 233 this.writeChars(ary, start, length); 234 } catch (Exception e) { 235 throw new SAXException (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 { 244 if (attributes > 0xFFFF) throw new SAXException ("Too many attributes"); 245 this.write((attributes >>> 8) & 0xFF); 246 this.write((attributes >>> 0) & 0xFF); 247 } 248 249 public final void writeString( final String str) throws SAXException { 250 Integer index = (Integer ) map.get(str); 251 if (index == null) { 252 map.put(str, new Integer (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 ("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 364 } 365 366 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 |