View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /*
6    * Copyright 2001-2004 The Apache Software Foundation.
7    *
8    * Licensed under the Apache License, Version 2.0 (the "License");
9    * you may not use this file except in compliance with the License.
10   * You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  /*
21   * $Id: TransletOutput.java,v 1.2.4.1 2005/09/05 09:19:44 pvedula Exp $
22   */
23  
24  package com.sun.org.apache.xalan.internal.xsltc.compiler;
25  
26  import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
27  import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC;
28  import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
29  import com.sun.org.apache.bcel.internal.generic.InstructionList;
30  import com.sun.org.apache.bcel.internal.generic.PUSH;
31  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
32  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
33  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
34  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.StringType;
35  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
36  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
37  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
38  
39  /**
40   * @author Morten Jorgensen
41   */
42  final class TransletOutput extends Instruction {
43  
44      private Expression _filename;
45      private boolean _append;
46  
47      /**
48       * Displays the contents of this <xsltc:output> element.
49       */
50      public void display(int indent) {
51          indent(indent);
52          Util.println("TransletOutput: " + _filename);
53      }
54  
55      /**
56       * Parse the contents of this <xsltc:output> element. The only attribute
57       * we recognise is the 'file' attribute that contains teh output filename.
58       */
59      public void parseContents(Parser parser) {
60          // Get the output filename from the 'file' attribute
61          String filename = getAttribute("file");
62  
63          // If the 'append' attribute is set to "yes" or "true",
64          // the output is appended to the file.
65          String append   = getAttribute("append");
66  
67          // Verify that the filename is in fact set
68          if ((filename == null) || (filename.equals(EMPTYSTRING))) {
69              reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "file");
70          }
71  
72          // Save filename as an attribute value template
73          _filename = AttributeValue.create(this, filename, parser);
74  
75          if (append != null && (append.toLowerCase().equals("yes") ||
76              append.toLowerCase().equals("true"))) {
77            _append = true;
78          }
79          else
80            _append = false;
81  
82          parseChildren(parser);
83      }
84  
85      /**
86       * Type checks the 'file' attribute (must be able to convert it to a str).
87       */
88      public Type typeCheck(SymbolTable stable) throws TypeCheckError {
89          final Type type = _filename.typeCheck(stable);
90          if (type instanceof StringType == false) {
91              _filename = new CastExpr(_filename, Type.String);
92          }
93          typeCheckContents(stable);
94          return Type.Void;
95      }
96  
97      /**
98       * Compile code that opens the give file for output, dumps the contents of
99       * the element to the file, then closes the file.
100      */
101     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
102         final ConstantPoolGen cpg = classGen.getConstantPool();
103         final InstructionList il = methodGen.getInstructionList();
104         final boolean isSecureProcessing = classGen.getParser().getXSLTC()
105                                            .isSecureProcessing();
106 
107         if (isSecureProcessing) {
108             int index = cpg.addMethodref(BASIS_LIBRARY_CLASS,
109                                          "unallowed_extension_elementF",
110                                          "(Ljava/lang/String;)V");
111             il.append(new PUSH(cpg, "redirect"));
112             il.append(new INVOKESTATIC(index));
113             return;
114         }
115 
116         // Save the current output handler on the stack
117         il.append(methodGen.loadHandler());
118 
119         final int open =  cpg.addMethodref(TRANSLET_CLASS,
120                                            "openOutputHandler",
121                                            "(" + STRING_SIG + "Z)" +
122                                            TRANSLET_OUTPUT_SIG);
123 
124         final int close =  cpg.addMethodref(TRANSLET_CLASS,
125                                             "closeOutputHandler",
126                                             "("+TRANSLET_OUTPUT_SIG+")V");
127 
128         // Create the new output handler (leave it on stack)
129         il.append(classGen.loadTranslet());
130         _filename.translate(classGen, methodGen);
131         il.append(new PUSH(cpg, _append));
132         il.append(new INVOKEVIRTUAL(open));
133 
134         // Overwrite current handler
135         il.append(methodGen.storeHandler());
136 
137         // Translate contents with substituted handler
138         translateContents(classGen, methodGen);
139 
140         // Close the output handler (close file)
141         il.append(classGen.loadTranslet());
142         il.append(methodGen.loadHandler());
143         il.append(new INVOKEVIRTUAL(close));
144 
145         // Restore old output handler from stack
146         il.append(methodGen.storeHandler());
147     }
148 }