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