Coverage Report - org.mule.config.transformer.AnnotatedTransformerProxy
 
Classes in this File Line Coverage Branch Coverage Complexity
AnnotatedTransformerProxy
0%
0/105
0%
0/88
0
 
 1  
 /*
 2  
  * $Id: AnnotatedTransformerProxy.java 19340 2010-09-03 14:36:29Z rossmason $
 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.config.transformer;
 11  
 
 12  
 import org.mule.api.MuleMessage;
 13  
 import org.mule.api.annotations.param.Payload;
 14  
 import org.mule.api.lifecycle.InitialisationException;
 15  
 import org.mule.api.transformer.DataType;
 16  
 import org.mule.api.transformer.DiscoverableTransformer;
 17  
 import org.mule.api.transformer.TransformerException;
 18  
 import org.mule.config.expression.ExpressionAnnotationsHelper;
 19  
 import org.mule.config.i18n.AnnotationsMessages;
 20  
 import org.mule.expression.transformers.ExpressionTransformer;
 21  
 import org.mule.transformer.AbstractMessageTransformer;
 22  
 import org.mule.transformer.types.DataTypeFactory;
 23  
 import org.mule.transformer.types.SimpleDataType;
 24  
 import org.mule.util.annotation.AnnotationUtils;
 25  
 
 26  
 import java.lang.reflect.Method;
 27  
 import java.lang.reflect.Modifier;
 28  
 import java.util.Arrays;
 29  
 import java.util.Collection;
 30  
 import java.util.Map;
 31  
 import java.util.WeakHashMap;
 32  
 
 33  
 /**
 34  
  * Creates a Mule {@link org.mule.api.transformer.Transformer} proxy around a transform method. The
 35  
  * transformer will be given a generated name which is the short name of the class and the method name
 36  
  * separated with a '.' i.e. 'MyTransformers.fooToBar'
 37  
  */
 38  
 public class AnnotatedTransformerProxy extends AbstractMessageTransformer implements DiscoverableTransformer
 39  
 {
 40  
     private int weighting;
 41  
 
 42  
     private Object proxy;
 43  
 
 44  
     private Method transformMethod;
 45  0
     private boolean messageAware = false;
 46  0
     private ExpressionTransformer paramTransformer = null;
 47  
     private Collection<TransformerArgumentResolver> resolvers;
 48  0
     private Map<Class<?>, Object> cachedObjects = new WeakHashMap<Class<?>, Object>();
 49  0
     private boolean sourceAnnotated = false;
 50  
 
 51  
     public AnnotatedTransformerProxy(int weighting, Object proxy, Method transformMethod, Class[] additionalSourceTypes, String sourceMimeType, String resultMimeType) throws TransformerException, InitialisationException
 52  0
     {
 53  0
         this.weighting = weighting;
 54  0
         this.proxy = proxy;
 55  
 
 56  
         //By default we allow a transformer to return null
 57  0
         setAllowNullReturn(true);
 58  
 
 59  0
         validateMethod(transformMethod, additionalSourceTypes);
 60  
 
 61  0
         this.transformMethod = transformMethod;
 62  0
         setReturnDataType(DataTypeFactory.createFromReturnType(transformMethod));
 63  
 
 64  0
         messageAware = MuleMessage.class.isAssignableFrom(transformMethod.getParameterTypes()[0]);
 65  0
         this.transformMethod = transformMethod;
 66  0
         if (additionalSourceTypes.length > 0)
 67  
         {
 68  0
             if (messageAware)
 69  
             {
 70  0
                 logger.error("Transformer: " + getName() + " is MuleMessage aware, this means additional source types configured on the transformer will be ignorred. Source types are: " + Arrays.toString(additionalSourceTypes));
 71  
             }
 72  
             else
 73  
             {
 74  0
                 for (int i = 0; i < additionalSourceTypes.length; i++)
 75  
                 {
 76  0
                     registerSourceType(new SimpleDataType(additionalSourceTypes[i], sourceMimeType));
 77  
 
 78  
                 }
 79  
             }
 80  
         }
 81  
         //The first Param is the always the object to transform
 82  0
         Class<?> source = transformMethod.getParameterTypes()[0];
 83  0
         registerSourceType(DataTypeFactory.create(source));
 84  0
         sourceAnnotated = (transformMethod.getParameterAnnotations()[0].length > 0 &&
 85  
                 transformMethod.getParameterAnnotations()[0][0] instanceof Payload);
 86  
 
 87  0
         setName(proxy.getClass().getSimpleName() + "." + transformMethod.getName());
 88  0
     }
 89  
 
 90  
     protected void validateMethod(Method method, Class[] sourceTypes) throws IllegalArgumentException
 91  
     {
 92  0
         int mods = method.getModifiers();
 93  0
         if(Modifier.isAbstract(mods) || Modifier.isInterface(mods) || !Modifier.isPublic(mods)
 94  
                 || method.getReturnType().equals(Void.TYPE) || method.getParameterTypes().length==0 ||
 95  
                 method.getReturnType().equals(Object.class) || Arrays.asList(method.getParameterTypes()).contains(Object.class) ||
 96  
                 Arrays.asList(sourceTypes).contains(Object.class))
 97  
         {
 98  
             //May lift the ban on OBject return and source types
 99  
             //The details as to why the method is invalid are in the message
 100  0
             throw new IllegalArgumentException(AnnotationsMessages.transformerMethodNotValid(method).getMessage());
 101  
         }
 102  0
     }
 103  
 
 104  
     @Override
 105  
     public void initialise() throws InitialisationException
 106  
     {
 107  0
         super.initialise();
 108  0
         if (AnnotationUtils.methodHasParamAnnotations(transformMethod))
 109  
         {
 110  
             try
 111  
             {
 112  0
                 paramTransformer = ExpressionAnnotationsHelper.getTransformerForMethodWithAnnotations(transformMethod, muleContext);
 113  
             }
 114  0
             catch (TransformerException e)
 115  
             {
 116  0
                 throw new InitialisationException(e, this);
 117  0
             }
 118  
         }
 119  0
         resolvers = muleContext.getRegistry().lookupObjects(TransformerArgumentResolver.class);
 120  0
     }
 121  
 
 122  
     @Override
 123  
     public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException
 124  
     {
 125  0
         Object firstArg = null;
 126  0
         Object[] params = new Object[transformMethod.getParameterTypes().length];
 127  0
         int paramCounter = 0;
 128  
 
 129  
         //the param transformer will convert the message to one or more objects depending on the annotations on the method
 130  
         //parameter
 131  0
         if (paramTransformer != null)
 132  
         {
 133  0
             Object paramArgs = paramTransformer.transformMessage(message, outputEncoding);
 134  
 
 135  0
             if (paramArgs != null && paramArgs.getClass().isArray())
 136  
             {
 137  0
                 Object[] temp = (Object[]) paramArgs;
 138  
                 //if the source is annotated, the paramTransformer will figure out the first parameter
 139  0
                 if (!sourceAnnotated)
 140  
                 {
 141  0
                     paramCounter++;
 142  
                 }
 143  0
                 for (int i = 0; i < temp.length; i++)
 144  
                 {
 145  0
                     params[paramCounter++] = temp[i];
 146  
                 }
 147  0
             }
 148  
             else
 149  
             {
 150  
                 //if the source is annotated, the paramTransformer will figure out the first parameter
 151  0
                 if (!sourceAnnotated)
 152  
                 {
 153  0
                     paramCounter++;
 154  
                 }
 155  0
                 params[paramCounter++] = paramArgs;
 156  
             }
 157  
         }
 158  
 
 159  0
         if (messageAware)
 160  
         {
 161  0
             firstArg = message;
 162  
         }
 163  0
         else if (!sourceAnnotated)
 164  
         {
 165  
             //This will perform any additional transformation from the source type to the method parameter type
 166  
             try
 167  
             {
 168  0
                 firstArg = message.getPayload(DataTypeFactory.create(transformMethod.getParameterTypes()[0]));
 169  
             }
 170  0
             catch (TransformerException e)
 171  
             {
 172  0
                 throw new TransformerException(e.getI18nMessage(), this, e);
 173  0
             }
 174  
         }
 175  
 
 176  
         //if the source is annotated, the paramTransformer will figure out the first parameter
 177  0
         if (!sourceAnnotated)
 178  
         {
 179  0
             params[0] = firstArg;
 180  0
             if (paramCounter == 0)
 181  
             {
 182  0
                 paramCounter++;
 183  
             }
 184  
         }
 185  
         //Lets see if there are any context objects to inject (i.e. JAXB)
 186  0
         if (paramCounter < transformMethod.getParameterTypes().length)
 187  
         {
 188  0
             for (int i = paramCounter; i < transformMethod.getParameterTypes().length; i++)
 189  
             {
 190  
                 Object o;
 191  0
                 Class<?> type = transformMethod.getParameterTypes()[i];
 192  0
                 o = cachedObjects.get(type);
 193  0
                 if (o != null)
 194  
                 {
 195  0
                     params[paramCounter++] = o;
 196  0
                     continue;
 197  
                 }
 198  0
                 DataType<?> source = DataTypeFactory.createFromParameterType(transformMethod, 0);
 199  
 
 200  0
                 for (TransformerArgumentResolver resolver : resolvers)
 201  
                 {
 202  
                     try
 203  
                     {
 204  0
                         o = resolver.resolve(type, source, this.returnType, muleContext);
 205  0
                         if (o != null)
 206  
                         {
 207  0
                             params[paramCounter++] = o;
 208  0
                             cachedObjects.put(type, o);
 209  0
                             break;
 210  
                         }
 211  
                     }
 212  0
                     catch (Exception e)
 213  
                     {
 214  0
                         throw new TransformerException(this, e);
 215  0
                     }
 216  
 
 217  
                 }
 218  0
                 if (o == null)
 219  
                 {
 220  0
                     throw new IllegalArgumentException("Failed to find resolver for object type: " + type + " for transform method: " + transformMethod);
 221  
                 }
 222  
             }
 223  
         }
 224  
         try
 225  
         {
 226  0
             return transformMethod.invoke(proxy, params);
 227  
         }
 228  0
         catch (Exception e)
 229  
         {
 230  0
             e.printStackTrace();
 231  0
             throw new TransformerException(this, e);
 232  
         }
 233  
     }
 234  
 
 235  
     public int getPriorityWeighting()
 236  
     {
 237  0
         return weighting;
 238  
     }
 239  
 
 240  
     public void setPriorityWeighting(int weighting)
 241  
     {
 242  0
         throw new UnsupportedOperationException("setPriorityWeighting");
 243  
     }
 244  
 
 245  
     @Override
 246  
     public boolean equals(Object o)
 247  
     {
 248  0
         if (this == o)
 249  
         {
 250  0
             return true;
 251  
         }
 252  0
         if (o == null || getClass() != o.getClass())
 253  
         {
 254  0
             return false;
 255  
         }
 256  
 
 257  0
         AnnotatedTransformerProxy that = (AnnotatedTransformerProxy) o;
 258  
 
 259  0
         if (messageAware != that.messageAware)
 260  
         {
 261  0
             return false;
 262  
         }
 263  0
         if (weighting != that.weighting)
 264  
         {
 265  0
             return false;
 266  
         }
 267  0
         if (proxy != null ? !proxy.equals(that.proxy) : that.proxy != null)
 268  
         {
 269  0
             return false;
 270  
         }
 271  0
         if (transformMethod != null ? !transformMethod.equals(that.transformMethod) : that.transformMethod != null)
 272  
         {
 273  0
             return false;
 274  
         }
 275  
 
 276  0
         return true;
 277  
     }
 278  
 
 279  
     @Override
 280  
     public int hashCode()
 281  
     {
 282  0
         int result = weighting;
 283  0
         result = 31 * result + (proxy != null ? proxy.hashCode() : 0);
 284  0
         result = 31 * result + (transformMethod != null ? transformMethod.hashCode() : 0);
 285  0
         result = 31 * result + (messageAware ? 1 : 0);
 286  0
         return result;
 287  
     }
 288  
 
 289  
 
 290  
 }