| /******************************************************************************* |
| * Copyright (c) 2001, 2004 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 |
| *******************************************************************************/ |
| |
| package org.eclipse.wst.wsdl.validation.internal; |
| |
| import java.io.BufferedReader; |
| import java.io.ByteArrayInputStream; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.ResourceBundle; |
| |
| import org.apache.xerces.impl.XMLErrorReporter; |
| import org.apache.xerces.parsers.DOMParser; |
| import org.apache.xerces.parsers.StandardParserConfiguration; |
| import org.apache.xerces.xni.XNIException; |
| import org.eclipse.wst.wsdl.validation.internal.exception.ValidateWSDLException; |
| import org.eclipse.wst.wsdl.validation.internal.resolver.URIResolver; |
| import org.eclipse.wst.wsdl.validation.internal.util.MessageGenerator; |
| import org.eclipse.wst.wsdl.validation.internal.xml.AbstractXMLConformanceFactory; |
| import org.eclipse.wst.wsdl.validation.internal.xml.DefaultXMLValidator; |
| import org.eclipse.wst.wsdl.validation.internal.xml.IXMLValidator; |
| import org.eclipse.wst.wsdl.validation.internal.xml.LineNumberDOMParser; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.xml.sax.InputSource; |
| |
| /** |
| * This is the main entrypoint to the WSDL Validator. The controller is |
| * responsible for calling the reader, the XML conformance check, the WSDL |
| * validation and the WS-I validation if selected. The controller contains any |
| * errors and warnings generated as well. |
| */ |
| public class ValidationController |
| { |
| protected final String _ERROR_PROBLEM_WSDL_VALIDATOR = "_ERROR_PROBLEM_WSDL_VALIDATOR"; |
| protected final String _ERROR_NO_WSDL_VALIDATOR = "_ERROR_NO_WSDL_VALIDATOR"; |
| protected final String _ERROR_PROBLEM_EXT_VALIDATOR = "_ERROR_PROBLEM_EXT_VALIDATOR"; |
| |
| protected ValidatorRegistry ver; |
| protected ResourceBundle resourcebundle; |
| protected MessageGenerator messagegenerator; |
| protected URIResolver uriResolver; |
| protected Hashtable attributes = new Hashtable(); |
| |
| //protected String wsdlNamespace = null; |
| |
| /** |
| * The ResourceBundle needs to be set so it can be passed to the reader. |
| * |
| * @param rb |
| * The resource bundle for this validator. |
| */ |
| public ValidationController(ResourceBundle rb, URIResolver uriResolver) |
| { |
| resourcebundle = rb; |
| messagegenerator = new MessageGenerator(resourcebundle); |
| this.uriResolver = uriResolver; |
| |
| ver = ValidatorRegistry.getInstance(); |
| } |
| |
| /** |
| * Add the attributes specified to the validation. |
| * |
| * @param attributes The attributes to add to the validation. |
| */ |
| public void setAttributes(Hashtable attributes) |
| { |
| this.attributes.putAll(attributes); |
| } |
| |
| /** |
| * Validate the WSDL file. Check the file for XML conformance. If it is XML |
| * conformant, read the file and check it for WSDL conformance. If it is WSDL |
| * conformant and WS-I conformance is set to suggest or require, check the |
| * file for WS-I conformance. |
| * |
| * @param uri |
| * The uri where the WSDL document is located. |
| * @param wsiLevel |
| * The level of WS-I conformance to use for validation. |
| * @return A validation report with the validation info for the file. |
| */ |
| // public IValidationReport validate(String uri) |
| // { return validate(uri, null); |
| // } |
| |
| /** |
| * Validate the WSDL file with the stream. This method will run the check of the |
| * WSDL document. The validation is broken up into three stages: XML conformance, |
| * WSDL semantic, and post validation. |
| * |
| * @param uri The URI of the WSDL document to be validated. |
| * @param inputStream The contents of the WSDL document to be validated. |
| * @return A validation report with the validation info for the file. |
| */ |
| public IValidationReport validate(String uri, InputStream inputStream) |
| { |
| |
| InputStream xmlValidateStream = null; |
| InputStream wsdlValidateStream = null; |
| if (inputStream != null) |
| { //copy the inputStream so we can use it more than once |
| String contents = createStringForInputStream(inputStream); |
| xmlValidateStream = new ByteArrayInputStream(contents.getBytes()); |
| wsdlValidateStream = new ByteArrayInputStream(contents.getBytes()); |
| } |
| |
| ControllerValidationInfo valInfo = new ValidationInfoImpl(uri, messagegenerator); |
| ((ValidationInfoImpl)valInfo).setURIResolver(uriResolver); |
| ((ValidationInfoImpl)valInfo).setAttributes(attributes); |
| |
| if (validateXML(valInfo, xmlValidateStream)) |
| { |
| Document wsdldoc = getDocument(uri, wsdlValidateStream); |
| String wsdlns = getWSDLNamespace(wsdldoc); |
| if (validateWSDL(wsdldoc, valInfo, wsdlns)) |
| { |
| validateExtensionValidators(wsdldoc, valInfo, wsdlns); |
| } |
| } |
| return (IValidationReport)valInfo; |
| } |
| |
| /** |
| * Validate the file for XML conformance. |
| * @param valInfo information about the validation |
| * @param inputStream the inputStream to validate |
| * @return True if the file is conformant, false otherwise. |
| */ |
| protected boolean validateXML(ControllerValidationInfo valInfo, InputStream inputStream) |
| { |
| IXMLValidator xmlValidator = AbstractXMLConformanceFactory.getInstance().getXMLValidator(); |
| xmlValidator.setURIResolver(uriResolver); |
| xmlValidator.setFile(valInfo.getFileURI()); |
| if (xmlValidator instanceof DefaultXMLValidator) |
| { |
| ((DefaultXMLValidator)xmlValidator).setInputStream(inputStream); |
| } |
| //xmlValidator.setValidationInfo(valInfo); |
| xmlValidator.run(); |
| // if there are no xml conformance problems go on to check the wsdl stuff |
| if (xmlValidator.hasErrors()) |
| { |
| // temp handling of XML errors until validator is updated. |
| List errors = xmlValidator.getErrors(); |
| Iterator errorsIter = errors.iterator(); |
| while (errorsIter.hasNext()) |
| { |
| IValidationMessage valMes = (IValidationMessage)errorsIter.next(); |
| |
| if (valMes instanceof ValidationMessageImpl && valInfo instanceof ValidationInfoImpl) |
| { String errorKey = ((ValidationMessageImpl)valMes).getErrorKey(); |
| Object[] messageArgs = ((ValidationMessageImpl)valMes).getMessageArguments(); |
| ((ValidationInfoImpl)valInfo).addError(valMes.getMessage(), valMes.getLine(), valMes.getColumn(), valMes.getURI(), errorKey, messageArgs); |
| } |
| else |
| { |
| valInfo.addError(valMes.getMessage(), valMes.getLine(), valMes.getColumn(), valMes.getURI()); |
| } |
| } |
| return false; |
| } |
| //wsdlNamespace = xmlValidator.getWSDLNamespace(); |
| return true; |
| } |
| |
| /** |
| * Validate the file for XML conformance. |
| * @param valInfo information about the validation |
| * @return True if the file is conformant, false otherwise. |
| */ |
| protected boolean validateXML(ControllerValidationInfo valInfo) |
| { return validateXML(valInfo, null); |
| } |
| |
| /** |
| * Validate the WSDL file. Set the errors and warning appropriately. |
| * |
| * @param wsdldoc A W3C document representation of the WSDL document. |
| * @param valInfo The current validation information. |
| * @param wsdlNamespace The WSDL namespace to validate. |
| * @return True if the file is valid, false otherwise. |
| */ |
| protected boolean validateWSDL(Document wsdldoc, ControllerValidationInfo valInfo, String wsdlNamespace) |
| { |
| WSDLValidatorDelegate[] wsdlVals = ver.queryValidatorRegistry(wsdlNamespace, ValidatorRegistry.WSDL_VALIDATOR); |
| if (wsdlVals != null) |
| { |
| for (int i = 0; i < wsdlVals.length; i++) |
| { |
| WSDLValidatorDelegate wsdlvaldel = wsdlVals[i]; |
| IWSDLValidator wsdlVal = wsdlvaldel.getValidator(); |
| |
| // If the wsdl validator isn't null, validate. |
| if (wsdlVal != null) |
| { |
| try |
| { |
| wsdlVal.validate(wsdldoc, valInfo); |
| } |
| catch (ValidateWSDLException e) |
| { |
| valInfo.addError(messagegenerator.getString(_ERROR_PROBLEM_WSDL_VALIDATOR, wsdlNamespace), 1, 1, valInfo.getFileURI()); |
| } |
| } |
| // If the validator is null and the namespace isn't create an error. |
| // If the namespace is null the file is empty (and the XML validator |
| // has let it go) |
| // so it is valid but does not need to be validated. |
| else |
| { |
| valInfo.addError( |
| messagegenerator.getString(_ERROR_NO_WSDL_VALIDATOR, wsdlNamespace), |
| 1, |
| 1, |
| valInfo.getFileURI()); |
| } |
| } |
| } |
| // No validators registered. |
| else |
| { |
| valInfo.addError(messagegenerator.getString(_ERROR_NO_WSDL_VALIDATOR, wsdlNamespace), 1, 1, valInfo.getFileURI()); |
| } |
| valInfo.completeWSDLValidation(); |
| |
| return valInfo.isWSDLValid(); |
| } |
| |
| /** |
| * Validate the WSDL file with the extension validator. Set the errors and warning appropriately. |
| * |
| * @param wsdldoc A W3C document representation of the WSDL document. |
| * @param valInfo The current validation information. |
| * @param wsdlNamespace The WSDL namespace to validate. |
| * @return True if the file is valid, false otherwise. |
| */ |
| protected void validateExtensionValidators(Document wsdldoc, ControllerValidationInfo valInfo, String wsdlNamespace) |
| { |
| WSDLValidatorDelegate[] extVals = ver.queryValidatorRegistry(wsdlNamespace, ValidatorRegistry.EXT_VALIDATOR); |
| if(extVals != null) |
| { |
| int numvals = extVals.length; |
| for(int i = 0; i < numvals; i++) |
| { |
| WSDLValidatorDelegate extvaldel = extVals[i]; |
| IWSDLValidator extval = extvaldel.getValidator(); |
| if(extval != null) |
| { |
| try |
| { |
| extval.validate(wsdldoc, valInfo); |
| } |
| catch(Throwable t) |
| { |
| valInfo.addWarning(messagegenerator.getString(_ERROR_PROBLEM_EXT_VALIDATOR, extvaldel.getValidatorClassName(), wsdlNamespace), 1, 1, valInfo.getFileURI()); |
| // This error should be logged and not displayed to the user. |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Set the ResourceBundle for this ValidatorManager. |
| * |
| * @param rb |
| * The resource bundle to set. |
| * @see #getResourceBundle |
| */ |
| public void setResourceBundle(ResourceBundle rb) |
| { |
| resourcebundle = rb; |
| } |
| |
| /** |
| * Get the ResourceBundle for this ValidationController. |
| * |
| * @return The resource bundle set for this ValidationController. |
| * @see #setResourceBundle |
| */ |
| public ResourceBundle getResourceBundle() |
| { |
| return resourcebundle; |
| } |
| |
| /** |
| * Get a DOM document representation of the WSDL document. |
| * |
| * @param uri The uri of the file to read |
| * @return The DOM model of the WSDL document or null if the document can't be read. |
| */ |
| private Document getDocument(String uri, InputStream inputStream) |
| { |
| try |
| { |
| // Catch a premature EOF error to allow empty WSDL files to be considered valid. |
| StandardParserConfiguration configuration = new StandardParserConfiguration() |
| { |
| protected XMLErrorReporter createErrorReporter() |
| { |
| return new XMLErrorReporter() |
| { |
| public void reportError(String domain, String key, Object[] arguments, short severity) throws XNIException |
| { |
| boolean reportError = true; |
| if (key.equals("PrematureEOF")) |
| { |
| reportError = false; |
| } |
| |
| if (reportError) |
| { |
| super.reportError(domain, key, arguments, severity); |
| } |
| } |
| }; |
| } |
| }; |
| |
| InputSource inputSource = null; |
| if (inputStream != null) |
| { //then we want to create a DOM from the inputstream |
| inputSource = new InputSource(inputStream); |
| } |
| else |
| { inputSource = new InputSource(uri); |
| } |
| |
| DOMParser builder = new LineNumberDOMParser(configuration); |
| builder.parse(inputSource); |
| Document doc = builder.getDocument(); |
| |
| return doc; |
| } |
| catch (Throwable t) |
| { |
| // TODO: Log error if the parser fails to read the WSDL document. |
| // In this case the validator will fail with an unexplained error message |
| // about a null WSDL namespace. This error should be addressed as well. |
| System.out.println(t); |
| } |
| return null; |
| } |
| |
| private String getWSDLNamespace(Document doc) |
| { |
| String wsdlns = null; |
| if(doc != null) |
| { |
| Element definitions = doc.getDocumentElement(); |
| if(definitions.getLocalName().equals("definitions")) |
| { |
| wsdlns = definitions.getNamespaceURI(); |
| } |
| } |
| return wsdlns; |
| } |
| |
| |
| |
| private final String createStringForInputStream(InputStream inputStream) |
| { |
| // Here we are reading the file and storing to a stringbuffer. |
| StringBuffer fileString = new StringBuffer(); |
| try |
| { |
| InputStreamReader inputReader = new InputStreamReader(inputStream); |
| BufferedReader reader = new BufferedReader(inputReader); |
| char[] chars = new char[1024]; |
| int numberRead = reader.read(chars); |
| while (numberRead != -1) |
| { |
| fileString.append(chars, 0, numberRead); |
| numberRead = reader.read(chars); |
| } |
| } |
| catch (Exception e) |
| { |
| //TODO: log error message |
| //e.printStackTrace(); |
| } |
| return fileString.toString(); |
| } |
| |
| } |