/* * ALMA - Atacama Large Millimiter Array * (c) European Southern Observatory, 2002 * Copyright by ESO (in the framework of the ALMA collaboration) * and Cosylab 2002, All rights reserved * * This library 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 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ package alma.acs.logging.tools; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.util.Date; import alma.acs.logging.engine.io.IOHelper; import alma.acs.logging.engine.io.IOPorgressListener; import com.cosylab.logging.engine.FiltersVector; import com.cosylab.logging.engine.ACS.ACSRemoteErrorListener; import com.cosylab.logging.engine.ACS.ACSRemoteLogListener; import com.cosylab.logging.engine.log.ILogEntry; import com.cosylab.logging.engine.log.LogField; /** * An object to extract the logs that matches the given criteria. * It reads the input file and parse each log and writes in the output * all the logs matching the criteria. * It is possible to specify a start and/or end date or pass the name * of a filter to load. The filters are the same used by jlog so * jlog can be used to edit and save such file. * * @author acaproni * */ public class LogFileExtractor implements ACSRemoteLogListener, ACSRemoteErrorListener, IOPorgressListener { // The start and end date of the logs in millisec. // If one of them is -1, the test is assumed passed // (i.e. the date is not checked) private long start=-1; private long end=-1; /** * The name of the file of filter */ private String filterFileName=null; /** * The filters */ private FiltersVector filters = null; /** * The name of the files for reading */ private final String[] inFileNames; /** * The name of the output file */ private String destFileName; /** * The size of the buffer for writing */ private static final int OUTPUT_BUFFER_SIZE=8192; /** * The writer to write the destination files */ private BufferedWriter outF=null; /** * The converter to format the log before saving */ private final LogConverter converter; /** * Constructor * The parameters defines the criteria. They can be null (but not all null of * course). * All the criteria are applied in AND. * If the start/end date are not present, the dates are not checked. * * @param inputFiles The name of the files of logs for input * @param outputFile The name of the file with the selected logs * @param startDate The start date of logs (can be null) * @param endDate The end date of the logs (can be null) * @param filterName The name of a file of filters to apply to select * logs (can be null) * @param converter The convert to save logs in different output formats * @throws <code>Exception</code> In case of error */ public LogFileExtractor( String inputFiles[], String outputFile, Date startDate, Date endDate, String filterName, LogConverter converter) throws Exception { if (startDate==null && endDate==null && filterName==null){ throw new IllegalArgumentException("No criteria for extraction"); } if (outputFile==null) { throw new IllegalArgumentException("The source can't be null"); } if (inputFiles==null || inputFiles.length==0) { throw new IllegalArgumentException("No source files"); } if (converter==null) { throw new IllegalArgumentException("The converter can't be null"); } this.converter=converter; inFileNames=new String[inputFiles.length]; System.arraycopy(inputFiles, 0, inFileNames, 0, inputFiles.length); destFileName=outputFile; // Add the extension to the outputfilename if not // already present String extension; if (converter instanceof XMLConverter) { extension=".xml"; } else { extension=".txt"; } if (!destFileName.toLowerCase().endsWith(extension)) { destFileName=destFileName+extension; } if (startDate!=null) { start=startDate.getTime();} if (endDate!=null) { end=endDate.getTime(); } if (end<=start && end!=-1 && start!=-1) { throw new IllegalArgumentException("Start date greater then end date"); } filterFileName=filterName; if (filterFileName!=null) { File f = new File(filterFileName); if (!f.canRead()) { throw new IllegalArgumentException(filterFileName+" is unreadable"); } filters = new FiltersVector(); filters.loadFilters(f,true,null); System.out.println("Will apply the following filters:\n" + filters.toString()); } } /** * Create the <code>BufferedWriter</code> and the <code>IOHelper</code> * for writing logs. * <P> * This method uses a new <code>IOHelper</code> to open a new file * where the logs are saved into. * It sets up: * <UL> * <LI>the <code>outHelper</code> * <LI>the <code>outF</code> * </UL> */ private void openDestFile() throws Exception { if (destFileName.length()==0) { throw new IllegalArgumentException("Wrong dest file name"); } outF = new BufferedWriter(new FileWriter(destFileName)); } /** * Extract the logs from the source to the destination * applying the selection criteria given in the * constructor */ public void extract() throws Exception { IOHelper inputHelper = new IOHelper(); inputHelper.setFilters(filters); openDestFile(); // Start the loading if (inFileNames==null) { // Read from stdin BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); inputHelper.loadLogs(in, this, null, this, this); } else for (String inFileName: inFileNames) { System.out.println("Processing "+inFileName); inputHelper.loadLogs(inFileName, this, null, this, this); } // Flush and close the output outF.flush(); outF.close(); outF=null; } /** * Check if the date of the log is between the requested start and * end date * * @param log The log to check * @return true if the time stamp of the log is between the start and the * end date (inclusive) */ private boolean checkDate(ILogEntry log) { Long date = (Long)log.getField(LogField.TIMESTAMP); boolean matches = true; matches = date>=start; if (matches && end!=-1) { matches = date<=end; } return matches; } /** * @see alma.acs.logging.engine.io.IOPorgressListener#bytesRead(long) */ @Override public void bytesRead(long bytes) {} /** * @see alma.acs.logging.engine.io.IOPorgressListener#bytesWritten(long) */ @Override public void bytesWritten(long bytes) {} /** * @see alma.acs.logging.engine.io.IOPorgressListener#logsRead(int) */ @Override public void logsRead(int numOfLogs) {} /** * @see alma.acs.logging.engine.io.IOPorgressListener#logsWritten(int) */ @Override public void logsWritten(int numOfLogs) {} /** */ @Override public void errorReceived(String xml) { System.err.println("Error with the following: "+xml); } /** * @see com.cosylab.logging.engine.ACS.ACSRemoteLogListener#logEntryReceived(com.cosylab.logging.engine.log.ILogEntry) */ @Override public void logEntryReceived(ILogEntry logEntry) { boolean matches=true; if (start!=-1 || end!=-1) { matches = checkDate(logEntry); } if (matches && filters!=null) { matches = filters.applyFilters(logEntry); } if (matches) { try { outF.write(converter.convert(logEntry)); } catch (IOException e) { System.err.println("Error writing a log: "+e.getMessage()); e.printStackTrace(System.err); } } } }