/* * 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.axiom.om.OMAbstractFactory; import org.apache.axiom.soap.SOAPEnvelope; import org.apache.axis2.AxisFault; import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.synapse.ManagedLifecycle; import org.apache.synapse.Mediator; import org.apache.synapse.MessageContext; import org.apache.synapse.SynapseException; import org.apache.synapse.SynapseLog; import org.apache.synapse.aspects.flow.statistics.collectors.RuntimeStatisticCollector; import org.apache.synapse.aspects.flow.statistics.data.artifact.ArtifactHolder; import org.apache.synapse.core.SynapseEnvironment; import org.apache.synapse.core.axis2.Axis2MessageContext; import org.apache.synapse.transport.passthru.PassThroughConstants; import org.apache.synapse.transport.passthru.util.RelayUtils; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * This is the base class for all List mediators * * @see ListMediator */ public abstract class AbstractListMediator extends AbstractMediator implements ListMediator { private static final String WSTX_EXCEPTION_PATTERN = ".*(Wstx)(.*Exception)"; /** the list of child mediators held. These are executed sequentially */ protected final List<Mediator> mediators = new ArrayList<Mediator>(); private boolean sequenceContentAware = false; public boolean mediate(MessageContext synCtx) { return mediate(synCtx,0); } public boolean mediate(MessageContext synCtx, int mediatorPosition) { boolean returnVal = true; int parentsEffectiveTraceState = synCtx.getTracingState(); // if I have been explicitly asked to enable or disable tracing, set it to the message // to pass it on; else, do nothing -> i.e. let the parents state flow setEffectiveTraceState(synCtx); int myEffectiveTraceState = synCtx.getTracingState(); try { SynapseLog synLog = getLog(synCtx); if (synLog.isTraceOrDebugEnabled()) { synLog.traceOrDebug("Sequence <" + getType() + "> :: mediate()"); synLog.traceOrDebug("Mediation started from mediator position : " + mediatorPosition); } for (int i = mediatorPosition; i < mediators.size(); i++) { // ensure correct trace state after each invocation of a mediator Mediator mediator = mediators.get(i); if (sequenceContentAware && mediator.isContentAware() && (!Boolean.TRUE.equals(synCtx.getProperty(PassThroughConstants.MESSAGE_BUILDER_INVOKED)))) { buildMessage(synCtx, synLog); } if (RuntimeStatisticCollector.isStatisticsEnabled()) { Integer statisticReportingIndex = mediator.reportOpenStatistics(synCtx, i == mediatorPosition); synCtx.setTracingState(myEffectiveTraceState); if (!mediator.mediate(synCtx)) { mediator.reportCloseStatistics(synCtx, statisticReportingIndex); returnVal = false; break; } mediator.reportCloseStatistics(synCtx, statisticReportingIndex); } else { synCtx.setTracingState(myEffectiveTraceState); if (!mediator.mediate(synCtx)) { returnVal = false; break; } } } } catch (SynapseException synEx) { // Create a Pattern object Pattern wstxExpattern = Pattern.compile(WSTX_EXCEPTION_PATTERN); // Now create matcher object. Matcher wstxExMatcher = wstxExpattern.matcher(ExceptionUtils.getStackTrace(synEx)); if (wstxExMatcher.find()) { consumeInputOnOmException(synCtx); } throw synEx; } catch (Exception ex) { String errorMsg = ex.getMessage(); // Create a Pattern object Pattern wstxExpattern = Pattern.compile(WSTX_EXCEPTION_PATTERN); // Now create matcher object. Matcher wstxExMatcher = wstxExpattern.matcher(ExceptionUtils.getStackTrace(ex)); if (errorMsg == null) { errorMsg = "Runtime error occurred while mediating the message"; } if (wstxExMatcher.find()) { consumeInputOnOmException(synCtx); } handleException(errorMsg, ex, synCtx); } finally { synCtx.setTracingState(parentsEffectiveTraceState); } return returnVal; } private void buildMessage(MessageContext synCtx, SynapseLog synLog) { try { if (synLog.isTraceOrDebugEnabled()) { synLog.traceOrDebug("Building message. Sequence <" + getType() + "> is content aware"); } RelayUtils.buildMessage(((Axis2MessageContext) synCtx).getAxis2MessageContext(), false); } catch (Exception e) { handleException("Error while building message", e, synCtx); } } public List<Mediator> getList() { return mediators; } public boolean addChild(Mediator m) { return mediators.add(m); } public boolean addAll(List<Mediator> c) { return mediators.addAll(c); } public Mediator getChild(int pos) { return mediators.get(pos); } public boolean removeChild(Mediator m) { return mediators.remove(m); } public Mediator removeChild(int pos) { return mediators.remove(pos); } /** * Initialize child mediators recursively * @param se synapse environment */ public void init(SynapseEnvironment se) { if (log.isDebugEnabled()) { log.debug("Initializing child mediators of mediator : " + getType()); } for (int i = 0; i < mediators.size(); i++) { Mediator mediator = mediators.get(i); mediator.setMediatorPosition(i); if (mediator instanceof ManagedLifecycle) { ((ManagedLifecycle) mediator).init(se); } if (mediator.isContentAware()) { if (log.isDebugEnabled()) { log.debug(mediator.getType() + " is content aware, setting sequence <" + getType() + "> as content aware"); } sequenceContentAware = true; } } } /** * Destroy child mediators recursively */ public void destroy() { if (log.isDebugEnabled()) { log.debug("Destroying child mediators of mediator : " + getType()); } for (Mediator mediator : mediators) { if (mediator instanceof ManagedLifecycle) { ((ManagedLifecycle) mediator).destroy(); } } } @Override public boolean isContentAware() { return sequenceContentAware; } public void setStatisticIdForMediators(ArtifactHolder holder){ for (Mediator mediator : mediators) { mediator.setComponentStatisticsId(holder); } } /** * This method will read the entire content from the input stream of the request if there is a parsing error. * * @param synCtx Synapse message context. */ private void consumeInputOnOmException(MessageContext synCtx) { try { RelayUtils.consumeAndDiscardMessage(((Axis2MessageContext) synCtx).getAxis2MessageContext()); } catch (AxisFault axisFault) { log.error("Exception while consuming the input stream on Om Exception", axisFault); } SOAPEnvelope soapEnvelope; if (synCtx.isSOAP11()) { soapEnvelope = OMAbstractFactory.getSOAP11Factory().createSOAPEnvelope(); soapEnvelope.addChild(OMAbstractFactory.getSOAP11Factory().createSOAPBody()); } else { soapEnvelope = OMAbstractFactory.getSOAP12Factory().createSOAPEnvelope(); soapEnvelope.addChild(OMAbstractFactory.getSOAP12Factory().createSOAPBody()); } try { synCtx.setEnvelope(soapEnvelope); } catch (AxisFault e) { log.error("Exception or Error occurred resetting SOAP Envelope", e); } } }