blob: 9580b63138bcbaa6a3e6047466adc76f8a7a66cf [file] [log] [blame]
/*******************************************************************************
* 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)
{
//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();
}
}