KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xalan > internal > 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.1.2.1 2006/09/19 01:06:49 jeffsuttor Exp $
18  */

19
20 package com.sun.org.apache.xalan.internal.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 com.sun.org.apache.bcel.internal.classfile.JavaClass;
40 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
41 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
42 import com.sun.org.apache.xml.internal.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      * State of the secure processing feature.
127      */

128     private boolean _isSecureProcessing = false;
129
130     /**
131      * XSLTC compiler constructor
132      */

133     public XSLTC() {
134     _parser = new Parser(this);
135     }
136
137     /**
138      * Set the state of the secure processing feature.
139      */

140     public void setSecureProcessing(boolean flag) {
141         _isSecureProcessing = flag;
142     }
143     
144     /**
145      * Return the state of the secure processing feature.
146      */

147     public boolean isSecureProcessing() {
148         return _isSecureProcessing;
149     }
150
151     /**
152      * Only for user by the internal TrAX implementation.
153      */

154     public Parser getParser() {
155         return _parser;
156     }
157
158     /**
159      * Only for user by the internal TrAX implementation.
160      */

161     public void setOutputType(int type) {
162     _outputType = type;
163     }
164
165     /**
166      * Only for user by the internal TrAX implementation.
167      */

168     public Properties JavaDoc getOutputProperties() {
169     return _parser.getOutputProperties();
170     }
171
172     /**
173      * Initializes the compiler to compile a new stylesheet
174      */

175     public void init() {
176     reset();
177     _reader = null;
178     _classes = new Vector JavaDoc();
179     _bcelClasses = new Vector JavaDoc();
180     }
181
182     /**
183      * Initializes the compiler to produce a new translet
184      */

185     private void reset() {
186     _nextGType = DTM.NTYPES;
187     _elements = new Hashtable JavaDoc();
188     _attributes = new Hashtable JavaDoc();
189     _namespaces = new Hashtable JavaDoc();
190     _namespaces.put("",new Integer JavaDoc(_nextNSType));
191     _namesIndex = new Vector JavaDoc(128);
192     _namespaceIndex = new Vector JavaDoc(32);
193     _namespacePrefixes = new Hashtable JavaDoc();
194         _stylesheet = null;
195     _parser.init();
196     //_variableSerial = 1;
197
_modeSerial = 1;
198     _stylesheetSerial = 1;
199     _stepPatternSerial = 1;
200     _helperClassSerial = 0;
201     _attributeSetSerial = 0;
202     _multiDocument = false;
203     _hasIdCall = false;
204     _numberFieldIndexes = new int[] {
205         -1, // LEVEL_SINGLE
206
-1, // LEVEL_MULTIPLE
207
-1 // LEVEL_ANY
208
};
209     }
210
211     /**
212      * Defines an external SourceLoader to provide the compiler with documents
213      * referenced in xsl:include/import
214      * @param loader The SourceLoader to use for include/import
215      */

216     public void setSourceLoader(SourceLoader loader) {
217     _loader = loader;
218     }
219
220     /**
221      * Set a flag indicating if templates are to be inlined or not. The
222      * default is to do inlining, but this causes problems when the
223      * stylesheets have a large number of templates (e.g. branch targets
224      * exceeding 64K or a length of a method exceeding 64K).
225      */

226     public void setTemplateInlining(boolean templateInlining) {
227     _templateInlining = templateInlining;
228     }
229
230     /**
231      * Set the parameters to use to locate the correct <?xml-stylesheet ...?>
232      * processing instruction in the case where the input document to the
233      * compiler (and parser) is an XML document.
234      * @param media The media attribute to be matched. May be null, in which
235      * case the prefered templates will be used (i.e. alternate = no).
236      * @param title The value of the title attribute to match. May be null.
237      * @param charset The value of the charset attribute to match. May be null.
238      */

239     public void setPIParameters(String JavaDoc media, String JavaDoc title, String JavaDoc charset) {
240     _parser.setPIParameters(media, title, charset);
241     }
242
243     /**
244      * Compiles an XSL stylesheet pointed to by a URL
245      * @param url An URL containing the input XSL stylesheet
246      */

247     public boolean compile(URL JavaDoc url) {
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, _className);
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 pointed to by a URL
263      * @param url An URL containing the input XSL stylesheet
264      * @param name The name to assign to the translet class
265      */

266     public boolean compile(URL JavaDoc url, String JavaDoc name) {
267     try {
268         // Open input stream from URL and wrap inside InputSource
269
final InputStream JavaDoc stream = url.openStream();
270         final InputSource JavaDoc input = new InputSource JavaDoc(stream);
271         input.setSystemId(url.toString());
272         return compile(input, name);
273     }
274     catch (IOException JavaDoc e) {
275         _parser.reportError(Constants.FATAL, new ErrorMsg(e));
276         return false;
277     }
278     }
279
280     /**
281      * Compiles an XSL stylesheet passed in through an InputStream
282      * @param input An InputStream that will pass in the stylesheet contents
283      * @param name The name of the translet class to generate
284      * @return 'true' if the compilation was successful
285      */

286     public boolean compile(InputStream JavaDoc stream, String JavaDoc name) {
287     final InputSource JavaDoc input = new InputSource JavaDoc(stream);
288     input.setSystemId(name); // We have nothing else!!!
289
return compile(input, name);
290     }
291
292     /**
293      * Compiles an XSL stylesheet passed in through an InputStream
294      * @param input An InputSource that will pass in the stylesheet contents
295      * @param name The name of the translet class to generate - can be null
296      * @return 'true' if the compilation was successful
297      */

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

377     public boolean compile(Vector JavaDoc stylesheets) {
378     // Get the number of stylesheets (ie. URLs) in the vector
379
final int count = stylesheets.size();
380
381     // Return straight away if the vector is empty
382
if (count == 0) return true;
383
384     // Special handling needed if the URL count is one, becuase the
385
// _className global must not be reset if it was set explicitly
386
if (count == 1) {
387         final Object JavaDoc url = stylesheets.firstElement();
388         if (url instanceof URL JavaDoc)
389         return compile((URL JavaDoc)url);
390         else
391         return false;
392     }
393     else {
394         // Traverse all elements in the vector and compile
395
final Enumeration JavaDoc urls = stylesheets.elements();
396         while (urls.hasMoreElements()) {
397         _className = null; // reset, so that new name will be computed
398
final Object JavaDoc url = urls.nextElement();
399         if (url instanceof URL JavaDoc) {
400             if (!compile((URL JavaDoc)url)) return false;
401         }
402         }
403     }
404     return true;
405     }
406
407     /**
408      * Returns an array of bytecode arrays generated by a compilation.
409      * @return JVM bytecodes that represent translet class definition
410      */

411     public byte[][] getBytecodes() {
412     final int count = _classes.size();
413     final byte[][] result = new byte[count][1];
414     for (int i = 0; i < count; i++)
415         result[i] = (byte[])_classes.elementAt(i);
416     return result;
417     }
418
419     /**
420      * Compiles a stylesheet pointed to by a URL. The result is put in a
421      * set of byte arrays. One byte array for each generated class.
422      * @param name The name of the translet class to generate
423      * @param input An InputSource that will pass in the stylesheet contents
424      * @param outputType The output type
425      * @return JVM bytecodes that represent translet class definition
426      */

427     public byte[][] compile(String JavaDoc name, InputSource JavaDoc input, int outputType) {
428     _outputType = outputType;
429     if (compile(input, name))
430         return getBytecodes();
431     else
432         return null;
433     }
434
435     /**
436      * Compiles a stylesheet pointed to by a URL. The result is put in a
437      * set of byte arrays. One byte array for each generated class.
438      * @param name The name of the translet class to generate
439      * @param input An InputSource that will pass in the stylesheet contents
440      * @return JVM bytecodes that represent translet class definition
441      */

442     public byte[][] compile(String JavaDoc name, InputSource JavaDoc input) {
443         return compile(name, input, BYTEARRAY_OUTPUT);
444     }
445
446     /**
447      * Set the XMLReader to use for parsing the next input stylesheet
448      * @param reader XMLReader (SAX2 parser) to use
449      */

450     public void setXMLReader(XMLReader JavaDoc reader) {
451     _reader = reader;
452     }
453
454     /**
455      * Get the XMLReader to use for parsing the next input stylesheet
456      */

457     public XMLReader JavaDoc getXMLReader() {
458     return _reader ;
459     }
460
461     /**
462      * Get a Vector containing all compile error messages
463      * @return A Vector containing all compile error messages
464      */

465     public Vector JavaDoc getErrors() {
466     return _parser.getErrors();
467     }
468
469     /**
470      * Get a Vector containing all compile warning messages
471      * @return A Vector containing all compile error messages
472      */

473     public Vector JavaDoc getWarnings() {
474     return _parser.getWarnings();
475     }
476
477     /**
478      * Print all compile error messages to standard output
479      */

480     public void printErrors() {
481     _parser.printErrors();
482     }
483
484     /**
485      * Print all compile warning messages to standard output
486      */

487     public void printWarnings() {
488     _parser.printWarnings();
489     }
490
491     /**
492      * This method is called by the XPathParser when it encounters a call
493      * to the document() function. Affects the DOM used by the translet.
494      */

495     protected void setMultiDocument(boolean flag) {
496     _multiDocument = flag;
497     }
498
499     public boolean isMultiDocument() {
500     return _multiDocument;
501     }
502
503     /**
504      * This method is called by the XPathParser when it encounters a call
505      * to the nodeset() extension function. Implies multi document.
506      */

507     protected void setCallsNodeset(boolean flag) {
508     if (flag) setMultiDocument(flag);
509     _callsNodeset = flag;
510     }
511
512     public boolean callsNodeset() {
513     return _callsNodeset;
514     }
515
516     protected void setHasIdCall(boolean flag) {
517         _hasIdCall = flag;
518     }
519
520     public boolean hasIdCall() {
521         return _hasIdCall;
522     }
523
524     /**
525      * Set the class name for the generated translet. This class name is
526      * overridden if multiple stylesheets are compiled in one go using the
527      * compile(Vector urls) method.
528      * @param className The name to assign to the translet class
529      */

530     public void setClassName(String JavaDoc className) {
531     final String JavaDoc base = Util.baseName(className);
532     final String JavaDoc noext = Util.noExtName(base);
533     String JavaDoc name = Util.toJavaName(noext);
534
535     if (_packageName == null)
536         _className = name;
537     else
538         _className = _packageName + '.' + name;
539     }
540
541     /**
542      * Get the class name for the generated translet.
543      */

544     public String JavaDoc getClassName() {
545     return _className;
546     }
547
548     /**
549      * Convert for Java class name of local system file name.
550      * (Replace '.' with '/' on UNIX and replace '.' by '\' on Windows/DOS.)
551      */

552     private String JavaDoc classFileName(final String JavaDoc className) {
553     return className.replace('.', File.separatorChar) + ".class";
554     }
555
556     /**
557      * Generate an output File object to send the translet to
558      */

559     private File JavaDoc getOutputFile(String JavaDoc className) {
560     if (_destDir != null)
561         return new File JavaDoc(_destDir, classFileName(className));
562     else
563         return new File JavaDoc(classFileName(className));
564     }
565
566     /**
567      * Set the destination directory for the translet.
568      * The current working directory will be used by default.
569      */

570     public boolean setDestDirectory(String JavaDoc dstDirName) {
571     final File JavaDoc dir = new File JavaDoc(dstDirName);
572     if (dir.exists() || dir.mkdirs()) {
573         _destDir = dir;
574         return true;
575     }
576     else {
577         _destDir = null;
578         return false;
579     }
580     }
581
582     /**
583      * Set an optional package name for the translet and auxiliary classes
584      */

585     public void setPackageName(String JavaDoc packageName) {
586     _packageName = packageName;
587     if (_className != null) setClassName(_className);
588     }
589
590     /**
591      * Set the name of an optional JAR-file to dump the translet and
592      * auxiliary classes to
593      */

594     public void setJarFileName(String JavaDoc jarFileName) {
595     final String JavaDoc JAR_EXT = ".jar";
596     if (jarFileName.endsWith(JAR_EXT))
597         _jarFileName = jarFileName;
598     else
599         _jarFileName = jarFileName + JAR_EXT;
600     _outputType = JAR_OUTPUT;
601     }
602
603     public String JavaDoc getJarFileName() {
604     return _jarFileName;
605     }
606
607     /**
608      * Set the top-level stylesheet
609      */

610     public void setStylesheet(Stylesheet stylesheet) {
611     if (_stylesheet == null) _stylesheet = stylesheet;
612     }
613
614     /**
615      * Returns the top-level stylesheet
616      */

617     public Stylesheet getStylesheet() {
618     return _stylesheet;
619     }
620
621     /**
622      * Registers an attribute and gives it a type so that it can be mapped to
623      * DOM attribute types at run-time.
624      */

625     public int registerAttribute(QName name) {
626     Integer JavaDoc code = (Integer JavaDoc)_attributes.get(name.toString());
627     if (code == null) {
628         code = new Integer JavaDoc(_nextGType++);
629         _attributes.put(name.toString(), code);
630         final String JavaDoc uri = name.getNamespace();
631         final String JavaDoc local = "@"+name.getLocalPart();
632         if ((uri != null) && (!uri.equals("")))
633         _namesIndex.addElement(uri+":"+local);
634         else
635         _namesIndex.addElement(local);
636         if (name.getLocalPart().equals("*")) {
637         registerNamespace(name.getNamespace());
638         }
639     }
640     return code.intValue();
641     }
642
643     /**
644      * Registers an element and gives it a type so that it can be mapped to
645      * DOM element types at run-time.
646      */

647     public int registerElement(QName name) {
648     // Register element (full QName)
649
Integer JavaDoc code = (Integer JavaDoc)_elements.get(name.toString());
650     if (code == null) {
651         _elements.put(name.toString(), code = new Integer JavaDoc(_nextGType++));
652         _namesIndex.addElement(name.toString());
653     }
654     if (name.getLocalPart().equals("*")) {
655         registerNamespace(name.getNamespace());
656     }
657     return code.intValue();
658     }
659
660      /**
661       * Registers a namespace prefix and gives it a type so that it can be mapped to
662       * DOM namespace types at run-time.
663       */

664   
665     public int registerNamespacePrefix(QName name) {
666     
667     Integer JavaDoc code = (Integer JavaDoc)_namespacePrefixes.get(name.toString());
668     if (code == null) {
669         code = new Integer JavaDoc(_nextGType++);
670         _namespacePrefixes.put(name.toString(), code);
671         final String JavaDoc uri = name.getNamespace();
672         if ((uri != null) && (!uri.equals(""))){
673             // namespace::ext2:ped2 will be made empty in TypedNamespaceIterator
674
_namesIndex.addElement("?");
675         } else{
676            _namesIndex.addElement("?"+name.getLocalPart());
677         }
678     }
679     return code.intValue();
680     }
681
682     /**
683      * Registers a namespace and gives it a type so that it can be mapped to
684      * DOM namespace types at run-time.
685      */

686     public int registerNamespace(String JavaDoc namespaceURI) {
687     Integer JavaDoc code = (Integer JavaDoc)_namespaces.get(namespaceURI);
688     if (code == null) {
689         code = new Integer JavaDoc(_nextNSType++);
690         _namespaces.put(namespaceURI,code);
691         _namespaceIndex.addElement(namespaceURI);
692     }
693     return code.intValue();
694     }
695
696     public int nextModeSerial() {
697     return _modeSerial++;
698     }
699
700     public int nextStylesheetSerial() {
701     return _stylesheetSerial++;
702     }
703
704     public int nextStepPatternSerial() {
705     return _stepPatternSerial++;
706     }
707
708     public int[] getNumberFieldIndexes() {
709     return _numberFieldIndexes;
710     }
711
712     public int nextHelperClassSerial() {
713     return _helperClassSerial++;
714     }
715
716     public int nextAttributeSetSerial() {
717     return _attributeSetSerial++;
718     }
719
720     public Vector JavaDoc getNamesIndex() {
721     return _namesIndex;
722     }
723
724     public Vector JavaDoc getNamespaceIndex() {
725     return _namespaceIndex;
726     }
727
728     /**
729      * Returns a unique name for every helper class needed to
730      * execute a translet.
731      */

732     public String JavaDoc getHelperClassName() {
733     return getClassName() + '$' + _helperClassSerial++;
734     }
735
736     public void dumpClass(JavaClass clazz) {
737
738     if (_outputType == FILE_OUTPUT ||
739         _outputType == BYTEARRAY_AND_FILE_OUTPUT)
740     {
741         File JavaDoc outFile = getOutputFile(clazz.getClassName());
742         String JavaDoc parentDir = outFile.getParent();
743         if (parentDir != null) {
744             File JavaDoc parentFile = new File JavaDoc(parentDir);
745             if (!parentFile.exists())
746                 parentFile.mkdirs();
747         }
748     }
749
750     try {
751         switch (_outputType) {
752         case FILE_OUTPUT:
753         clazz.dump(
754             new BufferedOutputStream JavaDoc(
755             new FileOutputStream JavaDoc(
756                 getOutputFile(clazz.getClassName()))));
757         break;
758         case JAR_OUTPUT:
759         _bcelClasses.addElement(clazz);
760         break;
761         case BYTEARRAY_OUTPUT:
762         case BYTEARRAY_AND_FILE_OUTPUT:
763         case BYTEARRAY_AND_JAR_OUTPUT:
764         case CLASSLOADER_OUTPUT:
765         ByteArrayOutputStream JavaDoc out = new ByteArrayOutputStream JavaDoc(2048);
766         clazz.dump(out);
767         _classes.addElement(out.toByteArray());
768
769         if (_outputType == BYTEARRAY_AND_FILE_OUTPUT)
770           clazz.dump(new BufferedOutputStream JavaDoc(
771             new FileOutputStream JavaDoc(getOutputFile(clazz.getClassName()))));
772         else if (_outputType == BYTEARRAY_AND_JAR_OUTPUT)
773           _bcelClasses.addElement(clazz);
774
775         break;
776         }
777     }
778     catch (Exception JavaDoc e) {
779         e.printStackTrace();
780     }
781     }
782
783     /**
784      * File separators are converted to forward slashes for ZIP files.
785      */

786     private String JavaDoc entryName(File JavaDoc f) throws IOException JavaDoc {
787     return f.getName().replace(File.separatorChar, '/');
788     }
789
790     /**
791      * Generate output JAR-file and packages
792      */

793     public void outputToJar() throws IOException JavaDoc {
794     // create the manifest
795
final Manifest JavaDoc manifest = new Manifest JavaDoc();
796     final java.util.jar.Attributes JavaDoc atrs = manifest.getMainAttributes();
797     atrs.put(java.util.jar.Attributes.Name.MANIFEST_VERSION,"1.2");
798
799     final Map JavaDoc map = manifest.getEntries();
800     // create manifest
801
Enumeration JavaDoc classes = _bcelClasses.elements();
802     final String JavaDoc now = (new Date JavaDoc()).toString();
803     final java.util.jar.Attributes.Name dateAttr =
804         new java.util.jar.Attributes.Name("Date");
805     while (classes.hasMoreElements()) {
806         final JavaClass clazz = (JavaClass)classes.nextElement();
807         final String JavaDoc className = clazz.getClassName().replace('.','/');
808         final java.util.jar.Attributes JavaDoc attr = new java.util.jar.Attributes JavaDoc();
809         attr.put(dateAttr, now);
810         map.put(className+".class", attr);
811     }
812
813     final File JavaDoc jarFile = new File JavaDoc(_destDir, _jarFileName);
814     final JarOutputStream JavaDoc jos =
815         new JarOutputStream JavaDoc(new FileOutputStream JavaDoc(jarFile), manifest);
816     classes = _bcelClasses.elements();
817     while (classes.hasMoreElements()) {
818         final JavaClass clazz = (JavaClass)classes.nextElement();
819         final String JavaDoc className = clazz.getClassName().replace('.','/');
820         jos.putNextEntry(new JarEntry JavaDoc(className+".class"));
821         final ByteArrayOutputStream JavaDoc out = new ByteArrayOutputStream JavaDoc(2048);
822         clazz.dump(out); // dump() closes it's output stream
823
out.writeTo(jos);
824     }
825     jos.close();
826     }
827
828     /**
829      * Turn debugging messages on/off
830      */

831     public void setDebug(boolean debug) {
832     _debug = debug;
833     }
834
835     /**
836      * Get current debugging message setting
837      */

838     public boolean debug() {
839     return _debug;
840     }
841
842
843     /**
844      * Retrieve a string representation of the character data to be stored
845      * in the translet as a <code>char[]</code>. There may be more than
846      * one such array required.
847      * @param index The index of the <code>char[]</code>. Zero-based.
848      * @return String The character data to be stored in the corresponding
849      * <code>char[]</code>.
850      */

851     public String JavaDoc getCharacterData(int index) {
852         return ((StringBuffer JavaDoc) m_characterData.elementAt(index)).toString();
853     }
854
855     /**
856      * Get the number of char[] arrays, thus far, that will be created to
857      * store literal text in the stylesheet.
858      */

859     public int getCharacterDataCount() {
860         return (m_characterData != null) ? m_characterData.size() : 0;
861     }
862
863     /**
864      * Add literal text to char arrays that will be used to store character
865      * data in the stylesheet.
866      * @param newData String data to be added to char arrays.
867      * Pre-condition: <code>newData.length() &le; 21845</code>
868      * @return int offset at which character data will be stored
869      */

870     public int addCharacterData(String JavaDoc newData) {
871         StringBuffer JavaDoc currData;
872         if (m_characterData == null) {
873             m_characterData = new Vector JavaDoc();
874             currData = new StringBuffer JavaDoc();
875             m_characterData.addElement(currData);
876         } else {
877             currData = (StringBuffer JavaDoc) m_characterData
878                                            .elementAt(m_characterData.size()-1);
879         }
880
881         // Character data could take up to three-times as much space when
882
// written to the class file as UTF-8. The maximum size for a
883
// constant is 65535/3. If we exceed that,
884
// (We really should use some "bin packing".)
885
if (newData.length() + currData.length() > 21845) {
886             currData = new StringBuffer JavaDoc();
887             m_characterData.addElement(currData);
888         }
889
890         int newDataOffset = currData.length();
891         currData.append(newData);
892
893         return newDataOffset;
894     }
895 }
896
Popular Tags