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: TransletOutput.java,v 1.12 2004/02/16 22:25:10 minchau Exp $
  18. */
  19. package com.sun.org.apache.xalan.internal.xsltc.compiler;
  20. import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
  21. import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
  22. import com.sun.org.apache.bcel.internal.generic.InstructionList;
  23. import com.sun.org.apache.bcel.internal.generic.PUSH;
  24. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
  25. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
  26. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
  27. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.StringType;
  28. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
  29. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
  30. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
  31. /**
  32. * @author Morten Jorgensen
  33. */
  34. final class TransletOutput extends Instruction {
  35. private Expression _filename;
  36. private boolean _append;
  37. /**
  38. * Displays the contents of this <xsltc:output> element.
  39. */
  40. public void display(int indent) {
  41. indent(indent);
  42. Util.println("TransletOutput: " + _filename);
  43. }
  44. /**
  45. * Parse the contents of this <xsltc:output> element. The only attribute
  46. * we recognise is the 'file' attribute that contains teh output filename.
  47. */
  48. public void parseContents(Parser parser) {
  49. // Get the output filename from the 'file' attribute
  50. String filename = getAttribute("file");
  51. // If the 'append' attribute is set to "yes" or "true",
  52. // the output is appended to the file.
  53. String append = getAttribute("append");
  54. // Verify that the filename is in fact set
  55. if ((filename == null) || (filename.equals(EMPTYSTRING))) {
  56. reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "file");
  57. }
  58. // Save filename as an attribute value template
  59. _filename = AttributeValue.create(this, filename, parser);
  60. if (append != null && (append.toLowerCase().equals("yes") ||
  61. append.toLowerCase().equals("true"))) {
  62. _append = true;
  63. }
  64. else
  65. _append = false;
  66. parseChildren(parser);
  67. }
  68. /**
  69. * Type checks the 'file' attribute (must be able to convert it to a str).
  70. */
  71. public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  72. final Type type = _filename.typeCheck(stable);
  73. if (type instanceof StringType == false) {
  74. _filename = new CastExpr(_filename, Type.String);
  75. }
  76. typeCheckContents(stable);
  77. return Type.Void;
  78. }
  79. /**
  80. * Compile code that opens the give file for output, dumps the contents of
  81. * the element to the file, then closes the file.
  82. */
  83. public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
  84. final ConstantPoolGen cpg = classGen.getConstantPool();
  85. final InstructionList il = methodGen.getInstructionList();
  86. // Save the current output handler on the stack
  87. il.append(methodGen.loadHandler());
  88. final int open = cpg.addMethodref(TRANSLET_CLASS,
  89. "openOutputHandler",
  90. "(" + STRING_SIG + "Z)" +
  91. TRANSLET_OUTPUT_SIG);
  92. final int close = cpg.addMethodref(TRANSLET_CLASS,
  93. "closeOutputHandler",
  94. "("+TRANSLET_OUTPUT_SIG+")V");
  95. // Create the new output handler (leave it on stack)
  96. il.append(classGen.loadTranslet());
  97. _filename.translate(classGen, methodGen);
  98. il.append(new PUSH(cpg, _append));
  99. il.append(new INVOKEVIRTUAL(open));
  100. // Overwrite current handler
  101. il.append(methodGen.storeHandler());
  102. // Translate contents with substituted handler
  103. translateContents(classGen, methodGen);
  104. // Close the output handler (close file)
  105. il.append(classGen.loadTranslet());
  106. il.append(methodGen.loadHandler());
  107. il.append(new INVOKEVIRTUAL(close));
  108. // Restore old output handler from stack
  109. il.append(methodGen.storeHandler());
  110. }
  111. }