/*******************************************************************************
 *
 * Copyright (c) 2002-2003 IBM Corporation, Beacon Information Technology Inc. and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   IBM      - Initial API and implementation
 *   BeaconIT - Initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.wsi.internal.core.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.Vector;

import org.eclipse.wst.wsi.internal.core.WSIConstants;
import org.eclipse.wst.wsi.internal.core.WSIException;
import org.eclipse.wst.wsi.internal.core.log.MimePart;
import org.eclipse.wst.wsi.internal.core.log.MimeParts;
import org.eclipse.wst.wsi.internal.core.log.impl.MimePartImpl;
import org.eclipse.wst.wsi.internal.core.log.impl.MimePartsImpl;
import org.eclipse.wst.wsi.internal.core.profile.ProfileAssertions;
import org.eclipse.wst.wsi.internal.core.xml.XMLUtils;

/**
 * General set of utilities.
 */
public final class Utils
{
  public static final byte CR = (byte) '\r';
  public static final byte LF = (byte) '\n';

  /**
   * Common timestamp format.
   */
  //	public static final SimpleDateFormat timestampFormat = new SimpleDateFormat ("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
  public static final SimpleDateFormat timestampFormat =
    new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");

  /**
   * Basic date format.
   */
  public static final SimpleDateFormat dateFormat =
    new SimpleDateFormat("yyyy-MM-dd");

  /**
   * Wrapper method for error logging;
   * for now it just goes to stderr.
   * @param inError  an error message.
   */
  public final static void logError(String inError)
  {
    System.err.println("Error: " + inError);
  }

  /** 
   * Get exception information as a string.
   * @param throwable  a Throwable object.
   * @return exception information as a string.
   */
  public final static String getExceptionDetails(Throwable throwable)
  {
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);

    pw.println("Exception: ");
    throwable.printStackTrace(pw);

    return sw.toString();
  }

  /**
   * Get current date and time as a timestamp.
   * @return urrent date and time as a timestamp.
   */
  public static String getTimestamp()
  {
    // Use GMT timezone
    //timestampFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
    timestampFormat.setTimeZone(TimeZone.getDefault());

    // Return timestamp
    return timestampFormat.format(new Date());
  }

  /**
   * Get current date for default time zone.
   * @return current date for default time zone.
   */
  public static String getDate()
  {
    // Use GMT timezone
    dateFormat.setTimeZone(TimeZone.getDefault());

    // Return date
    return dateFormat.format(new Date());
  }

  /**
   * Get HTTP status code.
   * @param httpHeaders  HTTP headers.
   * @return HTTP status code.
   * @throws WSIException if the status code in http headers was not found.
   */
  public static String getHTTPStatusCode(String httpHeaders)
    throws WSIException
  {
    String statusCode = null;

    if (httpHeaders.startsWith("HTTP"))
    {
      // Get location of status code
      int index = httpHeaders.indexOf(" ");
      int index2 = httpHeaders.indexOf(" ", index + 1);

      if ((index == -1) || (index2 == -1))
      {
        throw new WSIException(
          "Could not find status code in http headers: [" + httpHeaders + "].");
      }

      else
      {
        statusCode = httpHeaders.substring(index + 1, index2);
      }
    }

    else
    {
      throw new WSIException(
        "Could not find status code in http headers: [" + httpHeaders + "].");
    }

    // Return status code
    return statusCode;
  }

  /**
   * Get HTTP headers from a full message.
   * @param fullMessage  a message.
   * @return HTTP headers from a full message.
   */
  public static String getHTTPHeaders(String fullMessage)
  {
    //String httpHeaders = null;

    // Try looking for the double newline
    int index = fullMessage.indexOf("\r\n\r\n");
    if (index != -1)
    {
      index += 4;
    }
    else
    {
      // check for case "\r\r...\r\n\r\r...\n"
      // Note the index that is returned points to the first character 
      // immediatedly following the first occurence of the CRLFCRLF. 
      index = getFirstCRLFCRLF(fullMessage);
      if (index == -1)
      {
        logError(
          "Unable to parse HTTP message to find headers.  Full message: "
          + fullMessage);
        return "x-WSI-Test-Tool-Error: Couldn't find headers.  Full message: ["
          + fullMessage
          + "].";
      }
    }

    // Return HTTP headers
    return fullMessage.substring(0, index);
  }

  /**
   * Get SOAP message from a full message.
   * @param fullMessage  a message.
   * @return SOAP message from a full message.
   */
  public static String getContent(String fullMessage)
  {
    String message = "";

    // Find start of message
    int index = fullMessage.indexOf("\r\n\r\n");
    if (index != -1)
    {
      index += 4;
    }
    else
    {
      // check for case "\r\r...\r\n\r\r...\n"
      // Note the index that is returned points to the first character 
      // immediatedly following the first occurence of the CRLFCRLF. 
      index = getFirstCRLFCRLF(fullMessage);
    }    	

    if (index < 0)
    {
    	// If we couldn't find the end of the HTTP headers or the start of the message, then show error
      logError(
        "Unable to parse message to get content.  Full message: "
          + fullMessage);
      message =
        "x-WSI-Test-Tool-Error: Couldn't find message content.  Full message: ["
          + fullMessage
          + "].";
    }
    // If the index is greater than the length, then there is no message content
    else if (index >= fullMessage.length())
    {
      message = "";
    }

    // Else get the message content
    else
    {
      message = fullMessage.substring(index);
    }

    // Return SOAP message
    return message;
  }
 
  /**
   * Get HTTP headers from a full message.
   * @param fullMessage  a message.
   * @return HTTP headers from a full message.
   */
  public static byte[] getHTTPHeaders(byte[] fullMessage)
  {
    //String httpHeaders = null;
    int index = getFirstCRLFCRLF(fullMessage, 0);
    if (index == -1)
    {
      logError(
        "Unable to parse HTTP message to find headers.  Full message: "
          + fullMessage);
      return ("x-WSI-Test-Tool-Error: Couldn't find headers.  Full message: ["
        + fullMessage + "].").getBytes();
    }

    // Return HTTP headers
	byte[] b = new byte[index];
	System.arraycopy(fullMessage, 0, b, 0, index);

    return b;
  }

  /**
   * Get HTTP headers from a full message.
   * @param fullMessage  a message.
   * @return HTTP headers from a full message.
   */
  public static String getHTTPHeadersAsString(byte[] fullMessage, String encoding)
  {
    //String httpHeaders = null;
    int index = getFirstCRLFCRLF(fullMessage, 0);
    if (index == -1)
    {
      logError(
        "Unable to parse HTTP message to find headers.  Full message: "
          + fullMessage);
      return "x-WSI-Test-Tool-Error: Couldn't find headers.  Full message: ["
        + fullMessage + "].";
    }

    // Return HTTP headers
    try
    {
      return new String(fullMessage, 0, index, encoding);
    }
    catch (UnsupportedEncodingException e)
    {
        logError(
                "Unsupported Encoding: " + encoding + ".  Full message: "
                  + fullMessage);
              return "x-WSI-Test-Tool-Error: Unsupported Encoding \"" + encoding + "\".  Full message: ["
                + fullMessage + "].";
    }
  }

  /**
   * Get SOAP message from a full message.
   * @param fullMessage  a message.
   * @return SOAP message from a full message.
   */
  public static String getContentAsString(byte[] message)
  {
  	String content = "";
    //String httpHeaders = null;
    int index = getFirstCRLFCRLF(message, 0);

    // If we couldn't find the end of the HTTP headers or the start of the message, then show error
    if (index < 0)
    {
      logError(
        "Unable to parse message to get content.  Full message: "
          + message);
      content =
        "x-WSI-Test-Tool-Error: Couldn't find message content.  Full message: ["
          + message.toString()
          + "].";
    }

    // Else get the message content
    else if (index < message.length)
    {
      try
      {
        content = new String(message, index, message.length - index);
       }
      catch (Exception e)
      {
      	logError(
      	        "Unable to parse message to get content.  Full message: "
      	          + message);
      	content =
      	        "x-WSI-Test-Tool-Error: Couldn't find message content.  Full message: ["
      	          + message.toString()
      	          + "].";
      }
    }

    // Return SOAP message
    return content;
  }

  /**
   * Get SOAP message from a full message.
   * @param fullMessage  a message.
   * @return SOAP message from a full message.
   */
  public static byte[] getContent(byte[] message)
  {
    byte[] content = new byte [0];

    //String httpHeaders = null;
    int index = getFirstCRLFCRLF(message, 0);
 
    // If we couldn't find the end of the HTTP headers or the start of the message, then show error
    if (index < 0)
    {
      logError(
        "Unable to parse message to get content.  Full message: "
          + message);
      message =
        ("x-WSI-Test-Tool-Error: Couldn't find message content.  Full message: ["
          + message.toString()
          + "].").getBytes();
    }

    // If the index is greater than the length, then there is no message content
    //else if (index >= fullMessage.length())
    //{
    //  message = "";
    //}

    // Else get the message content
    else if (index < message.length)
    {
    	byte[] b = new byte[message.length - index];
    	System.arraycopy(message, index, b, 0, message.length - index);

        content = b;
    }

    // Return SOAP message
    return content;
  }

  
  /**
	 * Returns the first location of a CRLF.
	 *
	 * @return int
	 */
	public static int getFirstCRLF(byte[] buffer, int index) 
	{
		int size = buffer.length;
		int i = index;
		while (i < size - 1) {
			if (buffer[i] == CR && buffer[i+1] == LF)
				return i;
			i++;
		}
		return -1;
	}

	/**
	 * Returns the first location of a CRLF followed imediately by another CRLF.
	 *
	 * @return int
	 */
	public static int getFirstCRLFCRLF(byte[] buffer, int index) 
	{
		int size = buffer.length;
		int i = index;
		while (i < size - 3) 
		{
		  if (buffer[i] == CR && buffer[i+1] == LF && buffer[i+2] == CR)
		  {
			if (buffer[i+3] == LF)
			{
			  return i+4;
			}
			else
			{
			  int j = i + 3;
			  while (j < buffer.length && buffer[j] == CR)
			  {
				j++;
			  }
			  if (j < buffer.length && buffer[j] == LF)
			  {
			  	return j + 1;
			  }
			}
		  }
		  i++;
		}
		return -1;
	}

	/**
	 * Returns the first location of a CRLF followed imediately by another CRLF.
	 *
	 * @return int
	 */
	public static int getFirstCRLFCRLF(String buffer) 
	{
		int index = buffer.indexOf("\r\n\r");
		if (index != -1)
		{
		  int i = index +3;
		  while (i < buffer.length() && buffer.startsWith("\r", i))
		     i++;
		
		  if (i < buffer.length() && buffer.startsWith("\n", i))
			return i+1;
		  else
			return getFirstCRLFCRLF(buffer.substring(index + 3));
		}
		else
		{
		  return -1;
		}
	}

	/**
     * Returns the list of indices which marks the separation of parts.
     */
	public static int[] getBoundaryIndices(byte[] message, String boundaryStr)
	{
	  int[] indices = new int[256];
	  int indicesIndex = 0;
	  try
	  {
	    byte[] boundary = ("\r\n--" + boundaryStr).getBytes("US-ASCII");

	    int index = 0;
	    int start = 0;
	    while (index != -1)
	    {
	      index = indexOf(message, boundary, start);
	      
	      if (index != -1) 
	      {
		    start = index + boundary.length;
	    	indices[indicesIndex] = index;
	    	indicesIndex++;
	      }
	    }
      	int[] b = new int[indicesIndex];
    	System.arraycopy(indices, 0, b, 0, indicesIndex);
    	indices = b;
	  }
	  catch (Exception e)
	  {}
	  return indices;
	}
 
    /**
     * Returns the index of the first occurrence of key in the buffer.
     */
	public static int indexOf(byte[] buffer, byte[] key, int start)
	{
		int bufferLen = buffer.length;
		int keyLen = key.length;
		int i,j,k = 0;
		
		if (keyLen > bufferLen - start)
		{
			return -1;
		}
	
		for (k = start + keyLen - 1; k < bufferLen; k++)
		{
           for (j = keyLen - 1, i = k; (j >= 0) && (buffer[i] == key[j]); j--) 
           {
               i--;
           }

           if (j == (-1)) {
               return i + 1;
           }
		}

		return -1;
	}
	/**
   * Get contents of a resource and return as a input stream.
   *
   * @param resourceName the name of the resource to get and return as
   *                      an input stream.
   * @return contents of a resource as an input stream.
   * @throws IOException if the resource could not be located.
   */
  public static InputStream getInputStream(String resourceName)
    throws IOException
  {
    InputStream is = null;

    // If resource reference is a URL, then input stream from URL
    try
    {
      // Try to create URL
      URL urlResource = new URL(resourceName);

      // If successful, then get URL input stream
      is = getInputStream(urlResource);
    }

    // Else try to read resource directly
    catch (MalformedURLException mue)
    {
      boolean bTryClassLoader = false;

      try
      {
        // Open file input stream
        is = new BufferedInputStream(new FileInputStream(resourceName));
      }
      catch (FileNotFoundException fnfe)
      {
        // Set try class loader flag
        bTryClassLoader = true;
      }
      catch (SecurityException se)
      {
        // Set try class loader flag
        bTryClassLoader = true;
      }
      catch (Exception e)
      {
        // DEBUG:
        System.out.println("Exception in getInputStream :" + e.toString());
      }

      // If try class loader, then use it to get input stream
      if (bTryClassLoader)
      {
        // Use class loader to load resource
        is = ClassLoader.getSystemResourceAsStream(resourceName);
      }
    }

    // If the input stream is null, then throw FileNotFoundException
    if (is == null)
    {
      //try this
      is =
        Thread.currentThread().getContextClassLoader().getResourceAsStream(
          resourceName);
    }

    // If the input stream is null, then throw FileNotFoundException
    if (is == null)
    {
      //try this
      URL aURL =
        Thread.currentThread().getContextClassLoader().getResource(
          resourceName);
      if (aURL != null)
        is = getInputStream(aURL);
    }

    if (is == null)
      // Throw execption
      throw new FileNotFoundException(
        "Could not locate resource file: " + resourceName);

    // Return input stream
    return is;
  }

  /**
   * Get the input stream from a URL.
   * @param urlFile the URL to get the input stream from.
   * @return the input stream corresponding to the given URL.
   * @throws IOException if attempt to open the file denoted by URL has failed.
   * @throws ConnectException if trouble connecting to URL.
   */
  public static InputStream getInputStream(URL urlFile)
    throws IOException, ConnectException
  {
    InputStream is = null;

    // ADD: how are URLs that are password protected handled????

    try
    {
      // Open file input stream
      is = new BufferedInputStream(urlFile.openStream());
    }

    catch (ConnectException e)
    {
      // Re-throw this excpetion with additional information
      throw new java.net.ConnectException(
        "Could not connect to URL: " + urlFile.toExternalForm() + ".");
    }

    // Return input stream
    return is;
  }

  /**
   * Get contents of a resource and return as a input stream.
   * @param fileLocation the location of the file.
   * @return contents of a resource as a input stream.
   */
  public static boolean fileExists(String fileLocation)
  {
    boolean fileExists = false;

    // If resource reference is a URL, then input stream from URL
    try
    {
      // Try to create URL
      URL url = new URL(fileLocation);

      // If successful, then try to open connection
      url.openStream();
      fileExists = true;
    }

    // Else try to read resource directly
    catch (MalformedURLException mue)
    {
      try
      {
        File file = new File(fileLocation);

        fileExists = file.exists();
      }

      catch (Exception e2)
      {
        fileExists = false;
      }
    }

    catch (FileNotFoundException fnfe)
    {
      fileExists = false;
    }

    catch (Exception e)
    {
      fileExists = false;
    }

    // Return file exists indicator
    return fileExists;
  }

  /**
   * Get local host name.
   * @return the local host name.
   */
  public static String getLocalHostName()
  {
    String sLocalHostName;

    try
    {
      // Get local host name
      sLocalHostName = InetAddress.getLocalHost().getHostName();
    }
    catch (Exception e)
    {
      // Set default local host name
      sLocalHostName = "127.0.0.1";
    }

    // Return local host name
    return sLocalHostName;
  }

  /**
   * Build a URL string from hostname, port and URN.
   *
   * @param hostname the hostname.
   * @param port the port.
   * @param urn the URN.
   * @return formatted URL string.
   */
  public static String formatURL(String hostname, String port, String urn)
  {
    // Build URN
    String formatURN = urn;

    // If URN doesn't start with "/", then add it
    if (!(formatURN.startsWith("/")))
    {
      // Add "/" to beginning of the string
      formatURN = "/" + urn;
    }

    // Return URL string
    return "http://" + hostname + ":" + port + formatURN;
  }

  /**
   * This method will replace all of the occurances of a string
   * with a substitution string.
   *
   * @param sText String to udpate.
   * @param sFind String to find.
   * @param sReplace String to use for substitution.
   * @return updated string.
   */
  public static String replaceString(
    String sText,
    String sFind,
    String sReplace)
  {
    int iPrevIndex = 0;

    int iFindLen = sFind.length();
    int iReplaceLen = sReplace.length();

    String sUpdatedText = sText;

    // Replace all occurances of the find string
    for (int iIndex = sUpdatedText.indexOf(sFind);
      iIndex < (sUpdatedText.length() - 1) && iIndex != -1;
      iIndex = sUpdatedText.indexOf(sFind, iPrevIndex + iReplaceLen))
    {
      // Set updated text from the front portion + replacement text + back portion
      sUpdatedText =
        sUpdatedText.substring(0, iIndex)
          + sReplace
          + sUpdatedText.substring(iIndex + iFindLen);

      // Set the previous index field
      iPrevIndex = iIndex;
    }

    // Return updated text string
    return sUpdatedText;
  }

  /**
   * Convert string to hex string.
   * @param data  a String object.
   * @return hex string.
   */
  public static String toHexString(String data)
  {
    char[] HEX_CHARS =
      {
        '0',
        '1',
        '2',
        '3',
        '4',
        '5',
        '6',
        '7',
        '8',
        '9',
        'A',
        'B',
        'C',
        'D',
        'E',
        'F' };

    // Get string as byte array
    byte[] byteData = data.getBytes();

    // Get length
    int length = byteData.length;

    // Create Char buffer
    char[] charBuffer = new char[length * 2];

    int next;
    for (int byteCnt = 0, charCnt = 0; byteCnt < length;)
    {
      next = byteData[byteCnt++];
      charBuffer[charCnt++] = HEX_CHARS[(next >>> 4) & 0x0F];
      charBuffer[charCnt++] = HEX_CHARS[next & 0x0F];
    }

    return new String(charBuffer);
  }

  /**
   * Convert byte buffer to hex string.
   * @param data  a byte array.
   * @return hex string.
   */
  public static String toHexString(byte[] byteData)
  {
    char[] HEX_CHARS =
      {
        '0',
        '1',
        '2',
        '3',
        '4',
        '5',
        '6',
        '7',
        '8',
        '9',
        'A',
        'B',
        'C',
        'D',
        'E',
        'F' };


    // Get length
    int length = byteData.length;

    // Create Char buffer
    char[] charBuffer = new char[length * 2];

    int next;
    for (int byteCnt = 0, charCnt = 0; byteCnt < length;)
    {
      next = byteData[byteCnt++];
      charBuffer[charCnt++] = HEX_CHARS[(next >>> 4) & 0x0F];
      charBuffer[charCnt++] = HEX_CHARS[next & 0x0F];
    }

    return new String(charBuffer);
  }

  // I18N: 2003.02.26 modified by K.Nakagome@BeaconIT
  /**
   * Get MIME charset from a HTTP headers.
   * @param httpHeaders String of HTTP header.
   * @return the MIME charset string.
   * @author K.Nakagome@BeaconIT Japan SIG 
   */
  public static String getHTTPCharset(String httpHeaders)
  {
    String mimeCharset = null;

    mimeCharset = httpHeaders.toUpperCase();
    int[] index = { -1, -1, -1 };
    int indexS = mimeCharset.indexOf("CHARSET");
    int indexE = Integer.MAX_VALUE;
    if (indexS < 17)
    {
      return "";
    }
    indexS = mimeCharset.indexOf("=", indexS + 7);
    if (indexS == -1)
    {
      return "";
    }
    indexS++;
    index[0] = mimeCharset.indexOf("'", indexS);
    index[1] = mimeCharset.indexOf("\r\n", indexS);
    index[2] = mimeCharset.indexOf("\"", indexS);
    for (int i = 0; i < 3; i++)
    {
      if (index[i] != -1 & indexE > index[i])
      {
        indexE = index[i];
      }
    }

    if (indexE != Integer.MAX_VALUE)
    {
      mimeCharset = httpHeaders.substring(indexS, indexE);
      mimeCharset.trim();
    }
    else
    {
      mimeCharset = "";
    }
    return mimeCharset;
  }

  /**
   * Checks to see if the message is a simple SOAP message or whether it is a SOAP messagwe with attachments.
   */
  public static boolean isMultipartRelatedMessage(String httpHeaders)
  {
  	boolean result = false;
    try 
    {
      // check header for mime version and boundary
      String contentType = HTTPUtils.getHttpHeaderAttribute(httpHeaders, HTTPConstants.HEADER_CONTENT_TYPE);
      if (contentType == null)
      {
        // there is no contentType, check if there is a boundary attribute
        String boundary = Utils.getHttpHeaderSubAttribute(httpHeaders, HTTPConstants.HEADER_CONTENT_TYPE, "boundary");
        if ((boundary != null) && (!boundary.equals("")))
           result = true;
      }
      else
      {
        result = contentType.equalsIgnoreCase("multipart/related");
      }
    } 
    catch (WSIException e)
	{ 
    	result = false; 
    }
    return result;
  }

  public static String getHttpHeaderAttribute(String httpHeaders, String attributeName)
  { String result = null;
  	try
  	{
     result = HTTPUtils.getHttpHeaderAttribute(httpHeaders, attributeName);
  	}
    catch (WSIException e)
	{ 
    	result = null; 
    }
    return result;
 }

  public static String getHttpHeaderSubAttribute(String httpHeaders, String attributeName, String subAttributeName)
  { String result = null;
  	try
  	{
     result = HTTPUtils.getHttpHeaderSubAttribute(httpHeaders, attributeName, subAttributeName);
  	}
    catch (WSIException e)
	{ 
    	result = null; 
    }
    return result;
 }

  public static String getMimeHeaderAttribute(String mimeHeaders, String attributeName)
  { String result = null;
  	try
  	{
     result = MIMEUtils.getMimeHeaderAttribute(mimeHeaders, attributeName);
  	}
    catch (WSIException e)
	{ 
    	result = null; 
    }
    return result;
 }

  public static String getMimeHeaderSubAttribute(String mimeHeaders, String attributeName, String subAttributeName)
  { String result = null;
  	try
  	{
     result = MIMEUtils.getMimeHeaderSubAttribute(mimeHeaders, attributeName, subAttributeName);
  	}
    catch (WSIException e)
	{ 
    	result = null; 
    }
    return result;
 }
  // I18N: 2003.02.26 modified by K.Nakagome@BeaconIT
  /**
   * Get XML encoding from a SOAP Messages.
   * @param message  SOAP Message String. 
   * @return character encoding of XML.
   * @author K.Nakagome@BeaconIT Japan SIG 
   */
  public static String getXMLEncoding(String message)
  {
    String xmlDef = null;

    int indexS = message.indexOf("<?xml");
    int indexE = -1;
    if (indexS != -1)
    {
      indexE = message.indexOf("?>", indexS);
      if (indexE > indexS)
      {
        xmlDef = message.substring(indexS, indexE);
      }
    }

    if (xmlDef != null)
    {
      indexS = xmlDef.indexOf("encoding");
      if (indexS == -1)
      {
        xmlDef = "";
      }
      else
      {
        xmlDef = xmlDef.substring(indexS + 8);
        xmlDef = xmlDef.trim();
      }
    }
    else
    {
      return "";
    }

    if (xmlDef.length() > 3)
    {
      indexS = xmlDef.indexOf("=");
      if (indexS == 0)
      {
        xmlDef = xmlDef.substring(1);
      }
      else
      {
        return "";
      }
    }

    if (xmlDef.length() > 3)
    {
      String end = "\"";
      indexS = xmlDef.indexOf(end);
      if (indexS != 0)
      {
        indexS = xmlDef.indexOf((end = "'"));
      }
      if (indexS == 0)
      {
        indexE = xmlDef.indexOf(end, 3);
        if (indexE != -1)
        {
          xmlDef = xmlDef.substring(1, indexE);
        }
        else
        {
          xmlDef = "";
        }
      }
      else
      {
        xmlDef = "";
      }
    }
    return xmlDef;
  }

  // I18N: 2003.02.26 modified by K.Nakagome@BeaconIT
  private static ResourceBundle javaEncodingResource = null;
  private static final String JAVA_ENCODING_RESOURCE =
    "org.wsi.test.util.JavaEncoding";
  private static final String JAVA_ENCODING_DEFAULT = "UTF-8";

  // I18N: 2003.02.26 modified by K.Nakagome@BeaconIT
  /**
   * Get Java VM supported character encoding.
   * 
   * @param mimeEncoding  string of MIME(IANA) character encoding. 
   * @return string of character encoding supported by Java VM.
   * @author K.Nakagome@BeaconIT Japan SIG 
   */
  public static String getJavaEncoding(String mimeEncoding)
  {
    if (mimeEncoding == null || mimeEncoding.length() == 0)
    {
      return JAVA_ENCODING_DEFAULT;
    }
    try
    {
      if (javaEncodingResource == null)
      {
        javaEncodingResource = ResourceBundle.getBundle(JAVA_ENCODING_RESOURCE);
      }
      return javaEncodingResource.getString(mimeEncoding);
    }
    catch (Throwable t)
    {
      return mimeEncoding;
    }
  }

  /**
   * Convert an array to a Vector.
   * 
   * @param array  the array to be converted .
   * @return converted Vector (null if array is null, empty if empty).
   * @author Graham Turrell IBM
   */
  public static Vector arrayToVector(Object[] array)
  {
    if (array == null)
      return null;
    Vector v = new Vector(array.length);
    for (int i = 0; i < array.length; i++)
      v.add(array[i]);
    return v;
  }
  /**
   * Checks to ensure that version of the profile test assertion 
   * document is supported in this version of the test tools.
   * @param profileAssertions - a profile TAD.
   * @return true if the version of the profile test assertion
   *         docuement is supported in this version of the test tools.
   */
  public static boolean isValidProfileTADVersion(ProfileAssertions profileAssertions)
  {
    boolean result = false;

    String name = profileAssertions.getTADName();
    String version = profileAssertions.getTADVersion();

    if (WSIConstants.BASIC_PROFILE_TAD_NAME.equals(name))
    {
      result =
        checkVersionNumber(WSIConstants.BASIC_PROFILE_TAD_VERSION, version);
    } else if (WSIConstants.BASIC_PROFILE_1_1_TAD_NAME.equals(name))
    {  
      result =
        checkVersionNumber(WSIConstants.BASIC_PROFILE_1_1_TAD_VERSION, version);
    } else if (WSIConstants.SIMPLE_SOAP_BINDINGS_PROFILE_TAD_NAME.equals(name))
    {
      result =
        checkVersionNumber(WSIConstants.SIMPLE_SOAP_BINDINGS_PROFILE_TAD_VERSION, version);
    } else if (WSIConstants.ATTACHMENTS_PROFILE_TAD_NAME.equals(name))
    {
      result =
        checkVersionNumber(WSIConstants.ATTACHMENTS_PROFILE_TAD_VERSION, version);
    }
    return result;
  }

  /**
   * Checks to ensure that version number of the actual profile test assertion 
   * document is supported in this version of the test tools.
   * @param supportedVersion - supported version number of profile TAD.
   * @param actualVersion    - actual version number of profile TAD. 
   * @return true if the version number of the actual profile test assertion
   *         document is supported in this version of the test tools.
   */
  private static boolean checkVersionNumber(
    String supportedVersion,
    String actualVersion)
  {
    boolean validVersion = true;

    try
    {
      StringTokenizer supportedVersionTokenizer =
        new StringTokenizer(supportedVersion, ".");
      StringTokenizer actualVersionTokenizer =
        new StringTokenizer(actualVersion, ".");

      while (supportedVersionTokenizer.hasMoreTokens() && validVersion)
      {
        int supportedVersionToken =
          Integer.parseInt(supportedVersionTokenizer.nextToken());
        if (actualVersionTokenizer.hasMoreTokens())
        {
          int actualVersionToken =
            Integer.parseInt(actualVersionTokenizer.nextToken());
          if (supportedVersionToken > actualVersionToken) break;
          else validVersion = (supportedVersionToken >= actualVersionToken);
        }
      }
    }
    catch (Exception e)
    {
      validVersion = false;
    }
    return validVersion;
  }
  
  /**
   * Identifies the root part in the list using the "start" attribute.
   * If the "start" attribute does not exist then the first part is designated the root.
   */
  public static MimePart findRootPart(String httpHeaders, Collection parts)
  {
  	MimePart root = null;
    String start = Utils.getHttpHeaderSubAttribute(httpHeaders, HTTPConstants.HEADER_CONTENT_TYPE, "start");
    if (!parts.isEmpty())
    {
      // default to the first part in the collection
      root = (MimePart)parts.iterator().next();
    	
      if ((start != null) && (!start.equals("")))
      {
    	Iterator i = parts.iterator();
    	boolean rootNotFound = true;
    	while (i.hasNext() && rootNotFound)
    	{
    	  MimePart part = (MimePart)i.next();
    	  String headers = part.getHeaders();
    	  if (headers != null)
    	  {
            String contentId = Utils.getMimeHeaderAttribute(headers, MIMEConstants.HEADER_CONTENT_ID);
            if (start.equals(contentId))
            {
              root = part;
			  rootNotFound = false;
            }
    	  }
    	}
      }
    }
  	return root;
  }
  
  /**
   * Decodes the given encoded string.
   */
  public static byte[] decodeBase64(String str)
  {
  	try
  	{
    	sun.misc.BASE64Decoder decoder =  new sun.misc.BASE64Decoder();
  	    return decoder.decodeBuffer(str);
  	}
  	catch (Exception e)
  	{
  		return new byte[0];
  	}
  }

  /**
   * Encodes the given byte array.
   */
  public static String encodeBase64(byte[] buffer)
  {    
  	sun.misc.BASE64Encoder encoder =  new sun.misc.BASE64Encoder();
  	return encoder.encodeBuffer(buffer);  
  }

  public static MimeParts parseMultipartRelatedMessage(String message, String httpHeaders, String encoding)
  {
  	byte[] buffer = null;
  	try
	{ 
  	  buffer = message.getBytes(encoding);
	}
  	catch (Exception e)
	{
  		return null;
	}
  	return parseMultipartRelatedMessage(buffer, httpHeaders, encoding);
  }
  public static MimeParts parseMultipartRelatedMessage(byte[] message, String httpHeaders, String encoding)
  {
    MimeParts mimeParts = new MimePartsImpl();
    String boundary = Utils.getHttpHeaderSubAttribute(httpHeaders, HTTPConstants.HEADER_CONTENT_TYPE, "boundary");
    ArrayList parts = new ArrayList();
    
    if (boundary == null)
    {
    	// assume it is a simple SOAP message
    	return null;
    }
    else
    {
      String start = Utils.getHttpHeaderSubAttribute(httpHeaders, HTTPConstants.HEADER_CONTENT_TYPE, "start");
      int[] indices = Utils.getBoundaryIndices(message, boundary);
      boolean rootNotFound = true;
      
      for (int i= indices.length - 2; i>=0; i--)
      {
        try
    	{
          MimePart part = new MimePartImpl();
          int index = Utils.getFirstCRLFCRLF(message, indices[i]);
          if ((index > indices[i]) && (index < indices[i+1]))
          {
            // the boundary string & mime headers (include the trailing CRLF CRLF)
        	String str = new String(message, indices[i], (index - indices[i]), "US-ASCII");
        	String delimiter = str.substring(0, str.indexOf("\r\n", 2) + 2);

        	if (i == indices.length -2)
        	{
        	  String endDelimiter = new String(message, indices[i + 1], message.length - indices[i + 1], "US-ASCII");
        	  int j = str.indexOf("\r\n", 2);
        	  if (j != -1)
        	    endDelimiter = str.substring(0, str.indexOf("\r\n", 2) + 2);
              part.setBoundaryStrings(new String[]{delimiter, endDelimiter});
            }
        	else
        	  part.setBoundaryStrings(new String[]{delimiter});
       
        	// the headers
        	String headers = str.substring(delimiter.length());
            if (headers.startsWith("\r\n"))
            {
          	  // no headers present
          	  part.setHeaders("");
            }
            else
            {
          	  part.setHeaders(headers);
            }
            
            // the content
            String contentId = Utils.getMimeHeaderAttribute(headers, MIMEConstants.HEADER_CONTENT_ID);
            int size = indices[i+1] - (index);
         	byte[] content = new byte[size];
      	    System.arraycopy(message, index, content, 0, size);
      	  
            if ((rootNotFound && (i == 0)) ||
            	((start != null) && (!start.equals("")) && (start.equals(contentId))))
            {
              // root part -- do not encode
              part.setContent(new String(content, encoding));
              mimeParts.setRootPart(part);
            }
            else
            {
              String transferEncoding =  Utils.getMimeHeaderAttribute(headers, MIMEConstants.HEADER_CONTENT_TRANSFER_ENCODING);
   
              if ((transferEncoding != null) && transferEncoding.equalsIgnoreCase("base64"))
              	part.setContent(new String(content, encoding));
              else
                part.setContent(Utils.encodeBase64(content));
            }
           parts.add(part);
         }
    	}
    	catch (Exception e)
    	{
    	  return null;
    	}
      }
      int size = parts.size();
      for (int i = size-1; i>=0; i--)
         mimeParts.addPart((MimePart)parts.get(i));
    }
    return mimeParts;
  }

  public static String toXMLString(MimeParts mimeParts)
  {
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);

    // Add message content with attachments element
    pw.print("<" + WSIConstants.ELEM_MESSAGE_CONTENT_WITH_ATTACHMENTS);
    pw.print(">");

    Collection partList = mimeParts.getParts();
    if (!partList.isEmpty())
        {
         	Iterator iMimeParts = partList.iterator();
        	while (iMimeParts.hasNext())
            {
        	  MimePart mimePart = (MimePart)iMimeParts.next();
         	  pw.print(mimePart.toXMLString(""));
            }
        }

        // Add end message element
        pw.println("</" + WSIConstants.ELEM_MESSAGE_CONTENT_WITH_ATTACHMENTS + ">");
    // Return string
    return sw.toString();
  }

  public static void main (String[] args)
  {
  	try
	{
  	  FileInputStream inputStream = new FileInputStream("d:\\b.xml");
  	  int i = inputStream.available();
  	  byte[] buffer = new byte[i];
  	  inputStream.read(buffer);
  	  String message = new String(buffer);
  	  message = XMLUtils.xmlRemoveEscapedString(message);
  	  String headers = Utils.getHTTPHeaders(message);
  	  MimeParts parts = Utils.parseMultipartRelatedMessage(message, headers, Utils.JAVA_ENCODING_DEFAULT);
  	  System.out.println(Utils.toXMLString(parts));
	}
  	catch (Exception e){}
  }
}
