1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * @LastModified: Nov 2017 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22 package com.sun.org.apache.xalan.internal.xsltc.compiler; 23 24 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 25 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; 26 import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; 27 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; 28 import com.sun.org.apache.bcel.internal.generic.InstructionList; 29 import com.sun.org.apache.bcel.internal.generic.NEW; 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.MethodGenerator; 33 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; 34 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; 35 36 /** 37 * @author Jacek Ambroziak 38 * @author Santiago Pericas-Geertsen 39 * @author Morten Jorgensen 40 */ 41 final class Message extends Instruction { 42 private boolean _terminate = false; 43 44 public void parseContents(Parser parser) { 45 String termstr = getAttribute("terminate"); 46 if (termstr != null) { 47 _terminate = termstr.equals("yes"); 48 } 49 parseChildren(parser); 50 } 51 52 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 53 typeCheckContents(stable); 54 return Type.Void; 55 } 56 57 @SuppressWarnings("fallthrough") // at default 58 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 59 final ConstantPoolGen cpg = classGen.getConstantPool(); 60 final InstructionList il = methodGen.getInstructionList(); 61 62 // Load the translet (for call to displayMessage() function) 63 il.append(classGen.loadTranslet()); 64 65 switch (elementCount()) { 66 case 0: 67 il.append(new PUSH(cpg, "")); 68 break; 69 case 1: 70 SyntaxTreeNode child = elementAt(0); 71 if (child instanceof Text) { 72 il.append(new PUSH(cpg, ((Text) child).getText())); 73 break; 74 } 75 // falls through 76 default: 77 // Push current output handler onto the stack 78 il.append(methodGen.loadHandler()); 79 80 // Replace the current output handler by a ToXMLStream 81 il.append(new NEW(cpg.addClass(STREAM_XML_OUTPUT))); 82 il.append(methodGen.storeHandler()); 83 84 // Push a reference to a StringWriter 85 il.append(new NEW(cpg.addClass(STRING_WRITER))); 86 il.append(DUP); 87 il.append(DUP); 88 il.append(new INVOKESPECIAL( 89 cpg.addMethodref(STRING_WRITER, "<init>", "()V"))); 90 91 // Load ToXMLStream 92 il.append(methodGen.loadHandler()); 93 il.append(new INVOKESPECIAL( 94 cpg.addMethodref(STREAM_XML_OUTPUT, "<init>", 95 "()V"))); 96 97 // Invoke output.setWriter(STRING_WRITER) 98 il.append(methodGen.loadHandler()); 99 il.append(SWAP); 100 il.append(new INVOKEINTERFACE( 101 cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE, 102 "setWriter", 103 "("+WRITER_SIG+")V"), 2)); 104 105 // Invoke output.setEncoding("UTF-8") 106 il.append(methodGen.loadHandler()); 107 il.append(new PUSH(cpg, "UTF-8")); // other encodings? 108 il.append(new INVOKEINTERFACE( 109 cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE, 110 "setEncoding", 111 "("+STRING_SIG+")V"), 2)); 112 113 // Invoke output.setOmitXMLDeclaration(true) 114 il.append(methodGen.loadHandler()); 115 il.append(ICONST_1); 116 il.append(new INVOKEINTERFACE( 117 cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE, 118 "setOmitXMLDeclaration", 119 "(Z)V"), 2)); 120 121 il.append(methodGen.loadHandler()); 122 il.append(new INVOKEINTERFACE( 123 cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE, 124 "startDocument", 125 "()V"), 1)); 126 127 // Inline translation of contents 128 translateContents(classGen, methodGen); 129 130 il.append(methodGen.loadHandler()); 131 il.append(new INVOKEINTERFACE( 132 cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE, 133 "endDocument", 134 "()V"), 1)); 135 136 // Call toString() on StringWriter 137 il.append(new INVOKEVIRTUAL( 138 cpg.addMethodref(STRING_WRITER, "toString", 139 "()" + STRING_SIG))); 140 141 // Restore old output handler 142 il.append(SWAP); 143 il.append(methodGen.storeHandler()); 144 break; 145 } 146 147 // Send the resulting string to the message handling method 148 il.append(new INVOKEVIRTUAL(cpg.addMethodref(TRANSLET_CLASS, 149 "displayMessage", 150 "("+STRING_SIG+")V"))); 151 152 // If 'terminate' attribute is set to 'yes': Instanciate a 153 // RunTimeException, but it on the stack and throw an exception 154 if (_terminate == true) { 155 // Create a new instance of RunTimeException 156 final int einit = cpg.addMethodref("java.lang.RuntimeException", 157 "<init>", 158 "(Ljava/lang/String;)V"); 159 il.append(new NEW(cpg.addClass("java.lang.RuntimeException"))); 160 il.append(DUP); 161 il.append(new PUSH(cpg,"Termination forced by an " + 162 "xsl:message instruction")); 163 il.append(new INVOKESPECIAL(einit)); 164 il.append(ATHROW); 165 } 166 } 167 168 }