KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > xsltc > compiler > XSLTC


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

16 /*
17  * $Id: XSLTC.java,v 1.57 2004/02/16 22:25:33 minchau Exp $
18  */

19
20 package org.apache.xalan.xsltc.compiler;
21
22 import java.io.BufferedOutputStream JavaDoc;
23 import java.io.ByteArrayOutputStream JavaDoc;
24 import java.io.File JavaDoc;
25 import java.io.FileOutputStream JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.InputStream JavaDoc;
28 import java.net.URL JavaDoc;
29 import java.util.Date JavaDoc;
30 import java.util.Enumeration JavaDoc;
31 import java.util.Hashtable JavaDoc;
32 import java.util.Map JavaDoc;
33 import java.util.Properties JavaDoc;
34 import java.util.Vector JavaDoc;
35 import java.util.jar.JarEntry JavaDoc;
36 import java.util.jar.JarOutputStream JavaDoc;
37 import java.util.jar.Manifest JavaDoc;
38
39 import org.apache.bcel.classfile.JavaClass;
40 import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
41 import org.apache.xalan.xsltc.compiler.util.Util;
42 import org.apache.xml.dtm.DTM;
43
44 import org.xml.sax.InputSource JavaDoc;
45 import org.xml.sax.XMLReader JavaDoc;
46
47 /**
48  * @author Jacek Ambroziak
49  * @author Santiago Pericas-Geertsen
50  * @author G. Todd Miller
51  * @author Morten Jorgensen
52  * @author John Howard (johnh@schemasoft.com)
53  */

54 public final class XSLTC {
55
56     // A reference to the main stylesheet parser object.
57
private Parser _parser;
58
59     // A reference to an external XMLReader (SAX parser) passed to us
60
private XMLReader JavaDoc _reader = null;
61
62     // A reference to an external SourceLoader (for use with include/import)
63
private SourceLoader _loader = null;
64
65     // A reference to the stylesheet being compiled.
66
private Stylesheet _stylesheet;
67
68     // Counters used by various classes to generate unique names.
69
// private int _variableSerial = 1;
70
private int _modeSerial = 1;
71     private int _stylesheetSerial = 1;
72     private int _stepPatternSerial = 1;
73     private int _helperClassSerial = 0;
74     private int _attributeSetSerial = 0;
75
76     private int[] _numberFieldIndexes;
77
78     // Name index tables
79
private int _nextGType; // Next available element type
80
private Vector JavaDoc _namesIndex; // Index of all registered QNames
81
private Hashtable JavaDoc _elements; // Hashtable of all registered elements
82
private Hashtable JavaDoc _attributes; // Hashtable of all registered attributes
83

84     // Namespace index tables
85
private int _nextNSType; // Next available namespace type
86
private Vector JavaDoc _namespaceIndex; // Index of all registered namespaces
87
private Hashtable JavaDoc _namespaces; // Hashtable of all registered namespaces
88
private Hashtable JavaDoc _namespacePrefixes;// Hashtable of all registered namespace prefixes
89

90
91     // All literal text in the stylesheet
92
private Vector JavaDoc m_characterData;
93
94     // These define the various methods for outputting the translet
95
public static final int FILE_OUTPUT = 0;
96     public static final int JAR_OUTPUT = 1;
97     public static final int BYTEARRAY_OUTPUT = 2;
98     public static final int CLASSLOADER_OUTPUT = 3;
99     public static final int BYTEARRAY_AND_FILE_OUTPUT = 4;
100     public static final int BYTEARRAY_AND_JAR_OUTPUT = 5;
101
102
103     // Compiler options (passed from command line or XSLTC client)
104
private boolean _debug = false; // -x
105
private String JavaDoc _jarFileName = null; // -j <jar-file-name>
106
private String JavaDoc _className = null; // -o <class-name>
107
private String JavaDoc _packageName = null; // -p <package-name>
108
private File JavaDoc _destDir = null; // -d <directory-name>
109
private int _outputType = FILE_OUTPUT; // by default
110

111     private Vector JavaDoc _classes;
112     private Vector JavaDoc _bcelClasses;
113     private boolean _callsNodeset = false;
114     private boolean _multiDocument = false;
115     private boolean _hasIdCall = false;
116
117     /**
118      * Set to true if template inlining is requested. Template
119      * inlining used to be the default, but we have found that
120      * Hotspots does a better job with shorter methods, so the
121      * default is *not* to inline now.
122      */

123     private boolean _templateInlining = false;
124
125     /**
126      * XSLTC compiler constructor
127      */

128     public XSLTC() {
129     _parser = new Parser(this);
130     }
131
132     /**
133      * Only for user by the internal TrAX implementation.
134      */

135     public Parser getParser() {
136         return _parser;
137     }
138
139     /**
140      * Only for user by the internal TrAX implementation.
141      */

142     public void setOutputType(int type) {
143     _outputType = type;
144     }
145
146     /**
147      * Only for user by the internal TrAX implementation.
148      */

149     public Properties JavaDoc getOutputProperties() {
150     return _parser.getOutputProperties();
151     }
152
153     /**
154      * Initializes the compiler to compile a new stylesheet
155      */

156     public void init() {
157     reset();
158     _reader = null;
159     _classes = new Vector JavaDoc();
160     _bcelClasses = new Vector JavaDoc();
161     }
162
163     /**
164      * Initializes the compiler to produce a new translet
165      */

166     private void reset() {
167     _nextGType = DTM.NTYPES;
168     _elements = new Hashtable JavaDoc();
169     _attributes = new Hashtable JavaDoc();
170     _namespaces = new Hashtable JavaDoc();
171     _namespaces.put("",new Integer JavaDoc(_nextNSType));
172     _namesIndex = new Vector JavaDoc(128);
173     _namespaceIndex = new Vector JavaDoc(32);
174     _namespacePrefixes = new Hashtable JavaDoc();
175         _stylesheet = null;
176     _parser.init();
177     //_variableSerial = 1;
178
_modeSerial = 1;
179     _stylesheetSerial = 1;
180     _stepPatternSerial = 1;
181     _helperClassSerial = 0;
182     _attributeSetSerial = 0;
183     _multiDocument = false;
184     _hasIdCall = false;
185     _numberFieldIndexes = new int[] {
186         -1, // LEVEL_SINGLE
187
-1, // LEVEL_MULTIPLE
188
-1 // LEVEL_ANY
189
};
190     }
191
192     /**
193      * Defines an external SourceLoader to provide the compiler with documents
194      * referenced in xsl:include/import
195      * @param loader The SourceLoader to use for include/import
196      */

197     public void setSourceLoader(SourceLoader loader) {
198     _loader = loader;
199     }
200
201     /**
202      * Set a flag indicating if templates are to be inlined or not. The
203      * default is to do inlining, but this causes problems when the
204      * stylesheets have a large number of templates (e.g. branch targets
205      * exceeding 64K or a length of a method exceeding 64K).
206      */

207     public void setTemplateInlining(boolean templateInlining) {
208     _templateInlining = templateInlining;
209     }
210
211     /**
212      * Set the parameters to use to locate the correct <?xml-stylesheet ...?>
213      * processing instruction in the case where the input document to the
214      * compiler (and parser) is an XML document.
215      * @param media The media attribute to be matched. May be null, in which
216      * case the prefered templates will be used (i.e. alternate = no).
217      * @param title The value of the title attribute to match. May be null.
218      * @param charset The value of the charset attribute to match. May be null.
219      */

220     public void setPIParameters(String JavaDoc media, String JavaDoc title, String JavaDoc charset) {
221     _parser.setPIParameters(media, title, charset);
222     }
223
224     /**
225      * Compiles an XSL stylesheet pointed to by a URL
226      * @param url An URL containing the input XSL stylesheet
227      */

228     public boolean compile(URL JavaDoc url) {
229     try {
230         // Open input stream from URL and wrap inside InputSource
231
final InputStream JavaDoc stream = url.openStream();
232         final InputSource JavaDoc input = new InputSource JavaDoc(stream);
233         input.setSystemId(url.toString());
234         return compile(input, _className);
235     }
236     catch (IOException JavaDoc e) {
237         _parser.reportError(Constants.FATAL, new ErrorMsg(e));
238         return false;
239     }
240     }
241
242     /**
243      * Compiles an XSL stylesheet pointed to by a URL
244      * @param url An URL containing the input XSL stylesheet
245      * @param name The name to assign to the translet class
246      */

247     public boolean compile(URL JavaDoc url, String JavaDoc name) {
248     try {
249         // Open input stream from URL and wrap inside InputSource
250
final InputStream JavaDoc stream = url.openStream();
251         final InputSource JavaDoc input = new InputSource JavaDoc(stream);
252         input.setSystemId(url.toString());
253         return compile(input, name);
254     }
255     catch (IOException JavaDoc e) {
256         _parser.reportError(Constants.FATAL, new ErrorMsg(e));
257         return false;
258     }
259     }
260
261     /**
262      * Compiles an XSL stylesheet passed in through an InputStream
263      * @param input An InputStream that will pass in the stylesheet contents
264      * @param name The name of the translet class to generate
265      * @return 'true' if the compilation was successful
266      */

267     public boolean compile(InputStream JavaDoc stream, String JavaDoc name) {
268     final InputSource JavaDoc input = new InputSource JavaDoc(stream);
269     input.setSystemId(name); // We have nothing else!!!
270
return compile(input, name);
271     }
272
273     /**
274      * Compiles an XSL stylesheet passed in through an InputStream
275      * @param input An InputSource that will pass in the stylesheet contents
276      * @param name The name of the translet class to generate - can be null
277      * @return 'true' if the compilation was successful
278      */

279     public boolean compile(InputSource JavaDoc input, String JavaDoc name) {
280     try {
281         // Reset globals in case we're called by compile(Vector v);
282
reset();
283
284         // The systemId may not be set, so we'll have to check the URL
285
String JavaDoc systemId = null;
286         if (input != null) {
287             systemId = input.getSystemId();
288         }
289
290         // Set the translet class name if not already set
291
if (_className == null) {
292         if (name != null) {
293             setClassName(name);
294                 }
295         else if (systemId != null && !systemId.equals("")) {
296             setClassName(Util.baseName(systemId));
297                 }
298                 
299                 // Ensure we have a non-empty class name at this point
300
if (_className == null || _className.length() == 0) {
301             setClassName("GregorSamsa"); // default translet name
302
}
303         }
304
305         // Get the root node of the abstract syntax tree
306
SyntaxTreeNode element = null;
307         if (_reader == null) {
308         element = _parser.parse(input);
309         }
310         else {
311         element = _parser.parse(_reader, input);
312         }
313
314         // Compile the translet - this is where the work is done!
315
if ((!_parser.errorsFound()) && (element != null)) {
316         // Create a Stylesheet element from the root node
317
_stylesheet = _parser.makeStylesheet(element);
318         _stylesheet.setSourceLoader(_loader);
319         _stylesheet.setSystemId(systemId);
320         _stylesheet.setParentStylesheet(null);
321         _stylesheet.setTemplateInlining(_templateInlining);
322         _parser.setCurrentStylesheet(_stylesheet);
323
324         // Create AST under the Stylesheet element (parse & type-check)
325
_parser.createAST(_stylesheet);
326         }
327         // Generate the bytecodes and output the translet class(es)
328
if ((!_parser.errorsFound()) && (_stylesheet != null)) {
329         _stylesheet.setCallsNodeset(_callsNodeset);
330         _stylesheet.setMultiDocument(_multiDocument);
331         _stylesheet.setHasIdCall(_hasIdCall);
332
333         // Class synchronization is needed for BCEL
334
synchronized (getClass()) {
335             _stylesheet.translate();
336         }
337         }
338     }
339     catch (Exception JavaDoc e) {
340         /*if (_debug)*/ e.printStackTrace();
341         _parser.reportError(Constants.FATAL, new ErrorMsg(e));
342     }
343     catch (Error JavaDoc e) {
344         if (_debug) e.printStackTrace();
345         _parser.reportError(Constants.FATAL, new ErrorMsg(e));
346     }
347     finally {
348         _reader = null; // reset this here to be sure it is not re-used
349
}
350     return !_parser.errorsFound();
351     }
352
353     /**
354      * Compiles a set of stylesheets pointed to by a Vector of URLs
355      * @param stylesheets A Vector containing URLs pointing to the stylesheets
356      * @return 'true' if the compilation was successful
357      */

358     public boolean compile(Vector JavaDoc stylesheets) {
359     // Get the number of stylesheets (ie. URLs) in the vector
360
final int count = stylesheets.size();
361
362     // Return straight away if the vector is empty
363
if (count == 0) return true;
364
365     // Special handling needed if the URL count is one, becuase the
366
// _className global must not be reset if it was set explicitly
367
if (count == 1) {
368         final Object JavaDoc url = stylesheets.firstElement();
369         if (url instanceof URL JavaDoc)
370         return compile((URL JavaDoc)url);
371         else
372         return false;
373     }
374     else {
375         // Traverse all elements in the vector and compile
376
final Enumeration JavaDoc urls = stylesheets.elements();
377         while (urls.hasMoreElements()) {
378         _className = null; // reset, so that new name will be computed
379
final Object JavaDoc url = urls.nextElement();
380         if (url instanceof URL JavaDoc) {
381             if (!compile((URL JavaDoc)url)) return false;
382         }
383         }
384     }
385     return true;
386     }
387
388     /**
389      * Returns an array of bytecode arrays generated by a compilation.
390      * @return JVM bytecodes that represent translet class definition
391      */

392     public byte[][] getBytecodes() {
393     final int count = _classes.size();
394     final byte[][] result = new byte[count][1];
395     for (int i = 0; i < count; i++)
396         result[i] = (byte[])_classes.elementAt(i);
397     return result;
398     }
399
400     /**
401      * Compiles a stylesheet pointed to by a URL. The result is put in a
402      * set of byte arrays. One byte array for each generated class.
403      * @param name The name of the translet class to generate
404      * @param input An InputSource that will pass in the stylesheet contents
405      * @param outputType The output type
406      * @return JVM bytecodes that represent translet class definition
407      */

408     public byte[][] compile(String JavaDoc name, InputSource JavaDoc input, int outputType) {
409     _outputType = outputType;
410     if (compile(input, name))
411         return getBytecodes();
412     else
413         return null;
414     }
415
416     /**
417      * Compiles a stylesheet pointed to by a URL. The result is put in a
418      * set of byte arrays. One byte array for each generated class.
419      * @param name The name of the translet class to generate
420      * @param input An InputSource that will pass in the stylesheet contents
421      * @return JVM bytecodes that represent translet class definition
422      */

423     public byte[][] compile(String JavaDoc name, InputSource JavaDoc input) {
424         return compile(name, input, BYTEARRAY_OUTPUT);
425     }
426
427     /**
428      * Set the XMLReader to use for parsing the next input stylesheet
429      * @param reader XMLReader (SAX2 parser) to use
430      */

431     public void setXMLReader(XMLReader JavaDoc reader) {
432     _reader = reader;
433     }
434
435     /**
436      * Get the XMLReader to use for parsing the next input stylesheet
437      */

438     public XMLReader JavaDoc getXMLReader() {
439     return _reader ;
440     }
441
442     /**
443      * Get a Vector containing all compile error messages
444      * @return A Vector containing all compile error messages
445      */

446     public Vector JavaDoc getErrors() {
447     return _parser.getErrors();
448     }
449
450     /**
451      * Get a Vector containing all compile warning messages
452      * @return A Vector containing all compile error messages
453      */

454     public Vector JavaDoc getWarnings() {
455     return _parser.getWarnings();
456     }
457
458     /**
459      * Print all compile error messages to standard output
460      */

461     public void printErrors() {
462     _parser.printErrors();
463     }
464
465     /**
466      * Print all compile warning messages to standard output
467      */

468     public void printWarnings() {
469     _parser.printWarnings();
470     }
471
472     /**
473      * This method is called by the XPathParser when it encounters a call
474      * to the document() function. Affects the DOM used by the translet.
475      */

476     protected void setMultiDocument(boolean flag) {
477     _multiDocument = flag;
478     }
479
480     public boolean isMultiDocument() {
481     return _multiDocument;
482     }
483
484     /**
485      * This method is called by the XPathParser when it encounters a call
486      * to the nodeset() extension function. Implies multi document.
487      */

488     protected void setCallsNodeset(boolean flag) {
489     if (flag) setMultiDocument(flag);
490     _callsNodeset = flag;
491     }
492
493     public boolean callsNodeset() {
494     return _callsNodeset;
495     }
496
497     protected void setHasIdCall(boolean flag) {
498         _hasIdCall = flag;
499     }
500
501     public boolean hasIdCall() {
502         return _hasIdCall;
503     }
504
505     /**
506      * Set the class name for the generated translet. This class name is
507      * overridden if multiple stylesheets are compiled in one go using the
508      * compile(Vector urls) method.
509      * @param className The name to assign to the translet class
510      */

511     public void setClassName(String JavaDoc className) {
512     final String JavaDoc base = Util.baseName(className);
513     final String JavaDoc noext = Util.noExtName(base);
514     String JavaDoc name = Util.toJavaName(noext);
515
516     if (_packageName == null)
517         _className = name;
518     else
519         _className = _packageName + '.' + name;
520     }
521
522     /**
523      * Get the class name for the generated translet.
524      */

525     public String JavaDoc getClassName() {
526     return _className;
527     }
528
529     /**
530      * Convert for Java class name of local system file name.
531      * (Replace '.' with '/' on UNIX and replace '.' by '\' on Windows/DOS.)
532      */

533     private String JavaDoc classFileName(final String JavaDoc className) {
534     return className.replace('.', File.separatorChar) + ".class";
535     }
536
537     /**
538      * Generate an output File object to send the translet to
539      */

540     private File JavaDoc getOutputFile(String JavaDoc className) {
541     if (_destDir != null)
542         return new File JavaDoc(_destDir, classFileName(className));
543     else
544         return new File JavaDoc(classFileName(className));
545     }
546
547     /**
548      * Set the destination directory for the translet.
549      * The current working directory will be used by default.
550      */

551     public boolean setDestDirectory(String JavaDoc dstDirName) {
552     final File JavaDoc dir = new File JavaDoc(dstDirName);
553     if (dir.exists() || dir.mkdirs()) {
554         _destDir = dir;
555         return true;
556     }
557     else {
558         _destDir = null;
559         return false;
560     }
561     }
562
563     /**
564      * Set an optional package name for the translet and auxiliary classes
565      */

566     public void setPackageName(String JavaDoc packageName) {
567     _packageName = packageName;
568     if (_className != null) setClassName(_className);
569     }
570
571     /**
572      * Set the name of an optional JAR-file to dump the translet and
573      * auxiliary classes to
574      */

575     public void setJarFileName(String JavaDoc jarFileName) {
576     final String JavaDoc JAR_EXT = ".jar";
577     if (jarFileName.endsWith(JAR_EXT))
578         _jarFileName = jarFileName;
579     else
580         _jarFileName = jarFileName + JAR_EXT;
581     _outputType = JAR_OUTPUT;
582     }
583
584     public String JavaDoc getJarFileName() {
585     return _jarFileName;
586     }
587
588     /**
589      * Set the top-level stylesheet
590      */

591     public void setStylesheet(Stylesheet stylesheet) {
592     if (_stylesheet == null) _stylesheet = stylesheet;
593     }
594
595     /**
596      * Returns the top-level stylesheet
597      */

598     public Stylesheet getStylesheet() {
599     return _stylesheet;
600     }
601
602     /**
603      * Registers an attribute and gives it a type so that it can be mapped to
604      * DOM attribute types at run-time.
605      */

606     public int registerAttribute(QName name) {
607     Integer JavaDoc code = (Integer JavaDoc)_attributes.get(name.toString());
608     if (code == null) {
609         code = new Integer JavaDoc(_nextGType++);
610         _attributes.put(name.toString(), code);
611         final String JavaDoc uri = name.getNamespace();
612         final String JavaDoc local = "@"+name.getLocalPart();
613         if ((uri != null) && (!uri.equals("")))
614         _namesIndex.addElement(uri+":"+local);
615         else
616         _namesIndex.addElement(local);
617         if (name.getLocalPart().equals("*")) {
618         registerNamespace(name.getNamespace());
619         }
620     }
621     return code.intValue();
622     }
623
624     /**
625      * Registers an element and gives it a type so that it can be mapped to
626      * DOM element types at run-time.
627      */

628     public int registerElement(QName name) {
629     // Register element (full QName)
630
Integer JavaDoc code = (Integer JavaDoc)_elements.get(name.toString());
631     if (code == null) {
632         _elements.put(name.toString(), code = new Integer JavaDoc(_nextGType++));
633         _namesIndex.addElement(name.toString());
634     }
635     if (name.getLocalPart().equals("*")) {
636         registerNamespace(name.getNamespace());
637     }
638     return code.intValue();
639     }
640
641      /**
642       * Registers a namespace prefix and gives it a type so that it can be mapped to
643       * DOM namespace types at run-time.
644       */

645   
646     public int registerNamespacePrefix(QName name) {
647     
648     Integer JavaDoc code = (Integer JavaDoc)_namespacePrefixes.get(name.toString());
649     if (code == null) {
650         code = new Integer JavaDoc(_nextGType++);
651         _namespacePrefixes.put(name.toString(), code);
652         final String JavaDoc uri = name.getNamespace();
653         if ((uri != null) && (!uri.equals(""))){
654             // namespace::ext2:ped2 will be made empty in TypedNamespaceIterator
655
_namesIndex.addElement("?");
656         } else{
657            _namesIndex.addElement("?"+name.getLocalPart());
658         }
659     }
660     return code.intValue();
661     }
662
663     /**
664      * Registers a namespace and gives it a type so that it can be mapped to
665      * DOM namespace types at run-time.
666      */

667     public int registerNamespace(String JavaDoc namespaceURI) {
668     Integer JavaDoc code = (Integer JavaDoc)_namespaces.get(namespaceURI);
669     if (code == null) {
670         code = new Integer JavaDoc(_nextNSType++);
671         _namespaces.put(namespaceURI,code);
672         _namespaceIndex.addElement(namespaceURI);
673     }
674     return code.intValue();
675     }
676
677     public int nextModeSerial() {
678     return _modeSerial++;
679     }
680
681     public int nextStylesheetSerial() {
682     return _stylesheetSerial++;
683     }
684
685     public int nextStepPatternSerial() {
686     return _stepPatternSerial++;
687     }
688
689     public int[] getNumberFieldIndexes() {
690     return _numberFieldIndexes;
691     }
692
693     public int nextHelperClassSerial() {
694     return _helperClassSerial++;
695     }
696
697     public int nextAttributeSetSerial() {
698     return _attributeSetSerial++;
699     }
700
701     public Vector JavaDoc getNamesIndex() {
702     return _namesIndex;
703     }
704
705     public Vector JavaDoc getNamespaceIndex() {
706     return _namespaceIndex;
707     }
708
709     /**
710      * Returns a unique name for every helper class needed to
711      * execute a translet.
712      */

713     public String JavaDoc getHelperClassName() {
714     return getClassName() + '$' + _helperClassSerial++;
715     }
716
717     public void dumpClass(JavaClass clazz) {
718
719     if (_outputType == FILE_OUTPUT ||
720         _outputType == BYTEARRAY_AND_FILE_OUTPUT)
721     {
722         File JavaDoc outFile = getOutputFile(clazz.getClassName());
723         String JavaDoc parentDir = outFile.getParent();
724         if (parentDir != null) {
725             File JavaDoc parentFile = new File JavaDoc(parentDir);
726             if (!parentFile.exists())
727                 parentFile.mkdirs();
728         }
729     }
730
731     try {
732         switch (_outputType) {
733         case FILE_OUTPUT:
734         clazz.dump(
735             new BufferedOutputStream JavaDoc(
736             new FileOutputStream JavaDoc(
737                 getOutputFile(clazz.getClassName()))));
738         break;
739         case JAR_OUTPUT:
740         _bcelClasses.addElement(clazz);
741         break;
742         case BYTEARRAY_OUTPUT:
743         case BYTEARRAY_AND_FILE_OUTPUT:
744         case BYTEARRAY_AND_JAR_OUTPUT:
745         case CLASSLOADER_OUTPUT:
746         ByteArrayOutputStream JavaDoc out = new ByteArrayOutputStream JavaDoc(2048);
747         clazz.dump(out);
748         _classes.addElement(out.toByteArray());
749
750         if (_outputType == BYTEARRAY_AND_FILE_OUTPUT)
751           clazz.dump(new BufferedOutputStream JavaDoc(
752             new FileOutputStream JavaDoc(getOutputFile(clazz.getClassName()))));
753         else if (_outputType == BYTEARRAY_AND_JAR_OUTPUT)
754           _bcelClasses.addElement(clazz);
755
756         break;
757         }
758     }
759     catch (Exception JavaDoc e) {
760         e.printStackTrace();
761     }
762     }
763
764     /**
765      * File separators are converted to forward slashes for ZIP files.
766      */

767     private String JavaDoc entryName(File JavaDoc f) throws IOException JavaDoc {
768     return f.getName().replace(File.separatorChar, '/');
769     }
770
771     /**
772      * Generate output JAR-file and packages
773      */

774     public void outputToJar() throws IOException JavaDoc {
775     // create the manifest
776
final Manifest JavaDoc manifest = new Manifest JavaDoc();
777     final java.util.jar.Attributes JavaDoc atrs = manifest.getMainAttributes();
778     atrs.put(java.util.jar.Attributes.Name.MANIFEST_VERSION,"1.2");
779
780     final Map JavaDoc map = manifest.getEntries();
781     // create manifest
782
Enumeration JavaDoc classes = _bcelClasses.elements();
783     final String JavaDoc now = (new Date JavaDoc()).toString();
784     final java.util.jar.Attributes.Name dateAttr =
785         new java.util.jar.Attributes.Name("Date");
786     while (classes.hasMoreElements()) {
787         final JavaClass clazz = (JavaClass)classes.nextElement();
788         final String JavaDoc className = clazz.getClassName().replace('.','/');
789         final java.util.jar.Attributes JavaDoc attr = new java.util.jar.Attributes JavaDoc();
790         attr.put(dateAttr, now);
791         map.put(className+".class", attr);
792     }
793
794     final File JavaDoc jarFile = new File JavaDoc(_destDir, _jarFileName);
795     final JarOutputStream JavaDoc jos =
796         new JarOutputStream JavaDoc(new FileOutputStream JavaDoc(jarFile), manifest);
797     classes = _bcelClasses.elements();
798     while (classes.hasMoreElements()) {
799         final JavaClass clazz = (JavaClass)classes.nextElement();
800         final String JavaDoc className = clazz.getClassName().replace('.','/');
801         jos.putNextEntry(new JarEntry JavaDoc(className+".class"));
802         final ByteArrayOutputStream JavaDoc out = new ByteArrayOutputStream JavaDoc(2048);
803         clazz.dump(out); // dump() closes it's output stream
804
out.writeTo(jos);
805     }
806     jos.close();
807     }
808
809     /**
810      * Turn debugging messages on/off
811      */

812     public void setDebug(boolean debug) {
813     _debug = debug;
814     }
815
816     /**
817      * Get current debugging message setting
818      */

819     public boolean debug() {
820     return _debug;
821     }
822
823
824     /**
825      * Retrieve a string representation of the character data to be stored
826      * in the translet as a <code>char[]</code>. There may be more than
827      * one such array required.
828      * @param index The index of the <code>char[]</code>. Zero-based.
829      * @return String The character data to be stored in the corresponding
830      * <code>char[]</code>.
831      */

832     public String JavaDoc getCharacterData(int index) {
833         return ((StringBuffer JavaDoc) m_characterData.elementAt(index)).toString();
834     }
835
836     /**
837      * Get the number of char[] arrays, thus far, that will be created to
838      * store literal text in the stylesheet.
839      */

840     public int getCharacterDataCount() {
841         return (m_characterData != null) ? m_characterData.size() : 0;
842     }
843
844     /**
845      * Add literal text to char arrays that will be used to store character
846      * data in the stylesheet.
847      * @param newData String data to be added to char arrays.
848      * Pre-condition: <code>newData.length() &le; 21845</code>
849      * @return int offset at which character data will be stored
850      */

851     public int addCharacterData(String JavaDoc newData) {
852         StringBuffer JavaDoc currData;
853         if (m_characterData == null) {
854             m_characterData = new Vector JavaDoc();
855             currData = new StringBuffer JavaDoc();
856             m_characterData.addElement(currData);
857         } else {
858             currData = (StringBuffer JavaDoc) m_characterData
859                                            .elementAt(m_characterData.size()-1);
860         }
861
862         // Character data could take up to three-times as much space when
863
// written to the class file as UTF-8. The maximum size for a
864
// constant is 65535/3. If we exceed that,
865
// (We really should use some "bin packing".)
866
if (newData.length() + currData.length() > 21845) {
867             currData = new StringBuffer JavaDoc();
868             m_characterData.addElement(currData);
869         }
870
871         int newDataOffset = currData.length();
872         currData.append(newData);
873
874         return newDataOffset;
875     }
876 }
877
Popular Tags