org.powertac.logtool.LogtoolCore.java Source code

Java tutorial

Introduction

Here is the source code for org.powertac.logtool.LogtoolCore.java

Source

/*
 * Copyright (c) 2012 by the original author
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.powertac.logtool;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import javax.annotation.PostConstruct;

import org.apache.logging.log4j.Logger;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.compressors.CompressorException;
import org.apache.commons.compress.compressors.CompressorStreamFactory;
import org.apache.logging.log4j.LogManager;
import org.powertac.common.msg.SimEnd;
import org.powertac.common.msg.SimStart;
import org.powertac.common.repo.DomainRepo;
import org.powertac.common.spring.SpringApplicationContext;
import org.powertac.logtool.common.DomainObjectReader;
import org.powertac.logtool.common.MissingDomainObject;
import org.powertac.logtool.common.DomainBuilder;
import org.powertac.logtool.common.NewObjectListener;
import org.powertac.logtool.ifc.Analyzer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * Reads a state log file, re-creates and updates objects, calls
 * listeners.
 * @author John Collins
 */
@Service
public class LogtoolCore {
    static private Logger log = LogManager.getLogger(LogtoolCore.class.getName());

    @Autowired
    private DomainObjectReader reader;

    @Autowired
    private DomainBuilder builder;

    private boolean simEnd = false;
    private boolean isInterrupted = false;

    static private CompressorStreamFactory compressFactory = new CompressorStreamFactory();
    static private ArchiveStreamFactory archiveFactory = new ArchiveStreamFactory();

    /**
     * Default constructor
     */
    public LogtoolCore() {
        super();
    }

    @PostConstruct
    public void postConstruct() {
        reader.registerNewObjectListener(new SimStartHandler(), SimStart.class);
        reader.registerNewObjectListener(new SimEndHandler(), SimEnd.class);
        builder.setup();
    }

    /**
     * Sets the per-timeslot pause value, used by Visualizer
     */
    public void setPerTimeslotPause(int msec) {
        reader.setTimeslotPause(msec);
    }

    /**
     * Processes a command line, providing a state-log file from the local
     * filesystem, or a remote URL.
     */
    public String processCmdLine(String[] args) {
        if (args.length < 2) {
            return "Usage: Logtool file analyzer ...";
        }
        String source = args[0];

        Analyzer[] tools = new Analyzer[args.length - 1];
        for (int i = 1; i < args.length; i++) {
            try {
                Class<?> toolClass = Class.forName(args[i]);
                tools[i - 1] = (Analyzer) toolClass.newInstance();
            } catch (ClassNotFoundException e1) {
                return "Cannot find analyzer class " + args[i];
            } catch (Exception ex) {
                return "Exception creating analyzer " + ex.toString();
            }
        }

        return readStateLog(source, tools);
    }

    /**
     * Reads the given state-log source using the DomainObjectReader. Specify the
     * state-log as a local filename or a remote URL, or pass "-" or null to read
     * from standard-input.
     */
    public String readStateLog(String source, Analyzer... tools) {
        if (null == source || "-".equals(source)) {
            log.info("Reading from standard input");
            return readStateLog(System.in, tools);
        }
        try {
            URL inputURL = new URL(source);
            log.info("Reading url " + source);
            return readStateLog(inputURL, tools);
        } catch (MalformedURLException x) {
            // Continue, assuming it is a regular file
        }
        log.info("Reading file " + source);
        File inputFile = new File(source);
        if (!inputFile.canRead()) {
            return "Cannot read file " + source;
        }
        return readStateLog(inputFile, tools);
    }

    /**
     * Reads state-log from given input file using the DomainObjectReader.
     */
    public String readStateLog(File inputFile, Analyzer... tools) {
        try {
            return readStateLog(new FileInputStream(inputFile), tools);
        } catch (FileNotFoundException e) {
            return "Cannot open file " + inputFile.getPath();
        }
    }

    /**
     * Reads state-log from given input url using the DomainObjectReader.
     */
    public String readStateLog(URL inputURL, Analyzer... tools) {
        try {
            return readStateLog(inputURL.openStream(), tools);
        } catch (IOException e) {
            return "Cannot open url " + inputURL.toString();
        }
    }

    /**
     * Reads state-log from given input stream using the DomainObjectReader.
     */
    public String readStateLog(InputStream inputStream, Analyzer... tools) {
        Reader inputReader;
        String line = null;

        log.info("Reading state log from stream for {}", tools[0].getClass().getName());
        simEnd = false;
        isInterrupted = false;

        try {
            // Stack compression logic if appropriate
            try {
                if (!inputStream.markSupported()) {
                    inputStream = new BufferedInputStream(inputStream);
                }
                inputStream = compressFactory.createCompressorInputStream(inputStream);
            } catch (CompressorException x) {
                // Stream not compressed (or unknown compression scheme)
            }

            // Stack archive logic if appropriate
            try {
                if (!inputStream.markSupported()) {
                    inputStream = new BufferedInputStream(inputStream);
                }
                ArchiveInputStream archiveStream = archiveFactory.createArchiveInputStream(inputStream);
                ArchiveEntry entry;
                inputStream = null;
                while ((entry = archiveStream.getNextEntry()) != null) {
                    String name = entry.getName();
                    if (entry.isDirectory() || !name.startsWith("log/") || !name.endsWith(".state")
                            || name.endsWith("init.state")) {
                        continue;
                    }
                    inputStream = archiveStream;
                    break;
                }
                if (inputStream == null) {
                    return "Cannot read archive, no valid state log entry";
                }
            } catch (ArchiveException x) {
                // Stream not archived (or unknown archiving scheme)
            }

            // Recycle repos from previous session
            List<DomainRepo> repos = SpringApplicationContext.listBeansOfType(DomainRepo.class);
            for (DomainRepo repo : repos) {
                repo.recycle();
            }

            // Now go read the state-log
            inputReader = new InputStreamReader(inputStream);
            for (Analyzer tool : tools) {
                log.info("Setting up {}", tool.getClass().getName());
                tool.setup();
            }
            BufferedReader in = new BufferedReader(inputReader);
            int lineNumber = 0;
            while (!simEnd) {
                synchronized (this) {
                    if (isInterrupted) {
                        in.close();
                        break;
                    }
                }
                line = in.readLine();
                if (null == line) {
                    log.info("Last line " + lineNumber);
                    break;
                }
                lineNumber += 1;
                reader.readObject(line);
            }
            builder.report();
            for (Analyzer tool : tools) {
                tool.report();
            }
        } catch (IOException e) {
            return "Error reading from stream";
        } catch (MissingDomainObject e) {
            return "MDO on " + line;
        }
        return null;
    }

    public synchronized void interrupt() {
        isInterrupted = true;
    }

    class SimStartHandler implements NewObjectListener {
        @Override
        public void handleNewObject(Object thing) {
        }
    }

    class SimEndHandler implements NewObjectListener {

        @Override
        public void handleNewObject(Object thing) {
            simEnd = true;
        }

    }
}