1 /* 2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. 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 package com.sun.org.apache.xalan.internal.xsltc.compiler.util; 22 23 import com.sun.org.apache.bcel.internal.generic.BranchHandle; 24 import com.sun.org.apache.bcel.internal.generic.CHECKCAST; 25 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 26 import com.sun.org.apache.bcel.internal.generic.GETFIELD; 27 import com.sun.org.apache.bcel.internal.generic.GOTO; 28 import com.sun.org.apache.bcel.internal.generic.IFEQ; 29 import com.sun.org.apache.bcel.internal.generic.ILOAD; 30 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; 31 import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; 32 import com.sun.org.apache.bcel.internal.generic.ISTORE; 33 import com.sun.org.apache.bcel.internal.generic.Instruction; 34 import com.sun.org.apache.bcel.internal.generic.InstructionList; 35 import com.sun.org.apache.bcel.internal.generic.NEW; 36 import com.sun.org.apache.bcel.internal.generic.PUSH; 37 import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants; 38 import com.sun.org.apache.xalan.internal.xsltc.compiler.FlowList; 39 import com.sun.org.apache.xalan.internal.xsltc.compiler.NodeTest; 40 41 /** 42 * @author Jacek Ambroziak 43 * @author Santiago Pericas-Geertsen 44 * @LastModified: Oct 2017 45 */ 46 public final class NodeType extends Type { 47 private final int _type; 48 NodeType()49 protected NodeType() { 50 this(NodeTest.ANODE); 51 } 52 NodeType(int type)53 protected NodeType(int type) { 54 _type = type; 55 } 56 getType()57 public int getType() { 58 return _type; 59 } 60 toString()61 public String toString() { 62 return "node-type"; 63 } 64 identicalTo(Type other)65 public boolean identicalTo(Type other) { 66 return other instanceof NodeType; 67 } 68 hashCode()69 public int hashCode() { 70 return _type; 71 } 72 toSignature()73 public String toSignature() { 74 return "I"; 75 } 76 toJCType()77 public com.sun.org.apache.bcel.internal.generic.Type toJCType() { 78 return com.sun.org.apache.bcel.internal.generic.Type.INT; 79 } 80 81 /** 82 * Translates a node into an object of internal type <code>type</code>. 83 * The translation to int is undefined since nodes are always converted 84 * to reals in arithmetic expressions. 85 * 86 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 87 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, Type type)88 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 89 Type type) { 90 if (type == Type.String) { 91 translateTo(classGen, methodGen, (StringType) type); 92 } 93 else if (type == Type.Boolean) { 94 translateTo(classGen, methodGen, (BooleanType) type); 95 } 96 else if (type == Type.Real) { 97 translateTo(classGen, methodGen, (RealType) type); 98 } 99 else if (type == Type.NodeSet) { 100 translateTo(classGen, methodGen, (NodeSetType) type); 101 } 102 else if (type == Type.Reference) { 103 translateTo(classGen, methodGen, (ReferenceType) type); 104 } 105 else if (type == Type.Object) { 106 translateTo(classGen, methodGen, (ObjectType) type); 107 } 108 else { 109 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 110 toString(), type.toString()); 111 classGen.getParser().reportError(Constants.FATAL, err); 112 } 113 } 114 115 /** 116 * Expects a node on the stack and pushes its string value. 117 * 118 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 119 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, StringType type)120 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 121 StringType type) { 122 final ConstantPoolGen cpg = classGen.getConstantPool(); 123 final InstructionList il = methodGen.getInstructionList(); 124 125 switch (_type) { 126 case NodeTest.ROOT: 127 case NodeTest.ELEMENT: 128 il.append(methodGen.loadDOM()); 129 il.append(SWAP); // dom ref must be below node index 130 int index = cpg.addInterfaceMethodref(DOM_INTF, 131 GET_ELEMENT_VALUE, 132 GET_ELEMENT_VALUE_SIG); 133 il.append(new INVOKEINTERFACE(index, 2)); 134 break; 135 136 case NodeTest.ANODE: 137 case NodeTest.COMMENT: 138 case NodeTest.ATTRIBUTE: 139 case NodeTest.PI: 140 il.append(methodGen.loadDOM()); 141 il.append(SWAP); // dom ref must be below node index 142 index = cpg.addInterfaceMethodref(DOM_INTF, 143 GET_NODE_VALUE, 144 GET_NODE_VALUE_SIG); 145 il.append(new INVOKEINTERFACE(index, 2)); 146 break; 147 148 default: 149 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 150 toString(), type.toString()); 151 classGen.getParser().reportError(Constants.FATAL, err); 152 break; 153 } 154 } 155 156 /** 157 * Translates a node into a synthesized boolean. 158 * If the expression is "@attr", 159 * then "true" is pushed iff "attr" is an attribute of the current node. 160 * If the expression is ".", the result is always "true". 161 * 162 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 163 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, BooleanType type)164 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 165 BooleanType type) { 166 final InstructionList il = methodGen.getInstructionList(); 167 FlowList falsel = translateToDesynthesized(classGen, methodGen, type); 168 il.append(ICONST_1); 169 final BranchHandle truec = il.append(new GOTO(null)); 170 falsel.backPatch(il.append(ICONST_0)); 171 truec.setTarget(il.append(NOP)); 172 } 173 174 /** 175 * Expects a node on the stack and pushes a real. 176 * First the node is converted to string, and from string to real. 177 * 178 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 179 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, RealType type)180 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 181 RealType type) { 182 translateTo(classGen, methodGen, Type.String); 183 Type.String.translateTo(classGen, methodGen, Type.Real); 184 } 185 186 /** 187 * Expects a node on the stack and pushes a singleton node-set. Singleton 188 * iterators are already started after construction. 189 * 190 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 191 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, NodeSetType type)192 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 193 NodeSetType type) { 194 ConstantPoolGen cpg = classGen.getConstantPool(); 195 InstructionList il = methodGen.getInstructionList(); 196 197 // Create a new instance of SingletonIterator 198 il.append(new NEW(cpg.addClass(SINGLETON_ITERATOR))); 199 il.append(DUP_X1); 200 il.append(SWAP); 201 final int init = cpg.addMethodref(SINGLETON_ITERATOR, "<init>", 202 "(" + NODE_SIG +")V"); 203 il.append(new INVOKESPECIAL(init)); 204 } 205 206 /** 207 * Subsume Node into ObjectType. 208 * 209 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 210 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, ObjectType type)211 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 212 ObjectType type) { 213 methodGen.getInstructionList().append(NOP); 214 } 215 216 /** 217 * Translates a node into a non-synthesized boolean. It does not push a 218 * 0 or a 1 but instead returns branchhandle list to be appended to the 219 * false list. 220 * 221 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateToDesynthesized 222 */ translateToDesynthesized(ClassGenerator classGen, MethodGenerator methodGen, BooleanType type)223 public FlowList translateToDesynthesized(ClassGenerator classGen, 224 MethodGenerator methodGen, 225 BooleanType type) { 226 final InstructionList il = methodGen.getInstructionList(); 227 return new FlowList(il.append(new IFEQ(null))); 228 } 229 230 /** 231 * Expects a node on the stack and pushes a boxed node. Boxed nodes 232 * are represented by an instance of <code>com.sun.org.apache.xalan.internal.xsltc.dom.Node</code>. 233 * 234 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 235 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, ReferenceType type)236 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 237 ReferenceType type) { 238 final ConstantPoolGen cpg = classGen.getConstantPool(); 239 final InstructionList il = methodGen.getInstructionList(); 240 il.append(new NEW(cpg.addClass(RUNTIME_NODE_CLASS))); 241 il.append(DUP_X1); 242 il.append(SWAP); 243 il.append(new PUSH(cpg, _type)); 244 il.append(new INVOKESPECIAL(cpg.addMethodref(RUNTIME_NODE_CLASS, 245 "<init>", "(II)V"))); 246 } 247 248 /** 249 * Translates a node into the Java type denoted by <code>clazz</code>. 250 * Expects a node on the stack and pushes an object of the appropriate 251 * type after coercion. 252 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, Class<?> clazz)253 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 254 Class<?> clazz) { 255 final ConstantPoolGen cpg = classGen.getConstantPool(); 256 final InstructionList il = methodGen.getInstructionList(); 257 258 String className = clazz.getName(); 259 if (className.equals("java.lang.String")) { 260 translateTo(classGen, methodGen, Type.String); 261 return; 262 } 263 264 il.append(methodGen.loadDOM()); 265 il.append(SWAP); // dom ref must be below node index 266 267 if (className.equals("org.w3c.dom.Node") || 268 className.equals("java.lang.Object")) { 269 int index = cpg.addInterfaceMethodref(DOM_INTF, 270 MAKE_NODE, 271 MAKE_NODE_SIG); 272 il.append(new INVOKEINTERFACE(index, 2)); 273 } 274 else if (className.equals("org.w3c.dom.NodeList")) { 275 int index = cpg.addInterfaceMethodref(DOM_INTF, 276 MAKE_NODE_LIST, 277 MAKE_NODE_LIST_SIG); 278 il.append(new INVOKEINTERFACE(index, 2)); 279 } 280 else { 281 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 282 toString(), className); 283 classGen.getParser().reportError(Constants.FATAL, err); 284 } 285 } 286 287 /** 288 * Translates an object of this type to its boxed representation. 289 */ translateBox(ClassGenerator classGen, MethodGenerator methodGen)290 public void translateBox(ClassGenerator classGen, 291 MethodGenerator methodGen) { 292 translateTo(classGen, methodGen, Type.Reference); 293 } 294 295 /** 296 * Translates an object of this type to its unboxed representation. 297 */ translateUnBox(ClassGenerator classGen, MethodGenerator methodGen)298 public void translateUnBox(ClassGenerator classGen, 299 MethodGenerator methodGen) { 300 final ConstantPoolGen cpg = classGen.getConstantPool(); 301 final InstructionList il = methodGen.getInstructionList(); 302 il.append(new CHECKCAST(cpg.addClass(RUNTIME_NODE_CLASS))); 303 il.append(new GETFIELD(cpg.addFieldref(RUNTIME_NODE_CLASS, 304 NODE_FIELD, 305 NODE_FIELD_SIG))); 306 } 307 308 /** 309 * Returns the class name of an internal type's external representation. 310 */ getClassName()311 public String getClassName() { 312 return(RUNTIME_NODE_CLASS); 313 } 314 LOAD(int slot)315 public Instruction LOAD(int slot) { 316 return new ILOAD(slot); 317 } 318 STORE(int slot)319 public Instruction STORE(int slot) { 320 return new ISTORE(slot); 321 } 322 } 323