/*
 * Copyright (C) 2004-2005  exedio GmbH (www.exedio.com)
 *
 * 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 com.exedio.cope.instrument;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;

import com.exedio.cope.Cope;

public final class Main
{

	private static final String TEMPFILE_SUFFIX=".temp_cope_injection";
	
	public static void main(final String[] args)
	{
		try
		{
			(new Main()).run(new File("."), args, true);
		}
		catch(RuntimeException e)
		{
			e.printStackTrace();
			throw e;
		}
		catch(IllegalParameterException e)
		{
			e.printStackTrace();
			throw new RuntimeException(e);
		}
		catch(InjectorParseException e)
		{
			e.printStackTrace();
			throw new RuntimeException(e);
		}
		catch(IOException e)
		{
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	Main()
	{}
	
	private void printUsage(PrintStream o)
	{
		o.println("usage:");
		o.print("java ");
		o.print(getClass().getName());
		o.println(" tobemodified1.java ...");
	}
	
	final void run(final File dir, final String[] args, final boolean verbose) throws IllegalParameterException, InjectorParseException, IOException
	{
		final ArrayList sourcefiles = new ArrayList();
		
		for(int i=0; i<args.length; i++)
			sourcefiles.add(new File(dir, args[i]));
		
		run(sourcefiles, verbose);
	}
		
	final void run(final ArrayList sourcefiles, final boolean verbose) throws IllegalParameterException, InjectorParseException, IOException
	{
		{
			final Package runtimePackage = Cope.class.getPackage();
			final Package instrumentorPackage = Main.class.getPackage();
			final String runtimeVersion = runtimePackage.getImplementationVersion();
			final String instrumentorVersion = instrumentorPackage.getImplementationVersion();
			if(verbose)
			{
				System.out.println("Instrumentor version: "+instrumentorVersion);
				System.out.println("Runtime version: "+runtimeVersion);
			}
			if(runtimeVersion!=null && instrumentorVersion!=null && !runtimeVersion.equals(instrumentorVersion))
				throw new RuntimeException("version of cope runtime library ("+runtimeVersion+") does dot match version of cope instrumentor: "+instrumentorVersion);
		}
		
		if(sourcefiles.isEmpty())
			throw new IllegalParameterException("nothing to do.");
		
		final JavaRepository repository = new JavaRepository();

		this.verbose = verbose;
		instrumented = 0;
		skipped = 0;
		for(Iterator i=sourcefiles.iterator(); i.hasNext(); )
		{
			final File tobemodifiedfile = (File)i.next();
			final File outputfile=new File(tobemodifiedfile.getAbsolutePath()+TEMPFILE_SUFFIX);
			final File inputfile = tobemodifiedfile;

			if(!inputfile.exists())
				throw new RuntimeException("error: input file " + inputfile.getAbsolutePath() + " does not exist.");
			if(!inputfile.isFile())
				throw new RuntimeException("error: input file " + inputfile.getAbsolutePath() + " is not a regular file.");
				
			if(outputfile.exists())
			{
				if(inputfile.getCanonicalPath().equals(outputfile.getCanonicalPath()))
					throw new RuntimeException("error: input file and output file are the same.");
				if(!outputfile.isFile())
					throw new RuntimeException("error: output file is not a regular file.");
			}
			
			final Injector injector = new Injector(inputfile, new Instrumentor(), repository);
			try
			{
				injector.parseFile();
			}
			finally
			{
				if(injector!=null) injector.close();
			}
			
			final Generator generator = new Generator(injector.javafile, outputfile);
			try
			{
				generator.write();
			}
			finally
			{
				if(generator!=null) generator.close();
			}
			
			if(injector.getCRC()!=generator.getCRC())
			{
				logInstrumented(tobemodifiedfile);
				if(!outputfile.exists())
					throw new RuntimeException("not exists "+outputfile+".");
				if(!tobemodifiedfile.delete())
					throw new RuntimeException("deleting "+tobemodifiedfile+" failed.");
				if(!outputfile.renameTo(tobemodifiedfile))
					throw new RuntimeException("renaming "+outputfile+" to "+tobemodifiedfile+" failed.");
			}
			else
			{
				logSkipped(tobemodifiedfile);
				if(!outputfile.exists())
					throw new RuntimeException("not exists "+outputfile+".");
				if(!outputfile.delete())
					throw new RuntimeException("deleting "+tobemodifiedfile+" failed.");
			}
		}

		if(verbose || instrumented>0)
			System.out.println("Instrumented " + instrumented + ' ' + (instrumented==1 ? "file" : "files") + ", skipped " + skipped + " in " + ((File)sourcefiles.iterator().next()).getParentFile().getAbsolutePath());
	}

	boolean verbose;
	int skipped;
	int instrumented;
	
	private void logSkipped(final File file)
	{
		if(verbose)
			System.out.println("Instrumented " + file);
		
		skipped++;
	}
	
	private void logInstrumented(final File file)
	{
		if(verbose)
			System.out.println("Skipped " + file);
		
		instrumented++;
	}
	
}

@@ -3204,28 +3204,21 @@
 al File 
-tobemodified
+input
 file = (
@@ -3256,17 +3256,19 @@
 tputfile
-=
+ = 
 new File
@@ -3268,28 +3268,21 @@
 ew File(
-tobemodified
+input
 file.get
@@ -3317,52 +3317,8 @@
 IX);
-%0A%09%09%09final File inputfile = tobemodifiedfile;
 %0A%0A%09%09
@@ -4348,28 +4348,21 @@
 umented(
-tobemodified
+input
 file);%0A%09
@@ -4460,28 +4460,21 @@
 %09%09%09%09if(!
-tobemodified
+input
 file.del
@@ -4520,36 +4520,29 @@
 %22deleting %22+
-tobemodified
+input
 file+%22 faile
@@ -4575,28 +4575,21 @@
 enameTo(
-tobemodified
+input
 file))%0A%09
@@ -4649,28 +4649,21 @@
 +%22 to %22+
-tobemodified
+input
 file+%22 f
@@ -4705,28 +4705,21 @@
 Skipped(
-tobemodified
+input
 file);%0A%09
@@ -4882,28 +4882,21 @@
 eting %22+
-tobemodified
+input
 file+%22 f

rename tobemodifiedfile to inputfile