gdaniels 02/03/30 20:15:32 Modified: java/src/org/apache/axis/description OperationDesc.java ServiceDesc.java java/src/org/apache/axis/message RPCElement.java java/src/org/apache/axis/providers/java RPCProvider.java java/src/org/apache/axis/utils resources.properties Added: java/test/inheritance Child.java PackageTests.java Parent.java TestInheritance.java Log: * First part of inheritance code in ServiceDesc - walk up the inheritance tree when syncing/creating methods, stopping at "java.*" or "javax.*" classes. Will add configurable "stop classes" to this soon. * Add unit test to make sure inheritance code works, and that we correctly resolve methods in a few situations. * Make code a little tighter in a few places, throw faults instead of potential NPEs Revision Changes Path 1.6 +3 -0 xml-axis/java/src/org/apache/axis/description/OperationDesc.java Index: OperationDesc.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/description/OperationDesc.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- OperationDesc.java 29 Mar 2002 23:25:45 -0000 1.5 +++ OperationDesc.java 31 Mar 2002 04:15:31 -0000 1.6 @@ -205,6 +205,9 @@ public ParameterDesc getParameter(int i) { + if (parameters.size() <= i) + return null; + return (ParameterDesc)parameters.get(i); } 1.10 +37 -6 xml-axis/java/src/org/apache/axis/description/ServiceDesc.java Index: ServiceDesc.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/description/ServiceDesc.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- ServiceDesc.java 29 Mar 2002 23:26:36 -0000 1.9 +++ ServiceDesc.java 31 Mar 2002 04:15:31 -0000 1.10 @@ -318,7 +318,7 @@ * 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) + private void syncOperationToClass(OperationDesc oper, Class implClass) { // If we're already mapped to a Java method, no need to do anything. if (oper.getMethod() != null) @@ -372,6 +372,13 @@ return; } } + + // Didn't find a match. Try the superclass, if appropriate + Class superClass = implClass.getSuperclass(); + if (!superClass.getName().startsWith("java.") && + !superClass.getName().startsWith("javax.")) { + syncOperationToClass(oper, superClass); + } } /** @@ -467,14 +474,14 @@ // 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 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); + syncOperationToClass(oper, implClass); } } } @@ -483,16 +490,40 @@ // 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); + } + + /** + * Look for methods matching this name, and for each one, create an + * OperationDesc (if it's not already in our list). + * + * TODO: Make this more efficient + */ + private void createOperationsForName(Class implClass, String methodName) + { Method [] methods = implClass.getDeclaredMethods(); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; - if (method.getName().equals(methodName)) + if (method.getName().equals(methodName)) { createOperationForMethod(method); + } } - // Note that we never have to look at this method name again. - completedNames.add(methodName); + Class superClass = implClass.getSuperclass(); + if (!superClass.getName().startsWith("java.") && + !superClass.getName().startsWith("javax.")) { + createOperationsForName(superClass, methodName); + } } /** 1.46 +3 -0 xml-axis/java/src/org/apache/axis/message/RPCElement.java Index: RPCElement.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/message/RPCElement.java,v retrieving revision 1.45 retrieving revision 1.46 diff -u -r1.45 -r1.46 --- RPCElement.java 27 Mar 2002 17:53:07 -0000 1.45 +++ RPCElement.java 31 Mar 2002 04:15:31 -0000 1.46 @@ -234,6 +234,9 @@ } } } + + throw new SAXException( + JavaUtils.getMessage("noSuchOperation", name)); } if (elementIsFirstParam) { 1.52 +5 -0 xml-axis/java/src/org/apache/axis/providers/java/RPCProvider.java Index: RPCProvider.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/providers/java/RPCProvider.java,v retrieving revision 1.51 retrieving revision 1.52 diff -u -r1.51 -r1.52 --- RPCProvider.java 29 Mar 2002 23:27:07 -0000 1.51 +++ RPCProvider.java 31 Mar 2002 04:15:31 -0000 1.52 @@ -153,6 +153,11 @@ operation = serviceDesc.getOperationByElementQName(qname); } + if (operation == null) { + throw new AxisFault(JavaUtils.getMessage("noSuchOperation", + methodName)); + } + // Create the array we'll use to hold the actual parameter // values. We know how big to make it from the metadata. Object[] argValues = new Object [operation.getNumParams()]; 1.86 +1 -0 xml-axis/java/src/org/apache/axis/utils/resources.properties Index: resources.properties =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/utils/resources.properties,v retrieving revision 1.85 retrieving revision 1.86 diff -u -r1.85 -r1.86 --- resources.properties 25 Mar 2002 04:44:02 -0000 1.85 +++ resources.properties 31 Mar 2002 04:15:31 -0000 1.86 @@ -795,3 +795,4 @@ badParameterMode=Invalid parameter mode byte ({0}) passed to getModeAsString(). attach.bounday.mns=Marking streams not supported. +noSuchOperation=No such operation ''{0}'' \ No newline at end of file 1.1 xml-axis/java/test/inheritance/Child.java Index: Child.java =================================================================== package test.inheritance; public class Child extends Parent { public static final String HELLO_MSG = "Hello from the Child class"; public static final String OVERLOAD_MSG = "The Child got "; public String normal() { return HELLO_MSG; } public String overloaded(int i) { return OVERLOAD_MSG + i; } } 1.1 xml-axis/java/test/inheritance/PackageTests.java Index: PackageTests.java =================================================================== /* * The Apache Software License, Version 1.1 * * * Copyright (c) 2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Axis" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package test.inheritance; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; public class PackageTests extends TestCase { public PackageTests(String name) { super(name); } public static Test suite() throws Exception { TestSuite suite = new TestSuite(); suite.addTestSuite(TestInheritance.class); return suite; } } 1.1 xml-axis/java/test/inheritance/Parent.java Index: Parent.java =================================================================== package test.inheritance; public class Parent { public static final String HELLO_MSG = "Hello from the Parent class!"; public static final String OVERLOAD_MSG = "The Parent got "; public String inherited() { return HELLO_MSG; } public String overloaded(String param) { return OVERLOAD_MSG + param; } } 1.1 xml-axis/java/test/inheritance/TestInheritance.java Index: TestInheritance.java =================================================================== package test.inheritance; import junit.framework.TestCase; import org.apache.axis.handlers.soap.SOAPService; import org.apache.axis.providers.java.RPCProvider; import org.apache.axis.configuration.SimpleProvider; import org.apache.axis.server.AxisServer; import org.apache.axis.transport.local.LocalTransport; import org.apache.axis.client.Call; import org.apache.axis.client.Service; public class TestInheritance extends TestCase { private AxisServer server; private LocalTransport transport; public TestInheritance(String s) { super(s); } protected void setUp() throws Exception { SimpleProvider config = new SimpleProvider(); SOAPService service = new SOAPService(new RPCProvider()); service.setOption("className", "test.inheritance.Child"); service.setOption("allowedMethods", "*"); config.deployService("inheritanceTest", service); server = new AxisServer(config); transport = new LocalTransport(server); transport.setRemoteService("inheritanceTest"); } public void testInheritance() throws Exception { Call call = new Call(new Service()); call.setTransport(transport); String ret = (String)call.invoke("inherited", null); assertEquals("Inherited method returned bad result", Parent.HELLO_MSG, ret); ret = (String)call.invoke("normal", null); assertEquals("Child method returned bad result", Child.HELLO_MSG, ret); ret = (String)call.invoke("overloaded", new Object [] { "test" }); assertTrue("Overloaded (String) method returned bad result", ret.startsWith(Parent.OVERLOAD_MSG)); ret = (String)call.invoke("overloaded", new Object [] { new Integer(5) }); assertTrue("Overloaded (int) method returned bad result", ret.startsWith(Child.OVERLOAD_MSG)); } }