/* * ============LICENSE_START======================================================= * Common Utils-Test * ================================================================================ * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ * 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. * ============LICENSE_END========================================================= */ package org.onap.policy.common.utils.test.log.logback; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.regex.Matcher; import java.util.regex.Pattern; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.AppenderBase; /** * This is an appender that is intended for use by JUnit tests that wish to * capture logged messages. The appender takes an optional list of regular * expressions that are used to identify and extract data of interest. *

* If no patterns are provided, then every logged message is recorded. However, * if patterns are provided, then only messages that match one of the patterns * are recorded. In addition, if the pattern contains a capture group that is * non-null, only the captured group is recorded. Otherwise, the entire portion * of the message that matches the pattern is recorded. *

* All operations are thread-safe. */ public class ExtractAppender extends AppenderBase { /** * Extracted text is placed here. */ private final Queue extracted; /** * Regular expressions/Patterns to be used to extract text. Uses a * LinkedHashMap so that order is preserved. */ private final LinkedHashMap patterns; /** * Records every message that is logged. */ public ExtractAppender() { this(new LinkedList<>()); } /** * Records portions of messages that match one of the regular expressions. * * @param regex * regular expression (i.e., {@link Pattern}) to match */ public ExtractAppender(String... regex) { this(new LinkedList<>(), regex); } /** * Rather than allocating an internal queue to store matched messages, * messages are recorded in the specified target queue using the * {@link Queue#offer(Object)} method. Note: whenever the queue is used, it * will be synchronized to prevent simultaneous accesses. * * @param target * @param regex * regular expression (i.e., {@link Pattern}) to match */ public ExtractAppender(Queue target, String... regex) { extracted = target; patterns = new LinkedHashMap<>(regex.length); for (String re : regex) { patterns.put(re, Pattern.compile(re)); } } /* * (non-Javadoc) * * @see ch.qos.logback.core.AppenderBase#append(Object) */ @Override protected void append(ILoggingEvent event) { String msg = event.getMessage(); synchronized (patterns) { if (patterns.isEmpty()) { addExtraction(msg); return; } for (Pattern p : patterns.values()) { Matcher m = p.matcher(msg); if (m.find()) { addGroupMatch(m); break; } } } } /** * Adds the first match group to {@link #extracted}. * * @param mat * the matcher containing the groups * @return {@code true} if a group was found, {@code false} otherwise */ private void addGroupMatch(Matcher mat) { int ngroups = mat.groupCount(); for (int x = 1; x <= ngroups; ++x) { String txt = mat.group(x); if (txt != null) { addExtraction(txt); return; } } addExtraction(mat.group()); } /** * Adds an item to {@link #extracted}, in a thread-safe manner. It uses the * queue's offer() method so that the queue can discard the item if * it so chooses, without generating an exception. * * @param txt * text to be added */ private void addExtraction(String txt) { synchronized (extracted) { extracted.offer(txt); } } /** * Gets the text that has been extracted. * * @return a copy of the text that has been extracted */ public List getExtracted() { synchronized (extracted) { return new ArrayList<>(extracted); } } /** * Clears the list of extracted text. */ public void clearExtractions() { synchronized (extracted) { extracted.clear(); } } /** * Adds a pattern to be matched by this appender. * * @param regex * regular expression (i.e., {@link Pattern}) to match */ public void setPattern(String regex) { synchronized (patterns) { patterns.put(regex, Pattern.compile(regex)); } } }