| 1 55 package org.jboss.axis.description; 56 57 import org.jboss.axis.AxisServiceConfig; 58 import org.jboss.axis.Constants; 59 import org.jboss.axis.InternalException; 60 import org.jboss.axis.encoding.DefaultTypeMappingImpl; 61 import org.jboss.axis.encoding.TypeMapping; 62 import org.jboss.axis.encoding.TypeMappingRegistry; 63 import org.jboss.axis.encoding.TypeMappingRegistryImpl; 64 import org.jboss.axis.enums.Style; 65 import org.jboss.axis.enums.Use; 66 import org.jboss.axis.message.SOAPBodyElementAxisImpl; 67 import org.jboss.axis.message.SOAPEnvelopeAxisImpl; 68 import org.jboss.axis.utils.JavaUtils; 69 import org.jboss.axis.utils.Messages; 70 import org.jboss.axis.utils.bytecode.ParamNameExtractor; 71 import org.jboss.axis.wsdl.Skeleton; 72 import org.jboss.axis.wsdl.fromJava.Namespaces; 73 import org.jboss.logging.Logger; 74 import org.w3c.dom.Document ; 75 import org.w3c.dom.Element ; 76 77 import javax.xml.namespace.QName ; 78 import javax.xml.rpc.holders.Holder ; 79 import javax.xml.rpc.server.ServiceLifecycle ; 80 import java.lang.reflect.InvocationTargetException ; 81 import java.lang.reflect.Method ; 82 import java.lang.reflect.Modifier ; 83 import java.util.ArrayList ; 84 import java.util.Collection ; 85 import java.util.Collections ; 86 import java.util.Comparator ; 87 import java.util.HashMap ; 88 import java.util.Iterator ; 89 import java.util.List ; 90 import java.util.StringTokenizer ; 91 92 93 102 public class ServiceDesc 103 { 104 105 private static Logger log = Logger.getLogger(ServiceDesc.class.getName()); 106 107 110 private String name = null; 111 112 113 116 private List allowedMethods = null; 117 118 121 private List disallowedMethods = null; 122 123 126 private Style style = Style.RPC; 127 private Use use = Use.ENCODED; 128 129 private boolean useSet = false; 133 134 137 private Class implClass = null; 138 139 142 private ArrayList operations = new ArrayList (); 143 144 147 private List namespaceMappings = null; 148 149 155 private String wsdlFileName = null; 156 157 162 private String endpointURL = null; 163 164 167 private HashMap properties = null; 168 169 173 private boolean isSkeletonClass = false; 174 175 178 private Method skelMethod = null; 179 180 184 private ArrayList stopClasses = null; 185 186 189 private HashMap name2OperationsMap = null; 190 private HashMap qname2OperationsMap = null; 191 private HashMap method2OperationMap = new HashMap (); 192 private HashMap method2ParamsMap = new HashMap (); 193 private OperationDesc messageServiceDefaultOp = null; 194 195 198 private ArrayList completedNames = new ArrayList (); 199 200 203 private TypeMapping tm = DefaultTypeMappingImpl.getSingleton(); 204 205 private TypeMappingRegistry tmr = null; 206 207 private boolean haveAllSkeletonMethods = false; 208 private boolean introspectionComplete = false; 209 210 213 public ServiceDesc() 214 { 215 } 216 217 222 public Style getStyle() 223 { 224 return style; 225 } 226 227 public void setStyle(Style style) 228 { 229 this.style = style; 230 if (!useSet) 231 { 232 use = style == Style.RPC ? Use.ENCODED : Use.LITERAL; 234 } 235 } 236 237 242 public Use getUse() 243 { 244 return use; 245 } 246 247 public void setUse(Use use) 248 { 249 useSet = true; 250 this.use = use; 251 } 252 253 262 public boolean isWrapped() 263 { 264 return ((style == Style.RPC) || 265 (style == Style.WRAPPED)); 266 } 267 268 274 public String getWSDLFile() 275 { 276 return wsdlFileName; 277 } 278 279 286 public void setWSDLFile(String wsdlFileName) 287 { 288 this.wsdlFileName = wsdlFileName; 289 } 290 291 public List getAllowedMethods() 292 { 293 return allowedMethods; 294 } 295 296 public void setAllowedMethods(List allowedMethods) 297 { 298 this.allowedMethods = allowedMethods; 299 } 300 301 public Class getImplClass() 302 { 303 return implClass; 304 } 305 306 316 public void setImplClass(Class implClass) 317 { 318 if (this.implClass != null) 319 throw new IllegalArgumentException (Messages.getMessage("implAlreadySet")); 320 321 this.implClass = implClass; 322 if (Skeleton.class.isAssignableFrom(implClass)) 323 { 324 isSkeletonClass = true; 325 loadSkeletonOperations(); 326 } 327 } 328 329 private void loadSkeletonOperations() 330 { 331 Method method = null; 332 try 333 { 334 method = implClass.getDeclaredMethod("getOperationDescs", 335 new Class []{}); 336 } 337 catch (NoSuchMethodException e) 338 { 339 } 340 catch (SecurityException e) 341 { 342 } 343 if (method == null) 344 { 345 return; 347 } 348 349 try 350 { 351 Collection opers = (Collection )method.invoke(implClass, null); 352 for (Iterator i = opers.iterator(); i.hasNext();) 353 { 354 OperationDesc skelDesc = (OperationDesc)i.next(); 355 addOperationDesc(skelDesc); 356 } 357 } 358 catch (IllegalAccessException e) 359 { 360 return; 361 } 362 catch (IllegalArgumentException e) 363 { 364 return; 365 } 366 catch (InvocationTargetException e) 367 { 368 return; 369 } 370 haveAllSkeletonMethods = true; 371 } 372 373 public TypeMapping getTypeMapping() 374 { 375 return tm; 376 } 377 378 public void setTypeMapping(TypeMapping tm) 379 { 380 this.tm = tm; 381 } 382 383 386 public String getName() 387 { 388 return name; 389 } 390 391 396 public void setName(String name) 397 { 398 this.name = name; 399 } 400 401 public ArrayList getStopClasses() 402 { 403 return stopClasses; 404 } 405 406 public void setStopClasses(ArrayList stopClasses) 407 { 408 this.stopClasses = stopClasses; 409 } 410 411 public List getDisallowedMethods() 412 { 413 return disallowedMethods; 414 } 415 416 public void setDisallowedMethods(List disallowedMethods) 417 { 418 this.disallowedMethods = disallowedMethods; 419 } 420 421 public void addOperationDesc(OperationDesc operation) 422 { 423 operations.add(operation); 424 operation.setParent(this); 425 if (name2OperationsMap == null) 426 { 427 name2OperationsMap = new HashMap (); 428 } 429 430 String name = operation.getName(); 432 ArrayList overloads = (ArrayList )name2OperationsMap.get(name); 433 if (overloads == null) 434 { 435 overloads = new ArrayList (); 436 name2OperationsMap.put(name, overloads); 437 } 438 overloads.add(operation); 439 } 440 441 448 public ArrayList getOperations() 449 { 450 loadServiceDescByIntrospection(); return operations; 452 } 453 454 460 public OperationDesc[] getOperationsByName(String methodName) 461 { 462 getSyncedOperationsForName(implClass, methodName); 463 464 if (name2OperationsMap == null) 465 return null; 466 467 ArrayList overloads = (ArrayList )name2OperationsMap.get(methodName); 468 if (overloads == null) 469 { 470 return null; 471 } 472 473 OperationDesc[] array = new OperationDesc[overloads.size()]; 474 return (OperationDesc[])overloads.toArray(array); 475 } 476 477 483 public OperationDesc getOperationByName(String methodName) 484 { 485 getSyncedOperationsForName(implClass, methodName); 489 490 if (name2OperationsMap == null) 491 return null; 492 493 ArrayList overloads = (ArrayList )name2OperationsMap.get(methodName); 494 if (overloads == null) 495 { 496 return null; 497 } 498 499 return (OperationDesc)overloads.get(0); 500 } 501 502 508 public OperationDesc getOperationByElementQName(QName qname) 509 { 510 OperationDesc[] overloads = getOperationsByQName(qname); 511 512 if ((overloads != null) && overloads.length > 0) 514 return overloads[0]; 515 516 return null; 517 } 518 519 525 public OperationDesc[] getOperationsByQName(QName qname) 526 { 527 529 initQNameMap(); 531 532 ArrayList overloads = (ArrayList )qname2OperationsMap.get(qname); 533 534 if (overloads == null) 535 { 536 if ((isWrapped() || 538 ((style == Style.MESSAGE) && 539 (getDefaultNamespace() == null))) && 540 (name2OperationsMap != null)) 541 { 542 overloads = (ArrayList )name2OperationsMap.get(qname.getLocalPart()); 544 } 545 546 if ((style == Style.MESSAGE) && (messageServiceDefaultOp != null)) 549 return new OperationDesc[]{messageServiceDefaultOp}; 550 551 if (overloads == null) 552 return null; 553 } 554 555 getSyncedOperationsForName(implClass, 556 ((OperationDesc)overloads.get(0)).getName()); 557 558 Collections.sort(overloads, 563 new Comparator () 564 { 565 public int compare(Object o1, Object o2) 566 { 567 Method meth1 = ((OperationDesc)o1).getMethod(); 568 Method meth2 = ((OperationDesc)o2).getMethod(); 569 return (meth1.getParameterTypes().length - 570 meth2.getParameterTypes().length); 571 } 572 }); 573 574 OperationDesc[] array = new OperationDesc[overloads.size()]; 575 return (OperationDesc[])overloads.toArray(array); 576 } 577 578 private synchronized void initQNameMap() 579 { 580 if (qname2OperationsMap == null) 581 { 582 loadServiceDescByIntrospection(); 583 584 qname2OperationsMap = new HashMap (); 585 for (Iterator i = operations.iterator(); i.hasNext();) 586 { 587 OperationDesc operationDesc = (OperationDesc)i.next(); 588 QName qname = operationDesc.getElementQName(); 589 ArrayList list = (ArrayList )qname2OperationsMap.get(qname); 590 if (list == null) 591 { 592 list = new ArrayList (); 593 qname2OperationsMap.put(qname, list); 594 } 595 list.add(operationDesc); 596 } 597 } 598 } 599 600 609 private void syncOperationToClass(OperationDesc opDesc, Class implClass) 610 { 611 log.debug("Enter: syncOperationToClass " + opDesc); 612 613 678 if (opDesc.getMethod() != null) 680 return; 681 682 684 Method [] methods = implClass.getDeclaredMethods(); 685 Method possibleMatch = null; 687 688 for (int i = 0; i < methods.length; i++) 689 { 690 Method method = methods[i]; 691 if (Modifier.isPublic(method.getModifiers()) && 692 method.getName().equals(opDesc.getName()) && 693 method2OperationMap.get(method) == null) 694 { 695 696 log.debug("Sync method: " + method); 697 698 if (style == Style.MESSAGE) 699 { 700 int messageOperType = checkMessageMethod(method); 701 if (messageOperType == OperationDesc.MSG_METHOD_NONCONFORMING) continue; 702 if (messageOperType == -1) 703 { 704 throw new InternalException("Couldn't match method to any of the allowable message-style patterns!"); 705 } 706 opDesc.setMessageOperationStyle(messageOperType); 707 } 708 709 Class [] paramTypes = method.getParameterTypes(); 711 if (paramTypes.length != opDesc.getNumParams()) 712 { 713 log.debug("Number of parameters don't match"); 714 continue; 715 } 716 717 int j; 718 boolean conversionNecessary = false; 719 for (j = 0; j < paramTypes.length; j++) 720 { 721 Class type = paramTypes[j]; 722 Class actualType = type; 723 724 log.debug("Converting param: " + type); 725 726 if (Holder .class.isAssignableFrom(type)) 727 actualType = JavaUtils.getHolderValueType(type); 728 729 ParameterDesc param = opDesc.getParameter(j); 730 Class paramClass = param.getJavaType(); 731 732 QName typeQName = param.getTypeQName(); 733 if (typeQName == null) 734 { 735 typeQName = tm.getTypeQName(type); 743 param.setTypeQName(typeQName); 744 log.debug("Setting param TypeQName: " + typeQName); 745 746 } 747 else 748 { 749 if (paramClass != null && JavaUtils.getHolderValueType(paramClass) != null) 756 { 757 paramClass = JavaUtils.getHolderValueType(paramClass); 758 log.debug("Setting param class to holder type: " + paramClass); 759 } 760 if (paramClass == null) 761 { 762 paramClass = tm.getClassForQName(param.getTypeQName()); 763 log.debug("Setting param class from TypeQName: " + paramClass); 764 } 765 766 if (paramClass != null) 767 { 768 if (!JavaUtils.isConvertable(paramClass, actualType)) 772 { 773 log.debug("Param class is not convertible: [param=" + paramClass + ",actual=" + actualType + "]"); 774 break; 775 } 776 777 if (!actualType.isAssignableFrom(paramClass)) 778 { 779 conversionNecessary = true; 781 log.debug("Actual type is not assignable from param class: [param=" + paramClass + ",actual=" + actualType + "]"); 782 } 783 } 784 } 785 param.setJavaType(type); 789 log.debug("Setting param java type: " + type); 790 } 791 792 if (j != paramTypes.length) 793 { 794 continue; 796 } 797 798 possibleMatch = method; 800 log.debug("Possible match: " + possibleMatch); 801 802 if (!conversionNecessary) 805 { 806 break; 807 } 808 809 log.debug("Conversion still necessary"); 810 } 811 } 812 813 if (possibleMatch != null) 818 { 819 ParameterDesc retParamDesc = opDesc.getReturnParamDesc(); 820 QName retTypeQName = retParamDesc.getTypeQName(); 821 Class retType = retParamDesc.getJavaType(); 822 if (retTypeQName != null && retType == null) 823 retType = tm.getClassForQName(retTypeQName); 824 825 if (retType != null) 826 { 827 Class seiReturnType = possibleMatch.getReturnType(); 828 if (JavaUtils.isConvertable(retType, seiReturnType)) 829 { 830 opDesc.setReturnClass(seiReturnType); 831 log.debug("Setting return type: " + seiReturnType); 832 } 833 else 834 { 835 log.warn("Return type is not convertible to: " + retType); 836 } 838 } 839 840 if (possibleMatch != null) 841 { 842 createFaultMetadata(possibleMatch, opDesc); 844 845 opDesc.setMethod(possibleMatch); 846 method2OperationMap.put(possibleMatch, opDesc); 847 log.debug("Setting operation method: " + possibleMatch); 848 } 849 } 850 851 if (opDesc.getMethod() == null) 853 { 854 Class superClass = implClass.getSuperclass(); 855 if (superClass != null && 856 !superClass.getName().startsWith("java.") && 857 !superClass.getName().startsWith("javax.") && 858 (stopClasses == null || 859 !stopClasses.contains(superClass.getName()))) 860 { 861 862 log.debug("No match found, trying super class"); 863 syncOperationToClass(opDesc, superClass); 864 } 865 } 866 867 if (opDesc.getMethod() == null) 869 { 870 InternalException ie = 871 new InternalException(Messages.getMessage("serviceDescOperSync00", 872 opDesc.getName(), 873 implClass.getName())); 874 throw ie; 875 } 876 } 877 878 private int checkMessageMethod(Method method) 879 { 880 Class [] params = method.getParameterTypes(); 883 884 if (params.length == 1) 885 { 886 if ((params[0] == Element [].class) && 887 (method.getReturnType() == Element [].class)) 888 { 889 return OperationDesc.MSG_METHOD_ELEMENTARRAY; 890 } 891 892 if ((params[0] == SOAPBodyElementAxisImpl[].class) && 893 (method.getReturnType() == SOAPBodyElementAxisImpl[].class)) 894 { 895 return OperationDesc.MSG_METHOD_BODYARRAY; 896 } 897 898 if ((params[0] == Document .class) && 899 (method.getReturnType() == Document |