📄 javaservicedesc.java
字号:
// FIXME : Should we prefer an exact match from a base class over // a with-conversion match from the target class? If so, // we'll need to change the logic below. if (possibleMatch != null) { Class returnClass = possibleMatch.getReturnType(); oper.setReturnClass(returnClass); QName returnType = oper.getReturnType(); if (returnType == null) { oper.setReturnType(getTypeMapping().getTypeQName(returnClass)); } // Do the faults createFaultMetadata(possibleMatch, oper); oper.setMethod(possibleMatch); method2OperationMap.put(possibleMatch, oper); return; } // Didn't find a match. Try the superclass, if appropriate Class superClass = implClass.getSuperclass(); if (superClass != null && !superClass.getName().startsWith("java.") && !superClass.getName().startsWith("javax.") && (stopClasses == null || !stopClasses.contains(superClass.getName()))) { syncOperationToClass(oper, superClass); } // Exception if sync fails to find method for operation if (oper.getMethod() == null) { InternalException ie = new InternalException(Messages.getMessage("serviceDescOperSync00", oper.getName(), implClass.getName())); throw ie; } } private Method[] getMethods(Class implClass) { if (implClass.isInterface()){ // only return methods that are not part of start classes List methodsList = new ArrayList(); Method[] methods = implClass.getMethods(); if (methods != null) { for (int i = 0; i < methods.length; i++) { String declaringClass = methods[i].getDeclaringClass().getName(); if (!declaringClass.startsWith("java.") && !declaringClass.startsWith("javax.")) { methodsList.add(methods[i]); } } } return (Method[])methodsList.toArray(new Method[]{}); } else { return implClass.getDeclaredMethods(); } } private int checkMessageMethod(Method method) { // Collect the types so we know what we're dealing with in the target // method. Class [] params = method.getParameterTypes(); if (params.length == 1) { if ((params[0] == Element[].class) && (method.getReturnType() == Element[].class)) { return OperationDesc.MSG_METHOD_ELEMENTARRAY; } if ((params[0] == SOAPBodyElement[].class) && (method.getReturnType() == SOAPBodyElement[].class)) { return OperationDesc.MSG_METHOD_BODYARRAY; } if ((params[0] == Document.class) && (method.getReturnType() == Document.class)) { return OperationDesc.MSG_METHOD_DOCUMENT; } } else if (params.length == 2) { if (((params[0] == SOAPEnvelope.class) && (params[1] == SOAPEnvelope.class)) || ((params[0] == javax.xml.soap.SOAPEnvelope.class) && (params[1] == javax.xml.soap.SOAPEnvelope.class)) && (method.getReturnType() == void.class)){ return OperationDesc.MSG_METHOD_SOAPENVELOPE; } } if( null != allowedMethods && !allowedMethods.isEmpty() ) throw new InternalException (Messages.getMessage("badMsgMethodParams", method.getName())); return OperationDesc.MSG_METHOD_NONCONFORMING; } /** * Fill in a service description by introspecting the implementation * class. */ public void loadServiceDescByIntrospection() { loadServiceDescByIntrospection(implClass); // Setting this to null means there is nothing more to do, and it // avoids future string compares. completedNames = null; } /** * Fill in a service description by introspecting the implementation * class. */ public void loadServiceDescByIntrospection(Class implClass) { if (introspectionComplete || implClass == null) { return; } // set the implementation class for the service description this.implClass = implClass; if (Skeleton.class.isAssignableFrom(implClass)) { isSkeletonClass = true; loadSkeletonOperations(); } /** If the class knows what it should be exporting, * respect its wishes. */ AxisServiceConfig axisConfig = null; try { Method method = implClass.getDeclaredMethod( "getAxisServiceConfig", new Class [] {}); if (method != null && Modifier.isStatic(method.getModifiers())) { axisConfig = (AxisServiceConfig)method.invoke(null, null); } } catch (Exception e) { // No problem, just continue without... } if (axisConfig != null) { String allowedMethodsStr = axisConfig.getAllowedMethods(); if (allowedMethodsStr != null && !"*".equals(allowedMethodsStr)) { ArrayList methodList = new ArrayList(); StringTokenizer tokenizer = new StringTokenizer(allowedMethodsStr, " ,"); while (tokenizer.hasMoreTokens()) { methodList.add(tokenizer.nextToken()); } setAllowedMethods(methodList); } } loadServiceDescByIntrospectionRecursive(implClass); // All operations should now be synchronized. Check it. for (Iterator iterator = operations.iterator(); iterator.hasNext();) { OperationDesc operation = (OperationDesc) iterator.next(); if (operation.getMethod() == null) { throw new InternalException( Messages.getMessage("badWSDDOperation", operation.getName(), "" + operation.getNumParams())); } } if ((style == Style.MESSAGE) && operations.size() == 1) { messageServiceDefaultOp = (OperationDesc)operations.get(0); } introspectionComplete = true; } /** * Is this method from ServiceLifeCycle interface? * @param m * @return true if this method is from ServiceLifeCycle interface */ private boolean isServiceLifeCycleMethod(Class implClass, Method m) { if(javax.xml.rpc.server.ServiceLifecycle.class.isAssignableFrom(implClass)) { String methodName = m.getName(); if(methodName.equals("init")) { // Check if the method signature is // "public abstract void init(Object context) throws ServiceException;" Class[] classes = m.getParameterTypes(); if(classes != null && classes.length == 1 && classes[0] == Object.class && m.getReturnType() == Void.TYPE) { return true; } } else if (methodName.equals("destroy")){ // Check if the method signature is // "public abstract void destroy();" Class[] classes = m.getParameterTypes(); if(classes != null && classes.length == 0 && m.getReturnType() == Void.TYPE) { return true; } } } return false; } /** * Recursive helper class for loadServiceDescByIntrospection */ private void loadServiceDescByIntrospectionRecursive(Class implClass) { if (Skeleton.class.equals(implClass)) { return; } Method [] methods = getMethods(implClass); for (int i = 0; i < methods.length; i++) { if (Modifier.isPublic(methods[i].getModifiers()) && !isServiceLifeCycleMethod(implClass, methods[i])) { getSyncedOperationsForName(implClass, methods[i].getName()); } } if (implClass.isInterface()) { Class [] superClasses = implClass.getInterfaces(); for (int i = 0; i < superClasses.length; i++) { Class superClass = superClasses[i]; if (!superClass.getName().startsWith("java.") && !superClass.getName().startsWith("javax.") && (stopClasses == null || !stopClasses.contains(superClass.getName()))) { loadServiceDescByIntrospectionRecursive(superClass); } } } else { Class superClass = implClass.getSuperclass(); if (superClass != null && !superClass.getName().startsWith("java.") && !superClass.getName().startsWith("javax.") && (stopClasses == null || !stopClasses.contains(superClass.getName()))) { loadServiceDescByIntrospectionRecursive(superClass); } } } /** * Fill in a service description by introspecting the implementation * class. This version takes the implementation class and the in-scope * TypeMapping. */ public void loadServiceDescByIntrospection(Class cls, TypeMapping tm) { // Should we complain if the implClass changes??? implClass = cls; this.tm = tm; if (Skeleton.class.isAssignableFrom(implClass)) { isSkeletonClass = true; loadSkeletonOperations(); } loadServiceDescByIntrospection(); } /** * Makes sure we have completely synchronized OperationDescs with * the implementation class. */ private void getSyncedOperationsForName(Class implClass, String methodName) { // If we're a Skeleton deployment, skip the statics. if (isSkeletonClass) { if (methodName.equals("getOperationDescByName") || methodName.equals("getOperationDescs")) return; } // If we have no implementation class, don't worry about it (we're // probably on the client) if (implClass == null) return; // If we're done introspecting, or have completed this method, return if (completedNames == null || completedNames.contains(methodName)) return; // Skip it if it's not a sanctioned method name if ((allowedMethods != null) && !allowedMethods.contains(methodName)) return; if ((disallowedMethods != null) && disallowedMethods.contains(methodName)) return; // If we're a skeleton class, make sure we don't already have any // OperationDescs for this name (as that might cause conflicts), // then load them up from the Skeleton class. if (isSkeletonClass && !haveAllSkeletonMethods) { // FIXME : Check for existing ones and fault if found if (skelMethod == null) { // Grab metadata from the Skeleton for parameter info try { skelMethod = implClass.getDeclaredMethod( "getOperationDescByName", new Class [] { String.class }); } catch (NoSuchMethodException e) { } catch (SecurityException e) { } if (skelMethod == null) { // FIXME : Throw an error? return; } } try { List skelList = (List)skelMethod.invoke(implClass, new Object [] { methodName }); if (skelList != null) { Iterator i = skelList.iterator(); while (i.hasNext()) { addOperationDesc((OperationDesc)i.next()); } } } catch (IllegalAccessException e) { if(log.isDebugEnabled()) { log.debug(Messages.getMessage("exception00"), e); } return; } catch (IllegalArgumentException e) { if(log.isDebugEnabled()) { log.debug(Messages.getMessage("exception00"), e); } return; } catch (InvocationTargetException e) { if(log.isDebugEnabled()) { log.debug(Messages.getMessage("exception00"), e); } return; } } // OK, go find any current OperationDescs for this method name and // make sure they're synced with the actual class. if (name2OperationsMap != null) { ArrayList currentOverloads = (ArrayList)name2OperationsMap.get(methodName); if (currentOverloads != null) { // For each one, sync it to the implementation class' methods for (Iterator i = currentOverloads.iterator(); i.hasNext();) { OperationDesc oper = (OperationDesc) i.next(); if (oper.getMethod() == null) { syncOperationToClass(oper, implClass); } } } } // Now all OperationDescs from deployment data have been completely // filled in. So we now make new OperationDescs for any method // overloads which were not covered above. // NOTE : This is the "lenient" approach, which allows you to // specify one overload and still get the others by introspection. // We could equally well return above if we found OperationDescs, // and have a rule that if you specify any overloads, you must specify // all the ones you want accessible. createOperationsForName(implClass, methodName); // Note that we never have to look at this method name again. completedNames.add(methodName); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -