/*
 * <copyright> Copyright (c) 2006 by Know-Center, Graz, Austria </copyright>
 * 
 * This software is the confidential and proprietary information of Know-Center,
 * Graz, Austria. You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with Know-Center.
 * 
 * KNOW-CENTER MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT. KNOW-CENTER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
 * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES.
 * 
 * $Id: CodingHelper.java,v 1.6 2006/10/11 07:52:36 wprinz Exp $
 */
package at.knowcenter.wag.egov.egiz.tools;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.codec.binary.Base64;

/**
 * This class provides encoding and decoding methods and other coding methods.
 * All methods are static!
 * 
 * @author wlackner
 */
public class CodingHelper
{

  /**
   * Static Base64 object
   */
  private static Base64 b64 = new Base64();

  /**
   * This method encodes a given Unicode (Java) String to UTF-8 bytes and then
   * encodes these UTF-8 bytes to a Base64 US-ASCII (Java) String.
   * 
   * @param plain_string
   *          to be encoded
   * @return the UTF-8 and Base64 encoded string
   */
  public static String encodeUTF8AsBase64(String plain_string)
  {
    try
    {
      byte[] utf8_bytes = plain_string.getBytes("UTF-8");
      byte[] base64_bytes = b64.encode(utf8_bytes);
      String encoded_string = new String(base64_bytes, "US-ASCII");
      return encoded_string;
    }
    catch (UnsupportedEncodingException e)
    {
      e.printStackTrace();
      throw new RuntimeException(e);
    }
  }

  /**
   * This method decodes the UTF-8 bytes from a Base64 US-ASCII (Java) String
   * and decodes the UTF-8 bytes to a unicode (Java) String.
   * 
   * @param encoded_string
   *          to be decoded
   * @return the Base64 and UTF-8 decoded string
   */
  public static String decodeUTF8FromBase64(String encoded_string)
  {
    try
    {
      byte[] base64_bytes = encoded_string.getBytes("US-ASCII");
      byte[] utf8_bytes = b64.decode(base64_bytes);
      String plain_string = new String(utf8_bytes, "UTF-8");
      return plain_string;
    }
    catch (UnsupportedEncodingException e)
    {
      e.printStackTrace();
      throw new RuntimeException(e);
    }
  }

  // /**
  // * This method encodes a given string UTF-8
  // *
  // * @param theString to be encoded
  // * @return the UTF-8 encoded string
  // */
  // public static byte[] encodeUTF8(String theString) {
  // byte[] utf8 = null;
  // try {
  // utf8 = theString.getBytes("UTF-8");
  // } catch (UnsupportedEncodingException e) {
  // e.printStackTrace();
  // }
  // return utf8;
  // }

  // /**
  // * This method decodes a given UTF-8 string
  // *
  // * @param theString to be decoded
  // * @return the decoded UTF-8 string
  // */
  // public static String decodeUTF8(String theString) {
  // byte[] ba = theString.getBytes();
  // String the_string = decodeUTF8(ba);
  // if (the_string != null) {
  // return the_string;
  // }
  // return theString;
  // }

  // /**
  // * This method decodes a given UTF-8 byte array
  // *
  // * @param ba the byte array to be decoded
  // * @return the decoded UTF-8 string
  // */
  // public static String decodeUTF8(byte[] ba) {
  // String the_string = null;
  // try {
  // the_string = new String(ba, "UTF-8");
  // } catch (UnsupportedEncodingException e) {
  // e.printStackTrace();
  // }
  // return the_string;
  // }

  /**
   * This method decodes a given Base64 string.
   * 
   * <p>
   * Note that the given String must only contain Base64 characters. (The string
   * will be converted to a byte array of "US-ASCII" (7 bit) bytes and then this
   * byte array will be decoded using the Base64 algorithm.
   * </p>
   * 
   * @param theString
   *          to be decoded
   * @return a Base64 decoded byte array
   */
  public static byte[] decodeBase64(String theString)
  {
    try
    {
      byte[] base64_bytes = theString.getBytes("US-ASCII");
      return b64.decode(base64_bytes);
    }
    catch (UnsupportedEncodingException e)
    {
      e.printStackTrace();
      throw new RuntimeException("Very Strange: US-ASCII encoding not supported???", e);
    }
  }

  /**
   * This method decodes a given Base64 byte array
   * 
   * @param ba
   *          the byte array to be decoded
   * @return a Base64 decoded byte array
   */
  public static byte[] decodeBase64(byte[] ba)
  {
    return b64.decode(ba);
  }

  /**
   * This method encodes a given byte array Base64
   * 
   * @param plainString
   *          the byte array to be encoded
   * @return the Base64 encoded string
   */
  public static String encodeBase64(byte[] plainString)
  {
    try
    {
      byte[] base64_bytes = b64.encode(plainString);
      return new String(base64_bytes, "US-ASCII");
    }
    catch (UnsupportedEncodingException e)
    {
      e.printStackTrace();
      throw new RuntimeException("Very Strange: US-ASCII encoding not supported???", e);
    }
  }

  /**
   * This method builds an SHA-1 hash value of a given byte array.
   * 
   * @param data
   *          the byte array to build the hash value for
   * @return the calculated hash value as a byte array
   * @see MessageDigest
   */
  public static byte[] buildDigest(byte[] data)
  {
    MessageDigest sha_1 = null;
    try
    {
      sha_1 = MessageDigest.getInstance("SHA-1");
      sha_1.update(data);
      return sha_1.digest();
    }
    catch (NoSuchAlgorithmException e)
    {
      return null;
    }
  }

  /**
   * This method escapes a given string with HTML entities.
   * 
   * @param rawString
   *          the string to escaped
   * @return the HTML escaped string
   */
  public static String htmlEscape(String rawString)
  {
    rawString = rawString.replaceAll("\\&", "&amp;");
    rawString = rawString.replaceAll("\\<", "&lt;");
    rawString = rawString.replaceAll("\\>", "&gt;");
    rawString = rawString.replaceAll("\">", "&quot;");
    return rawString;
  }

  /**
   * This method checks, if a byte array contains chars that are not base64
   * conform.
   * 
   * @param byteArray
   *          the array to test
   * @return boolean, if a byte array is base64 conform, false otherwise
   */
  public static boolean isB64(byte[] byteArray)
  {
    try
    {
      return Base64.isArrayByteBase64(byteArray);
    }
    catch (ArrayIndexOutOfBoundsException e)
    {
      return false;
    }
  }

  /**
   * This method checks, if a string contains chars that are not base64 conform.
   * 
   * @param string
   *          the chars to test
   * @return boolean, if the given string is base64 conform, false otherwise
   */
  public static boolean isB64(String string)
  {
    try
    {
      return Base64.isArrayByteBase64(string.getBytes());
    }
    catch (ArrayIndexOutOfBoundsException e)
    {
      return false;
    }
  }
}