All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.andy2003.core.LogFile Maven / Gradle / Ivy

The newest version!
/**
 * 	This file is part of Kayak.
 *
 *	Kayak is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU Lesser General Public License as published by
 *	the Free Software Foundation, either version 3 of the License, or
 *	(at your option) any later version.
 *
 *	Kayak is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU Lesser General Public License
 *	along with Kayak.  If not, see .
 *
 */
package com.github.andy2003.core;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

/**
 * Represents an already existing log file. On creation the file is parsed and
 * the relevant content is available as properties.
 * @author Jan-Niklas Meier 
 */
public class LogFile {

    private static final Logger logger = Logger.getLogger(LogFile.class.getCanonicalName());

    private Boolean compressed;
    private File file;
    private InputStream inputStream;
    private String description;
    private String platform;
    private HashMap deviceAlias;
    private long startTime;
    private long stopTime;
    private long startPosition;

    public static final Pattern platformPattern = Pattern.compile("[A-Z0-9_]+");
    public static final Pattern descriptionPattern = Pattern.compile("[a-zA-Z0-9\\s]+");
    public static final Pattern descriptionLinePattern = Pattern.compile("DESCRIPTION \"[^\"]+\"");
    public static final Pattern platformLinePattern = Pattern.compile("PLATFORM [A-Z0-9_]+");
    public static final Pattern deviceAliasLinePattern = Pattern.compile("DEVICE_ALIAS [A-Za-z0-9]+ [a-z0-9]{1,16}");

    public long getStartPosition() {
        return startPosition;
    }

    public long getStartTime() {
        return startTime;
    }

    public long getStopTime() {
        return stopTime;
    }


    public long getLength() {
        return stopTime - startTime;
    }

    public long getSize() {
        return file.length();
    }

    public File getFile() {
        return file;
    }

    public String getAlias(String s) {
        return deviceAlias.get(s);
    }

    public Set getBusses() {
        Set keys = deviceAlias.keySet();
        return keys;
    }

    public String getDescription() {
        return description;
    }

    public String getPlatform() {
        return platform;
    }

    public Boolean getCompressed() {
        return compressed;
    }

    public String getFileName() {
        return file.getName();
    }

    public void setPlatform(String platform) throws FileNotFoundException, IOException {
        if(!platformPattern.matcher(platform).matches())
            throw new IllegalArgumentException("Platform must match " + platformPattern.pattern());

        this.platform = platform;
        rewriteHeader();
    }

    public void setDescription(String description) throws FileNotFoundException, IOException {
        if(!descriptionPattern.matcher(description).matches())
            throw new IllegalArgumentException("Description must match " + descriptionPattern.pattern());

        this.description = description;
        rewriteHeader();
    }

    public LogFile(File file) throws FileNotFoundException, IOException {
        this.file = file;
        this.platform = "";
        this.description = "";
        deviceAlias = new HashMap();
        String filename = file.getPath();

        if (filename.endsWith(".log.gz")) {
            compressed = true;
            inputStream = new GZIPInputStream(new FileInputStream(file));
        } else {
            compressed = false;
            inputStream = new FileInputStream(file);
        }

        parseHeader();
        findPositions();
    }

    private void rewriteHeader() throws FileNotFoundException, IOException {
        BufferedWriter wr = null;
        BufferedReader br = null;
        File tempFile = new File(file.getAbsolutePath() + ".tmp");
        if(compressed) {
            GZIPInputStream zipStream = new GZIPInputStream(new FileInputStream(file));
            br = new BufferedReader(new InputStreamReader(zipStream));
            GZIPOutputStream outStream = new GZIPOutputStream(new FileOutputStream(tempFile));
            wr = new BufferedWriter(new OutputStreamWriter(outStream));
        } else {
            br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
            wr = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(tempFile)));
        }

        String line = null;
        boolean descriptionWritten = false;
        boolean platformWritten = false;

        /* update header */
        while ((line = br.readLine()) != null) {
            if (descriptionLinePattern.matcher(line).matches()) {
                wr.write("DESCRIPTION \"");
                wr.write(description);
                wr.write("\"\n");
                descriptionWritten = true;
            } else if(platformLinePattern.matcher(line).matches()) {
                wr.write("PLATFORM ");
                wr.write(platform);
                wr.write("\n");
                platformWritten = true;
            } else if(line.startsWith("(")) {
                if(!descriptionWritten) {
                    wr.write("DESCRIPTION \"");
                    wr.write(description);
                    wr.write("\"\n");
                }

                if(!platformWritten) {
                    wr.write("PLATFORM ");
                    wr.write(platform);
                    wr.write("\n");
                }

                wr.write(line);
                wr.append('\n');
                break;
            /* Write all other lines */
            } else {
                wr.write(line);
                wr.append('\n');
            }
        }

        /* write rest of file without checking */
        char[] buff = new char[4096];
        int len;
        while ((len = br.read(buff, 0, 4096)) > 0) {
            wr.write(buff, 0, len);
        }

        wr.close();
        br.close();

        if (!file.delete()) {
            logger.log(Level.WARNING, "Could not delete old file");
            return;
        }

        if (!tempFile.renameTo(file)) {
            logger.log(Level.WARNING, "Could not rename new file to old filename");
        }
    }

    private void parseHeader() {
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        long startTime = 0;
        try {
            while (true) {
                String line = reader.readLine();

                if(line == null)
                    break;

                if(descriptionLinePattern.matcher(line).matches()) {
                    int start = line.indexOf('\"') + 1;
                    int stop = line.lastIndexOf("\"");
                    description = line.substring(start, stop);
                } else if(platformLinePattern.matcher(line).matches()) {
                    int start = line.indexOf(' ') + 1;
                    platform = line.substring(start);
                } else if (deviceAliasLinePattern.matcher(line).matches()) {
                    int start = line.indexOf(' ') + 1;
                    int stop = line.lastIndexOf(' ');
                    String alias = line.substring(start, stop);
                    String bus = line.substring(stop + 1);
                    deviceAlias.put(bus, alias);
                /*
                 * All lines that are not recognized and not pure whitespace cause
                 * the header parsing to abort.
                 */
                } else if (line.startsWith("(")) {
                    if (description.equals("")) {
                        description = file.getName();
                    }
                    if (platform.equals("")) {
                        platform = "No platform";
                    }

                    Frame f = Frame.fromLogFileNotation(line).getFrame();
                    startTime = f.getTimestamp();
                    break;
                }
            }

        } catch (IOException ex) {
            logger.log(Level.WARNING, "IOException while loading log file.", ex);
        } finally {
            try {
                reader.close();
            } catch (Exception ex) {
                logger.log(Level.WARNING, "Could not close reader.", ex);
            }
        }
    }

    private void findPositions() {
        RandomAccessFile newFile = null;
        try {
            newFile = new RandomAccessFile(file, "r");

            while(true) {
                long posBefore = newFile.getFilePointer();
                String line = newFile.readLine();
                if(line.startsWith("(")) {
                    Frame f = Frame.fromLogFileNotation(line).getFrame();
                    startTime = f.getTimestamp();
                    startPosition = posBefore;
                    break;
                }
            }

            for(long checkPos = newFile.length() - 10;checkPos>0;checkPos--) {
                newFile.seek(checkPos);

                String line = newFile.readLine();

                if(line != null) {
                    Frame.FrameBusNamePair pair = Frame.fromLogFileNotation(line);

                    if(pair != null) {
                        newFile.seek(checkPos);
                        stopTime = pair.getFrame().getTimestamp();
                        break;
                    }
                }
            }
        } catch(IOException ex) {
            logger.log(Level.INFO, "Exception while finding positions.", ex);
        } finally {
            try {
                newFile.close();
            } catch (Exception ex) {
                Logger.getLogger(SeekableLogFileReplay.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final LogFile other = (LogFile) obj;
        if(other.getFileName().equals(getFileName()))
            return true;

        return false;
    }

    @Override
    public int hashCode() {
        return getFileName().hashCode();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy