Coverage Report - org.mule.impl.model.AbstractComponent
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractComponent
61%
124/202
49%
35/72
2.293
 
 1  
 /*
 2  
  * $Id: AbstractComponent.java 10415 2008-01-21 10:46:37Z 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.impl.model;
 12  
 
 13  
 import org.mule.MuleManager;
 14  
 import org.mule.config.i18n.CoreMessages;
 15  
 import org.mule.config.i18n.MessageFactory;
 16  
 import org.mule.impl.DefaultComponentExceptionStrategy;
 17  
 import org.mule.impl.MuleDescriptor;
 18  
 import org.mule.impl.OptimizedRequestContext;
 19  
 import org.mule.impl.internal.notifications.ComponentNotification;
 20  
 import org.mule.management.stats.ComponentStatistics;
 21  
 import org.mule.providers.AbstractConnector;
 22  
 import org.mule.umo.ComponentException;
 23  
 import org.mule.umo.UMOComponent;
 24  
 import org.mule.umo.UMODescriptor;
 25  
 import org.mule.umo.UMOEvent;
 26  
 import org.mule.umo.UMOException;
 27  
 import org.mule.umo.UMOMessage;
 28  
 import org.mule.umo.endpoint.UMOEndpoint;
 29  
 import org.mule.umo.endpoint.UMOImmutableEndpoint;
 30  
 import org.mule.umo.lifecycle.InitialisationException;
 31  
 import org.mule.umo.model.ModelException;
 32  
 import org.mule.umo.model.UMOModel;
 33  
 import org.mule.umo.provider.DispatchException;
 34  
 import org.mule.umo.provider.UMOMessageReceiver;
 35  
 import org.mule.util.concurrent.WaitableBoolean;
 36  
 
 37  
 import java.beans.ExceptionListener;
 38  
 import java.util.ArrayList;
 39  
 import java.util.Iterator;
 40  
 import java.util.List;
 41  
 
 42  
 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
 43  
 
 44  
 import org.apache.commons.logging.Log;
 45  
 import org.apache.commons.logging.LogFactory;
 46  
 
 47  
 /**
 48  
  * A base implementation for all UMOComponents in Mule
 49  
  */
 50  
 public abstract class AbstractComponent implements UMOComponent
 51  
 {
 52  
     /**
 53  
      * logger used by this class
 54  
      */
 55  358
     protected transient Log logger = LogFactory.getLog(getClass());
 56  
 
 57  
     /**
 58  
      * The Mule descriptor associated with the component
 59  
      */
 60  358
     protected MuleDescriptor descriptor = null;
 61  
 
 62  358
     protected ComponentStatistics stats = null;
 63  
 
 64  
     /**
 65  
      * Determines if the component has been stopped
 66  
      */
 67  358
     protected AtomicBoolean stopped = new AtomicBoolean(true);
 68  
 
 69  
     /**
 70  
      * Determines whether stop has been called and is still in progress
 71  
      */
 72  358
     protected WaitableBoolean stopping = new WaitableBoolean(false);
 73  
 
 74  
     /**
 75  
      * determines if the proxy pool has been initialised
 76  
      */
 77  358
     protected AtomicBoolean poolInitialised = new AtomicBoolean(false);
 78  
 
 79  
     /**
 80  
      * The exception strategy used by the component, this is provided by the
 81  
      * UMODescriptor
 82  
      */
 83  358
     protected ExceptionListener exceptionListener = null;
 84  
 
 85  
     /**
 86  
      * Determines if the component has been initilised
 87  
      */
 88  358
     protected AtomicBoolean initialised = new AtomicBoolean(false);
 89  
 
 90  
     /**
 91  
      * The model in which this component is registered
 92  
      */
 93  
     protected UMOModel model;
 94  
 
 95  
     /**
 96  
      * Determines if the component has been paused
 97  
      */
 98  358
     protected WaitableBoolean paused = new WaitableBoolean(false);
 99  
 
 100  
     /**
 101  
      * Default constructor
 102  
      */
 103  
     public AbstractComponent(MuleDescriptor descriptor, UMOModel model)
 104  358
     {
 105  358
         if (descriptor == null)
 106  
         {
 107  0
             throw new IllegalArgumentException("Descriptor cannot be null");
 108  
         }
 109  358
         this.descriptor = descriptor;
 110  358
         this.model = model;
 111  358
     }
 112  
 
 113  
     /**
 114  
      * Initialise the component. The component will first create a Mule UMO from the
 115  
      * UMODescriptor and then initialise a pool based on the attributes in the
 116  
      * UMODescriptor.
 117  
      * 
 118  
      * @throws org.mule.umo.lifecycle.InitialisationException if the component fails
 119  
      *             to initialise
 120  
      * @see org.mule.umo.UMODescriptor
 121  
      */
 122  
     public final synchronized void initialise() throws InitialisationException
 123  
     {
 124  46
         if (initialised.get())
 125  
         {
 126  2
             throw new InitialisationException(
 127  
                 CoreMessages.objectAlreadyInitialised("Component '" + descriptor.getName() + "'"), this);
 128  
         }
 129  44
         descriptor.initialise();
 130  
 
 131  44
         this.exceptionListener = descriptor.getExceptionListener();
 132  
 
 133  
         // initialise statistics
 134  44
         stats = createStatistics();
 135  
 
 136  44
         stats.setEnabled(((MuleManager) MuleManager.getInstance()).getStatistics().isEnabled());
 137  44
         ((MuleManager) MuleManager.getInstance()).getStatistics().add(stats);
 138  44
         stats.setOutboundRouterStat(getDescriptor().getOutboundRouter().getStatistics());
 139  44
         stats.setInboundRouterStat(getDescriptor().getInboundRouter().getStatistics());
 140  
 
 141  44
         doInitialise();
 142  44
         initialised.set(true);
 143  44
         fireComponentNotification(ComponentNotification.COMPONENT_INITIALISED);
 144  
 
 145  44
     }
 146  
 
 147  
     protected ComponentStatistics createStatistics()
 148  
     {
 149  10
         return new ComponentStatistics(getName(),
 150  
             descriptor.getThreadingProfile().getMaxThreadsActive());
 151  
     }
 152  
 
 153  
     protected void fireComponentNotification(int action)
 154  
     {
 155  200
         MuleManager.getInstance().fireNotification(new ComponentNotification(descriptor, action));
 156  200
     }
 157  
 
 158  
     public void forceStop() throws UMOException
 159  
     {
 160  0
         if (!stopped.get())
 161  
         {
 162  0
             logger.debug("Stopping UMOComponent");
 163  0
             stopping.set(true);
 164  0
             fireComponentNotification(ComponentNotification.COMPONENT_STOPPING);
 165  0
             doForceStop();
 166  0
             stopped.set(true);
 167  0
             stopping.set(false);
 168  0
             fireComponentNotification(ComponentNotification.COMPONENT_STOPPED);
 169  
         }
 170  0
     }
 171  
 
 172  
     public void stop() throws UMOException
 173  
     {
 174  40
         if (!stopped.get())
 175  
         {
 176  34
             logger.debug("Stopping UMOComponent");
 177  34
             stopping.set(true);
 178  34
             fireComponentNotification(ComponentNotification.COMPONENT_STOPPING);
 179  
 
 180  
             // Unregister Listeners for the component
 181  34
             unregisterListeners();
 182  
 
 183  34
             doStop();
 184  34
             stopped.set(true);
 185  34
             initialised.set(false);
 186  34
             fireComponentNotification(ComponentNotification.COMPONENT_STOPPED);
 187  
         }
 188  40
     }
 189  
 
 190  
     public void start() throws UMOException
 191  
     {
 192  42
         start(false);
 193  30
     }
 194  
 
 195  
     /**
 196  
      * Starts a Mule Component.
 197  
      * 
 198  
      * @param startPaused - Start component in a "paused" state (messages are
 199  
      *            received but not processed).
 200  
      */
 201  
     protected void start(boolean startPaused) throws UMOException
 202  
     {
 203  
 
 204  
         // Create the receivers for the component but do not start them yet.
 205  42
         registerListeners();
 206  
 
 207  
         // We connect the receivers _before_ starting the component because there may
 208  
         // be
 209  
         // some initialization required for the component which needs to have them
 210  
         // connected.
 211  
         // For example, the org.mule.providers.soap.glue.GlueMessageReceiver adds
 212  
         // InitialisationCallbacks within its doConnect() method (see MULE-804).
 213  42
         connectListeners();
 214  
 
 215  
         // Start (and pause) the component.
 216  42
         if (stopped.get())
 217  
         {
 218  40
             stopped.set(false);
 219  40
             paused.set(false);
 220  40
             doStart();
 221  
         }
 222  30
         fireComponentNotification(ComponentNotification.COMPONENT_STARTED);
 223  30
         if (startPaused)
 224  
         {
 225  0
             pause();
 226  
         }
 227  
 
 228  
         // We start the receivers _after_ starting the component because if a message
 229  
         // gets routed to the component before it is started,
 230  
         // org.mule.impl.model.AbstractComponent.dispatchEvent() will throw a
 231  
         // ComponentException with message COMPONENT_X_IS_STOPPED (see MULE-526).
 232  30
         startListeners();
 233  30
     }
 234  
 
 235  
     /**
 236  
      * Pauses event processing for a single Mule Component. Unlike stop(), a paused
 237  
      * component will still consume messages from the underlying transport, but those
 238  
      * messages will be queued until the component is resumed.
 239  
      */
 240  
     public final void pause() throws UMOException
 241  
     {
 242  
 
 243  10
         doPause();
 244  8
         paused.set(true);
 245  8
         fireComponentNotification(ComponentNotification.COMPONENT_PAUSED);
 246  8
     }
 247  
 
 248  
     /**
 249  
      * Resumes a single Mule Component that has been paused. If the component is not
 250  
      * paused nothing is executed.
 251  
      */
 252  
     public final void resume() throws UMOException
 253  
     {
 254  16
         doResume();
 255  12
         paused.set(false);
 256  12
         fireComponentNotification(ComponentNotification.COMPONENT_RESUMED);
 257  12
     }
 258  
 
 259  
     /**
 260  
      * Determines if the component is in a paused state
 261  
      * 
 262  
      * @return True if the component is in a paused state, false otherwise
 263  
      */
 264  
     public boolean isPaused()
 265  
     {
 266  32
         return paused.get();
 267  
     }
 268  
 
 269  
     /**
 270  
      * Custom components can execute code necessary to put the component in a paused
 271  
      * state here. If a developer overloads this method the doResume() method MUST
 272  
      * also be overloaded to avoid inconsistent state in the component
 273  
      * 
 274  
      * @throws UMOException
 275  
      */
 276  
     protected void doPause() throws UMOException
 277  
     {
 278  
         // template method
 279  2
     }
 280  
 
 281  
     /**
 282  
      * Custom components can execute code necessary to resume a component once it has
 283  
      * been paused If a developer overloads this method the doPause() method MUST
 284  
      * also be overloaded to avoid inconsistent state in the component
 285  
      * 
 286  
      * @throws UMOException
 287  
      */
 288  
     protected void doResume() throws UMOException
 289  
     {
 290  
         // template method
 291  2
     }
 292  
 
 293  
     public final void dispose()
 294  
     {
 295  
         try
 296  
         {
 297  42
             if (!stopped.get())
 298  
             {
 299  10
                 stop();
 300  
             }
 301  
         }
 302  0
         catch (UMOException e)
 303  
         {
 304  
             // Failed to stop the component. But since we're being disposed now anyway, we can
 305  
             // only log this failure and continue cleaning up
 306  0
             logger.error("Failed to stop component: " + descriptor.getName(), e);
 307  42
         }
 308  42
         doDispose();
 309  38
         fireComponentNotification(ComponentNotification.COMPONENT_DISPOSED);
 310  38
         ((MuleManager) MuleManager.getInstance()).getStatistics().remove(stats);
 311  38
     }
 312  
 
 313  
     public ComponentStatistics getStatistics()
 314  
     {
 315  34
         return stats;
 316  
     }
 317  
 
 318  
     /*
 319  
      * (non-Javadoc)
 320  
      * 
 321  
      * @see org.mule.umo.UMOSession#getDescriptor()
 322  
      */
 323  
     public UMODescriptor getDescriptor()
 324  
     {
 325  846
         return descriptor;
 326  
     }
 327  
 
 328  
     public void dispatchEvent(UMOEvent event) throws UMOException
 329  
     {
 330  2
         if (stopping.get() || stopped.get())
 331  
         {
 332  2
             throw new ComponentException(
 333  
                 CoreMessages.componentIsStopped(this.getDescriptor().getName()), 
 334  
                 event.getMessage(), this);
 335  
         }
 336  
 
 337  
         try
 338  
         {
 339  0
             waitIfPaused(event);
 340  
         }
 341  0
         catch (InterruptedException e)
 342  
         {
 343  0
             throw new ComponentException(event.getMessage(), this, e);
 344  0
         }
 345  
 
 346  
         // Dispatching event to an inbound endpoint
 347  
         // in the MuleSession#dispatchEvent
 348  0
         UMOImmutableEndpoint endpoint = event.getEndpoint();
 349  
 
 350  0
         if (!endpoint.canReceive())
 351  
         {
 352  
             try
 353  
             {
 354  0
                 endpoint.dispatch(event);
 355  
             }
 356  0
             catch (Exception e)
 357  
             {
 358  0
                 throw new DispatchException(event.getMessage(), event.getEndpoint(), e);
 359  0
             }
 360  
 
 361  0
             return;
 362  
         }
 363  
 
 364  
         // Dispatching event to the component
 365  0
         if (stats.isEnabled())
 366  
         {
 367  0
             stats.incReceivedEventASync();
 368  
         }
 369  
 
 370  0
         if (logger.isDebugEnabled())
 371  
         {
 372  0
             logger.debug("Component: " + descriptor.getName() + " has received asynchronous event on: "
 373  
                          + event.getEndpoint().getEndpointURI());
 374  
         }
 375  
 
 376  0
         doDispatch(event);
 377  0
     }
 378  
 
 379  
     public UMOMessage sendEvent(UMOEvent event) throws UMOException
 380  
     {
 381  10
         if (stopping.get() || stopped.get())
 382  
         {
 383  2
             throw new ComponentException(
 384  
                 CoreMessages.componentIsStopped(this.getDescriptor().getName()), 
 385  
                 event.getMessage(), this);
 386  
         }
 387  
 
 388  
         try
 389  
         {
 390  8
             waitIfPaused(event);
 391  
         }
 392  0
         catch (InterruptedException e)
 393  
         {
 394  0
             throw new ComponentException(event.getMessage(), this, e);
 395  8
         }
 396  
 
 397  8
         if (stats.isEnabled())
 398  
         {
 399  0
             stats.incReceivedEventSync();
 400  
         }
 401  8
         if (logger.isDebugEnabled())
 402  
         {
 403  0
             logger.debug("Component: " + descriptor.getName() + " has received synchronous event on: "
 404  
                          + event.getEndpoint().getEndpointURI());
 405  
         }
 406  8
         event = OptimizedRequestContext.unsafeSetEvent(event);
 407  8
         return doSend(event);
 408  
     }
 409  
 
 410  
     /**
 411  
      * Called before an event is sent or dispatched to a component, it will block
 412  
      * until resume() is called. Users can override this method if they want to
 413  
      * handle pausing differently e.g. implement a store and forward policy
 414  
      * 
 415  
      * @param event the current event being passed to the component
 416  
      * @throws InterruptedException if the thread is interrupted
 417  
      */
 418  
     protected void waitIfPaused(UMOEvent event) throws InterruptedException
 419  
     {
 420  8
         if (logger.isDebugEnabled() && paused.get())
 421  
         {
 422  0
             logger.debug("Component: " + descriptor.getName()
 423  
                          + " is paused. Blocking call until resume is called");
 424  
         }
 425  8
         paused.whenFalse(null);
 426  8
     }
 427  
 
 428  
     /**
 429  
      * @return the Mule descriptor name which is associated with the component
 430  
      */
 431  
     public String getName()
 432  
     {
 433  46
         return descriptor.getName();
 434  
     }
 435  
 
 436  
     /*
 437  
      * (non-Javadoc)
 438  
      * 
 439  
      * @see java.lang.Object#toString()
 440  
      */
 441  
     public String toString()
 442  
     {
 443  74
         return descriptor.getName();
 444  
     }
 445  
 
 446  
     public boolean isStopped()
 447  
     {
 448  0
         return stopped.get();
 449  
     }
 450  
 
 451  
     public boolean isStopping()
 452  
     {
 453  0
         return stopping.get();
 454  
     }
 455  
 
 456  
     protected void handleException(Exception e)
 457  
     {
 458  0
         if (exceptionListener instanceof DefaultComponentExceptionStrategy)
 459  
         {
 460  0
             if (((DefaultComponentExceptionStrategy) exceptionListener).getComponent() == null)
 461  
             {
 462  0
                 ((DefaultComponentExceptionStrategy) exceptionListener).setComponent(this);
 463  
             }
 464  
         }
 465  0
         exceptionListener.exceptionThrown(e);
 466  0
     }
 467  
 
 468  
     /**
 469  
      * Provides a consistent mechanism for custom models to create components.
 470  
      * 
 471  
      * @return
 472  
      * @throws UMOException
 473  
      */
 474  
     protected Object lookupComponent() throws UMOException
 475  
     {
 476  10
         return ComponentFactory.createComponent(getDescriptor());
 477  
     }
 478  
 
 479  
     protected void doForceStop() throws UMOException
 480  
     {
 481  
         // template method
 482  0
     }
 483  
 
 484  
     protected void doStop() throws UMOException
 485  
     {
 486  
         // template method
 487  0
     }
 488  
 
 489  
     protected void doStart() throws UMOException
 490  
     {
 491  
         // template method
 492  0
     }
 493  
 
 494  
     protected void doDispose()
 495  
     {
 496  
         // template method
 497  0
     }
 498  
 
 499  
     protected void doInitialise() throws InitialisationException
 500  
     {
 501  
         // template method
 502  0
     }
 503  
 
 504  
     public boolean isStarted()
 505  
     {
 506  42
         return !stopped.get();
 507  
     }
 508  
 
 509  
     protected abstract UMOMessage doSend(UMOEvent event) throws UMOException;
 510  
 
 511  
     protected abstract void doDispatch(UMOEvent event) throws UMOException;
 512  
 
 513  
     public Object getInstance() throws UMOException
 514  
     {
 515  0
         return lookupComponent();
 516  
     }
 517  
 
 518  
     protected void registerListeners() throws UMOException
 519  
     {
 520  
         UMOEndpoint endpoint;
 521  42
         List endpoints = getIncomingEndpoints();
 522  
 
 523  42
         for (Iterator it = endpoints.iterator(); it.hasNext();)
 524  
         {
 525  22
             endpoint = (UMOEndpoint) it.next();
 526  
             try
 527  
             {
 528  22
                 endpoint.getConnector().registerListener(this, endpoint);
 529  
             }
 530  0
             catch (UMOException e)
 531  
             {
 532  0
                 throw e;
 533  
             }
 534  0
             catch (Exception e)
 535  
             {
 536  0
                 throw new ModelException(
 537  
                     CoreMessages.failedtoRegisterOnEndpoint(this.getDescriptor().getName(),
 538  
                         endpoint.getEndpointURI()), e);
 539  22
             }
 540  
         }
 541  42
     }
 542  
 
 543  
     protected void unregisterListeners() throws UMOException
 544  
     {
 545  
         UMOEndpoint endpoint;
 546  34
         List endpoints = getIncomingEndpoints();
 547  
 
 548  34
         for (Iterator it = endpoints.iterator(); it.hasNext();)
 549  
         {
 550  22
             endpoint = (UMOEndpoint) it.next();
 551  
             try
 552  
             {
 553  22
                 endpoint.getConnector().unregisterListener(this, endpoint);
 554  
             }
 555  0
             catch (UMOException e)
 556  
             {
 557  0
                 throw e;
 558  
             }
 559  0
             catch (Exception e)
 560  
             {
 561  0
                 throw new ModelException(
 562  
                     CoreMessages.failedToUnregister(this.getDescriptor().getName(), 
 563  
                         endpoint.getEndpointURI()), e);
 564  22
             }
 565  
         }
 566  34
     }
 567  
 
 568  
     protected void startListeners() throws UMOException
 569  
     {
 570  
         UMOEndpoint endpoint;
 571  30
         List endpoints = getIncomingEndpoints();
 572  
 
 573  30
         for (Iterator it = endpoints.iterator(); it.hasNext();)
 574  
         {
 575  12
             endpoint = (UMOEndpoint) it.next();
 576  12
             UMOMessageReceiver receiver = ((AbstractConnector) endpoint.getConnector()).getReceiver(this,
 577  
                 endpoint);
 578  12
             if (receiver != null && endpoint.getConnector().isStarted()
 579  
                 && endpoint.getInitialState().equals(UMOEndpoint.INITIAL_STATE_STARTED))
 580  
             {
 581  12
                 receiver.start();
 582  
             }
 583  12
         }
 584  30
     }
 585  
 
 586  
     protected void stopListeners() throws UMOException
 587  
     {
 588  
         UMOEndpoint endpoint;
 589  0
         List endpoints = getIncomingEndpoints();
 590  
 
 591  0
         for (Iterator it = endpoints.iterator(); it.hasNext();)
 592  
         {
 593  0
             endpoint = (UMOEndpoint) it.next();
 594  0
             UMOMessageReceiver receiver = ((AbstractConnector) endpoint.getConnector()).getReceiver(this,
 595  
                 endpoint);
 596  0
             if (receiver != null)
 597  
             {
 598  0
                 receiver.stop();
 599  
             }
 600  0
         }
 601  0
     }
 602  
 
 603  
     protected void connectListeners() throws UMOException
 604  
     {
 605  
         UMOEndpoint endpoint;
 606  42
         List endpoints = getIncomingEndpoints();
 607  
 
 608  42
         for (Iterator it = endpoints.iterator(); it.hasNext();)
 609  
         {
 610  22
             endpoint = (UMOEndpoint) it.next();
 611  22
             UMOMessageReceiver receiver = ((AbstractConnector) endpoint.getConnector()).getReceiver(this,
 612  
                 endpoint);
 613  22
             if (receiver != null)
 614  
             {
 615  
                 try
 616  
                 {
 617  22
                     receiver.connect();
 618  
                 }
 619  0
                 catch (Exception e)
 620  
                 {
 621  0
                     throw new ModelException(
 622  
                         MessageFactory.createStaticMessage("Failed to connect listener "
 623  
                                     + receiver + " for endpoint " + endpoint.getName()),
 624  
                         e);
 625  22
                 }
 626  
             }
 627  22
         }
 628  42
     }
 629  
 
 630  
     protected void disconnectListeners() throws UMOException
 631  
     {
 632  
         UMOEndpoint endpoint;
 633  0
         List endpoints = getIncomingEndpoints();
 634  
 
 635  0
         for (Iterator it = endpoints.iterator(); it.hasNext();)
 636  
         {
 637  0
             endpoint = (UMOEndpoint) it.next();
 638  0
             UMOMessageReceiver receiver = ((AbstractConnector) endpoint.getConnector()).getReceiver(this,
 639  
                 endpoint);
 640  0
             if (receiver != null)
 641  
             {
 642  
                 try
 643  
                 {
 644  0
                     receiver.disconnect();
 645  
                 }
 646  0
                 catch (Exception e)
 647  
                 {
 648  0
                     throw new ModelException(
 649  
                         MessageFactory.createStaticMessage("Failed to disconnect listener "
 650  
                                     + receiver + " for endpoint " + endpoint.getName()),
 651  
                         e);
 652  0
                 }
 653  
             }
 654  0
         }
 655  0
     }
 656  
 
 657  
     /**
 658  
      * Returns a list of all incoming endpoints on a component.
 659  
      */
 660  
     protected List getIncomingEndpoints()
 661  
     {
 662  148
         List endpoints = new ArrayList();
 663  
 
 664  
         // Add inbound endpoints
 665  148
         endpoints.addAll(getDescriptor().getInboundRouter().getEndpoints());
 666  
         // Add the (deprecated) single inbound endpoint.
 667  148
         if (getDescriptor().getInboundEndpoint() != null)
 668  
         {
 669  78
             endpoints.add(getDescriptor().getInboundEndpoint());
 670  
         }
 671  
 
 672  
         // Add response endpoints
 673  148
         if (getDescriptor().getResponseRouter() != null
 674  
             && getDescriptor().getResponseRouter().getEndpoints() != null)
 675  
         {
 676  0
             endpoints.addAll(getDescriptor().getResponseRouter().getEndpoints());
 677  
         }
 678  148
         return endpoints;
 679  
     }
 680  
 
 681  
 }