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