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 6 * or more contributor license agreements. See the NOTICE file 7 * distributed with this work for additional information 8 * regarding copyright ownership. The ASF licenses this file 9 * to you under the Apache License, Version 2.0 (the 10 * "License"); you may not use this file except in compliance 11 * with 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, 16 * software distributed under the License is distributed on an 17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 * KIND, either express or implied. See the License for the 19 * specific language governing permissions and limitations 20 * under the License. 21 */ 22 23package com.sun.org.apache.xpath.internal.compiler; 24 25import com.sun.org.apache.xpath.internal.functions.Function; 26import java.lang.reflect.InvocationTargetException; 27import java.util.HashMap; 28import javax.xml.transform.TransformerException; 29 30/** 31 * The function table for XPath. 32 */ 33public class FunctionTable 34{ 35 36 /** The 'current()' id. */ 37 public static final int FUNC_CURRENT = 0; 38 39 /** The 'last()' id. */ 40 public static final int FUNC_LAST = 1; 41 42 /** The 'position()' id. */ 43 public static final int FUNC_POSITION = 2; 44 45 /** The 'count()' id. */ 46 public static final int FUNC_COUNT = 3; 47 48 /** The 'id()' id. */ 49 public static final int FUNC_ID = 4; 50 51 /** The 'key()' id (XSLT). */ 52 public static final int FUNC_KEY = 5; 53 54 /** The 'local-name()' id. */ 55 public static final int FUNC_LOCAL_PART = 7; 56 57 /** The 'namespace-uri()' id. */ 58 public static final int FUNC_NAMESPACE = 8; 59 60 /** The 'name()' id. */ 61 public static final int FUNC_QNAME = 9; 62 63 /** The 'generate-id()' id. */ 64 public static final int FUNC_GENERATE_ID = 10; 65 66 /** The 'not()' id. */ 67 public static final int FUNC_NOT = 11; 68 69 /** The 'true()' id. */ 70 public static final int FUNC_TRUE = 12; 71 72 /** The 'false()' id. */ 73 public static final int FUNC_FALSE = 13; 74 75 /** The 'boolean()' id. */ 76 public static final int FUNC_BOOLEAN = 14; 77 78 /** The 'number()' id. */ 79 public static final int FUNC_NUMBER = 15; 80 81 /** The 'floor()' id. */ 82 public static final int FUNC_FLOOR = 16; 83 84 /** The 'ceiling()' id. */ 85 public static final int FUNC_CEILING = 17; 86 87 /** The 'round()' id. */ 88 public static final int FUNC_ROUND = 18; 89 90 /** The 'sum()' id. */ 91 public static final int FUNC_SUM = 19; 92 93 /** The 'string()' id. */ 94 public static final int FUNC_STRING = 20; 95 96 /** The 'starts-with()' id. */ 97 public static final int FUNC_STARTS_WITH = 21; 98 99 /** The 'contains()' id. */ 100 public static final int FUNC_CONTAINS = 22; 101 102 /** The 'substring-before()' id. */ 103 public static final int FUNC_SUBSTRING_BEFORE = 23; 104 105 /** The 'substring-after()' id. */ 106 public static final int FUNC_SUBSTRING_AFTER = 24; 107 108 /** The 'normalize-space()' id. */ 109 public static final int FUNC_NORMALIZE_SPACE = 25; 110 111 /** The 'translate()' id. */ 112 public static final int FUNC_TRANSLATE = 26; 113 114 /** The 'concat()' id. */ 115 public static final int FUNC_CONCAT = 27; 116 117 /** The 'substring()' id. */ 118 public static final int FUNC_SUBSTRING = 29; 119 120 /** The 'string-length()' id. */ 121 public static final int FUNC_STRING_LENGTH = 30; 122 123 /** The 'system-property()' id. */ 124 public static final int FUNC_SYSTEM_PROPERTY = 31; 125 126 /** The 'lang()' id. */ 127 public static final int FUNC_LANG = 32; 128 129 /** The 'function-available()' id (XSLT). */ 130 public static final int FUNC_EXT_FUNCTION_AVAILABLE = 33; 131 132 /** The 'element-available()' id (XSLT). */ 133 public static final int FUNC_EXT_ELEM_AVAILABLE = 34; 134 135 /** The 'unparsed-entity-uri()' id (XSLT). */ 136 public static final int FUNC_UNPARSED_ENTITY_URI = 36; 137 138 /** The 'here()' id (XML Signature). */ 139 public static final int FUNC_HERE = 37; 140 141 // Proprietary 142 143 /** The 'document-location()' id (Proprietary). */ 144 public static final int FUNC_DOCLOCATION = 35; 145 146 /** 147 * The function table. 148 */ 149 private static Class m_functions[]; 150 151 /** Table of function name to function ID associations. */ 152 private static final HashMap<String, Integer> m_functionID = new HashMap<>(); 153 154 /** 155 * The function table contains customized functions 156 */ 157 private Class m_functions_customer[] = new Class[NUM_ALLOWABLE_ADDINS]; 158 159 /** 160 * Table of function name to function ID associations for customized functions 161 */ 162 private HashMap<String, Integer> m_functionID_customer = new HashMap<>(); 163 164 /** 165 * Number of built in functions. Be sure to update this as 166 * built-in functions are added. 167 */ 168 private static final int NUM_BUILT_IN_FUNCS = 38; 169 170 /** 171 * Number of built-in functions that may be added. 172 */ 173 private static final int NUM_ALLOWABLE_ADDINS = 30; 174 175 /** 176 * The index to the next free function index. 177 */ 178 private int m_funcNextFreeIndex = NUM_BUILT_IN_FUNCS; 179 180 static 181 { 182 m_functions = new Class[NUM_BUILT_IN_FUNCS]; 183 m_functions[FUNC_CURRENT] = com.sun.org.apache.xpath.internal.functions.FuncCurrent.class; 184 m_functions[FUNC_LAST] = com.sun.org.apache.xpath.internal.functions.FuncLast.class; 185 m_functions[FUNC_POSITION] = com.sun.org.apache.xpath.internal.functions.FuncPosition.class; 186 m_functions[FUNC_COUNT] = com.sun.org.apache.xpath.internal.functions.FuncCount.class; 187 m_functions[FUNC_ID] = com.sun.org.apache.xpath.internal.functions.FuncId.class; 188 // J2SE does not support Xalan interpretive 189 // m_functions[FUNC_KEY] = 190 // com.sun.org.apache.xalan.internal.templates.FuncKey.class; 191 m_functions[FUNC_LOCAL_PART] = 192 com.sun.org.apache.xpath.internal.functions.FuncLocalPart.class; 193 m_functions[FUNC_NAMESPACE] = 194 com.sun.org.apache.xpath.internal.functions.FuncNamespace.class; 195 m_functions[FUNC_QNAME] = com.sun.org.apache.xpath.internal.functions.FuncQname.class; 196 m_functions[FUNC_GENERATE_ID] = 197 com.sun.org.apache.xpath.internal.functions.FuncGenerateId.class; 198 m_functions[FUNC_NOT] = com.sun.org.apache.xpath.internal.functions.FuncNot.class; 199 m_functions[FUNC_TRUE] = com.sun.org.apache.xpath.internal.functions.FuncTrue.class; 200 m_functions[FUNC_FALSE] = com.sun.org.apache.xpath.internal.functions.FuncFalse.class; 201 m_functions[FUNC_BOOLEAN] = com.sun.org.apache.xpath.internal.functions.FuncBoolean.class; 202 m_functions[FUNC_LANG] = com.sun.org.apache.xpath.internal.functions.FuncLang.class; 203 m_functions[FUNC_NUMBER] = com.sun.org.apache.xpath.internal.functions.FuncNumber.class; 204 m_functions[FUNC_FLOOR] = com.sun.org.apache.xpath.internal.functions.FuncFloor.class; 205 m_functions[FUNC_CEILING] = com.sun.org.apache.xpath.internal.functions.FuncCeiling.class; 206 m_functions[FUNC_ROUND] = com.sun.org.apache.xpath.internal.functions.FuncRound.class; 207 m_functions[FUNC_SUM] = com.sun.org.apache.xpath.internal.functions.FuncSum.class; 208 m_functions[FUNC_STRING] = com.sun.org.apache.xpath.internal.functions.FuncString.class; 209 m_functions[FUNC_STARTS_WITH] = 210 com.sun.org.apache.xpath.internal.functions.FuncStartsWith.class; 211 m_functions[FUNC_CONTAINS] = com.sun.org.apache.xpath.internal.functions.FuncContains.class; 212 m_functions[FUNC_SUBSTRING_BEFORE] = 213 com.sun.org.apache.xpath.internal.functions.FuncSubstringBefore.class; 214 m_functions[FUNC_SUBSTRING_AFTER] = 215 com.sun.org.apache.xpath.internal.functions.FuncSubstringAfter.class; 216 m_functions[FUNC_NORMALIZE_SPACE] = 217 com.sun.org.apache.xpath.internal.functions.FuncNormalizeSpace.class; 218 m_functions[FUNC_TRANSLATE] = 219 com.sun.org.apache.xpath.internal.functions.FuncTranslate.class; 220 m_functions[FUNC_CONCAT] = com.sun.org.apache.xpath.internal.functions.FuncConcat.class; 221 m_functions[FUNC_SYSTEM_PROPERTY] = 222 com.sun.org.apache.xpath.internal.functions.FuncSystemProperty.class; 223 m_functions[FUNC_EXT_FUNCTION_AVAILABLE] = 224 com.sun.org.apache.xpath.internal.functions.FuncExtFunctionAvailable.class; 225 m_functions[FUNC_EXT_ELEM_AVAILABLE] = 226 com.sun.org.apache.xpath.internal.functions.FuncExtElementAvailable.class; 227 m_functions[FUNC_SUBSTRING] = 228 com.sun.org.apache.xpath.internal.functions.FuncSubstring.class; 229 m_functions[FUNC_STRING_LENGTH] = 230 com.sun.org.apache.xpath.internal.functions.FuncStringLength.class; 231 m_functions[FUNC_DOCLOCATION] = 232 com.sun.org.apache.xpath.internal.functions.FuncDoclocation.class; 233 m_functions[FUNC_UNPARSED_ENTITY_URI] = 234 com.sun.org.apache.xpath.internal.functions.FuncUnparsedEntityURI.class; 235 m_functions[FUNC_HERE] = 236 com.sun.org.apache.xpath.internal.functions.FuncHere.class; 237 } 238 239 static{ 240 m_functionID.put(Keywords.FUNC_CURRENT_STRING, 241 FunctionTable.FUNC_CURRENT); 242 m_functionID.put(Keywords.FUNC_LAST_STRING, 243 FunctionTable.FUNC_LAST); 244 m_functionID.put(Keywords.FUNC_POSITION_STRING, 245 FunctionTable.FUNC_POSITION); 246 m_functionID.put(Keywords.FUNC_COUNT_STRING, 247 FunctionTable.FUNC_COUNT); 248 m_functionID.put(Keywords.FUNC_ID_STRING, 249 FunctionTable.FUNC_ID); 250 m_functionID.put(Keywords.FUNC_KEY_STRING, 251 FunctionTable.FUNC_KEY); 252 m_functionID.put(Keywords.FUNC_LOCAL_PART_STRING, 253 FunctionTable.FUNC_LOCAL_PART); 254 m_functionID.put(Keywords.FUNC_NAMESPACE_STRING, 255 FunctionTable.FUNC_NAMESPACE); 256 m_functionID.put(Keywords.FUNC_NAME_STRING, 257 FunctionTable.FUNC_QNAME); 258 m_functionID.put(Keywords.FUNC_GENERATE_ID_STRING, 259 FunctionTable.FUNC_GENERATE_ID); 260 m_functionID.put(Keywords.FUNC_NOT_STRING, 261 FunctionTable.FUNC_NOT); 262 m_functionID.put(Keywords.FUNC_TRUE_STRING, 263 FunctionTable.FUNC_TRUE); 264 m_functionID.put(Keywords.FUNC_FALSE_STRING, 265 FunctionTable.FUNC_FALSE); 266 m_functionID.put(Keywords.FUNC_BOOLEAN_STRING, 267 FunctionTable.FUNC_BOOLEAN); 268 m_functionID.put(Keywords.FUNC_LANG_STRING, 269 FunctionTable.FUNC_LANG); 270 m_functionID.put(Keywords.FUNC_NUMBER_STRING, 271 FunctionTable.FUNC_NUMBER); 272 m_functionID.put(Keywords.FUNC_FLOOR_STRING, 273 FunctionTable.FUNC_FLOOR); 274 m_functionID.put(Keywords.FUNC_CEILING_STRING, 275 FunctionTable.FUNC_CEILING); 276 m_functionID.put(Keywords.FUNC_ROUND_STRING, 277 FunctionTable.FUNC_ROUND); 278 m_functionID.put(Keywords.FUNC_SUM_STRING, 279 FunctionTable.FUNC_SUM); 280 m_functionID.put(Keywords.FUNC_STRING_STRING, 281 FunctionTable.FUNC_STRING); 282 m_functionID.put(Keywords.FUNC_STARTS_WITH_STRING, 283 FunctionTable.FUNC_STARTS_WITH); 284 m_functionID.put(Keywords.FUNC_CONTAINS_STRING, 285 FunctionTable.FUNC_CONTAINS); 286 m_functionID.put(Keywords.FUNC_SUBSTRING_BEFORE_STRING, 287 FunctionTable.FUNC_SUBSTRING_BEFORE); 288 m_functionID.put(Keywords.FUNC_SUBSTRING_AFTER_STRING, 289 FunctionTable.FUNC_SUBSTRING_AFTER); 290 m_functionID.put(Keywords.FUNC_NORMALIZE_SPACE_STRING, 291 FunctionTable.FUNC_NORMALIZE_SPACE); 292 m_functionID.put(Keywords.FUNC_TRANSLATE_STRING, 293 FunctionTable.FUNC_TRANSLATE); 294 m_functionID.put(Keywords.FUNC_CONCAT_STRING, 295 FunctionTable.FUNC_CONCAT); 296 m_functionID.put(Keywords.FUNC_SYSTEM_PROPERTY_STRING, 297 FunctionTable.FUNC_SYSTEM_PROPERTY); 298 m_functionID.put(Keywords.FUNC_EXT_FUNCTION_AVAILABLE_STRING, 299 FunctionTable.FUNC_EXT_FUNCTION_AVAILABLE); 300 m_functionID.put(Keywords.FUNC_EXT_ELEM_AVAILABLE_STRING, 301 FunctionTable.FUNC_EXT_ELEM_AVAILABLE); 302 m_functionID.put(Keywords.FUNC_SUBSTRING_STRING, 303 FunctionTable.FUNC_SUBSTRING); 304 m_functionID.put(Keywords.FUNC_STRING_LENGTH_STRING, 305 FunctionTable.FUNC_STRING_LENGTH); 306 m_functionID.put(Keywords.FUNC_UNPARSED_ENTITY_URI_STRING, 307 FunctionTable.FUNC_UNPARSED_ENTITY_URI); 308 m_functionID.put(Keywords.FUNC_DOCLOCATION_STRING, 309 FunctionTable.FUNC_DOCLOCATION); 310 m_functionID.put(Keywords.FUNC_HERE_STRING, 311 FunctionTable.FUNC_HERE); 312 } 313 314 public FunctionTable(){ 315 } 316 317 /** 318 * Return the name of the a function in the static table. Needed to avoid 319 * making the table publicly available. 320 */ 321 String getFunctionName(int funcID) { 322 if (funcID < NUM_BUILT_IN_FUNCS) return m_functions[funcID].getName(); 323 else return m_functions_customer[funcID - NUM_BUILT_IN_FUNCS].getName(); 324 } 325 326 /** 327 * Obtain a new Function object from a function ID. 328 * 329 * @param which The function ID, which may correspond to one of the FUNC_XXX 330 * values found in {@link com.sun.org.apache.xpath.internal.compiler.FunctionTable}, but may 331 * be a value installed by an external module. 332 * 333 * @return a a new Function instance. 334 * 335 * @throws javax.xml.transform.TransformerException if ClassNotFoundException, 336 * IllegalAccessException, or InstantiationException is thrown. 337 */ 338 Function getFunction(int which) 339 throws javax.xml.transform.TransformerException 340 { 341 try{ 342 if (which < NUM_BUILT_IN_FUNCS) { 343 return (Function) m_functions[which].getConstructor().newInstance(); 344 } else { 345 Class<?> c = m_functions_customer[which-NUM_BUILT_IN_FUNCS]; 346 return (Function) c.getConstructor().newInstance(); 347 } 348 }catch (InstantiationException | IllegalAccessException | SecurityException | 349 IllegalArgumentException | InvocationTargetException | NoSuchMethodException ex){ 350 throw new TransformerException(ex.getMessage()); 351 } 352 } 353 354 /** 355 * Obtain a function ID from a given function name 356 * @param key the function name in a java.lang.String format. 357 * @return a function ID, which may correspond to one of the FUNC_XXX values 358 * found in {@link com.sun.org.apache.xpath.internal.compiler.FunctionTable}, but may be a 359 * value installed by an external module. 360 */ 361 Integer getFunctionID(String key){ 362 Integer id = m_functionID_customer.get(key); 363 if (null == id) id = m_functionID.get(key); 364 return id; 365 } 366 367 /** 368 * Install a built-in function. 369 * @param name The unqualified name of the function, must not be null 370 * @param func A Implementation of an XPath Function object. 371 * @return the position of the function in the internal index. 372 */ 373 public int installFunction(String name, Class func) 374 { 375 376 int funcIndex; 377 Integer funcIndexObj = getFunctionID(name); 378 379 if (func != null && !Function.class.isAssignableFrom(func)) { 380 throw new ClassCastException(func.getName() 381 + " cannot be cast to " 382 + Function.class.getName()); 383 } 384 385 if (null != funcIndexObj) 386 { 387 funcIndex = funcIndexObj; 388 389 if (funcIndex < NUM_BUILT_IN_FUNCS){ 390 funcIndex = m_funcNextFreeIndex++; 391 m_functionID_customer.put(name, funcIndex); 392 } 393 m_functions_customer[funcIndex - NUM_BUILT_IN_FUNCS] = func; 394 } 395 else 396 { 397 funcIndex = m_funcNextFreeIndex++; 398 m_functions_customer[funcIndex-NUM_BUILT_IN_FUNCS] = func; 399 m_functionID_customer.put(name, funcIndex); 400 } 401 return funcIndex; 402 } 403 404 /** 405 * Tell if a built-in, non-namespaced function is available. 406 * 407 * @param methName The local name of the function. 408 * 409 * @return True if the function can be executed. 410 */ 411 public boolean functionAvailable(String methName) 412 { 413 Integer tblEntry = m_functionID.get(methName); 414 if (null != tblEntry) return true; 415 else{ 416 tblEntry = m_functionID_customer.get(methName); 417 return (null != tblEntry); 418 } 419 } 420} 421