blob: 83d886c2c08e1be0c027eb895a2f92ceafaa7b9e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2002-2005 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 - Initial API and implementation
*******************************************************************************/
package org.eclipse.wst.wsi.internal.core.profile.validator.impl.wsdl;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import javax.wsdl.Definition;
import javax.wsdl.Types;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.UnknownExtensibilityElement;
import org.eclipse.wst.wsi.internal.core.WSIException;
import org.eclipse.wst.wsi.internal.core.WSITag;
import org.eclipse.wst.wsi.internal.core.profile.TestAssertion;
import org.eclipse.wst.wsi.internal.core.profile.validator.EntryContext;
import org.eclipse.wst.wsi.internal.core.profile.validator.impl.AssertionProcess;
import org.eclipse.wst.wsi.internal.core.report.AssertionResult;
import org.eclipse.wst.wsi.internal.core.util.ErrorList;
import org.eclipse.wst.wsi.internal.core.util.StringTokenizer;
import org.eclipse.wst.wsi.internal.core.xml.XMLUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* BP2202.
* <context>For a candidate wsdl:types element within a WSDL document which imports an XML schema directly or indirectly.</context>
* <assertionDescription>The imported schema uses UTF-8 or UTF-16 for the encoding.</assertionDescription>
*/
public class BP2202 extends AssertionProcess implements WSITag
{
private final WSDLValidatorImpl validator;
/**
* @param WSDLValidatorImpl
*/
public BP2202(WSDLValidatorImpl impl)
{
super(impl);
this.validator = impl;
}
private ErrorList errors = new ErrorList();
private boolean importFound = false;
private final char[] OMMITED_XML_DECLARATION_DELIMITERS =
new char[] { 0x20, 0x9, 0xD, 0xA, '\'', '\"' };
private final char[] XML_DECLARATION_DELIMITERS = new char[] { '=' };
private final String UTF_8_ENCODING = "UTF-8";
private final String UTF_16_ENCODING = "UTF-16";
private final String ENCODING_TOKEN = "encoding";
private final String VERSION_TOKEN = "version";
/* (non-Javadoc)
* @see org.wsi.test.profile.validator.impl.BaseValidatorImpl.AssertionProcess#validate(org.wsi.test.profile.TestAssertion, org.wsi.test.profile.validator.EntryContext)
*/
public AssertionResult validate(
TestAssertion testAssertion,
EntryContext entryContext)
throws WSIException
{
result = result = AssertionResult.RESULT_NOT_APPLICABLE;
//Definition def = (Definition) entryContext.getEntry().getEntryDetail();
Types types = (Types) entryContext.getEntry().getEntryDetail();
List exts = null;
//if (def.getTypes() != null)
if (types != null)
//exts = def.getTypes().getExtensibilityElements();
exts = types.getExtensibilityElements();
if (exts != null)
{
Definition definition = null;
if ((definition =
validator.analyzerContext.getCandidateInfo().getDefinition(types))
== null)
{
throw new WSIException("Could not find types definition in any WSDL document.");
}
Iterator it = exts.iterator();
while (it.hasNext())
{
ExtensibilityElement el = (ExtensibilityElement) it.next();
if (el instanceof UnknownExtensibilityElement
&& el.getElementType().equals(ELEM_XSD_SCHEMA))
searchForSchema(((UnknownExtensibilityElement) el).getElement(),
definition.getDocumentBaseURI());
}
}
if (!errors.isEmpty())
{
result = AssertionResult.RESULT_FAILED;
failureDetail = this.validator.createFailureDetail(errors.toString(), entryContext);
}
else if (!importFound)
result = AssertionResult.RESULT_NOT_APPLICABLE;
else
result = AssertionResult.RESULT_PASSED;
return validator.createAssertionResult(testAssertion, result, failureDetail);
}
/*
* Search xsd schema or xsd import from node. If node is xsd import it's loading schema.
* @param n - node
*/
private void searchForSchema(Node n, String context)
{
while (n != null)
{
// searches for xsd:import element
if (Node.ELEMENT_NODE == n.getNodeType())
{
// if xsd:schema element is found -> process schema
if (XMLUtils.equals(n, ELEM_XSD_SCHEMA))
{
processSchema(n, context);
}
else
{
// if xsd:import element is found -> load schema and process schema
if (XMLUtils.equals(n, ELEM_XSD_IMPORT))
{
importFound = true;
loadSchema(n, context);
}
else
// else iterate element recursively
searchForSchema(n.getFirstChild(), context);
}
}
n = n.getNextSibling();
}
}
/*
* It loads xsd schema and then check valid encoding and looking for xsd:schema element for next process.
* @param importNode - xsd schema
*/
private void loadSchema(Node importNode, String context)
{
Element im = (Element) importNode;
Attr schemaLocation = XMLUtils.getAttribute(im, ATTR_XSD_SCHEMALOCATION);
// try to parse imported XSD
if (schemaLocation != null && schemaLocation.getValue() != null)
try
{
// if any error or root element is not XSD schema -> error
String decl =
readXMLDeclarationStatement(schemaLocation.getValue(), context);
if (!validDeclaration(decl,
ENCODING_TOKEN,
new String[] { UTF_8_ENCODING, UTF_16_ENCODING }))
{
Attr a = XMLUtils.getAttribute(im, ATTR_XSD_NAMESPACE);
errors.add((a != null) ? a.getValue() : "");
}
if (!validDeclaration(decl, "version", new String[] { "1.0" }))
{
errors.add(
"Version number in XML declaration is not 1.0. XML schema file: "
+ schemaLocation.getValue());
}
// DEBUG:
// System.out.println(schemaLocation.getValue() + ":" + context);
Document schema =
validator.parseXMLDocumentURL(schemaLocation.getValue(), context);
if (XMLUtils.equals(schema.getDocumentElement(), ELEM_XSD_SCHEMA))
{
Attr a = XMLUtils.getAttribute(im, ATTR_XSD_NAMESPACE);
String namespace = (a != null) ? a.getValue() : "";
processSchema(schema.getDocumentElement(),
XMLUtils.createURLString(schemaLocation.getValue(), context));
}
result = result = AssertionResult.RESULT_PASSED;
}
catch (Throwable t)
{
}
}
/**
* Reads an XML declaration statement.
* @param location
* @return String
*/
private String readXMLDeclarationStatement(String location, String baseURI)
{
String result = null;
try
{
new URL(location);
}
catch (Throwable t)
{
// nothing
int i = baseURI.lastIndexOf('/');
int j = baseURI.lastIndexOf('\\');
if (j > i)
i = j;
location = baseURI.substring(0, i + 1) + location;
}
if (location != null)
{
URL url = null;
Reader reader = null;
try
{
try
{
url = new URL(location);
}
catch (MalformedURLException e)
{
// we should try to access location as file
}
if (url != null)
{
reader = new InputStreamReader(url.openStream());
}
else
{
reader = new InputStreamReader(new FileInputStream(location));
}
int charCode;
boolean end = false;
if (reader.ready())
{
charCode = reader.read();
while (reader.ready() && !(charCode == '<'))
{
charCode = reader.read();
}
StringBuffer buf = new StringBuffer();
if (charCode == '<')
{
buf.append((char) charCode);
while (reader.ready() && !end)
{
charCode = reader.read();
buf.append((char) charCode);
end = charCode == '>';
}
}
else
{
// NOTE: This result does not get propogated back!
result = AssertionResult.RESULT_FAILED;
failureDetailMessage =
"Cannot read the XML declaration statement.";
}
result = buf.toString();
}
}
catch (Exception e)
{
errors.add(e.getMessage());
}
finally
{
if (reader != null)
{
try
{
reader.close();
}
catch (Throwable e)
{
}
}
}
}
return result;
}
/*
* @param xmlDecl - xml declaration
* @return if xml declaration contains encoding="utf-16" or encoding="utf-8" it retirns true.
*/
private boolean validEncoding(String xmlDecl)
{
//boolean result = false;
boolean result = true;
if (xmlDecl != null)
{
StringTokenizer st =
new StringTokenizer(
OMMITED_XML_DECLARATION_DELIMITERS,
XML_DECLARATION_DELIMITERS);
Enumeration tokens = st.parse(xmlDecl);
boolean found = false;
while (tokens.hasMoreElements() && !found)
{
String token = (String) tokens.nextElement();
if (token.equals(ENCODING_TOKEN))
{
found = true;
tokens.nextElement();
String enc = (String) tokens.nextElement();
result =
UTF_8_ENCODING.equalsIgnoreCase(enc)
|| UTF_16_ENCODING.equalsIgnoreCase(enc);
}
}
}
return result;
}
/**
* @param xmlDecl - xml declaration
* @return if xml declaration contains valid version number then true is returned.
*/
private boolean validDeclaration(
String xmlDecl,
String tokenName,
String[] checkValueList)
{
//boolean result = false;
boolean result = true;
if (xmlDecl != null)
{
StringTokenizer st =
new StringTokenizer(
OMMITED_XML_DECLARATION_DELIMITERS,
XML_DECLARATION_DELIMITERS);
Enumeration tokens = st.parse(xmlDecl);
if (tokens.hasMoreElements())
{
boolean found = false;
while (tokens.hasMoreElements() && !found)
{
String token = (String) tokens.nextElement();
if (token.equals(tokenName))
{
found = true;
result = false;
tokens.nextElement();
String tokenValue = (String) tokens.nextElement();
for (int i = 0; i < checkValueList.length && !result; i++)
{
if (checkValueList[i].equalsIgnoreCase(tokenValue))
result = true;
}
}
}
}
// If there are no tokens then it is not a valid declaraction
else
{
result = false;
}
}
return result;
}
/*
* It's looking for xsd import and load it if find.
* @param schema - xsd schema
* @param namespace - namespace of schema
*/
private void processSchema(Node schema, String context)
{
Node n = schema.getFirstChild();
while (n != null)
{
if (Node.ELEMENT_NODE == n.getNodeType()
&& XMLUtils.equals(n, ELEM_XSD_IMPORT))
{
importFound = true;
loadSchema(n, context);
}
n = n.getNextSibling();
}
}
}