Coverage Report - org.mule.module.ibeans.config.IBeanBinding
 
Classes in this File Line Coverage Branch Coverage Complexity
IBeanBinding
0%
0/82
0%
0/42
0
 
 1  
 /*
 2  
  * $Id: IBeanBinding.java 19952 2010-10-15 18:39:57Z aperepel $
 3  
  * -------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 package org.mule.module.ibeans.config;
 11  
 
 12  
 import org.mule.DefaultMuleEvent;
 13  
 import org.mule.api.EndpointAnnotationParser;
 14  
 import org.mule.api.MessagingException;
 15  
 import org.mule.api.MuleContext;
 16  
 import org.mule.api.MuleEvent;
 17  
 import org.mule.api.MuleException;
 18  
 import org.mule.api.MuleRuntimeException;
 19  
 import org.mule.api.component.InterfaceBinding;
 20  
 import org.mule.api.endpoint.ImmutableEndpoint;
 21  
 import org.mule.api.endpoint.InboundEndpoint;
 22  
 import org.mule.api.endpoint.OutboundEndpoint;
 23  
 import org.mule.config.i18n.CoreMessages;
 24  
 import org.mule.module.ibeans.spi.MuleCallAnnotationHandler;
 25  
 import org.mule.module.ibeans.spi.MuleIBeansPlugin;
 26  
 import org.mule.module.ibeans.spi.support.DynamicRequestInterfaceBinding;
 27  
 import org.mule.util.annotation.AnnotationMetaData;
 28  
 import org.mule.util.annotation.AnnotationUtils;
 29  
 
 30  
 import java.lang.annotation.Annotation;
 31  
 import java.lang.reflect.InvocationHandler;
 32  
 import java.lang.reflect.Method;
 33  
 import java.lang.reflect.Proxy;
 34  
 import java.util.Collection;
 35  
 import java.util.Collections;
 36  
 import java.util.HashMap;
 37  
 import java.util.Iterator;
 38  
 import java.util.List;
 39  
 import java.util.Map;
 40  
 
 41  
 import org.apache.commons.logging.Log;
 42  
 import org.apache.commons.logging.LogFactory;
 43  
 import org.ibeans.annotation.Call;
 44  
 import org.ibeans.annotation.Template;
 45  
 import org.ibeans.annotation.param.Body;
 46  
 import org.ibeans.annotation.param.BodyParam;
 47  
 import org.ibeans.annotation.param.HeaderParam;
 48  
 import org.ibeans.api.IBeanInvoker;
 49  
 import org.ibeans.api.IBeansException;
 50  
 import org.ibeans.api.channel.HTTP;
 51  
 import org.ibeans.impl.IntegrationBeanInvocationHandler;
 52  
 import org.ibeans.impl.InvokeAnnotationHandler;
 53  
 import org.ibeans.impl.TemplateAnnotationHandler;
 54  
 
 55  
 /**
 56  
  * TODO
 57  
  */
 58  
 public class IBeanBinding implements InterfaceBinding
 59  
 {
 60  
 
 61  0
     private static final Log logger = LogFactory.getLog(IBeanBinding.class);
 62  
 
 63  
     private Class interfaceClass;
 64  
 
 65  
     // The endpoint used to actually dispatch the message
 66  
     protected OutboundEndpoint endpoint;
 67  
 
 68  
     protected IBeanFlowConstruct flow;
 69  
 
 70  
     protected MuleIBeansPlugin plugin;
 71  
     
 72  
     protected MuleContext muleContext;
 73  
 
 74  
     public IBeanBinding(IBeanFlowConstruct flow, MuleContext muleContext, MuleIBeansPlugin plugin)
 75  0
     {
 76  0
         this.flow = flow;
 77  0
         this.muleContext = muleContext;
 78  0
         this.plugin = plugin;
 79  0
     }
 80  
 
 81  
     public String getMethod()
 82  
     {
 83  0
         throw new UnsupportedOperationException();
 84  
     }
 85  
 
 86  
     public void setMethod(String method)
 87  
     {
 88  0
         throw new UnsupportedOperationException();
 89  
     }
 90  
 
 91  
     public MuleEvent process(MuleEvent event) throws MessagingException
 92  
     {
 93  
         try
 94  
         {
 95  0
             return endpoint.process(new DefaultMuleEvent(event.getMessage(), endpoint, event.getSession()));
 96  
         }
 97  0
         catch (MessagingException e)
 98  
         {
 99  0
             throw e;
 100  
         }
 101  0
         catch (MuleException e)
 102  
         {
 103  0
             throw new MessagingException(e.getI18nMessage(), event, e);
 104  
         }
 105  
     }
 106  
 
 107  
     public void setInterface(Class interfaceClass)
 108  
     {
 109  0
         this.interfaceClass = interfaceClass;
 110  0
     }
 111  
 
 112  
     public Class getInterface()
 113  
     {
 114  0
         return interfaceClass;
 115  
     }
 116  
 
 117  
     public Object createProxy(Object target)
 118  
     {
 119  0
         Map<String, String> evals = new HashMap<String, String>();
 120  
         try
 121  
         {
 122  0
             IBeanInvoker<MuleCallAnnotationHandler, TemplateAnnotationHandler, InvokeAnnotationHandler> invoker = plugin.getIBeanInvoker();
 123  0
             invoker.getCallHandler().setFlow(flow);
 124  
 
 125  0
             List<AnnotationMetaData> annos = AnnotationUtils.getAllMethodAnnotations(getInterface());
 126  0
             for (AnnotationMetaData metaData : annos)
 127  
             {
 128  0
                 if (metaData.getAnnotation() instanceof Call)
 129  
                 {
 130  0
                     Collection c = muleContext.getRegistry().lookupObjects(EndpointAnnotationParser.class);
 131  
                     String scheme;
 132  
                     boolean http;
 133  0
                     String uri = ((Call) metaData.getAnnotation()).uri();
 134  0
                     int i = uri.indexOf(":/");
 135  0
                     if (i == -1)
 136  
                     {
 137  0
                         scheme = "dynamic";
 138  
                     }
 139  
                     else
 140  
                     {
 141  0
                         scheme = uri.substring(0, i);
 142  
                     }
 143  0
                     http = scheme.contains("http");
 144  
 
 145  0
                     Map metaInfo = new HashMap();
 146  
                     //By setting the connectorName we ensure that only one connector is created for each iBean
 147  0
                     metaInfo.put("connectorName", metaData.getClazz().getSimpleName() + "." + scheme); //RM*  THis affects the connector name generation + "#" + target.hashCode());
 148  
 
 149  0
                     for (Iterator iterator = c.iterator(); iterator.hasNext();)
 150  
                     {
 151  0
                         EndpointAnnotationParser parser = (EndpointAnnotationParser) iterator.next();
 152  0
                         if (parser.supports(metaData.getAnnotation(), metaData.getClazz(), metaData.getMember()))
 153  
                         {
 154  
                             InterfaceBinding binding;
 155  0
                             Method method = (Method) metaData.getMember();
 156  0
                             boolean callChannel = false;
 157  
                             Annotation ann;
 158  
                             //This is a little messy, but we need to detect whether we are doing a Mule 'send' or Mule 'request' call.
 159  
                             //Request calls get data from a resource such as DB, email inbox or message queue. These types of request will
 160  
                             //not have any payload or headers defined.
 161  
                             //The other way to handle this is to introduce a new annotation to explicitly handle this (See the Get annotation).
 162  
                             //The issue is it may be difficult for the user to understand the difference between @Call and @Get. Instead we figure it out
 163  
                             //here.
 164  0
                             for (int x = 0; x < method.getParameterAnnotations().length; x++)
 165  
                             {
 166  0
                                 ann = method.getParameterAnnotations()[x][0];
 167  0
                                 if (ann.annotationType().equals(Body.class) ||
 168  
                                         ann.annotationType().equals(BodyParam.class) ||
 169  
                                         ann.annotationType().equals(HeaderParam.class))
 170  
                                 {
 171  
 
 172  0
                                     callChannel = true;
 173  
 
 174  0
                                     break;
 175  
                                 }
 176  
                             }
 177  
                             //TODO remove the HTTP hack above. Its required becuase HTTP request on the dispatcher
 178  
                             //don't honour authenitcation for some reason.  Also even though there may not be any headers
 179  
                             //defined we still need to attach some headers to the HTTP method. This is very difficult when
 180  
                             //using request
 181  0
                             if (callChannel || http)
 182  
                             {
 183  0
                                 OutboundEndpoint endpoint = parser.parseOutboundEndpoint(metaData.getAnnotation(), metaInfo);
 184  0
                                 binding = new CallInterfaceBinding(this.flow);
 185  0
                                 binding.setEndpoint(endpoint);
 186  0
                             }
 187  
                             else
 188  
                             {
 189  0
                                 InboundEndpoint endpoint = parser.parseInboundEndpoint(metaData.getAnnotation(), Collections.EMPTY_MAP);
 190  0
                                 binding = new DynamicRequestInterfaceBinding();
 191  0
                                 binding.setEndpoint(endpoint);
 192  
                             }
 193  
                             //We need to differenciate between GET and POST
 194  
                             //TODO Consider making this explicit since an iBeans is really a service interaction definition
 195  0
                             if (http)
 196  
                             {
 197  0
                                 List<AnnotationMetaData> temp = AnnotationUtils.getParamAnnotations(method);
 198  0
                                 boolean post = false;
 199  0
                                 for (AnnotationMetaData data : temp)
 200  
                                 {
 201  0
                                     if (data.getAnnotation().annotationType().equals(Body.class) ||
 202  
                                             data.getAnnotation().annotationType().equals(BodyParam.class))
 203  
                                     {
 204  0
                                         post = true;
 205  0
                                         break;
 206  
                                     }
 207  
                                 }
 208  
                                 //By default Mule will post if no method is set
 209  0
                                 if (!post && binding.getEndpoint().getProperties().get(HTTP.METHOD_KEY) == null)
 210  
                                 {
 211  0
                                     binding.getEndpoint().getProperties().put(HTTP.METHOD_KEY, "GET");
 212  
                                 }
 213  
                             }
 214  
 
 215  0
                             binding.setInterface(getInterface());
 216  0
                             binding.setMethod(metaData.getMember().toString());
 217  0
                             invoker.getCallHandler().addRouterForInterface(binding);
 218  
 
 219  
                         }
 220  0
                     }
 221  0
                 }
 222  0
                 else if (metaData.getAnnotation() instanceof Template)
 223  
                 {
 224  0
                     evals.put(metaData.getMember().toString(), ((Template) metaData.getAnnotation()).value());
 225  
                 }
 226  
             }
 227  
 
 228  0
             if (evals.size() > 0)
 229  
             {
 230  0
                 invoker.getTemplateHandler().setEvals(evals);
 231  
             }
 232  
 
 233  0
             Object proxy = Proxy.newProxyInstance(getInterface().getClassLoader(), new Class[]{getInterface()}, createInvocationHandler());
 234  0
             if (logger.isDebugEnabled())
 235  
             {
 236  0
                 logger.debug("Have proxy?: " + (null != proxy));
 237  
             }
 238  0
             return proxy;
 239  
 
 240  
         }
 241  0
         catch (Exception e)
 242  
         {
 243  0
             throw new MuleRuntimeException(CoreMessages.failedToCreateProxyFor(target), e);
 244  
         }
 245  
     }
 246  
 
 247  
     public void setEndpoint(ImmutableEndpoint e)
 248  
     {
 249  0
         endpoint = (OutboundEndpoint) e;
 250  0
     }
 251  
 
 252  
     public String toString()
 253  
     {
 254  0
         final StringBuffer sb = new StringBuffer();
 255  0
         sb.append("IBeanBinding");
 256  0
         sb.append(", interface=").append(interfaceClass);
 257  0
         sb.append('}');
 258  0
         return sb.toString();
 259  
     }
 260  
 
 261  
     public ImmutableEndpoint getEndpoint()
 262  
     {
 263  0
         return endpoint;
 264  
     }
 265  
 
 266  
     protected InvocationHandler createInvocationHandler() throws IBeansException
 267  
     {
 268  0
         return new IntegrationBeanInvocationHandler(interfaceClass, plugin);
 269  
     }
 270  
 }