-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #105 from matty-r/84
84
- Loading branch information
Showing
19 changed files
with
1,137 additions
and
251 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
package urChatBasic.backend.utils; | ||
|
||
import java.time.LocalDateTime; | ||
import java.time.ZoneId; | ||
import java.time.format.DateTimeFormatter; | ||
import java.time.temporal.TemporalAccessor; | ||
import java.util.Date; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
public class LogPatternParser | ||
{ | ||
|
||
// Define enum for log patterns | ||
public enum LogPattern | ||
{ | ||
DATE("%d", "(?<DATE>.*UTC?)", Date.class, "UTC "), | ||
SERVER("%marker", "\\s(?<SERVER>[A-Za-z0-9.-]+)-", String.class, "-"), | ||
CHANNEL("%marker", "(?<CHANNEL>#.*?)\\s", String.class, " "), // Named group for channel, excluding the trailing whitespace | ||
USER("%msg", "(?<USER>.*?):", String.class, ": "), | ||
MESSAGE("%msg", "\\s(?<MESSAGE>.*)$", String.class, ""); | ||
|
||
private final String pattern; | ||
private final String regex; | ||
private final String appendString; | ||
private final Class<?> patternClass; | ||
public final static String PATTERN_LAYOUT = "%d{yyy-MM-dd HH:mm:ss.SSS}{UTC}UTC %marker %msg%n"; | ||
public final static String DATE_LAYOUT = "yyyy-MM-dd HH:mm:ss.SSS"; | ||
|
||
LogPattern (String pattern, String regex, Class<?> patternClass, String appendString) | ||
{ | ||
this.pattern = pattern; | ||
this.regex = regex; | ||
this.patternClass = patternClass; | ||
this.appendString = appendString; | ||
} | ||
|
||
public String getPattern () | ||
{ | ||
return pattern; | ||
} | ||
|
||
public Class<?> getPatternClass () | ||
{ | ||
return patternClass; | ||
} | ||
|
||
public String getRegex () | ||
{ | ||
return regex; | ||
} | ||
|
||
public String getMatchGroup () | ||
{ | ||
return this.toString(); | ||
} | ||
|
||
public String getAppendString () | ||
{ | ||
return appendString; | ||
} | ||
} | ||
|
||
public static Date parseDate (String dateString) | ||
{ | ||
dateString = dateString.trim(); | ||
// Step 1: Define the DateTimeFormatter with the pattern | ||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); | ||
TemporalAccessor temporalAccessor = null; | ||
try{ | ||
// Step 2: Parse the string into a TemporalAccessor object using the formatter | ||
temporalAccessor = formatter.parse(dateString.replace("UTC", "")); | ||
} catch (Exception exc) | ||
{ | ||
System.out.println(exc); | ||
} | ||
|
||
// Step 3: Convert the TemporalAccessor to a LocalDateTime object | ||
LocalDateTime localDateTime = LocalDateTime.from(temporalAccessor); | ||
|
||
// Step 4: Convert the LocalDateTime to the local timezone | ||
LocalDateTime localDateTimeInLocalTimeZone = localDateTime | ||
.atZone(ZoneId.of("UTC")) | ||
.withZoneSameInstant(ZoneId.systemDefault()) | ||
.toLocalDateTime(); | ||
|
||
// Step 5: Convert the LocalDateTime to a Date object | ||
Date date = Date.from(localDateTimeInLocalTimeZone.atZone(ZoneId.systemDefault()).toInstant()); | ||
|
||
|
||
return date; | ||
} | ||
|
||
// Method to format Date object to string in UTC | ||
public static String formatDateToString(Date date) { | ||
// Define the DateTimeFormatter with the pattern | ||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); | ||
|
||
// Convert the Date object to LocalDateTime | ||
LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); | ||
|
||
// Convert the LocalDateTime to UTC time zone | ||
LocalDateTime localDateTimeInUtc = localDateTime.atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime(); | ||
|
||
// Format the LocalDateTime to string | ||
return formatter.format(localDateTimeInUtc); | ||
} | ||
|
||
// Parse log line using specified pattern | ||
public static void parseLogLine (String logLine) | ||
{ | ||
Map<String, Object> parsedValues = new HashMap<String, Object>(); | ||
|
||
for (LogPattern pattern : LogPattern.values()) | ||
{ | ||
Pattern regexPattern = Pattern.compile(pattern.getRegex()); | ||
Matcher matcher = regexPattern.matcher(logLine); | ||
if (matcher.find()) | ||
{ | ||
String fullMatch = matcher.group(0); | ||
String match = matcher.group(pattern.getMatchGroup()); | ||
System.out.println(pattern.name() + " group: " + match); | ||
// parsedValues.put(pattern.toString(), match); | ||
switch (pattern.getPatternClass().getSimpleName()) { | ||
case "Date": | ||
parsedValues.put(pattern.toString(), parseDate(match)); | ||
logLine = logLine.replaceFirst(fullMatch, "").trim(); | ||
break; | ||
default: | ||
parsedValues.put(pattern.toString(), match); | ||
if(logLine.length() == fullMatch.length()) | ||
break; | ||
|
||
logLine = logLine.replaceFirst(fullMatch, "").trim(); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
System.out.println("Done"); | ||
} | ||
|
||
public static Map<String, Object> parseLogLineFull (String logLine) { | ||
logLine = logLine.trim(); | ||
Map<String, Object> parsedValues = new HashMap<>(); | ||
|
||
StringBuilder combinedRegexBuilder = new StringBuilder(); | ||
combinedRegexBuilder.append(LogPattern.DATE.getRegex()); | ||
combinedRegexBuilder.append(LogPattern.SERVER.getRegex()); | ||
combinedRegexBuilder.append(LogPattern.CHANNEL.getRegex()); | ||
combinedRegexBuilder.append(LogPattern.USER.getRegex()); | ||
combinedRegexBuilder.append(LogPattern.MESSAGE.getRegex()); | ||
String combinedRegex = combinedRegexBuilder.toString(); | ||
|
||
Pattern regexPattern = Pattern.compile(combinedRegex); | ||
Matcher matcher = regexPattern.matcher(logLine); | ||
while (matcher.find()) { | ||
for (LogPattern pattern : LogPattern.values()) { | ||
if (matcher.group(pattern.toString()) != null) { | ||
String match = matcher.group(pattern.getMatchGroup()); | ||
switch (pattern.getPatternClass().getSimpleName()) { | ||
case "Date": | ||
parsedValues.put(pattern.toString(), parseDate(match)); | ||
break; | ||
default: | ||
parsedValues.put(pattern.toString(), match); | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
return parsedValues; | ||
} | ||
} |
101 changes: 101 additions & 0 deletions
101
src/urChatBasic/backend/utils/ReverseLineInputStream.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package urChatBasic.backend.utils; | ||
|
||
import java.io.File; | ||
import java.io.FileNotFoundException; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.RandomAccessFile; | ||
|
||
/** | ||
* @see https://web.archive.org/web/20220701011119/https://stackoverflow.com/questions/8664705/how-to-read-file-from-end-to-start-in-reverse-order-in-javaa | ||
*/ | ||
public class ReverseLineInputStream extends InputStream { | ||
|
||
RandomAccessFile in; | ||
|
||
long currentLineStart = -1; | ||
long currentLineEnd = -1; | ||
long currentPos = -1; | ||
long lastPosInFile = -1; | ||
int lastChar = -1; | ||
|
||
|
||
public ReverseLineInputStream(File file) throws FileNotFoundException { | ||
in = new RandomAccessFile(file, "r"); | ||
currentLineStart = file.length(); | ||
currentLineEnd = file.length(); | ||
lastPosInFile = file.length() -1; | ||
currentPos = currentLineEnd; | ||
|
||
} | ||
|
||
private void findPrevLine() throws IOException { | ||
if (lastChar == -1) { | ||
in.seek(lastPosInFile); | ||
lastChar = in.readByte(); | ||
} | ||
|
||
currentLineEnd = currentLineStart; | ||
|
||
// There are no more lines, since we are at the beginning of the file and no lines. | ||
if (currentLineEnd == 0) { | ||
currentLineEnd = -1; | ||
currentLineStart = -1; | ||
currentPos = -1; | ||
return; | ||
} | ||
|
||
long filePointer = currentLineStart -1; | ||
|
||
while ( true) { | ||
filePointer--; | ||
|
||
// we are at start of file so this is the first line in the file. | ||
if (filePointer < 0) { | ||
break; | ||
} | ||
|
||
in.seek(filePointer); | ||
int readByte = in.readByte(); | ||
|
||
// We ignore last LF in file. search back to find the previous LF. | ||
if (readByte == 0xA && filePointer != lastPosInFile ) { | ||
break; | ||
} | ||
} | ||
// we want to start at pointer +1 so we are after the LF we found or at 0 the start of the file. | ||
currentLineStart = filePointer + 1; | ||
currentPos = currentLineStart; | ||
} | ||
|
||
public int read() throws IOException { | ||
|
||
if (currentPos < currentLineEnd ) { | ||
in.seek(currentPos++); | ||
int readByte = in.readByte(); | ||
return readByte; | ||
} else if (currentPos > lastPosInFile && currentLineStart < currentLineEnd) { | ||
// last line in file (first returned) | ||
findPrevLine(); | ||
if (lastChar != '\n' && lastChar != '\r') { | ||
// last line is not terminated | ||
return '\n'; | ||
} else { | ||
return read(); | ||
} | ||
} else if (currentPos < 0) { | ||
return -1; | ||
} else { | ||
findPrevLine(); | ||
return read(); | ||
} | ||
} | ||
|
||
@Override | ||
public void close() throws IOException { | ||
if (in != null) { | ||
in.close(); | ||
in = null; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.