001// Generated by delombok at Sun Jun 30 16:31:41 CEST 2019
002package com.credibledoc.substitution.doc.module.substitution;
003
004import com.credibledoc.combiner.date.DateService;
005import com.credibledoc.combiner.log.buffered.LogBufferedReader;
006import com.credibledoc.combiner.log.buffered.LogFileReader;
007import com.credibledoc.combiner.node.file.NodeFile;
008import com.credibledoc.combiner.tactic.Tactic;
009import com.credibledoc.substitution.core.exception.SubstitutionRuntimeException;
010import org.springframework.stereotype.Service;
011import javax.inject.Inject;
012import java.io.File;
013import java.text.SimpleDateFormat;
014import java.util.Date;
015import java.util.regex.Matcher;
016import java.util.regex.Pattern;
017
018/**
019 * Implementation of the {@link Tactic}
020 * for the {@link SubstitutionTactic}.
021 */
022@Service
023public class SubstitutionTactic implements Tactic {
024    /**
025     * RegEx of a date in a {@link SubstitutionTactic} log line,
026     * for example <pre>29.09.2018 22:53:42.494|https-jsse-nio-15443-exec-1...</pre>
027     */
028    private static final String PATTERN_DATE_STRING = "\\d\\d\\.\\d\\d\\.\\d\\d\\d\\d\\s\\d\\d:\\d\\d:\\d\\d\\.\\d\\d\\d";
029    /**
030     * Compiled {@value #PATTERN_DATE_STRING} value
031     */
032    private static final Pattern PATTERN_DATE = Pattern.compile(PATTERN_DATE_STRING);
033    /**
034     * {@link Pattern} of date and time of {@link SubstitutionTactic}, for example
035     * for example <pre>29.09.2018 22:53:42.494|https-jsse-nio-15443-exec-1...</pre>
036     */
037    private static final String DATE_FORMAT_STRING = "dd.MM.yyyy HH:mm:ss.SSS";
038    private static final String ONE_SPACE = " ";
039    private static final int THREAD_NAME_INDEX = 35;
040    private static final String PIPE = "|";
041    private final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_FORMAT_STRING);
042
043    @Override
044    public Date findDate(File file) {
045        try (LogBufferedReader logBufferedReader = new LogBufferedReader(new LogFileReader(file))) {
046            String line = logBufferedReader.readLine();
047            while (line != null) {
048                Date date = parseDateFromLine(line);
049                if (date != null) {
050                    return date;
051                }
052                line = logBufferedReader.readLine();
053            }
054            return null;
055        } catch (Exception e) {
056            throw new SubstitutionRuntimeException("Cannot find date. File: " + file.getAbsolutePath(), e);
057        }
058    }
059
060    @Override
061    public Date findDate(String line, NodeFile nodeFile) {
062        return parseDateFromLine(line);
063    }
064
065    @Override
066    public boolean containsDate(String line) {
067        if (line == null) {
068            return false;
069        }
070        return PATTERN_DATE.matcher(line).find();
071    }
072
073    @Override
074    public String parseDateStingFromLine(String line) {
075        if (line == null) {
076            return null;
077        }
078        return findDateString(line);
079    }
080
081    /**
082     * Parse a {@link Date} from a log line.
083     *
084     * @param line    for example
085     *                <pre>29.09.2018 22:53:42.494|https-jsse-nio-15443-exec-1...</pre>
086     *                for {@link SubstitutionTactic}
087     * @return a parsed {@link Date}, for example 13.04.2018 07:27:41.462
088     * or 'null' if the line is null or the date cannot be found.
089     */
090    private Date parseDateFromLine(String line) {
091        if (line == null) {
092            return null;
093        }
094        try {
095            String clientDateString = findDateString(line);
096            if (clientDateString != null) {
097                return simpleDateFormat.parse(clientDateString);
098            }
099            return null;
100        } catch (Exception e) {
101            throw new SubstitutionRuntimeException("Cannot parse a date from the line: " + line, e);
102        }
103    }
104
105    /**
106     * Parse a {@link Date} from a log line.
107     *
108     * @param line for example
109     * <pre>29.09.2018 22:53:42.494|https-jsse-nio-15443-exec-1...</pre>
110     * for {@link SubstitutionTactic}
111     * @return a parsed {@link Date}, for example 13.04.2018 07:27:41.462 or 'null' if the line is 'null' or the date cannot be found.
112     */
113    private String findDateString(String line) {
114        int maxLength = line.length() > 90 ? 90 : line.length();
115        String dateString = null;
116        Matcher matcher = PATTERN_DATE.matcher(line.substring(0, maxLength));
117        if (matcher.find()) {
118            dateString = matcher.group();
119        }
120        return dateString;
121    }
122
123    /**
124     * Examples:
125     * <pre>05.11.2018 08:37:08.100|https-jsse-nio-15443-exec-10|DEBUG|...</pre>
126     * <pre>19.12.2018 06:17:56.761 http-nio-8080-exec-305 INFO  [1212121]...</pre>
127     */
128    @Override
129    public String findThreadName(String line) {
130        int beginIndex = line.indexOf(PIPE);
131        int endIndex = line.indexOf(PIPE, beginIndex + 1);
132        if (isPipeSeparator(line)) {
133            if (beginIndex != -1 && endIndex != -1) {
134                return line.substring(beginIndex + PIPE.length(), endIndex);
135            }
136        } else {
137            int firstSpaceIndex = line.indexOf(ONE_SPACE);
138            int secondSpaceIndex = line.indexOf(ONE_SPACE, firstSpaceIndex + 1);
139            int thirdSpaceIndex = line.indexOf(ONE_SPACE, secondSpaceIndex + 1);
140            return line.substring(secondSpaceIndex + 1, thirdSpaceIndex);
141        }
142        return null;
143    }
144
145    private boolean isPipeSeparator(String line) {
146        return line.substring(0, THREAD_NAME_INDEX).contains(PIPE);
147    }
148
149    @Override
150    public Date findDate(String line) {
151        return DateService.getInstance().parseDateTimeFromLine(line, simpleDateFormat, PATTERN_DATE, 35);
152    }
153
154    @Override
155    public String getShortName() {
156        return "substitution-doc";
157    }
158
159    @Override
160    public boolean identifyApplication(String line, LogBufferedReader logBufferedReader) {
161        return line.contains("com.credibledoc.substitution.doc.");
162    }
163
164    @Inject
165    @java.lang.SuppressWarnings("all")
166    public SubstitutionTactic() {
167    }
168}