| /******************************************************************************* |
| * 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"; |
| |
| /* (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)) |
| { |
| 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(); |
| } |
| } |
| |
| } |