
org.gradle.integtests.fixtures.executer.LogContent Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-api Show documentation
Show all versions of gradle-api Show documentation
Gradle 6.9.1 API redistribution.
/*
* Copyright 2018 the original author or authors.
*
* 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 org.gradle.integtests.fixtures.executer;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import org.apache.commons.lang.StringUtils;
import org.fusesource.jansi.AnsiOutputStream;
import org.gradle.api.Action;
import org.gradle.api.UncheckedIOException;
import org.gradle.internal.Pair;
import javax.annotation.Nullable;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class LogContent {
private final static Pattern DEBUG_PREFIX = Pattern.compile("\\d{2}:\\d{2}:\\d{2}\\.\\d{3} \\[\\w+] \\[.+?] ");
private final static String PROGRESS_BAR_PATTERN = "<[-=(\u001b\\[\\d+[a-zA-Z;])]*> \\d+% (INITIALIZ|CONFIGUR|EXECUT|WAIT)ING( \\[((\\d+h )? \\d+m )?\\d+s\\])?";
private final static String WORK_IN_PROGRESS_PATTERN = "\u001b\\[\\d+[a-zA-Z]> (IDLE|[:a-z][\\w\\s\\d:>/\\\\\\.]+)\u001b\\[\\d*[a-zA-Z]";
private final static String DOWN_MOVEMENT_WITH_NEW_LINE_PATTERN = "\u001b\\[\\d+B\\n";
private final static Pattern WORK_IN_PROGRESS_AREA_PATTERN = Pattern.compile(PROGRESS_BAR_PATTERN + "|" + WORK_IN_PROGRESS_PATTERN + "|" + DOWN_MOVEMENT_WITH_NEW_LINE_PATTERN);
private final static Pattern JAVA_ILLEGAL_ACCESS_WARNING_PATTERN = Pattern.compile("(?ms)WARNING: An illegal reflective access operation has occurred$.+?"
+ "^WARNING: All illegal access operations will be denied in a future release\r?\n");
private final ImmutableList lines;
private final boolean definitelyNoDebugPrefix;
private final LogContent rawContent;
private LogContent(ImmutableList lines, boolean definitelyNoDebugPrefix, LogContent rawContent) {
this.lines = lines;
this.rawContent = rawContent == null ? this : rawContent;
this.definitelyNoDebugPrefix = definitelyNoDebugPrefix || lines.isEmpty();
}
/**
* Creates a new instance, from raw characters.
*/
public static LogContent of(String chars) {
String stripped = stripWorkInProgressArea(chars);
LogContent raw = new LogContent(toLines(stripped), false, null);
return new LogContent(toLines(stripJavaIllegalAccessWarnings(stripped)), false, raw);
}
private static ImmutableList toLines(String chars) {
List lines = new ArrayList();
int pos = 0;
while (pos < chars.length()) {
int next = chars.indexOf('\n', pos);
if (next < 0) {
lines.add(chars.substring(pos));
pos = chars.length();
continue;
}
if (next > pos && chars.charAt(next - 1) == '\r') {
lines.add(chars.substring(pos, next - 1));
pos = next + 1;
} else {
lines.add(chars.substring(pos, next));
pos = next + 1;
}
if (pos == chars.length()) {
// trailing EOL
lines.add("");
}
}
return ImmutableList.copyOf(lines);
}
/**
* Creates a new instance from a sequence of lines (without the line separators).
*/
public static LogContent of(List lines) {
return new LogContent(ImmutableList.copyOf(lines), false, null);
}
public static LogContent empty() {
return new LogContent(ImmutableList.of(), true, null);
}
/**
* Returns the original content that this content was built from, after transforms such as {@link #removeDebugPrefix()} or {@link #splitOnFirstMatchingLine(Pattern)}.
*/
public LogContent getRawContent() {
return rawContent;
}
/**
* Does not return the text of this content.
*/
@Override
public String toString() {
// Intentionally not the text
return lines.toString();
}
/**
* Returns this content formatted using a new line char to separate lines.
*/
public String withNormalizedEol() {
if (lines.isEmpty()) {
return "";
}
return Joiner.on('\n').join(lines);
}
/**
* Returns this content separated into lines. The line does not include the line separator.
*/
public ImmutableList getLines() {
return lines;
}
private LogContent lines(int startLine, int endLine) {
if (rawContent != this) {
throw new UnsupportedOperationException("not implemented");
}
return new LogContent(lines.subList(startLine, endLine), definitelyNoDebugPrefix, null);
}
/**
* Visits each line in this content. The line does not include the line separator.
*/
public void eachLine(Action super String> action) {
for (String line : lines) {
action.execute(line);
}
}
/**
* Locates the log content starting with the first line that matches the given pattern, or null if no such line.
*
* @return a pair containing (content-before-matching-line, content-from-matching-line)
*/
public @Nullable
Pair splitOnFirstMatchingLine(Pattern pattern) {
for (int i = 0; i < lines.size(); i++) {
String line = lines.get(i);
if (pattern.matcher(line).matches()) {
LogContent before = new LogContent(lines.subList(0, i), definitelyNoDebugPrefix, rawContent.lines(0, i));
LogContent after = new LogContent(lines.subList(i, lines.size()), definitelyNoDebugPrefix, rawContent.lines(i, lines.size()));
return Pair.of(before, after);
}
}
return null;
}
/**
* Returns the number of lines that match the given pattern.
*/
public int countMatches(Pattern pattern) {
int count = 0;
for (String line : lines) {
if (pattern.matcher(line).matches()) {
count++;
}
}
return count;
}
/**
* Drops the first n lines.
*/
public LogContent drop(int i) {
return new LogContent(lines.subList(i, lines.size()), definitelyNoDebugPrefix, rawContent.lines(i, lines.size()));
}
/**
* Returns a copy of this log content with the debug prefix removed.
*/
public LogContent removeDebugPrefix() {
if (definitelyNoDebugPrefix) {
return this;
}
List result = new ArrayList(lines.size());
for (String line : lines) {
java.util.regex.Matcher matcher = DEBUG_PREFIX.matcher(line);
if (matcher.lookingAt()) {
result.add(line.substring(matcher.end()));
} else {
result.add(line);
}
}
return new LogContent(ImmutableList.copyOf(result), true, rawContent);
}
/**
* Returns a copy of this log content with ANSI control characters removed.
*/
public LogContent removeAnsiChars() {
if (lines.isEmpty()) {
return this;
}
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Writer writer = new OutputStreamWriter(new AnsiOutputStream(baos));
for (int i = 0; i < lines.size(); i++) {
if (i > 0) {
writer.write("\n");
}
writer.write(lines.get(i));
}
writer.flush();
return new LogContent(toLines(baos.toString()), definitelyNoDebugPrefix, rawContent);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
/**
* Remove all blank lines.
*/
public LogContent removeBlankLines() {
List nonBlankLines = lines.stream().filter(StringUtils::isNotBlank).collect(Collectors.toList());
return new LogContent(ImmutableList.copyOf(nonBlankLines), definitelyNoDebugPrefix, rawContent);
}
public static String stripWorkInProgressArea(String output) {
String result = output;
for (int i = 1; i <= 10; ++i) {
result = result.replaceAll(workInProgressAreaScrollingPattern(i), "");
}
return WORK_IN_PROGRESS_AREA_PATTERN.matcher(result).replaceAll("");
}
public static String stripJavaIllegalAccessWarnings(String result) {
return JAVA_ILLEGAL_ACCESS_WARNING_PATTERN.matcher(result).replaceAll("");
}
private static String workInProgressAreaScrollingPattern(int scroll) {
return "(\u001b\\[0K\\n){" + scroll + "}\u001b\\[" + scroll + "A";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy