/**
* File: ToAssertions.java
* Content: Separate program to convert the Debug.assert lines into JDK1.4 assertions
* Author: LuisM Pena
* Date: 6th February 2001
* Version: 0.60.00
* Last change:
* Comments:
* Lines with preprocess directives are translated into ;//@Prep->
* Are considered preprocess directives those starting with Debug. or Trace.
* It also removes import sensei.util.Debug
* This method is obviously not generic, but works perfectly in sensei
*
*
**/
package preprocessors;
import sensei.util.Parameters;
import sensei.util.ParameterException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import java.util.Vector;
/**
* Separate program to add/remove debug directives
**/
public class ToAssertions implements FileFilter
{
public ToAssertions(boolean recursive, boolean quiet)
{
this.recursive = recursive;
this.quiet=quiet;
processed = new HashMap();
}
//*************************************************************************************//
//**************************** PREPROCESS *********************************************//
//*************************************************************************************//
/**
* Handles the arguments as a file or directory and add/removes the debug directives
* Returns true if the processing is all right
**/
public boolean preprocess(File arg)
{
boolean ret;
if (arg.isDirectory())
ret=preprocessDirectory(arg);
else if (arg.isFile())
ret=preprocessFile(arg);
else
ret=error(arg, "is not a valid directory or file");
return ret;
}
//*************************************************************************************//
//**************************** PREPROCESS DIRECTORY ***********************************//
//*************************************************************************************//
/**
* Handles the arguments as a directory and add/removes the debug directives on every
* java file.
* Returns true if the processing is all right
**/
public boolean preprocessDirectory(File directory)
{
boolean ret=true;
File files[]=directory.listFiles(this);
for (int i=0; ret && i<files.length ; i++)
ret=preprocess(files[i]);
return ret;
}
//*************************************************************************************//
//**************************** PREPROCESS FILE ****************************************//
//*************************************************************************************//
/**
* Handles the arguments as a file and add/removes the debug directives
* Returns true if the processing is all right
**/
public boolean preprocessFile(File arg)
{
boolean ret=true;
if (accept(arg))
{
//rename it
File renamed=new File(arg.getAbsoluteFile()+SecExtension);
if (!arg.renameTo(renamed))
ret=error(arg,"can not be renamed into " + renamed.toString());
else
{
processed.put(renamed, arg);
ret=preprocessFile(renamed, arg);
}
}
return ret;
}
//*************************************************************************************//
//**************************** PREPROCESS FILE ****************************************//
//*************************************************************************************//
/**
* Preprocess the file specified into the target given
**/
public boolean preprocessFile(File source, File target)
{
BufferedReader input = null;
PrintWriter output = null;
boolean ret=true;
try
{
if (!quiet)
System.out.print(target.getAbsoluteFile());
input = new BufferedReader(new FileReader(source));
output= new PrintWriter(new FileOutputStream(target));
int changes=0;
String line = input.readLine();
while(line!=null)
{
if (isImportDebugDirective(line))
{
changes++;
}
else
{
int index=isAssertDirective(line);
if (index==-1)
output.println(line);
else
{
++changes;
output.println(translateAssertDirective(line, index));
}
}
line=input.readLine();
}
if (!quiet)
if (changes>0)
System.out.println(" : " + changes + " lines changed");
else
System.out.println();
}
catch(IOException ex)
{
ret=error(target,ex.getMessage());
}
finally
{
if (input!=null) try{input.close();}catch(IOException ex){}
if (output!=null) output.close();
}
return ret;
}
//*************************************************************************************//
//**************************** IS ASSERT DIRECTIVE ************************************//
//*************************************************************************************//
/**
* Returns different of -1 if it's an assert directive. Otherwise, returns the
* position where it starts
**/
public int isAssertDirective(String line)
{
int index=-1;
String trimed = line.trim();
if (trimed.startsWith("Debug.assert"))
index=line.indexOf("D");
return index;
}
//*************************************************************************************//
//**************************** IS IMPORT DEBUG DIRECTIVE ******************************//
//*************************************************************************************//
/**
* Returns true if the line is an import sensei.util.Debug directive
**/
public boolean isImportDebugDirective(String line)
{
return (line.trim().startsWith("import") && (line.indexOf("sensei.util.Debug")!=-1));
}
//*************************************************************************************//
//**************************** TRANSLATE ASSERT DIRECTIVE *****************************//
//*************************************************************************************//
/**
* Translates a Debug.assert directive into a JDK 1.4 assertion from a line.
* It must be completely included on the same line!
**/
public String translateAssertDirective(String line, int where)
{
int openPar = line.indexOf("(",where);
if (openPar==-1) errorOnLine(line);
String firstParam =getFirstParam(line, openPar+1);
if (firstParam==null) errorOnLine(line);
return line.substring(0,where)+"assert " + firstParam + ";";
}
private void errorOnLine(String line)
{
System.out.println(line + " is not a valid DEBUG assertion");
System.exit(0);
}
private String getFirstParam(String read, int start){
int pos=start, len=read.length();
int openPar=0;
while(pos<len) {
char c=read.charAt(pos);
if (c=='\\') {
return null; //error!
}
else if (c=='\'') {
pos=passCharacter(read, pos, '\'', len);
if (pos==-1) {
return null;
}
}
else if (c=='\"') {
pos=passCharacter(read, pos, '\"', len);
if (pos==-1) {
return null;
}
}
else if (c=='(') {
openPar++;
}
else if (c==')') {
if (--openPar<0)
return null;
}
else if (c==',' && openPar==0) {
return read.substring(start,pos);
}
else if ((c=='/') && ((pos+1)<len)){
c=read.charAt(pos+1);
if (c=='/') {
return null; //comment??
}
else if (c=='*') {
if ((pos=passComment(read, pos+2, len))==-1) {
return null;
}
}
}
++pos;
}
return null;
}
private int passCharacter(String read, int pos, char pass, int len){
while(++pos<len) {
char c=read.charAt(pos);
if (c=='\\') {
++pos; //do not read next character
}
else if (c==pass) {
return pos;
}
}
return -1;
}
private int passComment(String read, int pos, int len){
while(pos<len) {
char c=read.charAt(pos++);
if (c=='*' && pos<len && read.charAt(pos)=='/') {
return pos;
}
}
return -1;
}
//*************************************************************************************//
//**************************** ACCEPT *************************************************//
//*************************************************************************************//
/**
* FileFilter method: only accept java files
**/
public boolean accept(File file)
{
return (recursive && file.isDirectory()) || (file.isFile() && file.getName().toLowerCase().endsWith(".java"));
}
//*************************************************************************************//
//**************************** ERROR **************************************************//
//*************************************************************************************//
/**
* Displays an error on the error stream. returns false
**/
boolean error(File file, String errorMessage)
{
System.out.println("\nError on " + file.toString() + " : " + errorMessage);
recoverBackups();
return false;
}
//*************************************************************************************//
//**************************** RECOVER BACKUPS ****************************************//
//*************************************************************************************//
/**
* Recover the backups
**/
void recoverBackups()
{
Iterator entries=processed.entrySet().iterator();
while(entries.hasNext())
{
Map.Entry entry = (Map.Entry) (entries.next());
File backup=(File)(entry.getKey());
File original=(File)(entry.getValue());
original.delete();
if (!backup.renameTo(original))
System.out.println("I cannot rename back " + backup.toString() + " into " + original.toString());
}
processed.clear();
}
//*************************************************************************************//
//**************************** REMOVE BACKUPS *****************************************//
//*************************************************************************************//
/**
* Removes the backups
**/
public void removeBackups()
{
Iterator entries=processed.keySet().iterator();
while(entries.hasNext())
{
File backup = (File) (entries.next());
if (!backup.delete())
System.out.println("I cannot delete the backup " + backup.toString());
}
}
//*************************************************************************************//
//**************************** MAIN ***************************************************//
//*************************************************************************************//
/**
* Main function, just checks the arguments and passes it to the ToAssertions class
**/
public static void main(String args[])
{
try
{
Vector validParams=new Vector();
validParams.add(RecursiveParameter);
validParams.add(NoBackupParameter);
validParams.add(QuietParameter);
Parameters param=new Parameters(args, validParams, new Vector(), 1, Integer.MAX_VALUE);
ToAssertions prep = new ToAssertions(
param.hasParameter(RecursiveParameter),
param.hasParameter(QuietParameter)
);
boolean ok=true;
for (int i=0; ok && i < param.getArgumentsLength() ; i++)
ok = prep.preprocess(new File(param.getArgument(i)));
if (ok && param.hasParameter(NoBackupParameter))
prep.removeBackups();
}
catch(ParameterException ex)
{
System.out.println(ex.getMessage());
System.out.println("Use: [-recursive] [-nobackup] [-quiet] file/directory [files/directories]");
}
}
boolean recursive, nobackup, quiet;
HashMap processed;
static final String RecursiveParameter="recursive";
static final String NoBackupParameter="nobackup";
static final String QuietParameter="quiet";
static final String SecExtension=".noprep";
}