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