1 16 19 20 package org.apache.xalan.xsltc.compiler; 21 22 import java.lang.reflect.Constructor ; 23 import java.lang.reflect.Method ; 24 import java.lang.reflect.Modifier ; 25 import java.util.Enumeration ; 26 import java.util.Hashtable ; 27 import java.util.Vector ; 28 29 import org.apache.bcel.generic.ConstantPoolGen; 30 import org.apache.bcel.generic.IFEQ; 31 import org.apache.bcel.generic.INVOKEINTERFACE; 32 import org.apache.bcel.generic.INVOKESPECIAL; 33 import org.apache.bcel.generic.INVOKESTATIC; 34 import org.apache.bcel.generic.INVOKEVIRTUAL; 35 import org.apache.bcel.generic.InstructionConstants; 36 import org.apache.bcel.generic.InstructionList; 37 import org.apache.bcel.generic.InvokeInstruction; 38 import org.apache.bcel.generic.NEW; 39 import org.apache.bcel.generic.PUSH; 40 import org.apache.bcel.generic.LocalVariableGen; 41 import org.apache.bcel.generic.ASTORE; 42 import org.apache.bcel.generic.ANEWARRAY; 43 import org.apache.bcel.generic.ALOAD; 44 import org.apache.bcel.generic.ACONST_NULL; 45 46 47 import org.apache.xalan.xsltc.compiler.util.BooleanType; 48 import org.apache.xalan.xsltc.compiler.util.ClassGenerator; 49 import org.apache.xalan.xsltc.compiler.util.ErrorMsg; 50 import org.apache.xalan.xsltc.compiler.util.IntType; 51 import org.apache.xalan.xsltc.compiler.util.MethodGenerator; 52 import org.apache.xalan.xsltc.compiler.util.MethodType; 53 import org.apache.xalan.xsltc.compiler.util.MultiHashtable; 54 import org.apache.xalan.xsltc.compiler.util.ObjectType; 55 import org.apache.xalan.xsltc.compiler.util.ReferenceType; 56 import org.apache.xalan.xsltc.compiler.util.Type; 57 import org.apache.xalan.xsltc.compiler.util.TypeCheckError; 58 59 66 class FunctionCall extends Expression { 67 68 private QName _fname; 70 private final Vector _arguments; 72 private final static Vector EMPTY_ARG_LIST = new Vector (0); 74 75 protected final static String EXT_XSLTC = 77 TRANSLET_URI; 78 79 protected final static String JAVA_EXT_XSLTC = 80 EXT_XSLTC + "/java"; 81 82 protected final static String EXT_XALAN = 83 "http://xml.apache.org/xalan"; 84 85 protected final static String JAVA_EXT_XALAN = 86 "http://xml.apache.org/xalan/java"; 87 88 protected final static String JAVA_EXT_XALAN_OLD = 89 "http://xml.apache.org/xslt/java"; 90 91 protected final static String EXSLT_COMMON = 92 "http://exslt.org/common"; 93 94 protected final static String EXSLT_MATH = 95 "http://exslt.org/math"; 96 97 protected final static String EXSLT_SETS = 98 "http://exslt.org/sets"; 99 100 protected final static String EXSLT_DATETIME = 101 "http://exslt.org/dates-and-times"; 102 103 protected final static String EXSLT_STRINGS = 104 "http://exslt.org/strings"; 105 106 protected final static int NAMESPACE_FORMAT_JAVA = 0; 108 protected final static int NAMESPACE_FORMAT_CLASS = 1; 109 protected final static int NAMESPACE_FORMAT_PACKAGE = 2; 110 protected final static int NAMESPACE_FORMAT_CLASS_OR_PACKAGE = 3; 111 112 private int _namespace_format = NAMESPACE_FORMAT_JAVA; 114 115 118 Expression _thisArgument = null; 119 120 private String _className; 122 private Class _clazz; 123 private Method _chosenMethod; 124 private Constructor _chosenConstructor; 125 private MethodType _chosenMethodType; 126 127 private boolean unresolvedExternal; 129 130 private boolean _isExtConstructor = false; 132 133 private boolean _isStatic = false; 135 136 private boolean resolveDynamic = false; 138 139 private static final MultiHashtable _internal2Java = new MultiHashtable(); 141 142 private static final Hashtable _java2Internal = new Hashtable (); 144 145 private static final Hashtable _extensionNamespaceTable = new Hashtable (); 147 148 private static final Hashtable _extensionFunctionTable = new Hashtable (); 150 155 static class JavaType { 156 public Class type; 157 public int distance; 158 159 public JavaType(Class type, int distance){ 160 this.type = type; 161 this.distance = distance; 162 } 163 public boolean equals(Object query){ 164 return query.equals(type); 165 } 166 } 167 168 174 static { 175 try { 176 final Class nodeClass = Class.forName("org.w3c.dom.Node"); 177 final Class nodeListClass = Class.forName("org.w3c.dom.NodeList"); 178 179 181 _internal2Java.put(Type.Boolean, new JavaType(Boolean.TYPE, 0)); 183 _internal2Java.put(Type.Boolean, new JavaType(Boolean .class, 1)); 184 _internal2Java.put(Type.Boolean, new JavaType(Object .class, 2)); 185 186 _internal2Java.put(Type.Real, new JavaType(Double.TYPE, 0)); 189 _internal2Java.put(Type.Real, new JavaType(Double .class, 1)); 190 _internal2Java.put(Type.Real, new JavaType(Float.TYPE, 2)); 191 _internal2Java.put(Type.Real, new JavaType(Long.TYPE, 3)); 192 _internal2Java.put(Type.Real, new JavaType(Integer.TYPE, 4)); 193 _internal2Java.put(Type.Real, new JavaType(Short.TYPE, 5)); 194 _internal2Java.put(Type.Real, new JavaType(Byte.TYPE, 6)); 195 _internal2Java.put(Type.Real, new JavaType(Character.TYPE, 7)); 196 _internal2Java.put(Type.Real, new JavaType(Object .class, 8)); 197 198 _internal2Java.put(Type.Int, new JavaType(Double.TYPE, 0)); 200 _internal2Java.put(Type.Int, new JavaType(Double .class, 1)); 201 _internal2Java.put(Type.Int, new JavaType(Float.TYPE, 2)); 202 _internal2Java.put(Type.Int, new JavaType(Long.TYPE, 3)); 203 _internal2Java.put(Type.Int, new JavaType(Integer.TYPE, 4)); 204 _internal2Java.put(Type.Int, new JavaType(Short.TYPE, 5)); 205 _internal2Java.put(Type.Int, new JavaType(Byte.TYPE, 6)); 206 _internal2Java.put(Type.Int, new JavaType(Character.TYPE, 7)); 207 _internal2Java.put(Type.Int, new JavaType(Object .class, 8)); 208 209 _internal2Java.put(Type.String, new JavaType(String .class, 0)); 211 _internal2Java.put(Type.String, new JavaType(Object .class, 1)); 212 213 _internal2Java.put(Type.NodeSet, new JavaType(nodeListClass, 0)); 215 _internal2Java.put(Type.NodeSet, new JavaType(nodeClass, 1)); 216 _internal2Java.put(Type.NodeSet, new JavaType(Object .class, 2)); 217 _internal2Java.put(Type.NodeSet, new JavaType(String .class, 3)); 218 219 _internal2Java.put(Type.Node, new JavaType(nodeListClass, 0)); 221 _internal2Java.put(Type.Node, new JavaType(nodeClass, 1)); 222 _internal2Java.put(Type.Node, new JavaType(Object .class, 2)); 223 _internal2Java.put(Type.Node, new JavaType(String .class, 3)); 224 225 _internal2Java.put(Type.ResultTree, new JavaType(nodeListClass, 0)); 227 _internal2Java.put(Type.ResultTree, new JavaType(nodeClass, 1)); 228 _internal2Java.put(Type.ResultTree, new JavaType(Object .class, 2)); 229 _internal2Java.put(Type.ResultTree, new JavaType(String .class, 3)); 230 231 _internal2Java.put(Type.Reference, new JavaType(Object .class, 0)); 232 233 _java2Internal.put(Boolean.TYPE, Type.Boolean); 235 _java2Internal.put(Void.TYPE, Type.Void); 236 _java2Internal.put(Character.TYPE, Type.Real); 237 _java2Internal.put(Byte.TYPE, Type.Real); 238 _java2Internal.put(Short.TYPE, Type.Real); 239 _java2Internal.put(Integer.TYPE, Type.Real); 240 _java2Internal.put(Long.TYPE, Type.Real); 241 _java2Internal.put(Float.TYPE, Type.Real); 242 _java2Internal.put(Double.TYPE, Type.Real); 243 244 _java2Internal.put(String .class, Type.String); 245 246 _java2Internal.put(Object .class, Type.Reference); 247 248 _java2Internal.put(nodeListClass, Type.NodeSet); 250 _java2Internal.put(nodeClass, Type.NodeSet); 251 252 _extensionNamespaceTable.put(EXT_XALAN, "org.apache.xalan.lib.Extensions"); 254 _extensionNamespaceTable.put(EXSLT_COMMON, "org.apache.xalan.lib.ExsltCommon"); 255 _extensionNamespaceTable.put(EXSLT_MATH, "org.apache.xalan.lib.ExsltMath"); 256 _extensionNamespaceTable.put(EXSLT_SETS, "org.apache.xalan.lib.ExsltSets"); 257 _extensionNamespaceTable.put(EXSLT_DATETIME, "org.apache.xalan.lib.ExsltDatetime"); 258 _extensionNamespaceTable.put(EXSLT_STRINGS, "org.apache.xalan.lib.ExsltStrings"); 259 260 _extensionFunctionTable.put(EXSLT_COMMON + ":nodeSet", "nodeset"); 262 _extensionFunctionTable.put(EXSLT_COMMON + ":objectType", "objectType"); 263 _extensionFunctionTable.put(EXT_XALAN + ":nodeset", "nodeset"); 264 } 265 catch (ClassNotFoundException e) { 266 System.err.println(e); 267 } 268 } 269 270 public FunctionCall(QName fname, Vector arguments) { 271 _fname = fname; 272 _arguments = arguments; 273 _type = null; 274 } 275 276 public FunctionCall(QName fname) { 277 this(fname, EMPTY_ARG_LIST); 278 } 279 280 public String getName() { 281 return(_fname.toString()); 282 } 283 284 public void setParser(Parser parser) { 285 super.setParser(parser); 286 if (_arguments != null) { 287 final int n = _arguments.size(); 288 for (int i = 0; i < n; i++) { 289 final Expression exp = (Expression)_arguments.elementAt(i); 290 exp.setParser(parser); 291 exp.setParent(this); 292 } 293 } 294 } 295 296 public String getClassNameFromUri(String uri) 297 { 298 String className = (String )_extensionNamespaceTable.get(uri); 299 300 if (className != null) 301 return className; 302 else { 303 if (uri.startsWith(JAVA_EXT_XSLTC)) { 304 int length = JAVA_EXT_XSLTC.length() + 1; 305 return (uri.length() > length) ? uri.substring(length) : EMPTYSTRING; 306 } 307 else if (uri.startsWith(JAVA_EXT_XALAN)) { 308 int length = JAVA_EXT_XALAN.length() + 1; 309 return (uri.length() > length) ? uri.substring(length) : EMPTYSTRING; 310 } 311 else if (uri.startsWith(JAVA_EXT_XALAN_OLD)) { 312 int length = JAVA_EXT_XALAN_OLD.length() + 1; 313 return (uri.length() > length) ? uri.substring(length) : EMPTYSTRING; 314 } 315 else { 316 int index = uri.lastIndexOf('/'); 317 return (index > 0) ? uri.substring(index+1) : uri; 318 } 319 } 320 } 321 322 326 public Type typeCheck(SymbolTable stable) 327 throws TypeCheckError 328 { 329 if (_type != null) return _type; 330 331 final String namespace = _fname.getNamespace(); 332 String local = _fname.getLocalPart(); 333 334 if (isExtension()) { 335 _fname = new QName(null, null, local); 336 return typeCheckStandard(stable); 337 } 338 else if (isStandard()) { 339 return typeCheckStandard(stable); 340 } 341 else { 343 try { 344 _className = getClassNameFromUri(namespace); 345 346 final int pos = local.lastIndexOf('.'); 347 if (pos > 0) { 348 _isStatic = true; 349 if (_className != null && _className.length() > 0) { 350 _namespace_format = NAMESPACE_FORMAT_PACKAGE; 351 _className = _className + "." + local.substring(0, pos); 352 } 353 else { 354 _namespace_format = NAMESPACE_FORMAT_JAVA; 355 _className = local.substring(0, pos); 356 } 357 358 _fname = new QName(namespace, null, local.substring(pos + 1)); 359 } 360 else { 361 if (_className != null && _className.length() > 0) { 362 try { 363 _clazz = ObjectFactory.findProviderClass( 364 _className, ObjectFactory.findClassLoader(), true); 365 _namespace_format = NAMESPACE_FORMAT_CLASS; 366 } 367 catch (ClassNotFoundException e) { 368 _namespace_format = NAMESPACE_FORMAT_PACKAGE; 369 } 370 } 371 else 372 _namespace_format = NAMESPACE_FORMAT_JAVA; 373 374 if (local.indexOf('-') > 0) { 375 local = replaceDash(local); 376 } 377 378 String extFunction = (String )_extensionFunctionTable.get(namespace + ":" + local); 379 if (extFunction != null) { 380 _fname = new QName(null, null, extFunction); 381 return typeCheckStandard(stable); 382 } 383 else 384 _fname = new QName(namespace, null, local); 385 } 386 387 return typeCheckExternal(stable); 388 } 389 catch (TypeCheckError e) { 390 ErrorMsg errorMsg = e.getErrorMsg(); 391 if (errorMsg == null) { 392 final String name = _fname.getLocalPart(); 393 errorMsg = new ErrorMsg(ErrorMsg.METHOD_NOT_FOUND_ERR, name); 394 } 395 getParser().reportError(ERROR, errorMsg); 396 return _type = Type.Void; 397 } 398 } 399 } 400 401 406 public Type typeCheckStandard(SymbolTable stable) throws TypeCheckError { 407 _fname.clearNamespace(); 409 final int n = _arguments.size(); 410 final Vector argsType = typeCheckArgs(stable); 411 final MethodType args = new MethodType(Type.Void, argsType); 412 final MethodType ptype = 413 lookupPrimop(stable, _fname.getLocalPart(), args); 414 415 if (ptype != null) { 416 for (int i = 0; i < n; i++) { 417 final Type argType = (Type) ptype.argsType().elementAt(i); 418 final Expression exp = (Expression)_arguments.elementAt(i); 419 if (!argType.identicalTo(exp.getType())) { 420 try { 421 _arguments.setElementAt(new CastExpr(exp, argType), i); 422 } 423 catch (TypeCheckError e) { 424 throw new TypeCheckError(this); } 426 } 427 } 428 _chosenMethodType = ptype; 429 return _type = ptype.resultType(); 430 } 431 throw new TypeCheckError(this); 432 } 433 434 435 436 public Type typeCheckConstructor(SymbolTable stable) throws TypeCheckError{ 437 final Vector constructors = findConstructors(); 438 if (constructors == null) { 439 throw new TypeCheckError(ErrorMsg.CONSTRUCTOR_NOT_FOUND, 441 _className); 442 443 } 444 445 final int nConstructors = constructors.size(); 446 final int nArgs = _arguments.size(); 447 final Vector argsType = typeCheckArgs(stable); 448 449 int bestConstrDistance = Integer.MAX_VALUE; 451 _type = null; for (int j, i = 0; i < nConstructors; i++) { 453 final Constructor constructor = 455 (Constructor )constructors.elementAt(i); 456 final Class [] paramTypes = constructor.getParameterTypes(); 457 458 Class extType = null; 459 int currConstrDistance = 0; 460 for (j = 0; j < nArgs; j++) { 461 extType = paramTypes[j]; 463 final Type intType = (Type)argsType.elementAt(j); 464 Object match = _internal2Java.maps(intType, extType); 465 if (match != null) { 466 currConstrDistance += ((JavaType)match).distance; 467 } 468 else if (intType instanceof ObjectType) { 469 ObjectType objectType = (ObjectType)intType; 470 if (objectType.getJavaClass() == extType) 471 continue; 472 else if (extType.isAssignableFrom(objectType.getJavaClass())) 473 currConstrDistance += 1; 474 else { 475 currConstrDistance = Integer.MAX_VALUE; 476 break; 477 } 478 } 479 else { 480 currConstrDistance = Integer.MAX_VALUE; 482 break; 483 } 484 } 485 486 if (j == nArgs && currConstrDistance < bestConstrDistance ) { 487 _chosenConstructor = constructor; 488 _isExtConstructor = true; 489 bestConstrDistance = currConstrDistance; 490 491 _type = (_clazz != null) ? Type.newObjectType(_clazz) 492 : Type.newObjectType(_className); 493 } 494 } 495 496 if (_type != null) { 497 return _type; 498 } 499 else{ 500 resolveDynamic = true; 501 } 502 503 return _type = (_clazz != null) ? Type.newObjectType(_clazz) 504 : Type.newObjectType(_className); 505 } 506 507 508 515 public Type typeCheckExternal(SymbolTable stable) throws TypeCheckError { 516 int nArgs = _arguments.size(); 517 final String name = _fname.getLocalPart(); 518 519 if (_fname.getLocalPart().equals("new")) { 521 return typeCheckConstructor(stable); 522 } 523 else { 525 boolean hasThisArgument = false; 526 527 if (nArgs == 0) 528 _isStatic = true; 529 530 if (!_isStatic) { 531 if (_namespace_format == NAMESPACE_FORMAT_JAVA 532 || _namespace_format == NAMESPACE_FORMAT_PACKAGE) 533 hasThisArgument = true; 534 535 Expression firstArg = (Expression)_arguments.elementAt(0); 536 Type firstArgType = (Type)firstArg.typeCheck(stable); 537 538 if (_namespace_format == NAMESPACE_FORMAT_CLASS 539 && firstArgType instanceof ObjectType 540 && _clazz != null 541 && _clazz.isAssignableFrom(((ObjectType)firstArgType).getJavaClass())) 542 hasThisArgument = true; 543 else if(firstArgType instanceof ReferenceType){ 544 resolveDynamic = true; 545 typeCheckArgs(stable); 546 return Type.String; 547 } 548 549 if (hasThisArgument) { 550 _thisArgument = (Expression) _arguments.elementAt(0); 551 _arguments.remove(0); nArgs--; 552 if (firstArgType instanceof ObjectType) { 553 _className = ((ObjectType) firstArgType).getJavaClassName(); 554 } 555 else 556 throw new TypeCheckError(ErrorMsg.NO_JAVA_FUNCT_THIS_REF, name); 557 } 558 } 559 else if (_className.length() == 0) { 560 566 final Parser parser = getParser(); 567 if (parser != null) { 568 reportWarning(this, parser, ErrorMsg.FUNCTION_RESOLVE_ERR, 569 _fname.toString()); 570 } 571 unresolvedExternal = true; 572 return _type = Type.Int; } 574 } 575 576 final Vector methods = findMethods(); 577 578 if (methods == null) { 579 throw new TypeCheckError(ErrorMsg.METHOD_NOT_FOUND_ERR, _className + "." + name); 581 } 582 583 Class extType = null; 584 final int nMethods = methods.size(); 585 final Vector argsType = typeCheckArgs(stable); 586 587 int bestMethodDistance = Integer.MAX_VALUE; 589 _type = null; for (int j, i = 0; i < nMethods; i++) { 591 final Method method = (Method )methods.elementAt(i); 593 final Class [] paramTypes = method.getParameterTypes(); 594 595 int currMethodDistance = 0; 596 for (j = 0; j < nArgs; j++) { 597 extType = paramTypes[j]; 599 final Type intType = (Type)argsType.elementAt(j); 600 Object match = _internal2Java.maps(intType, extType); 601 if (match != null) { 602 currMethodDistance += ((JavaType)match).distance; 603 } 604 else { 605 if (intType instanceof ReferenceType) { 610 currMethodDistance += 1; 611 } 612 else if (intType instanceof ObjectType) { 613 ObjectType object = (ObjectType)intType; 614 if (extType.getName().equals(object.getJavaClassName())) 615 currMethodDistance += 0; 616 else if (extType.isAssignableFrom(object.getJavaClass())) 617 currMethodDistance += 1; 618 else { 619 currMethodDistance = Integer.MAX_VALUE; 620 break; 621 } 622 } 623 else { 624 currMethodDistance = Integer.MAX_VALUE; 625 break; 626 } 627 } 628 } 629 630 if (j == nArgs) { 631 extType = method.getReturnType(); 633 634 _type = (Type) _java2Internal.get(extType); 635 if (_type == null) { 636 _type = Type.newObjectType(extType); 637 } 638 639 if (_type != null && currMethodDistance < bestMethodDistance) { 641 _chosenMethod = method; 642 bestMethodDistance = currMethodDistance; 643 } 644 } 645 } 646 647 if (_chosenMethod != null && _thisArgument == null && 650 !Modifier.isStatic(_chosenMethod.getModifiers())) { 651 throw new TypeCheckError(ErrorMsg.NO_JAVA_FUNCT_THIS_REF, getMethodSignature(argsType)); 652 } 653 654 if (_type != null) { 655 if (_type == Type.NodeSet) { 656 getXSLTC().setMultiDocument(true); 657 } 658 return _type; 659 } 660 661 throw new TypeCheckError(ErrorMsg.ARGUMENT_CONVERSION_ERR, getMethodSignature(argsType)); 662 } 663 664 667 public Vector typeCheckArgs(SymbolTable stable) throws TypeCheckError { 668 final Vector result = new Vector (); 669 final Enumeration e = _arguments.elements(); 670 while (e.hasMoreElements()) { 671 final Expression exp = (Expression)e.nextElement(); 672 result.addElement(exp.typeCheck(stable)); 673 } 674 return result; 675 } 676 677 protected final Expression argument(int i) { 678 return (Expression)_arguments.elementAt(i); 679 } 680 681 protected final Expression argument() { 682 return argument(0); 683 } 684 685 protected final int argumentCount() { 686 return _arguments.size(); 687 } 688 689 protected final void setArgument(int i, Expression exp) { 690 _arguments.setElementAt(exp, i); 691 } 692 693 697 public void translateDesynthesized(ClassGenerator classGen, 698 MethodGenerator methodGen) 699 { 700 Type type = Type.Boolean; 701 if (_chosenMethodType != null) 702 type = _chosenMethodType.resultType(); 703 704 final InstructionList il = methodGen.getInstructionList(); 705 translate(classGen, methodGen); 706 707 if ((type instanceof BooleanType) || (type instanceof IntType)) { 708 _falseList.add(il.append(new IFEQ(null))); 709 } 710 } 711 712 713 717 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 718 final int n = argumentCount(); 719 final ConstantPoolGen cpg = classGen.getConstantPool(); 720 final InstructionList il = methodGen.getInstructionList(); 721 int index; 722 723 if (isStandard() || isExtension()) { 725 for (int i = 0; i < n; i++) { 726 final Expression exp = argument(i); 727 exp.translate(classGen, methodGen); 728 exp.startIterator(classGen, methodGen); 729 } 730 731 final String name = _fname.toString().replace('-', '_') + "F"; 733 String args = Constants.EMPTYSTRING; 734 735 if (name.equals("sumF")) { 737 args = DOM_INTF_SIG; 738 il.append(methodGen.loadDOM()); 739 } 740 else if (name.equals("normalize_spaceF")) { 741 if (_chosenMethodType.toSignature(args). 742 equals("()Ljava/lang/String;")) { 743 args = "I"+DOM_INTF_SIG; 744 il.append(methodGen.loadContextNode()); 745 il.append(methodGen.loadDOM()); 746 } 747 } 748 749 index = cpg.addMethodref(BASIS_LIBRARY_CLASS, name, 751 _chosenMethodType.toSignature(args)); 752 il.append(new INVOKESTATIC(index)); 753 } 754 else if (unresolvedExternal) { 757 index = cpg.addMethodref(BASIS_LIBRARY_CLASS, 758 "unresolved_externalF", 759 "(Ljava/lang/String;)V"); 760 il.append(new PUSH(cpg, _fname.toString())); 761 il.append(new INVOKESTATIC(index)); 762 } 763 else if (_isExtConstructor) { 764 final String clazz = 765 _chosenConstructor.getDeclaringClass().getName(); 766 Class [] paramTypes = _chosenConstructor.getParameterTypes(); 767 768 il.append(new NEW(cpg.addClass(_className))); 769 il.append(InstructionConstants.DUP); 770 771 for (int i = 0; i < n; i++) { 772 final Expression exp = argument(i); 773 exp.translate(classGen, methodGen); 774 exp.startIterator(classGen, methodGen); 776 exp.getType().translateTo(classGen, methodGen, paramTypes[i]); 777 } 778 779 final StringBuffer buffer = new StringBuffer (); 780 buffer.append('('); 781 for (int i = 0; i < paramTypes.length; i++) { 782 buffer.append(getSignature(paramTypes[i])); 783 } 784 buffer.append(')'); 785 buffer.append("V"); 786 787 index = cpg.addMethodref(clazz, 788 "<init>", 789 buffer.toString()); 790 il.append(new INVOKESPECIAL(index)); 791 792 (Type.Object).translateFrom(classGen, methodGen, 794 _chosenConstructor.getDeclaringClass()); 795 796 } 797 else if(resolveDynamic) { 798 799 final LocalVariableGen _local = methodGen.addLocalVariable2("objects", 800 org.apache.bcel.generic.Type.OBJECT, il.getEnd()); 801 802 il.append(new PUSH(cpg, n + 1)); 804 il.append(new ANEWARRAY(cpg.addClass(OBJECT_CLASS))); 805 806 il.append(DUP); 808 if (_thisArgument != null) { 809 il.append(new PUSH(cpg, 0)); 810 _thisArgument.translate(classGen, methodGen); 811 } 812 else { 814 il.append(new PUSH(cpg, 0)); 815 il.append(ACONST_NULL); 816 } 817 il.append(AASTORE); 818 819 for (int i = 0; i < n; i++) { 821 il.append(DUP); 822 il.append(new PUSH(cpg, i + 1)); 823 Expression exp = argument(i); 824 exp.translate(classGen, methodGen); 825 exp.startIterator(classGen, methodGen); 826 exp.getType().translateTo(classGen, methodGen, Type.Reference); 827 il.append(AASTORE); 828 } 829 il.append(new ASTORE(_local.getIndex())); 830 831 String methodName = null; 833 if (_chosenMethod != null) 834 methodName = _chosenMethod.getName(); 835 else 836 methodName = _fname.getLocalPart(); 837 838 il.append(new PUSH(cpg, _className)); 839 il.append(new PUSH(cpg, methodName)); 840 il.append(new ALOAD(_local.getIndex())); 841 842 index = cpg.addMethodref(CALL_FUNCTION_CLASS, INVOKE_METHOD, 843 "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;"); 844 il.append(new INVOKESTATIC(index)); 845 846 } 847 else { 849 final String clazz = _chosenMethod.getDeclaringClass().getName(); 850 Class [] paramTypes = _chosenMethod.getParameterTypes(); 851 852 if (_thisArgument != null) { 854 _thisArgument.translate(classGen, methodGen); 855 } 856 857 for (int i = 0; i < n; i++) { 858 final Expression exp = argument(i); 859 exp.translate(classGen, methodGen); 860 exp.startIterator(classGen, methodGen); 862 exp.getType().translateTo(classGen, methodGen, paramTypes[i]); 863 } 864 865 final StringBuffer buffer = new StringBuffer (); 866 buffer.append('('); 867 for (int i = 0; i < paramTypes.length; i++) { 868 buffer.append(getSignature(paramTypes[i])); 869 } 870 buffer.append(')'); 871 buffer.append(getSignature(_chosenMethod.getReturnType())); 872 873 if (_thisArgument != null && _clazz.isInterface()) { 874 index = cpg.addInterfaceMethodref(clazz, 875 _fname.getLocalPart(), 876 buffer.toString()); 877 il.append(new INVOKEINTERFACE(index, n+1)); 878 } 879 else { 880 index = cpg.addMethodref(clazz, 881 _fname.getLocalPart(), 882 buffer.toString()); 883 il.append(_thisArgument != null ? (InvokeInstruction) new INVOKEVIRTUAL(index) : 884 (InvokeInstruction) new INVOKESTATIC(index)); 885 } 886 887 _type.translateFrom(classGen, methodGen, 889 _chosenMethod.getReturnType()); 890 } 891 } 892 893 public String toString() { 894 return "funcall(" + _fname + ", " + _arguments + ')'; 895 } 896 897 public boolean isStandard() { 898 final String namespace = _fname.getNamespace(); 899 return (namespace == null) || (namespace.equals(Constants.EMPTYSTRING)); 900 } 901 902 public boolean isExtension() { 903 final String namespace = _fname.getNamespace(); 904 return (namespace != null) && (namespace.equals(EXT_XSLTC)); 905 } 906 907 912 private Vector findMethods() { 913 914 Vector result = null; 915 final String namespace = _fname.getNamespace(); 916 917 if (_className != null && _className.length() > 0) { 918 final int nArgs = _arguments.size(); 919 try { 920 if (_clazz == null) { 921 _clazz = ObjectFactory.findProviderClass( 922 _className, ObjectFactory.findClassLoader(), true); 923 924 if (_clazz == null) { 925 final ErrorMsg msg = 926 new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, _className); 927 getParser().reportError(Constants.ERROR, msg); 928 } 929 } 930 931 final String methodName = _fname.getLocalPart(); 932 final Method [] methods = _clazz.getMethods(); 933 934 for (int i = 0; i < methods.length; i++) { 935 final int mods = methods[i].getModifiers(); 936 if (Modifier.isPublic(mods) 938 && methods[i].getName().equals(methodName) 939 && methods[i].getParameterTypes().length == nArgs) 940 { 941 if (result == null) { 942 result = new Vector (); 943 } 944 result.addElement(methods[i]); 945 } 946 } 947 } 948 catch (ClassNotFoundException e) { 949 final ErrorMsg msg = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, _className); 950 getParser().reportError(Constants.ERROR, msg); 951 } 952 } 953 return result; 954 } 955 956 961 private Vector findConstructors() { 962 Vector result = null; 963 final String namespace = _fname.getNamespace(); 964 965 final int nArgs = _arguments.size(); 966 try { 967 if (_clazz == null) { 968 _clazz = ObjectFactory.findProviderClass( 969 _className, ObjectFactory.findClassLoader(), true); 970 971 if (_clazz == null) { 972 final ErrorMsg msg = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, _className); 973 getParser().reportError(Constants.ERROR, msg); 974 } 975 } 976 977 final Constructor [] constructors = _clazz.getConstructors(); 978 979 for (int i = 0; i < constructors.length; i++) { 980 final int mods = constructors[i].getModifiers(); 981 if (Modifier.isPublic(mods) && 983 constructors[i].getParameterTypes().length == nArgs) 984 { 985 if (result == null) { 986 result = new Vector (); 987 } 988 result.addElement(constructors[i]); 989 } 990 } 991 } 992 catch (ClassNotFoundException e) { 993 final ErrorMsg msg = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, _className); 994 getParser().reportError(Constants.ERROR, msg); 995 } 996 997 return result; 998 } 999 1000 1001 1004 static final String getSignature(Class clazz) { 1005 if (clazz.isArray()) { 1006 final StringBuffer sb = new StringBuffer (); 1007 Class cl = clazz; 1008 while (cl.isArray()) { 1009 sb.append("["); 1010 cl = cl.getComponentType(); 1011 } 1012 sb.append(getSignature(cl)); 1013 return sb.toString(); 1014 } 1015 else if (clazz.isPrimitive()) { 1016 if (clazz == Integer.TYPE) { 1017 return "I"; 1018 } 1019 else if (clazz == Byte.TYPE) { 1020 return "B"; 1021 } 1022 else if (clazz == Long.TYPE) { 1023 return "J"; 1024 } 1025 else if (clazz == Float.TYPE) { 1026 return "F"; 1027 } 1028 else if (clazz == Double.TYPE) { 1029 return "D"; 1030 } 1031 else if (clazz == Short.TYPE) { 1032 return "S"; 1033 } 1034 else if (clazz == Character.TYPE) { 1035 return "C"; 1036 } 1037 else if (clazz == Boolean.TYPE) { 1038 return "Z"; 1039 } 1040 else if (clazz == Void.TYPE) { 1041 return "V"; 1042 } 1043 else { 1044 final String name = clazz.toString(); 1045 ErrorMsg err = new ErrorMsg(ErrorMsg.UNKNOWN_SIG_TYPE_ERR,name); 1046 throw new Error (err.toString()); 1047 } 1048 } 1049 else { 1050 return "L" + clazz.getName().replace('.', '/') + ';'; 1051 } 1052 } 1053 1054 1057 static final String getSignature(Method meth) { 1058 final StringBuffer sb = new StringBuffer (); 1059 sb.append('('); 1060 final Class [] params = meth.getParameterTypes(); for (int j = 0; j < params.length; j++) { 1062 sb.append(getSignature(params[j])); 1063 } 1064 return sb.append(')').append(getSignature(meth.getReturnType())) 1065 .toString(); 1066 } 1067 1068 1071 static final String getSignature(Constructor cons) { 1072 final StringBuffer sb = new StringBuffer (); 1073 sb.append('('); 1074 final Class [] params = cons.getParameterTypes(); for (int j = 0; j < params.length; j++) { 1076 sb.append(getSignature(params[j])); 1077 } 1078 return sb.append(")V").toString(); 1079 } 1080 1081 1084 private String getMethodSignature(Vector argsType) { 1085 final StringBuffer buf = new StringBuffer (_className); 1086 buf.append('.').append(_fname.getLocalPart()).append('('); 1087 1088 int nArgs = argsType.size(); 1089 for (int i = 0; i < nArgs; i++) { 1090 final Type intType = (Type)argsType.elementAt(i); 1091 buf.append(intType.toString()); 1092 if (i < nArgs - 1) buf.append(", "); 1093 } 1094 1095 buf.append(')'); 1096 return buf.toString(); 1097 } 1098 1099 1104 protected static String replaceDash(String name) 1105 { 1106 char dash = '-'; 1107 StringBuffer buff = new StringBuffer (""); 1108 for (int i = 0; i < name.length(); i++) { 1109 if (i > 0 && name.charAt(i-1) == dash) 1110 buff.append(Character.toUpperCase(name.charAt(i))); 1111 else if (name.charAt(i) != dash) 1112 buff.append(name.charAt(i)); 1113 } 1114 return buff.toString(); 1115 } 1116 1117} 1118 | Popular Tags |