Example usage for java.util.regex Matcher appendTail

List of usage examples for java.util.regex Matcher appendTail

Introduction

In this page you can find the example usage for java.util.regex Matcher appendTail.

Prototype

public StringBuilder appendTail(StringBuilder sb) 

Source Link

Document

Implements a terminal append-and-replace step.

Usage

From source file:org.opennms.ng.dao.support.DefaultResourceDao.java

/**
 * Fetch a specific resource by string ID.
 * @return Resource or null if resource cannot be found.
 * @throws IllegalArgumentException When the resource ID string does not match the expected regex pattern
 * @throws org.springframework.orm.ObjectRetrievalFailureException If any exceptions are thrown while searching for the resource
 *///  w  w  w . j  a v a2 s .co  m
@Override
public OnmsResource getResourceById(String id) {
    OnmsResource resource = null;

    Pattern p = Pattern.compile("([^\\[]+)\\[([^\\]]*)\\](?:\\.|$)");
    Matcher m = p.matcher(id);
    StringBuffer sb = new StringBuffer();

    while (m.find()) {
        String resourceTypeName = DefaultResourceDao.decode(m.group(1));
        String resourceName = DefaultResourceDao.decode(m.group(2));

        try {
            if (resource == null) {
                resource = getTopLevelResource(resourceTypeName, resourceName);
            } else {
                resource = getChildResource(resource, resourceTypeName, resourceName);
            }
        } catch (Throwable e) {
            LOG.warn("Could not get resource for resource ID \"{}\"", id, e);
            return null;
        }

        m.appendReplacement(sb, "");
    }

    m.appendTail(sb);

    if (sb.length() > 0) {
        LOG.warn("resource ID '{}' does not match pattern '{}' at '{}'", id, p.toString(), sb);
        return null;
    } else {
        return resource;
    }
}

From source file:com.ichi2.libanki.Media.java

private List<String> _expandClozes(String string) {
    Set<String> ords = new TreeSet<String>();
    Matcher m = Pattern.compile("\\{\\{c(\\d+)::.+?\\}\\}").matcher(string);
    while (m.find()) {
        ords.add(m.group(1));/*w w  w.  ja va  2 s  .c o m*/
    }
    ArrayList<String> strings = new ArrayList<String>();
    String clozeReg = Template.clozeReg;

    for (String ord : ords) {
        StringBuffer buf = new StringBuffer();
        m = Pattern.compile(String.format(Locale.US, clozeReg, ord)).matcher(string);
        while (m.find()) {
            if (!TextUtils.isEmpty(m.group(3))) {
                m.appendReplacement(buf, "[$3]");
            } else {
                m.appendReplacement(buf, "[...]");
            }
        }
        m.appendTail(buf);
        String s = buf.toString().replaceAll(String.format(Locale.US, clozeReg, ".+?"), "$1");
        strings.add(s);
    }
    strings.add(string.replaceAll(String.format(Locale.US, clozeReg, ".+?"), "$1"));
    return strings;
}

From source file:com.ikanow.infinit.e.application.utils.LogstashConfigUtils.java

public static String validateLogstashInput(String sourceKey, String config, StringBuffer errorMessage,
        boolean isAdmin) {

    if (null == _props) {
        _props = new PropertiesManager();
        String allowedInputs = _props.getProperty("harvest.logstash.allowed_inputs");

        if ((null == allowedInputs) || (allowedInputs.isEmpty())) {
            allowedInputs = "collectd,drupal_dblog,gelf,gemfire,imap,irc,lumberjack,s3,snmptrap,sqs,syslog,twitter,udp,xmpp,zenoss";
            // currently *not* allowed by default: elasticsearch,eventlog,exec,file,ganglia,generator,graphite,heroku,jmx,log4j,pipe,puppet_facter,rabbitmq,redit,relp,sqlite,stdin,stomp,tcp,unix,varnishlog,websocket,wmi,zeromq
        }//from w w  w .jav a2  s  .co m
        _allowedInputs.addAll(Arrays.asList(allowedInputs.toLowerCase().split("\\s*,\\s*")));

        String allowedFilters = _props.getProperty("harvest.logstash.allowed_filters");
        if ((null == allowedFilters) || (allowedFilters.isEmpty())) {
            allowedFilters = "advisor,alter,anonymize,checksum,cidr,cipher,clone,collate,csv,date,dns,drop,elapsed,extractnumbers,fingerprint,geoip,gelfify,grep,grok,grokdiscovery,l18n,json,json_encode,kv,metaevent,metrics,multiline,mutate,noop,prune,punct,railsparallelrequest,range,sleep,split,sumnumbers,syslog_pri,throttle,translate,unique,urldecode,useragent,uuid,wms,wmts,xml";
            // currently *not* allowed by default: elasticsearch,ruby,zeromq
        }
        _allowedFilters.addAll(Arrays.asList(allowedFilters.toLowerCase().split("\\s*,\\s*")));
    } //TESTED (3_2a)

    // Configuration validation, phase 1

    errorMessage.append("Validation error:");
    BasicDBObject jsonifiedConfig = parseLogstashConfig(config, errorMessage);
    if (null == jsonifiedConfig) {
        return null;
    }
    errorMessage.setLength(0);

    // Configuration validation, phase 2 - very basic checks on the structure of the object

    Object input = jsonifiedConfig.get("input");
    if ((null == input) || !(input instanceof BasicDBObject)) { // Does input exist?
        errorMessage.append(
                "Invalid input format, should be 'input { INPUT_TYPE { ... } }' (only one INPUT_TYPE) and also contain a filter, no \"s around them. (0)");
        return null;
    } //TESTED (3_1d)
    else { // Check there's only one input type and (unless admin) it's one of the allowed types
        BasicDBObject inputDbo = (BasicDBObject) input;
        if (1 != inputDbo.size()) {
            errorMessage.append(
                    "Invalid input format, should be 'input { INPUT_TYPE { ... } }' (only one INPUT_TYPE) and also contain a filter, no \"s around them. (1)");
            return null;
        } //TESTED
        if (!isAdmin) {
            for (String key : inputDbo.keySet()) {
                if (!_allowedInputs.contains(key.toLowerCase())) {
                    errorMessage.append("Security error, non-admin not allowed input type " + key
                            + ", allowed options: " + _allowedInputs.toString());
                    return null;
                } //TESTED
            }
        } //TESTED (3_1abc)
    }
    Object filter = jsonifiedConfig.get("filter");
    if ((null == filter) || !(filter instanceof BasicDBObject)) { // Does filter exist?
        errorMessage.append(
                "Invalid input format, should be 'input { INPUT_TYPE { ... } }' (only one INPUT_TYPE) and also contain a filter, no \"s around them. (2)");
        return null;
    } //TESTED (3_2d)
    else { // Check there's only one input type and (unless admin) it's one of the allowed types
        if (!isAdmin) {
            BasicDBObject filterDbo = (BasicDBObject) filter;
            for (String key : filterDbo.keySet()) {
                if (!_allowedFilters.contains(key.toLowerCase())) {
                    errorMessage.append("Security error, non-admin not allowed filter type " + key
                            + ", allowed options: " + _allowedFilters.toString());
                    return null;
                } //TESTED
            }
        } //TESTED (3_2abc)
    }

    // Configuration validation, phase 3

    Matcher m = null;
    m = _validationRegexInputReplace.matcher(config);
    if (!m.find()) {
        errorMessage.append(
                "Invalid input format, should be 'input { INPUT_TYPE { ... } }' (only one INPUT_TYPE) and also contain a filter, no \"s around them. (3)");
        return null;
    } //TESTED (see above)
    else { // If admin check on allowed types
        String inputType = m.group(2).toLowerCase();

        // If it's a file-based plugin then replace sincedb_path (check that it's not used during the JSON-ification):
        if (inputType.equalsIgnoreCase("file") || inputType.equalsIgnoreCase("s3")) {
            config = _validationRegexInputReplace.matcher(config)
                    .replaceFirst("$1\n      sincedb_path => \"_XXX_DOTSINCEDB_XXX_\"\n");
        } //TESTED

    } //TESTED

    m = _validationRegexNoSourceKey.matcher(config);
    // (this won't help malicious changes to source key, but will let people know they're not supposed to)
    if (m.find()) {
        errorMessage.append(
                "Not allowed to reference sourceKey - this is automatically appended by the logstash harvester");
        return null;
    } //TESTED      

    // OK now need to append the sourceKey at each stage of the pipeline to really really ensure that nobody sets sourceKey to be different 

    m = _validationRegexAppendFields.matcher(config);
    StringBuffer newConfig = new StringBuffer();
    if (m.find()) {
        m.appendReplacement(newConfig, "add_field => [ \"sourceKey\", \"" + sourceKey + "\"] \n\n" + m.group()
                + " \n if [sourceKey] == \"" + sourceKey + "\" { \n\n ");
    } else {
        errorMessage.append(
                "Invalid input format, should be 'input { INPUT_TYPE { ... } }' (only one INPUT_TYPE) and also contain a filter, no \"s around them. (4)");
        return null;
    }
    m.appendTail(newConfig);
    config = newConfig.toString();
    config = config.replaceAll("}[^}]*$", ""); // (remove the last })
    config += "\n\n mutate { update => [ \"sourceKey\", \"" + sourceKey + "\"] } \n}\n}\n"; // double check the sourceKey hasn't been overwritten and close the if from above
    //TESTED (syntactically correct and does overwrite sourceKey everywhere - success_2_2)

    return config;
}

From source file:org.sakaiproject.util.impl.FormattedTextImpl.java

public String encodeUrlsAsHtml(String text) {
    // MOVED FROM Web
    Pattern p = Pattern.compile(
            "(?<!href=['\"]{1})(((https?|s?ftp|ftps|file|smb|afp|nfs|(x-)?man|gopher|txmt)://|mailto:)[-:;@a-zA-Z0-9_.,~%+/?=&#]+(?<![.,?:]))");
    Matcher m = p.matcher(text);
    StringBuffer buf = new StringBuffer();
    while (m.find()) {
        String matchedUrl = m.group();
        m.appendReplacement(buf, "<a href=\"" + unEscapeHtml(matchedUrl) + "\">$1</a>");
    }/*from   ww  w .j  a  v  a2  s.  c om*/
    m.appendTail(buf);
    return buf.toString();
}

From source file:org.opennms.ng.dao.support.DefaultResourceDao.java

/**
 * Fetch a specific list of resources by string ID.
 * @return Resources or null if resources cannot be found.
 * @throws IllegalArgumentException When the resource ID string does not match the expected regex pattern
 * @throws org.springframework.orm.ObjectRetrievalFailureException If any exceptions are thrown while searching for the resource
 *///  w ww . j  av  a 2s  .  c  om
@Override
public List<OnmsResource> getResourceListById(String id)
        throws IllegalArgumentException, ObjectRetrievalFailureException {
    OnmsResource topLevelResource = null;

    Pattern p = Pattern.compile("([^\\[]+)\\[([^\\]]*)\\](?:\\.|$)");
    Matcher m = p.matcher(id);
    StringBuffer sb = new StringBuffer();

    while (m.find()) {
        String resourceTypeName = DefaultResourceDao.decode(m.group(1));
        String resourceName = DefaultResourceDao.decode(m.group(2));

        try {
            if (topLevelResource == null) {
                topLevelResource = getTopLevelResource(resourceTypeName, resourceName);
            } else {
                return getChildResourceList(topLevelResource);
            }
        } catch (Throwable e) {
            throw new ObjectRetrievalFailureException(OnmsResource.class, id,
                    "Could not get resource for resource ID '" + id + "'", e);
        }

        m.appendReplacement(sb, "");
    }

    m.appendTail(sb);

    if (sb.length() > 0) {
        throw new IllegalArgumentException(
                "resource ID '" + id + "' does not match pattern '" + p.toString() + "' at '" + sb + "'");
    }
    return null;
}

From source file:mergedoc.core.Comment.java

/**
 * JDK1.5  API ???? pre HTML ??/*from w  w  w. ja  v  a  2s  .  c  o  m*/
 * ???????????Java ?????
 * ????pre ????????????? API ?
 * ???
 */
private void replacePreBody() {

    // pre ??????????
    if (!docBody.contains("<pre>")) {
        return;
    }

    // Java ? pre ??
    LinkedList<String> pres = null;
    String commentBody = FastStringUtils.replaceAll(srcBody, "(?m)^\\s*\\*( |)", "");
    Pattern pat = PatternCache.getPattern("(?s)(<pre>\n)(.+?)(\n</pre>)");
    Matcher mat = pat.matcher(commentBody);
    while (mat.find()) {
        if (pres == null) {
            pres = new LinkedList<String>();
        }
        pres.add(mat.group(2));
    }
    if (pres == null) {
        return;
    }

    // API ? pre ?? Java ???
    Matcher descMatcher = pat.matcher(docBody);
    StringBuffer sb = new StringBuffer();
    while (descMatcher.find()) {

        // pre ??????????
        if (pres.size() == 0) {
            return;
        }
        String value = FastStringUtils.quoteReplacement(pres.removeFirst());
        descMatcher.appendReplacement(sb, "$1" + value + "$3");
    }
    descMatcher.appendTail(sb);

    // pre ????????
    if (pres.size() == 0) {
        docBody = sb.toString();
    }
}

From source file:org.nuxeo.common.utils.TextTemplate.java

/**
 * That method is not recursive. It processes the given text only once.
 *
 * @param props CryptoProperties containing the variable values
 * @param text Text to process//  w  w  w  .j a v a  2  s .  c  o m
 * @return the processed text
 * @since 7.4
 */
protected String processString(CryptoProperties props, String text) {
    Matcher m = PATTERN.matcher(text);
    StringBuffer sb = new StringBuffer();
    while (m.find()) {
        // newVarsValue == ${[#]embeddedVar[:=default]}
        String embeddedVar = m.group(PATTERN_GROUP_VAR);
        String value = props.getProperty(embeddedVar, keepEncryptedAsVar);
        if (value == null) {
            value = m.group(PATTERN_GROUP_DEFAULT);
        }
        if (value != null) {
            if (trim) {
                value = value.trim();
            }
            if (Crypto.isEncrypted(value)) {
                if (keepEncryptedAsVar && m.group(PATTERN_GROUP_DECRYPT) == null) {
                    value = "${" + embeddedVar + "}";
                } else {
                    value = new String(vars.getCrypto().decrypt(value));
                }
            }

            // Allow use of backslash and dollars characters
            value = Matcher.quoteReplacement(value);
            m.appendReplacement(sb, value);
        }
    }
    m.appendTail(sb);
    return sb.toString();
}

From source file:hydrograph.ui.dataviewer.filter.FilterHelper.java

/**
 * Gets the condition./*from w  w  w.j  a v  a2 s.  c o m*/
 * 
 * @param conditionsList
 *            the conditions list
 * @param fieldsAndTypes
 *            the fields and types
 * @param groupSelectionMap
 *            the group selection map
 * @param isDisplayPressed
 *            the is display pressed
 * @return the condition
 */
public StringBuffer getCondition(final List<Condition> conditionsList, final Map<String, String> fieldsAndTypes,
        final Map<Integer, List<List<Integer>>> groupSelectionMap, boolean isDisplayPressed) {

    //put number of elements in the list
    //1 2 3 4 5
    List<String> actualStringList = new LinkedList<>();
    for (int conditionIndex = 0; conditionIndex < conditionsList.size(); conditionIndex++) {
        actualStringList.add(conditionIndex, String.valueOf((conditionIndex)));
    }
    logger.trace(actualStringList.toString());
    //start adding brackets for grouping
    Set<Integer> treeSet = (Set<Integer>) groupSelectionMap.keySet();
    if (treeSet.size() > 0) {
        for (Integer position : treeSet) {
            List<List<Integer>> groupsInColumn = groupSelectionMap.get(position);
            for (int groupIndex = 0; groupIndex < groupsInColumn.size(); groupIndex++) {
                List<Integer> group = groupsInColumn.get(groupIndex);
                //add opening bracket before first element in the group
                if (!group.isEmpty()) {
                    Integer firstItem = group.get(0);
                    Integer firstItemIndex = actualStringList.indexOf(String.valueOf(firstItem));
                    actualStringList.add(firstItemIndex, FilterConstants.OPEN_BRACKET);
                    //add closing bracket after last element in the group                     
                    Integer lastItem = group.get(group.size() - 1);
                    Integer lastItemIndex = actualStringList.indexOf(String.valueOf(lastItem));
                    actualStringList.add(lastItemIndex + 1, FilterConstants.CLOSE_BRACKET);
                }
            }
        }
    }

    //start adding relational operators
    int indexOfRelational = 1;
    //start from 2nd index
    for (int item = 1; item < conditionsList.size(); item++) {
        int indexOfItem = actualStringList.indexOf(String.valueOf(item));
        while (true) {
            if ((actualStringList.get(indexOfItem - 1)).matches(FilterConstants.REGEX_DIGIT)
                    || (actualStringList.get(indexOfItem - 1))
                            .equalsIgnoreCase(FilterConstants.CLOSE_BRACKET)) {
                actualStringList.add(indexOfItem,
                        conditionsList.get(indexOfRelational).getRelationalOperator());
                break;
            } else {
                indexOfItem = indexOfItem - 1;
            }
        }
        indexOfRelational += 1;
        logger.trace(actualStringList.toString());
    }

    StringBuffer buffer = new StringBuffer();
    for (int item = 0; item < conditionsList.size(); item++) {
        StringBuffer conditionString = new StringBuffer();

        Condition condition = conditionsList.get(item);
        if (StringUtils.equalsIgnoreCase(condition.getConditionalOperator(), FilterConstants.BETWEEN)
                || StringUtils.equalsIgnoreCase(condition.getConditionalOperator(),
                        FilterConstants.BETWEEN_FIELD)) {
            conditionString.append(condition.getFieldName()).append(FilterConstants.SINGLE_SPACE)
                    .append(condition.getConditionalOperator()).append(FilterConstants.SINGLE_SPACE)
                    .append(getConditionValue(condition.getFieldName(), condition.getValue1(),
                            condition.getConditionalOperator(), fieldsAndTypes, isDisplayPressed))
                    .append(FilterConstants.SINGLE_SPACE).append(FilterConstants.AND)
                    .append(FilterConstants.SINGLE_SPACE)
                    .append(getConditionValue(condition.getFieldName(), condition.getValue2(),
                            condition.getConditionalOperator(), fieldsAndTypes, isDisplayPressed));
        } else {
            conditionString.append(condition.getFieldName()).append(FilterConstants.SINGLE_SPACE)
                    .append(condition.getConditionalOperator()).append(FilterConstants.SINGLE_SPACE)
                    .append(getConditionValue(condition.getFieldName(), condition.getValue1(),
                            condition.getConditionalOperator(), fieldsAndTypes, isDisplayPressed));
        }
        int index = actualStringList.indexOf(String.valueOf(item));
        actualStringList.set(index, conditionString.toString());
    }

    for (String item : actualStringList) {
        buffer.append(item + FilterConstants.SINGLE_SPACE);
    }

    Pattern p = Pattern.compile("\\(Field\\)");
    Matcher m = p.matcher(buffer);
    StringBuffer temp = new StringBuffer();
    while (m.find()) {
        m.appendReplacement(temp, "");
    }
    m.appendTail(temp);
    buffer = new StringBuffer(temp);
    return buffer;
}

From source file:org.codelibs.fess.helper.ViewHelper.java

protected String replaceHighlightQueries(final String cache, final String[] queries) {
    final StringBuffer buf = new StringBuffer(cache.length() + 100);
    final StringBuffer segBuf = new StringBuffer(1000);
    final Pattern p = Pattern.compile("<[^>]+>");
    final Matcher m = p.matcher(cache);
    final String[] regexQueries = new String[queries.length];
    final String[] hlQueries = new String[queries.length];
    for (int i = 0; i < queries.length; i++) {
        regexQueries[i] = Pattern.quote(queries[i]);
        hlQueries[i] = highlightTagPre + queries[i] + highlightTagPost;
    }//  www . j a va 2s . co  m
    while (m.find()) {
        segBuf.setLength(0);
        m.appendReplacement(segBuf, StringUtil.EMPTY);
        String segment = segBuf.toString();
        for (int i = 0; i < queries.length; i++) {
            segment = Pattern.compile(regexQueries[i], Pattern.CASE_INSENSITIVE).matcher(segment)
                    .replaceAll(hlQueries[i]);
        }
        buf.append(segment);
        buf.append(m.group(0));
    }
    segBuf.setLength(0);
    m.appendTail(segBuf);
    String segment = segBuf.toString();
    for (int i = 0; i < queries.length; i++) {
        segment = Pattern.compile(regexQueries[i], Pattern.CASE_INSENSITIVE).matcher(segment)
                .replaceAll(hlQueries[i]);
    }
    buf.append(segment);
    return buf.toString();
}

From source file:com.ikanow.aleph2.harvest.logstash.utils.LogstashConfigUtils.java

public static String validateLogstashInput(LogstashHarvesterConfigBean globals, String sourceKey, String config,
        StringBuffer errorMessage, boolean isAdmin) {

    _allowedInputs.addAll(Arrays.asList(globals.non_admin_inputs().toLowerCase().split("\\s*,\\s*")));
    _allowedFilters.addAll(Arrays.asList(globals.non_admin_filters().toLowerCase().split("\\s*,\\s*")));
    _allowedOutputs.addAll(Arrays.asList(globals.non_admin_outputs().toLowerCase().split("\\s*,\\s*")));

    // Configuration validation, phase 1

    errorMessage.append("Validation error:");
    ObjectNode jsonifiedConfig = parseLogstashConfig(config, errorMessage);
    if (null == jsonifiedConfig) {
        return null;
    }//from  w w  w.  j a  v  a 2 s. com
    errorMessage.setLength(0);

    // Configuration validation, phase 2 - very basic checks on the structure of the object

    Object input = jsonifiedConfig.get("input");
    if ((null == input) || !(input instanceof ObjectNode)) { // Does input exist?
        errorMessage.append(
                "Invalid input format, should be 'input { INPUT_TYPE { ... } }' (only one INPUT_TYPE) and also contain a filter, no \"s around them. (0)");
        return null;
    } //TESTED (3_1d)
    else { // Check there's only one input type and (unless admin) it's one of the allowed types
        ObjectNode inputDbo = (ObjectNode) input;
        if (1 != inputDbo.size()) {
            errorMessage.append(
                    "Invalid input format, should be 'input { INPUT_TYPE { ... } }' (only one INPUT_TYPE) and also contain a filter, no \"s around them. (1)");
            return null;
        } //TESTED
        if (!isAdmin) {
            for (String key : (Iterable<String>) () -> inputDbo.fieldNames()) {
                if (!_allowedInputs.contains(key.toLowerCase())) {
                    errorMessage.append("Security error, non-admin not allowed input type " + key
                            + ", allowed options: " + _allowedInputs.toString());
                    return null;
                } //TESTED
            }
        } //TESTED (3_1abc)
    }
    Object filter = jsonifiedConfig.get("filter");
    if ((null == filter) || !(filter instanceof ObjectNode)) { // Does filter exist?
        errorMessage.append(
                "Invalid input format, should be 'input { INPUT_TYPE { ... } }' (only one INPUT_TYPE) and also contain a filter, no \"s around them. (2)");
        return null;
    } //TESTED (3_2d)
    else { // Check there's only one input type and (unless admin) it's one of the allowed types
        if (!isAdmin) {
            ObjectNode filterDbo = (ObjectNode) filter;
            for (String key : (Iterable<String>) () -> filterDbo.fieldNames()) {
                if (!_allowedFilters.contains(key.toLowerCase())) {
                    errorMessage.append("Security error, non-admin not allowed filter type " + key
                            + ", allowed options: " + _allowedFilters.toString());
                    return null;
                } //TESTED
            }
        } //TESTED (3_2abc)
    }

    //TODO: same for output

    // Configuration validation, phase 3

    Matcher m = null;
    m = _validationRegexInputReplace.matcher(config);
    if (!m.find()) {
        errorMessage.append(
                "Invalid input format, should be 'input { INPUT_TYPE { ... } }' (only one INPUT_TYPE) and also contain a filter, no \"s around them. (3)");
        return null;
    } //TESTED (see above)
    else { // If admin check on allowed types
        String inputType = m.group(2).toLowerCase();

        // If it's a file-based plugin then replace sincedb_path (check that it's not used during the JSON-ification):
        if (inputType.equalsIgnoreCase("file")) {
            config = _validationRegexInputReplace.matcher(config)
                    .replaceFirst("$1\n      sincedb_path => \"_XXX_DOTSINCEDB_XXX_\"\n");
        } else if (inputType.equalsIgnoreCase("s3")) {
            config = _validationRegexInputReplace.matcher(config).replaceFirst(
                    "$1\n      sincedb_path => \"_XXX_DOTSINCEDB_XXX_\"\n      temporary_directory => \"_XXX_LSTEMPDIR_XXX_\"");
        }

    } //TESTED

    m = _validationRegexNoSourceKey.matcher(config);
    // (this won't help malicious changes to source key, but will let people know they're not supposed to)
    if (m.find()) {
        errorMessage.append(
                "Not allowed to reference sourceKey - this is automatically appended by the logstash harvester");
        return null;
    } //TESTED      

    // OK now need to append the sourceKey at each stage of the pipeline to really really ensure that nobody sets sourceKey to be different 

    m = _validationRegexAppendFields.matcher(config);
    StringBuffer newConfig = new StringBuffer();
    if (m.find()) {
        m.appendReplacement(newConfig, "add_field => [  \"[@metadata][sourceKey]\", \"" + sourceKey + "\"] \n\n"
                + m.group() + " \n if [@metadata][sourceKey] == \"" + sourceKey + "\" { \n\n ");
    } else {
        errorMessage.append(
                "Invalid input format, should be 'input { INPUT_TYPE { ... } }' (only one INPUT_TYPE) and also contain a filter, no \"s around them. (4)");
        return null;
    }
    m.appendTail(newConfig);
    config = newConfig.toString();
    config = config.replaceAll("}[^}]*$", ""); // (remove the last })
    config += "\n\n mutate { update => [ \"[@metadata][sourceKey]\", \"" + sourceKey + "\"] } \n}\n}\n"; // double check the sourceKey hasn't been overwritten and close the if from above
    //TESTED (syntactically correct and does overwrite sourceKey everywhere - success_2_2)

    return config;
}