📄 javaservicedesc.java
字号:
Method method = operation.getMethod(); if (method != null) { method2OperationMap.remove(method); } } } public void addOperationDesc(OperationDesc operation) { operations.add(operation); operation.setParent(this); if (name2OperationsMap == null) { name2OperationsMap = new HashMap(); } // Add name to name2Operations Map String name = operation.getName(); ArrayList overloads = (ArrayList)name2OperationsMap.get(name); if (overloads == null) { overloads = new ArrayList(); name2OperationsMap.put(name, overloads); } else if (JavaUtils.isTrue( AxisProperties.getProperty(Constants.WSIBP11_COMPAT_PROPERTY)) && overloads.size() > 0) { throw new RuntimeException(Messages.getMessage("noOverloadedOperations", name)); } overloads.add(operation); } /** * get all the operations as a list of OperationDescs. * this method triggers an evaluation of the valid operations by * introspection, so use sparingly * @return reference to the operations array. This is not a copy */ public ArrayList getOperations() { loadServiceDescByIntrospection(); // Just in case... return operations; } /** * get all overloaded operations by name * @param methodName * @return null for no match, or an array of OperationDesc objects */ public OperationDesc [] getOperationsByName(String methodName) { getSyncedOperationsForName(implClass, methodName); if (name2OperationsMap == null) return null; ArrayList overloads = (ArrayList)name2OperationsMap.get(methodName); if (overloads == null) { return null; } OperationDesc [] array = new OperationDesc [overloads.size()]; return (OperationDesc[])overloads.toArray(array); } /** * Return an operation matching the given method name. Note that if we * have multiple overloads for this method, we will return the first one. * @return null for no match */ public OperationDesc getOperationByName(String methodName) { // If we need to load up operations from introspection data, do it. // This returns fast if we don't need to do anything, so it's not very // expensive. getSyncedOperationsForName(implClass, methodName); if (name2OperationsMap == null) return null; ArrayList overloads = (ArrayList)name2OperationsMap.get(methodName); if (overloads == null) { return null; } return (OperationDesc)overloads.get(0); } /** * Map an XML QName to an operation. Returns the first one it finds * in the case of mulitple matches. * @return null for no match */ public OperationDesc getOperationByElementQName(QName qname) { OperationDesc [] overloads = getOperationsByQName(qname); // Return the first one.... if ((overloads != null) && overloads.length > 0) return overloads[0]; return null; } /** * Return all operations which match this QName (i.e. get all the * overloads) * @return null for no match */ public OperationDesc [] getOperationsByQName(QName qname) { // Look in our mapping of QNames -> operations. // But first, let's make sure we've initialized said mapping.... initQNameMap(); ArrayList overloads = (ArrayList)qname2OperationsMap.get(qname); if (overloads == null) { // Nothing specifically matching this QName. if (name2OperationsMap != null) { if ((isWrapped() || ((style == Style.MESSAGE) && (getDefaultNamespace() == null)))) { // Try ignoring the namespace....? overloads = (ArrayList) name2OperationsMap.get(qname.getLocalPart()); } else { // TODO the above code is weird: a JavaServiceDesc can be document or rpc and // still define a WSDL operation using a wrapper style mapping. // The following code handles this case. Object ops = name2OperationsMap.get(qname.getLocalPart()); if (ops != null) { overloads = new ArrayList((Collection) ops); for (Iterator iter = overloads.iterator(); iter.hasNext();) { OperationDesc operationDesc = (OperationDesc) iter.next(); if (Style.WRAPPED != operationDesc.getStyle()) { iter.remove(); } } } } } // Handle the case where a single Message-style operation wants // to accept anything. if ((style == Style.MESSAGE) && (messageServiceDefaultOp != null)) return new OperationDesc [] { messageServiceDefaultOp }; if (overloads == null) return null; } getSyncedOperationsForName(implClass, ((OperationDesc)overloads.get(0)).getName()); // Sort the overloads by number of arguments - prevents us calling methods // with more parameters than supplied in the request (with missing parameters // defaulted to null) when a perfectly good method exists with exactly the // supplied parameters. Collections.sort(overloads, new Comparator() { public int compare(Object o1, Object o2) { Method meth1 = ((OperationDesc)o1).getMethod(); Method meth2 = ((OperationDesc)o2).getMethod(); return (meth1.getParameterTypes().length - meth2.getParameterTypes().length); } }); OperationDesc [] array = new OperationDesc [overloads.size()]; return (OperationDesc[])overloads.toArray(array); } private synchronized void initQNameMap() { if (qname2OperationsMap == null) { loadServiceDescByIntrospection(); qname2OperationsMap = new HashMap(); for (Iterator i = operations.iterator(); i.hasNext();) { OperationDesc operationDesc = (OperationDesc) i.next(); QName qname = operationDesc.getElementQName(); ArrayList list = (ArrayList)qname2OperationsMap.get(qname); if (list == null) { list = new ArrayList(); qname2OperationsMap.put(qname, list); } list.add(operationDesc); } } } /** * Synchronize an existing OperationDesc to a java.lang.Method. * * This method is used when the deployer has specified operation metadata * and we want to match that up with a real java Method so that the * Operation-level dispatch carries us all the way to the implementation. * Search the declared methods on the implementation class to find one * with an argument list which matches our parameter list. */ private void syncOperationToClass(OperationDesc oper, Class implClass) { // ------------------------------------------------ // Developer Note: // // The goal of the sync code is to associate // the OperationDesc/ParamterDesc with the // target Method. There are a number of ways to get to this // point depending on what information // is available. Here are the main scenarios: // // A) Deployment with wsdd (non-skeleton): // * OperationDesc/ParameterDesc loaded from deploy.wsdd // * Loaded ParameterDesc does not have javaType, // so it is discovered using the TypeMappingRegistry // (also loaded via deploy.wsdd) and the // typeQName specified by the ParameterDesc. // * Sync occurs using the discovered // javaTypes and the javaTypes of the Method // parameters // // B) Deployment with no wsdd OperationDesc info (non-skeleton): // * Implementation Class introspected to build // OperationDesc/ParameterDesc. // * ParameterDesc is known via introspection. // * ParameterDesc are discovered using javaType // and TypeMappingRegistry. // * Sync occurs using the introspected // javaTypes and the javaTypes of the Method // parameters // // C) Deployment with wsdd (skeleton): // * OperationDesc/ParameterDesc loaded from the Skeleton // * In this scenario the ParameterDescs' already // have javaTypes (see E below). // * Sync occurs using the ParameterDesc // javaTypes and the javaTypes of the Method // parameters. // // D) Commandline Java2WSDL loading non-Skeleton Class/Interface // * Class/Interface introspected to build // OperationDesc/ParameterDesc. // * The javaTypes of the ParameterDesc are set using introspection. // * typeQNames are determined for built-in types using // from the default TypeMappingRegistry. Other // typeQNames are guessed from the javaType. Note // that there is no loaded TypeMappingRegistry. // * Sync occurs using the ParameterDesc // javaTypes and the javaTypes of the Method // parameters. // // E) Commandline Java2WSDL loading Skeleton Class // * OperationDesc/ParameterDesc loaded from Skeleton // * Each ParameterDesc has an appropriate typeQName // * Each ParameterDesc also has a javaType, which is // essential for sync'ing up with the // method since there is no loaded TypeMappingRegistry. // * Syncronization occurs using the ParameterDesc // javaTypes and the javaTypes of the Method // parameters. // // So in each scenario, the ultimate sync'ing occurs // using the javaTypes of the ParameterDescs and the // javaTypes of the Method parameters. // // ------------------------------------------------ // If we're already mapped to a Java method, no need to do anything. if (oper.getMethod() != null) return; // Find the method. We do this once for each Operation. Method[] methods = getMethods(implClass); // A place to keep track of possible matches Method possibleMatch = null; for (int i = 0; i < methods.length; i++) { Method method = methods[i]; if (Modifier.isPublic(method.getModifiers()) && method.getName().equals(oper.getName()) && method2OperationMap.get(method) == null) { if (style == Style.MESSAGE) { int messageOperType = checkMessageMethod(method); if(messageOperType == OperationDesc.MSG_METHOD_NONCONFORMING) continue; if (messageOperType == -1) { throw new InternalException("Couldn't match method to any of the allowable message-style patterns!"); } oper.setMessageOperationStyle(messageOperType); // Don't bother checking params if we're message style possibleMatch = method; break; } // Check params Class [] paramTypes = method.getParameterTypes(); if (paramTypes.length != oper.getNumParams()) continue; int j; boolean conversionNecessary = false; for (j = 0; j < paramTypes.length; j++) { Class type = paramTypes[j]; Class actualType = type; if (Holder.class.isAssignableFrom(type)) { actualType = JavaUtils.getHolderValueType(type); } ParameterDesc param = oper.getParameter(j); QName typeQName = param.getTypeQName(); if (typeQName == null) { // No typeQName is available. Set it using // information from the actual type. // (Scenarios B and D) // There is no need to try and match with // the Method parameter javaType because // the ParameterDesc is being constructed // by introspecting the Method. typeQName = getTypeMapping().getTypeQName(actualType); param.setTypeQName(typeQName); } else { // A type qname is available. // Ensure that the ParameterDesc javaType // is convertable to the Method parameter type // // Use the available javaType (Scenarios C and E) // or get one from the TMR (Scenario A). Class paramClass = param.getJavaType(); if (paramClass != null && JavaUtils.getHolderValueType(paramClass) != null) { paramClass = JavaUtils.getHolderValueType(paramClass); } if (paramClass == null) { paramClass = getTypeMapping().getClassForQName(param.getTypeQName(), type); } if (paramClass != null) { // This is a match if the paramClass is somehow // convertable to the "real" parameter type. If not, // break out of this loop. if (!JavaUtils.isConvertable(paramClass, actualType)) { break; } if (!actualType.isAssignableFrom(paramClass)) { // This doesn't fit without conversion conversionNecessary = true; } } } // In all scenarios the ParameterDesc javaType is set to // match the javaType in the corresponding parameter. // This is essential. param.setJavaType(type); } if (j != paramTypes.length) { // failed. continue; } // This is our latest possibility possibleMatch = method; // If this is exactly it, stop now. Otherwise keep looking // just in case we find a better match. if (!conversionNecessary) { break; } } } // At this point, we may or may not have a possible match.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -