Coverage Report - org.mule.transformer.AbstractTransformer
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractTransformer
90%
89/99
77%
46/60
2.318
 
 1  
 /*
 2  
  * $Id: AbstractTransformer.java 11517 2008-03-31 21:34:19Z dirk.olmes $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.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  
 
 11  
 package org.mule.transformer;
 12  
 
 13  
 import org.mule.api.MuleMessage;
 14  
 import org.mule.api.endpoint.ImmutableEndpoint;
 15  
 import org.mule.api.lifecycle.InitialisationException;
 16  
 import org.mule.api.transformer.Transformer;
 17  
 import org.mule.api.transformer.TransformerException;
 18  
 import org.mule.api.transport.MessageAdapter;
 19  
 import org.mule.config.i18n.CoreMessages;
 20  
 import org.mule.transport.NullPayload;
 21  
 import org.mule.util.ClassUtils;
 22  
 import org.mule.util.FileUtils;
 23  
 import org.mule.util.StringMessageUtils;
 24  
 import org.mule.util.StringUtils;
 25  
 
 26  
 import java.io.InputStream;
 27  
 import java.util.Collections;
 28  
 import java.util.List;
 29  
 
 30  
 import javax.xml.transform.stream.StreamSource;
 31  
 
 32  
 import edu.emory.mathcs.backport.java.util.concurrent.CopyOnWriteArrayList;
 33  
 
 34  
 import org.apache.commons.logging.Log;
 35  
 import org.apache.commons.logging.LogFactory;
 36  
 
 37  
 /**
 38  
  * <code>AbstractTransformer</code> is a base class for all transformers.
 39  
  * Transformations transform one object into another.
 40  
  */
 41  
 
 42  
 public abstract class AbstractTransformer implements Transformer
 43  
 {
 44  
     protected static final int DEFAULT_TRUNCATE_LENGTH = 200;
 45  
 
 46  5472
     protected final Log logger = LogFactory.getLog(getClass());
 47  
 
 48  
     /**
 49  
      * The return type that will be returned by the {@link #transform} method is
 50  
      * called
 51  
      */
 52  5472
     protected Class returnClass = Object.class;
 53  
 
 54  
     /**
 55  
      * The name that identifies this transformer. If none is set the class name of
 56  
      * the transformer is used
 57  
      */
 58  5472
     protected String name = null;
 59  
 
 60  
     /** The endpoint that this transformer instance is configured on */
 61  5472
     protected ImmutableEndpoint endpoint = null;
 62  
 
 63  
     /**
 64  
      * A list of supported Class types that the source payload passed into this
 65  
      * transformer
 66  
      */
 67  5472
     protected final List sourceTypes = new CopyOnWriteArrayList();
 68  
 
 69  
     /**
 70  
      * Determines whether the transformer will throw an exception if the message
 71  
      * passed is is not supported or the return tye is incorrect
 72  
      */
 73  5472
     private boolean ignoreBadInput = false;
 74  
 
 75  
     /** default constructor required for discovery */
 76  
     public AbstractTransformer()
 77  
     {
 78  5472
         super();
 79  5472
     }
 80  
 
 81  
     protected Object checkReturnClass(Object object) throws TransformerException
 82  
     {
 83  356
         if (returnClass != null)
 84  
         {
 85  356
             if (!returnClass.isInstance(object))
 86  
             {
 87  72
                 throw new TransformerException(
 88  
                         CoreMessages.transformUnexpectedType(object.getClass(), returnClass),
 89  
                         this);
 90  
             }
 91  
         }
 92  
 
 93  284
         if (logger.isDebugEnabled())
 94  
         {
 95  0
             logger.debug("The transformed object is of expected type. Type is: " +
 96  
                     ClassUtils.getSimpleName(object.getClass()));
 97  
         }
 98  
 
 99  284
         return object;
 100  
     }
 101  
 
 102  
     protected void registerSourceType(Class aClass)
 103  
     {
 104  16942
         if (!sourceTypes.contains(aClass))
 105  
         {
 106  16942
             sourceTypes.add(aClass);
 107  
 
 108  16942
             if (aClass.equals(Object.class))
 109  
             {
 110  1178
                 logger.debug("java.lang.Object has been added as source type for this transformer, there will be no source type checking performed");
 111  
             }
 112  
         }
 113  16942
     }
 114  
 
 115  
     protected void unregisterSourceType(Class aClass)
 116  
     {
 117  0
         sourceTypes.remove(aClass);
 118  0
     }
 119  
 
 120  
     /** @return transformer name */
 121  
     public String getName()
 122  
     {
 123  13792
         if (name == null)
 124  
         {
 125  4594
             name = this.generateTransformerName();
 126  
         }
 127  13792
         return name;
 128  
     }
 129  
 
 130  
     /** @param string  */
 131  
     public void setName(String string)
 132  
     {
 133  4594
         if (string == null)
 134  
         {
 135  0
             string = ClassUtils.getSimpleName(this.getClass());
 136  
         }
 137  
 
 138  4594
         logger.debug("Setting transformer name to: " + string);
 139  4594
         name = string;
 140  4594
     }
 141  
 
 142  
     /*
 143  
      * (non-Javadoc)
 144  
      *
 145  
      * @see org.mule.transformer.Transformer#getReturnClass()
 146  
      */
 147  
     public Class getReturnClass()
 148  
     {
 149  178
         return returnClass;
 150  
     }
 151  
 
 152  
     /*
 153  
      * (non-Javadoc)
 154  
      *
 155  
      * @see org.mule.transformer.Transformer#setReturnClass(java.lang.String)
 156  
      */
 157  
     public void setReturnClass(Class newClass)
 158  
     {
 159  7378
         returnClass = newClass;
 160  7378
     }
 161  
 
 162  
     public boolean isSourceTypeSupported(Class aClass)
 163  
     {
 164  554
         return isSourceTypeSupported(aClass, false);
 165  
     }
 166  
 
 167  
     public boolean isSourceTypeSupported(Class aClass, boolean exactMatch)
 168  
     {
 169  918
         int numTypes = sourceTypes.size();
 170  
 
 171  918
         if (numTypes == 0)
 172  
         {
 173  344
             return !exactMatch;
 174  
         }
 175  
 
 176  1078
         for (int i = 0; i < numTypes; i++)
 177  
         {
 178  876
             Class anotherClass = (Class) sourceTypes.get(i);
 179  876
             if (exactMatch)
 180  
             {
 181  412
                 if (anotherClass.equals(aClass))
 182  
                 {
 183  4
                     return true;
 184  
                 }
 185  
             }
 186  464
             else if (anotherClass.isAssignableFrom(aClass))
 187  
             {
 188  368
                 return true;
 189  
             }
 190  
         }
 191  
 
 192  202
         return false;
 193  
     }
 194  
 
 195  
     /**
 196  
      * Transforms the object.
 197  
      *
 198  
      * @param src The source object to transform.
 199  
      * @return The transformed object
 200  
      */
 201  
     public final Object transform(Object src) throws TransformerException
 202  
     {
 203  370
         String encoding = null;
 204  
 
 205  370
         Object payload = src;
 206  
         MessageAdapter adapter;
 207  370
         if (src instanceof MessageAdapter)
 208  
         {
 209  182
             encoding = ((MessageAdapter) src).getEncoding();
 210  182
             adapter = (MessageAdapter) src;
 211  182
             if ((!isSourceTypeSupported(MessageAdapter.class, true)
 212  
                     && !isSourceTypeSupported(MuleMessage.class, true)
 213  
                     && !(this instanceof AbstractMessageAwareTransformer))
 214  
                     )
 215  
             {
 216  164
                 src = ((MessageAdapter) src).getPayload();
 217  164
                 payload = adapter.getPayload();
 218  
             }
 219  
         }
 220  
 
 221  370
         if (encoding == null && endpoint != null)
 222  
         {
 223  0
             encoding = endpoint.getEncoding();
 224  
         }
 225  370
         else if (encoding == null)
 226  
         {
 227  188
             encoding = FileUtils.DEFAULT_ENCODING;
 228  
         }
 229  
 
 230  370
         Class srcCls = src.getClass();
 231  370
         if (!isSourceTypeSupported(srcCls))
 232  
         {
 233  10
             if (ignoreBadInput)
 234  
             {
 235  4
                 logger.debug("Source type is incompatible with this transformer and property 'ignoreBadInput' is set to true, so the transformer chain will continue.");
 236  4
                 return payload;
 237  
             }
 238  
             else
 239  
             {
 240  6
                 throw new TransformerException(
 241  
                         CoreMessages.transformOnObjectUnsupportedTypeOfEndpoint(this.getName(),
 242  
                                 payload.getClass(), endpoint), this);
 243  
             }
 244  
         }
 245  
 
 246  360
         if (logger.isDebugEnabled())
 247  
         {
 248  0
             logger.debug("Applying transformer " + getName() + " (" + getClass().getName() + ")");
 249  0
             logger.debug("Object before transform: "
 250  
                     + StringMessageUtils.truncate(StringMessageUtils.toString(payload), DEFAULT_TRUNCATE_LENGTH, false));
 251  
         }
 252  
 
 253  
         Object result;
 254  360
         result = doTransform(payload, encoding);
 255  
         // }
 256  356
         if (result == null)
 257  
         {
 258  6
             result = NullPayload.getInstance();
 259  
         }
 260  
 
 261  356
         if (logger.isDebugEnabled())
 262  
         {
 263  0
             logger.debug("Object after transform: "
 264  
                     + StringMessageUtils.truncate(StringMessageUtils.toString(result), DEFAULT_TRUNCATE_LENGTH, false));
 265  
         }
 266  
 
 267  356
         result = checkReturnClass(result);
 268  284
         return result;
 269  
     }
 270  
 
 271  
     protected boolean isConsumed(Class srcCls)
 272  
     {
 273  0
         return InputStream.class.isAssignableFrom(srcCls) || StreamSource.class.isAssignableFrom(srcCls);
 274  
     }
 275  
 
 276  
     public ImmutableEndpoint getEndpoint()
 277  
     {
 278  4
         return endpoint;
 279  
     }
 280  
 
 281  
     /*
 282  
      * (non-Javadoc)
 283  
      *
 284  
      * @see org.mule.api.transformer.Transformer#setConnector(org.mule.api.transport.Connector)
 285  
      */
 286  
     public void setEndpoint(ImmutableEndpoint endpoint)
 287  
     {
 288  558
         this.endpoint = endpoint;
 289  558
     }
 290  
 
 291  
     protected abstract Object doTransform(Object src, String encoding) throws TransformerException;
 292  
 
 293  
     /**
 294  
      * Template method where deriving classes can do any initialisation after the
 295  
      * properties have been set on this transformer
 296  
      *
 297  
      * @throws InitialisationException
 298  
      */
 299  
     public void initialise() throws InitialisationException
 300  
     {
 301  
         // do nothing, subclasses may override
 302  5172
     }
 303  
 
 304  
     protected String generateTransformerName()
 305  
     {
 306  4594
         String name = ClassUtils.getSimpleName(this.getClass());
 307  4594
         int i = name.indexOf("To");
 308  4594
         if (i > 0 && returnClass != null)
 309  
         {
 310  4590
             String target = ClassUtils.getSimpleName(returnClass);
 311  4590
             if (target.equals("byte[]"))
 312  
             {
 313  1150
                 target = "byteArray";
 314  
             }
 315  4590
             name = name.substring(0, i + 2) + StringUtils.capitalize(target);
 316  
         }
 317  4594
         return name;
 318  
     }
 319  
 
 320  
     public List getSourceTypes()
 321  
     {
 322  26
         return Collections.unmodifiableList(sourceTypes);
 323  
     }
 324  
 
 325  
     public boolean isIgnoreBadInput()
 326  
     {
 327  4
         return ignoreBadInput;
 328  
     }
 329  
 
 330  
     public void setIgnoreBadInput(boolean ignoreBadInput)
 331  
     {
 332  10
         this.ignoreBadInput = ignoreBadInput;
 333  10
     }
 334  
 
 335  
     // @Override
 336  
     public String toString()
 337  
     {
 338  10242
         StringBuffer sb = new StringBuffer(80);
 339  10242
         sb.append(ClassUtils.getSimpleName(this.getClass()));
 340  10242
         sb.append("{this=").append(Integer.toHexString(System.identityHashCode(this)));
 341  10242
         sb.append(", name='").append(name).append('\'');
 342  10242
         sb.append(", ignoreBadInput=").append(ignoreBadInput);
 343  10242
         sb.append(", returnClass=").append(returnClass);
 344  10242
         sb.append(", sourceTypes=").append(sourceTypes);
 345  10242
         sb.append('}');
 346  10242
         return sb.toString();
 347  
     }
 348  
 
 349  
     public boolean isAcceptNull()
 350  
     {
 351  0
         return false;
 352  
     }
 353  
 
 354  
 }