KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > 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 com.tc.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 com.tc.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             int n;
344             while(( n = zis.read(buff, k, buff.length-k)) > 0) {
345               k += n;
346             }
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 = System.in;
384         OutputStream JavaDoc os = new BufferedOutputStream JavaDoc(System.out);
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 (inRepresentation == 0 || outRepresentation == 0) {
410             showUsage();
411             return;
412         }
413
414         Processor m = new Processor(inRepresentation,
415                 outRepresentation,
416                 is,
417                 os,
418                 xslt);
419
420         long l1 = System.currentTimeMillis();
421         int n = m.process();
422         long l2 = System.currentTimeMillis();
423         System.err.println(n);
424         System.err.println("" + (l2 - l1) + "ms " + (1000f * n / (l2 - l1))
425                 + " resources/sec");
426     }
427
428     private static int getRepresentation(String JavaDoc s) {
429         if ("code".equals(s)) {
430             return BYTECODE;
431         } else if ("xml".equals(s)) {
432             return MULTI_XML;
433         } else if ("singlexml".equals(s)) {
434             return SINGLE_XML;
435         }
436         return 0;
437     }
438
439     private static void showUsage() {
440         System.err.println("Usage: Main <in format> <out format> [-in <input jar>] [-out <output jar>] [-xslt <xslt file>]");
441         System.err.println(" when -in or -out is omitted sysin and sysout would be used");
442         System.err.println(" <in format> and <out format> - code | xml | singlexml");
443     }
444
445     /**
446      * IputStream wrapper class used to protect input streams from being closed
447      * by some XML parsers.
448      */

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

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

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

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

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

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

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

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

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

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

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

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

901     private static final class OutputSlicingHandler extends DefaultHandler JavaDoc {
902         private String JavaDoc subdocumentRoot;
903
904         private ContentHandlerFactory subdocumentHandlerFactory;
905
906         private EntryElement entryElement;
907
908         private boolean isXml;
909
910         private boolean subdocument = false;
911
912         private ContentHandler JavaDoc subdocumentHandler;
913
914         /**
915          * Constructs a new {@link OutputSlicingHandler SubdocumentHandler}
916          * object.
917          *
918          * @param subdocumentHandlerFactory a
919          * {@link ContentHandlerFactory ContentHandlerFactory} used to
920          * create {@link ContentHandler ContentHandler} instances for
921          * subdocuments.
922          * @param entryElement TODO.
923          * @param isXml TODO.
924          */

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