1 17 package org.apache.ws.jaxme.xs.impl; 18 19 import java.io.File ; 20 import java.io.IOException ; 21 import java.net.MalformedURLException ; 22 import java.net.URL ; 23 import java.util.ArrayList ; 24 import java.util.HashMap ; 25 import java.util.HashSet ; 26 import java.util.Iterator ; 27 import java.util.List ; 28 import java.util.Map ; 29 import java.util.Set ; 30 31 import javax.xml.parsers.ParserConfigurationException ; 32 33 import org.apache.ws.jaxme.xs.XSContentHandler; 34 import org.apache.ws.jaxme.xs.XSElement; 35 import org.apache.ws.jaxme.xs.XSObjectFactory; 36 import org.apache.ws.jaxme.xs.XSParser; 37 import org.apache.ws.jaxme.xs.XSSchema; 38 import org.apache.ws.jaxme.xs.parser.XSContext; 39 import org.apache.ws.jaxme.xs.parser.XsSAXParser; 40 import org.apache.ws.jaxme.xs.parser.impl.LocSAXException; 41 import org.apache.ws.jaxme.xs.xml.XsAnyURI; 42 import org.apache.ws.jaxme.xs.xml.XsEAnnotation; 43 import org.apache.ws.jaxme.xs.xml.XsEImport; 44 import org.apache.ws.jaxme.xs.xml.XsEInclude; 45 import org.apache.ws.jaxme.xs.xml.XsENotation; 46 import org.apache.ws.jaxme.xs.xml.XsERedefine; 47 import org.apache.ws.jaxme.xs.xml.XsESchema; 48 import org.apache.ws.jaxme.xs.xml.XsETopLevelSimpleType; 49 import org.apache.ws.jaxme.xs.xml.XsNCName; 50 import org.apache.ws.jaxme.xs.xml.XsObject; 51 import org.apache.ws.jaxme.xs.xml.XsObjectFactory; 52 import org.apache.ws.jaxme.xs.xml.XsQName; 53 import org.apache.ws.jaxme.xs.xml.XsRedefinable; 54 import org.apache.ws.jaxme.xs.xml.XsTAttribute; 55 import org.apache.ws.jaxme.xs.xml.XsTAttributeGroup; 56 import org.apache.ws.jaxme.xs.xml.XsTComplexType; 57 import org.apache.ws.jaxme.xs.xml.XsTLocalElement; 58 import org.apache.ws.jaxme.xs.xml.XsTNamedGroup; 59 import org.apache.ws.jaxme.xs.xml.XsTSimpleExplicitGroup; 60 import org.apache.ws.jaxme.xs.xml.XsTTopLevelElement; 61 import org.w3c.dom.Node ; 62 import org.xml.sax.EntityResolver ; 63 import org.xml.sax.InputSource ; 64 import org.xml.sax.Locator ; 65 import org.xml.sax.SAXException ; 66 import org.xml.sax.XMLReader ; 67 68 69 73 public class XSLogicalParser { 74 77 public static class AddedImport { 78 private final String targetNamespace, schemaLocation; 79 private final Node node; 80 85 public AddedImport(XsAnyURI pTargetNamespace, String pSchemaLocation) { 86 this(pTargetNamespace == null ? "" : pTargetNamespace.toString(), pSchemaLocation); 87 } 88 93 public AddedImport(String pTargetNamespace, String pSchemaLocation) { 94 this(pTargetNamespace, pSchemaLocation, null); 95 } 96 104 public AddedImport(String pTargetNamespace, String pSchemaLocation, Node pNode) { 105 targetNamespace = pTargetNamespace == null ? "" : pTargetNamespace.toString(); 106 if (pSchemaLocation == null) { 107 throw new IllegalStateException ("The schemaLocation must not be null."); 108 } 109 schemaLocation = pSchemaLocation; 110 node = pNode; 111 } 112 public boolean equals(Object pOther) { 113 if (pOther instanceof AddedImport) { 114 AddedImport other = (AddedImport) pOther; 115 return targetNamespace.equals(other.targetNamespace) && 116 schemaLocation.equals(other.schemaLocation); 117 } else { 118 return false; 119 } 120 } 121 public int hashCode() { 122 return targetNamespace.hashCode() + schemaLocation.hashCode(); 123 } 124 125 127 public String getNamespace() { 128 return targetNamespace; 129 } 130 131 134 public String getSchemaLocation() { 135 return schemaLocation; 136 } 137 138 141 public Node getNode() { 142 return node; 143 } 144 } 145 146 private boolean notValidating; 147 private List syntaxSchemas = new ArrayList (); 148 private XsESchema[] syntaxSchemaArray; 149 private XSSchema schema; 150 private Set parsedSchemas; 151 private List addedImports = new ArrayList (); 152 153 protected XSContext getData() { 154 return XSParser.getRunningInstance().getContext(); 155 } 156 157 159 public void setValidating(boolean pValidating) { 160 notValidating = !pValidating; 161 } 162 163 165 public boolean isValidating() { 166 return !notValidating; 167 } 168 169 181 public void addImport(String pNamespace, String pSchemaLocation) { 182 addedImports.add(new AddedImport(pNamespace, pSchemaLocation)); 183 } 184 185 198 public void addImport(String pNamespace, String pSchemaLocation, Node pSchema) { 199 addedImports.add(new XSLogicalParser.AddedImport(pNamespace, pSchemaLocation, pSchema)); 200 } 201 202 204 public AddedImport[] getAddedImports() { 205 return (AddedImport[]) addedImports.toArray(new AddedImport[addedImports.size()]); 206 } 207 208 210 public XSSchema getSchema() { return schema; } 211 212 214 protected void setSchema(XSSchema pSchema) { 215 schema = pSchema; 216 } 217 218 protected XsESchema parseSyntax(Node pNode) throws SAXException { 219 XSContext data = getData(); 220 try { 221 XsObjectFactory factory = data.getXsObjectFactory(); 222 XsESchema mySchema = factory.newXsESchema(); 223 XsSAXParser xsSAXParser = factory.newXsSAXParser(mySchema); 224 addSyntaxSchema(mySchema); 225 try { 226 data.setCurrentContentHandler(xsSAXParser); 227 DOMSerializer ds = new DOMSerializer(); 228 ds.serialize(pNode, xsSAXParser); 229 return (XsESchema) xsSAXParser.getBean(); 230 } finally { 231 removeSyntaxSchema(); 232 } 233 } finally { 234 data.setCurrentContentHandler(null); 235 } 236 } 237 238 240 protected InputSource getInputSource(String pReferencingSystemId, String pURI) throws SAXException { 241 URL url = null; 242 if (pReferencingSystemId != null) { 243 try { 245 url = new URL (new URL (pReferencingSystemId), pURI); 246 } catch (MalformedURLException e) { 247 } 248 249 if (url == null) { 250 try { 251 url = new File (new File (pReferencingSystemId).getParentFile(), pURI).toURL(); 252 } catch (MalformedURLException e) { 253 } 254 } 255 } 256 257 if (url == null) { 258 try { 259 url = new URL (pURI); 260 } catch (MalformedURLException e) { 261 try { 262 url = new File (pURI).toURL(); 263 } catch (MalformedURLException f) { 264 throw new SAXException("Failed to parse the URI " + pURI); 265 } 266 } 267 } 268 269 try { 270 InputSource isource = new InputSource (url.openStream()); 271 isource.setSystemId(url.toString()); 272 return isource; 273 } catch (IOException e) { 274 throw new SAXException("Failed to open the URL " + url, e); 275 } 276 } 277 278 279 protected XsESchema parseSyntax(Locator pLocator, String pSchemaLocation) 280 throws SAXException, IOException , ParserConfigurationException { 281 XsESchema result = getData().getXsObjectFactory().newXsESchema(); 282 parseSyntax(pLocator, pSchemaLocation, result); 283 return result; 284 } 285 286 protected void parseSyntax(Locator pLocator, String pSchemaLocation, 287 XsESchema pSchema) 288 throws SAXException, IOException , ParserConfigurationException { 289 XSContext data = getData(); 290 try { 291 XsObjectFactory factory = data.getXsObjectFactory(); 292 XMLReader xr = factory.newXMLReader(isValidating()); 293 EntityResolver entityResolver = xr.getEntityResolver(); 294 InputSource schemaSource = null; 295 if (entityResolver != null) { 296 schemaSource = entityResolver.resolveEntity(null, pSchemaLocation); 297 } 298 if (schemaSource == null) { 299 schemaSource = getInputSource(pLocator == null ? null : pLocator.getSystemId(), 300 pSchemaLocation); 301 } 302 303 XsSAXParser xsSAXParser = factory.newXsSAXParser(pSchema); 304 addSyntaxSchema(pSchema); 305 try { 306 data.setCurrentContentHandler(xsSAXParser); 307 xr.setContentHandler(xsSAXParser); 308 xr.parse(schemaSource); 309 } finally { 310 removeSyntaxSchema(); 311 } 312 } finally { 313 data.setCurrentContentHandler(null); 314 } 315 } 316 317 319 protected void redefine(XsESchema pSyntaxSchema, 320 XsERedefine pRedefine, XsRedefinable pChild) throws SAXException { 321 XSSchema mySchema = getSchema(); 322 XSContext data = getData(); 323 XSObjectFactory factory = data.getXSObjectFactory(); 324 if (pChild instanceof XsTAttributeGroup) { 325 XsTAttributeGroup attributeGroup = (XsTAttributeGroup) pChild; 326 mySchema.redefine(factory.newXSAttributeGroup(mySchema, attributeGroup)); 327 } else if (pChild instanceof XsTNamedGroup) { 328 XsTNamedGroup group = (XsTNamedGroup) pChild; 329 mySchema.redefine(factory.newXSGroup(mySchema, group)); 330 } else if (pChild instanceof XsETopLevelSimpleType) { 331 XsETopLevelSimpleType type = (XsETopLevelSimpleType) pChild; 332 mySchema.redefine(factory.newXSType(mySchema, type)); 333 } else if (pChild instanceof XsTComplexType) { 334 XsTComplexType type = (XsTComplexType) pChild; 335 mySchema.redefine(factory.newXSType(mySchema, type)); 336 } else { 337 Locator locator = (pChild instanceof XsObject) ? ((XsObject) pChild).getLocator() : pRedefine.getLocator(); 338 throw new LocSAXException("Unknown type for redefinition: " + pChild.getClass().getName() + 339 ", perhaps you should handle this in a subclass?", locator); 340 } 341 } 342 343 344 345 348 protected void add(XsESchema pSyntaxSchema, Object pChild) throws SAXException { 349 XSSchema mySchema = getSchema(); 350 XSContext data = getData(); 351 XSObjectFactory factory = data.getXSObjectFactory(); 352 if (pChild instanceof XsEAnnotation) { 353 XsEAnnotation annotation = (XsEAnnotation) pChild; 354 mySchema.add(factory.newXSAnnotation(mySchema, annotation)); 355 } else if (pChild instanceof XsETopLevelSimpleType) { 356 XsETopLevelSimpleType type = (XsETopLevelSimpleType) pChild; 357 mySchema.add(factory.newXSType(mySchema, type)); 358 } else if (pChild instanceof XsTComplexType) { 359 XsTComplexType type = (XsTComplexType) pChild; 360 mySchema.add(factory.newXSType(mySchema, type)); 361 } else if (pChild instanceof XsTNamedGroup) { 362 XsTNamedGroup group = (XsTNamedGroup) pChild; 363 mySchema.add(factory.newXSGroup(mySchema, group)); 364 } else if (pChild instanceof XsTAttributeGroup) { 365 XsTAttributeGroup attributeGroup = (XsTAttributeGroup) pChild; 366 mySchema.add(factory.newXSAttributeGroup(mySchema, attributeGroup)); 367 } else if (pChild instanceof XsTTopLevelElement) { 368 XsTTopLevelElement element = (XsTTopLevelElement) pChild; 369 mySchema.add(factory.newXSElement(mySchema, element)); 370 } else if (pChild instanceof XsTAttribute) { 371 XsTAttribute attribute = (XsTAttribute) pChild; 372 mySchema.add(factory.newXSAttribute(mySchema, attribute)); 373 } else if (pChild instanceof XsENotation) { 374 XsENotation notation = (XsENotation) pChild; 375 mySchema.add(factory.newXSNotation(mySchema, notation)); 376 } else { 377 Locator locator = (pChild instanceof XsObject) ? 378 ((XsObject) pChild).getLocator() : pSyntaxSchema.getLocator(); 379 throw new LocSAXException("Unknown child type: " + pChild.getClass().getName() + 380 ", perhaps you should handle this in a subclass?", locator); 381 } 382 } 383 384 386 protected void redefineSchema(XsESchema pRedefiningSchema, 387 XsERedefine pRedefine) 388 throws SAXException, IOException , ParserConfigurationException { 389 throw new LocSAXException("Redefine isn't yet implemented.", pRedefine.getLocator()); 391 } 392 393 395 protected void includeSchema(XsESchema pIncludingSchema, 396 XsEInclude pInclude) 397 throws SAXException, IOException , ParserConfigurationException { 398 final XsAnyURI schemaLocation = pInclude.getSchemaLocation(); 399 if (schemaLocation == null) { 400 throw new LocSAXException("Invalid include: Missing 'schemaLocation' attribute.", 401 pInclude.getLocator()); 402 } 403 Locator locator = pInclude.getLocator(); 404 XsESchema includedSchema = parseSyntax(locator, schemaLocation.toString()); 405 XsAnyURI incNamespace = includedSchema.getTargetNamespace(); 406 if (incNamespace == null) { 407 if (pIncludingSchema.getTargetNamespace() != null) { 408 includedSchema.setTargetNamespace(pIncludingSchema.getTargetNamespace()); 409 } 410 } else { 411 XsAnyURI myNamespace = includedSchema.getTargetNamespace(); 412 if (!incNamespace.equals(myNamespace)) { 413 throw new LocSAXException("Invalid include: The included schemas target namespace " + 414 incNamespace + " and the including schemas target namespace " + 415 myNamespace + " do not match.", 416 pInclude.getLocator()); 417 } 418 } 419 parse(includedSchema, schemaLocation.toString()); 420 } 421 422 private void checkValidImportSchema(XsESchema pImportingSchema, String pNamespace, 423 Locator pLocator) 424 throws SAXException { 425 if (pNamespace == null) { 426 if (pImportingSchema.getTargetNamespace() == null) { 427 throw new LocSAXException("The importing schema has no 'targetNamespace' attribute and" + 428 " the 'import' element has no 'namespace' attribute, which is" + 429 " forbidden. Perhaps you want to use include?", 430 pLocator); 431 } 432 } else { 433 if ("".equals(pNamespace)) { 434 throw new LocSAXException("Invalid import: Empty 'namespace' attribute, which is forbidden." + 435 " Perhaps you want to omit the attribute to indicate the absence of a namespace?", 436 pLocator); 437 } 438 XsAnyURI targetNamespace = pImportingSchema.getTargetNamespace(); 439 if (targetNamespace != null && 440 pNamespace.equals(targetNamespace.toString())) { 441 throw new LocSAXException("The importing schema and the imported schema have the same namespace, which is forbidden. Perhaps you want to use include?", 442 pLocator); 443 } 444 } 445 } 446 447 private void importSchema(XsESchema pImportingSchema, String pNamespace, 448 XsESchema pImportedSchema, Locator pLocator, 449 String pSchemaLocation) 450 throws SAXException, ParserConfigurationException , IOException { 451 XsAnyURI impNamespace = pImportedSchema.getTargetNamespace(); 452 if (pNamespace == null) { 453 if (impNamespace != null) { 454 throw new LocSAXException("The 'import' element does not have a 'namespace' attribute, but the imported schema has target namespace " + 455 impNamespace + ", it ought to match and have none.", 456 pLocator); 457 } 458 } else { 459 if (impNamespace == null) { 460 throw new LocSAXException("The 'import' element has a 'namespace' attribute (" + pNamespace + 461 "), but the imported schema has no 'targetNamespace' attribute.", 462 pLocator); 463 } else if (!pNamespace.equals(impNamespace.toString())) { 464 throw new LocSAXException("The 'import' elements 'namespace' attribute (" + pNamespace + 465 ") and the imported schemas 'targetNamespace' attribute (" + 466 impNamespace + ") do not match.", 467 pLocator); 468 } 469 } 470 parse(pImportedSchema, pSchemaLocation); 471 } 472 473 475 protected void importSchema(XsESchema pImportingSchema, 476 String pNamespace, String pSchemaLocation, 477 Locator pLocator) 478 throws SAXException, IOException , ParserConfigurationException { 479 if (pSchemaLocation == null) { 480 return; 481 } 482 checkValidImportSchema(pImportingSchema, pNamespace, pLocator); 483 484 XsESchema importedSchema = parseSyntax(pLocator, pSchemaLocation); 485 importSchema(pImportingSchema, pNamespace, importedSchema, pLocator, pSchemaLocation); 486 } 487 488 protected void importSchema(XsESchema pImportingSchema, String pNamespace, Node pNode, 489 String pSchemaLocation) 490 throws SAXException, IOException , ParserConfigurationException { 491 checkValidImportSchema(pImportingSchema, pNamespace, null); 492 XsESchema importedSchema = parseSyntax(pNode); 493 importSchema(pImportingSchema, pNamespace, importedSchema, null, pSchemaLocation); 494 } 495 496 500 protected void parse(XsESchema pSyntaxSchema, String pSchemaLocation) 501 throws ParserConfigurationException , SAXException, IOException { 502 if (pSchemaLocation != null) { 503 AddedImport schema = new AddedImport(pSyntaxSchema.getTargetNamespace(), 504 pSchemaLocation); 505 if (parsedSchemas == null) { 506 parsedSchemas = new HashSet (); 507 } else if (parsedSchemas.contains(schema)) { 508 return; } 510 parsedSchemas.add(schema); 511 512 for (int i = 0; i < addedImports.size(); i++) { 513 AddedImport addedImport = (AddedImport) addedImports.get(i); 514 if (schema.equals(addedImport)) { 515 return; 516 } 517 } 518 } 519 addSyntaxSchema(pSyntaxSchema); 520 try { 521 Object [] childs = pSyntaxSchema.getChilds(); 522 523 for (int i = 0; i < childs.length; i++) { 524 Object o = childs[i]; 525 if (o instanceof XsEInclude) { 526 includeSchema(pSyntaxSchema, (XsEInclude) o); 527 } else if (o instanceof XsERedefine) { 528 redefineSchema(pSyntaxSchema, (XsERedefine) o); 529 } else if (o instanceof XsEImport) { 530 XsEImport xsEImport = (XsEImport) o; 531 XsAnyURI namespace = xsEImport.getNamespace(); 532 XsAnyURI schemaLocation = xsEImport.getSchemaLocation(); 533 importSchema(pSyntaxSchema, namespace == null ? null : namespace.toString(), 534 schemaLocation == null ? null : schemaLocation.toString(), 535 xsEImport.getLocator()); 536 } else { 537 add(pSyntaxSchema, childs[i]); 538 } 539 } 540 } finally { 541 removeSyntaxSchema(); 542 } 543 } 544 545 546 private static class SubstitutionGroup { 547 private final List members = new ArrayList (); 548 private final XSElement head; 549 550 public SubstitutionGroup(XSElement pHead) { 551 head = pHead; 552 } 553 public XSElement getHead() { return head; } 554 public XSElement[] getMembers() { 555 return (XSElement[]) members.toArray(new XSElement[members.size()]); 556 } 557 public void addMember(XSElement pElement) { 558 members.add(pElement); 559 } 560 } 561 562 protected void createSubstitutionGroups(XSSchema pSchema) throws SAXException { 563 Object [] myChilds = pSchema.getChilds(); 564 565 Map substitutionGroups = new HashMap (); 567 for (int i = 0; i < myChilds.length; i++) { 568 if (myChilds[i] instanceof XSElement) { 569 XSElement element = (XSElement) myChilds[i]; 570 XsQName qName = element.getSubstitutionGroupName(); 571 if (qName != null) { 572 SubstitutionGroup group = (SubstitutionGroup) substitutionGroups.get(qName); 573 if (group == null) { 574 XSElement head = pSchema.getElement(qName); 575 if (head == null) { 576 throw new LocSAXException("The substituted element " + qName + " is missing in the schema.", 577 element.getLocator()); 578 } 579 if (head.isBlockedForSubstitution()) { 580 throw new LocSAXException("The substituted element " + qName + " is blocked for substitution.", 581 element.getLocator()); 582 } 583 group = new SubstitutionGroup(head); 584 if (!head.isAbstract()) { 585 group.addMember(head); 586 } 587 substitutionGroups.put(qName, group); 588 } 589 group.addMember(element); 590 } 591 } 592 } 593 594 for (Iterator iter = substitutionGroups.values().iterator(); iter.hasNext(); ) { 597 SubstitutionGroup group = (SubstitutionGroup) iter.next(); 598 XSElementImpl head = (XSElementImpl) group.getHead(); 599 XsObject object = head.getXsObject(); 600 XsESchema syntaxSchema = object.getXsESchema(); 601 602 String namespace = syntaxSchema.getTargetNamespace().toString(); 604 String localName = head.getName().getLocalName() + "Group"; 605 XsQName suggestion = new XsQName(namespace, localName); 606 if (pSchema.getGroup(suggestion) != null) { 607 for (int i = 0; ; i++) { 608 suggestion = new XsQName(namespace, localName + i); 609 if (pSchema.getGroup(suggestion) == null) { 610 break; 611 } 612 } 613 } 614 615 XsTNamedGroup namedGroup = object.getObjectFactory().newXsTNamedGroup(syntaxSchema); 616 namedGroup.setName(new XsNCName(suggestion.getLocalName())); 617 XsTSimpleExplicitGroup choice = namedGroup.createChoice(); 618 XSElement[] members = group.getMembers(); 619 for (int j = 0; j < members.length; j++) { 620 XSElement member = members[j]; 621 XsTLocalElement memberElement = choice.createElement(); 622 memberElement.setRef(member.getName()); 623 } 624 625 XSGroupImpl xsGroup = (XSGroupImpl) getSchema().getXSObjectFactory().newXSGroup(pSchema, namedGroup); 626 pSchema.add(xsGroup); 627 head.setSubstitutionGroup(xsGroup); 628 } 629 } 630 631 637 public XSContentHandler getXSContentHandler(String pSystemId) throws SAXException { 638 return new XSContentHandlerImpl(this, pSystemId); 639 } 640 641 643 public XSSchema parse(Node pNode) throws SAXException { 644 XSContentHandler handler = getXSContentHandler(null); 645 DOMSerializer ds = new DOMSerializer(); 646 ds.serialize(pNode, handler); 647 return handler.getXSSchema(); 648 } 649 650 656 public XSSchema parse(InputSource pSource) 657 throws ParserConfigurationException , SAXException, IOException { 658 XSContentHandler contentHandler = getXSContentHandler(pSource.getSystemId()); 659 XSContext data = getData(); 660 XMLReader xr = data.getXsObjectFactory().newXMLReader(isValidating()); 661 xr.setContentHandler(contentHandler); 662 xr.parse(pSource); 663 return getSchema(); 664 } 665 666 protected void clearSyntaxSchemas() { 667 syntaxSchemas.clear(); 668 syntaxSchemaArray = null; 669 } 670 671 protected void addSyntaxSchema(XsESchema pSyntaxSchema) { 672 syntaxSchemas.add(pSyntaxSchema); 673 syntaxSchemaArray = null; 674 } 675 676 protected void removeSyntaxSchema() { 677 syntaxSchemas.remove(syntaxSchemas.size()-1); 678 syntaxSchemaArray = null; 679 } 680 681 685 public XsESchema[] getSyntaxSchemas() { 686 if (syntaxSchemaArray == null) { 687 syntaxSchemaArray = (XsESchema[]) syntaxSchemas.toArray(new XsESchema[syntaxSchemas.size()]); 688 } 689 return syntaxSchemaArray; 690 } 691 692 694 public XsESchema getCurrentSyntaxSchema() { 695 if (syntaxSchemaArray == null || syntaxSchemaArray.length == 0) { 696 return null; 697 } else { 698 return syntaxSchemaArray[syntaxSchemaArray.length-1]; 699 } 700 } 701 } 702 | Popular Tags |