You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicemix.apache.org by gn...@apache.org on 2006/11/23 15:53:10 UTC

svn commit: r478592 - /incubator/servicemix/trunk/deployables/serviceengines/servicemix-jsr181/src/main/java/org/apache/servicemix/jsr181/xfire/ServiceFactoryHelper.java

Author: gnodet
Date: Thu Nov 23 06:53:04 2006
New Revision: 478592

URL: http://svn.apache.org/viewvc?view=rev&rev=478592
Log:
SM-754: Issues with jsr181 proxies using jaxws + doc/lit wrapped.
This fix should be in xfire, but in the mean time ...

Modified:
    incubator/servicemix/trunk/deployables/serviceengines/servicemix-jsr181/src/main/java/org/apache/servicemix/jsr181/xfire/ServiceFactoryHelper.java

Modified: incubator/servicemix/trunk/deployables/serviceengines/servicemix-jsr181/src/main/java/org/apache/servicemix/jsr181/xfire/ServiceFactoryHelper.java
URL: http://svn.apache.org/viewvc/incubator/servicemix/trunk/deployables/serviceengines/servicemix-jsr181/src/main/java/org/apache/servicemix/jsr181/xfire/ServiceFactoryHelper.java?view=diff&rev=478592&r1=478591&r2=478592
==============================================================================
--- incubator/servicemix/trunk/deployables/serviceengines/servicemix-jsr181/src/main/java/org/apache/servicemix/jsr181/xfire/ServiceFactoryHelper.java (original)
+++ incubator/servicemix/trunk/deployables/serviceengines/servicemix-jsr181/src/main/java/org/apache/servicemix/jsr181/xfire/ServiceFactoryHelper.java Thu Nov 23 06:53:04 2006
@@ -16,20 +16,61 @@
  */
 package org.apache.servicemix.jsr181.xfire;
 
-import java.lang.reflect.Constructor;
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
+import javax.jws.WebMethod;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.ws.RequestWrapper;
+import javax.xml.ws.ResponseWrapper;
+import javax.xml.ws.WebFault;
+
+import org.codehaus.xfire.MessageContext;
 import org.codehaus.xfire.XFire;
+import org.codehaus.xfire.XFireRuntimeException;
 import org.codehaus.xfire.aegis.AegisBindingProvider;
+import org.codehaus.xfire.aegis.stax.ElementReader;
+import org.codehaus.xfire.aegis.stax.ElementWriter;
 import org.codehaus.xfire.aegis.type.DefaultTypeMappingRegistry;
+import org.codehaus.xfire.aegis.type.Type;
 import org.codehaus.xfire.aegis.type.TypeMappingRegistry;
 import org.codehaus.xfire.annotations.AnnotationServiceFactory;
 import org.codehaus.xfire.annotations.WebAnnotations;
 import org.codehaus.xfire.annotations.commons.CommonsWebAttributes;
+import org.codehaus.xfire.annotations.jsr181.Jsr181WebAnnotations;
+import org.codehaus.xfire.exchange.InMessage;
+import org.codehaus.xfire.exchange.MessageSerializer;
+import org.codehaus.xfire.exchange.OutMessage;
+import org.codehaus.xfire.fault.FaultSender;
+import org.codehaus.xfire.fault.XFireFault;
+import org.codehaus.xfire.handler.OutMessageSender;
+import org.codehaus.xfire.jaxb2.JaxbType;
+import org.codehaus.xfire.jaxws.handler.WebFaultHandler;
+import org.codehaus.xfire.jaxws.type.JAXWSTypeRegistry;
+import org.codehaus.xfire.service.FaultInfo;
+import org.codehaus.xfire.service.OperationInfo;
+import org.codehaus.xfire.service.Service;
+import org.codehaus.xfire.service.ServiceInfo;
+import org.codehaus.xfire.service.binding.AbstractBinding;
 import org.codehaus.xfire.service.binding.ObjectServiceFactory;
+import org.codehaus.xfire.service.binding.PostInvocationHandler;
+import org.codehaus.xfire.service.binding.ServiceInvocationHandler;
+import org.codehaus.xfire.soap.AbstractSoapBinding;
 import org.codehaus.xfire.transport.TransportManager;
+import org.codehaus.xfire.util.ClassLoaderUtils;
+import org.codehaus.xfire.util.STAXUtils;
+import org.codehaus.xfire.util.stax.DepthXMLStreamReader;
 import org.codehaus.xfire.xmlbeans.XmlBeansTypeRegistry;
 
 public class ServiceFactoryHelper {
@@ -120,9 +161,7 @@
         } else if (selectedAnnotations.equals(AN_JAVA5) && 
                    selectedTypeMapping.equals(TM_JAXB2)) {
             try {
-                Class clazz = Class.forName("org.codehaus.xfire.jaxws.JAXWSServiceFactory");
-                Constructor ct = clazz.getDeclaredConstructor(new Class[] { TransportManager.class });
-                factory = (ObjectServiceFactory) ct.newInstance(new Object[] { xfire.getTransportManager() });
+                factory = new FixedJAXWSServiceFactory(xfire.getTransportManager());
             } catch (Exception e) {
                 factory = new AnnotationServiceFactory(wa, 
                         xfire.getTransportManager(), 
@@ -140,4 +179,384 @@
         return factory;
     }
     
+    public static class FixedJAXWSServiceFactory extends AnnotationServiceFactory {
+        public FixedJAXWSServiceFactory(TransportManager transportManager) {
+            super(new Jsr181WebAnnotations(), 
+                  transportManager, 
+                  new AegisBindingProvider(new JAXWSTypeRegistry()));
+        }
+        protected void registerHandlers(Service service)
+        {
+            service.addInHandler(new ServiceInvocationHandler());
+            service.addInHandler(new PostInvocationHandler());
+            service.addOutHandler(new OutMessageSender());
+            service.addFaultHandler(new FaultSender());
+            service.addFaultHandler(new WebFaultHandler());
+        }
+        public String getOperationName(ServiceInfo service, Method method) {
+            Annotation[] annotations = method.getAnnotations();
+            for (int i = 0; i < annotations.length; i++) {
+                if (annotations[i] instanceof WebMethod) {
+                    if (((WebMethod) annotations[i]).operationName() != null) {
+                        return ((WebMethod) annotations[i]).operationName();
+                    }
+                }
+            }
+            return super.getOperationName(service, method);
+        }        
+        @Override
+        protected OperationInfo addOperation(Service endpoint, Method method, String style)
+        {
+            OperationInfo op = super.addOperation(endpoint, method, style);
+            
+            return op;
+        }
+
+        @Override
+        protected FaultInfo addFault(Service service, OperationInfo op, Class exClazz)
+        {
+            FaultInfo info = super.addFault(service, op, exClazz);
+            
+            return info;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        protected boolean isFaultInfoClass(Class exClass) 
+        {
+            return exClass.isAnnotationPresent(WebFault.class);
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        protected QName getFaultName(Service service, OperationInfo o, Class exClass, Class beanClass)
+        {
+            WebFault webFault = (WebFault) exClass.getAnnotation(WebFault.class);
+            
+            if (webFault == null || webFault.name().equals(""))
+                return super.getFaultName(service, o, exClass, beanClass);
+
+            String ns = webFault.targetNamespace();
+            if (ns == null) ns = service.getTargetNamespace();
+            
+            return new QName(ns, webFault.name());
+        }
+
+        protected MessageSerializer getSerializer(AbstractSoapBinding binding)
+        {
+           return new FixedJAXWSBinding(super.getSerializer(binding));
+        }
+
+        public void createBindingOperation(Service service, AbstractSoapBinding binding, OperationInfo op)
+        {
+            super.createBindingOperation(service, binding, op);
+            binding.setSerializer(op, new FixedJAXWSOperationBinding(op, super.getSerializer(binding)));
+        }
+        @Override
+        protected QName createInputMessageName(OperationInfo op)
+        {
+            if (op.getMethod().isAnnotationPresent(RequestWrapper.class))
+            {
+                RequestWrapper wrapper = op.getMethod().getAnnotation(RequestWrapper.class);
+                
+                String ns = wrapper.targetNamespace();
+                if (ns.length() == 0) ns = op.getService().getPortType().getNamespaceURI();
+
+                String name = wrapper.localName();
+                if (name.length() == 0) name = op.getName();
+                
+                return new QName(ns, name);
+            }
+            
+            return super.createInputMessageName(op);
+        }
+
+        @Override
+        protected QName createOutputMessageName(OperationInfo op)
+        {
+            if (op.getMethod().isAnnotationPresent(ResponseWrapper.class))
+            {
+                ResponseWrapper wrapper = op.getMethod().getAnnotation(ResponseWrapper.class);
+                
+                String ns = wrapper.targetNamespace();
+                if (ns.length() == 0) ns = op.getService().getPortType().getNamespaceURI();
+
+                String name = wrapper.localName();
+                if (name.length() == 0) name = op.getName();
+                
+                return new QName(ns, name);
+            }
+            
+            return super.createOutputMessageName(op);
+        }
+    }
+    
+    public static class FixedJAXWSOperationBinding implements MessageSerializer {
+        private MessageSerializer delegate;
+
+        private boolean processInput = false;
+        private List inputPDs = new ArrayList();
+        private Class inputClass;
+        
+        private boolean processOutput = false;
+        private List outputPDs = new ArrayList();
+        private Class outputClass;
+        
+        public FixedJAXWSOperationBinding(OperationInfo op, MessageSerializer delegate) {
+            this.delegate = delegate;
+            
+            Method declared = op.getMethod();
+            if (declared.isAnnotationPresent(RequestWrapper.class))
+            {
+                this.processInput = true;
+                RequestWrapper wrapper = op.getMethod().getAnnotation(RequestWrapper.class);
+                
+                try
+                {
+                    inputClass = ClassLoaderUtils.loadClass(wrapper.className(), getClass());
+                    String[] inputOrder = ((XmlType) inputClass.getAnnotation(XmlType.class)).propOrder();
+                    BeanInfo inputBeanInfo = Introspector.getBeanInfo(inputClass);
+                    
+                    PropertyDescriptor[] pds = inputBeanInfo.getPropertyDescriptors();
+                    for (int i = 0; i < inputOrder.length; i++)
+                    {
+                        inputPDs.add(getPropertyDescriptor(pds, inputOrder[i]));
+                    }
+                }
+                catch (ClassNotFoundException e)
+                {
+                    throw new XFireRuntimeException("Could not load request class for operation " + op.getName(), e);
+                }
+                catch (IntrospectionException e)
+                {
+                    throw new XFireRuntimeException("Could introspect request class for operation " + op.getName(), e);
+                }
+            }
+            
+            if (declared.isAnnotationPresent(ResponseWrapper.class))
+            {
+                this.processOutput = true;
+                ResponseWrapper wrapper = op.getMethod().getAnnotation(ResponseWrapper.class);
+
+                try
+                {
+                    outputClass = ClassLoaderUtils.loadClass(wrapper.className(), getClass());
+                    String[] outputOrder = ((XmlType) outputClass.getAnnotation(XmlType.class)).propOrder();
+                    BeanInfo outputBeanInfo = Introspector.getBeanInfo(outputClass);
+                    
+                    PropertyDescriptor[] pds = outputBeanInfo.getPropertyDescriptors();
+                    for (int i = 0; i < outputOrder.length; i++)
+                    {
+                        outputPDs.add(getPropertyDescriptor(pds, outputOrder[i]));
+                    }
+                }
+                catch (ClassNotFoundException e)
+                {
+                    throw new XFireRuntimeException("Could not load response class for operation " + op.getName(), e);
+                }
+                catch (IntrospectionException e)
+                {
+                    throw new XFireRuntimeException("Could introspect response class for operation " + op.getName(), e);
+                }
+            }
+        }
+
+        protected PropertyDescriptor getPropertyDescriptor(PropertyDescriptor[] descriptors, String name)
+        {
+            for (int i = 0; i < descriptors.length; i++)
+            {
+                if (descriptors[i].getName().equals(name))
+                    return descriptors[i];
+            }
+            
+            return null;
+        }
+        
+        public void readMessage(InMessage message, MessageContext context)
+            throws XFireFault
+        {
+            if (AbstractBinding.isClientModeOn(context)) {
+                if (processOutput) {
+                    Service service = context.getService();
+                    AegisBindingProvider provider = (AegisBindingProvider) service.getBindingProvider();
+                    Type type = provider.getType(service, outputClass);
+                    Object in = type.readObject(new ElementReader(message.getXMLStreamReader()), context);
+                    List<Object> parameters = new ArrayList<Object>();
+                    for (Iterator itr = outputPDs.iterator(); itr.hasNext();) {
+                        PropertyDescriptor pd = (PropertyDescriptor) itr.next();
+                        try {
+                            Object val = getReadMethod(outputClass, pd).invoke(in, new Object[] {});
+                            parameters.add(val);
+                        } catch (Exception e) {
+                            throw new XFireRuntimeException("Couldn't read property " + pd.getName(), e);
+                        }
+                    }
+                    message.setBody(parameters);
+                } else {
+                    delegate.readMessage(message, context);
+                }
+            } else {
+                if (processInput) {
+                    Service service = context.getService();
+                    AegisBindingProvider provider = (AegisBindingProvider) service.getBindingProvider();
+                    Type type = provider.getType(service, inputClass);
+                    Object in = type.readObject(new ElementReader(message.getXMLStreamReader()), context);
+                    List<Object> parameters = new ArrayList<Object>();
+                    for (Iterator itr = inputPDs.iterator(); itr.hasNext();) {
+                        PropertyDescriptor pd = (PropertyDescriptor) itr.next();
+                        try {
+                            Object val = getReadMethod(inputClass, pd).invoke(in, new Object[] {});
+                            parameters.add(val);
+                        } catch (Exception e) {
+                            throw new XFireRuntimeException("Couldn't read property " + pd.getName(), e);
+                        }
+                    }
+                    message.setBody(parameters);
+                } else {
+                    delegate.readMessage(message, context);
+                }
+            }
+        }
+
+        public void writeMessage(OutMessage message, XMLStreamWriter writer, MessageContext context)
+            throws XFireFault
+        {
+            if (processOutput)
+            {
+                Object[] params = (Object[]) message.getBody();
+                
+                Service service = context.getService();
+                AegisBindingProvider provider = (AegisBindingProvider) service.getBindingProvider();
+                
+                Type type = provider.getType(service, outputClass);
+
+                Object out;
+                try
+                {
+                    out = outputClass.newInstance();
+                }
+                catch (Exception e)
+                {
+                    throw new XFireRuntimeException("Could not instantiate resposne class " + outputClass.getName(), e);
+                }
+                
+                for (int i = 0; i < outputPDs.size(); i++)
+                {
+                    PropertyDescriptor pd = (PropertyDescriptor) outputPDs.get(i);
+                    Object val = params[i];
+                    
+                    if (val == null) continue;
+                    
+                    try
+                    {
+                        getWriteMethod(pd).invoke(out, new Object[] {val});
+                    }
+                    catch (Exception e)
+                    {
+                        throw new XFireRuntimeException("Couldn't read property " + pd.getName(), e);
+                    }
+                }
+                ((JaxbType) type).writeObject(out, new ElementWriter(writer), context);
+            }
+            else
+            {
+                delegate.writeMessage(message, writer, context);
+            }
+        }
+        
+        protected Method getReadMethod(Class clazz, PropertyDescriptor pd) 
+        {
+            Method mth = pd.getReadMethod();
+            if (mth == null && pd.getPropertyType() == Boolean.class) {
+                String name = pd.getName();
+                name = name.substring(0, 1).toUpperCase() + name.substring(1);
+                name = "is" + name;
+                try 
+                {
+                    mth = clazz.getMethod(name, new Class[0]);
+                    if (mth != null) {
+                        pd.setReadMethod(mth);
+                    }
+                } 
+                catch (IntrospectionException e) 
+                {
+                    // do nothing
+                }
+                catch (NoSuchMethodException e) 
+                {
+                    // do nothing
+                }
+            }
+            return mth;
+        }
+        
+        protected Method getWriteMethod(PropertyDescriptor pd) 
+        {
+            return pd.getWriteMethod();
+        }
+    }
+    
+    public static class FixedJAXWSBinding 
+    extends AbstractBinding
+    implements MessageSerializer
+{
+    private MessageSerializer delegate;
+    private Map<OperationInfo, FixedJAXWSOperationBinding> op2Binding = 
+        new HashMap<OperationInfo, FixedJAXWSOperationBinding>();
+    
+    public FixedJAXWSBinding(MessageSerializer delegate)
+    {
+        super();
+
+        this.delegate = delegate;
+    }
+
+    public void readMessage(InMessage message, MessageContext context)
+        throws XFireFault
+    {
+        Service endpoint = context.getService();
+        
+        DepthXMLStreamReader dr = new DepthXMLStreamReader(context.getInMessage().getXMLStreamReader());
+
+        if ( !STAXUtils.toNextElement(dr) )
+            throw new XFireFault("There must be a method name element.", XFireFault.SENDER);
+        
+        OperationInfo op = context.getExchange().getOperation();
+
+        if (!isClientModeOn(context) && op == null)
+        {
+            op = endpoint.getServiceInfo().getOperation( dr.getLocalName() );
+
+            if (op != null)
+            {
+                setOperation(op, context);
+    
+                FixedJAXWSOperationBinding opBinding = getOperationBinding(op);
+                opBinding.readMessage(message, context);
+                return;
+            }
+        }
+
+        delegate.readMessage(message, context);
+    }
+
+    private FixedJAXWSOperationBinding getOperationBinding(OperationInfo op)
+    {
+        FixedJAXWSOperationBinding opBinding = (FixedJAXWSOperationBinding) op2Binding.get(op);
+        if (opBinding == null)
+        {
+            opBinding = new FixedJAXWSOperationBinding(op, delegate);
+            op2Binding.put(op, opBinding);
+        }
+        return opBinding;
+    }
+
+    public void writeMessage(OutMessage message, XMLStreamWriter writer, MessageContext context)
+        throws XFireFault
+    {
+        OperationInfo op = context.getExchange().getOperation();
+        
+    }
+}
+
 }