Author: jochen Date: Fri Mar 3 14:10:05 2006 New Revision: 382944 URL: http://svn.apache.org/viewcvs?rev=382944&view=rev Log: Performing the next step in the implementation of introspection. (See XMLRPC-75.)
Added: webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/ReflectiveXmlRpcMetaDataHandler.java webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/Util.java webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/XmlRpcSystemImpl.java webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java Modified: webservices/xmlrpc/trunk/.settings/org.eclipse.jdt.core.prefs webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/AbstractReflectiveHandlerMapping.java Modified: webservices/xmlrpc/trunk/.settings/org.eclipse.jdt.core.prefs URL: http://svn.apache.org/viewcvs/webservices/xmlrpc/trunk/.settings/org.eclipse.jdt.core.prefs?rev=382944&r1=382943&r2=382944&view=diff ============================================================================== --- webservices/xmlrpc/trunk/.settings/org.eclipse.jdt.core.prefs (original) +++ webservices/xmlrpc/trunk/.settings/org.eclipse.jdt.core.prefs Fri Mar 3 14:10:05 2006 @@ -1,9 +1,9 @@ -#Fri Feb 24 13:58:31 CET 2006 +#Fri Mar 03 08:22:27 CET 2006 eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.3 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.compliance=1.5 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate @@ -15,7 +15,7 @@ org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled org.eclipse.jdt.core.compiler.problem.discouragedReference=warning org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning org.eclipse.jdt.core.compiler.problem.fieldHiding=warning org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore @@ -59,4 +59,4 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.4 +org.eclipse.jdt.core.compiler.source=1.5 Added: webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/ReflectiveXmlRpcMetaDataHandler.java URL: http://svn.apache.org/viewcvs/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/ReflectiveXmlRpcMetaDataHandler.java?rev=382944&view=auto ============================================================================== --- webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/ReflectiveXmlRpcMetaDataHandler.java (added) +++ webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/ReflectiveXmlRpcMetaDataHandler.java Fri Mar 3 14:10:05 2006 @@ -0,0 +1,62 @@ +/* + * Copyright 1999,2006 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.xmlrpc.metadata; + +import java.lang.reflect.Method; + +import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.server.AbstractReflectiveHandlerMapping; +import org.apache.xmlrpc.server.ReflectiveXmlRpcHandler; + + +/** Default implementation of [EMAIL PROTECTED] XmlRpcMetaDataHandler}. + */ +public class ReflectiveXmlRpcMetaDataHandler extends ReflectiveXmlRpcHandler + implements XmlRpcMetaDataHandler { + private final String[][] signatures; + private final String methodHelp; + + /** Creates a new instance. + * @param pMapping The mapping, which creates this handler. + * @param pClass The class, which has been inspected to create + * this handler. Typically, this will be the same as + * <pre>pInstance.getClass()</pre>. It is used for diagnostic + * messages only. + * @param pInstance The instance, which will be invoked for + * executing the handler. + * @param pMethod The method, which will be invoked for + * executing the handler. + * @param pSignatures The signature, which will be returned by + * [EMAIL PROTECTED] #getSignatures()}. + * @param pMethodHelp The help string, which will be returned + * by [EMAIL PROTECTED] #getMethodHelp()}. + */ + public ReflectiveXmlRpcMetaDataHandler(AbstractReflectiveHandlerMapping pMapping, + Class pClass, Object pInstance, Method pMethod, + String[][] pSignatures, String pMethodHelp) { + super(pMapping, pClass, pInstance, pMethod); + signatures = pSignatures; + methodHelp = pMethodHelp; + } + + public String[][] getSignatures() throws XmlRpcException { + return signatures; + } + + public String getMethodHelp() throws XmlRpcException { + return methodHelp; + } +} Added: webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/Util.java URL: http://svn.apache.org/viewcvs/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/Util.java?rev=382944&view=auto ============================================================================== --- webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/Util.java (added) +++ webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/Util.java Fri Mar 3 14:10:05 2006 @@ -0,0 +1,141 @@ +/* + * Copyright 1999,2006 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.xmlrpc.metadata; + +import java.io.Serializable; +import java.lang.reflect.Method; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import org.w3c.dom.Node; + + +/** Utility class, which provides services to meta data + * handlers and handler mappings. + */ +public class Util { + /** This field should solve the problem, that we do not + * want to depend on the presence of JAXB. However, if + * it is available, we want to support it. + */ + private static final Class jaxbElementClass; + static { + Class c; + try { + c = Class.forName("javax.xml.bind.Element"); + } catch (ClassNotFoundException e) { + c = null; + } + jaxbElementClass = c; + } + + /** Returns a signature for the given return type or + * parameter class. + * @param pType The class for which a signature is being + * queried. + * @return Signature, if known, or null. + */ + public static String getSignatureType(Class type) { + if (type == Integer.TYPE || type == Integer.class) + return "int"; + if (type == Double.TYPE || type == Double.class) + return "double"; + if (type == Boolean.TYPE || type == Boolean.class) + return "boolean"; + if (type == String.class) + return "string"; + if (Object[].class.isAssignableFrom(type) + || List.class.isAssignableFrom(type)) + return "array"; + if (Map.class.isAssignableFrom(type)) + return "struct"; + if (Date.class.isAssignableFrom(type) + || Calendar.class.isAssignableFrom(type)) + return "dateTime.iso8601"; + if (type == byte[].class) + return "base64"; + + // extension types + if (type == void.class) + return "ex:nil"; + if (type == Byte.TYPE || type == Byte.class) + return "ex:i1"; + if (type == Short.TYPE || type == Short.class) + return "ex:i2"; + if (type == Long.TYPE || type == Long.class) + return "ex:i8"; + if (type == Float.TYPE || type == Float.class) + return "ex:float"; + if (Node.class.isAssignableFrom(type)) + return "ex:node"; + if (jaxbElementClass != null + && jaxbElementClass.isAssignableFrom(type)) { + return "ex:jaxbElement"; + } + if (Serializable.class.isAssignableFrom(type)) + return "base64"; + + // give up + return null; + } + + /** Returns a signature for the given method. + * @param pMethod Method, for which a signature is + * being queried. + * @return Signature string, or null, if no signature + * is available. + */ + public static String[] getSignature(Method pMethod) { + Class[] paramClasses = pMethod.getParameterTypes(); + String[] sig = new String[paramClasses.length + 1]; + String s = getSignatureType(pMethod.getReturnType()); + if (s == null) { + return null; + } + sig[0] = s; + for (int i = 0; i < paramClasses.length; i++) { + s = getSignatureType(paramClasses[i]); + if (s == null) { + return null; + } + sig[i+1] = s; + } + return sig; + } + + /** Returns a help string for the given method, which + * is applied to the given class. + */ + public static String getMethodHelp(Class pClass, Method pMethod) { + StringBuffer sb = new StringBuffer(); + sb.append("Invokes the method "); + sb.append(pMethod.getReturnType().getClass().getName()); + sb.append("."); + sb.append(pClass.getName()); + sb.append("("); + Class[] paramClasses = pMethod.getParameterTypes(); + for (int i = 0; i < paramClasses.length; i++) { + if (i > 0) { + sb.append(", "); + } + sb.append(paramClasses[i].getName()); + } + sb.append(")."); + return sb.toString(); + } +} Added: webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/XmlRpcSystemImpl.java URL: http://svn.apache.org/viewcvs/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/XmlRpcSystemImpl.java?rev=382944&view=auto ============================================================================== --- webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/XmlRpcSystemImpl.java (added) +++ webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/XmlRpcSystemImpl.java Fri Mar 3 14:10:05 2006 @@ -0,0 +1,56 @@ +/* + * Copyright 1999,2006 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.xmlrpc.metadata; + +import org.apache.xmlrpc.XmlRpcException; + + +/** This class implements the various "system" calls, + * as specifies by [EMAIL PROTECTED] XmlRpcListableHandlerMapping}. + * Suggested use is to create an instance and add it to + * the handler mapping with the "system" prefix. + */ +public class XmlRpcSystemImpl { + private XmlRpcListableHandlerMapping mapping; + + /** Creates a new instance, which provides meta data + * for the given handler mappings methods. + */ + public XmlRpcSystemImpl(XmlRpcListableHandlerMapping pMapping) { + mapping = pMapping; + } + + /** Implements the "system.methodSignature" call. + * @see XmlRpcListableHandlerMapping#getMethodSignature(String) + */ + public String[][] methodSignature(String methodName) throws XmlRpcException { + return mapping.getMethodSignature(methodName); + } + + /** Implements the "system.methodHelp" call. + * @see XmlRpcListableHandlerMapping#getMethodHelp(String) + */ + public String methodHelp(String methodName) throws XmlRpcException { + return mapping.getMethodHelp(methodName); + } + + /** Implements the "system.listMethods" call. + * @see XmlRpcListableHandlerMapping#getListMethods() + */ + public String[] listMethods() throws XmlRpcException { + return mapping.getListMethods(); + } +} Modified: webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/AbstractReflectiveHandlerMapping.java URL: http://svn.apache.org/viewcvs/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/AbstractReflectiveHandlerMapping.java?rev=382944&r1=382943&r2=382944&view=diff ============================================================================== --- webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/AbstractReflectiveHandlerMapping.java (original) +++ webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/AbstractReflectiveHandlerMapping.java Fri Mar 3 14:10:05 2006 @@ -1,22 +1,43 @@ +/* + * Copyright 1999,2006 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.apache.xmlrpc.server; -import org.apache.xmlrpc.XmlRpcRequest; -import org.apache.xmlrpc.XmlRpcException; -import org.apache.xmlrpc.XmlRpcHandler; -import org.apache.xmlrpc.common.XmlRpcNotAuthorizedException; - -import java.util.Map; -import java.util.HashMap; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.XmlRpcHandler; +import org.apache.xmlrpc.XmlRpcRequest; +import org.apache.xmlrpc.metadata.ReflectiveXmlRpcMetaDataHandler; +import org.apache.xmlrpc.metadata.Util; +import org.apache.xmlrpc.metadata.XmlRpcListableHandlerMapping; +import org.apache.xmlrpc.metadata.XmlRpcMetaDataHandler; /** Abstract base class of handler mappings, which are * using reflection. */ -public abstract class AbstractReflectiveHandlerMapping implements XmlRpcHandlerMapping { - /** An object implementing this interface may be used +public abstract class AbstractReflectiveHandlerMapping + implements XmlRpcListableHandlerMapping { + /** An object implementing this interface may be used * to validate user names and passwords. */ public interface AuthenticationHandler { @@ -106,35 +127,26 @@ if (pInstance == null) { throw new NullPointerException("The object instance must not be null."); } - return new XmlRpcHandler(){ - public Object execute(XmlRpcRequest pRequest) throws XmlRpcException { - AuthenticationHandler authHandler = getAuthenticationHandler(); - if (authHandler != null && !authHandler.isAuthorized(pRequest)) { - throw new XmlRpcNotAuthorizedException("Not authorized"); - } - Object[] args = new Object[pRequest.getParameterCount()]; - for (int j = 0; j < args.length; j++) { - args[j] = pRequest.getParameter(j); - } - try { - return pMethod.invoke(pInstance, args); - } catch (IllegalAccessException e) { - throw new XmlRpcException("Illegal access to method " - + pMethod.getName() + " in class " - + pClass.getName(), e); - } catch (IllegalArgumentException e) { - throw new XmlRpcException("Illegal argument for method " - + pMethod.getName() + " in class " - + pClass.getName(), e); - } catch (InvocationTargetException e) { - Throwable t = e.getTargetException(); - throw new XmlRpcException("Failed to invoke method " - + pMethod.getName() + " in class " - + pClass.getName() + ": " - + t.getMessage(), t); - } - } - }; + String[] sig = getSignature(pMethod); + String help = getMethodHelp(pClass, pMethod); + if (sig == null || help == null) { + return new ReflectiveXmlRpcHandler(this, pClass, pInstance, pMethod); + } + return new ReflectiveXmlRpcMetaDataHandler(this, pClass, pInstance, + pMethod, new String[][]{sig}, help); + } + + /** Creates a signature for the given method. + */ + protected String[] getSignature(Method pMethod) { + return Util.getSignature(pMethod); + } + + /** Creates a help string for the given method, when applied + * to the given class. + */ + protected String getMethodHelp(Class pClass, Method pMethod) { + return Util.getMethodHelp(pClass, pMethod); } /** Returns the [EMAIL PROTECTED] XmlRpcHandler} with the given name. @@ -150,4 +162,33 @@ } return result; } + + public String[] getListMethods() throws XmlRpcException { + List list = new ArrayList(); + for (Iterator iter = handlerMap.entrySet().iterator(); + iter.hasNext(); ) { + Map.Entry entry = (Map.Entry) iter.next(); + if (entry.getValue() instanceof XmlRpcMetaDataHandler) { + list.add(entry.getKey()); + } + } + + return (String[]) list.toArray(new String[list.size()]); + } + + public String getMethodHelp(String pHandlerName) throws XmlRpcException { + XmlRpcHandler h = getHandler(pHandlerName); + if (h instanceof XmlRpcMetaDataHandler) + return ((XmlRpcMetaDataHandler)h).getMethodHelp(); + throw new XmlRpcNoSuchHandlerException("No help available for method: " + + pHandlerName); + } + + public String[][] getMethodSignature(String pHandlerName) throws XmlRpcException { + XmlRpcHandler h = getHandler(pHandlerName); + if (h instanceof XmlRpcMetaDataHandler) + return ((XmlRpcMetaDataHandler)h).getSignatures(); + throw new XmlRpcNoSuchHandlerException("No metadata available for method: " + + pHandlerName); + } } Added: webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java URL: http://svn.apache.org/viewcvs/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java?rev=382944&view=auto ============================================================================== --- webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java (added) +++ webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java Fri Mar 3 14:10:05 2006 @@ -0,0 +1,82 @@ +/* + * Copyright 1999,2006 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.xmlrpc.server; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.XmlRpcHandler; +import org.apache.xmlrpc.XmlRpcRequest; +import org.apache.xmlrpc.common.XmlRpcNotAuthorizedException; +import org.apache.xmlrpc.server.AbstractReflectiveHandlerMapping.AuthenticationHandler; + + +/** Default implementation of [EMAIL PROTECTED] XmlRpcHandler}. + */ +public class ReflectiveXmlRpcHandler implements XmlRpcHandler { + private final AbstractReflectiveHandlerMapping mapping; + private final Class clazz; + private final Object instance; + private final Method method; + + /** Creates a new instance. + * @param pMapping The mapping, which creates this handler. + * @param pClass The class, which has been inspected to create + * this handler. Typically, this will be the same as + * <pre>pInstance.getClass()</pre>. It is used for diagnostic + * messages only. + * @param pInstance The instance, which will be invoked for + * executing the handler. + * @param pMethod The method, which will be invoked for + * executing the handler. + */ + public ReflectiveXmlRpcHandler(AbstractReflectiveHandlerMapping pMapping, + Class pClass, Object pInstance, Method pMethod) { + mapping = pMapping; + clazz = pClass; + instance = pInstance; + method = pMethod; + } + + public Object execute(XmlRpcRequest pRequest) throws XmlRpcException { + AuthenticationHandler authHandler = mapping.getAuthenticationHandler(); + if (authHandler != null && !authHandler.isAuthorized(pRequest)) { + throw new XmlRpcNotAuthorizedException("Not authorized"); + } + Object[] args = new Object[pRequest.getParameterCount()]; + for (int j = 0; j < args.length; j++) { + args[j] = pRequest.getParameter(j); + } + try { + return method.invoke(instance, args); + } catch (IllegalAccessException e) { + throw new XmlRpcException("Illegal access to method " + + method.getName() + " in class " + + clazz.getName(), e); + } catch (IllegalArgumentException e) { + throw new XmlRpcException("Illegal argument for method " + + method.getName() + " in class " + + clazz.getName(), e); + } catch (InvocationTargetException e) { + Throwable t = e.getTargetException(); + throw new XmlRpcException("Failed to invoke method " + + method.getName() + " in class " + + clazz.getName() + ": " + + t.getMessage(), t); + } + } +} \ No newline at end of file