Return-Path: Delivered-To: apmail-ws-axis-dev-archive@www.apache.org Received: (qmail 71456 invoked from network); 17 Nov 2006 04:02:29 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 17 Nov 2006 04:02:29 -0000 Received: (qmail 48139 invoked by uid 500); 17 Nov 2006 04:02:39 -0000 Delivered-To: apmail-ws-axis-dev-archive@ws.apache.org Received: (qmail 47875 invoked by uid 500); 17 Nov 2006 04:02:38 -0000 Mailing-List: contact axis-cvs-help@ws.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list axis-cvs@ws.apache.org Received: (qmail 47863 invoked by uid 500); 17 Nov 2006 04:02:38 -0000 Delivered-To: apmail-ws-axis2-cvs@ws.apache.org Received: (qmail 47858 invoked by uid 99); 17 Nov 2006 04:02:38 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 16 Nov 2006 20:02:38 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 16 Nov 2006 20:02:23 -0800 Received: by eris.apache.org (Postfix, from userid 65534) id CE8F91A984D; Thu, 16 Nov 2006 20:01:51 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r476045 [2/2] - in /webservices/axis2/trunk/java/modules/jaxws: src/org/apache/axis2/jaxws/ src/org/apache/axis2/jaxws/client/proxy/ src/org/apache/axis2/jaxws/description/impl/ src/org/apache/axis2/jaxws/i18n/ src/org/apache/axis2/jaxws/ma... Date: Fri, 17 Nov 2006 04:01:50 -0000 To: axis2-cvs@ws.apache.org From: scheu@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20061117040151.CE8F91A984D@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/MethodMarshallerUtils.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/MethodMarshallerUtils.java?view=diff&rev=476045&r1=476044&r2=476045 ============================================================================== --- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/MethodMarshallerUtils.java (original) +++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/MethodMarshallerUtils.java Thu Nov 16 20:01:48 2006 @@ -17,19 +17,52 @@ * under the License. */ package org.apache.axis2.jaxws.marshaller.impl.alt; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Future; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.ws.AsyncHandler; +import javax.xml.ws.Holder; +import javax.xml.ws.Response; import javax.xml.ws.WebServiceException; +import org.apache.axis2.jaxws.ExceptionFactory; import org.apache.axis2.jaxws.description.EndpointDescription; +import org.apache.axis2.jaxws.description.FaultDescription; import org.apache.axis2.jaxws.description.OperationDescription; +import org.apache.axis2.jaxws.description.ParameterDescription; import org.apache.axis2.jaxws.description.ServiceDescription; +import org.apache.axis2.jaxws.i18n.Messages; import org.apache.axis2.jaxws.marshaller.MethodMarshaller; import org.apache.axis2.jaxws.marshaller.impl.MethodMarshallerImpl; +import org.apache.axis2.jaxws.message.Block; import org.apache.axis2.jaxws.message.Message; +import org.apache.axis2.jaxws.message.MessageException; import org.apache.axis2.jaxws.message.Protocol; +import org.apache.axis2.jaxws.message.XMLFault; +import org.apache.axis2.jaxws.message.XMLFaultReason; +import org.apache.axis2.jaxws.message.databinding.JAXBBlockContext; +import org.apache.axis2.jaxws.message.factory.JAXBBlockFactory; +import org.apache.axis2.jaxws.message.util.MessageUtils; +import org.apache.axis2.jaxws.registry.FactoryRegistry; +import org.apache.axis2.jaxws.util.ClassUtils; +import org.apache.axis2.jaxws.util.XMLRootElementUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import javax.jws.WebParam.Mode; +import javax.jws.soap.SOAPBinding.Style; /** @@ -38,6 +71,9 @@ class MethodMarshallerUtils { private static Log log = LogFactory.getLog(MethodMarshallerUtils.class); + + private static JAXBBlockFactory factory = + (JAXBBlockFactory)FactoryRegistry.getFactory(JAXBBlockFactory.class); /** * Intentionally Private. This is a static utility class @@ -45,6 +81,571 @@ private MethodMarshallerUtils() { } + /** + * Returns the list of PDElements that need to be marshalled onto the wire + * + * @param params ParameterDescription for this operation + * @param sigArguments arguments + * @param isInput indicates if input or output params(input args on client, output args on server) + * @param usePartName indicates whether to use the partName or name for the name of the xml element + * partName is used for RPC and doc/lit wrapped, name is used for doc/lit bare + * @param forceXSIType if upgrading a type to an element + * @return PDElements + */ + static List getPDElements(ParameterDescription[] params, Object[] sigArguments, boolean isInput, boolean usePartName, boolean forceXSIType) { + List pvList = new ArrayList(); + + int index = 0; + for (int i=0; i getPDElements(ParameterDescription[] params, + Message message, + Set packages, + boolean isInput, + boolean usePartName) throws MessageException, XMLStreamException { + + List pvList = new ArrayList(); + + int index = 0; + for (int i=0; i pvList) + throws InstantiationException, IllegalAccessException, ClassNotFoundException { + Object[] args = new Object[pds.length]; + int pvIndex = 0; + for (int i=0; i< args.length; i++) { + // Get the paramValue + PDElement pv = (pvIndex < pvList.size()) ? pvList.get(pvIndex) : null; + ParameterDescription pd = pds[i]; + if (pv == null || + pv.getParam() != pd) { + // We have a ParameterDesc but there is not an equivalent PDElement. + // Provide the default + if (pd.isHolderType()) { + args[i] = createHolder(pd.getParameterType(), null); + } else { + args[i] = null; + } + } else { + + // We have a matching paramValue + Object value = pv.getElementValue(); + pvIndex++; + + // The signature wants the object that is rendered as the type + value = XMLRootElementUtil.getTypeEnabledObject(value); + + // The signature may want a holder representation + if (pd.isHolderType()) { + args[i] = createHolder(pd.getParameterType(), value); + } else { + args[i] = value; + } + } + + } + return args; + } + + /** + * Update the signature arguments on the client with the unmarshalled element enabled objects (pvList) + * @param pds ParameterDescriptions + * @param pvList Element Enabled objects + * @param signatureArgs Signature Arguments (the out/inout holders are updated) + * @throws InstantiationException + * @throws IllegalAccessException + * @throws ClassNotFoundException + */ + static void updateResponseSignatureArgs(ParameterDescription[] pds, List pvList, Object[] signatureArgs) + throws InstantiationException, IllegalAccessException, ClassNotFoundException { + int pvIndex = 0; + + // Each ParameterDescriptor has a correspondinging signatureArg from the + // the initial client call. The pvList contains the response values from the message. + // Walk the ParameterDescriptor/SignatureArg list and populate the holders with + // the match PDElement + for (int i=0; i< pds.length; i++) { + // Get the paramValue + PDElement pv = (pvIndex < pvList.size()) ? pvList.get(pvIndex) : null; + ParameterDescription pd = pds[i]; + if (pv != null && pv.getParam() == pd) { + // We have a matching paramValue + Object value = pv.getElementValue(); + pvIndex++; + + // The signature wants the object that is rendered as the type + value = XMLRootElementUtil.getTypeEnabledObject(value); + + // TODO Assert that this ParameterDescriptor must represent + // an OUT or INOUT and must have a non-null holder object to + // store the value + if (isHolder(signatureArgs[i])) { + ((Holder) signatureArgs[i]).value = value; + } + } + } + } + + /** + * Marshal the element enabled objects (pvList) to the Message + * @param pvList element enabled objects + * @param message Message + * @param packages Packages needed to do a JAXB Marshal + * @throws MessageException + */ + static void toMessage(List pvList, Message message, Set packages) throws MessageException { + + int index = message.getNumBodyBlocks(); + for (int i=0; i packages, + Message message, + boolean forceXSIType) + throws MessageException { + // If this type is an element rendering, then we are okay + // If it is a type rendering then make a JAXBElement + if (!XMLRootElementUtil.isElementEnabled(returnType)) { + returnValue = XMLRootElementUtil.getElementEnabledObject(returnNS, returnLocalPart,returnType, returnValue, forceXSIType); + } + + // Create a JAXBBlock out of the value. + Block block = factory.createFrom(returnValue, + new JAXBBlockContext(packages), + null); // The factory will get the qname from the value + message.setBodyBlock(0, block); + } + + /** + * Unmarshal the return object from the message + * @param packages + * @param message + * @return type enabled object + * @throws MessageException + * @throws XMLStreamException + */ + static Object getReturnValue(Set packages, Message message) + throws MessageException, XMLStreamException { + + + // The return object is the first block in the body + if (message.getStyle() == Style.RPC) { + // TODO add xsi type + } + Block block = message.getBodyBlock(0, new JAXBBlockContext(packages), factory); + + // Get the business object. We want to return the object that represents the type. + Object returnValue = block.getBusinessObject(true); + // The signature wants the object that is rendered as the type + returnValue = XMLRootElementUtil.getTypeEnabledObject(returnValue); + return returnValue; + } + + /** + * Utility method to get the Class representing the actual return type + * + * @param operationDesc + * @return actual return type + */ + static Class getActualReturnType(OperationDescription operationDesc){ + Method seiMethod = operationDesc.getSEIMethod(); + Class returnType = seiMethod.getReturnType(); + if(isAsync(operationDesc)){ + //pooling implementation + if(Response.class == returnType){ + Type type = seiMethod.getGenericReturnType(); + ParameterizedType pType = (ParameterizedType) type; + return (Class)pType.getActualTypeArguments()[0]; + } + //Callback Implementation + else{ + Type[] type = seiMethod.getGenericParameterTypes(); + Class parameters[]= seiMethod.getParameterTypes(); + int i=0; + for(Class param:parameters){ + if(AsyncHandler.class.isAssignableFrom(param)){ + ParameterizedType pType = (ParameterizedType)type[i]; + return (Class)pType.getActualTypeArguments()[0]; + } + i++; + } + } + + } + + return returnType; + } + + /** + * Marshaling a fault is essentially the same for rpc/lit and doc/lit. + * This method is used by all of the MethodMarshallers + * @param throwable Throwable to marshal + * @param operationDesc OperationDescription + * @param packages Packages needed to marshal the object + * @param message Message + * @param forceXSIType if the faultbean + * @throws MessageException + * @throws NoSuchMethodException + * @throws InvocationTargetException + * @throws IllegalAccessException + */ + static void marshalFaultResponse(Throwable throwable, OperationDescription operationDesc, Set packages, Message message, + boolean forceXSIType) + throws MessageException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { + + // Get the root cause of the throwable object + if (log.isDebugEnabled()) { + log.debug("Marshal Throwable =" + throwable.getClass().getName()); + log.debug(" message=" + throwable.getMessage()); + log.debug(" stack=" + MessageUtils.stackToString(throwable)); + } + Throwable t = ClassUtils.getRootCause(throwable); + + XMLFault xmlfault = null; + + // Get the FaultDescriptor matching this Exception. + // If FaultDescriptor is found, this is a JAX-B Service Exception. + // If not found, this is a System Exception + FaultDescription fd = operationDesc.resolveFaultByExceptionName(t.getClass().getName()); + + String text = null; + if (fd != null) { + // Service Exception. + + // Get the fault bean object. Make sure it can be rendered as an element + Method getFaultInfo = t.getClass().getMethod("getFaultInfo", null); + Object faultBeanObject = getFaultInfo.invoke(t, null); + if (!XMLRootElementUtil.isElementEnabled(faultBeanObject.getClass())) { + faultBeanObject = XMLRootElementUtil.getElementEnabledObject(fd.getTargetNamespace(), fd.getName(), + faultBeanObject.getClass(), faultBeanObject, forceXSIType); + } + + // Create a detailblock representing the faultBeanObject + JAXBBlockContext context = new JAXBBlockContext(packages); + Block[] detailBlocks = new Block[1]; + detailBlocks[0] = factory.createFrom(faultBeanObject,context,null); + + // Now make a XMLFault containing the detailblock + text = t.getMessage(); + xmlfault = new XMLFault(null, new XMLFaultReason(text), detailBlocks); + } else { + // System Exception + xmlfault = new XMLFault(null, // Use the default XMLFaultCode + new XMLFaultReason(text)); // Assumes text is the language supported by the current Locale + } + // Add the fault to the message + message.setXMLFault(xmlfault); + } + + /** + * Unmarshal the service/system exception from a Message. + * This is used by all of the marshallers + * @param operationDesc + * @param packages + * @param message + * @param isRPC + * @return Throwable + * @throws MessageException + * @throws ClassNotFoundException + * @throws IllegalAccessException + * @throws InstantiationException + * @throws XMLStreamException + * @throws InvocationTargetException + * @throws NoSuchMethodException + */ + static Throwable demarshalFaultResponse(OperationDescription operationDesc, Set packages,Message message, boolean isRPC) + throws MessageException, ClassNotFoundException, IllegalAccessException, + InstantiationException, XMLStreamException, InvocationTargetException, NoSuchMethodException { + + Throwable exception = null; + // Get the fault from the message and get the detail blocks (probably one) + XMLFault xmlfault = message.getXMLFault(); + Block[] detailBlocks = xmlfault.getDetailBlocks(); + + + if ((operationDesc.getFaultDescriptions().length == 0) || (detailBlocks == null)) { + // This is a system exception if the method does not throw a checked exception or if + // there is nothing in the detail element. + // Shouldn't this create + + // Create SystemException + // TODO shouldn't the exception capture the contents of the detail blocks + exception = createSystemException(xmlfault.getReason().getText()); + } else { + + // TODO what if there are multiple blocks in the detail ? + // We should create a generic fault with the appropriate detail + + // Get the JAXB object from the block + JAXBBlockContext blockContext = new JAXBBlockContext(packages); + + if (isRPC) { + //TODO add xsi:type + } + Block jaxbBlock = factory.createFrom(detailBlocks[0], blockContext); + Object faultBeanObject = jaxbBlock.getBusinessObject(true); + + // At this point, faultBeanObject is an object that can be rendered as an + // element. We want the object that represents the type. Also get the + // name of the element. + QName faultBeanQName = null; + if (faultBeanObject instanceof JAXBElement) { + faultBeanQName = ((JAXBElement)faultBeanObject).getName(); + faultBeanObject = ((JAXBElement)faultBeanObject).getValue(); + } else { + faultBeanQName = XMLRootElementUtil.getXmlRootElementQName(faultBeanObject); + } + + // Using the faultBeanQName, find the matching faultDescription + FaultDescription faultDesc = null; + for(int i=0; i + * @param paramType + * @param value + * @return + * @throws IllegalAccessException + * @throws InstantiationException + * @throws ClassNotFoundException + */ + static Holder createHolder(Class paramType, T value) throws IllegalAccessException, InstantiationException, ClassNotFoundException{ + if(Holder.class.isAssignableFrom(paramType)){ + Class holderClazz = loadClass(paramType.getName()); + Holder holder = (Holder) holderClazz.newInstance(); + holder.value = value; + return holder; + } + return null; + } + + /** + * Load the class + * @param className + * @return loaded class + * @throws ClassNotFoundException + */ + static Class loadClass(String className)throws ClassNotFoundException{ + // TODO J2W AccessController Needed + // Don't make this public, its a security exposure + return Class.forName(className, true, Thread.currentThread().getContextClassLoader()); + } + + /** Create a JAX-WS Service Exception (Generated Exception) + * @param message + * @param exceptionclass + * @param bean + * @param beanFormalType + * @return + * @throws InvocationTargetException + * @throws IllegalAccessException + * @throws InstantiationException + * @throws NoSuchMethodException + */ + private static Exception createServiceException(String message, Class exceptionclass, Object bean, Class beanFormalType) throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException { + // All webservice exception classes are required to have a constructor that takes a (String, bean) argument + // TODO necessary to be more careful here with instantiating, cassting, etc? + if (log.isDebugEnabled()) { + log.debug("Constructing JAX-WS Exception:" + exceptionclass); + } + Constructor constructor = exceptionclass.getConstructor(new Class[] { String.class, beanFormalType }); + Object exception = constructor.newInstance(new Object[] { message, bean }); + return (Exception) exception; + + } + + /** + * Create a system exception + * @param message + * @return + */ + private static Exception createSystemException(String message) { + return ExceptionFactory.makeWebServiceException(message); + } + + } Added: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/PDElement.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/PDElement.java?view=auto&rev=476045 ============================================================================== --- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/PDElement.java (added) +++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/PDElement.java Thu Nov 16 20:01:48 2006 @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.axis2.jaxws.marshaller.impl.alt; + +import org.apache.axis2.jaxws.description.ParameterDescription; + + +/** + * A PDElement object holds a ParameterDescription (Param) and + * the "Element" value. + * Characteristics of the "Element" value. + * * The Element value is ready for marshalling or is the result of unmarshalling. + * * The Element value represents the element rendering. Thus it is either + * a JAXBElement or has the @XmlRootElement annotation. (i.e. it is never a + * java.lang.String) + * * The Element value is not a JAX-WS object. (i.e. it is not a holder or exception) + */ +public class PDElement { + private ParameterDescription param; + private Object value; + + public PDElement(ParameterDescription param, Object value) { + super(); + this.param = param; + this.value = value; + } + + public ParameterDescription getParam() { + return param; + } + + public Object getElementValue() { + return value; + } + +} Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/RPCLitMethodMarshaller.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/RPCLitMethodMarshaller.java?view=diff&rev=476045&r1=476044&r2=476045 ============================================================================== --- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/RPCLitMethodMarshaller.java (original) +++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/RPCLitMethodMarshaller.java Thu Nov 16 20:01:48 2006 @@ -18,17 +18,23 @@ */ package org.apache.axis2.jaxws.marshaller.impl.alt; +import java.util.List; +import java.util.Set; + +import javax.jws.soap.SOAPBinding.Style; import javax.xml.namespace.QName; import javax.xml.ws.WebServiceException; import org.apache.axis2.jaxws.ExceptionFactory; import org.apache.axis2.jaxws.description.EndpointDescription; import org.apache.axis2.jaxws.description.OperationDescription; +import org.apache.axis2.jaxws.description.ParameterDescription; import org.apache.axis2.jaxws.description.ServiceDescription; import org.apache.axis2.jaxws.marshaller.MethodMarshaller; -import org.apache.axis2.jaxws.marshaller.impl.MethodMarshallerImpl; import org.apache.axis2.jaxws.message.Message; import org.apache.axis2.jaxws.message.Protocol; +import org.apache.axis2.jaxws.message.factory.MessageFactory; +import org.apache.axis2.jaxws.registry.FactoryRegistry; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -50,44 +56,222 @@ this.protocol = protocol; } - public Object demarshalResponse(Message message, Object[] inputArgs) - throws WebServiceException { + public Message marshalRequest(Object[] signatureArguments) throws WebServiceException { // Note all exceptions are caught and rethrown with a WebServiceException try { - // TODO Add Real Code - throw new UnsupportedOperationException(); + + // Sample RPC message + // .. + // + // + // ... + // + // + // + // Important points. + // 1) RPC has an operation element under the body. This is the name of the + // wsdl operation. + // 2) The data blocks are located underneath the operation element. (In doc/lit + // the data elements are underneath the body. + // 3) The name of the data blocks (m:param) are defined by the wsdl:part not the + // schema. + // 4) The type of the data block (data:foo) is defined by schema (thus there is + // JAXB type rendering. Since we are using JAXB to marshal the data, + // we always generate an xsi:type attribute. This is an implemenation detail + // and is not defined by any spec. + + + // Get the operation information + ParameterDescription[] pds =operationDesc.getParameterDescriptions(); + Set packages = endpointDesc.getPackages(); + + // Create the message + MessageFactory mf = (MessageFactory)FactoryRegistry.getFactory(MessageFactory.class); + Message m = mf.create(protocol); + + // Indicate the style and operation element name. This triggers the message to + // put the data blocks underneath the operation element + m.setStyle(Style.RPC); + m.setOperationElement(operationDesc.getName()); + + // The input object represent the signature arguments. + // Signature arguments are both holders and non-holders + // Convert the signature into a list of JAXB objects for marshalling + List pvList = + MethodMarshallerUtils.getPDElements(pds, + signatureArguments, + true, // input + true, // use partName since this is rpc/lit + true); // always force xsi:type since this is rpc/lit + + // Put values onto the message + MethodMarshallerUtils.toMessage(pvList, m, packages); + + return m; } catch(Exception e) { throw ExceptionFactory.makeWebServiceException(e); } } - + public Object[] demarshalRequest(Message message) - throws WebServiceException { + throws WebServiceException { // Note all exceptions are caught and rethrown with a WebServiceException try { - // TODO Add Real Code - throw new UnsupportedOperationException(); + // Sample RPC message + // .. + // + // + // ... + // + // + // + // Important points. + // 1) RPC has an operation element under the body. This is the name of the + // wsdl operation. + // 2) The data blocks are located underneath the operation element. (In doc/lit + // the data elements are underneath the body. + // 3) The name of the data blocks (m:param) are defined by the wsdl:part not the + // schema. + // 4) The type of the data block (data:foo) is defined by schema (thus there is + // JAXB type rendering. + // 5) We always send an xsi:type, but other vendor's may not. + // Get the operation information + ParameterDescription[] pds =operationDesc.getParameterDescriptions(); + Set packages = endpointDesc.getPackages(); + + // Indicate that the style is RPC. This is important so that the message understands + // that the data blocks are underneath the operation element + message.setStyle(Style.RPC); + + // Unmarshal the ParamValues from the Message + List pvList = MethodMarshallerUtils.getPDElements(pds, message, packages, true, true); + + // Build the signature arguments + Object[] sigArguments = MethodMarshallerUtils.createRequestSignatureArgs(pds, pvList); + + return sigArguments; } catch(Exception e) { throw ExceptionFactory.makeWebServiceException(e); } } - public Message marshalResponse(Object returnObject, Object[] holderObjects) + + + public Message marshalResponse(Object returnObject, Object[] signatureArgs) throws WebServiceException { // Note all exceptions are caught and rethrown with a WebServiceException try { - // TODO Add Real Code - throw new UnsupportedOperationException(); + // Sample RPC message + // .. + // + // + // ... + // + // + // + // Important points. + // 1) RPC has an operation element under the body. This is the name of the + // wsdl operation. + // 2) The data blocks are located underneath the operation element. (In doc/lit + // the data elements are underneath the body. + // 3) The name of the data blocks (m:param) are defined by the wsdl:part not the + // schema. + // 4) The type of the data block (data:foo) is defined by schema (thus there is + // JAXB type rendering. Since we are using JAXB to marshal the data, + // we always generate an xsi:type attribute. This is an implemenation detail + // and is not defined by any spec. + + // Get the operation information + ParameterDescription[] pds =operationDesc.getParameterDescriptions(); + Set packages = endpointDesc.getPackages(); + + // Create the message + MessageFactory mf = (MessageFactory)FactoryRegistry.getFactory(MessageFactory.class); + Message m = mf.create(protocol); + + // Indicate the style and operation element name. This triggers the message to + // put the data blocks underneath the operation element + m.setStyle(Style.RPC); + + // TODO Is there an annotation for the operation element response ? + String localPart = operationDesc.getName().getLocalPart() + "Response"; + QName responseOp = new QName(operationDesc.getName().getNamespaceURI(), localPart); + m.setOperationElement(responseOp); + + // Put the return object onto the message + Class returnType = MethodMarshallerUtils.getActualReturnType(operationDesc); + if (returnType != void.class) { + MethodMarshallerUtils.toMessage(returnObject, + returnType, + operationDesc.getResultTargetNamespace(), + operationDesc.getResultPartName(), + packages, + m, + true); // forceXSI since this is rpc/lit + } + + // Convert the holder objects into a list of JAXB objects for marshalling + List pvList = + MethodMarshallerUtils.getPDElements(pds, + signatureArgs, + false, // output + true, // use partName since this is rpc/lit + true); // forceXSI since this is rpc/lit + + // Put values onto the message + MethodMarshallerUtils.toMessage(pvList, m, packages); + + return m; } catch(Exception e) { throw ExceptionFactory.makeWebServiceException(e); } } - public Message marshalRequest(Object[] object) throws WebServiceException { + + public Object demarshalResponse(Message message, Object[] signatureArgs) + throws WebServiceException { // Note all exceptions are caught and rethrown with a WebServiceException try { - // TODO Add Real Code - throw new UnsupportedOperationException(); + // Sample RPC message + // .. + // + // + // ... + // + // + // + // Important points. + // 1) RPC has an operation element under the body. This is the name of the + // wsdl operation. + // 2) The data blocks are located underneath the operation element. (In doc/lit + // the data elements are underneath the body. + // 3) The name of the data blocks (m:param) are defined by the wsdl:part not the + // schema. + // 4) The type of the data block (data:foo) is defined by schema (thus there is + // JAXB type rendering. + // 5) We always send an xsi:type, but other vendor's may not. + // Get the operation information + ParameterDescription[] pds =operationDesc.getParameterDescriptions(); + Set packages = endpointDesc.getPackages(); + + // Indicate that the style is RPC. This is important so that the message understands + // that the data blocks are underneath the operation element + message.setStyle(Style.RPC); + + // Get the return value. + Class returnType = MethodMarshallerUtils.getActualReturnType(operationDesc); + Object returnValue = null; + if (returnType != void.class) { + returnValue = MethodMarshallerUtils.getReturnValue(packages, message); + } + + // Unmarshall the ParamValues from the Message + List pvList = MethodMarshallerUtils.getPDElements(pds, message, packages, false, true); + + // Populate the response Holders + MethodMarshallerUtils.updateResponseSignatureArgs(pds, pvList, signatureArgs); + + return returnValue; } catch(Exception e) { throw ExceptionFactory.makeWebServiceException(e); } @@ -96,18 +280,27 @@ public Message marshalFaultResponse(Throwable throwable) throws WebServiceException { // Note all exceptions are caught and rethrown with a WebServiceException try { - // TODO Add Real Code - throw new UnsupportedOperationException(); + // Create the message + MessageFactory mf = (MessageFactory)FactoryRegistry.getFactory(MessageFactory.class); + Message m = mf.create(protocol); + + // Put the fault onto the message + MethodMarshallerUtils.marshalFaultResponse(throwable, + operationDesc, + endpointDesc.getPackages(), + m, + true); // always marshal xsi:type if rpc/lit + return m; } catch(Exception e) { throw ExceptionFactory.makeWebServiceException(e); } } - public Object demarshalFaultResponse(Message message) throws WebServiceException { + public Throwable demarshalFaultResponse(Message message) throws WebServiceException { // Note all exceptions are caught and rethrown with a WebServiceException try { - // TODO Add Real Code - throw new UnsupportedOperationException(); + Throwable t = MethodMarshallerUtils.demarshalFaultResponse(operationDesc, endpointDesc.getPackages(), message, true); + return t; } catch(Exception e) { throw ExceptionFactory.makeWebServiceException(e); } Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/impl/JAXBBlockFactoryImpl.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/impl/JAXBBlockFactoryImpl.java?view=diff&rev=476045&r1=476044&r2=476045 ============================================================================== --- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/impl/JAXBBlockFactoryImpl.java (original) +++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/impl/JAXBBlockFactoryImpl.java Thu Nov 16 20:01:48 2006 @@ -29,7 +29,7 @@ import org.apache.axis2.jaxws.message.databinding.JAXBBlockContext; import org.apache.axis2.jaxws.message.factory.JAXBBlockFactory; import org.apache.axis2.jaxws.message.impl.BlockFactoryImpl; -import org.apache.axis2.jaxws.util.ClassUtils; +import org.apache.axis2.jaxws.util.XMLRootElementUtil; /** * JAXBBlockFactoryImpl @@ -77,7 +77,7 @@ // The business object must be either a JAXBElement or a block with an @XmlRootElement qname. The best way // to verify this is to get the QName from the business object. - QName bQName = ClassUtils.getXmlRootElementQName(businessObject); + QName bQName = XMLRootElementUtil.getXmlRootElementQName(businessObject); if (bQName == null) { throw ExceptionFactory.makeMessageException(Messages.getMessage("JAXBBlockFactoryErr2", businessObject.getClass().getName()), null); } Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/impl/JAXBBlockImpl.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/impl/JAXBBlockImpl.java?view=diff&rev=476045&r1=476044&r2=476045 ============================================================================== --- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/impl/JAXBBlockImpl.java (original) +++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/impl/JAXBBlockImpl.java Thu Nov 16 20:01:48 2006 @@ -44,7 +44,7 @@ import org.apache.axis2.jaxws.message.databinding.JAXBUtils; import org.apache.axis2.jaxws.message.factory.BlockFactory; import org.apache.axis2.jaxws.message.impl.BlockImpl; -import org.apache.axis2.jaxws.util.ClassUtils; +import org.apache.axis2.jaxws.util.XMLRootElementUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -110,7 +110,7 @@ jaxb = u.unmarshal(reader); // Set the qname - QName qName = ClassUtils.getXmlRootElementQName(jaxb); + QName qName = XMLRootElementUtil.getXmlRootElementQName(jaxb); if (qName != null) { // qname should always be non-null setQName(qName); } Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/util/MessageUtils.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/util/MessageUtils.java?view=diff&rev=476045&r1=476044&r2=476045 ============================================================================== --- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/util/MessageUtils.java (original) +++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/util/MessageUtils.java Thu Nov 16 20:01:48 2006 @@ -96,7 +96,7 @@ equals(e.getNamespace().getNamespaceURI())) { return OMAbstractFactory.getSOAP11Factory(); } else { - return OMAbstractFactory.getSOAP11Factory(); + return OMAbstractFactory.getSOAP12Factory(); } } return null; Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/JAXWSMessageReceiver.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/JAXWSMessageReceiver.java?view=diff&rev=476045&r1=476044&r2=476045 ============================================================================== --- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/JAXWSMessageReceiver.java (original) +++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/JAXWSMessageReceiver.java Thu Nov 16 20:01:48 2006 @@ -124,7 +124,6 @@ } } catch (Exception e) { - // TODO NLS ThreadContextMigratorUtil.performThreadCleanup(Constants.THREAD_CONTEXT_MIGRATOR_LIST_ID, axisRequestMsgCtx); throw ExceptionFactory.makeWebServiceException(e); } Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/dispatcher/JavaBeanDispatcher.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/dispatcher/JavaBeanDispatcher.java?view=diff&rev=476045&r1=476044&r2=476045 ============================================================================== --- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/dispatcher/JavaBeanDispatcher.java (original) +++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/dispatcher/JavaBeanDispatcher.java Thu Nov 16 20:01:48 2006 @@ -80,6 +80,19 @@ response = target.invoke(serviceInstance, methodInputParams); } catch (Exception e) { response = e; + if (log.isDebugEnabled()) { + log.debug("Exception invoking a method of " + + serviceImplClass.toString() + " of instance " + + serviceInstance.toString()); + + log.debug("Method = " + target.toGenericString()); + + for (int i=0; i + + // Kinds of generated classes: Service, Provider, Impl, Exception, Holder // Or the class is in the jaxws.xml.ws package @@ -367,65 +367,6 @@ return true; } return false; - } - - - /** - * @param clazz - * @return namespace of root element qname or null if this is not object does not represent a root element - */ - public static QName getXmlRootElementQName(Object obj){ - - // A JAXBElement stores its name - if (obj instanceof JAXBElement) { - return ((JAXBElement) obj).getName(); - } - - Class clazz = obj.getClass(); - - // If the clazz is a primitive, then it does not have a corresponding root element. - if (clazz.isPrimitive() || - getWrapperClass(clazz) != null) { - return null; - } - - // See if the object represents a root element - XmlRootElement root = (XmlRootElement) clazz.getAnnotation(XmlRootElement.class); - if (root == null) { - return null; - } - - String namespace = root.namespace(); - String localPart = root.name(); - - // The namespace may need to be defaulted - if (namespace == null || namespace.length() == 0 || namespace.equals("##default")) { - Package pkg = clazz.getPackage(); - XmlSchema schema = (XmlSchema) pkg.getAnnotation(XmlSchema.class); - if (schema != null) { - namespace = schema.namespace(); - } else { - return null; - } - } - return new QName(namespace, localPart); - } - - /** - * @param clazz - * @return true if this class has a corresponding xml root element - */ - public static boolean isXmlRootElementDefined(Class clazz){ - // If the clazz is a primitive, then it does not have a corresponding root element. - if (clazz.isPrimitive() || - getWrapperClass(clazz) != null) { - return false; - } - // TODO We could also prune out other known classes that will not have root elements defined. - // java.util.Date, arrays, java.math.BigInteger. - - XmlRootElement root = (XmlRootElement) clazz.getAnnotation(XmlRootElement.class); - return root !=null; } } Added: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/util/XMLRootElementUtil.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/util/XMLRootElementUtil.java?view=auto&rev=476045 ============================================================================== --- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/util/XMLRootElementUtil.java (added) +++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/util/XMLRootElementUtil.java Thu Nov 16 20:01:48 2006 @@ -0,0 +1,268 @@ +/* + * Copyright 2004,2005 The Apache Software Foundation. + * Copyright 2006 International Business Machines Corp. + * + * 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.axis2.jaxws.util; + +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.util.Map; +import java.util.WeakHashMap; + +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.namespace.QName; + +/** + * This utility contains code to determine if an Object is + * "element enabled" or "type enabled". + * + * Here is an example for illustration: + * + * ... + * + * + * + * .. + * + * + * .. + * + * JAXB will generate the following objects: E1, T2, E3 + * E1 will have an @XMLRootElement annotation. It is "element" and "type" enabled. + * e2 does not have a generated object. So it will be represented as a JAXBElement + * that contains an object T2. The JAXBElement is "element" enabled. + * T2 represents a complexType. It is only "type" enabled. + * E3 represents the e3 complexType (it does not represent the e3 element). Thus E3 + * is "type enabled". + * + * When JAXB unmarshals an object, it will return an "element" enabled object (either + * a generatated object with @XMLRootElement or a JAXBElement). + * Conversely, you must always marshal "element" enabled objects. + * @see org.apache.axis2.jaxws.marshaller.impl.alt.PDElement + * + * At the signature level, the values passed as arguments in an SEI operation represent + * type enabled objects. Each of the object must be converted to an element enabled object + * to marshal (or conversely converted to a type enabled object when unmarshalling) + * + * ----------------------------------------- + * There are other simular utility methods in this class. Including utilities to get + * a xml name -> bean property map. + * + * ----------------------------------------- + * + * @TODO A secondary reason usage of XMLRootElementUtil is to isolate all of the + * @XMLRootElement and related annotation queries. Annotation queries are expensive. + * A follow-on version of this class will cache the results so that we can improve performance. + * + */ +public class XMLRootElementUtil { + + /** + * Constructor is intentionally private. This class only provides static utility methods + */ + private XMLRootElementUtil() { + + } + + /** + * Return true if this class is element enabled + * @param clazz + * @return true if this class has a corresponding xml root element + */ + public static boolean isElementEnabled(Class clazz){ + if (clazz.equals(JAXBElement.class)) { + return true; + } + + // If the clazz is a primitive, then it does not have a corresponding root element. + if (clazz.isPrimitive() || ClassUtils.getWrapperClass(clazz) != null) { + return false; + } + + // Presence of an annotation means that it can be rendered as a root element + XmlRootElement root = (XmlRootElement) clazz.getAnnotation(XmlRootElement.class); + return root !=null; + } + + /** + * Returns ture if this class is type enabled + * @param clazz + * @return + */ + public static boolean isTypeEnabled(Class clazz) { + // Primitives, Primitive wrappers, BigDecimal, etc. are all type enabled + // So are all classes with @XmlRootElement or @XmlType. + // For now I am only going to assume that the class is type enabled unless it is JAXBElement + return (!clazz.equals(JAXBElement.class)); + } + + /** + * Return type enabled object + * @param obj type or element enabled object + * @return type enabled object + */ + public static Object getTypeEnabledObject(Object obj) { + if (obj == null) { + return null; + } + if (obj instanceof JAXBElement) { + return ((JAXBElement) obj).getValue(); + } + return obj; + } + + /** + * Return an object that can be marshalled/unmarshalled as an element + * If the specified object is already element enabled, it is returned. + * @param namespace + * @param localPart + * @param cls either the class or super class of obj + * @param type element or type enabled object + * @return + */ + public static Object getElementEnabledObject(String namespace, String localPart, Class cls, Object obj, boolean forceXSIType) { + if (obj != null && isElementEnabled(obj.getClass())) { + return obj; + } + + QName qName = new QName(namespace, localPart); + + // I think the way to force an xsi:type is to use Object as the class + if (forceXSIType) { + cls = Object.class; + } + JAXBElement element = new JAXBElement(qName, cls, obj); + return element; + } + + + + /** + * @param clazz + * @return namespace of root element qname or null if this is not object does not represent a root element + */ + public static QName getXmlRootElementQName(Object obj){ + + // A JAXBElement stores its name + if (obj instanceof JAXBElement) { + return ((JAXBElement) obj).getName(); + } + + Class clazz = obj.getClass(); + + // If the clazz is a primitive, then it does not have a corresponding root element. + if (clazz.isPrimitive() || + ClassUtils.getWrapperClass(clazz) != null) { + return null; + } + + // See if the object represents a root element + XmlRootElement root = (XmlRootElement) clazz.getAnnotation(XmlRootElement.class); + if (root == null) { + return null; + } + + String namespace = root.namespace(); + String localPart = root.name(); + + // The namespace may need to be defaulted + if (namespace == null || namespace.length() == 0 || namespace.equals("##default")) { + Package pkg = clazz.getPackage(); + XmlSchema schema = (XmlSchema) pkg.getAnnotation(XmlSchema.class); + if (schema != null) { + namespace = schema.namespace(); + } else { + return null; + } + } + return new QName(namespace, localPart); + } + + + /** + * The JAXBClass has a set of bean properties each represented by a PropertyDescriptor + * Each of the fields of the class has an associated xml name. + * The method returns a map where the key is the xml name and value is the PropertyDescriptor + * @param jaxbClass + * @return map + */ + public static Map createPropertyDescriptorMap(Class jaxbClass) throws NoSuchFieldException, IntrospectionException { + + // TODO This is a very performance intensive search we should cache the calculated map keyed by the jaxbClass + + PropertyDescriptor[] pds = Introspector.getBeanInfo(jaxbClass).getPropertyDescriptors(); + // Make this a weak map in case we want to cache the resolts + Map map = new WeakHashMap(); + + // Unfortunately the element names are stored on the fields. + // Therefore we need to to match up the field and property descriptor + Field[] fields = jaxbClass.getDeclaredFields(); + for(PropertyDescriptor pd:pds){ + for(Field field:fields){ + String fieldName = field.getName(); + + // Use the name of the field and property to find the match + if (fieldName.equalsIgnoreCase(pd.getDisplayName()) || + fieldName.equalsIgnoreCase(pd.getName()) ) { + // Get the xmlElement name for this field + String xmlName =getXmlElementName(jaxbClass, field); + map.put(xmlName, pd); + break; + } + + // Unfortunately, sometimes the field name is preceeded by an underscore + if (fieldName.startsWith("_")) { + fieldName = fieldName.substring(1); + if (fieldName.equalsIgnoreCase(pd.getDisplayName()) || + fieldName.equalsIgnoreCase(pd.getName())) { + // Get the xmlElement name for this field + String xmlName =getXmlElementName(jaxbClass, field); + map.put(xmlName, pd); + break; + } + } + } + } + return map; + } + + /** + * Get the name of the field by looking at the XmlElement annotation. + * @param jaxbClass + * @param fieldName + * @return + * @throws NoSuchFieldException + */ + private static String getXmlElementName(Class jaxbClass, Field field)throws NoSuchFieldException{ + XmlElement xmlElement =field.getAnnotation(XmlElement.class); + + + // If XmlElement does not exist, default to using the field name + if (xmlElement == null || + xmlElement.name().equals("##default")) { + return field.getName(); + } + return xmlElement.name(); + + } + + + +} Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/JAXBWrapperTool.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/JAXBWrapperTool.java?view=diff&rev=476045&r1=476044&r2=476045 ============================================================================== --- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/JAXBWrapperTool.java (original) +++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/JAXBWrapperTool.java Thu Nov 16 20:01:48 2006 @@ -17,7 +17,7 @@ package org.apache.axis2.jaxws.wrapper; -import java.util.ArrayList; +import java.util.List; import java.util.Map; import org.apache.axis2.jaxws.wrapper.impl.JAXBWrapperException; @@ -34,9 +34,9 @@ * @param jaxbObject that is the wrapper element (JAXBElement or object with @XMLRootElement) * @param jaxbContext JAXBContext * @param childNames list of xml child names as String - * @return list of Objects in the same order as the element names. + * @return list of Objects in the same order as the element names. */ - public Object[] unWrap(Object jaxbObject, ArrayList childNames) throws JAXBWrapperException; + public Object[] unWrap(Object jaxbObject, List childNames) throws JAXBWrapperException; /** @@ -46,11 +46,10 @@ * Note that the jaxbClass must be the class the represents the complexType. (It should never be JAXBElement) * * @param jaxbClass - * @param childObjects, component objects + * @param childObjects, component type objects * @param childNames list of xml child names as String - * @return list of Objects in the same order as the element names. */ - public Object wrap(Class jaxbClass, ArrayList childNames, Map childObjects) throws JAXBWrapperException; + public Object wrap(Class jaxbClass, List childNames, Map childObjects) throws JAXBWrapperException; } Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/impl/JAXBWrapperToolImpl.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/impl/JAXBWrapperToolImpl.java?view=diff&rev=476045&r1=476044&r2=476045 ============================================================================== --- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/impl/JAXBWrapperToolImpl.java (original) +++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/impl/JAXBWrapperToolImpl.java Thu Nov 16 20:01:48 2006 @@ -23,6 +23,7 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.WeakHashMap; @@ -30,6 +31,7 @@ import javax.xml.bind.annotation.XmlElement; import org.apache.axis2.jaxws.i18n.Messages; +import org.apache.axis2.jaxws.util.XMLRootElementUtil; import org.apache.axis2.jaxws.wrapper.JAXBWrapperTool; @@ -45,7 +47,7 @@ */ public Object[] unWrap(Object jaxbObject, - ArrayList childNames) throws JAXBWrapperException{ + List childNames) throws JAXBWrapperException{ try{ if(jaxbObject == null){ throw new JAXBWrapperException(Messages.getMessage("JAXBWrapperErr1")); @@ -54,6 +56,7 @@ throw new JAXBWrapperException(Messages.getMessage("JAXBWrapperErr2")); } + // Review: I think that we can remove the next statement. This is an assertion of the tool // Get the object that will have the property descriptors (i.e. the object representing the complexType) Object jaxbComplexTypeObj = (jaxbObject instanceof JAXBElement) ? ((JAXBElement)jaxbObject).getValue() : // Type object is the value of the JAXBElement @@ -84,7 +87,7 @@ * @see org.apache.axis2.jaxws.wrapped.JAXBWrapperTool#wrap(java.lang.Class, java.lang.String, java.util.ArrayList, java.util.ArrayList) */ public Object wrap(Class jaxbClass, - ArrayList childNames, Map childObjects) + List childNames, Map childObjects) throws JAXBWrapperException { try{ @@ -120,91 +123,40 @@ * childName if not use xmlElement annotation name and create PropertyInfo add childName or xmlElement name there, set propertyDescriptor * and return Map. * @param jaxbClass - Class jaxbClass name - * @param childNames - ArrayList of childNames + * @param childNames - ArrayList of xml childNames * @return Map - map of ChildNames that map to PropertyInfo that hold the propertyName and PropertyDescriptor. * @throws IntrospectionException, NoSuchFieldException */ - private Map createPropertyDescriptors(Class jaxbClass, ArrayList childNames) throws IntrospectionException, NoSuchFieldException, JAXBWrapperException{ + private Map createPropertyDescriptors(Class jaxbClass, List childNames) throws IntrospectionException, NoSuchFieldException, JAXBWrapperException{ Map map = new WeakHashMap(); - PropertyDescriptor[] pds = Introspector.getBeanInfo(jaxbClass).getPropertyDescriptors(); - Map jaxbClassPds = filterDescriptors(pds, jaxbClass); + + Map pdMap = XMLRootElementUtil.createPropertyDescriptorMap(jaxbClass); Field field[] = jaxbClass.getDeclaredFields(); - if(field.length != childNames.size()){ + + // It is possible the that the number of fields is greater than the number of child elements due + // to customizations. + if(field.length < childNames.size()){ throw new JAXBWrapperException(Messages.getMessage("JAXBWrapperErr4", jaxbClass.getName())); } - pds=null; + + + // Create property infos for each class name + for (int i=0; i filterDescriptors(PropertyDescriptor[] allPds, Class jaxbClass) throws NoSuchFieldException{ - Map filteredPds = new WeakHashMap(); - Field[] fields = jaxbClass.getDeclaredFields(); - for(PropertyDescriptor pd:allPds){ - for(Field field:fields){ - if(field.getName().equals(pd.getDisplayName())){ - filteredPds.put(pd.getDisplayName(), pd); - break; - }else{ - String xmlName =getXmlElementName(jaxbClass, field.getName()); - if(xmlName.equals(pd.getDisplayName())){ - filteredPds.put(field.getName(), pd); - break; - } - if(xmlName.toLowerCase().equals(pd.getDisplayName().toLowerCase())){ - filteredPds.put(field.getName(), pd); - break; - } - } - } - } - allPds=null; - return filteredPds; - } - /** - * Get the name of the xml element by looking at the XmlElement annotation. - * @param jaxbClass - * @param fieldName - * @return - * @throws NoSuchFieldException - */ - private String getXmlElementName(Class jaxbClass, String fieldName)throws NoSuchFieldException{ - Field field = jaxbClass.getDeclaredField(fieldName); - XmlElement xmlElement =field.getAnnotation(XmlElement.class); - - // If XmlElement does not exist, default to using the field name - if (xmlElement == null) { - return fieldName; - } - return xmlElement.name(); - - } } Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/impl/PropertyInfo.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/impl/PropertyInfo.java?view=diff&rev=476045&r1=476044&r2=476045 ============================================================================== --- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/impl/PropertyInfo.java (original) +++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/impl/PropertyInfo.java Thu Nov 16 20:01:48 2006 @@ -25,30 +25,44 @@ import org.apache.commons.logging.LogFactory; +/** + * A PropertyInfo is constructed with a PropertyDescriptor and + * exposes get/set methods to access the object on a bean that matches the PropertyDescriptor + * + */ public class PropertyInfo { - String propertyName; PropertyDescriptor descriptor; private static Log log = LogFactory.getLog(PropertyInfo.class); /** * @param propertyName * @param descriptor */ - public PropertyInfo(String propertyName, PropertyDescriptor descriptor) { + public PropertyInfo(PropertyDescriptor descriptor) { super(); - - this.propertyName = propertyName; this.descriptor = descriptor; } - public String getPropertyName(){ - return this.propertyName; - } + /** + * Get the object + * @param targetBean + * @return Object for this property or null + * @throws InvocationTargetException + * @throws IllegalAccessException + */ public Object get(Object targetBean)throws InvocationTargetException, IllegalAccessException{ Method method = descriptor.getReadMethod(); return method.invoke(targetBean, null); } + /** + * Set the object + * @param targetBean + * @param propValue + * @throws InvocationTargetException + * @throws IllegalAccessException + * @throws JAXBWrapperException + */ public void set(Object targetBean, Object propValue)throws InvocationTargetException, IllegalAccessException, JAXBWrapperException{ Method method = descriptor.getWriteMethod(); Object[] object = new Object[]{propValue}; Modified: webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/message/MessageRPCTests.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/message/MessageRPCTests.java?view=diff&rev=476045&r1=476044&r2=476045 ============================================================================== --- webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/message/MessageRPCTests.java (original) +++ webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/message/MessageRPCTests.java Thu Nov 16 20:01:48 2006 @@ -300,7 +300,11 @@ // Check to make sure the right object was returned assertNotNull(bo); + if (bo instanceof JAXBElement) { + bo = ((JAXBElement) bo).getValue(); + } assertTrue(bo instanceof StockPrice); + // Check to make sure the content of that object is correct StockPrice obj = (StockPrice) bo; Modified: webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/AddressBookTests.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/AddressBookTests.java?view=diff&rev=476045&r1=476044&r2=476045 ============================================================================== --- webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/AddressBookTests.java (original) +++ webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/AddressBookTests.java Thu Nov 16 20:01:48 2006 @@ -49,6 +49,7 @@ * Test the endpoint by invoking it with a JAX-WS Dispatch. */ public void testAddressBookWithDispatch() throws Exception { + try { System.out.println("----------------------------------"); System.out.println("test: " + getName()); @@ -80,6 +81,10 @@ assertTrue(response.isStatus()); System.out.println("[pass] - valid response received"); System.out.println("[response] - " + response.isStatus()); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } } /** --------------------------------------------------------------------- To unsubscribe, e-mail: axis-cvs-unsubscribe@ws.apache.org For additional commands, e-mail: axis-cvs-help@ws.apache.org