KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > libraries > asm > xml > Processor


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

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

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

246       boolean singleInputDocument = inRepresentation==SINGLE_XML;
247       if( inRepresentation==BYTECODE) { // read bytecode and process it with handler
248
ClassReader cr = new ClassReader( readEntry( zis, ze));
249         cr.accept( new SAXClassAdapter( handler, singleInputDocument), false);
250       
251       } else { // read XML and process it with handler
252
XMLReader JavaDoc reader = XMLReaderFactory.createXMLReader();
253         reader.setContentHandler( handler);
254         reader.parse( new InputSource JavaDoc( singleInputDocument ?
255             ( InputStream JavaDoc) new ProtectedInputStream( zis) : new ByteArrayInputStream JavaDoc( readEntry( zis, ze))));
256       
257       }
258     } catch( Exception JavaDoc ex) {
259       update( ze.getName());
260       update( ex);
261     }
262   }
263
264   private EntryElement getEntryElement( ZipOutputStream JavaDoc zos) {
265     if( outRepresentation==SINGLE_XML) {
266       return new SingleDocElement( zos);
267     } else {
268       return new ZipEntryElement( zos);
269     }
270   }
271
272   /*
273   private ContentHandlerFactory getHandlerFactory( OutputStream os, SAXTransformerFactory saxtf, Templates templates) {
274     ContentHandlerFactory factory = null;
275     if( templates==null) {
276       if( outputRepresentation==BYTECODE) {
277         // factory used to write bytecode
278         factory = new ASMContentHandlerFactory( os, computeMax);
279       } else {
280         // factory used to write XML
281         factory = new SAXWriterFactory( os, true);
282       }
283     } else {
284       if( outputRepresentation==BYTECODE) {
285         // factory used to transform and then write bytecode
286         factory = new ASMTransformerHandlerFactory( saxtf, templates, os, computeMax);
287       } else {
288         // factory used to transform and then write XML
289         factory = new TransformerHandlerFactory( saxtf, templates, os, outputRepresentation==SINGLE_XML);
290       }
291     }
292     
293     return factory;
294   }
295   */

296
297   private String JavaDoc getName( ZipEntry JavaDoc ze) {
298     String JavaDoc name = ze.getName();
299     if( isClassEntry( ze)) {
300       if( inRepresentation!=BYTECODE && outRepresentation==BYTECODE) {
301         name = name.substring( 0, name.length()-4); // .class.xml to .class
302
} else if( inRepresentation==BYTECODE && outRepresentation!=BYTECODE) {
303         name = name.concat( ".xml"); // .class to .class.xml
304
}
305       // } else if( CODE2ASM.equals( command)) {
306
// name = name.substring( 0, name.length()-6).concat( ".asm");
307
}
308     return name;
309   }
310
311   private byte[] readEntry(ZipInputStream JavaDoc zis, ZipEntry JavaDoc ze) throws IOException JavaDoc {
312     long size = ze.getSize();
313     if (size > -1) {
314       byte[] buff = new byte[(int) size];
315       // int k = 0;
316
// while(( n = zis.read(buff, k, buff.length-k)) > 0) {
317
// k += n;
318
// }
319
zis.read(buff);
320       return buff;
321     } else {
322       ByteArrayOutputStream JavaDoc bos = new ByteArrayOutputStream JavaDoc();
323       byte[] buff = new byte[4096];
324       int n;
325       while(( n = zis.read(buff)) != -1) {
326         bos.write(buff, 0, n);
327       }
328       return bos.toByteArray();
329     }
330   }
331   
332
333   /*
334    * (non-Javadoc)
335    * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
336    */

337   public void update( Object JavaDoc arg) {
338     if( arg instanceof Throwable JavaDoc) {
339       (( Throwable JavaDoc) arg).printStackTrace();
340     } else {
341       if(( n % 100)==0) {
342         System.err.println( n+" "+arg);
343       }
344     }
345     n++;
346   }
347   
348   public static void main( String JavaDoc[] args) throws Exception JavaDoc {
349     if( args.length<2) {
350       showUsage();
351       return;
352     }
353     
354     int inRepresentation = getRepresentation( args[ 0]);
355     int outRepresentation = getRepresentation( args[ 1]);
356     
357     InputStream JavaDoc is = null;
358     OutputStream JavaDoc os = null;
359     
360     Source JavaDoc xslt = null;
361     // boolean computeMax = true;
362

363     for( int i = 2; i<args.length; i++) {
364       if( "-in".equals( args[ i])) {
365         is = new FileInputStream JavaDoc( args[ ++i]);
366       
367       } else if( "-out".equals( args[ i])) {
368         os = new BufferedOutputStream JavaDoc( new FileOutputStream JavaDoc( args[ ++i]));
369       
370       } else if( "-xslt".equals( args[ i])) {
371         xslt = new StreamSource JavaDoc( new FileInputStream JavaDoc( args[ ++i]));
372       
373       // } else if( "-computemax".equals( args[ i].toLowerCase())) {
374
// computeMax = true;
375

376       } else {
377         showUsage();
378         return;
379         
380       }
381     }
382     
383     if( is==null || os==null || inRepresentation==0 || outRepresentation==0) {
384       showUsage();
385       return;
386     }
387     
388     Processor m = new Processor( inRepresentation, outRepresentation, is, os, xslt);
389     
390     long l1 = System.currentTimeMillis();
391     int n = m.process();
392     long l2 = System.currentTimeMillis();
393     System.err.println( n);
394     System.err.println( ""+( l2-l1)+"ms "+(1000f*n/( l2-l1))+" files/sec");
395   }
396
397   private static int getRepresentation( String JavaDoc s) {
398     if( "code".equals( s)) {
399       return BYTECODE;
400     } else if( "xml".equals( s)) {
401       return MULTI_XML;
402     } else if( "singlexml".equals( s)) {
403       return SINGLE_XML;
404     }
405     return 0;
406   }
407
408   private static void showUsage() {
409     System.err.println( "Usage: Main <in format> <out format> -in <input jar> -out <output jar> [-xslt <xslt fiel>]");
410     System.err.println( " <in format> and <out format> - code | xml | singlexml");
411   }
412
413   
414   /**
415    * IputStream wrapper class used to protect input streams from being
416    * closed by some stupid XML parsers.
417    */

418   private static final class ProtectedInputStream extends InputStream JavaDoc {
419     private final InputStream JavaDoc is;
420
421     private ProtectedInputStream( InputStream JavaDoc is) {
422       super();
423       this.is = is;
424     }
425
426     public final void close() throws IOException JavaDoc {
427     }
428
429     public final int read() throws IOException JavaDoc {
430       return is.read();
431     }
432
433     public final int read( byte[] b, int off, int len) throws IOException JavaDoc {
434       return is.read( b, off, len);
435     }
436
437     public final int available() throws IOException JavaDoc {
438       return is.available();
439     }
440   }
441
442
443   /**
444    * A {@link ContentHandlerFactory ContentHandlerFactory} is used to create
445    * {@link org.xml.sax.ContentHandler ContentHandler} instances for concrete context.
446    */

447   private static interface ContentHandlerFactory {
448
449     /**
450      * Creates an instance of the content handler.
451      *
452      * @return content handler
453      */

454     ContentHandler JavaDoc createContentHandler();
455     
456   }
457
458
459   /**
460    * SAXWriterFactory
461    */

462   private static final class SAXWriterFactory implements ContentHandlerFactory {
463     private Writer JavaDoc w;
464     private boolean optimizeEmptyElements;
465   
466     public SAXWriterFactory( Writer JavaDoc w, boolean optimizeEmptyElements) {
467       this.w = w;
468       this.optimizeEmptyElements = optimizeEmptyElements;
469     }
470     
471     public final ContentHandler JavaDoc createContentHandler() {
472       return new SAXWriter( w, optimizeEmptyElements);
473     }
474     
475   }
476   
477   
478   /**
479    * ASMContentHandlerFactory
480    */

481   private static final class ASMContentHandlerFactory implements ContentHandlerFactory {
482     private OutputStream JavaDoc os;
483     private boolean computeMax;
484   
485     public ASMContentHandlerFactory( OutputStream JavaDoc os, boolean computeMax) {
486       this.os = os;
487       this.computeMax = computeMax;
488     }
489     
490     public final ContentHandler JavaDoc createContentHandler() {
491       return new ASMContentHandler( os, computeMax);
492     }
493     
494   }
495   
496   
497   /**
498    * TransformerHandlerFactory
499    */

500   private static final class TransformerHandlerFactory implements ContentHandlerFactory {
501     private SAXTransformerFactory JavaDoc saxtf;
502     private Templates JavaDoc templates;
503     private ContentHandler JavaDoc outputHandler;
504   
505     public TransformerHandlerFactory( SAXTransformerFactory JavaDoc saxtf, Templates JavaDoc templates, ContentHandler JavaDoc outputHandler) {
506       this.saxtf = saxtf;
507       this.templates = templates;
508       this.outputHandler = outputHandler;
509     }
510     
511     public final ContentHandler JavaDoc createContentHandler() {
512       try {
513         TransformerHandler JavaDoc handler = saxtf.newTransformerHandler( templates);
514         handler.setResult( new SAXResult JavaDoc( outputHandler));
515         return handler;
516       } catch( TransformerConfigurationException JavaDoc ex) {
517         throw new RuntimeException JavaDoc( ex.toString());
518       }
519     }
520   }
521   
522   
523   /**
524    * SubdocumentHandlerFactory
525    */

526   private final static class SubdocumentHandlerFactory implements ContentHandlerFactory {
527     private ContentHandler JavaDoc subdocumentHandler;
528
529     public SubdocumentHandlerFactory( ContentHandler JavaDoc subdocumentHandler) {
530       this.subdocumentHandler = subdocumentHandler;
531     }
532     
533     public final ContentHandler JavaDoc createContentHandler() {
534       return subdocumentHandler;
535     }
536     
537   }
538
539   
540   /**
541    * A {@link org.xml.sax.ContentHandler ContentHandler} and
542    * {@link org.xml.sax.ext.LexicalHandler LexicalHandler} that serializes
543    * XML from SAX 2.0 events into {@link java.io.Writer Writer}.
544    *
545    * <i><blockquote>
546    * This implementation does not support namespaces,
547    * entity definitions (uncluding DTD), CDATA and text elements.
548    * </blockquote></i>
549    */

550   private final static class SAXWriter extends DefaultHandler JavaDoc implements LexicalHandler JavaDoc {
551     private static final char[] OFF = " ".toCharArray();
552     
553     private Writer JavaDoc w;
554     private boolean optimizeEmptyElements;
555     
556     private boolean openElement = false;
557     private int ident = 0;
558
559     
560     /**
561      * Creates <code>SAXWriter</code>.
562      *
563      * @param w writer
564      * @param optimizeEmptyElements if set to <code>true</code>,
565      * short XML syntax will be used for empty elements
566      */

567     public SAXWriter( Writer JavaDoc w, boolean optimizeEmptyElements) {
568       this.w = w;
569       this.optimizeEmptyElements = optimizeEmptyElements;
570     }
571     
572     public final void startElement( String JavaDoc ns, String JavaDoc localName, String JavaDoc qName, Attributes JavaDoc atts) throws SAXException JavaDoc {
573       try {
574         closeElement();
575
576         writeIdent();
577         w.write( "<".concat( qName));
578         if( atts!=null && atts.getLength()>0) writeAttributes( atts);
579
580         if( !optimizeEmptyElements) {
581           w.write( ">\n");
582         } else {
583           openElement = true;
584         }
585         ident += 2;
586       
587       } catch( IOException JavaDoc ex) {
588         throw new SAXException JavaDoc(ex);
589       
590       }
591     }
592
593     public final void endElement( String JavaDoc ns, String JavaDoc localName, String JavaDoc qName) throws SAXException JavaDoc {
594       ident -= 2;
595       try {
596         if( openElement) {
597           w.write( "/>\n");
598           openElement = false;
599         } else {
600           writeIdent();
601           w.write( "</"+qName+">\n");
602         }
603
604       } catch( IOException JavaDoc ex) {
605         throw new SAXException JavaDoc(ex);
606       
607       }
608     }
609
610     public final void endDocument() throws SAXException JavaDoc {
611       try {
612         w.flush();
613
614       } catch( IOException JavaDoc ex) {
615         throw new SAXException JavaDoc(ex);
616
617       }
618     }
619     
620     public final void comment( char[] ch, int off, int len) throws SAXException JavaDoc {
621       try {
622         closeElement();
623
624         writeIdent();
625         w.write( "<!-- ");
626         w.write( ch, off, len);
627         w.write( " -->\n");
628         
629       } catch( IOException JavaDoc ex) {
630         throw new SAXException JavaDoc(ex);
631     
632       }
633     }
634
635     public final void startDTD( String JavaDoc arg0, String JavaDoc arg1, String JavaDoc arg2) throws SAXException JavaDoc {
636     }
637
638     public final void endDTD() throws SAXException JavaDoc {
639     }
640
641     public final void startEntity( String JavaDoc arg0) throws SAXException JavaDoc {
642     }
643
644     public final void endEntity( String JavaDoc arg0) throws SAXException JavaDoc {
645     }
646
647     public final void startCDATA() throws SAXException JavaDoc {
648     }
649
650     public final void endCDATA() throws SAXException JavaDoc {
651     }
652
653     
654     private final void writeAttributes( Attributes JavaDoc atts) throws IOException JavaDoc {
655       StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
656       int len = atts.getLength();
657       for( int i = 0; i<len; i++) {
658         sb.append( " ").append( atts.getLocalName( i)).append( "=\"")
659           .append( esc( atts.getValue( i))).append( "\"");
660       }
661       w.write( sb.toString());
662     }
663     
664     /**
665      * Encode string with escaping.
666      *
667      * @param str string to encode.
668      * @return encoded string
669      */

670     private final String JavaDoc esc( String JavaDoc str) {
671       StringBuffer JavaDoc sb = new StringBuffer JavaDoc( str.length());
672       for( int i = 0; i < str.length(); i++) {
673         char ch = str.charAt( i);
674         switch( ch) {
675           case '&':
676             sb.append( "&amp;");
677             break;
678           
679           case '<':
680             sb.append( "&lt;");
681             break;
682           
683           case '>':
684             sb.append( "&gt;");
685             break;
686           
687           case '\"':
688             sb.append( "&quot;");
689             break;
690             
691           default:
692             if( ch>0x7f) {
693               sb.append( "&#").append( Integer.toString( ch)).append( ';');
694             } else {
695               sb.append( ch);
696             }
697           
698         }
699       }
700       return sb.toString();
701     }
702     
703     private final void writeIdent() throws IOException JavaDoc {
704       int n = ident;
705       while( n>0) {
706         if( n>OFF.length) {
707           w.write( OFF);
708           n -= OFF.length;
709         } else {
710           w.write( OFF, 0, n);
711           n = 0;
712         }
713       }
714     }
715
716     private final void closeElement() throws IOException JavaDoc {
717       if( openElement) {
718         w.write( ">\n");
719       }
720       openElement = false;
721     }
722     
723   }
724   
725   
726   /**
727    * A {@link org.xml.sax.ContentHandler ContentHandler} that splits XML documents
728    * into smaller chunks. Each chunk is processed by the nested
729    * {@link org.xml.sax.ContentHandler ContentHandler} obtained from
730    * {@link java.net.ContentHandlerFactory ContentHandlerFactory}.
731    * This is useful for running XSLT engine against large XML document that will
732    * hardly fit into the memory all together.
733    * <p>
734    * TODO use complete path for subdocumentRoot
735    */

736   private final static class InputSlicingHandler extends DefaultHandler JavaDoc {
737     private String JavaDoc subdocumentRoot;
738     private ContentHandler JavaDoc rootHandler;
739     private ContentHandlerFactory subdocumentHandlerFactory;
740     
741     private boolean subdocument = false;
742     private ContentHandler JavaDoc subdocumentHandler;
743
744     /**
745      * Constructs a new {@link InputSlicingHandler SubdocumentHandler} object.
746      *
747      * @param subdocumentRoot name/path to the root element of the subdocument
748      * @param rootHandler content handler for the entire document (subdocument envelope).
749      * @param subdocumentHandlerFactory a {@link ContentHandlerFactory ContentHandlerFactory}
750      * used to create {@link ContentHandler ContentHandler} instances for subdocuments.
751      */

752     public InputSlicingHandler( String JavaDoc subdocumentRoot, ContentHandler JavaDoc rootHandler,
753           ContentHandlerFactory subdocumentHandlerFactory) {
754       this.subdocumentRoot = subdocumentRoot;
755       this.rootHandler = rootHandler;
756       this.subdocumentHandlerFactory = subdocumentHandlerFactory;
757     }
758     
759     public final void startElement( String JavaDoc namespaceURI, String JavaDoc localName, String JavaDoc qName, Attributes JavaDoc list) throws SAXException JavaDoc {
760       if( subdocument) {
761         subdocumentHandler.startElement( namespaceURI, localName, qName, list);
762       } else if( localName.equals( subdocumentRoot)) {
763         subdocumentHandler = subdocumentHandlerFactory.createContentHandler();
764         subdocumentHandler.startDocument();
765         subdocumentHandler.startElement( namespaceURI, localName, qName, list);
766         subdocument = true;
767       } else if( rootHandler!=null) {
768         rootHandler.startElement( namespaceURI, localName, qName, list);
769       }
770     }
771     
772     public final void endElement( String JavaDoc namespaceURI, String JavaDoc localName, String JavaDoc qName) throws SAXException JavaDoc {
773       if( subdocument) {
774         subdocumentHandler.endElement( namespaceURI, localName, qName);
775         if( localName.equals( subdocumentRoot)) {
776           subdocumentHandler.endDocument();
777           subdocument = false;
778         }
779       } else if( rootHandler!=null) {
780         rootHandler.endElement( namespaceURI, localName, qName);
781       }
782     }
783     
784     public final void startDocument() throws SAXException JavaDoc {
785       if( rootHandler!=null) {
786         rootHandler.startDocument();
787       }
788     }
789
790     public final void endDocument() throws SAXException JavaDoc {
791       if( rootHandler!=null) {
792         rootHandler.endDocument();
793         
794       }
795     }
796     
797     public final void characters( char[] buff, int offset, int size) throws SAXException JavaDoc {
798       if( subdocument) {
799         subdocumentHandler.characters(buff, offset, size);
800       } else if( rootHandler!=null) {
801         rootHandler.characters(buff, offset, size);
802       }
803     }
804     
805   }
806
807   
808   /**
809    * A {@link org.xml.sax.ContentHandler ContentHandler} that splits XML documents
810    * into smaller chunks. Each chunk is processed by the nested
811    * {@link org.xml.sax.ContentHandler ContentHandler} obtained from
812    * {@link java.net.ContentHandlerFactory ContentHandlerFactory}.
813    * This is useful for running XSLT engine against large XML document that will
814    * hardly fit into the memory all together.
815    * <p>
816    * TODO use complete path for subdocumentRoot
817    */

818   private static final class OutputSlicingHandler extends DefaultHandler JavaDoc {
819     private String JavaDoc subdocumentRoot;
820     private ContentHandlerFactory subdocumentHandlerFactory;
821     private EntryElement entryElement;
822     private boolean isXml;
823     
824     private boolean subdocument = false;
825     private ContentHandler JavaDoc subdocumentHandler;
826
827     /**
828      * Constructs a new {@link OutputSlicingHandler SubdocumentHandler} object.
829      *
830      * @param subdocumentRoot name/path to the root element of the subdocument
831      * @param rootHandler content handler for the entire document (subdocument envelope).
832      * @param subdocumentHandlerFactory a {@link ContentHandlerFactory ContentHandlerFactory}
833      * used to create {@link ContentHandler ContentHandler} instances for subdocuments.
834      */

835     public OutputSlicingHandler( ContentHandlerFactory subdocumentHandlerFactory,
836           EntryElement entryElement, boolean isXml) {
837       this.subdocumentRoot = "class";
838       this.subdocumentHandlerFactory = subdocumentHandlerFactory;
839       this.entryElement = entryElement;
840       this.isXml = isXml;
841     }
842     
843     public final void startElement( String JavaDoc namespaceURI, String JavaDoc localName, String JavaDoc qName, Attributes JavaDoc list) throws SAXException JavaDoc {
844       if( subdocument) {
845         subdocumentHandler.startElement( namespaceURI, localName, qName, list);
846       } else if( localName.equals( subdocumentRoot)) {
847         String JavaDoc name = list.getValue( "name");
848         if( name==null || name.length()==0) throw new SAXException JavaDoc( "Class element without name attribute.");
849         try {
850           entryElement.openEntry( isXml ? name.concat( ".class.xml") : name.concat( ".class"));
851         } catch( IOException JavaDoc ex) {
852           throw new SAXException JavaDoc( ex.toString(), ex);
853         }
854         subdocumentHandler = subdocumentHandlerFactory.createContentHandler();
855         subdocumentHandler.startDocument();
856         subdocumentHandler.startElement( namespaceURI, localName, qName, list);
857         subdocument = true;
858       }
859     }
860     
861     public final void endElement( String JavaDoc namespaceURI, String JavaDoc localName, String JavaDoc qName) throws SAXException JavaDoc {
862       if( subdocument) {
863         subdocumentHandler.endElement( namespaceURI, localName, qName);
864         if( localName.equals( subdocumentRoot)) {
865           subdocumentHandler.endDocument();
866           subdocument = false;
867           try {
868             entryElement.closeEntry();
869           } catch( IOException JavaDoc ex) {
870             throw new SAXException JavaDoc( ex.toString(), ex);
871           }
872         }
873       }
874     }
875     
876     public final void startDocument() throws SAXException JavaDoc {
877     }
878
879     public final void endDocument() throws SAXException JavaDoc {
880     }
881     
882     public final void characters( char[] buff, int offset, int size) throws SAXException JavaDoc {
883       if( subdocument) {
884         subdocumentHandler.characters(buff, offset, size);
885       }
886     }
887     
888   }
889
890   
891   private static interface EntryElement {
892
893     OutputStream JavaDoc openEntry( String JavaDoc name) throws IOException JavaDoc;
894
895     void closeEntry() throws IOException JavaDoc;
896     
897   }
898
899
900   private static final class SingleDocElement implements EntryElement {
901     private OutputStream JavaDoc os;
902
903     public SingleDocElement( OutputStream JavaDoc os) {
904       this.os = os;
905     }
906     
907     public OutputStream JavaDoc openEntry( String JavaDoc name) throws IOException JavaDoc {
908       return os;
909     }
910     
911     public void closeEntry() throws IOException JavaDoc {
912       os.flush();
913     }
914     
915   }
916
917   
918   private static final class ZipEntryElement implements EntryElement {
919     private ZipOutputStream JavaDoc zos;
920
921     public ZipEntryElement( ZipOutputStream JavaDoc zos) {
922       this.zos = zos;
923     }
924     
925     public OutputStream JavaDoc openEntry( String JavaDoc name) throws IOException JavaDoc {
926       ZipEntry JavaDoc entry = new ZipEntry JavaDoc( name);
927       zos.putNextEntry( entry);
928       return zos;
929     }
930     
931     public void closeEntry() throws IOException JavaDoc {
932       zos.flush();
933       zos.closeEntry();
934     }
935     
936   }
937   
938 }
939
940
Popular Tags