/*
* 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.internal.client;
import static java.util.Optional.empty;
import static java.util.Optional.ofNullable;
import static org.mule.runtime.api.i18n.I18nMessageFactory.createStaticMessage;
import static org.mule.runtime.api.message.Message.of;
import static org.mule.runtime.core.DefaultEventContext.create;
import static org.mule.runtime.core.api.MessageExchangePattern.ONE_WAY;
import static org.mule.runtime.core.api.MessageExchangePattern.REQUEST_RESPONSE;
import static org.mule.runtime.core.api.client.SimpleOptionsBuilder.newOptions;
import static org.mule.runtime.core.api.config.MuleProperties.OBJECT_CONNECTOR_MESSAGE_PROCESSOR_LOCATOR;
import static org.mule.runtime.core.api.functional.Either.left;
import static org.mule.runtime.core.api.functional.Either.right;
import static org.mule.runtime.core.message.ErrorBuilder.builder;
import static org.mule.runtime.dsl.api.component.config.DefaultComponentLocation.fromSingleComponent;
import org.mule.runtime.api.exception.MuleException;
import org.mule.runtime.api.exception.MuleRuntimeException;
import org.mule.runtime.api.message.Error;
import org.mule.runtime.api.message.ErrorType;
import org.mule.runtime.api.message.Message;
import org.mule.runtime.core.api.DefaultMuleException;
import org.mule.runtime.core.api.Event;
import org.mule.runtime.core.api.MuleContext;
import org.mule.runtime.core.api.client.MuleClient;
import org.mule.runtime.core.api.client.MuleClientFlowConstruct;
import org.mule.runtime.core.api.client.OperationOptions;
import org.mule.runtime.core.api.connector.ConnectorOperationLocator;
import org.mule.runtime.core.api.construct.FlowConstruct;
import org.mule.runtime.core.api.construct.FlowConstructAware;
import org.mule.runtime.core.api.functional.Either;
import org.mule.runtime.core.internal.message.InternalMessage;
import org.mule.runtime.core.internal.message.InternalMessage.Builder;
import org.mule.runtime.core.api.processor.Processor;
import java.io.Serializable;
import java.util.Map;
import java.util.Optional;
public class DefaultLocalMuleClient implements MuleClient {
public static final String MESSAGE_FILTERED_ERROR_MESSAGE = "message filtered";
protected final MuleContext muleContext;
private FlowConstruct flowConstruct;
private ConnectorOperationLocator connectorOperatorLocator;
public DefaultLocalMuleClient(MuleContext muleContext) {
this.muleContext = muleContext;
this.flowConstruct = new MuleClientFlowConstruct(muleContext);
}
protected ConnectorOperationLocator getConnectorMessageProcessLocator() {
if (connectorOperatorLocator == null) {
this.connectorOperatorLocator = muleContext.getRegistry().get(OBJECT_CONNECTOR_MESSAGE_PROCESSOR_LOCATOR);
if (this.connectorOperatorLocator == null) {
throw new MuleRuntimeException(createStaticMessage("Could not find required %s in the registry under key %s",
ConnectorOperationLocator.class.getName(),
OBJECT_CONNECTOR_MESSAGE_PROCESSOR_LOCATOR));
}
}
return connectorOperatorLocator;
}
@Override
public void dispatch(String url, Object payload, Map<String, Serializable> messageProperties) throws MuleException {
dispatch(url, createMessage(payload, messageProperties));
}
@Override
public Either<Error, Message> send(String url, Object payload, Map<String, Serializable> messageProperties)
throws MuleException {
return send(url, createMessage(payload, messageProperties));
}
@Override
public Either<Error, Message> send(String url, Message message) throws MuleException {
final Processor connectorMessageProcessor = getConnectorMessageProcessLocator()
.locateConnectorOperation(url, newOptions().outbound().build(), REQUEST_RESPONSE);
if (connectorMessageProcessor != null) {
if (connectorMessageProcessor instanceof FlowConstructAware) {
((FlowConstructAware) connectorMessageProcessor).setFlowConstruct(flowConstruct);
}
return createEitherResult(connectorMessageProcessor.process(createMuleEvent(message)));
} else {
throw createUnsupportedUrlException(url);
}
}
private Either<Error, Message> createEitherResult(Event muleEvent) {
if (muleEvent == null) {
// This should never return a null event. This happen because of mule 3.x behaviour with filters.
// We will just return an error in this case.
ErrorType anyErrorType = muleContext.getErrorTypeRepository().getAnyErrorType();
return left(builder(new MuleRuntimeException(createStaticMessage(MESSAGE_FILTERED_ERROR_MESSAGE))).errorType(anyErrorType)
.build());
}
if (!muleEvent.getError().isPresent()) {
return right(muleEvent.getMessage());
}
return left(muleEvent.getError().get());
}
@Override
public Either<Error, Message> send(String url, Message message, OperationOptions operationOptions)
throws MuleException {
final Processor connectorMessageProcessor = getConnectorMessageProcessLocator()
.locateConnectorOperation(url, operationOptions, REQUEST_RESPONSE);
if (connectorMessageProcessor != null) {
if (connectorMessageProcessor instanceof FlowConstructAware) {
((FlowConstructAware) connectorMessageProcessor).setFlowConstruct(flowConstruct);
}
return createEitherResult(returnEvent(connectorMessageProcessor.process(createMuleEvent(message))));
} else {
throw createUnsupportedUrlException(url);
}
}
private MuleException createUnsupportedUrlException(String url) {
return new DefaultMuleException("No installed connector supports url " + url);
}
@Override
public Either<Error, Message> send(String url, Object payload, Map<String, Serializable> messageProperties,
long timeout)
throws MuleException {
return send(url, createMessage(payload, messageProperties), timeout);
}
@Override
public Either<Error, Message> send(String url, Message message, long timeout) throws MuleException {
return send(url, message, newOptions().outbound().responseTimeout(timeout).build());
}
protected Message createMessage(Object payload, Map<String, Serializable> messageProperties) {
final Builder builder = InternalMessage.builder().payload(payload);
if (messageProperties != null) {
builder.outboundProperties(messageProperties);
}
return builder.build();
}
@Override
public void dispatch(String url, Message message) throws MuleException {
final Processor connectorMessageProcessor = getConnectorMessageProcessLocator()
.locateConnectorOperation(url, newOptions().outbound().build(), ONE_WAY);
if (connectorMessageProcessor != null) {
if (connectorMessageProcessor instanceof FlowConstructAware) {
((FlowConstructAware) connectorMessageProcessor).setFlowConstruct(flowConstruct);
}
connectorMessageProcessor.process(createMuleEvent(message));
} else {
throw createUnsupportedUrlException(url);
}
}
@Override
public void dispatch(String url, Message message, OperationOptions operationOptions) throws MuleException {
final Processor connectorMessageProcessor =
getConnectorMessageProcessLocator().locateConnectorOperation(url, operationOptions, ONE_WAY);
if (connectorMessageProcessor != null) {
if (connectorMessageProcessor instanceof FlowConstructAware) {
((FlowConstructAware) connectorMessageProcessor).setFlowConstruct(flowConstruct);
}
connectorMessageProcessor.process(createMuleEvent(message));
} else {
dispatch(url, message);
}
}
@Override
public Either<Error, Optional<Message>> request(String url, long timeout) throws MuleException {
final OperationOptions operationOptions = newOptions().responseTimeout(timeout).build();
final Processor connectorMessageProcessor =
getConnectorMessageProcessLocator().locateConnectorOperation(url, operationOptions, ONE_WAY);
if (connectorMessageProcessor != null) {
if (connectorMessageProcessor instanceof FlowConstructAware) {
((FlowConstructAware) connectorMessageProcessor).setFlowConstruct(flowConstruct);
}
final Event event = connectorMessageProcessor.process(createMuleEvent(of(null)));
if (event == null) {
return right(empty());
}
if (event.getError().isPresent()) {
return left(event.getError().get());
}
return right(ofNullable(event.getMessage()));
} else {
return right(empty());
}
}
protected Event createMuleEvent(Message message) throws MuleException {
return baseEventBuilder(message).build();
}
private org.mule.runtime.core.api.Event.Builder baseEventBuilder(Message message) {
return Event.builder(create(flowConstruct, fromSingleComponent("muleClient"))).message(message).flow(flowConstruct);
}
protected Event returnEvent(Event event) {
if (event != null) {
return event;
} else {
return null;
}
}
}