/*
* Copyright (c) 2010-2017 Evolveum
*
* Licensed 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 com.evolveum.midpoint.notifications.impl.api.transports;
import com.evolveum.midpoint.model.common.expression.Expression;
import com.evolveum.midpoint.model.common.expression.ExpressionEvaluationContext;
import com.evolveum.midpoint.model.common.expression.ExpressionFactory;
import com.evolveum.midpoint.model.common.expression.ExpressionVariables;
import com.evolveum.midpoint.model.impl.expr.ModelExpressionThreadLocalHolder;
import com.evolveum.midpoint.notifications.api.NotificationManager;
import com.evolveum.midpoint.notifications.api.events.Event;
import com.evolveum.midpoint.notifications.api.transports.Message;
import com.evolveum.midpoint.notifications.api.transports.Transport;
import com.evolveum.midpoint.notifications.impl.NotificationFunctionsImpl;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismPropertyDefinition;
import com.evolveum.midpoint.prism.PrismPropertyDefinitionImpl;
import com.evolveum.midpoint.prism.PrismPropertyValue;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.LoggingUtils;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.CustomTransportConfigurationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.xml.namespace.QName;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Date;
/**
* TODO clean up
* @author mederly
*/
@Component
public class CustomTransport implements Transport {
private static final Trace LOGGER = TraceManager.getTrace(CustomTransport.class);
private static final String NAME = "custom";
private static final String DOT_CLASS = CustomTransport.class.getName() + ".";
@Autowired
protected PrismContext prismContext;
@Autowired
protected ExpressionFactory expressionFactory;
@Autowired
@Qualifier("cacheRepositoryService")
private transient RepositoryService cacheRepositoryService;
@Autowired
private NotificationManager notificationManager;
@PostConstruct
public void init() {
notificationManager.registerTransport(NAME, this);
}
@Override
public void send(Message message, String transportName, Event event, Task task, OperationResult parentResult) {
OperationResult result = parentResult.createSubresult(DOT_CLASS + "send");
result.addCollectionOfSerializablesAsParam("message recipient(s)", message.getTo());
result.addParam("message subject", message.getSubject());
SystemConfigurationType systemConfiguration = NotificationFunctionsImpl
.getSystemConfiguration(cacheRepositoryService, result);
if (systemConfiguration == null || systemConfiguration.getNotificationConfiguration() == null) {
String msg = "No notifications are configured. Custom notification to " + message.getTo() + " will not be sent.";
LOGGER.warn(msg) ;
result.recordWarning(msg);
return;
}
String configName = transportName.length() > NAME.length() ? transportName.substring(NAME.length() + 1) : null; // after "sms:"
CustomTransportConfigurationType configuration = systemConfiguration.getNotificationConfiguration().getCustomTransport().stream()
.filter(transportConfigurationType -> java.util.Objects.equals(configName, transportConfigurationType.getName()))
.findFirst().orElse(null);
if (configuration == null) {
String msg = "Custom configuration '" + configName + "' not found. Custom notification to " + message.getTo() + " will not be sent.";
LOGGER.warn(msg) ;
result.recordWarning(msg);
return;
}
String file = configuration.getRedirectToFile();
if (file != null) {
writeToFile(message, file, result);
return;
}
try {
evaluateExpression(configuration.getExpression(), getDefaultVariables(message, event),
"custom transport expression", task, result);
LOGGER.trace("Custom transport expression execution finished");
result.recordSuccess();
} catch (Throwable t) {
String msg = "Couldn't execute custom transport expression";
LoggingUtils.logException(LOGGER, msg, t);
result.recordFatalError(msg + ": " + t.getMessage(), t);
}
}
// TODO deduplicate
private void writeToFile(Message message, String file, OperationResult result) {
try {
TransportUtil.appendToFile(file, formatToFile(message));
result.recordSuccess();
} catch (IOException e) {
LoggingUtils.logException(LOGGER, "Couldn't write to message redirect file {}", e, file);
result.recordPartialError("Couldn't write to message redirect file " + file, e);
}
}
private String formatToFile(Message mailMessage) {
return "================ " + new Date() + " =======\n" + mailMessage.toString() + "\n\n";
}
// TODO deduplicate
private void evaluateExpression(ExpressionType expressionType, ExpressionVariables expressionVariables,
String shortDesc, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException {
QName resultName = new QName(SchemaConstants.NS_C, "result");
PrismPropertyDefinition<String> resultDef = new PrismPropertyDefinitionImpl<>(resultName, DOMUtil.XSD_STRING, prismContext);
Expression<PrismPropertyValue<String>,PrismPropertyDefinition<String>> expression = expressionFactory.makeExpression(expressionType, resultDef, shortDesc, task, result);
ExpressionEvaluationContext params = new ExpressionEvaluationContext(null, expressionVariables, shortDesc, task, result);
ModelExpressionThreadLocalHolder.evaluateExpressionInContext(expression, params, task, result);
}
protected ExpressionVariables getDefaultVariables(Message message, Event event) throws UnsupportedEncodingException {
ExpressionVariables variables = new ExpressionVariables();
variables.addVariableDefinition(SchemaConstants.C_MESSAGE, message);
variables.addVariableDefinition(SchemaConstants.C_EVENT, event);
return variables;
}
@Override
public String getDefaultRecipientAddress(UserType recipient) {
return "anything";
}
@Override
public String getName() {
return NAME;
}
}