/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.synapse.mediators.throttle;
import org.apache.axiom.om.OMElement;
import org.apache.axis2.clustering.ClusteringAgent;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.neethi.PolicyEngine;
import org.apache.synapse.*;
import org.apache.synapse.aspects.AspectConfiguration;
import org.apache.synapse.aspects.ComponentType;
import org.apache.synapse.aspects.flow.statistics.StatisticIdentityGenerator;
import org.apache.synapse.aspects.flow.statistics.collectors.RuntimeStatisticCollector;
import org.apache.synapse.aspects.flow.statistics.data.artifact.ArtifactHolder;
import org.apache.synapse.config.Entry;
import org.apache.synapse.config.SynapseConfiguration;
import org.apache.synapse.continuation.ContinuationStackManager;
import org.apache.synapse.continuation.ReliantContinuationState;
import org.apache.synapse.core.axis2.Axis2MessageContext;
import org.apache.synapse.core.SynapseEnvironment;
import org.apache.synapse.core.axis2.Axis2SynapseEnvironment;
import org.apache.synapse.debug.constructs.EnclosedInlinedSequence;
import org.apache.synapse.mediators.AbstractMediator;
import org.apache.synapse.mediators.FlowContinuableMediator;
import org.apache.synapse.mediators.base.SequenceMediator;
import org.apache.synapse.transport.nhttp.NhttpConstants;
import org.apache.synapse.commons.throttle.core.AccessRateController;
import org.apache.synapse.commons.throttle.core.ConcurrentAccessController;
import org.apache.synapse.commons.throttle.core.ConcurrentAccessReplicator;
import org.apache.synapse.commons.throttle.core.Throttle;
import org.apache.synapse.commons.throttle.core.ThrottleConstants;
import org.apache.synapse.commons.throttle.core.ThrottleDataHolder;
import org.apache.synapse.commons.throttle.core.ThrottleConfiguration;
import org.apache.synapse.commons.throttle.core.ThrottleException;
import org.apache.synapse.commons.throttle.core.ThrottleContext;
import org.apache.synapse.commons.throttle.core.AccessInformation;
import org.apache.synapse.commons.throttle.core.ThrottleFactory;
/**
* The Mediator for the throttling - Throttling will occur according to the ws-policy
* which is specified as the key for lookup from the registry or the inline policy
* Throttling can be applied on IP or Domain of the remote caller.Now has support for either
* Distributed or Standalone throttling schemes. Support two modes of throttling Concurrency and
* Access rate based throttling In concurrency based throttling - throttling ignores remote callers
* IP or Domains Considers only concurrent message flows at a given time. Access rate based
* throttling is bound to a particular remote caller.
*/
public class ThrottleMediator extends AbstractMediator implements ManagedLifecycle,
FlowContinuableMediator, EnclosedInlinedSequence {
/* The key for getting the throttling policy - key refers to a/an [registry] entry */
private String policyKey = null;
/* InLine policy object - XML */
private OMElement inLinePolicy = null;
/* The reference to the sequence which will execute when access is denied */
private String onRejectSeqKey = null;
/* The in-line sequence which will execute when access is denied */
private Mediator onRejectMediator = null;
/* The reference to the sequence which will execute when access is allowed */
private String onAcceptSeqKey = null;
/* The in-line sequence which will execute when access is allowed */
private Mediator onAcceptMediator = null;
/* The concurrent access control group id */
private String id;
/* Access rate controller - limit the remote caller access*/
private AccessRateController accessControler;
/* ConcurrentAccessController - limit the remote callers concurrent access */
private ConcurrentAccessController concurrentAccessController = null;
/* Replicates the concurrent access of remote across the cluster */
private ConcurrentAccessReplicator concurrentAccessReplicator;
/* Configuration where Throttle data is being kept */
private ConfigurationContext configContext;
/*Throttle Data is kept inside this holder eg :- Caller contexts */
private ThrottleDataHolder dataHolder;
/* The property key that used when the ConcurrentAccessController
look up from ThrottleDataHolder */
private String key;
/* Is this env. support clustering*/
private boolean isClusteringEnable = false;
/* The Throttle object - holds all runtime and configuration data */
private Throttle throttle;
/* Lock used to ensure thread-safe creation of the throttle
when throttle is created dynamically */
private final Object throttleLock = new Object();
/* Last version of dynamic policy resource*/
private long version;
public ThrottleMediator() {
}
public boolean mediate(MessageContext synCtx) {
if (synCtx.getEnvironment().isDebuggerEnabled()) {
if (super.divertMediationRoute(synCtx)) {
return true;
}
}
SynapseLog synLog = getLog(synCtx);
boolean isResponse = synCtx.isResponse();
boolean canAccess = true;
if (!isResponse) {
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Start : Throttle mediator");
if (synLog.isTraceTraceEnabled()) {
synLog.traceTrace("Message : " + synCtx.getEnvelope());
}
}
//we consider dynamic loading of policy loading only for the request flow mediation
//we ignore policy initialization for the response flow case we use the existing policy
//reference throttling only applies for request flow mediation
doInitializeThrottleDynamicPolicy(synCtx, synLog);
//in cluster environment local reference to concurrent access controller should be
//updated, local reference kept inside Throttle mediator maybe expired as a
//consequence of global concurrent access change with
//respect to controller we maintain at configuration context
if (isClusteringEnable) {
reloadDistributedConcurrentAccessController(synLog);
}
//throttle by concurrency is given the highest priority, if another throttling
// scheme fails eg :- rate based from this point onward Eg:- access rate
// checks we need to rollback the previous
if (concurrentAccessController != null) {
canAccess = doThrottleByConcurrency(isResponse, synLog);
}
//if the access is success through concurrency throttle and if this is a request message
//then do access rate based throttling
if (throttle != null && !isResponse && canAccess) {
org.apache.axis2.context.MessageContext axisMC =
((Axis2MessageContext) synCtx).getAxis2MessageContext();
canAccess = doThrottleByAccessRate(synCtx, axisMC, configContext, synLog);
}
// all the replication functionality of the access rate and concurrency based
// throttling handles by itself at throttle core level but for the the concurrency case
// this is done explicitly forcing as we make concurrent global state change available
// to other cluster nodes as synchronous manner
if (isClusteringEnable && concurrentAccessController != null) {
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Going to replicates the " +
"states of the ConcurrentAccessController with key : " + key);
}
concurrentAccessReplicator.replicate(key, concurrentAccessController);
}
if (concurrentAccessController != null) {
//maintain properties in message context for the concurrency throttling
synCtx.setProperty(SynapseConstants.SYNAPSE_CONCURRENCY_THROTTLE, true);
//maintain properties in message context for the concurrency throttling
synCtx.setProperty(SynapseConstants.SYNAPSE_CONCURRENCY_THROTTLE_KEY, key);
//maintain properties in message context for the concurrency throttling
synCtx.setProperty(SynapseConstants.SYNAPSE_CONCURRENT_ACCESS_CONTROLLER,
concurrentAccessController);
}
//maintain properties in message context for the concurrency throttling
if (isClusteringEnable) {
synCtx.setProperty(SynapseConstants.SYNAPSE_CONCURRENT_ACCESS_REPLICATOR,
concurrentAccessReplicator);
}
//depending on the subsequent throttling controller outcome from this point
// onwards mediation flow branches to either accept sequence or reject sequence
if (canAccess) {
//accept case
if (onAcceptSeqKey != null) {
Mediator mediator = synCtx.getSequence(onAcceptSeqKey);
if (mediator != null) {
ContinuationStackManager.updateSeqContinuationState(synCtx,
getMediatorPosition());
return mediator.mediate(synCtx);
} else {
handleException("Unable to find onAccept sequence with key : "
+ onAcceptSeqKey, synCtx);
}
} else if (onAcceptMediator != null) {
ContinuationStackManager.addReliantContinuationState(synCtx, 0,
getMediatorPosition());
boolean result = onAcceptMediator.mediate(synCtx);
if (result) {
ContinuationStackManager.removeReliantContinuationState(synCtx);
}
return result;
} else {
return true;
}
} else {
//reject case
if (onRejectSeqKey != null) {
Mediator mediator = synCtx.getSequence(onRejectSeqKey);
if (mediator != null) {
ContinuationStackManager.updateSeqContinuationState(synCtx,
getMediatorPosition());
return mediator.mediate(synCtx);
} else {
handleException("Unable to find onReject sequence with key : "
+ onRejectSeqKey, synCtx);
}
} else if (onRejectMediator != null) {
ContinuationStackManager.addReliantContinuationState(synCtx, 1,
getMediatorPosition());
boolean result = onRejectMediator.mediate(synCtx);
if (result) {
ContinuationStackManager.removeReliantContinuationState(synCtx);
}
return result;
} else {
return false;
}
}
}
synLog.traceOrDebug("End : Throttle mediator");
return canAccess;
}
public boolean mediate(MessageContext synCtx, ContinuationState continuationState) {
SynapseLog synLog = getLog(synCtx);
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Throttle mediator : Mediating from ContinuationState");
}
boolean result;
boolean isStatisticsEnabled = RuntimeStatisticCollector.isStatisticsEnabled();
int subBranch = ((ReliantContinuationState) continuationState).getSubBranch();
if (subBranch == 0) {
if (!continuationState.hasChild()) {
result = ((SequenceMediator) onAcceptMediator).
mediate(synCtx, continuationState.getPosition() + 1);
} else {
FlowContinuableMediator mediator =
(FlowContinuableMediator) ((SequenceMediator) onAcceptMediator).
getChild(continuationState.getPosition());
result = mediator.mediate(synCtx, continuationState.getChildContState());
if (isStatisticsEnabled) {
((Mediator) mediator).reportCloseStatistics(synCtx, null);
}
}
if (isStatisticsEnabled) {
onAcceptMediator.reportCloseStatistics(synCtx, null);
}
} else {
if (!continuationState.hasChild()) {
result = ((SequenceMediator) onRejectMediator).
mediate(synCtx, continuationState.getPosition() + 1);
} else {
FlowContinuableMediator mediator =
(FlowContinuableMediator) ((SequenceMediator) onRejectMediator).getChild(
continuationState.getPosition());
result = mediator.mediate(synCtx, continuationState.getChildContState());
if (isStatisticsEnabled) {
((Mediator) mediator).reportCloseStatistics(synCtx, null);
}
}
if (isStatisticsEnabled) {
onRejectMediator.reportCloseStatistics(synCtx, null);
}
}
return result;
}
/**
* Helper method that handles the concurrent access through throttle
*
* @param isResponse Current Message is response or not
* @param synLog the Synapse log to use
* @return true if the caller can access ,o.w. false
*/
private boolean doThrottleByConcurrency(boolean isResponse, SynapseLog synLog) {
boolean canAccess = true;
if (concurrentAccessController != null) {
// do the concurrency throttling
int concurrentLimit = concurrentAccessController.getLimit();
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Concurrent access controller for ID : " + id +
" allows : " + concurrentLimit + " concurrent accesses");
}
int available;
if (!isResponse) {
available = concurrentAccessController.getAndDecrement();
canAccess = available > 0;
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Concurrency Throttle : Access " +
(canAccess ? "allowed" : "denied") + " :: " + available
+ " of available of " + concurrentLimit + " connections");
}
}
}
return canAccess;
}
/**
* Helper method that handles the access-rate based throttling
*
* @param synCtx MessageContext(Synapse)
* @param axisMC MessageContext(Axis2)
* @param cc ConfigurationContext
* @param synLog the Synapse log to use
* @return ue if the caller can access ,o.w. false
*/
private boolean doThrottleByAccessRate(MessageContext synCtx,
org.apache.axis2.context.MessageContext axisMC,
ConfigurationContext cc,
SynapseLog synLog) {
String callerId = null;
boolean canAccess = true;
//remote ip of the caller
String remoteIP = (String) axisMC.getPropertyNonReplicable(
org.apache.axis2.context.MessageContext.REMOTE_ADDR);
//domain name of the caller
String domainName = (String) axisMC.getPropertyNonReplicable(NhttpConstants.REMOTE_HOST);
//Using remote caller domain name , If there is a throttle configuration for
// this domain name ,then throttling will occur according to that configuration
if (domainName != null) {
// do the domain based throttling
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("The Domain Name of the caller is :" + domainName);
}
// loads the DomainBasedThrottleContext
ThrottleContext context
= throttle.getThrottleContext(ThrottleConstants.DOMAIN_BASED_THROTTLE_KEY);
if (context != null) {
//loads the DomainBasedThrottleConfiguration
ThrottleConfiguration config = context.getThrottleConfiguration();
if (config != null) {
//checks the availability of a policy configuration for this domain name
callerId = config.getConfigurationKeyOfCaller(domainName);
if (callerId != null) { // there is configuration for this domain name
//If this is a clustered env.
if (isClusteringEnable) {
context.setConfigurationContext(cc);
context.setThrottleId(id);
}
try {
//Checks for access state
AccessInformation accessInformation = accessControler.canAccess(context,
callerId, ThrottleConstants.DOMAIN_BASE);
canAccess = accessInformation.isAccessAllowed();
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Access " + (canAccess ? "allowed" : "denied")
+ " for Domain Name : " + domainName);
}
//In the case of both of concurrency throttling and
//rate based throttling have enabled ,
//if the access rate less than maximum concurrent access ,
//then it is possible to occur death situation.To avoid that reset,
//if the access has denied by rate based throttling
if (!canAccess && concurrentAccessController != null) {
concurrentAccessController.incrementAndGet();
if (isClusteringEnable) {
dataHolder.setConcurrentAccessController
(key, concurrentAccessController);
}
}
} catch (ThrottleException e) {
handleException("Error occurred during throttling", e, synCtx);
}
}
}
}
} else {
synLog.traceOrDebug("The Domain name of the caller cannot be found");
}
//At this point , any configuration for the remote caller hasn't found ,
//therefore trying to find a configuration policy based on remote caller ip
if (callerId == null) {
//do the IP-based throttling
if (remoteIP == null) {
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("The IP address of the caller cannot be found");
}
canAccess = true;
} else {
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("The IP Address of the caller is :" + remoteIP);
}
try {
// Loads the IPBasedThrottleContext
ThrottleContext context =
throttle.getThrottleContext(ThrottleConstants.IP_BASED_THROTTLE_KEY);
if (context != null) {
//Loads the IPBasedThrottleConfiguration
ThrottleConfiguration config = context.getThrottleConfiguration();
if (config != null) {
//Checks the availability of a policy configuration for this ip
callerId = config.getConfigurationKeyOfCaller(remoteIP);
if (callerId != null) { // there is configuration for this ip
//For clustered env.
if (isClusteringEnable) {
context.setConfigurationContext(cc);
context.setThrottleId(id);
}
//Checks access state
AccessInformation accessInformation = accessControler.canAccess(
context,
callerId,
ThrottleConstants.IP_BASE);
canAccess = accessInformation.isAccessAllowed();
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Access " +
(canAccess ? "allowed" : "denied")
+ " for IP : " + remoteIP);
}
//In the case of both of concurrency throttling and
//rate based throttling have enabled ,
//if the access rate less than maximum concurrent access ,
//then it is possible to occur death situation.To avoid that reset,
//if the access has denied by rate based throttling
if (!canAccess && concurrentAccessController != null) {
concurrentAccessController.incrementAndGet();
if (isClusteringEnable) {
dataHolder.setConcurrentAccessController
(key, concurrentAccessController);
}
}
}
}
}
} catch (ThrottleException e) {
handleException("Error occurred during throttling", e, synCtx);
}
}
}
return canAccess;
}
/**
* Helper method that handles dynamic policy initialization
*
* @param synCtx MessageContext(Synapse)
*/
private void doInitializeThrottleDynamicPolicy(MessageContext synCtx, SynapseLog synLog) {
if (policyKey == null) {
return;
}
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Throttle mediator : Initializing dynamic Policy");
}
// If the policy has specified as a registry key.
// load or re-load policy from registry or local entry if not already available
Entry entry = synCtx.getConfiguration().getEntryDefinition(policyKey);
if (entry == null) {
handleException("Cannot find throttling policy using key : "
+ policyKey, synCtx);
} else {
boolean reCreate = false;
// if the key refers to a dynamic resource
if (entry.isDynamic()) {
if ((!entry.isCached() || entry.isExpired()) && version != entry.getVersion()) {
reCreate = true;
version = entry.getVersion();
}
}
//we ignore the static initialization case
if (reCreate || throttle == null) {
Object entryValue = synCtx.getEntry(policyKey);
if (entryValue == null) {
handleException(
"Null throttling policy returned by Entry : "
+ policyKey, synCtx);
} else {
if (!(entryValue instanceof OMElement)) {
handleException("Policy returned from key : " + policyKey +
" is not an OMElement", synCtx);
} else {
//Check for reload in a cluster environment
// For clustered environment ,if the concurrent access controller
// is not null and throttle is not null , then must reload.
if (isClusteringEnable && concurrentAccessController != null
&& throttle != null) {
concurrentAccessController = null; // set null ,
// because need to reload when throttle gets created again
}
try {
// creation of throttle should be thread safe if multiple request flow
// try to create a throttle object
synchronized (throttleLock) {
// Creates the throttle from the policy
throttle = ThrottleFactory.createMediatorThrottle(
PolicyEngine.getPolicy((OMElement) entryValue));
//For non-clustered environment , must re-initiates
//For clustered environment,
//concurrent access controller is null ,
//then must re-initiates
if (throttle != null && (concurrentAccessController == null
|| !isClusteringEnable)) {
concurrentAccessController =
throttle.getConcurrentAccessController();
if (concurrentAccessController != null) {
dataHolder.setConcurrentAccessController
(key, concurrentAccessController);
} else {
dataHolder.removeConcurrentAccessController(key);
}
}
}
} catch (ThrottleException e) {
handleException("Error processing the throttling policy",
e, synCtx);
}
}
}
}
}
}
/**
* Helper method that handles the update the local reference to the concurrent controller
*
* @param synLog the Synapse log to use
*/
private void reloadDistributedConcurrentAccessController(SynapseLog synLog) {
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Throttle mediator : Updating local " +
"reference to the Concurrent Access controller");
}
concurrentAccessController = dataHolder.getConcurrentAccessController(key);
}
public void init(SynapseEnvironment se) {
if (onAcceptMediator instanceof ManagedLifecycle) {
((ManagedLifecycle) onAcceptMediator).init(se);
} else if (onAcceptSeqKey != null) {
SequenceMediator onAcceptSeq =
(SequenceMediator) se.getSynapseConfiguration().
getSequence(onAcceptSeqKey);
if (onAcceptSeq == null || onAcceptSeq.isDynamic()) {
se.addUnavailableArtifactRef(onAcceptSeqKey);
}
}
if (onRejectMediator instanceof ManagedLifecycle) {
((ManagedLifecycle) onRejectMediator).init(se);
} else if (onRejectSeqKey != null) {
SequenceMediator onRejectSeq =
(SequenceMediator) se.getSynapseConfiguration().
getSequence(onRejectSeqKey);
if (onRejectSeq == null || onRejectSeq.isDynamic()) {
se.addUnavailableArtifactRef(onRejectSeqKey);
}
}
//reference to axis2 configuration context
configContext = ((Axis2SynapseEnvironment) se).getAxis2ConfigurationContext();
//throttling data holder initialization of
// runtime throttle data eg :- throttle contexts
dataHolder = (ThrottleDataHolder) configContext.
getProperty(ThrottleConstants.THROTTLE_INFO_KEY);
if (dataHolder == null) {
log.debug("Data holder not present in current Configuration Context");
synchronized (configContext) {
dataHolder = (ThrottleDataHolder) configContext.
getProperty(ThrottleConstants.THROTTLE_INFO_KEY);
if (dataHolder == null) {
dataHolder = new ThrottleDataHolder();
configContext.setNonReplicableProperty
(ThrottleConstants.THROTTLE_INFO_KEY, dataHolder);
}
}
}
//initializes whether clustering is enabled an Env. level
ClusteringAgent clusteringAgent = configContext.getAxisConfiguration().getClusteringAgent();
if (clusteringAgent != null) {
isClusteringEnable = true;
}
//static policy initialization
if (inLinePolicy != null) {
log.debug("Initializing using static throttling policy : " + inLinePolicy);
try {
throttle = ThrottleFactory.
createMediatorThrottle(PolicyEngine.getPolicy(inLinePolicy));
if (throttle != null && concurrentAccessController == null) {
concurrentAccessController = throttle.getConcurrentAccessController();
if (concurrentAccessController != null) {
dataHolder.setConcurrentAccessController(key, concurrentAccessController);
}
}
} catch (ThrottleException e) {
handleException("Error processing the throttling policy", e, null);
}
}
//access rate controller initialization
accessControler = new AccessRateController();
//replicator for global concurrent state maintenance
if (isClusteringEnable) {
concurrentAccessReplicator = new ConcurrentAccessReplicator(configContext);
}
}
public void destroy() {
//if synapse configuration refreshes we need to drop the previous throttle data
if (configContext != null) {
dataHolder.removeConcurrentAccessController(key);
}
if (onAcceptMediator instanceof ManagedLifecycle) {
((ManagedLifecycle) onAcceptMediator).destroy();
}
if (onRejectMediator instanceof ManagedLifecycle) {
((ManagedLifecycle) onRejectMediator).destroy();
}
}
/**
* To get the policy key - The key for which will used to lookup policy from the registry
*
* @return String
*/
public String getPolicyKey() {
return policyKey;
}
/**
* To set the policy key - The key for which lookup from the registry
*
* @param policyKey Value for picking policy from the registry
*/
public void setPolicyKey(String policyKey) {
this.policyKey = policyKey;
}
/**
* getting throttle policy which has defined as InLineXML
*
* @return InLine Throttle Policy
*/
public OMElement getInLinePolicy() {
return inLinePolicy;
}
/**
* setting throttle policy which has defined as InLineXML
*
* @param inLinePolicy Inline policy
*/
public void setInLinePolicy(OMElement inLinePolicy) {
this.inLinePolicy = inLinePolicy;
}
public String getOnRejectSeqKey() {
return onRejectSeqKey;
}
public void setOnRejectSeqKey(String onRejectSeqKey) {
this.onRejectSeqKey = onRejectSeqKey;
}
public Mediator getOnRejectMediator() {
return onRejectMediator;
}
public void setOnRejectMediator(Mediator onRejectMediator) {
this.onRejectMediator = onRejectMediator;
}
public String getOnAcceptSeqKey() {
return onAcceptSeqKey;
}
public void setOnAcceptSeqKey(String onAcceptSeqKey) {
this.onAcceptSeqKey = onAcceptSeqKey;
}
public Mediator getOnAcceptMediator() {
return onAcceptMediator;
}
public void setOnAcceptMediator(Mediator onAcceptMediator) {
this.onAcceptMediator = onAcceptMediator;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
this.key = ThrottleConstants.THROTTLE_PROPERTY_PREFIX + id + ThrottleConstants.CAC_SUFFIX;
}
@Override
public boolean isContentAware() {
return false;
}
@Override
public Mediator getInlineSequence(SynapseConfiguration synCfg, int inlinedSeqIdentifier) {
if (inlinedSeqIdentifier == 0) {
if (onRejectMediator != null) {
return onRejectMediator;
} else if (onRejectSeqKey != null) {
return synCfg.getSequence(onRejectSeqKey);
}
} else if (inlinedSeqIdentifier == 1) {
if (onAcceptMediator != null) {
return onAcceptMediator;
} else if (onAcceptSeqKey != null) {
return synCfg.getSequence(onAcceptSeqKey);
}
}
return null;
}
@Override
public void setComponentStatisticsId(ArtifactHolder holder) {
if (getAspectConfiguration() == null) {
configure(new AspectConfiguration(getMediatorName()));
}
String mediatorId =
StatisticIdentityGenerator.getIdForFlowContinuableMediator(getMediatorName(), ComponentType.MEDIATOR, holder);
getAspectConfiguration().setUniqueId(mediatorId);
String childId;
if (onAcceptSeqKey != null) {
childId = StatisticIdentityGenerator.getIdReferencingComponent(onAcceptSeqKey, ComponentType.SEQUENCE, holder);
StatisticIdentityGenerator.reportingEndEvent(childId, ComponentType.SEQUENCE, holder);
} else if (onAcceptMediator != null) {
onAcceptMediator.setComponentStatisticsId(holder);
}
if (onRejectSeqKey != null) {
childId = StatisticIdentityGenerator.getIdReferencingComponent(onRejectSeqKey, ComponentType.SEQUENCE, holder);
StatisticIdentityGenerator.reportingEndEvent(childId, ComponentType.SEQUENCE, holder);
} else if (onRejectMediator != null) {
onRejectMediator.setComponentStatisticsId(holder);
}
StatisticIdentityGenerator.reportingFlowContinuableEndEvent(mediatorId, ComponentType.MEDIATOR, holder);
}
}