/* * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.runtime.core.processor; import static org.mule.runtime.core.api.Event.builder; import static org.mule.runtime.core.api.lifecycle.LifecycleUtils.setFlowConstructIfNeeded; import static org.mule.runtime.core.api.lifecycle.LifecycleUtils.setMuleContextIfNeeded; import static org.mule.runtime.core.api.processor.MessageProcessors.processWithChildContext; import static org.mule.runtime.core.execution.MessageProcessorExecutionTemplate.createExecutionTemplate; import static reactor.core.publisher.Flux.from; import org.mule.runtime.core.api.MuleContext; import org.mule.runtime.core.api.Event; import org.mule.runtime.api.exception.MuleException; import org.mule.runtime.core.api.construct.FlowConstruct; import org.mule.runtime.core.api.construct.FlowConstructAware; import org.mule.runtime.core.api.context.MuleContextAware; import org.mule.runtime.api.lifecycle.Disposable; import org.mule.runtime.api.lifecycle.Initialisable; import org.mule.runtime.api.lifecycle.InitialisationException; import org.mule.runtime.api.lifecycle.Lifecycle; import org.mule.runtime.api.lifecycle.Startable; import org.mule.runtime.api.lifecycle.Stoppable; import org.mule.runtime.core.api.processor.Processor; import org.mule.runtime.core.execution.MessageProcessorExecutionTemplate; import org.mule.runtime.core.session.DefaultMuleSession; import org.reactivestreams.Publisher; public class ResponseMessageProcessorAdapter extends AbstractInterceptingMessageProcessor implements Lifecycle, FlowConstructAware { protected MessageProcessorExecutionTemplate messageProcessorExecutionTemplate = createExecutionTemplate(); protected Processor responseProcessor; public ResponseMessageProcessorAdapter() { super(); } public ResponseMessageProcessorAdapter(Processor responseProcessor) { super(); this.responseProcessor = responseProcessor; } public void setProcessor(Processor processor) { this.responseProcessor = processor; } @Override public Event process(Event event) throws MuleException { Event response = processNext(event); if (responseProcessor == null || !isEventValid(response)) { return response; } else { return resolveReturnEvent(responseProcessor.process(response), response); } } private Event resolveReturnEvent(Event result, Event original) { if (result == null) { // If <response> returns null then it acts as an implicit branch like in flows, the different // here is that what's next, it's not another message processor that follows this one in the // configuration file but rather the response phase of the inbound endpoint, or optionally // other response processing on the way back to the inbound endpoint. return original; } else { return result; } } @Override public Publisher<Event> apply(Publisher<Event> publisher) { if (responseProcessor == null) { return publisher; } else { return from(publisher) .transform(applyNext()) // Use flatMap and child context in order to handle null response and continue with current event .flatMap(event -> from(processWithChildContext(event, responseProcessor)).defaultIfEmpty(event)); } } @Override public void initialise() throws InitialisationException { if (responseProcessor instanceof MuleContextAware) { ((MuleContextAware) responseProcessor).setMuleContext(muleContext); } if (responseProcessor instanceof FlowConstructAware) { ((FlowConstructAware) responseProcessor).setFlowConstruct(flowConstruct); } if (responseProcessor instanceof Initialisable) { ((Initialisable) responseProcessor).initialise(); } } @Override public void start() throws MuleException { if (responseProcessor instanceof Startable) { ((Startable) responseProcessor).start(); } } @Override public void stop() throws MuleException { if (responseProcessor instanceof Stoppable) { ((Stoppable) responseProcessor).stop(); } } @Override public void dispose() { if (responseProcessor instanceof Disposable) { ((Disposable) responseProcessor).dispose(); } } @Override public void setFlowConstruct(FlowConstruct flowConstruct) { super.setFlowConstruct(flowConstruct); setFlowConstructIfNeeded(responseProcessor, flowConstruct); messageProcessorExecutionTemplate.setFlowConstruct(flowConstruct); } @Override public void setMuleContext(MuleContext muleContext) { super.setMuleContext(muleContext); setMuleContextIfNeeded(responseProcessor, muleContext); messageProcessorExecutionTemplate.setMuleContext(muleContext); } }