/*
* 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;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.Mediator;
import org.apache.synapse.MessageContext;
import org.apache.synapse.SynapseConstants;
import org.apache.synapse.SynapseException;
import org.apache.synapse.SynapseLog;
import org.apache.synapse.aspects.AspectConfigurable;
import org.apache.synapse.aspects.AspectConfiguration;
import org.apache.synapse.aspects.flow.statistics.StatisticIdentityGenerator;
import org.apache.synapse.aspects.flow.statistics.collectors.CloseEventCollector;
import org.apache.synapse.aspects.ComponentType;
import org.apache.synapse.aspects.flow.statistics.collectors.OpenEventCollector;
import org.apache.synapse.aspects.flow.statistics.data.artifact.ArtifactHolder;
import org.apache.synapse.aspects.flow.statistics.util.StatisticsConstants;
import org.apache.synapse.debug.constructs.SynapseMediationFlowPoint;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* This is the super class of all mediators, and defines common logging, tracing other aspects
* for all mediators who extend from this.
* elements of a mediator class.
*/
public abstract class AbstractMediator implements Mediator, AspectConfigurable {
/** the standard log for mediators, will assign the logger for the actual subclass */
protected Log log;
/** The runtime trace log for mediators */
protected static final Log trace = LogFactory.getLog(SynapseConstants.TRACE_LOGGER);
/**
* State of tracing for this mediator
*/
protected int traceState = SynapseConstants.TRACING_UNSET;
private AspectConfiguration aspectConfiguration;
private String description;
private String shortDescription;
private int mediatorPosition = 0;
private boolean isBreakPoint = false;
private boolean isSkipEnabled = false;
private SynapseMediationFlowPoint flowPoint = null;
/**
* A constructor that makes subclasses pick up the correct logger
*/
protected AbstractMediator() {
log = LogFactory.getLog(this.getClass());
}
/**
* Comment Texts List associated with the mediator
*/
private List<String> commentsList = new ArrayList<String>();
/**
* This method is invoked when mediation happens in debug mode, branches execution to
* the Debug Manager, further behavior is governed by the Debug Manager.
*
* @return false if the mediation should be continued after this method call, true if mediation
* of current child mediator position should be skipped
*/
public boolean divertMediationRoute(MessageContext synCtx) {
if (synCtx.getEnvironment().isDebuggerEnabled()) {
if (isSkipEnabled()) {
synCtx.getEnvironment().getSynapseDebugManager()
.advertiseMediationFlowSkip(synCtx, getRegisteredMediationFlowPoint());
return true;
} else if (isBreakPoint()) {
synCtx.getEnvironment().getSynapseDebugManager()
.advertiseMediationFlowBreakPoint(synCtx, getRegisteredMediationFlowPoint());
}
}
return false;
}
/**
* Returns the class name of the mediator
* @return the class name of the mediator
*/
public String getType() {
String cls = getClass().getName();
int p = cls.lastIndexOf(".");
if (p == -1)
return cls;
else
return cls.substring(p + 1);
}
/**
* Returns the tracing state
* @return the tracing state for this mediator (see SynapseConstants)
*/
public int getTraceState() {
return traceState;
}
/**
* Set the tracing state variable
* @param traceState the new tracing state for this mediator (see SynapseConstants)
*/
public void setTraceState(int traceState) {
this.traceState = traceState;
}
/**
* Set the description of the mediator
* @param description tobe set to the mediator
*/
public void setDescription(String description) {
this.description = description;
}
/**
* Gives the description of the mediator
* @return description of the mediator
*/
public String getDescription() {
return this.description;
}
/**
* Set the short description of the mediator
* @param shortDescription to be set to the mediator
*/
public void setShortDescription(String shortDescription) {
this.shortDescription = shortDescription;
}
/**
* Gives the short description of the mediator
* @return short description of the mediator
*/
public String getShortDescription() {
return this.shortDescription;
}
/**
* This method is used to save previous tracing state and set next the tracing
* state for a child mediator
*
* @param synCtx current message
*/
public void setEffectiveTraceState(MessageContext synCtx) {
// if I have been explicitly asked to enable or disable tracing, use it and pass it on
// else, do nothing -> i.e. let the parents state flow
if (traceState != SynapseConstants.TRACING_UNSET) {
synCtx.setTracingState(traceState);
}
}
/**
* Get a SynapseLog instance appropriate for the given context.
*
* @param synCtx the current message context
* @return MediatorLog instance - an implementation of the SynapseLog
*/
protected SynapseLog getLog(MessageContext synCtx) {
return new MediatorLog(log, isTraceOn(synCtx), synCtx);
}
/**
* Should this mediator perform tracing? True if its explicitly asked to
* trace, or its parent has been asked to trace and it does not reject it
* @param parentTraceState parents trace state
* @return true if tracing should be performed
*/
public boolean shouldTrace(int parentTraceState){
return
(traceState == SynapseConstants.TRACING_ON) ||
(traceState == SynapseConstants.TRACING_UNSET &&
parentTraceState == SynapseConstants.TRACING_ON);
}
public boolean shouldTrace(MessageContext msgCtx){
return isTracingEnabled() || shouldCaptureTracing(msgCtx);
}
/**
* Should this mediator perform tracing? True if its explicitly asked to
* trace, or its parent has been asked to trace and it does not reject it
*
* @deprecated This method will be removed in a future version of Synapse.
* Please use the {@link SynapseLog} instance returned by
* {@link #getLog(MessageContext)} for all logging inside a
* mediator.
*
* @param msgCtx the current message
* @return true if tracing should be performed
*/
@Deprecated
protected boolean isTraceOn(MessageContext msgCtx) {
return isTracingEnabled() || shouldCaptureTracing(msgCtx);
// return
// (traceState == SynapseConstants.TRACING_ON) ||
// (traceState == SynapseConstants.TRACING_UNSET &&
// msgCtx.getTracingState() == SynapseConstants.TRACING_ON);
}
/**
* Is tracing or debug logging on?
*
* @deprecated This method will be removed in a future version of Synapse.
* Please use the {@link SynapseLog} instance returned by
* {@link #getLog(MessageContext)} for all logging inside a
* mediator.
*
* @param isTraceOn is tracing known to be on?
* @return true, if either tracing or debug logging is on
*/
@Deprecated
protected boolean isTraceOrDebugOn(boolean isTraceOn) {
return isTraceOn || log.isDebugEnabled();
}
/**
* Perform Trace and Debug logging of a message @INFO (trace) and DEBUG (log)
*
* @deprecated This method will be removed in a future version of Synapse.
* Please use the {@link SynapseLog} instance returned by
* {@link #getLog(MessageContext)} for all logging inside a
* mediator.
*
* @param traceOn is runtime trace on for this message?
* @param msg the message to log/trace
*/
@Deprecated
protected void traceOrDebug(boolean traceOn, String msg) {
if (traceOn) {
trace.info(msg);
}
if (log.isDebugEnabled()) {
log.debug(msg);
}
}
/**
* Perform Trace and Debug logging of a message @WARN
*
* @deprecated This method will be removed in a future version of Synapse.
* Please use the {@link SynapseLog} instance returned by
* {@link #getLog(MessageContext)} for all logging inside a
* mediator.
*
* @param traceOn is runtime trace on for this message?
* @param msg the message to log/trace
*/
@Deprecated
protected void traceOrDebugWarn(boolean traceOn, String msg) {
if (traceOn) {
trace.warn(msg);
}
if (log.isDebugEnabled()) {
log.warn(msg);
}
}
/**
* Perform an audit log message to all logs @ INFO. Writes to the general log, the service log
* and the trace log (of trace is on)
*
* @deprecated This method will be removed in a future version of Synapse.
* Please use the {@link SynapseLog} instance returned by
* {@link #getLog(MessageContext)} for all logging inside a
* mediator.
*
* @param msg the log message
* @param msgContext the message context
*/
@Deprecated
protected void auditLog(String msg, MessageContext msgContext) {
log.info(msg);
if (msgContext.getServiceLog() != null) {
msgContext.getServiceLog().info(msg);
}
if (shouldTrace(msgContext)) {
trace.info(msg);
}
}
/**
* Perform an error log message to all logs @ ERROR. Writes to the general log, the service log
* and the trace log (of trace is on) and throws a SynapseException
* @param msg the log message
* @param msgContext the message context
*/
protected void handleException(String msg, MessageContext msgContext) {
log.error(msg);
if (msgContext.getServiceLog() != null) {
msgContext.getServiceLog().error(msg);
}
if (shouldTrace(msgContext)) {
trace.error(msg);
}
throw new SynapseException(msg);
}
/**
* Write an audit entry at WARN and trace and standard logs @WARN
*
* @deprecated This method will be removed in a future version of Synapse.
* Please use the {@link SynapseLog} instance returned by
* {@link #getLog(MessageContext)} for all logging inside a
* mediator.
*
* @param msg the message to log
* @param msgContext message context
*/
@Deprecated
protected void auditWarn(String msg, MessageContext msgContext) {
log.warn(msg);
if (msgContext.getServiceLog() != null) {
msgContext.getServiceLog().warn(msg);
}
if (shouldTrace(msgContext)) {
trace.warn(msg);
}
}
/**
* Perform an error log message to all logs @ ERROR. Writes to the general log, the service log
* and the trace log (of trace is on) and throws a SynapseException
* @param msg the log message
* @param e an Exception encountered
* @param msgContext the message context
*/
protected void handleException(String msg, Exception e, MessageContext msgContext) {
log.error(msg, e);
if (msgContext.getServiceLog() != null) {
msgContext.getServiceLog().error(msg, e);
}
if (shouldTrace(msgContext)) {
trace.error(msg, e);
}
throw new SynapseException(msg, e);
}
public boolean isStatisticsEnable() {
return this.aspectConfiguration != null
&& this.aspectConfiguration.isStatisticsEnable();
}
public void disableStatistics() {
if (this.aspectConfiguration != null) {
this.aspectConfiguration.disableStatistics();
}
}
public void enableStatistics() {
if (this.aspectConfiguration != null) {
this.aspectConfiguration.enableStatistics();
}
}
public boolean isTracingEnabled() {
return this.aspectConfiguration != null
&& this.aspectConfiguration.isTracingEnabled();
}
public void disableTracing() {
if (this.aspectConfiguration != null) {
this.aspectConfiguration.disableTracing();
}
}
public void enableTracing() {
if (this.aspectConfiguration != null) {
this.aspectConfiguration.enableTracing();
}
}
/**
* Configure aspects according to the given configuration
*
* @param aspectConfiguration AspectConfiguration instance
*/
public void configure(AspectConfiguration aspectConfiguration) {
this.aspectConfiguration = aspectConfiguration;
}
/**
* Get the aspects configuration
*
* @return AspectConfiguration instance
*/
public AspectConfiguration getAspectConfiguration() {
return aspectConfiguration;
}
public boolean isContentAware() {
return true;
}
public boolean isContentAltering() {
return false;
}
public int getMediatorPosition() {
return mediatorPosition;
}
public void setMediatorPosition(int position) {
mediatorPosition = position;
}
public String getInputType() {
return null;
}
public String getOutputType() {
return null;
}
/**
* Returns Comment List
*
* @return String List of comments
*/
public List<String> getCommentsList() {
return commentsList;
}
/**
* Sets comment list for the mediator
*
* @param commentsList String List of comments
*/
public void setCommentsList(List<String> commentsList) {
this.commentsList = commentsList;
}
/**
* Returns the name of the class of respective mediator. This was introduced to provide a unique way to get the
* mediator name because getType is implemented in different ways in different mediators (e.g.
* PayloadFactoryMediator)
* @return
*/
public String getMediatorName(){
String cls = getClass().getName();
return cls.substring(cls.lastIndexOf(".") + 1);
}
public Integer reportOpenStatistics(MessageContext messageContext, boolean isContentAltering) {
if (this instanceof FlowContinuableMediator) {
return OpenEventCollector
.reportFlowContinuableEvent(messageContext, getMediatorName(), ComponentType.MEDIATOR,
getAspectConfiguration(), isContentAltering() || isContentAltering);
} else {
return OpenEventCollector.reportChildEntryEvent(messageContext, getMediatorName(), ComponentType.MEDIATOR,
getAspectConfiguration(),
isContentAltering() || isContentAltering);
}
}
public void reportCloseStatistics(MessageContext messageContext, Integer currentIndex) {
CloseEventCollector.closeEntryEvent(messageContext, getMediatorName(), ComponentType.MEDIATOR, currentIndex,
isContentAltering());
}
public void registerMediationFlowPoint(SynapseMediationFlowPoint flowPoint) {
this.flowPoint = flowPoint;
}
public void unregisterMediationFlowPoint() {
if (this.flowPoint != null) {
if (!(isBreakPoint && isSkipEnabled)) {
this.flowPoint = null;
}
}
}
public SynapseMediationFlowPoint getRegisteredMediationFlowPoint() {
return flowPoint;
}
public boolean isBreakPoint() {
return isBreakPoint;
}
public boolean isSkipEnabled() {
return isSkipEnabled;
}
public void setBreakPoint(boolean isBreakPoint) {
this.isBreakPoint = isBreakPoint;
}
public void setSkipEnabled(boolean isSkipEnabled) {
this.isSkipEnabled = isSkipEnabled;
}
protected boolean shouldCaptureTracing(MessageContext synCtx) {
Boolean isCollectingTraces = (Boolean) synCtx.getProperty(StatisticsConstants.FLOW_TRACE_IS_COLLECTED);
if (isCollectingTraces == null) {
return false;
}
else {
return isCollectingTraces;
}
}
public void setComponentStatisticsId(ArtifactHolder holder) {
if (aspectConfiguration == null) {
aspectConfiguration = new AspectConfiguration(getMediatorName());
}
String sequenceId = StatisticIdentityGenerator.getIdForComponent(getMediatorName(), ComponentType.MEDIATOR, holder);
getAspectConfiguration().setUniqueId(sequenceId);
StatisticIdentityGenerator.reportingEndEvent(sequenceId, ComponentType.MEDIATOR, holder);
}
protected MediatorFaultHandler getLastSequenceFaultHandler(MessageContext synCtx) {
Stack faultStack = synCtx.getFaultStack();
if (faultStack != null && !faultStack.isEmpty()) {
Object o = faultStack.peek();
if (o instanceof MediatorFaultHandler) {
return (MediatorFaultHandler) o;
}
}
return null;
}
}