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