From a86522c1e7ee800fb540351871f4b06e859d89a0 Mon Sep 17 00:00:00 2001 From: Kevin Krouse Date: Tue, 1 Feb 2005 20:41:31 +0000 Subject: [PATCH] merge radu's change r149295 from trunk to 1.x branch Fix for http://issues.apache.org/jira/browse/XMLBEANS-35 git-svn-id: https://svn.apache.org/repos/asf/xmlbeans/branches/1.x@149446 13f79535-47bb-0310-9956-ffa450edef68 --- .../xmlbeans/impl/schema/SchemaTypeImpl.java | 10 +++ .../xmlbeans/impl/schema/StscState.java | 7 +- .../xmlbeans/impl/schema/StscTranslator.java | 68 +++++++++++++++++++ .../impl/tool/SchemaCodeGenerator.java | 7 +- test/src/drt/drtcases/ValidationTests.java | 56 +++++++++++++++ 5 files changed, 144 insertions(+), 4 deletions(-) diff --git a/src/typeimpl/org/apache/xmlbeans/impl/schema/SchemaTypeImpl.java b/src/typeimpl/org/apache/xmlbeans/impl/schema/SchemaTypeImpl.java index 4ed4868a1..5f422b230 100644 --- a/src/typeimpl/org/apache/xmlbeans/impl/schema/SchemaTypeImpl.java +++ b/src/typeimpl/org/apache/xmlbeans/impl/schema/SchemaTypeImpl.java @@ -65,6 +65,7 @@ public final class SchemaTypeImpl implements SchemaType, TypeStoreUserFactory private volatile SchemaField _containerField; private volatile int _containerFieldCode; private volatile int _containerFieldIndex; + private volatile QName[] _groupReferenceContext; private SchemaType.Ref[] _anonymousTyperefs; private boolean _isDocumentType; private boolean _isAttributeType; @@ -476,6 +477,15 @@ public void setContainerFieldIndex(short code, int index) _containerFieldIndex = index; } + /* package */ void setGroupReferenceContext(QName[] groupNames) + { + assertUnresolved(); + _groupReferenceContext = groupNames; + } + + /* package */ QName[] getGroupReferenceContext() + { return _groupReferenceContext; } + public SchemaType getOuterType() { return _outerSchemaTypeRef == null ? null : _outerSchemaTypeRef.get(); } diff --git a/src/typeimpl/org/apache/xmlbeans/impl/schema/StscState.java b/src/typeimpl/org/apache/xmlbeans/impl/schema/StscState.java index fbe52dda8..e2fe47a7d 100644 --- a/src/typeimpl/org/apache/xmlbeans/impl/schema/StscState.java +++ b/src/typeimpl/org/apache/xmlbeans/impl/schema/StscState.java @@ -75,7 +75,7 @@ public class StscState private Map _attributeTypes = new LinkedHashMap(); private Map _typesByClassname = new LinkedHashMap(); private Map _misspelledNames = new HashMap(); - private Set _processingGroups = new HashSet(); + private Set _processingGroups = new LinkedHashSet(); private Map _idConstraints = new LinkedHashMap(); private Set _namespaces = new HashSet(); private boolean _noUpa; @@ -754,6 +754,11 @@ void finishProcessing(Object obj) _processingGroups.remove(obj); } + Object[] getCurrentProcessing() + { + return _processingGroups.toArray(); + } + /* JAVAIZATION ====================================================*/ Map typesByClassname() diff --git a/src/typeimpl/org/apache/xmlbeans/impl/schema/StscTranslator.java b/src/typeimpl/org/apache/xmlbeans/impl/schema/StscTranslator.java index ecb7d7170..44cb94348 100644 --- a/src/typeimpl/org/apache/xmlbeans/impl/schema/StscTranslator.java +++ b/src/typeimpl/org/apache/xmlbeans/impl/schema/StscTranslator.java @@ -617,14 +617,26 @@ else if (ds instanceof List) if (typedef != null) { + Object[] grps = state.getCurrentProcessing(); + QName[] context = new QName[grps.length]; + for (int i = 0; i < context.length; i++) + if (grps[i] instanceof SchemaModelGroupImpl) + context[i] = ((SchemaModelGroupImpl ) grps[i]).getName(); + SchemaType repeat = checkRecursiveGroupReference(context, qname, (SchemaTypeImpl)outerType); + if (repeat != null) + sType = repeat; + else + { SchemaTypeImpl sTypeImpl = new SchemaTypeImpl(state.sts()); sType = sTypeImpl; sTypeImpl.setContainerField(impl); sTypeImpl.setOuterSchemaTypeRef(outerType == null ? null : outerType.getRef()); + sTypeImpl.setGroupReferenceContext(context); // leave the anonymous type unresolved: it will be resolved later. anonymousTypes.add(sType); sTypeImpl.setSimpleType(simpleTypedef); sTypeImpl.setParseContext(typedef, targetNamespace, chameleon, false); + } } if (sType == null) @@ -744,6 +756,62 @@ else if (block instanceof List) return impl; } + /** + * We need to do this because of the following kind of Schemas: + * + * + * + * + * + * + * + * + * + * (see JIRA bug XMLBEANS-35) + * Even though this should not be allowed because it produces an infinite + * number of anonymous types and local elements nested within each other, + * the de facto consensus among Schema processors is that this should be + * valid, therefore we have to detect this situation and "patch up" the + * Schema object model so that instead of creating a new anonymous type, + * we refer to the one that was already created earlier. + * In order to accomplish that, we store inside every anonymous type the + * list of groups that were dereferenced at the moment the type was created + * and if the same pattern is about to repeat, it means that we are in a + * case similar to the above. + */ + private static SchemaType checkRecursiveGroupReference(QName[] context, QName containingElement, SchemaTypeImpl outerType) + { + if (context.length < 1) + return null; + SchemaTypeImpl type = outerType; + + while (type != null) + { + if (type.getName() != null || type.isDocumentType()) + return null; // not anonymous + if (containingElement.equals(type.getContainerField().getName())) + { + QName[] outerContext = type.getGroupReferenceContext(); + if (outerContext != null && outerContext.length == context.length) + { + // Smells like trouble + boolean equal = true; + for (int i = 0; i < context.length; i++) + if (!(context[i] == null && outerContext[i] == null || + context[i] != null && context[i].equals(outerContext[i]))) + { + equal = false; + break; + } + if (equal) + return type; + } + } + type = (SchemaTypeImpl) type.getOuterType(); + } + return null; + } + private static String removeWhitespace(String xpath) { StringBuffer sb = new StringBuffer(); diff --git a/src/xmlcomp/org/apache/xmlbeans/impl/tool/SchemaCodeGenerator.java b/src/xmlcomp/org/apache/xmlbeans/impl/tool/SchemaCodeGenerator.java index d26374aba..900543f24 100644 --- a/src/xmlcomp/org/apache/xmlbeans/impl/tool/SchemaCodeGenerator.java +++ b/src/xmlcomp/org/apache/xmlbeans/impl/tool/SchemaCodeGenerator.java @@ -292,9 +292,10 @@ private static void tryToDelete(File dir) { if (dir.isDirectory()) { - String[] list = dir.list(); - for (int i = 0; i < list.length; i++) - tryToDelete(new File(dir, list[i])); + String[] list = dir.list(); // can return null if I/O error + if (list != null) + for (int i = 0; i < list.length; i++) + tryToDelete(new File(dir, list[i])); } if (!dir.delete()) return; // don't try very hard, because we're just deleting tmp diff --git a/test/src/drt/drtcases/ValidationTests.java b/test/src/drt/drtcases/ValidationTests.java index a630f692e..7d36db7c2 100644 --- a/test/src/drt/drtcases/ValidationTests.java +++ b/test/src/drt/drtcases/ValidationTests.java @@ -1599,4 +1599,60 @@ public void testValidate11() throws Exception { doTest(schemas, null, valid, invalid); } + public void testValidateNestedGroups ( ) + throws Exception + { + // This is a weird Schema, inspired from JIRA bug XMLBEANS-35 + // Make sure we compile it and then validate correctly + String schemas[] = { + "\n" + + "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n" + + "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n" + + "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + "\n" + + "\n" + + "\n"}; + + String valid[] = { + "\n" + + " \n" + + " \n" + + " " + + " \n" + + " \n" + + "\n"}; + + String invalid[] = { + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"}; + + doTest(schemas, null, valid, invalid); + } + }