1/* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 */ 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 22package com.sun.org.apache.xalan.internal.xsltc.compiler; 23 24import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 25import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; 26import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; 27import com.sun.org.apache.bcel.internal.generic.InstructionList; 28import com.sun.org.apache.bcel.internal.generic.PUSH; 29import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; 30import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; 31import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; 32import com.sun.org.apache.xalan.internal.xsltc.compiler.util.StringType; 33import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; 34import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; 35import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util; 36import jdk.xml.internal.JdkXmlFeatures; 37 38/** 39 * @author Morten Jorgensen 40 */ 41final class TransletOutput extends Instruction { 42 43 private Expression _filename; 44 private boolean _append; 45 46 /** 47 * Displays the contents of this <xsltc:output> element. 48 */ 49 public void display(int indent) { 50 indent(indent); 51 Util.println("TransletOutput: " + _filename); 52 } 53 54 /** 55 * Parse the contents of this <xsltc:output> element. The only attribute 56 * we recognise is the 'file' attribute that contains teh output filename. 57 */ 58 public void parseContents(Parser parser) { 59 // Get the output filename from the 'file' attribute 60 String filename = getAttribute("file"); 61 62 // If the 'append' attribute is set to "yes" or "true", 63 // the output is appended to the file. 64 String append = getAttribute("append"); 65 66 // Verify that the filename is in fact set 67 if ((filename == null) || (filename.equals(EMPTYSTRING))) { 68 reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "file"); 69 } 70 71 // Save filename as an attribute value template 72 _filename = AttributeValue.create(this, filename, parser); 73 74 if (append != null && (append.toLowerCase().equals("yes") || 75 append.toLowerCase().equals("true"))) { 76 _append = true; 77 } 78 else 79 _append = false; 80 81 parseChildren(parser); 82 } 83 84 /** 85 * Type checks the 'file' attribute (must be able to convert it to a str). 86 */ 87 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 88 final Type type = _filename.typeCheck(stable); 89 if (type instanceof StringType == false) { 90 _filename = new CastExpr(_filename, Type.String); 91 } 92 typeCheckContents(stable); 93 return Type.Void; 94 } 95 96 /** 97 * Compile code that opens the give file for output, dumps the contents of 98 * the element to the file, then closes the file. 99 */ 100 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 101 final ConstantPoolGen cpg = classGen.getConstantPool(); 102 final InstructionList il = methodGen.getInstructionList(); 103 final boolean isSecureProcessing = classGen.getParser().getXSLTC() 104 .isSecureProcessing(); 105 final boolean isExtensionFunctionEnabled = classGen.getParser().getXSLTC() 106 .getFeature(JdkXmlFeatures.XmlFeature.ENABLE_EXTENSION_FUNCTION); 107 108 if (isSecureProcessing && !isExtensionFunctionEnabled) { 109 int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, 110 "unallowed_extension_elementF", 111 "(Ljava/lang/String;)V"); 112 il.append(new PUSH(cpg, "redirect")); 113 il.append(new INVOKESTATIC(index)); 114 return; 115 } 116 117 // Save the current output handler on the stack 118 il.append(methodGen.loadHandler()); 119 120 final int open = cpg.addMethodref(TRANSLET_CLASS, 121 "openOutputHandler", 122 "(" + STRING_SIG + "Z)" + 123 TRANSLET_OUTPUT_SIG); 124 125 final int close = cpg.addMethodref(TRANSLET_CLASS, 126 "closeOutputHandler", 127 "("+TRANSLET_OUTPUT_SIG+")V"); 128 129 // Create the new output handler (leave it on stack) 130 il.append(classGen.loadTranslet()); 131 _filename.translate(classGen, methodGen); 132 il.append(new PUSH(cpg, _append)); 133 il.append(new INVOKEVIRTUAL(open)); 134 135 // Overwrite current handler 136 il.append(methodGen.storeHandler()); 137 138 // Translate contents with substituted handler 139 translateContents(classGen, methodGen); 140 141 // Close the output handler (close file) 142 il.append(classGen.loadTranslet()); 143 il.append(methodGen.loadHandler()); 144 il.append(new INVOKEVIRTUAL(close)); 145 146 // Restore old output handler from stack 147 il.append(methodGen.storeHandler()); 148 } 149} 150