177 lines
5.7 KiB
Java
177 lines
5.7 KiB
Java
package io.jenkins.plugins.sample;
|
|
|
|
import hudson.console.LineTransformationOutputStream;
|
|
|
|
import java.io.*;
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.charset.Charset;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Queue;
|
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
|
|
public class PBAutoBuildConsoleAnnotator extends LineTransformationOutputStream {
|
|
private final OutputStream out;
|
|
private final Charset charset;
|
|
private final boolean verboseLogging;
|
|
private final String workspace;
|
|
|
|
private List<String> warnings = new ArrayList<>();
|
|
private List<String> errors = new ArrayList<>();
|
|
|
|
private final PBAutoBuildErrorNote errorNote = new PBAutoBuildErrorNote();
|
|
private final PBAutoBuildWarningNote warningNote = new PBAutoBuildWarningNote();
|
|
|
|
// Pattern per Versione e Runtime
|
|
private Pattern versionPattern = Pattern.compile("PBAutoBuild Version: ([\\d\\.]+)");
|
|
private Pattern runtimePattern = Pattern.compile("Runtime Version: ([\\d\\.]+)");
|
|
|
|
// Pattern per Work Path
|
|
private Pattern workPathPattern = Pattern.compile("Work Path: (.+\\.exe)");
|
|
|
|
// Pattern per i progetti
|
|
private Pattern projectPattern = Pattern.compile("Deploying project ([a-zA-Z0-9_]+)");
|
|
|
|
// Pattern per i file (solo nome, escludendo il percorso)
|
|
private Pattern fileNamePattern = Pattern.compile("([^\\\\]+\\.\\w+)$");
|
|
private Pattern timestampPattern = Pattern.compile("(^\\d{2}:\\d{2}:\\d{2})");
|
|
|
|
// Pattern per Stage1, Stage2 e Regenerating
|
|
private Pattern stagePattern = Pattern.compile("(Normal|Stage1|Stage2|Regenerating) for ([a-zA-Z]:\\\\.*?\\\\([^\\\\]+\\.\\w+))");
|
|
private Pattern errorPattern = Pattern.compile("\\[\\s*Error\\s*\\](.*)");
|
|
private Pattern warningPattern = Pattern.compile("\\[\\s*Warning\\s*\\](.*)");
|
|
|
|
|
|
private final Queue<String> queueLog = new ConcurrentLinkedQueue<>();
|
|
private Thread consumerThread;
|
|
private boolean consumerThreadRunning;
|
|
|
|
|
|
public PBAutoBuildConsoleAnnotator(OutputStream out, Charset charset, boolean verboseLogging, String workspace) {
|
|
this.out = out;
|
|
this.charset = charset;
|
|
this.verboseLogging = verboseLogging;
|
|
this.workspace = workspace + File.separator;
|
|
|
|
startQueueConsumer();
|
|
}
|
|
|
|
|
|
@Override
|
|
protected void eol(byte[] b, int len) throws IOException {
|
|
String line = charset.decode(ByteBuffer.wrap(b, 0, len)).toString();
|
|
line = line.replace("\0", "").trim();
|
|
queueLog.add(line);
|
|
}
|
|
|
|
@Override
|
|
public void close() throws IOException {
|
|
stopQueueConsumer();
|
|
super.close();
|
|
out.close();
|
|
}
|
|
|
|
private void startQueueConsumer() {
|
|
consumerThreadRunning = true;
|
|
consumerThread = new Thread(() -> {
|
|
while (consumerThreadRunning) {
|
|
if (!queueLog.isEmpty()) {
|
|
final String item = queueLog.poll();
|
|
|
|
if (item != null) {
|
|
try {
|
|
processLine(item);
|
|
} catch (IOException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
} else {
|
|
try {
|
|
// queueLog.wait();
|
|
Thread.sleep(100);
|
|
} catch (InterruptedException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
consumerThread.start();
|
|
}
|
|
|
|
private void processLine(String line) throws IOException {
|
|
if (line.isEmpty()) return;
|
|
|
|
// Error messages handler
|
|
final String errorMessage = extractData(line, errorPattern);
|
|
|
|
if (errorMessage != null) { // Match the number of warnings
|
|
errorNote.encodeTo(out);
|
|
errors.add(errorMessage);
|
|
}
|
|
|
|
// Warning messages handler
|
|
final String warningMessage = extractData(line, warningPattern);
|
|
if (warningMessage != null) { // Match the number of warnings
|
|
warningNote.encodeTo(out);
|
|
warnings.add(warningMessage);
|
|
}
|
|
|
|
|
|
if (verboseLogging) {
|
|
line += "\r\n";
|
|
byte[] b1 = line.getBytes(charset);
|
|
out.write(b1, 0, b1.length);
|
|
} else {
|
|
// Estrarre i dati
|
|
String timestamp = extractData(line, timestampPattern);
|
|
|
|
line = line.replace(workspace, "")
|
|
.replace("\t", " ");
|
|
|
|
if (timestamp != null && !timestamp.isEmpty())
|
|
line = line.replace(timestamp, "").trim();
|
|
|
|
|
|
line += "\r\n";
|
|
byte[] bytesToWrite = line.getBytes();
|
|
out.write(bytesToWrite, 0, bytesToWrite.length);
|
|
}
|
|
}
|
|
|
|
// Metodo per fermare il thread di consumo
|
|
public void stopQueueConsumer() {
|
|
consumerThreadRunning = false;
|
|
synchronized (queueLog) {
|
|
queueLog.notify(); // Se il thread è in attesa, sveglialo
|
|
}
|
|
}
|
|
|
|
|
|
private String extractData(String log, Pattern pattern) {
|
|
Matcher matcher = pattern.matcher(log);
|
|
if (matcher.find()) {
|
|
return matcher.group(0);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private String extractFileNames(String log, Pattern pattern) {
|
|
Matcher matcher = pattern.matcher(log);
|
|
if (matcher.find()) {
|
|
return matcher.group(0); // Nome del file senza percorso
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private String extractStages(String log, Pattern pattern) {
|
|
Matcher matcher = pattern.matcher(log);
|
|
if (matcher.find()) {
|
|
return "[" + matcher.group(0) + "] " + matcher.group(2); // Stage (Stage1, Stage2, ecc.)
|
|
}
|
|
return null;
|
|
}
|
|
} |