/*
* 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.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Pattern;
import alma.acs.util.CmdLineArgs;
import alma.acs.util.CmdLineOption;
import alma.acs.util.CmdLineRegisteredOption;
/**
* A coommand line tool to perform some helpful operation
* with the files of logs
*
* @author acaproni
*
*/
public class LogAssistant {
/**
* The format of the date is the same as the ILogEntry without msecs
*/
public static final String TIME_FORMAT = "yyyy'-'MM'-'dd'T'HH':'mm':'ss";
/**
* The command to execute
*/
private char command; // -x, -p, -h
/**
* The start and end date for extraction
*/
private Date startDate=null, endDate=null;
/**
* The name of the filter file for extraction
*/
private String filterFileName=null;
/**
* The number of logs per file for splitting
*/
private Integer num=null;
/**
* The number of minutes per file while splitting
*/
private Integer minutes=null;
/**
* The name of the source file
*/
private String[] sourceFileNames=null;
/**
* The name of the file generated by the process
* <P>
* While splitting the process generates more file appending a
* sequencial number to this string
*/
private String destFileName=null;
/**
* The converter to save the logs in the preferred format.
*/
private LogConverter converter;
/**
* The index and order of the cols to write if the output is not XML
*/
private String cols=null;
/**
* Constructor
*
* @param args The command line params
*/
public LogAssistant(String[] args) {
// Parse the command line
parseCommandLine(args);
}
public void work() throws Exception {
if (checkState()) {
if (command=='x') {
extractLogs();
}
else if (command=='p') {
splitFile();
}
}
}
/**
* Parse the command line and fill the internal variables
* Throws an IllegalStateException if an error arises while parsing
* like for example invalid parameters.
*
* @param params The parameters in the command line
* @throws IllegalStateException If the parameters in the command line are invalid
*/
private void parseCommandLine(String[] params) throws IllegalStateException {
CmdLineArgs cmdLineArgs = new CmdLineArgs();
// help / usage is a special case
CmdLineRegisteredOption helpCmd = new CmdLineRegisteredOption("-h","-help",0);
cmdLineArgs.registerOption(helpCmd);
if (params.length == 1) {
cmdLineArgs.parseArgs(params);
if (cmdLineArgs.isSpecified(helpCmd)) {
command='h';
return;
}
}
if (params.length<5) {
// The param must be at least 5:
// -command (-split)
// at least one parameter for the command and its value (-time val)
// source
// destination
throw new IllegalStateException("Wrong number of params");
}
CmdLineRegisteredOption extractCmd = new CmdLineRegisteredOption("-x","-extract",0);
cmdLineArgs.registerOption(extractCmd);
CmdLineRegisteredOption splitCmd = new CmdLineRegisteredOption("-p","-split",0);
cmdLineArgs.registerOption(splitCmd);
CmdLineRegisteredOption csvOtuputFormat = new CmdLineRegisteredOption("-csv",0);
cmdLineArgs.registerOption(csvOtuputFormat);
CmdLineRegisteredOption txtOtuputFormat = new CmdLineRegisteredOption("-txt",0);
cmdLineArgs.registerOption(txtOtuputFormat);
CmdLineRegisteredOption xmlOtuputFormat = new CmdLineRegisteredOption("-xml",0);
cmdLineArgs.registerOption(xmlOtuputFormat);
CmdLineRegisteredOption twikiOtuputFormat = new CmdLineRegisteredOption("-twiki",0);
cmdLineArgs.registerOption(twikiOtuputFormat);
CmdLineRegisteredOption startTime = new CmdLineRegisteredOption("-s","-start",1);
cmdLineArgs.registerOption(startTime);
CmdLineRegisteredOption endTime = new CmdLineRegisteredOption("-e","-end",1);
cmdLineArgs.registerOption(endTime);
CmdLineRegisteredOption filterName = new CmdLineRegisteredOption("-f","-filter",1);
cmdLineArgs.registerOption(filterName);
CmdLineRegisteredOption time = new CmdLineRegisteredOption("-t","-time",1);
cmdLineArgs.registerOption(time);
CmdLineRegisteredOption number = new CmdLineRegisteredOption("-n","-num",1);
cmdLineArgs.registerOption(number);
CmdLineRegisteredOption columns = new CmdLineRegisteredOption("-l","-col",0);
cmdLineArgs.registerOption(columns);
CmdLineRegisteredOption dstFileOption = new CmdLineRegisteredOption("-dest",1);
cmdLineArgs.registerOption(dstFileOption);
CmdLineRegisteredOption sourceFilesOption = new CmdLineRegisteredOption("-src",1);
cmdLineArgs.registerOption(sourceFilesOption);
cmdLineArgs.parseArgs(params);
// Command==Extract
if (cmdLineArgs.isSpecified(extractCmd)) {
command='x';
}
// Command==split
if (cmdLineArgs.isSpecified(splitCmd)) {
command='p';
}
// Start date
if (cmdLineArgs.isSpecified(startTime)) {
String[] val = cmdLineArgs.getValues(startTime);
if (val==null || val.length<1) {
throw new IllegalStateException("Start date missing/wrong "+TIME_FORMAT);
}
try {
startDate=getDate(val[0]);
} catch (ParseException e) {
throw new IllegalStateException("Wrong date format "+TIME_FORMAT);
}
}
// End date
if (cmdLineArgs.isSpecified(endTime)) {
String[] val = cmdLineArgs.getValues(endTime);
if (val==null || val.length<1) {
throw new IllegalStateException("End date missing/wrong "+TIME_FORMAT);
}
try {
endDate=getDate(val[0]);
} catch (ParseException e) {
throw new IllegalStateException("Wrong date format "+TIME_FORMAT);
}
}
// Filter name
if (cmdLineArgs.isSpecified(filterName)) {
String[] val = cmdLineArgs.getValues(filterName);
if (val==null || val.length<1) {
throw new IllegalStateException("Wrong or missing filter name");
}
filterFileName=val[0];
}
// Time
if (cmdLineArgs.isSpecified(time)) {
String[] val = cmdLineArgs.getValues(time);
if (val==null || val.length<1) {
throw new IllegalStateException("Wrong or missing time (minutes)");
}
try {
minutes=Integer.parseInt(val[0]);
} catch (NumberFormatException e) {
throw new IllegalStateException("Wrong format for the time (minutes)");
}
}
// Number
if (cmdLineArgs.isSpecified(number)) {
String[] val = cmdLineArgs.getValues(number);
if (val==null || val.length<1) {
throw new IllegalStateException("Wrong or missing time (minutes)");
}
try {
num=Integer.parseInt(val[0]);
} catch (NumberFormatException e) {
throw new IllegalStateException("Wrong format for the number of logs");
}
}
// Col
if (cmdLineArgs.isSpecified(columns)) {
String[] val = cmdLineArgs.getValues(columns);
if (val==null || val.length<1) {
throw new IllegalStateException("Wrong or missing time (minutes)");
}
cols=val[0];
}
// Output format
int count=0; // How many output options?
if (cmdLineArgs.isSpecified(csvOtuputFormat)) {
System.out.println("Set output format to CSV");
converter=new CSVConverter(cols);
count++;
}
if (cmdLineArgs.isSpecified(xmlOtuputFormat)) {
System.out.println("Set output format to XML");
converter=new XMLConverter();
count++;
}
if (cmdLineArgs.isSpecified(txtOtuputFormat)) {
System.out.println("Set output format to plain ASCII text");
converter=new TextConverter(cols);
count++;
}
if (cmdLineArgs.isSpecified(twikiOtuputFormat)) {
System.out.println("Set output format to Twiki table");
converter=new TwikiTableConverter(cols);
count++;
}
if (count==0) {
// No converter ==> Use XML by default
converter=new XMLConverter();
System.out.println("No output format specified: using default XML.");
} else if (count>1) {
// Too many output formats
throw new IllegalStateException("Too many output format specified.");
}
// SOURCES
if (cmdLineArgs.isSpecified(sourceFilesOption)) {
sourceFileNames = cmdLineArgs.getValues(sourceFilesOption);
if (sourceFileNames==null || sourceFileNames.length<1) {
throw new IllegalStateException("Wrong or missing source file names");
}
} else {
// This is not an error: if the param is missing, the
// the tool read logs from the command line
}
// DESTINATION
if (cmdLineArgs.isSpecified(dstFileOption)) {
String[] val = cmdLineArgs.getValues(dstFileOption);
if (val==null || val.length<1) {
throw new IllegalStateException("Wrong or missing time (minutes)");
}
destFileName=val[0];
} else {
throw new IllegalStateException("No destination file in command line.");
}
}
/**
* Check the state of the variables.
* This method checks if the internal variables are set in the right way
* It is usually executed before running a command
*
* @return If the state is correct
*/
private boolean checkState() {
if (command!='x' && command!='p' && command!='h') {
System.out.println("Wrong command "+command);
return false;
}
if (command=='x') {
if (endDate==null && startDate==null && filterFileName==null) {
System.out.println("Selected extraction withouth criteria");
System.out.println("Please, set start date and/or end date and/or a filter file name");
return false;
}
if (filterFileName!=null) {
if (filterFileName.length()==0) {
System.out.println("Invalid empty name for the filter");
return false;
}
File filterFile = new File(filterFileName);
if (!filterFile.exists()) {
System.err.println(filterFileName+" does not exist!");
return false;
}
if (!filterFile.canRead()) {
System.out.println(filterFileName+" is unreadable");
return false;
}
// todo: print about using the filter
}
if (minutes!=null || num!=null) {
System.out.println("Warning: minutes and number of logs are ignored while eXtracting");
}
} else if (command=='p') {
if (num==null && minutes==null) {
System.out.println("Splitting selected without criteria");
System.out.println("Please, set the number of log or the time");
return false;
}
if (num!=null && minutes!=null) {
System.out.println("Set only one between number of logs and time to sPlit");
return false;
}
if (startDate!=null || endDate!=null || filterFileName!=null) {
System.out.println("Warning: start date, end date and the filter are ignored while sPlitting");
}
}
// Check if the input files exist and are readable
if (sourceFileNames!=null) {
for (String fileName: sourceFileNames) {
if (fileName==null || fileName.isEmpty()) {
System.out.println("Invalid source file name: "+fileName);
return false;
}
File inF = new File(fileName);
if (!inF.exists()) {
System.err.println(fileName+" does not exist!");
return false;
}
if (!inF.canRead()) {
System.out.println(fileName+" is unreadable");
return false;
}
}
}
return true;
}
/**
* Parse the given string into a Date
*
* @param date The string representing the date
* @return A Date obtained parsing the string
* @throws ParseException If an error happen getting the date from the string
*/
private Date getDate(String date) throws ParseException {
SimpleDateFormat df = new SimpleDateFormat(TIME_FORMAT);
return df.parse(date);
}
/**
* Extract the logs from the source to the destination file
*
*/
private void extractLogs() throws Exception {
LogFileExtractor extractor =
new LogFileExtractor(
sourceFileNames,
destFileName,
startDate,
endDate,
filterFileName,
converter);
extractor.extract();
}
/**
* Split the input log file in several files
*
*/
private void splitFile() throws Exception {
LogFileSplitter fileSplitter = new LogFileSplitter(
sourceFileNames,
destFileName,
num,
minutes,
converter);
fileSplitter.split();
}
/**
* Print a usage message on screen
*
* @param prgName The program name
*/
private static void usage(String prgName) {
System.out.println("USAGE: "+prgName+" command command_params [options] -dest <FileName> [-src <FileName> <FileName> ....]");
System.out.println("command:");
System.out.println("\t-extract|-x: extract logs depending on the command_params criteria");
System.out.println("\tcommand_params for extraction (applied as AND):");
System.out.println("\t\t-start|-s <start_date>: selects all the logs generated after the given date");
System.out.println("\t\t-end|-e <end_date>: selects all the logs generated before the given date");
System.out.println("\t\t-filter|-f <filter.xml>: selects all the logs that matches the filters specified in filter.xml");
System.out.println("\t-split|-p: split the source file depending on the command params criteria");
System.out.println("\tcommand_params for splitting:");
System.out.println("\t\t-time|-t <min>: split by time in minutes");
System.out.println("\t\t-num|-n <num>: split by number of logs");
System.out.println("\t-help|-h: print this help\n");
System.out.println("options:");
System.out.println("\t-xml: write the output as XML (default)");
System.out.println("\t-csv: write the output as CSV");
System.out.println("\t-txt: write the output as plain ASCII text");
System.out.println("\t-twiki: write the output as Twiki table");
System.out.println("\t-col|-l columns: select the columns to write in the csv (not supported by XML)");
System.out.println("-dest <filename>: the name of the destionation file.");
System.out.println("-src <filename>...: the name of the source files.");
System.out.println(" Can be omitted if log files are provided on stdin.");
System.out.println("\nSee ACS manual for further details.\n");
}
/**
* @param args
*/
public static void main(String[] args) {
LogAssistant assistant = null;
try {
assistant = new LogAssistant(args);
} catch (IllegalStateException ex) {
System.err.println("Error in the parameters: " + ex.getMessage());
usage("acsLogAssistant");
return;
}
if (assistant.command=='h') {
usage("acsLogAssistant");
return;
}
try {
assistant.work();
} catch (Throwable t) {
System.err.println("Exception working on logs: "+t.getMessage());
t.printStackTrace(System.err);
}
}
}