blob: 9aa2fea74bcd930a50a82e73bad7d63b390cbd76 [file] [log] [blame]
/*******************************************************************************
* 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.commons.codec.binary.Base64;
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;
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);
Base64 encoder = new Base64();
String encoding = new String(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_);
Base64 encoder = new Base64();
String encoding = new String(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;
}
}