﻿/*
 * Created on Dec 9, 2003
 *
 * Allows recursive directories of .as and .flas to be added 
 * to a Flash MX 2004 Professional Project Panel.
 * 
 * Copyright © 2003, Aral Balkan. All Rights Reserved.
 * Copyright © 2003, Ariaware Limited
 *
 * Flash & Flex training, consulting & development: http://www.ariaware.com
 * Support, docs & updates from http://www.FlashAnt.org
 *  
 */

import java.io.*;
import java.util.Enumeration;
import java.util.Vector;

public class flpmaker
{

	private OutputStreamWriter out = null;
	
	public static void main(String[] args)
	{
		flpmaker flpMaker = new flpmaker();

		String projectName = null;
		String directoryName = null;
		File projectRoot = null;
		
		if ( args.length == 2 )
		{	
			// both projectName and directoryName passed
			projectName = args[0]; 
			directoryName = args[1];
			
			projectRoot = new File( directoryName );  
		}
		else if ( args.length == 1 )
		{
			// only projectName passed, default to current directory
			projectName = args[0];
			projectRoot = new File ( "." );
		}
		else if ( args.length == 0 )
		{
			// default to current directory as project root
			projectRoot = new File( "." );	
			
			try
			{
				// default to name of directory for project name
				projectName = projectRoot.getCanonicalFile().getName();
			}
			catch (IOException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
		else 
		{
			// incorrect syntax
			System.out.println("FLPMaker (Flash Project Maker) BETA");
			System.out.println("Copyright © 2003, Aral Balkan. All Rights Reserved");
			System.out.println("Copyright © 2003, Bits And Pixels. http://www.BitsAndPixels.co.uk");
			System.out.println("—————————————————————————————————————————————————————————————————————");
			System.out.println("Recursively adds .AS and .FLA files in your project directory to");
			System.out.println("a new Flash MX 2004 Project file (FLP) while maintaining your");
			System.out.println("folder hierarchy.\n");
			System.out.println("Syntax: java flpmaker [nameOfProject] [rootDirectoryOfProject]");  
			System.out.println("—————————————————————————————————————————————————————————————————————");
			System.out.println("Released under the MIT license. Please see license.txt.\n");
			System.out.println("Support, docs and updates: http://www.flashant.org\n");
			System.out.println("Bug reports, comments, suggestions: Email: beta@bitsandpixels.co.uk");
						
			System.exit(0);
		}

		System.out.println ("Project Root Directory: "+ projectName);

		// start FLP
		flpMaker.startFLP( projectName );
		// read directories (without creating a root folder)			
		flpMaker.readDirectories( projectRoot, false );
		// end FLP
		flpMaker.endFLP();
	
	}
	
	/**
	 * Recursively read directories
	 *
	 */
	private void readDirectories ( File dir )
	{
		// folders are created by default 
		readDirectories ( dir, true );
	}	

	/**
	 * Recursively read directories
	 *
	 * Limitation: Currently does not check if a directory is a symbolic link. 
	 * Directories that are symbolic links that point to other directories within
	 * the same root will cause an infinite loop. 
	 * 
	 * TODO: Implement a hashtable and check for previously visited directories.
	 *       Procedure outlined here: http://www.jguru.com/faq/view.jsp?EID=235861
     */
	private void readDirectories( File dir, boolean createFolder )
	{
		File[] files = null;		// array of files 
		File file = null;			// generic file
		int fileCount = 0; 			// counter for number of files (not directories) in the current directory
		int directoryCount = 0;		// counter for number of directories (not files) in the current directory 
		boolean folderStarted = false; 	// has the directory (folder) been started?
		boolean folderEnded = false;		// has the directory (folder) been ended?
		int i;						// generic counter
		
		// status msg
		System.out.println("Searching: "+dir.getAbsolutePath());
		
		// get list of files in the directory
		files = dir.listFiles();
		
		// list of found files
		Vector foundFiles = new Vector();

		
		// search though all files for sub-directories
		for ( i = 0; i < files.length; i++)
		{
			file = files[i];
			
			if ( file.isDirectory() )
			{
				// do not search CVS directories
				if ( ! file.getAbsolutePath().endsWith ("CVS"))
				{
					directoryCount++;
					
					// Start the current directory if it hasn't already been 
					// so as to keep the directory structure of 
					// nested directories. 
					if ( (! folderStarted) && createFolder )
					{	
						String folderName = dir.getName();
						System.out.println("Creating folder: " + folderName);
						addFolderToFLP ( dir );
						
						folderStarted = true;
					}
					
					// recurse
					readDirectories( file );
				}
			}
		}
			
		// search through all files for matching .as and .fla files
		for ( i = 0; i < files.length; i++)
		{
			file = files[i];
								
			if ( file.isFile() )
			{
				
				fileCount++;
				
				// supported types are .as and .fla
				String fileName = file.getName();	
				
				if ( fileName.endsWith(".as") || fileName.endsWith(".fla") )
				{
					System.out.println ("  Found: "+fileName);
					foundFiles.add ( file );
				}
			}
		}
				
		// if files were found, add the current folder, along with
		// the found files to the FLP
		if ( foundFiles.size() > 0 )
		{
			// write out directory if not already written
			if ( (! folderStarted) && createFolder )
			{	
				String folderName = dir.getName();
				System.out.println("Creating folder: " + folderName);
				addFolderToFLP ( dir );
				
				folderStarted = true;
			}
			
			System.out.println ("Adding " + foundFiles.size() + " files...");
			
			Enumeration filesInDirEnum = foundFiles.elements(); 
			
			// add files to folder
			while ( filesInDirEnum.hasMoreElements() )
			{
				File fileToAdd = (File) filesInDirEnum.nextElement();
				System.out.println("Adding file: "+ fileToAdd.getName());
				addFileToFLP ( fileToAdd );
			}
			
			if ( (! folderEnded) && createFolder )
			{	
				// close the folder
				endFolderInFLP();
				
				folderEnded = true;
			}
		}
		
		// check if directory (folder) was ended,
		// if not, end it now 
		if ( !folderEnded && createFolder && folderStarted) //mace
		{	
			// close the folder
			endFolderInFLP();
			
			folderEnded = true;
		}
	
	}
	
	/**
	 * Start the XML file for a new FLP
	 * @param FLPname
	 */
	private void startFLP ( String FLPName )
	{
		OutputStream fout = null;
		String FLPFileName = null;
		
		// add extension if it is lacking
		if ( ! FLPName.endsWith(".flp") )
		{
			 FLPFileName = FLPName + ".flp";
		}
		else
		{
			FLPFileName = FLPName;
		}
		
		// delete file if it already exists
		File flp = new File(FLPFileName);
		if ( flp.exists() )
		{
			System.out.println("Old project file, "+FLPFileName + " exists, deleting...");
			boolean deleteSuccess = flp.delete();
			if ( ! deleteSuccess )
			{
				// don't know when this would happen since this little monster  
				// apparently ignores the read-only attribute on files in Windows
				System.out.println("Could not delete "+FLPFileName+", please check permissions and try running FLPMaker again.");
			}
		}
		
		
		// create stream
		try
		{
			fout = new FileOutputStream(FLPFileName);
		}
		catch (FileNotFoundException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		// buffer stream
		OutputStream bout= new BufferedOutputStream(fout);
		
		// create writer
		try
		{
			out = new OutputStreamWriter(bout, "8859_1");
		}
		catch (UnsupportedEncodingException e1)
		{
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		try
		{
			// start the FLP
			out.write ( "<flash_project name=\""+FLPName+"\" version=\"1\">\n");
		}
		catch (IOException e2)
		{
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
		
	}

	/**
	 * Adds a folder to the FLP XML file.
	 * @param folder
	 */
	private void addFolderToFLP ( File folder )
	{
		try
		{
			out.write("<project_folder name=\""+folder.getName()+"\" expanded=\"true\">\n");
		}
		catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	/**
	 * Adds a new .as or .fla file to the FLP
	 * @param file
	 */
	private void addFileToFLP ( File file )
	{
		String filePath = file.getAbsolutePath();
		String fileName = file.getName();
		// files may only be as or fla
		String fileType = fileName.endsWith(".as") ? "as" : "fla"; 
		
		try
		{
			out.write("<project_file path=\""+filePath+"\" filetype=\""+fileType+"\" />\n");
		}
		catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	/**
	 * Ends a project folder in the FLP XML.
	 *
	 */
	private void endFolderInFLP ()
	{
		try
		{
			out.write("</project_folder>\n");
		}
		catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}
	
	/**
	 * Ends the FLP XML file.
	 *
	 */
	private void endFLP ()
	{
		try
		{
			out.write("</flash_project>\n");
			out.flush();
			out.close();
		}
		catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}



