/* ===============================================================================
 *
 * Part of the InfoGlue Content Management Platform (www.infoglue.org)
 *
 * ===============================================================================
 *
 *  Copyright (C)
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License version 2, as published by the
 * Free Software Foundation. See the file LICENSE.html for more information.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY, including the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc. / 59 Temple
 * Place, Suite 330 / Boston, MA 02111-1307 / USA.
 *
 * ===============================================================================
 */

package org.infoglue.cmsinstaller;

import java.io.*;
import java.util.*;
import java.util.zip.*;

public abstract class InstallationCommander
{
	protected String appServer						= null;
	protected String cmsTargetFolder     			= null;
	protected String deliverWorkingTargetFolder 	= null;
	protected String deliverPreviewTargetFolder 	= null;
	protected String deliverLiveTargetFolder 		= null;
	protected String applicationServerHomePath 		= null;
	protected String tomcatContextFolder			= null;
	protected String createCMS						= null;
	protected String createDeliverWorking			= null;
	protected String createDeliverPreview			= null;
	protected String createDeliverLive 				= null;
	protected String appNameSuffix					= null;
	
	public static InstallationCommander getInstallationCommander(String appServer, String targetFolder, String appNameSuffix, String applicationServerHomePath, String createCMS, String createDeliverWorking, String createDeliverPreview, String createDeliverLive, String tomcatContextFolder/*, String tomcatVersion*/)
	{
		if(appServer.startsWith("Tomcat"))
			return new TomcatInstallationCommander(appServer, targetFolder, appNameSuffix, applicationServerHomePath, createCMS, createDeliverWorking, createDeliverPreview, createDeliverLive, tomcatContextFolder);
		else if(appServer.startsWith("JBoss"))
			return new JBossInstallationCommander(appServer, targetFolder, appNameSuffix, applicationServerHomePath, createCMS, createDeliverWorking, createDeliverPreview, createDeliverLive, tomcatContextFolder);
		else
			return null;
	}
	
	public InstallationCommander(String appServer, String targetFolder, String appNameSuffix, String applicationServerHomePath, String createCMS, String createDeliverWorking, String createDeliverPreview, String createDeliverLive, String tomcatContextFolder)
	{
		this.appServer				= appServer;
		this.applicationServerHomePath 			= applicationServerHomePath;
		this.createCMS 				= createCMS;
		this.createDeliverWorking 	= createDeliverWorking;
		this.createDeliverPreview 	= createDeliverPreview;
		this.createDeliverLive		= createDeliverLive;
		this.appNameSuffix 			= appNameSuffix;
		this.tomcatContextFolder 	= tomcatContextFolder;
		//this.tomcatVersion			= tomcatVersion;
		this.cmsTargetFolder     		= targetFolder + File.separator + "infoglueCMS" + appNameSuffix;
		this.deliverWorkingTargetFolder = targetFolder + File.separator + "infoglueDeliverWorking" + appNameSuffix;
		this.deliverPreviewTargetFolder = targetFolder + File.separator + "infoglueDeliverPreview" + appNameSuffix;
		this.deliverLiveTargetFolder 	= targetFolder + File.separator + "infoglueDeliverLive" + appNameSuffix;
	}

	public abstract String getPortletBase();
	
	public abstract void installFiles(String databaseTypeName) throws Exception;
	
	/**
	 * This method copies the newly created config-files to the installation dir.
	 */
	
	protected abstract void moveLocalConfigurationFiles(String databaseTypeName) throws Exception;
	
	
	/**
	 * This method checks if xml-packages are needed.
	 */
	
	protected boolean checkIfXMLLibsIsNeeded()
	{
		try
		{
			Class testClass = Class.forName("org.apache.xml.serialize.XMLSerializer");
			return false;
		}
		catch(ClassNotFoundException e)
		{
			Logger.logInfo("The installer will install the xml-packages as they seem to be missing.");
			return true;
		}
	}
	
	
	
	/**
	 * This method unzips the cms war-file.
	 */
	
	protected void unzipCMSWarFile(String cmsTargetFolder) throws Exception
	{
		String warFile = "infoglue-cms.war";
		
    	Enumeration entries;
    	ZipFile zipFile;
    	
    	System.out.println("Getting warFile: " + warFile + " to " + cmsTargetFolder);
    	zipFile = new ZipFile(warFile);
      	entries = zipFile.entries();

      	while(entries.hasMoreElements()) 
      	{
        	ZipEntry entry = (ZipEntry)entries.nextElement();

	        if(entry.isDirectory()) 
	        {
	          	(new File(cmsTargetFolder + File.separator + entry.getName())).mkdir();
	          	continue;
	        }
	
	        //System.err.println("Extracting file: " + this.cmsTargetFolder + File.separator + entry.getName());
	        copyInputStream(zipFile.getInputStream(entry), new BufferedOutputStream(new FileOutputStream(cmsTargetFolder + File.separator + entry.getName())));
	    }
	
	    zipFile.close();
	}


	/**
	 * This method unzips the cms war-file.
	 */
	
	protected void unzipDeliverWarFile(String path) throws Exception
	{
		String warFile = "infoglue-deliver.war";
		
    	Enumeration entries;
    	ZipFile zipFile;

    	zipFile = new ZipFile(warFile);
      	entries = zipFile.entries();

      	while(entries.hasMoreElements()) 
      	{
        	ZipEntry entry = (ZipEntry)entries.nextElement();

	        if(entry.isDirectory()) 
	        {
	          	(new File(path + File.separator + entry.getName())).mkdir();
	          	continue;
	        }
	
	        //System.err.println("Extracting file: " + this.deliverTargetFolder + File.separator + entry.getName());
	        copyInputStream(zipFile.getInputStream(entry), new BufferedOutputStream(new FileOutputStream(path + File.separator + entry.getName())));
	    }
	
	    zipFile.close();
	}

	
	/**
	 * Just copies the files...
	 */
	
	protected void copyInputStream(InputStream in, OutputStream out) throws IOException
	{
	    byte[] buffer = new byte[1024];
    	int len;

    	while((len = in.read(buffer)) >= 0)
      		out.write(buffer, 0, len);

    	in.close();
    	out.close();    	
  	}

	/**
	 * This method recursively zips a directory structure.
	 */

	public void zipDir(String dir2zip, int numberOfCharsToRemove, ZipOutputStream zos) throws Exception
	{
		// create a new File object based on the directory we have to zip File    
        File zipDir = new File(dir2zip); 
        
        // get a listing of the directory content
        String[] dirList = zipDir.list(); 
        
        byte[] readBuffer = new byte[2156]; 
        
        int bytesIn = 0; 

        for(int i=0; i<dirList.length; i++) 
        { 
        	File f = new File(zipDir, dirList[i]); 
	        if(f.isDirectory()) 
	        { 
	            String filePath = f.getPath(); 
	            zipDir(filePath, numberOfCharsToRemove, zos); 
	            continue; 
	        }
	        
            FileInputStream fis = new FileInputStream(f); 

            ZipEntry anEntry = new ZipEntry(f.getPath().substring(numberOfCharsToRemove)); 
    	    System.out.println("Adding " + f.getPath().substring(numberOfCharsToRemove));

            zos.putNextEntry(anEntry); 
            
            while((bytesIn = fis.read(readBuffer)) != -1) 
            { 
                zos.write(readBuffer, 0, bytesIn); 
            } 
           
            fis.close(); 
        } 
	}
	
	public void modifyOSCachePropertyFile(String targetFolder) throws Exception
	{
		FileInputStream fis = new FileInputStream(targetFolder + File.separator + "WEB-INF/classes/oscache.properties");
		String result = "";
		StringBuffer sb = new StringBuffer();
		
		int c;
		while((c = fis.read()) != -1)
		{
			sb.append((char)c);
		}
		result = sb.toString();
		fis.close();
		
		result = result.replaceAll("@cachePath@", targetFolder + File.separator + "cache");
		result = result.replaceAll("\\@cachePath\\@", targetFolder + File.separator + "cache");
		
		PrintWriter pw = new PrintWriter(new FileOutputStream(targetFolder + File.separator + "WEB-INF/classes/oscache.properties"));
		pw.println(result);
		pw.close();

	}

	
	protected void deleteRecursive(File file) throws IOException
	{
	   	File[] files = file.listFiles();

		for(int i=0; i<files.length; ++i)
	   	{
			if(files[i].isDirectory())
		  		deleteRecursive(files[i]);
			
			files[i].delete();
	   	}
	}

	protected List<String> getSharedLibs()
	{
        List<String> sharedLibs = new ArrayList<String>();
        
        sharedLibs.add("activation.jar");
        sharedLibs.add("mail.jar");
        sharedLibs.add("pluto-1.0.1.jar");
        sharedLibs.add("portlet-api-1.0.jar");
        sharedLibs.add("saxon9.jar");
        sharedLibs.add("saxon9-ant.jar");
        sharedLibs.add("saxon9-dom.jar");
        sharedLibs.add("saxon9-dom4j.jar");
        sharedLibs.add("saxon9-jdom.jar");
        sharedLibs.add("saxon9-sql.jar");
        sharedLibs.add("saxon9-xom.jar");
        sharedLibs.add("saxon9-xpath.jar");
        sharedLibs.add("saxon9-xqj.jar");
        sharedLibs.add("saxon9-s9api.jar");

        return sharedLibs;
	}

}
