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: Message.java,v 1.11 2004/02/16 22:24:28 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.INVOKESPECIAL;
  22. import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
  23. import com.sun.org.apache.bcel.internal.generic.InstructionList;
  24. import com.sun.org.apache.bcel.internal.generic.NEW;
  25. import com.sun.org.apache.bcel.internal.generic.PUSH;
  26. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
  27. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
  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. /**
  31. * @author Jacek Ambroziak
  32. * @author Santiago Pericas-Geertsen
  33. * @author Morten Jorgensen
  34. */
  35. final class Message extends Instruction {
  36. private boolean _terminate = false;
  37. public void parseContents(Parser parser) {
  38. String termstr = getAttribute("terminate");
  39. if (termstr != null) {
  40. _terminate = termstr.equals("yes");
  41. }
  42. parseChildren(parser);
  43. }
  44. public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  45. typeCheckContents(stable);
  46. return Type.Void;
  47. }
  48. public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
  49. final ConstantPoolGen cpg = classGen.getConstantPool();
  50. final InstructionList il = methodGen.getInstructionList();
  51. // Load the translet (for call to displayMessage() function)
  52. il.append(classGen.loadTranslet());
  53. switch (elementCount()) {
  54. case 0:
  55. il.append(new PUSH(cpg, ""));
  56. break;
  57. case 1:
  58. SyntaxTreeNode child = (SyntaxTreeNode) elementAt(0);
  59. if (child instanceof Text) {
  60. il.append(new PUSH(cpg, ((Text) child).getText()));
  61. break;
  62. }
  63. // falls through
  64. default:
  65. // Push current output handler onto the stack
  66. il.append(methodGen.loadHandler());
  67. // Replace the current output handler by a ToXMLStream
  68. il.append(new NEW(cpg.addClass(STREAM_XML_OUTPUT)));
  69. il.append(methodGen.storeHandler());
  70. // Push a reference to a StringWriter
  71. il.append(new NEW(cpg.addClass(STRING_WRITER)));
  72. il.append(DUP);
  73. il.append(DUP);
  74. il.append(new INVOKESPECIAL(
  75. cpg.addMethodref(STRING_WRITER, "<init>", "()V")));
  76. // Load ToXMLStream
  77. il.append(methodGen.loadHandler());
  78. il.append(new INVOKESPECIAL(
  79. cpg.addMethodref(STREAM_XML_OUTPUT, "<init>",
  80. "()V")));
  81. // Invoke output.setWriter(STRING_WRITER)
  82. il.append(methodGen.loadHandler());
  83. il.append(SWAP);
  84. il.append(new INVOKEVIRTUAL(
  85. cpg.addMethodref(OUTPUT_BASE, "setWriter",
  86. "("+WRITER_SIG+")V")));
  87. // Invoke output.setEncoding("UTF-8")
  88. il.append(methodGen.loadHandler());
  89. il.append(new PUSH(cpg, "UTF-8")); // other encodings?
  90. il.append(new INVOKEVIRTUAL(
  91. cpg.addMethodref(OUTPUT_BASE, "setEncoding",
  92. "("+STRING_SIG+")V")));
  93. // Invoke output.setOmitXMLDeclaration(true)
  94. il.append(methodGen.loadHandler());
  95. il.append(ICONST_1);
  96. il.append(new INVOKEVIRTUAL(
  97. cpg.addMethodref(OUTPUT_BASE, "setOmitXMLDeclaration",
  98. "(Z)V")));
  99. il.append(methodGen.loadHandler());
  100. il.append(new INVOKEVIRTUAL(
  101. cpg.addMethodref(OUTPUT_BASE, "startDocument",
  102. "()V")));
  103. // Inline translation of contents
  104. translateContents(classGen, methodGen);
  105. il.append(methodGen.loadHandler());
  106. il.append(new INVOKEVIRTUAL(
  107. cpg.addMethodref(OUTPUT_BASE, "endDocument",
  108. "()V")));
  109. // Call toString() on StringWriter
  110. il.append(new INVOKEVIRTUAL(
  111. cpg.addMethodref(STRING_WRITER, "toString",
  112. "()" + STRING_SIG)));
  113. // Restore old output handler
  114. il.append(SWAP);
  115. il.append(methodGen.storeHandler());
  116. break;
  117. }
  118. // Send the resulting string to the message handling method
  119. il.append(new INVOKEVIRTUAL(cpg.addMethodref(TRANSLET_CLASS,
  120. "displayMessage",
  121. "("+STRING_SIG+")V")));
  122. // If 'terminate' attribute is set to 'yes': Instanciate a
  123. // RunTimeException, but it on the stack and throw an exception
  124. if (_terminate == true) {
  125. // Create a new instance of RunTimeException
  126. final int einit = cpg.addMethodref("java.lang.RuntimeException",
  127. "<init>",
  128. "(Ljava/lang/String;)V");
  129. il.append(new NEW(cpg.addClass("java.lang.RuntimeException")));
  130. il.append(DUP);
  131. il.append(new PUSH(cpg,"Termination forced by an " +
  132. "xsl:message instruction"));
  133. il.append(new INVOKESPECIAL(einit));
  134. il.append(ATHROW);
  135. }
  136. }
  137. }