Coverage Report - org.mule.module.xml.transformer.jaxb.JAXBTransformerResolver
 
Classes in this File Line Coverage Branch Coverage Complexity
JAXBTransformerResolver
0%
0/53
0%
0/28
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.module.xml.transformer.jaxb;
 8  
 
 9  
 import org.mule.api.MuleContext;
 10  
 import org.mule.api.context.MuleContextAware;
 11  
 import org.mule.api.lifecycle.Disposable;
 12  
 import org.mule.api.registry.RegistrationException;
 13  
 import org.mule.api.registry.ResolverException;
 14  
 import org.mule.api.registry.TransformerResolver;
 15  
 import org.mule.api.transformer.DataType;
 16  
 import org.mule.api.transformer.Transformer;
 17  
 import org.mule.config.i18n.CoreMessages;
 18  
 import org.mule.transformer.simple.ObjectToString;
 19  
 import org.mule.util.annotation.AnnotationUtils;
 20  
 
 21  
 import java.io.IOException;
 22  
 import java.util.List;
 23  
 import java.util.Map;
 24  
 import java.util.concurrent.ConcurrentHashMap;
 25  
 
 26  
 import javax.xml.bind.JAXBContext;
 27  
 
 28  
 import org.apache.commons.logging.Log;
 29  
 import org.apache.commons.logging.LogFactory;
 30  
 
 31  
 /**
 32  
  * A {@link org.mule.api.registry.TransformerResolver} implementation used to discover whether the current transform
 33  
  * requests requires JAXB. The resolver will scan the source and return type for JAXB 2 annotations and will configure
 34  
  * a JAXB transformer accordingly.  The transformer is cached and will be used for any subsequent requests.
 35  
  *
 36  
  * The {@link javax.xml.bind.JAXBContext} instance needed for the transform can be discovered from the registry, this means one can be
 37  
  * pre-configured in Spring or Guice.  If there is no pre-configured {@link javax.xml.bind.JAXBContext} one will be created with the
 38  
  * annotated JAXB class.  This context will cached with the transformer.
 39  
  *
 40  
  * @since 3.0
 41  
  */
 42  0
 public class JAXBTransformerResolver implements TransformerResolver, MuleContextAware, Disposable
 43  
 {
 44  0
     public static final String[] ignoredPackages = {"java.,javax.,org.w3c.,org.mule.transport., org.mule.module."};
 45  
 
 46  
     /**
 47  
      * logger used by this class
 48  
      */
 49  0
     protected transient final Log logger = LogFactory.getLog(JAXBTransformerResolver.class);
 50  
 
 51  
     private MuleContext muleContext;
 52  
 
 53  
     //We cache the the transformers, this will get cleared when the server shuts down
 54  0
     private Map<String, Transformer> transformerCache = new ConcurrentHashMap<String, Transformer>();
 55  
 
 56  
     private JAXBContextResolver resolver;
 57  
 
 58  
     public void setMuleContext(MuleContext context)
 59  
     {
 60  0
         muleContext = context;
 61  0
     }
 62  
 
 63  
     public Transformer resolve(DataType source, DataType result) throws ResolverException
 64  
     {
 65  0
         Transformer t = transformerCache.get(source.toString() + result.toString());
 66  0
         if (t != null)
 67  
         {
 68  0
             return t;
 69  
         }
 70  
 
 71  
         try
 72  
         {
 73  0
             JAXBContext jaxb = getContextResolver().resolve(JAXBContext.class, source, result, muleContext);
 74  
 
 75  0
             if(jaxb==null)
 76  
             {
 77  0
                 return null;
 78  
             }
 79  0
             boolean marshal = false;
 80  0
             Class annotatedType = null;
 81  
 
 82  
 
 83  0
             if (getContextResolver().getMatchingClasses().contains(result.getType()))
 84  
             {
 85  0
                 annotatedType = result.getType();
 86  0
                 marshal = false;
 87  
             }
 88  
             else
 89  
             {
 90  0
                 if (getContextResolver().getMatchingClasses().contains(source.getType()))
 91  
                 {
 92  0
                     annotatedType = source.getType();
 93  0
                     marshal = true;
 94  
                 }
 95  
             }
 96  
 
 97  0
             if (annotatedType == null)
 98  
             {
 99  0
                 annotatedType = result.getType();
 100  0
                 boolean isJAXB = hasJaxbAnnotations(annotatedType);
 101  0
                 if (!isJAXB)
 102  
                 {
 103  0
                     marshal = true;
 104  0
                     annotatedType = source.getType();
 105  0
                     isJAXB = hasJaxbAnnotations(annotatedType);
 106  
                 }
 107  
 
 108  0
                 if (!isJAXB)
 109  
                 {
 110  0
                     return null;
 111  
                 }
 112  
             }
 113  
             //At this point we know we are dealing with JAXB, now lets check the registry to see if there is an exact
 114  
             //transformer that matches our criteria
 115  0
             List<Transformer> ts = muleContext.getRegistry().lookupTransformers(source, result);
 116  0
             if (ts.size() == 1 && !(ts.get(0) instanceof ObjectToString))
 117  
             {
 118  0
                 t = ts.get(0);
 119  
             }
 120  
             else
 121  
             {
 122  0
                 if (marshal)
 123  
                 {
 124  0
                     t = new JAXBMarshallerTransformer(jaxb, result);
 125  
                 }
 126  
                 else
 127  
                 {
 128  0
                     t = new JAXBUnmarshallerTransformer(jaxb, result);
 129  
                 }
 130  
             }
 131  
 
 132  0
             transformerCache.put(source.toString() + result.toString(), t);
 133  0
             return t;
 134  
 
 135  
         }
 136  0
         catch (Exception e)
 137  
         {
 138  0
             throw new ResolverException(CoreMessages.createStaticMessage("Failed to unmarshal"), e);
 139  
         }
 140  
     }
 141  
 
 142  
     public void transformerChange(Transformer transformer, RegistryAction registryAction)
 143  
     {
 144  
         //nothing to do
 145  0
     }
 146  
 
 147  
     public void dispose()
 148  
     {
 149  0
         transformerCache.clear();
 150  0
     }
 151  
 
 152  
     protected JAXBContextResolver getContextResolver() throws RegistrationException
 153  
     {
 154  0
         if(resolver==null)
 155  
         {
 156  0
             resolver = muleContext.getRegistry().lookupObject(JAXBContextResolver.class);
 157  
         }
 158  0
         return resolver;
 159  
     }
 160  
 
 161  
     protected boolean hasJaxbAnnotations(Class annotatedType)
 162  
     {
 163  
         // MULE-5931 The package can be null, e.g. for DataType.BYTE_ARRAY_DATA_TYPE
 164  0
         if(annotatedType.getPackage() != null)
 165  
         {
 166  0
             String p = annotatedType.getPackage().getName();
 167  0
             for (int i = 0; i < ignoredPackages.length; i++)
 168  
             {
 169  0
                 if(p.startsWith(ignoredPackages[i])) return false;
 170  
             }
 171  
         }
 172  
 
 173  
         try
 174  
         {
 175  0
              return AnnotationUtils.hasAnnotationWithPackage("javax.xml.bind.annotation", annotatedType);
 176  
         }
 177  0
         catch (IOException e)
 178  
         {
 179  0
             logger.warn("Failed to scan class for Jaxb annotations: " + annotatedType, e);
 180  0
             return false;
 181  
         }
 182  
     }
 183  
 }