/******************************************************************************
 * Product: Compiere ERP & CRM Smart Business Solution                        *
 * Copyright (C) 1999-2007 ComPiere, Inc. All Rights Reserved.                *
 * This program is free software, you can redistribute it and/or modify it    *
 * under the terms version 2 of the GNU General Public License as published   *
 * by the Free Software Foundation. This program 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 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.                     *
 * For the text or an alternative of this public license, you may reach us    *
 * ComPiere, Inc., 3600 Bridge Parkway #102, Redwood City, CA 94065, USA      *
 * or via info@compiere.org or http://www.compiere.org/license.html           *
 *****************************************************************************/
package org.compiere.util;

import java.io.*;
import java.util.logging.*;
import javax.crypto.*;

/**
 * 	Security Utility
 *	
 *  @author Jorg Janke
 *  @version $Id: SecureUtil.java,v 1.1 2008/01/16 07:34:32 jrmt Exp $
 */
public class SecureUtil
{
	/**
	 * 	Create New Key and Install.
	 * 	Should not be called as it always will create a new key
	 *	@param compiereHome compiere home directory
	 *	@return true if key installed
	 */
	public static boolean createNewKey (String compiereHome)
	{
		SecureUtil util = new SecureUtil();
		//	create key
		if (!util.createKey())
			return false;
		//	create Java class
		if (!util.createClassCode())
			return false;
		//	save Java class
		if (!util.saveClassCode(compiereHome))
			return false;
		return installKey(compiereHome);
	}	//	installNewKey
	
	/**
	 * 	Install Key
	 *	@param compiereHome compiere home directory
	 *	@return true if key installed
	 */
	public static boolean installKey (String compiereHome)
	{
		File keyFile = getKeyFile(compiereHome);
		if (!keyFile.exists())
		{
			log.info("File not found");
			return createNewKey(compiereHome);
		}
		// TODO: compile
		
		// TODO: move to package location
		
		// TODO: replace class in current classloader!
		
		//	Update Secure
		SecureEngine.reset();
		return true;
	}	//	installKey
	
	/**
	 * 	Get Key Name
	 *	@param compiereHome compiere home directory
	 *	@return file name
	 */
	public static File getKeyFile (String compiereHome)
	{
		return new File(compiereHome + classFileName);
	}	//	getFileName
	
	/**************************************************************************
	 * 	SecureUtil
	 */
	private SecureUtil()
	{
	}	//	SecureUtil
	
	/**	Logger	*/
    private static CLogger log = CLogger.getCLogger(SecureUtil.class);
	/** File name relative to CompiereHome	*/
	private static final String	classFileName = "/lib/CompiereSecure.dat";
	/**	The Key					*/
	private SecretKey 		m_key = null;
	/** Class Code				*/
	private StringBuffer	m_cc = null;

	/**
	 * 	Create Key
	 *	@return true if success
	 */
	private boolean createKey()
	{
		try
		{
			KeyGenerator keygen = KeyGenerator.getInstance("DES");
			m_key = keygen.generateKey();
		}
		catch (Exception e)
		{
			log.log(Level.SEVERE, "", e);
			m_key = null;
			return false;
		}
		byte[] keys = m_key.getEncoded();
		StringBuffer sb = new StringBuffer ("Key ")
			.append(m_key.getAlgorithm())
			.append("(").append(keys.length).append(")= ");
		for (int i = 0; i < keys.length; i++)
			sb.append(keys[i]).append(",");
		log.info(sb.toString());
		return true;
	}	//	createKey

	/**
	 * 	Create Class Code
	 *	@return true if success
	 */
	private boolean createClassCode()
	{
		m_cc = new StringBuffer()
			.append("package org.compiere.util; ")
			.append("import javax.crypto.*; ")
			.append("import javax.crypto.spec.*; ")
			.append("public class SecureKey{")
			.append("static protected SecretKey key = new SecretKeySpec ")
			.append("(new byte[]{");
		byte[] keys = m_key.getEncoded();
		for (int i = 0; i < keys.length; i++)
		{
			if (i != 0)
				m_cc.append(",");
			m_cc.append(keys[i]);
		}
		m_cc.append("},\"DES\");}");
		log.finest(m_cc.toString());
		log.fine("(#" + m_cc.length() + ")");
		return m_cc.length() > 0;
	}	//	createClassCode

	/**
	 * 	Save/overwrite Class Code
	 *	@param compiereHome home
	 *	@return true if success
	 */
	private boolean saveClassCode(String compiereHome)
	{
		File file = getKeyFile(compiereHome);
		String phase = "deleteFile";
		try
		{
			if (file.exists())
				file.delete();
			phase = "createNewFile";
			file.createNewFile();
			phase = "createWriter";
			FileWriter fw = new FileWriter(file);
			phase = "writeFile";
			fw.write(m_cc.toString());
			phase = "closeFile";
			fw.flush();
			fw.close();
		}
		catch (Exception e)
		{
			log.log(Level.SEVERE, phase, e);
			return false;
		}
		File backup = Util.createBackup(file);
		if (backup == null)
			return false;
		log.fine(file.getAbsolutePath() + " (#" + file.length() + ") - "
			+ backup.getAbsolutePath() + " (#" + backup.length() + ")");
		return true;
	}	//	saveClassCode

	/**************************************************************************
	 * 	Test
	 *	@param args
	 */
	public static void main(String[] args)
	{
		CLogMgt.initialize(true);
		CLogMgt.setLevel(Level.FINEST);

		installKey("C:\\Compiere2");
		
	}	//	main
	
}	//	SecureUtil
