https://bugs.eclipse.org/bugs/show_bug.cgi?id=379547 - Fix NPE and
infinite loop problem in XSDComparer
diff --git a/plugins/org.eclipse.bpel.model/src/org/eclipse/bpel/model/util/XSDComparer.java b/plugins/org.eclipse.bpel.model/src/org/eclipse/bpel/model/util/XSDComparer.java
index a9b4c92..eeb99b7 100644
--- a/plugins/org.eclipse.bpel.model/src/org/eclipse/bpel/model/util/XSDComparer.java
+++ b/plugins/org.eclipse.bpel.model/src/org/eclipse/bpel/model/util/XSDComparer.java
@@ -8,6 +8,8 @@
package org.eclipse.bpel.model.util;
import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
@@ -59,7 +61,8 @@
protected boolean strict = false;
protected boolean debug = false;
protected List<XSDDiagnostic> diagnostics;
-
+ protected Hashtable<XSDTerm,XSDTerm> terms = new Hashtable<XSDTerm,XSDTerm>();
+
public void setStrict(boolean flag) {
strict = flag;
}
@@ -68,6 +71,16 @@
debug = flag;
}
+ protected boolean alreadyCompared(XSDTerm term1, XSDTerm term2) {
+ XSDTerm t = terms.get(term1);
+ if (t==term2)
+ return true;
+ t = terms.get(term2);
+ if (t==term1)
+ return true;
+ return false;
+ }
+
/**
* The main comparison function that compares two XSD type definitions.
* These may be the entire schema or just fragments within a schema.
@@ -122,169 +135,175 @@
while (index1 < size1 && index2 < size2) {
term1 = list1.get(index1);
term2 = list2.get(index2);
- if ( term1 instanceof XSDElementDeclaration && term2 instanceof XSDElementDeclaration) {
- XSDElementDeclaration elem1 = (XSDElementDeclaration)term1;
- XSDElementDeclaration elem2 = (XSDElementDeclaration)term2;
- XSDTypeDefinition type1 = elem1.getTypeDefinition();
- XSDTypeDefinition type2 = elem2.getTypeDefinition();
- if (type1 instanceof XSDSimpleTypeDefinition && type2 instanceof XSDSimpleTypeDefinition) {
- dump("Comparing ", elem1, type1, level);
- dump(" to ", elem2, type2, level);
- if (!compareQNames(elem1, elem2)) {
- addError("different QNames: " + elem1.getQName() + " vs " + elem2.getQName(), term1,term2);
- return false;
- }
- String s1 = getTypeNameHierarchy(elem1);
- String s2 = getTypeNameHierarchy(elem2);
- if (!s1.equals(s2)) {
- addError("different data types: "+s1+" vs "+s2,elem1,elem2);
- return false;
- }
- } else if (type1 instanceof XSDComplexTypeDefinition && type2 instanceof XSDComplexTypeDefinition) {
- dump("Comparing ", elem1, type1, level);
- dump(" to ", elem2, type2, level);
- if (!compareQNames(elem1, elem2)) {
- addError("different QNames: " + elem1.getQName() + " vs " + elem2.getQName(), term1,term2);
- return false;
- }
- int min1 = getMinOccurs(term1);
- int min2 = getMinOccurs(term2);
- int max1 = getMaxOccurs(term1);
- int max2 = getMaxOccurs(term2);
- if (strict) {
- if (min1 != min2 || max1 != max2) {
- addError("different cardinality: " + min1 + " to " + max1 + " vs " + min2 + " to " + max2, term1,term2);
- return false;
- }
- } else {
- if ((max2>0 && min1 > max2) || (max1>0 && min2 > max1)) {
- addError("incompatible cardinality: " + min1 + " to " + max1 + " vs " + min2 + " to " + max2, term1,term2);
- return false;
- }
- }
- boolean result = compare(getChildTerms(elem1), getChildTerms(elem2), level + 1);
- if (!result) {
- addError("different complex element structures",elem1,elem2);
- return false;
- }
- } else {
- if (!strict) {
- // try shifting optional elements and continue from there
- dump("Elements out of sync - skipping optional elements");
- if (isOptional(elem1)) {
- // skip over this one and compare remaining elements
- List<XSDTerm> newList1 = new ArrayList<XSDTerm>();
- List<XSDTerm> newList2 = new ArrayList<XSDTerm>();
- for (int i = index1 + 1; i < size1; ++i)
- newList1.add(list1.get(i));
- for (int i = index2; i < size2; ++i)
- newList2.add(list2.get(i));
- if (compare(newList1, newList2, level)) {
- addWarning("skipped optional element(s) in left schema",elem1,elem2);
- return true;
- }
- addError("different complex element structures",elem1,elem2);
- }
- if (isOptional(elem2)) {
- // skip over this one and compare remaining elements
- List<XSDTerm> newList1 = new ArrayList<XSDTerm>();
- List<XSDTerm> newList2 = new ArrayList<XSDTerm>();
- for (int i = index1; i < size1; ++i)
- newList1.add(list1.get(i));
- for (int i = index2 + 1; i < size2; ++i)
- newList2.add(list2.get(i));
- if (compare(newList1, newList2, level)) {
- addWarning("skipped optional element(s) in right schema",elem1,elem2);
- return true;
- }
- addError("different complex element structures",elem1,elem2);
- }
- }
- addError("different complex element structures",elem1,elem2);
- return false;
- }
-
- List<XSDAttributeDeclaration> attrs1 = getAttributeDeclarations(elem1);
- List<XSDAttributeDeclaration> attrs2 = getAttributeDeclarations(elem2);
- if (attrs1.size() != attrs2.size()) {
- addError("different number of attributes",elem1,elem2);
- return false;
- }
- for (int i = 0; i < attrs1.size(); ++i) {
- XSDAttributeDeclaration attr1 = attrs1.get(i);
- XSDAttributeDeclaration attr2 = attrs2.get(i);
- if (!attr1.getQName().equals(attr2.getQName())) {
- addError("different attribute names: "+attr1.getQName()+" vs "+attr2.getQName(),elem1,elem2);
- return false;
- }
- String value1 = attr1.getLexicalValue();
- String value2 = attr2.getLexicalValue();
- if (value1==null)
- value1 = "";
- if (value2==null)
- value2 = "";
- if (!value1.equals(value2)) {
- addError("different attribute values: "+attr1.getLexicalValue()+" vs "+attr2.getLexicalValue(),elem1,elem2);
- return false;
- }
- }
-
- } else if (term1 instanceof XSDWildcard && !(term2 instanceof XSDWildcard) ) {
- // left schema term is a wildcard, right schema is not
- int min = getMinOccurs(term1);
- int max = getMinOccurs(term1);
- if (max==-1)
- max = size1;
-
- for (int n=min; n<=max; ++n) {
- // skip over this one and compare remaining elements
- List<XSDTerm> newList1 = new ArrayList<XSDTerm>();
- List<XSDTerm> newList2 = new ArrayList<XSDTerm>();
- for (int i = index1 + 1 + n; i < size1; ++i)
- newList1.add(list1.get(i));
- for (int i = index2; i < size2; ++i)
- newList2.add(list2.get(i));
- if (compare(newList1, newList2, level)) {
- addWarning("skipped optional element(s) in left schema",term1,term2);
- return true;
- }
- }
- addError("different complex element structures",term1,term2);
- return false;
- } else if (term1 instanceof XSDWildcard && !(term2 instanceof XSDWildcard) ) {
- // right schema is a wildcard, left schema is not
- int min = getMinOccurs(term2);
- int max = getMinOccurs(term2);
- if (max==-1)
- max = size2;
-
- for (int n=min; n<=max; ++n) {
- // skip over this one and compare remaining elements
- List<XSDTerm> newList1 = new ArrayList<XSDTerm>();
- List<XSDTerm> newList2 = new ArrayList<XSDTerm>();
- for (int i = index1; i < size1; ++i)
- newList1.add(list1.get(i));
- for (int i = index2 + 1 + n; i < size2; ++i)
- newList2.add(list2.get(i));
- if (compare(newList1, newList2, level)) {
- addWarning("skipped optional element(s) in right schema",term1,term2);
- return true;
- }
- }
- addError("different complex element structures",term1,term2);
- return false;
- } else if (term1 instanceof XSDWildcard && term2 instanceof XSDWildcard) {
- // both wildcards - it's a match!
- int min1 = getMinOccurs(term1);
- int max1 = getMinOccurs(term1);
- int min2 = getMinOccurs(term2);
- int max2 = getMinOccurs(term2);
- if (min1!=min2 || max1!=max2) {
- // not possible
- addError("different <xsd:any> cardinality: "+min1+" to "+max1+" vs "+min2+" to "+max2,term1,term2);
- }
+ if (alreadyCompared(term1,term2)) {
+ dump("Skipping ",term1,null,level);
}
-
+ else {
+ terms.put(term1,term2);
+ if ( term1 instanceof XSDElementDeclaration && term2 instanceof XSDElementDeclaration) {
+ XSDElementDeclaration elem1 = (XSDElementDeclaration)term1;
+ XSDElementDeclaration elem2 = (XSDElementDeclaration)term2;
+ XSDTypeDefinition type1 = elem1.getTypeDefinition();
+ XSDTypeDefinition type2 = elem2.getTypeDefinition();
+ if (type1 instanceof XSDSimpleTypeDefinition && type2 instanceof XSDSimpleTypeDefinition) {
+ dump("Comparing ", elem1, type1, level);
+ dump(" to ", elem2, type2, level);
+ if (!compareQNames(elem1, elem2)) {
+ addError("different QNames: " + elem1.getQName() + " vs " + elem2.getQName(), term1,term2);
+ return false;
+ }
+ String s1 = getTypeNameHierarchy(elem1);
+ String s2 = getTypeNameHierarchy(elem2);
+ if (!s1.equals(s2)) {
+ addError("different data types: "+s1+" vs "+s2,elem1,elem2);
+ return false;
+ }
+ } else if (type1 instanceof XSDComplexTypeDefinition && type2 instanceof XSDComplexTypeDefinition) {
+ dump("Comparing ", elem1, type1, level);
+ dump(" to ", elem2, type2, level);
+ if (!compareQNames(elem1, elem2)) {
+ addError("different QNames: " + elem1.getQName() + " vs " + elem2.getQName(), term1,term2);
+ return false;
+ }
+ int min1 = getMinOccurs(term1);
+ int min2 = getMinOccurs(term2);
+ int max1 = getMaxOccurs(term1);
+ int max2 = getMaxOccurs(term2);
+ if (strict) {
+ if (min1 != min2 || max1 != max2) {
+ addError("different cardinality: " + min1 + " to " + max1 + " vs " + min2 + " to " + max2, term1,term2);
+ return false;
+ }
+ } else {
+ if ((max2>0 && min1 > max2) || (max1>0 && min2 > max1)) {
+ addError("incompatible cardinality: " + min1 + " to " + max1 + " vs " + min2 + " to " + max2, term1,term2);
+ return false;
+ }
+ }
+ boolean result = compare(getChildTerms(elem1), getChildTerms(elem2), level + 1);
+ if (!result) {
+ addError("different complex element structures",elem1,elem2);
+ return false;
+ }
+ } else {
+ if (!strict) {
+ // try shifting optional elements and continue from there
+ dump("Elements out of sync - skipping optional elements");
+ if (isOptional(elem1)) {
+ // skip over this one and compare remaining elements
+ List<XSDTerm> newList1 = new ArrayList<XSDTerm>();
+ List<XSDTerm> newList2 = new ArrayList<XSDTerm>();
+ for (int i = index1 + 1; i < size1; ++i)
+ newList1.add(list1.get(i));
+ for (int i = index2; i < size2; ++i)
+ newList2.add(list2.get(i));
+ if (compare(newList1, newList2, level)) {
+ addWarning("skipped optional element(s) in left schema",elem1,elem2);
+ return true;
+ }
+ addError("different complex element structures",elem1,elem2);
+ }
+ if (isOptional(elem2)) {
+ // skip over this one and compare remaining elements
+ List<XSDTerm> newList1 = new ArrayList<XSDTerm>();
+ List<XSDTerm> newList2 = new ArrayList<XSDTerm>();
+ for (int i = index1; i < size1; ++i)
+ newList1.add(list1.get(i));
+ for (int i = index2 + 1; i < size2; ++i)
+ newList2.add(list2.get(i));
+ if (compare(newList1, newList2, level)) {
+ addWarning("skipped optional element(s) in right schema",elem1,elem2);
+ return true;
+ }
+ addError("different complex element structures",elem1,elem2);
+ }
+ }
+ addError("different complex element structures",elem1,elem2);
+ return false;
+ }
+
+ List<XSDAttributeDeclaration> attrs1 = getAttributeDeclarations(elem1);
+ List<XSDAttributeDeclaration> attrs2 = getAttributeDeclarations(elem2);
+ if (attrs1.size() != attrs2.size()) {
+ addError("different number of attributes",elem1,elem2);
+ return false;
+ }
+ for (int i = 0; i < attrs1.size(); ++i) {
+ XSDAttributeDeclaration attr1 = attrs1.get(i);
+ XSDAttributeDeclaration attr2 = attrs2.get(i);
+ if (!attr1.getQName().equals(attr2.getQName())) {
+ addError("different attribute names: "+attr1.getQName()+" vs "+attr2.getQName(),elem1,elem2);
+ return false;
+ }
+ String value1 = attr1.getLexicalValue();
+ String value2 = attr2.getLexicalValue();
+ if (value1==null)
+ value1 = "";
+ if (value2==null)
+ value2 = "";
+ if (!value1.equals(value2)) {
+ addError("different attribute values: "+attr1.getLexicalValue()+" vs "+attr2.getLexicalValue(),elem1,elem2);
+ return false;
+ }
+ }
+
+ } else if (term1 instanceof XSDWildcard && !(term2 instanceof XSDWildcard) ) {
+ // left schema term is a wildcard, right schema is not
+ int min = getMinOccurs(term1);
+ int max = getMinOccurs(term1);
+ if (max==-1)
+ max = size1;
+
+ for (int n=min; n<=max; ++n) {
+ // skip over this one and compare remaining elements
+ List<XSDTerm> newList1 = new ArrayList<XSDTerm>();
+ List<XSDTerm> newList2 = new ArrayList<XSDTerm>();
+ for (int i = index1 + 1 + n; i < size1; ++i)
+ newList1.add(list1.get(i));
+ for (int i = index2; i < size2; ++i)
+ newList2.add(list2.get(i));
+ if (compare(newList1, newList2, level)) {
+ addWarning("skipped optional element(s) in left schema",term1,term2);
+ return true;
+ }
+ }
+ addError("different complex element structures",term1,term2);
+ return false;
+ } else if (term1 instanceof XSDWildcard && !(term2 instanceof XSDWildcard) ) {
+ // right schema is a wildcard, left schema is not
+ int min = getMinOccurs(term2);
+ int max = getMinOccurs(term2);
+ if (max==-1)
+ max = size2;
+
+ for (int n=min; n<=max; ++n) {
+ // skip over this one and compare remaining elements
+ List<XSDTerm> newList1 = new ArrayList<XSDTerm>();
+ List<XSDTerm> newList2 = new ArrayList<XSDTerm>();
+ for (int i = index1; i < size1; ++i)
+ newList1.add(list1.get(i));
+ for (int i = index2 + 1 + n; i < size2; ++i)
+ newList2.add(list2.get(i));
+ if (compare(newList1, newList2, level)) {
+ addWarning("skipped optional element(s) in right schema",term1,term2);
+ return true;
+ }
+ }
+ addError("different complex element structures",term1,term2);
+ return false;
+ } else if (term1 instanceof XSDWildcard && term2 instanceof XSDWildcard) {
+ // both wildcards - it's a match!
+ int min1 = getMinOccurs(term1);
+ int max1 = getMinOccurs(term1);
+ int min2 = getMinOccurs(term2);
+ int max2 = getMinOccurs(term2);
+ if (min1!=min2 || max1!=max2) {
+ // not possible
+ addError("different <xsd:any> cardinality: "+min1+" to "+max1+" vs "+min2+" to "+max2,term1,term2);
+ }
+ }
+ }
+
++index1;
++index2;
}
@@ -768,7 +787,7 @@
private void dump(String label, XSDTerm term, XSDTypeDefinition type, int level) {
if (debug) {
- if (term != null && type != null) {
+ if (term != null) {
StringBuilder indent = new StringBuilder();
for (int i = 0; i < level; ++i)
indent.append( " " );
@@ -779,7 +798,7 @@
System.err.println(label + indent + "<" + decl.getName() + "> type=\""
+ this.getTypeNameHierarchy(decl)+"\"");
else if (type instanceof XSDComplexTypeDefinition || type == null)
- System.err.println(label + indent + "<" + decl.getName() + "\">");
+ System.err.println(label + indent + "<" + decl.getName() + ">");
else
System.err.println("dump: unknown XSD type: " + type.getClass().toString());
} else if (term instanceof XSDWildcard) {
@@ -828,4 +847,12 @@
boolean visit(XSDTypeDefinition type);
}
}
+
+ private static class XSDTermTuple {
+ public XSDTerm term1, term2;
+ public XSDTermTuple(XSDTerm term1, XSDTerm term2) {
+ this.term1 = term1;
+ this.term2 = term2;
+ }
+ }
}
diff --git a/plugins/org.eclipse.bpel.ui/src/org/eclipse/bpel/ui/properties/NamespacePrefixesProvider.java b/plugins/org.eclipse.bpel.ui/src/org/eclipse/bpel/ui/properties/NamespacePrefixesProvider.java
index ba3b137..043bcf3 100644
--- a/plugins/org.eclipse.bpel.ui/src/org/eclipse/bpel/ui/properties/NamespacePrefixesProvider.java
+++ b/plugins/org.eclipse.bpel.ui/src/org/eclipse/bpel/ui/properties/NamespacePrefixesProvider.java
@@ -174,13 +174,8 @@
{
if (o instanceof org.eclipse.wst.wsdl.Import)
{
- Definition wsdl = ((org.eclipse.wst.wsdl.Import)o).getEDefinition();
-
if ( ((org.eclipse.wst.wsdl.Import)o).getLocationURI().equals(wsdlImp.getLocationURI()) )
foundNew = false;
-
- Object ns = wsdl.getNamespaces().entrySet();
- System.out.println("ns="+ns);
}
else if (o instanceof org.eclipse.bpel.model.Import)
{
@@ -191,6 +186,7 @@
if (foundNew)
imports.add(wsdlImp);
+ // FIXME: we need to be able to support WSDL locations outside of the containing project!
if (!wsdlImp.getLocationURI().startsWith("http://"))
{
if (wsdlImp.getDefinition()!=null)