/* * 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.api.execution; import static java.lang.String.format; import static java.util.regex.Pattern.compile; import org.mule.runtime.api.meta.AnnotatedObject; import org.mule.runtime.api.util.ComponentLocationProvider; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.namespace.QName; /** * Provides a standard way to generate a log entry or message that references an element in a flow. * * @since 3.8.0 */ public abstract class LocationExecutionContextProvider extends ComponentLocationProvider implements ExceptionContextProvider { protected static final QName SOURCE_ELEMENT_ANNOTATION_KEY = new QName("http://www.mulesoft.org/schema/mule/documentation", "sourceElement"); private static final Pattern URL_PATTERN = compile("url=\"[a-z]*://([^@]*)@"); private static final Pattern ADDRESS_PATTERN = compile("address=\"[a-z]*://([^@]*)@"); private static final Pattern PASSWORD_PATTERN = compile("password=\"([^\"]*)\""); private static final String PASSWORD_MASK = "<<credentials>>"; public static final String PASSWORD_ATTRIBUTE_MASK = "password=\"%s\""; /** * Populates the passed beanAnnotations with the other passed parameters. * * @param beanAnnotations the map with annotations to populate * @param fileName the name of the file where the element definition was read from. * @param lineNumber the line number where the definition of the element starts in the file. * @param xmlContent the xml representation of the element definition. */ public static void addMetadataAnnotationsFromXml(Map<QName, Object> beanAnnotations, String fileName, int lineNumber, String xmlContent) { if (fileName != null) { beanAnnotations.put(SOURCE_FILE_ANNOTATION_KEY, fileName); } beanAnnotations.put(SOURCE_FILE_LINE_ANNOTATION_KEY, lineNumber); beanAnnotations.put(SOURCE_ELEMENT_ANNOTATION_KEY, xmlContent); } protected static String getSourceXML(AnnotatedObject element) { Object sourceXml = element.getAnnotation(SOURCE_ELEMENT_ANNOTATION_KEY); return sourceXml != null ? maskPasswords(sourceXml.toString()) : null; } protected static String maskPasswords(String xml) { xml = maskUrlPassword(xml, URL_PATTERN); xml = maskUrlPassword(xml, ADDRESS_PATTERN); Matcher matcher = PASSWORD_PATTERN.matcher(xml); if (matcher.find() && matcher.groupCount() > 0) { xml = xml.replaceAll(maskPasswordAttribute(matcher.group(1)), maskPasswordAttribute(PASSWORD_MASK)); } xml = maskUrlPassword(xml, PASSWORD_PATTERN); return xml; } private static String maskUrlPassword(String xml, Pattern pattern) { Matcher matcher = pattern.matcher(xml); if (matcher.find() && matcher.groupCount() > 0) { xml = xml.replaceAll(matcher.group(1), PASSWORD_MASK); } return xml; } private static String maskPasswordAttribute(String password) { return format(PASSWORD_ATTRIBUTE_MASK, password); } }