/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.test.ws.tools.validation;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import org.jboss.logging.Logger;
import org.jboss.ws.Constants;
import org.jboss.ws.metadata.wsdl.Extendable;
import org.jboss.ws.metadata.wsdl.WSDLBinding;
import org.jboss.ws.metadata.wsdl.WSDLBindingOperation;
import org.jboss.ws.metadata.wsdl.WSDLBindingOperationInput;
import org.jboss.ws.metadata.wsdl.WSDLBindingOperationOutput;
import org.jboss.ws.metadata.wsdl.WSDLDefinitions;
import org.jboss.ws.metadata.wsdl.WSDLEndpoint;
import org.jboss.ws.metadata.wsdl.WSDLExtensibilityElement;
import org.jboss.ws.metadata.wsdl.WSDLInterface;
import org.jboss.ws.metadata.wsdl.WSDLInterfaceOperation;
import org.jboss.ws.metadata.wsdl.WSDLInterfaceOperationInfault;
import org.jboss.ws.metadata.wsdl.WSDLInterfaceOperationInput;
import org.jboss.ws.metadata.wsdl.WSDLInterfaceOperationOutfault;
import org.jboss.ws.metadata.wsdl.WSDLInterfaceOperationOutput;
import org.jboss.ws.metadata.wsdl.WSDLProperty;
import org.jboss.ws.metadata.wsdl.WSDLService;
import org.jboss.ws.tools.exceptions.JBossWSToolsException;
import org.jboss.wsf.common.DOMUtils;
import org.w3c.dom.Element;
/**
* WSDL Validator Helper class
* @author <mailto:Anil.Saldhana@jboss.org>Anil Saldhana
* @since August 1, 2005
*/
public class WSDLValidationHelper
{
private final static Logger log = Logger.getLogger(WSDLValidationHelper.class);
/**
* Validate the WSDLBinding objects
* @param w1 WSDLDefinitions object for the first wsdl
* @param w2 WSDLDefinition object for the second wsdl
* @return true - if match, false - otherwise
* @throws JBossWSToolsException
*/
public static boolean validateBindings(WSDLDefinitions w1, WSDLDefinitions w2)
throws JBossWSToolsException
{ boolean bool = true;
WSDLBinding[] bindings1 = w1.getBindings();
WSDLBinding[] bindings2 = w2.getBindings();
if (bindings1 == null || bindings1.length == 0)
{
throw new JBossWSToolsException("bindings in first wsdl cannot be null");
}
if(bindings2 == null || bindings2.length == 0)
{
throw new JBossWSToolsException("bindings in second wsdl cannot be null");
}
if(bindings1.length != bindings2.length)
throw new JBossWSToolsException("Mismatch in the number of bindings");
for (int i = 0; i < bindings1.length; i++)
{
WSDLBinding binding1 = bindings1[i];
WSDLBinding binding2 = bindings2[i];
bool = bool && validateExtensibilityElements(binding1, binding2);
bool = bool && validateBindingOperations(binding1.getOperations(),binding2.getOperations());
}
return bool;
}
/**
* Validates the namespace definitions in the wsdl
* @param w1 WSDL Definitions for the first wsdl
* @param w2 WSDL Definitions for the second wsdl
* @return true if the namespace definitions match
* @throws JBossWSToolsException any inconsistencies
*/
public static boolean validateInterfaces(WSDLDefinitions w1, WSDLDefinitions w2)
throws JBossWSToolsException
{
boolean bool = false;
WSDLInterface[] wiarr1 = w1.getInterfaces();
WSDLInterface[] wiarr2 = w2.getInterfaces();
if(wiarr1.length != wiarr2.length)
throw new JBossWSToolsException("Number of interfaces mismatch");
int len = wiarr1.length;
for(int i = 0; i < len; i++)
{
WSDLInterface wi1 = wiarr1[i];
WSDLInterface wi2 = wiarr2[i];
if(checkQNameEquality(wi1.getName(),wi2.getName()) == false)
throw new JBossWSToolsException("Interface mismatch");
WSDLInterfaceOperation[] wioparr1 = wi1.getOperations();
WSDLInterfaceOperation[] wioparr2 = wi2.getOperations();
if(wioparr1.length != wioparr2.length)
throw new JBossWSToolsException("Number of Interface Operations mismatch");
int innerlen = wioparr1.length;
for(int j = 0 ; j< innerlen; j++)
{
bool = validateInterfaceOperation(wioparr1[j],wioparr2[j]);
if(bool == false)
throw new JBossWSToolsException("validation Interface Operations failed");
}
}
return bool;
}
/**
* Validates the extensibility elements contained into the specified Extendable
* objects.
* @param w1
* @param w2
* @return
* @throws JBossWSToolsException
*/
public static boolean validateExtensibilityElements(Extendable ext1, Extendable ext2)
throws JBossWSToolsException
{
boolean bool = true;
//add validation of further extensibility element types below
if (bool) bool = validatePolicyElements(ext1,ext2);
return bool;
}
private static boolean validatePolicyElements(Extendable ext1, Extendable ext2)
throws JBossWSToolsException
{
//policies
List<WSDLExtensibilityElement> pol1 = new ArrayList<WSDLExtensibilityElement>(
ext1.getExtensibilityElements(Constants.WSDL_ELEMENT_POLICY));
List<WSDLExtensibilityElement> pol2 = new ArrayList<WSDLExtensibilityElement>(
ext2.getExtensibilityElements(Constants.WSDL_ELEMENT_POLICY));
//check whether lists are the same size
if (pol1.size() != pol2.size())
throw new JBossWSToolsException("Policy WSDLExtensibilityElement mismatch!");
//check equality
for (WSDLExtensibilityElement el1 : pol1)
{
boolean done = false;
Iterator it = pol2.iterator();
WSDLExtensibilityElement el2 = null;
while (it.hasNext() && !done)
{
el2 = (WSDLExtensibilityElement)it.next();
done = (el1.isRequired() == el2.isRequired()) &&
checkElementEquality(el1.getElement(), el2.getElement());
}
if (!done)
{
log.error("Failing policy validation on policy on: "+ext1+" and "+ext2);
return false;
}
pol2.remove(el2);
}
//policy references
List<WSDLExtensibilityElement> polRef1 = new ArrayList<WSDLExtensibilityElement>(
ext1.getExtensibilityElements(Constants.WSDL_ELEMENT_POLICYREFERENCE));
List<WSDLExtensibilityElement> polRef2 = new ArrayList<WSDLExtensibilityElement>(
ext2.getExtensibilityElements(Constants.WSDL_ELEMENT_POLICYREFERENCE));
//check whether lists are the same size
if (polRef1.size() != polRef2.size())
throw new JBossWSToolsException("Policy ref WSDLExtensibilityElement mismatch!");
//check equality
for (WSDLExtensibilityElement el1 : polRef1)
{
boolean done = false;
Iterator it = polRef2.iterator();
WSDLExtensibilityElement el2 = null;
while (it.hasNext() && !done)
{
el2 = (WSDLExtensibilityElement)it.next();
done = (el1.isRequired() == el2.isRequired()) &&
checkElementEquality(el1.getElement(), el2.getElement());
}
if (!done)
{
log.error("Failing policy validation on policy ref on: "+ext1+" and "+ext2);
return false;
}
polRef2.remove(el2);
}
//check properties
WSDLProperty prop1 = ext1.getProperty(Constants.WSDL_PROPERTY_POLICYURIS);
WSDLProperty prop2 = ext2.getProperty(Constants.WSDL_PROPERTY_POLICYURIS);
if (prop1 != null || prop2 != null)
{
if (prop1 == null || prop2 == null || prop1.isRequired() != prop2.isRequired())
throw new JBossWSToolsException("Policy prop WSDLExtensibilityElement mismatch!");
String value1 = prop1.getValue();
String value2 = prop2.getValue();
if (value1 != null || value2 != null)
{
if (value1 == null || value2 == null || !value1.equalsIgnoreCase(value2))
{
log.error("Failing policy validation on policy uri prop on: "+ext1+" and "+ext2);
return false;
}
}
}
return true;
}
/**
* Validates the namespace definitions in the wsdl
* @param w1 WSDL Definitions for the first wsdl
* @param w2 WSDL Definitions for the second wsdl
* @return true if the namespace definitions match
* @throws JBossWSToolsException any inconsistencies
*/
public static boolean validateNSDefinitions(WSDLDefinitions w1, WSDLDefinitions w2)
throws JBossWSToolsException
{
String ts1 = w1.getTargetNamespace();
String ts2 = w2.getTargetNamespace();
if(ts1 == null || ts1.equals(""))
throw new JBossWSToolsException("Target Namespaces 1 is null");
if(ts2 == null || ts2.equals(""))
throw new JBossWSToolsException("Target Namespaces 2 is null");
if(ts1.equals(ts2) == false)
throw new JBossWSToolsException("Target Namespaces do not match");
Iterator iter1 = w1.getRegisteredPrefix();
/**
* IDEA: We get a namespace from the first wsdl and check that it is defined
* in the other wsdl, irrespective of the prefix match
*/
while(iter1.hasNext())
{
String prefix1 = (String)iter1.next();
String ns = w1.getNamespaceURI(prefix1);
//Ignore the namespaces that are generated by wscompile for arrays
if(ns.indexOf("arrays") > -1 )
continue;
String prefix2 = w2.getPrefix(ns);
if(prefix2 == null)
throw new JBossWSToolsException("Namespace " + ns + " not defined in the second wsdl");
}
//Lets check the prefixes and namespaces
/*while(iter1.hasNext() && iter2.hasNext())
{
String prefix1 = iter1.next();
String prefix2 = iter2.next();
String ns1 = w1.getNamespaceURI(prefix1);
String ns2 = w2.getNamespaceURI(prefix2);
if(prefix1.equals(prefix2)==false)
throw new JBossWSToolsException("Prefixes mismatch:"+prefix1 +" and " +prefix2 );
if(ns1.equals(ns2) == false)
{
StringBuffer sb = new StringBuffer("Prefixes:"+prefix1+" and "+prefix2+" have");
sb.append("Namespaces mismatch:"+ns1 +" and"+ns2);
throw new JBossWSToolsException(sb.toString());
}
}*/
return true;
}
/**
* Validate the WSDLServices for the two wsdl
* @param w1 WSDLDefinitions object of the first wsdl
* @param w2 WSDLDefinitions object of the second wsdl
* @return true-if match, false - otherwise
* @throws JBossWSToolsException
*/
public static boolean validateServices(WSDLDefinitions w1, WSDLDefinitions w2)
throws JBossWSToolsException
{
boolean bool = false;
WSDLService[] services1 = w1.getServices();
WSDLService[] services2 = w2.getServices();
if (services1 == null || services1.length == 0)
{
throw new JBossWSToolsException("services in first wsdl cannot be null");
}
if(services2 == null || services2.length == 0)
{
throw new JBossWSToolsException("services in second wsdl cannot be null");
}
if(services1.length != services2.length)
throw new JBossWSToolsException("Mismatch in the number of services");
for (int i = 0; i < services1.length; i++)
{
WSDLService s1 = services1[i];
WSDLService s2 = services2[i];
bool = checkQNameEquality(s1.getName(),s2.getName());
if(bool)
{
bool = validateExtensibilityElements(s1, s2);
WSDLEndpoint[] we1 = s1.getEndpoints();
WSDLEndpoint[] we2 = s2.getEndpoints();
bool = bool && validateWSDLEndpoints(we1, we2);
}
}
return bool;
}
/**
* Compare two QName (s) for equality
* @param name1
* @param name2
* @return
*/
private static boolean checkQNameEquality(QName name1, QName name2)
{
String str1 = name1.getLocalPart();
String str2 = name2.getLocalPart();
if(str1.equals(str2) == false) return false;
if(name1.getNamespaceURI().equals(name2.getNamespaceURI()) == false) return false;
return true;
}
/**
* Compare two Element (s) for equality (this cares about child elements and attributes only)
* @param el1
* @param el2
* @return
*/
private static boolean checkElementEquality(Element el1, Element el2)
{
QName qName1 = DOMUtils.getElementQName(el1);
QName qName2 = DOMUtils.getElementQName(el2);
if (!checkQNameEquality(qName1,qName2)) return false;
Map attributes1 = DOMUtils.getAttributes(el1); //map <QName, String>
Map attributes2 = DOMUtils.getAttributes(el2);
if (attributes1.size()!=attributes2.size()) return false;
for (Iterator it = attributes1.keySet().iterator(); it.hasNext(); )
{
QName key = (QName)it.next();
if (key.getPrefix().startsWith("xmlns")) continue;
if (!attributes2.containsKey(key)) return false;
String value1 = (String)attributes1.get(key);
String value2 = (String)attributes2.get(key);
if (!value1.equals(value2)) return false;
}
for (Iterator it = DOMUtils.getChildElements(el1); it.hasNext(); )
{
Element child1 = (Element)it.next();
Iterator it2 = DOMUtils.getChildElements(el2, DOMUtils.getElementQName(child1));
if (!it2.hasNext()) return false;
Element child2 = (Element)it2.next();
if (it2.hasNext() || !checkElementEquality(child1, child2)) return false;
}
return true;
}
private static boolean validateInterfaceOperation(WSDLInterfaceOperation w1,
WSDLInterfaceOperation w2) throws JBossWSToolsException
{
boolean bool = checkQNameEquality(w1.getName(),w2.getName());
bool = bool && validateExtensibilityElements(w1, w2);
if(bool)
{
//validate the inputs
WSDLInterfaceOperationInput wiarr1[] = w1.getInputs();
WSDLInterfaceOperationInput wiarr2[] = w2.getInputs();
if(wiarr1.length != wiarr2.length)
throw new JBossWSToolsException("Number of WSDLInterfaceOperationInput mismatch");
int len = wiarr1.length;
for(int i = 0 ; i < len; i ++)
{
bool = validateInterfaceOperationInput(wiarr1[i],wiarr2[i]);
if(!bool) return bool;
}
//validate the outputs
WSDLInterfaceOperationOutput woarr1[] = w1.getOutputs();
WSDLInterfaceOperationOutput woarr2[] = w2.getOutputs();
if(woarr1.length != woarr2.length)
throw new JBossWSToolsException("Number of WSDLInterfaceOperationInput mismatch");
len = woarr1.length;
for(int i = 0 ; i < len; i ++)
{
bool = validateInterfaceOperationOutput(woarr1[i],woarr2[i]);
if(!bool) return bool;
}
//validate the faults
WSDLInterfaceOperationInfault[] inf1 = w1.getInfaults();
WSDLInterfaceOperationInfault[] inf2 = w2.getInfaults();
if( (inf1 != null && inf2 == null) ||
(inf1 == null && inf2 != null) )
throw new JBossWSToolsException("Infaults mismatch for operation:"+w1.getName());
if(inf1.length != inf2.length)
throw new JBossWSToolsException("Number of Infaults mismatch for operation:"+w1.getName());
len = inf1.length;
for(int i=0; i< len; i++)
{
bool = checkQNameEquality(inf1[i].getRef(),inf2[i].getRef());
if(bool)
bool = checkStringEquality(inf1[i].getMessageLabel(),inf2[i].getMessageLabel());
if(bool == false) return bool;
}
WSDLInterfaceOperationOutfault[] outf1 = w1.getOutfaults();
WSDLInterfaceOperationOutfault[] outf2 = w2.getOutfaults();
if( (outf1 != null && outf2 == null) ||
(outf1 == null && outf2 != null) )
throw new JBossWSToolsException("Outfaults mismatch for operation:"+w1.getName());
if(outf1.length != outf2.length)
throw new JBossWSToolsException("Number of Infaults mismatch for operation:"+w1.getName());
len = outf1.length;
for(int i=0; i< len; i++)
{
bool = checkQNameEquality(outf1[i].getRef(),outf2[i].getRef());
if(bool)
bool = checkStringEquality(outf1[i].getMessageLabel(),outf2[i].getMessageLabel());
if(bool == false) return bool;
}
}
return bool;
}
private static boolean checkStringEquality(String one, String two)
{
if (one == null && two == null)
return true;
return one != null && one.equals(two);
}
private static boolean validateInterfaceOperationInput(WSDLInterfaceOperationInput i1,
WSDLInterfaceOperationInput i2) throws JBossWSToolsException
{
boolean bool = false;
QName xmlName1 = i1.getElement();
QName xmlName2 = i2.getElement();
bool = checkQNameEquality(xmlName1,xmlName2);
if(bool == false)
throw new JBossWSToolsException(xmlName1 + " & " + xmlName2 + " mismatch");
bool = validateExtensibilityElements(i1, i2);
if(bool == false)
throw new JBossWSToolsException("WSDLExtensibilityElement mismatch");
return bool;
}
private static boolean validateInterfaceOperationOutput(WSDLInterfaceOperationOutput i1,
WSDLInterfaceOperationOutput i2)
{
boolean bool = false;
bool = checkQNameEquality(i1.getElement(),i2.getElement());
if(bool == false) return false;
return bool;
}
private static boolean validateBindingOperations(WSDLBindingOperation[] barr1, WSDLBindingOperation[] barr2)
throws JBossWSToolsException
{
boolean bool = false;
if((barr1 == null && barr2 != null) ||
(barr1 != null && barr2 == null))
throw new JBossWSToolsException("Mismatch in the Binding Operations");
if(barr1.length != barr2.length)
throw new JBossWSToolsException("Mismatch in number of Binding Operations");
int len = barr1.length;
for(int i=0; i< len; i++)
{
bool = validateBindingOperation(barr1[i], barr2[i]);
if(!bool) return bool;
}
return bool;
}
private static boolean validateBindingOperation(WSDLBindingOperation b1, WSDLBindingOperation b2)
throws JBossWSToolsException
{
String bname = b1.getRef().getLocalPart();
boolean bool = false;
bool = checkQNameEquality(b1.getRef(),b2.getRef());
WSDLBindingOperationInput[] wb1 = b1.getInputs();
WSDLBindingOperationInput[] wb2 = b2.getInputs();
if(wb1.length != wb2.length)
throw new JBossWSToolsException("Mismatch in the number of inputs for binding op:"+bname);
int len = wb1.length;
for(int i=0; i< len; i++)
{
WSDLBindingOperationInput bindin1 = wb1[i];
WSDLBindingOperationInput bindin2 = wb2[i];
bool = checkStringEquality(bindin1.getMessageLabel(),bindin2.getMessageLabel());
bool = bool & validateExtensibilityElements(bindin1, bindin2);
if(!bool) return bool;
}
WSDLBindingOperationOutput[] wboutarr1 = b1.getOutputs();
WSDLBindingOperationOutput[] wboutarr2 = b2.getOutputs();
if(wboutarr1.length != wboutarr2.length)
throw new JBossWSToolsException("Mismatch in the number of outputs for binding op:"+bname);
len = wboutarr1.length;
for(int i=0; i< len; i++)
{
WSDLBindingOperationOutput bindout1 = wboutarr1[i];
WSDLBindingOperationOutput bindout2 = wboutarr2[i];
bool = checkStringEquality(bindout1.getMessageLabel(),bindout2.getMessageLabel());
}
bool = bool & validateExtensibilityElements(b1, b2);
return bool;
}
private static boolean validateWSDLEndpoints(WSDLEndpoint[] warr1, WSDLEndpoint[] warr2)
throws JBossWSToolsException
{
boolean bool = false;
if(warr1 == null || warr1.length == 0)
throw new JBossWSToolsException("Number of endpoints in first wsdl is null");
if(warr2 == null || warr2.length == 0)
throw new JBossWSToolsException("Number of endpoints in second wsdl is null");
int len = warr1.length;
for(int i=0; i< len;i++)
{
WSDLEndpoint e1 = warr1[i];
WSDLEndpoint e2 = warr2[i];
String add1 = e1.getAddress();
String add2 = e2.getAddress();
if(add1.equals(add2) == false)
throw new JBossWSToolsException("Endpoint addresses do not match");
bool = checkQNameEquality(e1.getBinding(),e2.getBinding());
if(bool == false)
throw new JBossWSToolsException("Endpoint binding do not match");
bool = checkQNameEquality(e1.getName(),e2.getName());
if(bool == false)
throw new JBossWSToolsException("Endpoint Names do not match");
bool = bool && validateExtensibilityElements(e1, e2);
}
return bool;
}
}