Coverage Report - org.mule.endpoint.AbstractEndpoint
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractEndpoint
0%
0/104
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.endpoint;
 8  
 
 9  
 import org.mule.MessageExchangePattern;
 10  
 import org.mule.api.MuleContext;
 11  
 import org.mule.api.MuleException;
 12  
 import org.mule.api.construct.FlowConstruct;
 13  
 import org.mule.api.endpoint.EndpointMessageProcessorChainFactory;
 14  
 import org.mule.api.endpoint.EndpointURI;
 15  
 import org.mule.api.endpoint.ImmutableEndpoint;
 16  
 import org.mule.api.lifecycle.Disposable;
 17  
 import org.mule.api.processor.MessageProcessor;
 18  
 import org.mule.api.processor.MessageProcessorChain;
 19  
 import org.mule.api.retry.RetryPolicyTemplate;
 20  
 import org.mule.api.routing.filter.Filter;
 21  
 import org.mule.api.security.EndpointSecurityFilter;
 22  
 import org.mule.api.security.SecurityFilter;
 23  
 import org.mule.api.transaction.TransactionConfig;
 24  
 import org.mule.api.transformer.Transformer;
 25  
 import org.mule.api.transport.Connector;
 26  
 import org.mule.processor.SecurityFilterMessageProcessor;
 27  
 import org.mule.routing.MessageFilter;
 28  
 import org.mule.util.ClassUtils;
 29  
 
 30  
 import java.net.URI;
 31  
 import java.util.HashMap;
 32  
 import java.util.LinkedList;
 33  
 import java.util.List;
 34  
 import java.util.Map;
 35  
 import java.util.regex.Matcher;
 36  
 import java.util.regex.Pattern;
 37  
 
 38  
 import edu.emory.mathcs.backport.java.util.Collections;
 39  
 
 40  
 import org.apache.commons.logging.Log;
 41  
 import org.apache.commons.logging.LogFactory;
 42  
 
 43  
 /**
 44  
  * <code>ImmutableMuleEndpoint</code> describes a Provider in the Mule Server. A
 45  
  * endpoint is a grouping of an endpoint, an endpointUri and a transformer.
 46  
  */
 47  
 public abstract class AbstractEndpoint implements ImmutableEndpoint, Disposable
 48  
 {
 49  
 
 50  
     private static final long serialVersionUID = -1650380871293160973L;
 51  
 
 52  
     public static final String PROPERTY_PROCESS_SYNCHRONOUSLY = "processSynchronously";
 53  
 
 54  
     /**
 55  
      * logger used by this class
 56  
      */
 57  0
     protected static final Log logger = LogFactory.getLog(AbstractEndpoint.class);
 58  
 
 59  
     /**
 60  
      * The endpoint used to communicate with the external system
 61  
      */
 62  
     private final Connector connector;
 63  
 
 64  
     /**
 65  
      * The endpointUri on which to send or receive information
 66  
      */
 67  
     private final EndpointURI endpointUri;
 68  
 
 69  
     private final EndpointMessageProcessorChainFactory messageProcessorsFactory;
 70  
 
 71  
     private final List <MessageProcessor> messageProcessors;
 72  
 
 73  
     private final List <MessageProcessor> responseMessageProcessors;
 74  
     
 75  
     private MessageProcessor messageProcessorChain;
 76  
 
 77  
     /**
 78  
      * The name for the endpoint
 79  
      */
 80  
     private final String name;
 81  
 
 82  
     /**
 83  
      * Any additional properties for the endpoint
 84  
      * // TODO This should be final. See MULE-3105
 85  
      * // TODO Shouldn't this be guarded from concurrent writes?
 86  
      */
 87  0
     private Map properties = new HashMap();
 88  
 
 89  
     /**
 90  
      * The transaction configuration for this endpoint
 91  
      */
 92  
     private final TransactionConfig transactionConfig;
 93  
 
 94  
     /**
 95  
      * determines whether unaccepted filtered events should be removed from the
 96  
      * source. If they are not removed its up to the Message receiver to handle
 97  
      * recieving the same message again
 98  
      */
 99  
     private final boolean deleteUnacceptedMessages;
 100  
 
 101  
     private final MessageExchangePattern messageExchangePattern;
 102  
     
 103  
     /**
 104  
      * How long to block when performing a remote synchronisation to a remote host.
 105  
      * This property is optional and will be set to the default Synchonous MuleEvent
 106  
      * time out value if not set
 107  
      */
 108  
     private final int responseTimeout;
 109  
 
 110  
     /**
 111  
      * The state that the endpoint is initialised in such as started or stopped
 112  
      */
 113  
     private final String initialState;
 114  
 
 115  
     private final String endpointEncoding;
 116  
 
 117  
     private MuleContext muleContext;
 118  
 
 119  
     protected RetryPolicyTemplate retryPolicyTemplate;
 120  
 
 121  
     private String endpointBuilderName;
 122  
 
 123  
     private final String endpointMimeType;
 124  
 
 125  0
     private boolean disableTransportTransformer = false;
 126  
 
 127  
     public AbstractEndpoint(Connector connector,
 128  
                             EndpointURI endpointUri,
 129  
                             String name,
 130  
                             Map properties,
 131  
                             TransactionConfig transactionConfig,
 132  
                             boolean deleteUnacceptedMessages,
 133  
                             MessageExchangePattern messageExchangePattern,
 134  
                             int responseTimeout,
 135  
                             String initialState,
 136  
                             String endpointEncoding,
 137  
                             String endpointBuilderName,
 138  
                             MuleContext muleContext,
 139  
                             RetryPolicyTemplate retryPolicyTemplate,
 140  
                             EndpointMessageProcessorChainFactory messageProcessorsFactory,
 141  
                             List <MessageProcessor> messageProcessors,
 142  
                             List <MessageProcessor> responseMessageProcessors,
 143  
                             boolean disableTransportTransformer,
 144  
                             String endpointMimeType)
 145  0
     {
 146  0
         this.connector = connector;
 147  0
         this.endpointUri = endpointUri;
 148  0
         this.name = name;
 149  
         // TODO Properties should be immutable. See MULE-3105
 150  
         // this.properties = Collections.unmodifiableMap(properties);
 151  0
         this.properties.putAll(properties);
 152  0
         this.transactionConfig = transactionConfig;
 153  0
         this.deleteUnacceptedMessages = deleteUnacceptedMessages;
 154  
 
 155  0
         this.responseTimeout = responseTimeout;
 156  0
         this.initialState = initialState;
 157  0
         this.endpointEncoding = endpointEncoding;
 158  0
         this.endpointBuilderName = endpointBuilderName;
 159  0
         this.muleContext = muleContext;
 160  0
         this.retryPolicyTemplate = retryPolicyTemplate;
 161  0
         this.endpointMimeType = endpointMimeType;
 162  0
         this.disableTransportTransformer = disableTransportTransformer;
 163  
 
 164  0
         if (transactionConfig != null && transactionConfig.getFactory() != null &&
 165  
             transactionConfig.getAction() != TransactionConfig.ACTION_NONE &&
 166  
             transactionConfig.getAction() != TransactionConfig.ACTION_NEVER)
 167  
         {
 168  0
             if (logger.isDebugEnabled())
 169  
             {
 170  0
                 logger.debug("Endpoint has a transaction configuration. Defaulting to REQUEST_RESPONSE. Endpoint is: " + toString());
 171  
             }
 172  0
             this.messageExchangePattern = MessageExchangePattern.REQUEST_RESPONSE;
 173  
         }
 174  
         else
 175  
         {
 176  0
             this.messageExchangePattern = messageExchangePattern;
 177  
         }
 178  
 
 179  0
         this.messageProcessorsFactory = messageProcessorsFactory;
 180  0
         if (messageProcessors == null)
 181  
         {
 182  0
             this.messageProcessors = Collections.emptyList();
 183  
         }
 184  
         else
 185  
         {
 186  0
             this.messageProcessors = messageProcessors;
 187  
         }
 188  0
         if (responseMessageProcessors == null)
 189  
         {
 190  0
             this.responseMessageProcessors = Collections.emptyList();
 191  
         }
 192  
         else
 193  
         {
 194  0
             this.responseMessageProcessors = responseMessageProcessors;
 195  
         }
 196  0
     }
 197  
 
 198  
     public EndpointURI getEndpointURI()
 199  
     {
 200  0
         return endpointUri;
 201  
     }
 202  
 
 203  
     public String getAddress()
 204  
     {
 205  0
         EndpointURI uri = getEndpointURI();
 206  0
         if (uri != null)
 207  
         {
 208  0
             return uri.getUri().toString();
 209  
         }
 210  
         else
 211  
         {
 212  0
             return null;
 213  
         }
 214  
     }
 215  
 
 216  
     public String getEncoding()
 217  
     {
 218  0
         return endpointEncoding;
 219  
     }
 220  
 
 221  
     public String getMimeType()
 222  
     {
 223  0
         return endpointMimeType;
 224  
     }
 225  
 
 226  
     public Connector getConnector()
 227  
     {
 228  0
         return connector;
 229  
     }
 230  
 
 231  
     public String getName()
 232  
     {
 233  0
         return name;
 234  
     }
 235  
 
 236  
     public EndpointMessageProcessorChainFactory getMessageProcessorsFactory()
 237  
     {
 238  0
         return messageProcessorsFactory;
 239  
     }
 240  
 
 241  
     public List <MessageProcessor> getMessageProcessors()
 242  
     {
 243  0
         return messageProcessors;
 244  
     }
 245  
 
 246  
     public List <MessageProcessor> getResponseMessageProcessors()
 247  
     {
 248  0
         return responseMessageProcessors;
 249  
     }
 250  
 
 251  
     /** @deprecated use getMessageProcessors() */
 252  
     public List<Transformer> getTransformers()
 253  
     {
 254  0
         return getTransformersFromProcessorList(messageProcessors);
 255  
     }
 256  
 
 257  
     public Map getProperties()
 258  
     {
 259  0
         return properties;
 260  
     }
 261  
 
 262  
     public boolean isReadOnly()
 263  
     {
 264  0
         return true;
 265  
     }
 266  
 
 267  
     @Override
 268  
     public String toString()
 269  
     {
 270  
         // Use the interface to retrieve the string and set
 271  
         // the endpoint uri to a default value
 272  0
         String sanitizedEndPointUri = null;
 273  0
         URI uri = null;
 274  0
         if (endpointUri != null)
 275  
         {
 276  0
             sanitizedEndPointUri = endpointUri.toString();
 277  0
             uri = endpointUri.getUri();
 278  
         }
 279  
         // The following will further sanitize the endpointuri by removing
 280  
         // the embedded password. This will only remove the password if the
 281  
         // uri contains all the necessary information to successfully rebuild the url
 282  0
         if (uri != null && (uri.getRawUserInfo() != null) && (uri.getScheme() != null) && (uri.getHost() != null)
 283  
                 && (uri.getRawPath() != null))
 284  
         {
 285  
             // build a pattern up that matches what we need tp strip out the password
 286  0
             Pattern sanitizerPattern = Pattern.compile("(.*):.*");
 287  0
             Matcher sanitizerMatcher = sanitizerPattern.matcher(uri.getRawUserInfo());
 288  0
             if (sanitizerMatcher.matches())
 289  
             {
 290  0
                 sanitizedEndPointUri = new StringBuffer(uri.getScheme()).append("://")
 291  
                         .append(sanitizerMatcher.group(1))
 292  
                         .append(":<password>")
 293  
                         .append("@")
 294  
                         .append(uri.getHost())
 295  
                         .append(uri.getRawPath())
 296  
                         .toString();
 297  
             }
 298  0
             if (uri.getRawQuery() != null)
 299  
             {
 300  0
                 sanitizedEndPointUri = sanitizedEndPointUri + "?" + uri.getRawQuery();
 301  
             }
 302  
 
 303  
         }
 304  
 
 305  0
         return ClassUtils.getClassName(getClass()) + "{endpointUri=" + sanitizedEndPointUri + ", connector="
 306  
                 + connector + ",  name='" + name + "', mep=" + messageExchangePattern + ", properties=" + properties
 307  
                 + ", transactionConfig=" + transactionConfig + ", deleteUnacceptedMessages=" + deleteUnacceptedMessages
 308  
                 + ", initialState=" + initialState + ", responseTimeout="
 309  
                 + responseTimeout + ", endpointEncoding=" + endpointEncoding + ", disableTransportTransformer="
 310  
                 + disableTransportTransformer + "}";
 311  
     }
 312  
 
 313  
     public String getProtocol()
 314  
     {
 315  0
         return connector.getProtocol();
 316  
     }
 317  
 
 318  
     public TransactionConfig getTransactionConfig()
 319  
     {
 320  0
         return transactionConfig;
 321  
     }
 322  
 
 323  
     protected static boolean equal(Object a, Object b)
 324  
     {
 325  0
         return ClassUtils.equal(a, b);
 326  
     }
 327  
 
 328  
     @Override
 329  
     public boolean equals(Object obj)
 330  
     {
 331  0
         if (this == obj)
 332  
         {
 333  0
             return true;
 334  
         }
 335  0
         if (obj == null || getClass() != obj.getClass())
 336  
         {
 337  0
             return false;
 338  
         }
 339  
 
 340  0
         final AbstractEndpoint other = (AbstractEndpoint) obj;
 341  0
         return equal(retryPolicyTemplate, other.retryPolicyTemplate)
 342  
                 && equal(connector, other.connector)
 343  
                 && deleteUnacceptedMessages == other.deleteUnacceptedMessages
 344  
                 && equal(endpointEncoding, other.endpointEncoding)
 345  
                 && equal(endpointUri, other.endpointUri)
 346  
                 && equal(initialState, other.initialState)
 347  
                 // don't include lifecycle state as lifecycle code includes hashing
 348  
                 // && equal(initialised, other.initialised)
 349  
                 && equal(messageExchangePattern, other.messageExchangePattern)
 350  
                 && equal(name, other.name) 
 351  
                 && equal(properties, other.properties)
 352  
                 && responseTimeout == other.responseTimeout
 353  
                 && equal(messageProcessors, other.messageProcessors)
 354  
                 && equal(responseMessageProcessors, other.responseMessageProcessors)
 355  
                 && equal(transactionConfig, other.transactionConfig)
 356  
                 && disableTransportTransformer == other.disableTransportTransformer;
 357  
     }
 358  
 
 359  
     @Override
 360  
     public int hashCode()
 361  
     {
 362  0
         return ClassUtils.hash(new Object[]{this.getClass(), retryPolicyTemplate, connector,
 363  
                 deleteUnacceptedMessages ? Boolean.TRUE : Boolean.FALSE,
 364  
                 endpointEncoding,
 365  
                 endpointUri,
 366  
                 initialState,
 367  
                 // don't include lifecycle state as lifecycle code includes hashing
 368  
                 // initialised,
 369  
                 messageExchangePattern,
 370  
                 name,
 371  
                 properties, 
 372  
                 Integer.valueOf(responseTimeout),
 373  
                 responseMessageProcessors,
 374  
                 transactionConfig,
 375  
                 messageProcessors,
 376  
                 disableTransportTransformer ? Boolean.TRUE : Boolean.FALSE});
 377  
     }
 378  
 
 379  
     public Filter getFilter()
 380  
     {
 381  
         // Call the first MessageFilter in the chain "the filter".
 382  0
         for (MessageProcessor mp : messageProcessors)
 383  
         {
 384  0
             if (mp instanceof MessageFilter)
 385  
             {
 386  0
                 return ((MessageFilter) mp).getFilter();
 387  
             }
 388  
         }
 389  0
         return null;
 390  
     }
 391  
 
 392  
     public boolean isDeleteUnacceptedMessages()
 393  
     {
 394  0
         return deleteUnacceptedMessages;
 395  
     }
 396  
 
 397  
     /**
 398  
      * Returns an EndpointSecurityFilter for this endpoint. If one is not set, there
 399  
      * will be no authentication on events sent via this endpoint
 400  
      *
 401  
      * @return EndpointSecurityFilter responsible for authenticating message flow via
 402  
      *         this endpoint.
 403  
      * @see org.mule.api.security.EndpointSecurityFilter
 404  
      */
 405  
     public EndpointSecurityFilter getSecurityFilter()
 406  
     {
 407  0
         for (MessageProcessor mp : messageProcessors)
 408  
         {
 409  0
             if (mp instanceof SecurityFilterMessageProcessor)
 410  
             {
 411  0
                 SecurityFilter filter = ((SecurityFilterMessageProcessor)mp).getFilter();
 412  0
                 if (filter instanceof EndpointSecurityFilter)
 413  
                 {
 414  0
                     return (EndpointSecurityFilter) filter;
 415  
                 }
 416  0
             }
 417  
         }
 418  
 
 419  0
         return null;
 420  
     }
 421  
 
 422  
     public MessageExchangePattern getExchangePattern()
 423  
     {
 424  0
         return messageExchangePattern;
 425  
     }
 426  
 
 427  
     /**
 428  
      * The timeout value for remoteSync invocations
 429  
      *
 430  
      * @return the timeout in milliseconds
 431  
      */
 432  
     public int getResponseTimeout()
 433  
     {
 434  0
         return responseTimeout;
 435  
     }
 436  
 
 437  
     /**
 438  
      * Sets the state the endpoint will be loaded in. The States are 'stopped' and
 439  
      * 'started' (default)
 440  
      *
 441  
      * @return the endpoint starting state
 442  
      */
 443  
     public String getInitialState()
 444  
     {
 445  0
         return initialState;
 446  
     }
 447  
 
 448  
     /** @deprecated use getResponseMessageProcessors() */
 449  
     public List<Transformer> getResponseTransformers()
 450  
     {
 451  0
         return getTransformersFromProcessorList(responseMessageProcessors);
 452  
     }
 453  
 
 454  
     private List<Transformer> getTransformersFromProcessorList(List<MessageProcessor> processors)
 455  
     {
 456  0
         List<Transformer> transformers = new LinkedList<Transformer>();
 457  0
         for (MessageProcessor processor : processors)
 458  
         {
 459  0
             if (processor instanceof Transformer)
 460  
             {
 461  0
                 transformers.add((Transformer) processor);
 462  
             }
 463  0
             else if (processor instanceof MessageProcessorChain)
 464  
             {
 465  0
                 transformers.addAll(getTransformersFromProcessorList(((MessageProcessorChain) processor).getMessageProcessors()));
 466  
             }
 467  
         }
 468  0
         return transformers;
 469  
     }
 470  
 
 471  
     public Object getProperty(Object key)
 472  
     {
 473  0
         return properties.get(key);
 474  
     }
 475  
 
 476  
     public MuleContext getMuleContext()
 477  
     {
 478  0
         return muleContext;
 479  
     }
 480  
 
 481  
     public RetryPolicyTemplate getRetryPolicyTemplate()
 482  
     {
 483  0
         return retryPolicyTemplate;
 484  
     }
 485  
 
 486  
     public String getEndpointBuilderName()
 487  
     {
 488  0
         return endpointBuilderName;
 489  
     }
 490  
 
 491  
     public boolean isProtocolSupported(String protocol)
 492  
     {
 493  0
         return connector.supportsProtocol(protocol);
 494  
     }
 495  
     
 496  
     public boolean isDisableTransportTransformer() 
 497  
     {
 498  0
         return disableTransportTransformer;
 499  
     }
 500  
 
 501  
     public void dispose()
 502  
     {
 503  0
         this.muleContext = null;
 504  
         //this.messageProcessors.clear();
 505  
         // Don't clear this, since it changes the hash code, which can foul up shutdown processing
 506  
         // when objects have been keyed by endpoint, e.g. dispatchers
 507  0
         this.messageProcessorChain = null;
 508  0
     }
 509  
 
 510  
     public MessageProcessor getMessageProcessorChain(FlowConstruct flowContruct) throws MuleException
 511  
     {
 512  0
         if (messageProcessorChain == null)
 513  
         {
 514  0
             messageProcessorChain = createMessageProcessorChain(flowContruct);
 515  
         }
 516  0
         return messageProcessorChain;
 517  
     }
 518  
 
 519  
     abstract protected MessageProcessor createMessageProcessorChain(FlowConstruct flowContruct) throws MuleException;
 520  
 }