KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > asm > xml > Processor


1 /***
2  * ASM XML Adapter
3  * Copyright (c) 2004, Eugene Kuleshov
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holders nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */

30 package org.objectweb.asm.xml;
31
32 import java.io.BufferedOutputStream JavaDoc;
33 import java.io.ByteArrayInputStream JavaDoc;
34 import java.io.ByteArrayOutputStream JavaDoc;
35 import java.io.FileInputStream JavaDoc;
36 import java.io.FileOutputStream JavaDoc;
37 import java.io.IOException JavaDoc;
38 import java.io.InputStream JavaDoc;
39 import java.io.OutputStream JavaDoc;
40 import java.io.OutputStreamWriter JavaDoc;
41 import java.io.Writer JavaDoc;
42 import java.util.zip.ZipEntry JavaDoc;
43 import java.util.zip.ZipInputStream JavaDoc;
44 import java.util.zip.ZipOutputStream JavaDoc;
45
46 import javax.xml.transform.Source JavaDoc;
47 import javax.xml.transform.Templates JavaDoc;
48 import javax.xml.transform.TransformerConfigurationException JavaDoc;
49 import javax.xml.transform.TransformerException JavaDoc;
50 import javax.xml.transform.TransformerFactory JavaDoc;
51 import javax.xml.transform.sax.SAXResult JavaDoc;
52 import javax.xml.transform.sax.SAXSource JavaDoc;
53 import javax.xml.transform.sax.SAXTransformerFactory JavaDoc;
54 import javax.xml.transform.sax.TransformerHandler JavaDoc;
55 import javax.xml.transform.stream.StreamSource JavaDoc;
56
57 import org.objectweb.asm.ClassReader;
58
59 import org.xml.sax.Attributes JavaDoc;
60 import org.xml.sax.ContentHandler JavaDoc;
61 import org.xml.sax.InputSource JavaDoc;
62 import org.xml.sax.SAXException JavaDoc;
63 import org.xml.sax.XMLReader JavaDoc;
64 import org.xml.sax.ext.LexicalHandler JavaDoc;
65 import org.xml.sax.helpers.AttributesImpl JavaDoc;
66 import org.xml.sax.helpers.DefaultHandler JavaDoc;
67 import org.xml.sax.helpers.XMLReaderFactory JavaDoc;
68
69 /**
70  * Processor is a command line tool that can be used for bytecode waving
71  * directed by XSL transformation. <p> In order to use a concrete XSLT engine,
72  * system property <tt>javax.xml.transform.TransformerFactory</tt> must be set
73  * to one of the following values.
74  *
75  * <blockquote> <table border="1" cellspacing="0" cellpadding="3"> <tr> <td>jd.xslt</td>
76  * <td>jd.xml.xslt.trax.TransformerFactoryImpl</td> </tr>
77  *
78  * <tr> <td>Saxon</td> <td>net.sf.saxon.TransformerFactoryImpl</td> </tr>
79  *
80  * <tr> <td>Caucho</td> <td>com.caucho.xsl.Xsl</td> </tr>
81  *
82  * <tr> <td>Xalan interpeter</td> <td>org.apache.xalan.processor.TransformerFactory</td>
83  * </tr>
84  *
85  * <tr> <td>Xalan xsltc</td> <td>org.apache.xalan.xsltc.trax.TransformerFactoryImpl</td>
86  * </tr> </table> </blockquote>
87  *
88  * @author Eugene Kuleshov
89  */

90 public class Processor {
91
92     public static final int BYTECODE = 1;
93
94     public static final int MULTI_XML = 2;
95
96     public static final int SINGLE_XML = 3;
97
98     private static final String JavaDoc SINGLE_XML_NAME = "classes.xml";
99
100     private int inRepresentation;
101
102     private int outRepresentation;
103
104     private InputStream JavaDoc input = null;
105
106     private OutputStream JavaDoc output = null;
107
108     private Source JavaDoc xslt = null;
109
110     private boolean computeMax;
111
112     private int n = 0;
113
114     public Processor(
115         int inRepresenation,
116         int outRepresentation,
117         InputStream JavaDoc input,
118         OutputStream JavaDoc output,
119         Source JavaDoc xslt)
120     {
121         this.inRepresentation = inRepresenation;
122         this.outRepresentation = outRepresentation;
123         this.input = input;
124         this.output = output;
125         this.xslt = xslt;
126         this.computeMax = true;
127     }
128
129     public int process() throws TransformerException JavaDoc, IOException JavaDoc, SAXException JavaDoc
130     {
131         ZipInputStream JavaDoc zis = new ZipInputStream JavaDoc(input);
132         final ZipOutputStream JavaDoc zos = new ZipOutputStream JavaDoc(output);
133         final OutputStreamWriter JavaDoc osw = new OutputStreamWriter JavaDoc(zos);
134
135         Thread.currentThread()
136                 .setContextClassLoader(getClass().getClassLoader());
137
138         TransformerFactory JavaDoc tf = TransformerFactory.newInstance();
139         if (!tf.getFeature(SAXSource.FEATURE)
140                 || !tf.getFeature(SAXResult.FEATURE))
141             return 0;
142
143         SAXTransformerFactory JavaDoc saxtf = (SAXTransformerFactory JavaDoc) tf;
144         Templates JavaDoc templates = null;
145         if (xslt != null) {
146             templates = saxtf.newTemplates(xslt);
147         }
148
149         // configuring outHandlerFactory
150
// ///////////////////////////////////////////////////////
151

152         EntryElement entryElement = getEntryElement(zos);
153
154         ContentHandler JavaDoc outDocHandler = null;
155         switch (outRepresentation) {
156             case BYTECODE:
157                 outDocHandler = new OutputSlicingHandler(new ASMContentHandlerFactory(zos,
158                         computeMax),
159                         entryElement,
160                         false);
161                 break;
162
163             case MULTI_XML:
164                 outDocHandler = new OutputSlicingHandler(new SAXWriterFactory(osw,
165                         true),
166                         entryElement,
167                         true);
168                 break;
169
170             case SINGLE_XML:
171                 ZipEntry JavaDoc outputEntry = new ZipEntry JavaDoc(SINGLE_XML_NAME);
172                 zos.putNextEntry(outputEntry);
173                 outDocHandler = new SAXWriter(osw, false);
174                 break;
175
176         }
177
178         // configuring inputDocHandlerFactory
179
// /////////////////////////////////////////////////
180
ContentHandler JavaDoc inDocHandler = null;
181         if (templates == null) {
182             inDocHandler = outDocHandler;
183         } else {
184             inDocHandler = new InputSlicingHandler("class",
185                     outDocHandler,
186                     new TransformerHandlerFactory(saxtf,
187                             templates,
188                             outDocHandler));
189         }
190         ContentHandlerFactory inDocHandlerFactory = new SubdocumentHandlerFactory(inDocHandler);
191
192         if (inDocHandler != null && inRepresentation != SINGLE_XML) {
193             inDocHandler.startDocument();
194             inDocHandler.startElement("",
195                     "classes",
196                     "classes",
197                     new AttributesImpl JavaDoc());
198         }
199
200         int i = 0;
201         ZipEntry JavaDoc ze = null;
202         while ((ze = zis.getNextEntry()) != null) {
203             update(ze.getName(), n++);
204             if (isClassEntry(ze)) {
205                 processEntry(zis, ze, inDocHandlerFactory);
206             } else {
207                 OutputStream JavaDoc os = entryElement.openEntry(getName(ze));
208                 copyEntry(zis, os);
209                 entryElement.closeEntry();
210             }
211
212             i++;
213         }
214
215         if (inDocHandler != null && inRepresentation != SINGLE_XML) {
216             inDocHandler.endElement("", "classes", "classes");
217             inDocHandler.endDocument();
218         }
219
220         if (outRepresentation == SINGLE_XML) {
221             zos.closeEntry();
222         }
223         zos.flush();
224         zos.close();
225
226         return i;
227     }
228
229     private void copyEntry(InputStream JavaDoc is, OutputStream JavaDoc os) throws IOException JavaDoc {
230         if (outRepresentation == SINGLE_XML)
231             return;
232
233         byte[] buff = new byte[2048];
234         int i;
235         while ((i = is.read(buff)) != -1) {
236             os.write(buff, 0, i);
237         }
238     }
239
240     private boolean isClassEntry(ZipEntry JavaDoc ze) {
241         String JavaDoc name = ze.getName();
242         return inRepresentation == SINGLE_XML && name.equals(SINGLE_XML_NAME)
243                 || name.endsWith(".class") || name.endsWith(".class.xml");
244     }
245
246     private void processEntry(
247         final ZipInputStream JavaDoc zis,
248         ZipEntry JavaDoc ze,
249         ContentHandlerFactory handlerFactory)
250     {
251         ContentHandler JavaDoc handler = handlerFactory.createContentHandler();
252         try {
253
254             // if (CODE2ASM.equals(command)) { // read bytecode and process it
255
// // with TraceClassVisitor
256
// ClassReader cr = new ClassReader(readEntry(zis, ze));
257
// cr.accept(new TraceClassVisitor(null, new PrintWriter(os)),
258
// false);
259
// }
260

261             boolean singleInputDocument = inRepresentation == SINGLE_XML;
262             if (inRepresentation == BYTECODE) { // read bytecode and process it
263
// with handler
264
ClassReader cr = new ClassReader(readEntry(zis, ze));
265                 cr.accept(new SAXClassAdapter(handler, singleInputDocument),
266                         false);
267
268             } else { // read XML and process it with handler
269
XMLReader JavaDoc reader = XMLReaderFactory.createXMLReader();
270                 reader.setContentHandler(handler);
271                 reader.parse(new InputSource JavaDoc(singleInputDocument
272                         ? (InputStream JavaDoc) new ProtectedInputStream(zis)
273                         : new ByteArrayInputStream JavaDoc(readEntry(zis, ze))));
274
275             }
276         } catch (Exception JavaDoc ex) {
277             update(ze.getName(), 0);
278             update(ex, 0);
279         }
280     }
281
282     private EntryElement getEntryElement(ZipOutputStream JavaDoc zos) {
283         if (outRepresentation == SINGLE_XML) {
284             return new SingleDocElement(zos);
285         }
286         return new ZipEntryElement(zos);
287     }
288
289     // private ContentHandlerFactory getHandlerFactory(
290
// OutputStream os,
291
// SAXTransformerFactory saxtf,
292
// Templates templates)
293
// {
294
// ContentHandlerFactory factory = null;
295
// if (templates == null) {
296
// if (outputRepresentation == BYTECODE) { // factory used to write
297
// // bytecode
298
// factory = new ASMContentHandlerFactory(os, computeMax);
299
// } else { // factory used to write XML
300
// factory = new SAXWriterFactory(os, true);
301
// }
302
// } else {
303
// if (outputRepresentation == BYTECODE) { // factory used to transform
304
// // and then write bytecode
305
// factory = new ASMTransformerHandlerFactory(saxtf,
306
// templates,
307
// os,
308
// computeMax);
309
// } else { // factory used to transformand then write XML
310
// factory = new TransformerHandlerFactory(saxtf,
311
// templates,
312
// os,
313
// outputRepresentation == SINGLE_XML);
314
// }
315
// }
316
// return factory;
317
// }
318

319     private String JavaDoc getName(ZipEntry JavaDoc ze) {
320         String JavaDoc name = ze.getName();
321         if (isClassEntry(ze)) {
322             if (inRepresentation != BYTECODE && outRepresentation == BYTECODE) {
323                 name = name.substring(0, name.length() - 4); // .class.xml to
324
// .class
325
} else if (inRepresentation == BYTECODE
326                     && outRepresentation != BYTECODE)
327             {
328                 name = name.concat(".xml"); // .class to .class.xml
329
}
330             // } else if( CODE2ASM.equals( command)) {
331
// name = name.substring( 0, name.length()-6).concat( ".asm");
332
}
333         return name;
334     }
335
336     private byte[] readEntry(ZipInputStream JavaDoc zis, ZipEntry JavaDoc ze)
337             throws IOException JavaDoc
338     {
339         long size = ze.getSize();
340         if (size > -1) {
341             byte[] buff = new byte[(int) size];
342             // int k = 0;
343
// while(( n = zis.read(buff, k, buff.length-k)) > 0) {
344
// k += n;
345
// }
346
zis.read(buff);
347             return buff;
348         }
349
350         ByteArrayOutputStream JavaDoc bos = new ByteArrayOutputStream JavaDoc();
351         byte[] buff = new byte[4096];
352         int i;
353         while ((i = zis.read(buff)) != -1) {
354             bos.write(buff, 0, i);
355         }
356         return bos.toByteArray();
357     }
358
359     /*
360      * (non-Javadoc)
361      *
362      * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
363      */

364     protected void update(Object JavaDoc arg, int n) {
365         if (arg instanceof Throwable JavaDoc) {
366             ((Throwable JavaDoc) arg).printStackTrace();
367         } else {
368             if ((n % 100) == 0) {
369                 System.err.println(n + " " + arg);
370             }
371         }
372     }
373
374     public static void main(String JavaDoc[] args) throws Exception JavaDoc {
375         if (args.length < 2) {
376             showUsage();
377             return;
378         }
379
380         int inRepresentation = getRepresentation(args[0]);
381         int outRepresentation = getRepresentation(args[1]);
382
383         InputStream JavaDoc is = null;
384         OutputStream JavaDoc os = null;
385
386         Source JavaDoc xslt = null;
387         // boolean computeMax = true;
388

389         for (int i = 2; i < args.length; i++) {
390             if ("-in".equals(args[i])) {
391                 is = new FileInputStream JavaDoc(args[++i]);
392
393             } else if ("-out".equals(args[i])) {
394                 os = new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(args[++i]));
395
396             } else if ("-xslt".equals(args[i])) {
397                 xslt = new StreamSource JavaDoc(new FileInputStream JavaDoc(args[++i]));
398
399                 // } else if( "-computemax".equals( args[ i].toLowerCase())) {
400
// computeMax = true;
401

402             } else {
403                 showUsage();
404                 return;
405
406             }
407         }
408
409         if (is == null || os == null || inRepresentation == 0
410                 || outRepresentation == 0)
411         {
412             showUsage();
413             return;
414         }
415
416         Processor m = new Processor(inRepresentation,
417                 outRepresentation,
418                 is,
419                 os,
420                 xslt);
421
422         long l1 = System.currentTimeMillis();
423         int n = m.process();
424         long l2 = System.currentTimeMillis();
425         System.err.println(n);
426         System.err.println("" + (l2 - l1) + "ms " + (1000f * n / (l2 - l1))
427                 + " resources/sec");
428     }
429
430     private static int getRepresentation(String JavaDoc s) {
431         if ("code".equals(s)) {
432             return BYTECODE;
433         } else if ("xml".equals(s)) {
434             return MULTI_XML;
435         } else if ("singlexml".equals(s)) {
436             return SINGLE_XML;
437         }
438         return 0;
439     }
440
441     private static void showUsage() {
442         System.err.println("Usage: Main <in format> <out format> -in <input jar> -out <output jar> [-xslt <xslt fiel>]");
443         System.err.println(" <in format> and <out format> - code | xml | singlexml");
444     }
445
446     /**
447      * IputStream wrapper class used to protect input streams from being closed
448      * by some stupid XML parsers.
449      */

450     private static final class ProtectedInputStream extends InputStream JavaDoc {
451         private final InputStream JavaDoc is;
452
453         private ProtectedInputStream(InputStream JavaDoc is) {
454             super();
455             this.is = is;
456         }
457
458         public final void close() throws IOException JavaDoc {
459         }
460
461         public final int read() throws IOException JavaDoc {
462             return is.read();
463         }
464
465         public final int read(byte[] b, int off, int len) throws IOException JavaDoc {
466             return is.read(b, off, len);
467         }
468
469         public final int available() throws IOException JavaDoc {
470             return is.available();
471         }
472     }
473
474     /**
475      * A {@link ContentHandlerFactory ContentHandlerFactory} is used to create
476      * {@link org.xml.sax.ContentHandler ContentHandler} instances for concrete
477      * context.
478      */

479     private static interface ContentHandlerFactory {
480
481         /**
482          * Creates an instance of the content handler.
483          *
484          * @return content handler
485          */

486         ContentHandler JavaDoc createContentHandler();
487
488     }
489
490     /**
491      * SAXWriterFactory
492      */

493     private static final class SAXWriterFactory implements
494             ContentHandlerFactory
495     {
496         private Writer JavaDoc w;
497
498         private boolean optimizeEmptyElements;
499
500         public SAXWriterFactory(Writer JavaDoc w, boolean optimizeEmptyElements) {
501             this.w = w;
502             this.optimizeEmptyElements = optimizeEmptyElements;
503         }
504
505         public final ContentHandler JavaDoc createContentHandler() {
506             return new SAXWriter(w, optimizeEmptyElements);
507         }
508
509     }
510
511     /**
512      * ASMContentHandlerFactory
513      */

514     private static final class ASMContentHandlerFactory implements
515             ContentHandlerFactory
516     {
517         private OutputStream JavaDoc os;
518
519         private boolean computeMax;
520
521         public ASMContentHandlerFactory(OutputStream JavaDoc os, boolean computeMax) {
522             this.os = os;
523             this.computeMax = computeMax;
524         }
525
526         public final ContentHandler JavaDoc createContentHandler() {
527             return new ASMContentHandler(os, computeMax);
528         }
529
530     }
531
532     /**
533      * TransformerHandlerFactory
534      */

535     private static final class TransformerHandlerFactory implements
536             ContentHandlerFactory
537     {
538         private SAXTransformerFactory JavaDoc saxtf;
539
540         private Templates JavaDoc templates;
541
542         private ContentHandler JavaDoc outputHandler;
543
544         public TransformerHandlerFactory(
545             SAXTransformerFactory JavaDoc saxtf,
546             Templates JavaDoc templates,
547             ContentHandler JavaDoc outputHandler)
548         {
549             this.saxtf = saxtf;
550             this.templates = templates;
551             this.outputHandler = outputHandler;
552         }
553
554         public final ContentHandler JavaDoc createContentHandler() {
555             try {
556                 TransformerHandler JavaDoc handler = saxtf.newTransformerHandler(templates);
557                 handler.setResult(new SAXResult JavaDoc(outputHandler));
558                 return handler;
559             } catch (TransformerConfigurationException JavaDoc ex) {
560                 throw new RuntimeException JavaDoc(ex.toString());
561             }
562         }
563     }
564
565     /**
566      * SubdocumentHandlerFactory
567      */

568     private final static class SubdocumentHandlerFactory implements
569             ContentHandlerFactory
570     {
571         private ContentHandler JavaDoc subdocumentHandler;
572
573         public SubdocumentHandlerFactory(ContentHandler JavaDoc subdocumentHandler) {
574             this.subdocumentHandler = subdocumentHandler;
575         }
576
577         public final ContentHandler JavaDoc createContentHandler() {
578             return subdocumentHandler;
579         }
580
581     }
582
583     /**
584      * A {@link org.xml.sax.ContentHandler ContentHandler} and
585      * {@link org.xml.sax.ext.LexicalHandler LexicalHandler} that serializes XML
586      * from SAX 2.0 events into {@link java.io.Writer Writer}.
587      *
588      * <i><blockquote> This implementation does not support namespaces, entity
589      * definitions (uncluding DTD), CDATA and text elements. </blockquote></i>
590      */

591     private final static class SAXWriter extends DefaultHandler JavaDoc implements
592             LexicalHandler JavaDoc
593     {
594         private static final char[] OFF = " ".toCharArray();
595
596         private Writer JavaDoc w;
597
598         private boolean optimizeEmptyElements;
599
600         private boolean openElement = false;
601
602         private int ident = 0;
603
604         /**
605          * Creates <code>SAXWriter</code>.
606          *
607          * @param w writer
608          * @param optimizeEmptyElements if set to <code>true</code>, short
609          * XML syntax will be used for empty elements
610          */

611         public SAXWriter(Writer JavaDoc w, boolean optimizeEmptyElements) {
612             this.w = w;
613             this.optimizeEmptyElements = optimizeEmptyElements;
614         }
615
616         public final void startElement(
617             String JavaDoc ns,
618             String JavaDoc localName,
619             String JavaDoc qName,
620             Attributes JavaDoc atts) throws SAXException JavaDoc
621         {
622             try {
623                 closeElement();
624
625                 writeIdent();
626                 w.write("<".concat(qName));
627                 if (atts != null && atts.getLength() > 0)
628                     writeAttributes(atts);
629
630                 if (!optimizeEmptyElements) {
631                     w.write(">\n");
632                 } else {
633                     openElement = true;
634                 }
635                 ident += 2;
636
637             } catch (IOException JavaDoc ex) {
638                 throw new SAXException JavaDoc(ex);
639
640             }
641         }
642
643         public final void endElement(String JavaDoc ns, String JavaDoc localName, String JavaDoc qName)
644                 throws SAXException JavaDoc
645         {
646             ident -= 2;
647             try {
648                 if (openElement) {
649                     w.write("/>\n");
650                     openElement = false;
651                 } else {
652                     writeIdent();
653                     w.write("</" + qName + ">\n");
654                 }
655
656             } catch (IOException JavaDoc ex) {
657                 throw new SAXException JavaDoc(ex);
658
659             }
660         }
661
662         public final void endDocument() throws SAXException JavaDoc {
663             try {
664                 w.flush();
665
666             } catch (IOException JavaDoc ex) {
667                 throw new SAXException JavaDoc(ex);
668
669             }
670         }
671
672         public final void comment(char[] ch, int off, int len)
673                 throws SAXException JavaDoc
674         {
675             try {
676                 closeElement();
677
678                 writeIdent();
679                 w.write("<!-- ");
680                 w.write(ch, off, len);
681                 w.write(" -->\n");
682
683             } catch (IOException JavaDoc ex) {
684                 throw new SAXException JavaDoc(ex);
685
686             }
687         }
688
689         public final void startDTD(String JavaDoc arg0, String JavaDoc arg1, String JavaDoc arg2)
690                 throws SAXException JavaDoc
691         {
692         }
693
694         public final void endDTD() throws SAXException JavaDoc {
695         }
696
697         public final void startEntity(String JavaDoc arg0) throws SAXException JavaDoc {
698         }
699
700         public final void endEntity(String JavaDoc arg0) throws SAXException JavaDoc {
701         }
702
703         public final void startCDATA() throws SAXException JavaDoc {
704         }
705
706         public final void endCDATA() throws SAXException JavaDoc {
707         }
708
709         private final void writeAttributes(Attributes JavaDoc atts) throws IOException JavaDoc {
710             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
711             int len = atts.getLength();
712             for (int i = 0; i < len; i++) {
713                 sb.append(" ")
714                         .append(atts.getLocalName(i))
715                         .append("=\"")
716                         .append(esc(atts.getValue(i)))
717                         .append("\"");
718             }
719             w.write(sb.toString());
720         }
721
722         /**
723          * Encode string with escaping.
724          *
725          * @param str string to encode.
726          * @return encoded string
727          */

728         private final String JavaDoc esc(String JavaDoc str) {
729             StringBuffer JavaDoc sb = new StringBuffer JavaDoc(str.length());
730             for (int i = 0; i < str.length(); i++) {
731                 char ch = str.charAt(i);
732                 switch (ch) {
733                     case '&':
734                         sb.append("&amp;");
735                         break;
736
737                     case '<':
738                         sb.append("&lt;");
739                         break;
740
741                     case '>':
742                         sb.append("&gt;");
743                         break;
744
745                     case '\"':
746                         sb.append("&quot;");
747                         break;
748
749                     default:
750                         if (ch > 0x7f) {
751                             sb.append("&#")
752                                     .append(Integer.toString(ch))
753                                     .append(';');
754                         } else {
755                             sb.append(ch);
756                         }
757
758                 }
759             }
760             return sb.toString();
761         }
762
763         private final void writeIdent() throws IOException JavaDoc {
764             int n = ident;
765             while (n > 0) {
766                 if (n > OFF.length) {
767                     w.write(OFF);
768                     n -= OFF.length;
769                 } else {
770                     w.write(OFF, 0, n);
771                     n = 0;
772                 }
773             }
774         }
775
776         private final void closeElement() throws IOException JavaDoc {
777             if (openElement) {
778                 w.write(">\n");
779             }
780             openElement = false;
781         }
782
783     }
784
785     /**
786      * A {@link org.xml.sax.ContentHandler ContentHandler} that splits XML
787      * documents into smaller chunks. Each chunk is processed by the nested
788      * {@link org.xml.sax.ContentHandler ContentHandler} obtained from
789      * {@link java.net.ContentHandlerFactory ContentHandlerFactory}. This is
790      * useful for running XSLT engine against large XML document that will
791      * hardly fit into the memory all together. <p> TODO use complete path for
792      * subdocumentRoot
793      */

794     private final static class InputSlicingHandler extends DefaultHandler JavaDoc {
795         private String JavaDoc subdocumentRoot;
796
797         private ContentHandler JavaDoc rootHandler;
798
799         private ContentHandlerFactory subdocumentHandlerFactory;
800
801         private boolean subdocument = false;
802
803         private ContentHandler JavaDoc subdocumentHandler;
804
805         /**
806          * Constructs a new {@link InputSlicingHandler SubdocumentHandler}
807          * object.
808          *
809          * @param subdocumentRoot name/path to the root element of the
810          * subdocument
811          * @param rootHandler content handler for the entire document
812          * (subdocument envelope).
813          * @param subdocumentHandlerFactory a
814          * {@link ContentHandlerFactory ContentHandlerFactory} used to
815          * create {@link ContentHandler ContentHandler} instances for
816          * subdocuments.
817          */

818         public InputSlicingHandler(
819             String JavaDoc subdocumentRoot,
820             ContentHandler JavaDoc rootHandler,
821             ContentHandlerFactory subdocumentHandlerFactory)
822         {
823             this.subdocumentRoot = subdocumentRoot;
824             this.rootHandler = rootHandler;
825             this.subdocumentHandlerFactory = subdocumentHandlerFactory;
826         }
827
828         public final void startElement(
829             String JavaDoc namespaceURI,
830             String JavaDoc localName,
831             String JavaDoc qName,
832             Attributes JavaDoc list) throws SAXException JavaDoc
833         {
834             if (subdocument) {
835                 subdocumentHandler.startElement(namespaceURI,
836                         localName,
837                         qName,
838                         list);
839             } else if (localName.equals(subdocumentRoot)) {
840                 subdocumentHandler = subdocumentHandlerFactory.createContentHandler();
841                 subdocumentHandler.startDocument();
842                 subdocumentHandler.startElement(namespaceURI,
843                         localName,
844                         qName,
845                         list);
846                 subdocument = true;
847             } else if (rootHandler != null) {
848                 rootHandler.startElement(namespaceURI, localName, qName, list);
849             }
850         }
851
852         public final void endElement(
853             String JavaDoc namespaceURI,
854             String JavaDoc localName,
855             String JavaDoc qName) throws SAXException JavaDoc
856         {
857             if (subdocument) {
858                 subdocumentHandler.endElement(namespaceURI, localName, qName);
859                 if (localName.equals(subdocumentRoot)) {
860                     subdocumentHandler.endDocument();
861                     subdocument = false;
862                 }
863             } else if (rootHandler != null) {
864                 rootHandler.endElement(namespaceURI, localName, qName);
865             }
866         }
867
868         public final void startDocument() throws SAXException JavaDoc {
869             if (rootHandler != null) {
870                 rootHandler.startDocument();
871             }
872         }
873
874         public final void endDocument() throws SAXException JavaDoc {
875             if (rootHandler != null) {
876                 rootHandler.endDocument();
877
878             }
879         }
880
881         public final void characters(char[] buff, int offset, int size)
882                 throws SAXException JavaDoc
883         {
884             if (subdocument) {
885                 subdocumentHandler.characters(buff, offset, size);
886             } else if (rootHandler != null) {
887                 rootHandler.characters(buff, offset, size);
888             }
889         }
890
891     }
892
893     /**
894      * A {@link org.xml.sax.ContentHandler ContentHandler} that splits XML
895      * documents into smaller chunks. Each chunk is processed by the nested
896      * {@link org.xml.sax.ContentHandler ContentHandler} obtained from
897      * {@link java.net.ContentHandlerFactory ContentHandlerFactory}. This is
898      * useful for running XSLT engine against large XML document that will
899      * hardly fit into the memory all together. <p> TODO use complete path for
900      * subdocumentRoot
901      */

902     private static final class OutputSlicingHandler extends DefaultHandler JavaDoc {
903         private String JavaDoc subdocumentRoot;
904
905         private ContentHandlerFactory subdocumentHandlerFactory;
906
907         private EntryElement entryElement;
908
909         private boolean isXml;
910
911         private boolean subdocument = false;
912
913         private ContentHandler JavaDoc subdocumentHandler;
914
915         /**
916          * Constructs a new {@link OutputSlicingHandler SubdocumentHandler}
917          * object.
918          *
919          * @param subdocumentRoot name/path to the root element of the
920          * subdocument
921          * @param rootHandler content handler for the entire document
922          * (subdocument envelope).
923          * @param subdocumentHandlerFactory a
924          * {@link ContentHandlerFactory ContentHandlerFactory} used to
925          * create {@link ContentHandler ContentHandler} instances for
926          * subdocuments.
927          */

928         public OutputSlicingHandler(
929             ContentHandlerFactory subdocumentHandlerFactory,
930             EntryElement entryElement,
931             boolean isXml)
932         {
933             this.subdocumentRoot = "class";
934             this.subdocumentHandlerFactory = subdocumentHandlerFactory;
935             this.entryElement = entryElement;
936             this.isXml = isXml;
937         }
938
939         public final void startElement(
940             String JavaDoc namespaceURI,
941             String JavaDoc localName,
942             String JavaDoc qName,
943             Attributes JavaDoc list) throws SAXException JavaDoc
944         {
945             if (subdocument) {
946                 subdocumentHandler.startElement(namespaceURI,
947                         localName,
948                         qName,
949                         list);
950             } else if (localName.equals(subdocumentRoot)) {
951                 String JavaDoc name = list.getValue("name");
952                 if (name == null || name.length() == 0)
953                     throw new SAXException JavaDoc("Class element without name attribute.");
954                 try {
955                     entryElement.openEntry(isXml
956                             ? name.concat(".class.xml")
957                             : name.concat(".class"));
958                 } catch (IOException JavaDoc ex) {
959                     throw new SAXException JavaDoc(ex.toString(), ex);
960                 }
961                 subdocumentHandler = subdocumentHandlerFactory.createContentHandler();
962                 subdocumentHandler.startDocument();
963                 subdocumentHandler.startElement(namespaceURI,
964                         localName,
965                         qName,
966                         list);
967                 subdocument = true;
968             }
969         }
970
971         public final void endElement(
972             String JavaDoc namespaceURI,
973             String JavaDoc localName,
974             String JavaDoc qName) throws SAXException JavaDoc
975         {
976             if (subdocument) {
977                 subdocumentHandler.endElement(namespaceURI, localName, qName);
978                 if (localName.equals(subdocumentRoot)) {
979                     subdocumentHandler.endDocument();
980                     subdocument = false;
981                     try {
982                         entryElement.closeEntry();
983                     } catch (IOException JavaDoc ex) {
984                         throw new SAXException JavaDoc(ex.toString(), ex);
985                     }
986                 }
987             }
988         }
989
990         public final void startDocument() throws SAXException JavaDoc {
991         }
992
993         public final void endDocument() throws SAXException JavaDoc {
994         }
995
996         public final void characters(char[] buff, int offset, int size)
997                 throws SAXException JavaDoc
998         {
999             if (subdocument) {
1000                subdocumentHandler.characters(buff, offset, size);
1001            }
1002        }
1003
1004    }
1005
1006    private static interface EntryElement {
1007
1008        OutputStream JavaDoc openEntry(String JavaDoc name) throws IOException JavaDoc;
1009
1010        void closeEntry() throws IOException JavaDoc;
1011
1012    }
1013
1014    private static final class SingleDocElement implements EntryElement {
1015        private OutputStream JavaDoc os;
1016
1017        public SingleDocElement(OutputStream JavaDoc os) {
1018            this.os = os;
1019        }
1020
1021        public OutputStream JavaDoc openEntry(String JavaDoc name) throws IOException JavaDoc {
1022            return os;
1023        }
1024
1025        public void closeEntry() throws IOException JavaDoc {
1026            os.flush();
1027        }
1028
1029    }
1030
1031    private static final class ZipEntryElement implements EntryElement {
1032        private ZipOutputStream JavaDoc zos;
1033
1034        public ZipEntryElement(ZipOutputStream JavaDoc zos) {
1035            this.zos = zos;
1036        }
1037
1038        public OutputStream JavaDoc openEntry(String JavaDoc name) throws IOException JavaDoc {
1039            ZipEntry JavaDoc entry = new ZipEntry JavaDoc(name);
1040            zos.putNextEntry(entry);
1041            return zos;
1042        }
1043
1044        public void closeEntry() throws IOException JavaDoc {
1045            zos.flush();
1046            zos.closeEntry();
1047        }
1048
1049    }
1050
1051}
1052
Popular Tags