/*******************************************************************************
 * Copyright (c) 2001, 2007 IBM Corporation 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 Corporation - initial API and implementation
 * yyyymmdd bug      Email and other contact information
 * -------- -------- -----------------------------------------------------------
 * 20060504   119296 pmoogk@ca.ibm.com - Peter Moogk
 * 20060517   142324 rsinha@ca.ibm.com - Rupam Kuehner
 * 20060711   150301 pmoogk@ca.ibm.com - Peter Moogk
 * 20060818   154393 pmoogk@ca.ibm.com - Peter Moogk
 * 20060906   156420 pmoogk@ca.ibm.com - Peter Moogk
 *******************************************************************************/

package org.eclipse.wst.ws.internal.parser.wsil;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Hashtable;
import javax.wsdl.Definition;
import javax.wsdl.WSDLException;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.wsil.Abstract;
import org.apache.wsil.Description;
import org.apache.wsil.Inspection;
import org.apache.wsil.Link;
import org.apache.wsil.Service;
import org.apache.wsil.WSILConstants;
import org.apache.wsil.WSILDocument;
import org.apache.wsil.WSILException;
import org.apache.wsil.extension.ExtensionElement;
import org.apache.wsil.extension.uddi.ServiceDescription;
import org.apache.wsil.extension.uddi.UDDIConstants;
import org.apache.wsil.extension.wsdl.WSDLConstants;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.wst.ws.internal.parser.disco.DISCOContractReference;
import org.eclipse.wst.ws.internal.parser.disco.DISCOParser;
import org.eclipse.wst.ws.internal.parser.disco.DISCOReference;
import org.eclipse.wst.wsdl.WSDLPlugin;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import sun.misc.BASE64Encoder;

public class WebServicesParser
{
  public static final int PARSE_NONE = 0;
  public static final int PARSE_WSIL = 1<<0;
  public static final int PARSE_WSDL = 1<<1;
  public static final int PARSE_LINKS = 1<<2;
  public static final int PARSE_DISCO = 1<<3;

  private String uri_;
  private Hashtable uriToEntityTable_;

  private String httpBasicAuthUsername_;
  private String httpBasicAuthPassword_;

  public WebServicesParser()
  {
    this(null);
  }

  public WebServicesParser(String uri)
  {
    uri_ = uri;
    uriToEntityTable_ = new Hashtable();
    httpBasicAuthUsername_ = null;
    httpBasicAuthPassword_ = null;
  }

  public String getURI()
  {
    return uri_;
  }

  public void setURI(String uri)
  {
    uri_ = uri;
  }

  public WebServiceEntity getWebServiceEntityByURI(String uri)
  {
    if (uri != null)
      return (WebServiceEntity)uriToEntityTable_.get(uri);
    else
      return null;
  }

  /**
   * 
   * @param wsilURI
   * @return
   * @deprecated replaced with getWSILDocumentVerbose(String, String)
   */
  public WSILDocument getWSILDocument(String wsilURI )
  {
    try
    {
      return getWSILDocumentVerbose(wsilURI, "UTF-8" );
    }
    catch (Exception t)
    {
    }
    return null;
  }
  
  /**
   * 
   * @param wsilURI
   * @return
   * @throws MalformedURLException
   * @throws IOException
   * @throws WWWAuthenticationException
   * @throws WSILException
   * @deprecated replaced with getWSILDocumentVerbose(String, String)
   */
  public WSILDocument getWSILDocumentVerbose(String wsilURI ) throws MalformedURLException, IOException, WWWAuthenticationException, WSILException
  {
    return getWSILDocumentVerbose( wsilURI, "UTF-8" );
  }
  
  public WSILDocument getWSILDocumentVerbose(String wsilURI, String byteEncoding ) throws MalformedURLException, IOException, WWWAuthenticationException, WSILException
  {
    WebServiceEntity wsEntity = getWebServiceEntityByURI(wsilURI);
    
    if (wsEntity == null)
    {
      wsEntity = new WebServiceEntity();
      wsEntity.setURI(wsilURI);
      uriToEntityTable_.put(wsilURI, wsEntity);
    }
    
    WSILDocument wsilDocument = (WSILDocument)wsEntity.getModel();
    
    if (wsilDocument == null)
    {
      // For some reason WSDL4J is not reading the content type properly for platform resources.  Therefore, we will get
      // the stream directly from Eclipse if we find a platform protocol specified in the URL.
      if( wsilURI.startsWith( "platform:/resource" ) )
      {
        String    path     = wsilURI.substring(18);
        IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember( path );
        
        if( resource instanceof IFile )
        {
          try
          {
            IFile             file   = (IFile)resource;
            InputStream       stream = file.getContents();
            InputStreamReader reader = new InputStreamReader( stream, file.getCharset() );
          
            wsilDocument = WSILDocument.newInstance();
            wsilDocument.read( reader );
          }
          catch( CoreException exc ){}
        }
      }
      else
      {
        // TODO the following 3 lines of code should probably be removed, since
        // the WSDL4J parser does not need a byte stream.
        byte[] b = getInputStreamAsByteArray(wsilURI);
        wsEntity.setBytes(b);
        setHTTPSettings(wsEntity);
      
        // This parser only checks the header of HTML for a particular encoding.
        // It doesn't check the encoding for general XML documents like WSDL and WSIL.
        // This causing this parser to alway use UTF-8 as the encoding.  Therefore,
        // since we can not trust the encoding specified we will not use it.  Instead,
        // we will just let the WSIL parser figure out what encoding to use.
      
        //InputStreamReader isr = new InputStreamReader(new ByteArrayInputStream(b), byteEncoding );
        wsilDocument = WSILDocument.newInstance();
        wsilDocument.read(wsilURI);
      }
      
      wsEntity.setType(WebServiceEntity.TYPE_WSIL);
      wsEntity.setModel(wsilDocument);
    }
    return wsilDocument;
  }

  public Definition getWSDLDefinition(String wsdlURI)
  {
    try
    {
      return getWSDLDefinitionVerbose(wsdlURI);
    }
    catch (Exception t)
    {
    }
    return null;
  }

  public Definition getWSDLDefinitionVerbose(String wsdlURI) throws MalformedURLException, IOException, WWWAuthenticationException, WSDLException
  {
    WebServiceEntity wsEntity = getWebServiceEntityByURI(wsdlURI);
    if (wsEntity == null)
    {
      wsEntity = new WebServiceEntity();
      wsEntity.setURI(wsdlURI);
      uriToEntityTable_.put(wsdlURI, wsEntity);
    }
    Definition definition = (Definition)wsEntity.getModel();
    if (definition == null)
    {
      byte[] b = getInputStreamAsByteArray(wsdlURI);
      wsEntity.setBytes(b);
      setHTTPSettings(wsEntity);
      ByteArrayInputStream bais = new ByteArrayInputStream(b);
      WSDLFactory factory = WSDLPlugin.INSTANCE.createWSDL4JFactory();
      WSDLReader wsdlReader = factory.newWSDLReader();
      definition = wsdlReader.readWSDL(wsdlURI, new InputSource(bais));
      wsEntity.setType(WebServiceEntity.TYPE_WSDL);
      wsEntity.setModel(definition);
    }
    return definition;
  }

  public void parse() throws MalformedURLException, IOException, ParserConfigurationException, SAXException, WWWAuthenticationException
  {
    parseURL(PARSE_WSIL | PARSE_WSDL | PARSE_LINKS | PARSE_DISCO);
  }

  public void parse(int parseOption) throws MalformedURLException, IOException, ParserConfigurationException, SAXException, WWWAuthenticationException
  {
    parseURL(parseOption);
  }

  private void parseURL(int parseOption) throws MalformedURLException, IOException, ParserConfigurationException, SAXException, WWWAuthenticationException
  {
    WebServiceEntity wsEntity = new WebServiceEntity();
    
    // This variable makes this object a little more thread safe than it was
    // before, although this object is not completely thread safe.  The scenario
    // that we are trying to avoid is where one call to this method gets blocked
    // at the getInputStreamAsByteArray call.  Then a second call to the method
    // is made that changes the uri_ global variable.  When the first call
    // completes it would use uri_ value from the second invocation instead
    // of the value from the first.  Storing the uri_ into this variable helps 
    // avoid this bad scenario.
    String theUri = uri_;
    
    wsEntity.setURI(theUri);
    byte[] b = getInputStreamAsByteArray(theUri);
    wsEntity.setBytes(b);
    setHTTPSettings(wsEntity);
    uriToEntityTable_.put(theUri, wsEntity);
    // parse uri_ as a HTML document
    HTMLHeadHandler headHandler = new HTMLHeadHandler(theUri);
    byte[] head = headHandler.harvestHeadTags(b);
    String byteEncoding = headHandler.getByteEncoding();
    SAXParserFactory factory = SAXParserFactory.newInstance();
    factory.setNamespaceAware(false);
    factory.setValidating(false);
    SAXParser parser = factory.newSAXParser();
    try
    {
      ByteArrayInputStream bais = new ByteArrayInputStream(head);
      InputStreamReader isr = new InputStreamReader(bais, byteEncoding);
      InputSource is = new InputSource(isr);
      parser.parse(is, headHandler);
    }
    catch (Exception t)
    {
    }
    String[] wsilURIs = headHandler.getWsils();
    String[] discoURIs = headHandler.getDiscos();
    // true if uri_ is a HTML document
    if (wsilURIs.length > 0 || discoURIs.length > 0)
    {
      wsEntity.setType(WebServiceEntity.TYPE_HTML);
      for (int i = 0; i < wsilURIs.length; i++)
      {
        String absoluteURI = convertToAbsoluteURI(theUri, wsilURIs[i]);
        WebServiceEntity wsilEntity = new WebServiceEntity();
        wsilEntity.setType(WebServiceEntity.TYPE_WSIL);
        wsilEntity.setURI(absoluteURI);
        associate(wsEntity, wsilEntity);
        uriToEntityTable_.put(absoluteURI, wsilEntity);
        if ((parseOption | PARSE_WSIL) == parseOption)
        {
          try
          {
            parseWSIL(absoluteURI, parseOption, byteEncoding );
          }
          catch (Exception t)
          {
          }
        }
      }
      for (int i=0;i<discoURIs.length;i++)
      {
        WebServiceEntity discoEntity = new WebServiceEntity();
        discoEntity.setType(WebServiceEntity.TYPE_DISCO);
        discoEntity.setURI(discoURIs[i]);
        associate(wsEntity,discoEntity);
        uriToEntityTable_.put(discoURIs[i],discoEntity);
        if ((parseOption | PARSE_DISCO) == parseOption)
        {
          try
          {
            parseDISCO(discoURIs[i],parseOption);
          }
          catch (Exception t)
          {
          }
        }
      }
    }
    // false if uri_ is not a HTML document
    // then parse uri_ as a WSIL document
    else
    {
      try
      {
        parseWSIL(theUri, parseOption, byteEncoding );
        // no exception thrown if uri_ is a WSIL document
        wsEntity.setType(WebServiceEntity.TYPE_WSIL);
      }
      catch (Exception t)
      {
        // exception thrown if uri_ is not a WSIL document
        // then parse uri_ as a DISCO document.
        try
        {
          parseDISCO(theUri, parseOption);
          // no exception thrown if uri_ is a DISCO document
          wsEntity.setType(WebServiceEntity.TYPE_DISCO);
        }
        catch (Exception t2)
        {
          // exception thrown if uri_ is not a DISCO document
          // then parse uri_ as a WSDL document
          try
          {
            parseWSDL(theUri);
            // no exception thrown if uri_ is a WSDL document
            wsEntity.setType(WebServiceEntity.TYPE_WSDL);
          }
          catch (Exception t3)
          {
            // exception thrown if uri_ is not a WSDL document
            // then do nothing
          }
        }
      }
    }
  }

  private void parseWSIL(String wsilURI, int parseOption, String byteEncoding ) throws WSILException, MalformedURLException, IOException, WSDLException, WWWAuthenticationException
  {
    WebServiceEntity wsilEntity = getWebServiceEntityByURI(wsilURI);
    WSILDocument wsilDoc = (WSILDocument)wsilEntity.getModel();
    if (wsilDoc != null)
    {
      // Prevent infinite loops from occurring when a WSIL cycles occur.
      return;
    }
    wsilDoc = getWSILDocumentVerbose(wsilURI, byteEncoding );
    Inspection inspection = wsilDoc.getInspection();
    Service[] services = inspection.getServices();
    for (int i = 0; i < services.length; i++)
    {
      Description[] descs = services[i].getDescriptions();
      // Set the documentation to the <service> element's first abstract.
      String documentation = null;
      Abstract[] abstracts = services[i].getAbstracts();
      if (abstracts != null && abstracts.length > 0)
        documentation = abstracts[0].getText();
      for (int j = 0; j < descs.length; j++)
      {
      	String referencedNS = descs[j].getReferencedNamespace();
      	// If a <description> element contains an abstract, use it to override the service documentation.      	
      	abstracts = descs[j].getAbstracts();
      	if (abstracts != null && abstracts.length > 0)
      	  documentation = abstracts[0].getText();
        if (WSDLConstants.NS_URI_WSDL.equals(referencedNS))
        {
          String location = descs[j].getLocation();
          if (location != null && location.length() > 0)
          {
            String absoluteURI = convertToAbsoluteURI(wsilURI, location);
            WebServiceEntity wsdlEntity = new WebServiceEntity();
            wsdlEntity.setType(WebServiceEntity.TYPE_WSDL);
            wsdlEntity.setURI(absoluteURI);
            wsdlEntity.setDocumentation(documentation);
            associate(wsilEntity, wsdlEntity);
            uriToEntityTable_.put(absoluteURI, wsdlEntity);
            if ((parseOption | PARSE_WSDL) == parseOption)
              parseWSDL(absoluteURI);
          }
        }
        else if (UDDIConstants.NS_URI_UDDI_V2.equals(referencedNS))
        {
          ExtensionElement ee = descs[j].getExtensionElement();
          if (ee instanceof ServiceDescription)
          {
            ServiceDescription sd = (ServiceDescription)ee;
            String inquiryURL = sd.getLocation();
            String serviceKey = sd.getServiceKey().getText();
            WebServiceEntity uddiServiceEntity = new WebServiceEntity();
            uddiServiceEntity.setType(WebServiceEntity.TYPE_UDDI_SERVICE);
            String uddiServiceKeyURI = UDDIURIHelper.getServiceKeyURI(serviceKey,inquiryURL);
            uddiServiceEntity.setURI(uddiServiceKeyURI);
            uddiServiceEntity.setDocumentation(documentation);
            associate(wsilEntity,uddiServiceEntity);
            uriToEntityTable_.put(uddiServiceKeyURI,uddiServiceEntity);
            // TODO: parse WSDL if necessary...
          }
        }
      }
    }
    Link[] links = inspection.getLinks();    
    for (int i = 0; i < links.length; i++)
    {
      if (WSILConstants.NS_URI_WSIL.equals(links[i].getReferencedNamespace()))
      {
        String documentation = null;
        Abstract[] abstracts = links[i].getAbstracts();
        if (abstracts != null && abstracts.length > 0)
          documentation = abstracts[0].getText();
        String linkLocation = links[i].getLocation();
        String absoluteURI = convertToAbsoluteURI(wsilURI, linkLocation);
        // Prevent cycles.
        WebServiceEntity wsilLinkEntity = getWebServiceEntityByURI(absoluteURI);
        if (wsilLinkEntity == null)
        {
          wsilLinkEntity = new WebServiceEntity();
          wsilLinkEntity.setType(WebServiceEntity.TYPE_WSIL);
          wsilLinkEntity.setURI(absoluteURI);
          wsilLinkEntity.setDocumentation(documentation);
          uriToEntityTable_.put(absoluteURI, wsilLinkEntity);
          if ((parseOption | PARSE_LINKS) == parseOption)
            parseWSIL(absoluteURI, parseOption, byteEncoding );
        }
        associate(wsilEntity,wsilLinkEntity);
      }
    }
  }
  
  private void parseDISCO(String discoURI, int parseOption) throws MalformedURLException, WWWAuthenticationException, Exception
  {
    WebServiceEntity discoEntity = getWebServiceEntityByURI(discoURI);
    byte[] b = getInputStreamAsByteArray(discoURI);
    discoEntity.setBytes(b);
    setHTTPSettings(discoEntity);
    ByteArrayInputStream bais = new ByteArrayInputStream(b);
    DISCOParser parser = new DISCOParser();
    DISCOReference[] references = parser.parse(discoURI,new InputSource(bais));
    if (references != null && references.length > 0)
    {
      for (int i=0;i<references.length;i++)
      {
        if (references[i] instanceof DISCOContractReference)
        {
          // contractRef
          DISCOContractReference reference = (DISCOContractReference)references[i];
          String ref = reference.getRef();
          String docRef = reference.getDocRef();
          WebServiceEntity wsdlEntity = new WebServiceEntity();
          wsdlEntity.setType(WebServiceEntity.TYPE_WSDL);
          wsdlEntity.setURI(ref);
          wsdlEntity.setDocumentation(docRef);
          associate(discoEntity,wsdlEntity);
          uriToEntityTable_.put(ref,wsdlEntity);
          if ((parseOption | PARSE_WSDL) == parseOption)
            parseWSDL(ref);
        }
        else
        {
          // discoveryRef
          String ref = references[i].getRef();
          // Prevent cycles.
          WebServiceEntity discoLinkEntity = getWebServiceEntityByURI(ref);
          if (discoLinkEntity == null)
          {
            discoLinkEntity = new WebServiceEntity();
            discoLinkEntity.setType(WebServiceEntity.TYPE_DISCO);
            discoLinkEntity.setURI(ref);
            uriToEntityTable_.put(ref,discoLinkEntity);
            if ((parseOption | PARSE_LINKS) == parseOption)
              parseDISCO(ref,parseOption);
          }
          associate(discoEntity,discoLinkEntity);
        }
      }
    }
  }

  private Definition parseWSDL(String wsdlURI) throws WSDLException, MalformedURLException, IOException, WWWAuthenticationException
  {
    return getWSDLDefinitionVerbose(wsdlURI);
  }

  private byte[] getInputStreamAsByteArray(String uriString) throws MalformedURLException, IOException, WWWAuthenticationException
  {
    // Try to get a cached copy of the byte[]
    WebServiceEntity wsEntity = getWebServiceEntityByURI(uriString);
    if (wsEntity != null)
    {
      byte[] bytes = wsEntity.getBytes();
      if (bytes != null)
        return bytes;
    }
    // Get the byte[] by opening a stream to the URI
    URL url = createURL(uriString);
    URLConnection conn = url.openConnection();
    // proxy server setting
    String proxyUserName = System.getProperty("http.proxyUserName");
    String proxyPassword = System.getProperty("http.proxyPassword");
    if (proxyUserName != null && proxyPassword != null)
    {
      StringBuffer userNamePassword = new StringBuffer(proxyUserName);
      userNamePassword.append(':').append(proxyPassword);
      BASE64Encoder encoder = new BASE64Encoder();
      String encoding = encoder.encode(userNamePassword.toString().getBytes());
      userNamePassword.setLength(0);
      userNamePassword.append("Basic ").append(encoding);
      conn.setRequestProperty("Proxy-authorization", userNamePassword.toString());
    }
    // HTTP basic authentication setting
    if (httpBasicAuthUsername_ != null && httpBasicAuthPassword_ != null)
    {
      StringBuffer sb = new StringBuffer(httpBasicAuthUsername_);
      sb.append(':').append(httpBasicAuthPassword_);
      BASE64Encoder encoder = new BASE64Encoder();
      String encoding = encoder.encode(sb.toString().getBytes());
      sb.setLength(0);
      sb.append("Basic ").append(encoding);
      conn.setRequestProperty("Authorization", sb.toString());
    }
    InputStream is = null;
    try
    {
      is = conn.getInputStream();
      String wwwAuthMsg = conn.getHeaderField("WWW-Authenticate");
      if (wwwAuthMsg != null)
        throw new WWWAuthenticationException(new IOException(), wwwAuthMsg, uriString);
    }
    catch (IOException ioe)
    {
      String wwwAuthMsg = conn.getHeaderField("WWW-Authenticate");
      if (wwwAuthMsg != null)
        throw new WWWAuthenticationException(ioe, wwwAuthMsg, uriString);
      else
        throw ioe;
    }
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] b = new byte[1024];
    int byteRead = is.read(b);
    while (byteRead != -1)
    {
      baos.write(b, 0, byteRead);
      byteRead = is.read(b);
    }
    is.close();
    return baos.toByteArray();
  }

  protected URL createURL(String url) throws MalformedURLException
  {
    return new URL(url);
  }

  private void associate(WebServiceEntity parent, WebServiceEntity child)
  {
    parent.addChild(child);
    child.setParent(parent);
  }

  private String convertToAbsoluteURI(String baseURI,String refURI)
  {
    if (refURI != null && refURI.indexOf(":") < 0)
    {
      StringBuffer absoluteURI = new StringBuffer(baseURI.substring(0,Math.max(baseURI.lastIndexOf('\\'),baseURI.lastIndexOf('/')+1)));
      absoluteURI.append(refURI);
      return absoluteURI.toString();
    }
    return refURI;
  }

  private void setHTTPSettings(WebServiceEntity entity)
  {
    if (httpBasicAuthUsername_ != null && httpBasicAuthPassword_ != null)
    {
      entity.setHTTPUsername(httpBasicAuthUsername_);
      entity.setHTTPPassword(httpBasicAuthPassword_);
    }
  }

  public String getHTTPBasicAuthUsername()
  {
    return httpBasicAuthUsername_;
  }

  public void setHTTPBasicAuthUsername(String username)
  {
    httpBasicAuthUsername_ = username;
  }

  public String getHTTPBasicAuthPassword()
  {
    return httpBasicAuthPassword_;
  }

  public void setHTTPBasicAuthPassword(String password)
  {
    httpBasicAuthPassword_ = password;
  }
}
