1 /* 2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.xml.internal.rngom.parse.xml; 27 28 import java.util.Enumeration; 29 import java.util.Hashtable; 30 import java.util.Stack; 31 import java.util.Vector; 32 import java.util.List; 33 import java.util.ArrayList; 34 import java.util.Arrays; 35 36 import com.sun.xml.internal.rngom.ast.builder.Annotations; 37 import com.sun.xml.internal.rngom.ast.builder.CommentList; 38 import com.sun.xml.internal.rngom.ast.builder.DataPatternBuilder; 39 import com.sun.xml.internal.rngom.ast.builder.Div; 40 import com.sun.xml.internal.rngom.ast.builder.ElementAnnotationBuilder; 41 import com.sun.xml.internal.rngom.ast.builder.Grammar; 42 import com.sun.xml.internal.rngom.ast.builder.GrammarSection; 43 import com.sun.xml.internal.rngom.ast.builder.Include; 44 import com.sun.xml.internal.rngom.ast.builder.IncludedGrammar; 45 import com.sun.xml.internal.rngom.ast.builder.NameClassBuilder; 46 import com.sun.xml.internal.rngom.ast.builder.SchemaBuilder; 47 import com.sun.xml.internal.rngom.ast.builder.Scope; 48 import com.sun.xml.internal.rngom.ast.om.Location; 49 import com.sun.xml.internal.rngom.ast.om.ParsedElementAnnotation; 50 import com.sun.xml.internal.rngom.ast.om.ParsedNameClass; 51 import com.sun.xml.internal.rngom.ast.om.ParsedPattern; 52 import com.sun.xml.internal.rngom.parse.Context; 53 import com.sun.xml.internal.rngom.parse.IllegalSchemaException; 54 import com.sun.xml.internal.rngom.parse.Parseable; 55 import com.sun.xml.internal.rngom.util.Localizer; 56 import com.sun.xml.internal.rngom.util.Uri; 57 import com.sun.xml.internal.rngom.xml.sax.AbstractLexicalHandler; 58 import com.sun.xml.internal.rngom.xml.sax.XmlBaseHandler; 59 import com.sun.xml.internal.rngom.xml.util.Naming; 60 import com.sun.xml.internal.rngom.xml.util.WellKnownNamespaces; 61 import org.xml.sax.Attributes; 62 import org.xml.sax.ContentHandler; 63 import org.xml.sax.ErrorHandler; 64 import org.xml.sax.Locator; 65 import org.xml.sax.SAXException; 66 import org.xml.sax.SAXNotRecognizedException; 67 import org.xml.sax.SAXNotSupportedException; 68 import org.xml.sax.SAXParseException; 69 import org.xml.sax.XMLReader; 70 import org.xml.sax.helpers.DefaultHandler; 71 72 class SchemaParser { 73 74 private static final String relaxngURIPrefix = 75 WellKnownNamespaces.RELAX_NG.substring(0, WellKnownNamespaces.RELAX_NG.lastIndexOf('/') + 1); 76 static final String relaxng10URI = WellKnownNamespaces.RELAX_NG; 77 private static final Localizer localizer = new Localizer(new Localizer(Parseable.class),SchemaParser.class); 78 79 private String relaxngURI; 80 private final XMLReader xr; 81 private final ErrorHandler eh; 82 private final SchemaBuilder schemaBuilder; 83 /** 84 * The value of the {@link SchemaBuilder#getNameClassBuilder()} 85 * for the {@link #schemaBuilder} object. 86 */ 87 private final NameClassBuilder nameClassBuilder; 88 private ParsedPattern startPattern; 89 private Locator locator; 90 private final XmlBaseHandler xmlBaseHandler = new XmlBaseHandler(); 91 private final ContextImpl context = new ContextImpl(); 92 93 private boolean hadError = false; 94 95 private Hashtable patternTable; 96 private Hashtable nameClassTable; 97 98 static class PrefixMapping { 99 final String prefix; 100 final String uri; 101 final PrefixMapping next; 102 103 PrefixMapping(String prefix, String uri, PrefixMapping next) { 104 this.prefix = prefix; 105 this.uri = uri; 106 this.next = next; 107 } 108 } 109 110 static abstract class AbstractContext extends DtdContext implements Context { 111 PrefixMapping prefixMapping; 112 113 AbstractContext() { 114 prefixMapping = new PrefixMapping("xml", WellKnownNamespaces.XML, null); 115 } 116 117 AbstractContext(AbstractContext context) { 118 super(context); 119 prefixMapping = context.prefixMapping; 120 } 121 122 public String resolveNamespacePrefix(String prefix) { 123 for (PrefixMapping p = prefixMapping; p != null; p = p.next) 124 if (p.prefix.equals(prefix)) 125 return p.uri; 126 return null; 127 } 128 129 public Enumeration prefixes() { 130 Vector v = new Vector(); 131 for (PrefixMapping p = prefixMapping; p != null; p = p.next) { 132 if (!v.contains(p.prefix)) 133 v.addElement(p.prefix); 134 } 135 return v.elements(); 136 } 137 138 public Context copy() { 139 return new SavedContext(this); 140 } 141 } 142 143 static class SavedContext extends AbstractContext { 144 private final String baseUri; 145 SavedContext(AbstractContext context) { 146 super(context); 147 this.baseUri = context.getBaseUri(); 148 } 149 150 public String getBaseUri() { 151 return baseUri; 152 } 153 } 154 155 class ContextImpl extends AbstractContext { 156 public String getBaseUri() { 157 return xmlBaseHandler.getBaseUri(); 158 } 159 } 160 161 static interface CommentHandler { 162 void comment(String value); 163 } 164 165 abstract class Handler implements ContentHandler, CommentHandler { 166 CommentList comments; 167 168 CommentList getComments() { 169 CommentList tem = comments; 170 comments = null; 171 return tem; 172 } 173 174 public void comment(String value) { 175 if (comments == null) 176 comments = schemaBuilder.makeCommentList(); 177 comments.addComment(value, makeLocation()); 178 } 179 public void processingInstruction(String target, String date) { } 180 public void skippedEntity(String name) { } 181 public void ignorableWhitespace(char[] ch, int start, int len) { } 182 public void startDocument() { } 183 public void endDocument() { } 184 public void startPrefixMapping(String prefix, String uri) { 185 context.prefixMapping = new PrefixMapping(prefix, uri, context.prefixMapping); 186 } 187 188 public void endPrefixMapping(String prefix) { 189 context.prefixMapping = context.prefixMapping.next; 190 } 191 192 public void setDocumentLocator(Locator loc) { 193 locator = loc; 194 xmlBaseHandler.setLocator(loc); 195 } 196 } 197 198 abstract class State extends Handler { 199 State parent; 200 String nsInherit; 201 String ns; 202 String datatypeLibrary; 203 /** 204 * The current scope, or null if there's none. 205 */ 206 Scope scope; 207 Location startLocation; 208 Annotations annotations; 209 210 void set() { 211 xr.setContentHandler(this); 212 } 213 214 abstract State create(); 215 abstract State createChildState(String localName) throws SAXException; 216 217 218 void setParent(State parent) { 219 this.parent = parent; 220 this.nsInherit = parent.getNs(); 221 this.datatypeLibrary = parent.datatypeLibrary; 222 this.scope = parent.scope; 223 this.startLocation = makeLocation(); 224 if (parent.comments != null) { 225 annotations = schemaBuilder.makeAnnotations(parent.comments, getContext()); 226 parent.comments = null; 227 } 228 else if (parent instanceof RootState) 229 annotations = schemaBuilder.makeAnnotations(null, getContext()); 230 } 231 232 String getNs() { 233 return ns == null ? nsInherit : ns; 234 } 235 236 boolean isRelaxNGElement(String uri) throws SAXException { 237 return uri.equals(relaxngURI); 238 } 239 240 public void startElement(String namespaceURI, 241 String localName, 242 String qName, 243 Attributes atts) throws SAXException { 244 xmlBaseHandler.startElement(); 245 if (isRelaxNGElement(namespaceURI)) { 246 State state = createChildState(localName); 247 if (state == null) { 248 xr.setContentHandler(new Skipper(this)); 249 return; 250 } 251 state.setParent(this); 252 state.set(); 253 state.attributes(atts); 254 } 255 else { 256 checkForeignElement(); 257 ForeignElementHandler feh = new ForeignElementHandler(this, getComments()); 258 feh.startElement(namespaceURI, localName, qName, atts); 259 xr.setContentHandler(feh); 260 } 261 } 262 263 public void endElement(String namespaceURI, 264 String localName, 265 String qName) throws SAXException { 266 xmlBaseHandler.endElement(); 267 parent.set(); 268 end(); 269 } 270 271 void setName(String name) throws SAXException { 272 error("illegal_name_attribute"); 273 } 274 275 void setOtherAttribute(String name, String value) throws SAXException { 276 error("illegal_attribute_ignored", name); 277 } 278 279 void endAttributes() throws SAXException { 280 } 281 282 void checkForeignElement() throws SAXException { 283 } 284 285 void attributes(Attributes atts) throws SAXException { 286 int len = atts.getLength(); 287 for (int i = 0; i < len; i++) { 288 String uri = atts.getURI(i); 289 if (uri.length() == 0) { 290 String name = atts.getLocalName(i); 291 if (name.equals("name")) 292 setName(atts.getValue(i).trim()); 293 else if (name.equals("ns")) 294 ns = atts.getValue(i); 295 else if (name.equals("datatypeLibrary")) { 296 datatypeLibrary = atts.getValue(i); 297 checkUri(datatypeLibrary); 298 if (!datatypeLibrary.equals("") 299 && !Uri.isAbsolute(datatypeLibrary)) 300 error("relative_datatype_library"); 301 if (Uri.hasFragmentId(datatypeLibrary)) 302 error("fragment_identifier_datatype_library"); 303 datatypeLibrary = Uri.escapeDisallowedChars(datatypeLibrary); 304 } 305 else 306 setOtherAttribute(name, atts.getValue(i)); 307 } 308 else if (uri.equals(relaxngURI)) 309 error("qualified_attribute", atts.getLocalName(i)); 310 else if (uri.equals(WellKnownNamespaces.XML) 311 && atts.getLocalName(i).equals("base")) 312 xmlBaseHandler.xmlBaseAttribute(atts.getValue(i)); 313 else { 314 if (annotations == null) 315 annotations = schemaBuilder.makeAnnotations(null, getContext()); 316 annotations.addAttribute(uri, atts.getLocalName(i), findPrefix(atts.getQName(i), uri), 317 atts.getValue(i), startLocation); 318 } 319 } 320 endAttributes(); 321 } 322 323 abstract void end() throws SAXException; 324 325 void endChild(ParsedPattern pattern) { 326 // XXX cannot happen; throw exception 327 } 328 329 void endChild(ParsedNameClass nc) { 330 // XXX cannot happen; throw exception 331 } 332 333 public void startDocument() { } 334 public void endDocument() { 335 if (comments != null && startPattern != null) { 336 startPattern = schemaBuilder.commentAfter(startPattern, comments); 337 comments = null; 338 } 339 } 340 341 public void characters(char[] ch, int start, int len) throws SAXException { 342 for (int i = 0; i < len; i++) { 343 switch(ch[start + i]) { 344 case ' ': 345 case '\r': 346 case '\n': 347 case '\t': 348 break; 349 default: 350 error("illegal_characters_ignored"); 351 break; 352 } 353 } 354 } 355 356 boolean isPatternNamespaceURI(String s) { 357 return s.equals(relaxngURI); 358 } 359 360 void endForeignChild(ParsedElementAnnotation ea) { 361 if (annotations == null) 362 annotations = schemaBuilder.makeAnnotations(null, getContext()); 363 annotations.addElement(ea); 364 } 365 366 void mergeLeadingComments() { 367 if (comments != null) { 368 if (annotations == null) 369 annotations = schemaBuilder.makeAnnotations(comments, getContext()); 370 else 371 annotations.addLeadingComment(comments); 372 comments = null; 373 } 374 } 375 } 376 377 class ForeignElementHandler extends Handler { 378 final State nextState; 379 ElementAnnotationBuilder builder; 380 final Stack builderStack = new Stack(); 381 StringBuffer textBuf; 382 Location textLoc; 383 384 ForeignElementHandler(State nextState, CommentList comments) { 385 this.nextState = nextState; 386 this.comments = comments; 387 } 388 389 public void startElement(String namespaceURI, String localName, 390 String qName, Attributes atts) { 391 flushText(); 392 if (builder != null) 393 builderStack.push(builder); 394 Location loc = makeLocation(); 395 builder = schemaBuilder.makeElementAnnotationBuilder(namespaceURI, 396 localName, 397 findPrefix(qName, namespaceURI), 398 loc, 399 getComments(), 400 getContext()); 401 int len = atts.getLength(); 402 for (int i = 0; i < len; i++) { 403 String uri = atts.getURI(i); 404 builder.addAttribute(uri, atts.getLocalName(i), findPrefix(atts.getQName(i), uri), 405 atts.getValue(i), loc); 406 } 407 } 408 409 public void endElement(String namespaceURI, String localName, 410 String qName) { 411 flushText(); 412 if (comments != null) 413 builder.addComment(getComments()); 414 ParsedElementAnnotation ea = builder.makeElementAnnotation(); 415 if (builderStack.empty()) { 416 nextState.endForeignChild(ea); 417 nextState.set(); 418 } 419 else { 420 builder = (ElementAnnotationBuilder)builderStack.pop(); 421 builder.addElement(ea); 422 } 423 } 424 425 public void characters(char ch[], int start, int length) { 426 if (textBuf == null) 427 textBuf = new StringBuffer(); 428 textBuf.append(ch, start, length); 429 if (textLoc == null) 430 textLoc = makeLocation(); 431 } 432 433 public void comment(String value) { 434 flushText(); 435 super.comment(value); 436 } 437 438 void flushText() { 439 if (textBuf != null && textBuf.length() != 0) { 440 builder.addText(textBuf.toString(), textLoc, getComments()); 441 textBuf.setLength(0); 442 } 443 textLoc = null; 444 } 445 } 446 447 class Skipper extends DefaultHandler implements CommentHandler { 448 int level = 1; 449 final State nextState; 450 451 Skipper(State nextState) { 452 this.nextState = nextState; 453 } 454 455 public void startElement(String namespaceURI, 456 String localName, 457 String qName, 458 Attributes atts) throws SAXException { 459 ++level; 460 } 461 462 public void endElement(String namespaceURI, 463 String localName, 464 String qName) throws SAXException { 465 if (--level == 0) 466 nextState.set(); 467 } 468 469 public void comment(String value) { 470 } 471 } 472 473 abstract class EmptyContentState extends State { 474 475 State createChildState(String localName) throws SAXException { 476 error("expected_empty", localName); 477 return null; 478 } 479 480 abstract ParsedPattern makePattern() throws SAXException; 481 482 void end() throws SAXException { 483 if (comments != null) { 484 if (annotations == null) 485 annotations = schemaBuilder.makeAnnotations(null, getContext()); 486 annotations.addComment(comments); 487 comments = null; 488 } 489 parent.endChild(makePattern()); 490 } 491 } 492 493 static private final int INIT_CHILD_ALLOC = 5; 494 495 abstract class PatternContainerState extends State { 496 List<ParsedPattern> childPatterns; 497 498 State createChildState(String localName) throws SAXException { 499 State state = (State)patternTable.get(localName); 500 if (state == null) { 501 error("expected_pattern", localName); 502 return null; 503 } 504 return state.create(); 505 } 506 507 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { 508 if (patterns.size() == 1 && anno == null) 509 return patterns.get(0); 510 return schemaBuilder.makeGroup(patterns, loc, anno); 511 } 512 513 void endChild(ParsedPattern pattern) { 514 if (childPatterns == null) 515 childPatterns = new ArrayList<ParsedPattern>(INIT_CHILD_ALLOC); 516 childPatterns.add(pattern); 517 } 518 519 void endForeignChild(ParsedElementAnnotation ea) { 520 if (childPatterns == null) 521 super.endForeignChild(ea); 522 else { 523 int idx = childPatterns.size()-1; 524 childPatterns.set(idx, schemaBuilder.annotateAfter(childPatterns.get(idx), ea)); 525 } 526 } 527 528 void end() throws SAXException { 529 if (childPatterns == null) { 530 error("missing_children"); 531 endChild(schemaBuilder.makeErrorPattern()); 532 } 533 if (comments != null) { 534 int idx = childPatterns.size()-1; 535 childPatterns.set(idx,schemaBuilder.commentAfter(childPatterns.get(idx), comments)); 536 comments = null; 537 } 538 sendPatternToParent(buildPattern(childPatterns, startLocation, annotations)); 539 } 540 541 void sendPatternToParent(ParsedPattern p) { 542 parent.endChild(p); 543 } 544 } 545 546 class GroupState extends PatternContainerState { 547 State create() { 548 return new GroupState(); 549 } 550 } 551 552 class ZeroOrMoreState extends PatternContainerState { 553 State create() { 554 return new ZeroOrMoreState(); 555 } 556 557 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { 558 return schemaBuilder.makeZeroOrMore(super.buildPattern(patterns, loc, null), loc, anno); 559 } 560 } 561 562 class OneOrMoreState extends PatternContainerState { 563 State create() { 564 return new OneOrMoreState(); 565 } 566 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { 567 return schemaBuilder.makeOneOrMore(super.buildPattern(patterns, loc, null), loc, anno); 568 } 569 } 570 571 class OptionalState extends PatternContainerState { 572 State create() { 573 return new OptionalState(); 574 } 575 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { 576 return schemaBuilder.makeOptional(super.buildPattern(patterns, loc, null), loc, anno); 577 } 578 } 579 580 class ListState extends PatternContainerState { 581 State create() { 582 return new ListState(); 583 } 584 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { 585 return schemaBuilder.makeList(super.buildPattern(patterns, loc, null), loc, anno); 586 } 587 } 588 589 class ChoiceState extends PatternContainerState { 590 State create() { 591 return new ChoiceState(); 592 } 593 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { 594 return schemaBuilder.makeChoice(patterns, loc, anno); 595 } 596 } 597 598 class InterleaveState extends PatternContainerState { 599 State create() { 600 return new InterleaveState(); 601 } 602 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) { 603 return schemaBuilder.makeInterleave(patterns, loc, anno); 604 } 605 } 606 607 class MixedState extends PatternContainerState { 608 State create() { 609 return new MixedState(); 610 } 611 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { 612 return schemaBuilder.makeMixed(super.buildPattern(patterns, loc, null), loc, anno); 613 } 614 } 615 616 static interface NameClassRef { 617 void setNameClass(ParsedNameClass nc); 618 } 619 620 class ElementState extends PatternContainerState implements NameClassRef { 621 ParsedNameClass nameClass; 622 boolean nameClassWasAttribute; 623 String name; 624 625 void setName(String name) { 626 this.name = name; 627 } 628 629 public void setNameClass(ParsedNameClass nc) { 630 nameClass = nc; 631 } 632 633 void endAttributes() throws SAXException { 634 if (name != null) { 635 nameClass = expandName(name, getNs(), null); 636 nameClassWasAttribute = true; 637 } 638 else 639 new NameClassChildState(this, this).set(); 640 } 641 642 State create() { 643 return new ElementState(); 644 } 645 646 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { 647 return schemaBuilder.makeElement(nameClass, super.buildPattern(patterns, loc, null), loc, anno); 648 } 649 650 void endForeignChild(ParsedElementAnnotation ea) { 651 if (nameClassWasAttribute || childPatterns!=null || nameClass == null) 652 super.endForeignChild(ea); 653 else 654 nameClass = nameClassBuilder.annotateAfter(nameClass, ea); 655 } 656 } 657 658 class RootState extends PatternContainerState { 659 IncludedGrammar grammar; 660 661 RootState() { 662 } 663 664 RootState(IncludedGrammar grammar, Scope scope, String ns) { 665 this.grammar = grammar; 666 this.scope = scope; 667 this.nsInherit = ns; 668 this.datatypeLibrary = ""; 669 } 670 671 State create() { 672 return new RootState(); 673 } 674 675 State createChildState(String localName) throws SAXException { 676 if (grammar == null) 677 return super.createChildState(localName); 678 if (localName.equals("grammar")) 679 return new MergeGrammarState(grammar); 680 error("expected_grammar", localName); 681 return null; 682 } 683 684 void checkForeignElement() throws SAXException { 685 error("root_bad_namespace_uri", WellKnownNamespaces.RELAX_NG); 686 } 687 688 void endChild(ParsedPattern pattern) { 689 startPattern = pattern; 690 } 691 692 boolean isRelaxNGElement(String uri) throws SAXException { 693 if (!uri.startsWith(relaxngURIPrefix)) 694 return false; 695 if (!uri.equals(WellKnownNamespaces.RELAX_NG)) 696 warning("wrong_uri_version", 697 WellKnownNamespaces.RELAX_NG.substring(relaxngURIPrefix.length()), 698 uri.substring(relaxngURIPrefix.length())); 699 relaxngURI = uri; 700 return true; 701 } 702 703 } 704 705 class NotAllowedState extends EmptyContentState { 706 State create() { 707 return new NotAllowedState(); 708 } 709 710 ParsedPattern makePattern() { 711 return schemaBuilder.makeNotAllowed(startLocation, annotations); 712 } 713 } 714 715 class EmptyState extends EmptyContentState { 716 State create() { 717 return new EmptyState(); 718 } 719 720 ParsedPattern makePattern() { 721 return schemaBuilder.makeEmpty(startLocation, annotations); 722 } 723 } 724 725 class TextState extends EmptyContentState { 726 State create() { 727 return new TextState(); 728 } 729 730 ParsedPattern makePattern() { 731 return schemaBuilder.makeText(startLocation, annotations); 732 } 733 } 734 735 class ValueState extends EmptyContentState { 736 final StringBuffer buf = new StringBuffer(); 737 String type; 738 739 State create() { 740 return new ValueState(); 741 } 742 743 void setOtherAttribute(String name, String value) throws SAXException { 744 if (name.equals("type")) 745 type = checkNCName(value.trim()); 746 else 747 super.setOtherAttribute(name, value); 748 } 749 750 public void characters(char[] ch, int start, int len) { 751 buf.append(ch, start, len); 752 } 753 754 void checkForeignElement() throws SAXException { 755 error("value_contains_foreign_element"); 756 } 757 758 ParsedPattern makePattern() throws SAXException { 759 if (type == null) 760 return makePattern("", "token"); 761 else 762 return makePattern(datatypeLibrary, type); 763 } 764 765 void end() throws SAXException { 766 mergeLeadingComments(); 767 super.end(); 768 } 769 770 ParsedPattern makePattern(String datatypeLibrary, String type) { 771 return schemaBuilder.makeValue(datatypeLibrary, 772 type, 773 buf.toString(), 774 getContext(), 775 getNs(), 776 startLocation, 777 annotations); 778 } 779 780 } 781 782 class DataState extends State { 783 String type; 784 ParsedPattern except = null; 785 DataPatternBuilder dpb = null; 786 787 State create() { 788 return new DataState(); 789 } 790 791 State createChildState(String localName) throws SAXException { 792 if (localName.equals("param")) { 793 if (except != null) 794 error("param_after_except"); 795 return new ParamState(dpb); 796 } 797 if (localName.equals("except")) { 798 if (except != null) 799 error("multiple_except"); 800 return new ChoiceState(); 801 } 802 error("expected_param_except", localName); 803 return null; 804 } 805 806 void setOtherAttribute(String name, String value) throws SAXException { 807 if (name.equals("type")) 808 type = checkNCName(value.trim()); 809 else 810 super.setOtherAttribute(name, value); 811 } 812 813 void endAttributes() throws SAXException { 814 if (type == null) 815 error("missing_type_attribute"); 816 else 817 dpb = schemaBuilder.makeDataPatternBuilder(datatypeLibrary, type, startLocation); 818 } 819 820 void endForeignChild(ParsedElementAnnotation ea) { 821 dpb.annotation(ea); 822 } 823 824 void end() throws SAXException { 825 ParsedPattern p; 826 if (dpb != null) { 827 if (except != null) 828 p = dpb.makePattern(except, startLocation, annotations); 829 else 830 p = dpb.makePattern(startLocation, annotations); 831 } 832 else 833 p = schemaBuilder.makeErrorPattern(); 834 // XXX need to capture comments 835 parent.endChild(p); 836 } 837 838 void endChild(ParsedPattern pattern) { 839 except = pattern; 840 } 841 842 } 843 844 class ParamState extends State { 845 private final StringBuffer buf = new StringBuffer(); 846 private final DataPatternBuilder dpb; 847 private String name; 848 849 ParamState(DataPatternBuilder dpb) { 850 this.dpb = dpb; 851 } 852 853 State create() { 854 return new ParamState(null); 855 } 856 857 void setName(String name) throws SAXException { 858 this.name = checkNCName(name); 859 } 860 861 void endAttributes() throws SAXException { 862 if (name == null) 863 error("missing_name_attribute"); 864 } 865 866 State createChildState(String localName) throws SAXException { 867 error("expected_empty", localName); 868 return null; 869 } 870 871 public void characters(char[] ch, int start, int len) { 872 buf.append(ch, start, len); 873 } 874 875 void checkForeignElement() throws SAXException { 876 error("param_contains_foreign_element"); 877 } 878 879 void end() throws SAXException { 880 if (name == null) 881 return; 882 if (dpb == null) 883 return; 884 mergeLeadingComments(); 885 dpb.addParam(name, buf.toString(), getContext(), getNs(), startLocation, annotations); 886 } 887 } 888 889 class AttributeState extends PatternContainerState implements NameClassRef { 890 ParsedNameClass nameClass; 891 boolean nameClassWasAttribute; 892 String name; 893 894 State create() { 895 return new AttributeState(); 896 } 897 898 void setName(String name) { 899 this.name = name; 900 } 901 902 public void setNameClass(ParsedNameClass nc) { 903 nameClass = nc; 904 } 905 906 void endAttributes() throws SAXException { 907 if (name != null) { 908 String nsUse; 909 if (ns != null) 910 nsUse = ns; 911 else 912 nsUse = ""; 913 nameClass = expandName(name, nsUse, null); 914 nameClassWasAttribute = true; 915 } 916 else 917 new NameClassChildState(this, this).set(); 918 } 919 920 void endForeignChild(ParsedElementAnnotation ea) { 921 if (nameClassWasAttribute || childPatterns!=null || nameClass == null) 922 super.endForeignChild(ea); 923 else 924 nameClass = nameClassBuilder.annotateAfter(nameClass, ea); 925 } 926 927 void end() throws SAXException { 928 if (childPatterns == null) 929 endChild(schemaBuilder.makeText(startLocation, null)); 930 super.end(); 931 } 932 933 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { 934 return schemaBuilder.makeAttribute(nameClass, super.buildPattern(patterns, loc, null), loc, anno); 935 } 936 937 State createChildState(String localName) throws SAXException { 938 State tem = super.createChildState(localName); 939 if (tem != null && childPatterns!=null) 940 error("attribute_multi_pattern"); 941 return tem; 942 } 943 944 } 945 946 abstract class SinglePatternContainerState extends PatternContainerState { 947 State createChildState(String localName) throws SAXException { 948 if (childPatterns==null) 949 return super.createChildState(localName); 950 error("too_many_children"); 951 return null; 952 } 953 } 954 955 class GrammarSectionState extends State { 956 GrammarSection section; 957 958 GrammarSectionState() { } 959 960 GrammarSectionState(GrammarSection section) { 961 this.section = section; 962 } 963 964 State create() { 965 return new GrammarSectionState(null); 966 } 967 968 State createChildState(String localName) throws SAXException { 969 if (localName.equals("define")) 970 return new DefineState(section); 971 if (localName.equals("start")) 972 return new StartState(section); 973 if (localName.equals("include")) { 974 Include include = section.makeInclude(); 975 if (include != null) 976 return new IncludeState(include); 977 } 978 if (localName.equals("div")) 979 return new DivState(section.makeDiv()); 980 error("expected_define", localName); 981 // XXX better errors 982 return null; 983 } 984 985 void end() throws SAXException { 986 if (comments != null) { 987 section.topLevelComment(comments); 988 comments = null; 989 } 990 } 991 992 void endForeignChild(ParsedElementAnnotation ea) { 993 section.topLevelAnnotation(ea); 994 } 995 } 996 997 class DivState extends GrammarSectionState { 998 final Div div; 999 DivState(Div div) { 1000 super(div); 1001 this.div = div; 1002 } 1003 1004 void end() throws SAXException { 1005 super.end(); 1006 div.endDiv(startLocation, annotations); 1007 } 1008 } 1009 1010 class IncludeState extends GrammarSectionState { 1011 String href; 1012 final Include include; 1013 1014 IncludeState(Include include) { 1015 super(include); 1016 this.include = include; 1017 } 1018 1019 void setOtherAttribute(String name, String value) throws SAXException { 1020 if (name.equals("href")) { 1021 href = value; 1022 checkUri(href); 1023 } 1024 else 1025 super.setOtherAttribute(name, value); 1026 } 1027 1028 void endAttributes() throws SAXException { 1029 if (href == null) 1030 error("missing_href_attribute"); 1031 else 1032 href = resolve(href); 1033 } 1034 1035 void end() throws SAXException { 1036 super.end(); 1037 if (href != null) { 1038 try { 1039 include.endInclude(parseable, href, getNs(), startLocation, annotations); 1040 } 1041 catch (IllegalSchemaException e) { 1042 } 1043 } 1044 } 1045 } 1046 1047 class MergeGrammarState extends GrammarSectionState { 1048 final IncludedGrammar grammar; 1049 MergeGrammarState(IncludedGrammar grammar) { 1050 super(grammar); 1051 this.grammar = grammar; 1052 } 1053 1054 void end() throws SAXException { 1055 super.end(); 1056 parent.endChild(grammar.endIncludedGrammar(startLocation, annotations)); 1057 } 1058 } 1059 1060 class GrammarState extends GrammarSectionState { 1061 Grammar grammar; 1062 1063 void setParent(State parent) { 1064 super.setParent(parent); 1065 grammar = schemaBuilder.makeGrammar(scope); 1066 section = grammar; 1067 scope = grammar; 1068 } 1069 1070 State create() { 1071 return new GrammarState(); 1072 } 1073 1074 void end() throws SAXException { 1075 super.end(); 1076 parent.endChild(grammar.endGrammar(startLocation, annotations)); 1077 } 1078 } 1079 1080 class RefState extends EmptyContentState { 1081 String name; 1082 1083 State create() { 1084 return new RefState(); 1085 } 1086 1087 1088 void endAttributes() throws SAXException { 1089 if (name == null) 1090 error("missing_name_attribute"); 1091 } 1092 1093 void setName(String name) throws SAXException { 1094 this.name = checkNCName(name); 1095 } 1096 1097 ParsedPattern makePattern() throws SAXException { 1098 if (name == null) 1099 return schemaBuilder.makeErrorPattern(); 1100 if(scope==null) { 1101 error("ref_outside_grammar",name); 1102 return schemaBuilder.makeErrorPattern(); 1103 } else 1104 return scope.makeRef(name, startLocation, annotations); 1105 } 1106 } 1107 1108 class ParentRefState extends RefState { 1109 State create() { 1110 return new ParentRefState(); 1111 } 1112 1113 ParsedPattern makePattern() throws SAXException { 1114 if (name == null) 1115 return schemaBuilder.makeErrorPattern(); 1116 if(scope==null) { 1117 error("parent_ref_outside_grammar",name); 1118 return schemaBuilder.makeErrorPattern(); 1119 } else 1120 return scope.makeParentRef(name, startLocation, annotations); 1121 } 1122 } 1123 1124 class ExternalRefState extends EmptyContentState { 1125 String href; 1126 ParsedPattern includedPattern; 1127 1128 State create() { 1129 return new ExternalRefState(); 1130 } 1131 1132 void setOtherAttribute(String name, String value) throws SAXException { 1133 if (name.equals("href")) { 1134 href = value; 1135 checkUri(href); 1136 } 1137 else 1138 super.setOtherAttribute(name, value); 1139 } 1140 1141 void endAttributes() throws SAXException { 1142 if (href == null) 1143 error("missing_href_attribute"); 1144 else 1145 href = resolve(href); 1146 } 1147 1148 ParsedPattern makePattern() { 1149 if (href != null) { 1150 try { 1151 return schemaBuilder.makeExternalRef(parseable, 1152 href, 1153 getNs(), 1154 scope, 1155 startLocation, 1156 annotations); 1157 } 1158 catch (IllegalSchemaException e) { } 1159 } 1160 return schemaBuilder.makeErrorPattern(); 1161 } 1162 } 1163 1164 abstract class DefinitionState extends PatternContainerState { 1165 GrammarSection.Combine combine = null; 1166 final GrammarSection section; 1167 1168 DefinitionState(GrammarSection section) { 1169 this.section = section; 1170 } 1171 1172 void setOtherAttribute(String name, String value) throws SAXException { 1173 if (name.equals("combine")) { 1174 value = value.trim(); 1175 if (value.equals("choice")) 1176 combine = GrammarSection.COMBINE_CHOICE; 1177 else if (value.equals("interleave")) 1178 combine = GrammarSection.COMBINE_INTERLEAVE; 1179 else 1180 error("combine_attribute_bad_value", value); 1181 } 1182 else 1183 super.setOtherAttribute(name, value); 1184 } 1185 1186 ParsedPattern buildPattern(List<ParsedPattern> patterns, Location loc, Annotations anno) throws SAXException { 1187 return super.buildPattern(patterns, loc, null); 1188 } 1189 } 1190 1191 class DefineState extends DefinitionState { 1192 String name; 1193 1194 DefineState(GrammarSection section) { 1195 super(section); 1196 } 1197 1198 State create() { 1199 return new DefineState(null); 1200 } 1201 1202 void setName(String name) throws SAXException { 1203 this.name = checkNCName(name); 1204 } 1205 1206 void endAttributes() throws SAXException { 1207 if (name == null) 1208 error("missing_name_attribute"); 1209 } 1210 1211 void sendPatternToParent(ParsedPattern p) { 1212 if (name != null) 1213 section.define(name, combine, p, startLocation, annotations); 1214 } 1215 1216 } 1217 1218 class StartState extends DefinitionState { 1219 1220 StartState(GrammarSection section) { 1221 super(section); 1222 } 1223 1224 State create() { 1225 return new StartState(null); 1226 } 1227 1228 void sendPatternToParent(ParsedPattern p) { 1229 section.define(GrammarSection.START, combine, p, startLocation, annotations); 1230 } 1231 1232 State createChildState(String localName) throws SAXException { 1233 State tem = super.createChildState(localName); 1234 if (tem != null && childPatterns!=null) 1235 error("start_multi_pattern"); 1236 return tem; 1237 } 1238 1239 } 1240 1241 abstract class NameClassContainerState extends State { 1242 State createChildState(String localName) throws SAXException { 1243 State state = (State)nameClassTable.get(localName); 1244 if (state == null) { 1245 error("expected_name_class", localName); 1246 return null; 1247 } 1248 return state.create(); 1249 } 1250 } 1251 1252 class NameClassChildState extends NameClassContainerState { 1253 final State prevState; 1254 final NameClassRef nameClassRef; 1255 1256 State create() { 1257 return null; 1258 } 1259 1260 NameClassChildState(State prevState, NameClassRef nameClassRef) { 1261 this.prevState = prevState; 1262 this.nameClassRef = nameClassRef; 1263 setParent(prevState.parent); 1264 this.ns = prevState.ns; 1265 } 1266 1267 void endChild(ParsedNameClass nameClass) { 1268 nameClassRef.setNameClass(nameClass); 1269 prevState.set(); 1270 } 1271 1272 void endForeignChild(ParsedElementAnnotation ea) { 1273 prevState.endForeignChild(ea); 1274 } 1275 1276 void end() throws SAXException { 1277 nameClassRef.setNameClass(nameClassBuilder.makeErrorNameClass()); 1278 error("missing_name_class"); 1279 prevState.set(); 1280 prevState.end(); 1281 } 1282 } 1283 1284 abstract class NameClassBaseState extends State { 1285 1286 abstract ParsedNameClass makeNameClass() throws SAXException; 1287 1288 void end() throws SAXException { 1289 parent.endChild(makeNameClass()); 1290 } 1291 } 1292 1293 class NameState extends NameClassBaseState { 1294 final StringBuffer buf = new StringBuffer(); 1295 1296 State createChildState(String localName) throws SAXException { 1297 error("expected_name", localName); 1298 return null; 1299 } 1300 1301 State create() { 1302 return new NameState(); 1303 } 1304 1305 public void characters(char[] ch, int start, int len) { 1306 buf.append(ch, start, len); 1307 } 1308 1309 void checkForeignElement() throws SAXException { 1310 error("name_contains_foreign_element"); 1311 } 1312 1313 ParsedNameClass makeNameClass() throws SAXException { 1314 mergeLeadingComments(); 1315 return expandName(buf.toString().trim(), getNs(), annotations); 1316 } 1317 1318 } 1319 1320 private static final int PATTERN_CONTEXT = 0; 1321 private static final int ANY_NAME_CONTEXT = 1; 1322 private static final int NS_NAME_CONTEXT = 2; 1323 private SAXParseable parseable; 1324 1325 class AnyNameState extends NameClassBaseState { 1326 ParsedNameClass except = null; 1327 1328 State create() { 1329 return new AnyNameState(); 1330 } 1331 1332 State createChildState(String localName) throws SAXException { 1333 if (localName.equals("except")) { 1334 if (except != null) 1335 error("multiple_except"); 1336 return new NameClassChoiceState(getContext()); 1337 } 1338 error("expected_except", localName); 1339 return null; 1340 } 1341 1342 int getContext() { 1343 return ANY_NAME_CONTEXT; 1344 } 1345 1346 ParsedNameClass makeNameClass() { 1347 if (except == null) 1348 return makeNameClassNoExcept(); 1349 else 1350 return makeNameClassExcept(except); 1351 } 1352 1353 ParsedNameClass makeNameClassNoExcept() { 1354 return nameClassBuilder.makeAnyName(startLocation, annotations); 1355 } 1356 1357 ParsedNameClass makeNameClassExcept(ParsedNameClass except) { 1358 return nameClassBuilder.makeAnyName(except, startLocation, annotations); 1359 } 1360 1361 void endChild(ParsedNameClass nameClass) { 1362 except = nameClass; 1363 } 1364 1365 } 1366 1367 class NsNameState extends AnyNameState { 1368 State create() { 1369 return new NsNameState(); 1370 } 1371 1372 ParsedNameClass makeNameClassNoExcept() { 1373 return nameClassBuilder.makeNsName(getNs(), null, null); 1374 } 1375 1376 ParsedNameClass makeNameClassExcept(ParsedNameClass except) { 1377 return nameClassBuilder.makeNsName(getNs(), except, null, null); 1378 } 1379 1380 int getContext() { 1381 return NS_NAME_CONTEXT; 1382 } 1383 1384 } 1385 1386 class NameClassChoiceState extends NameClassContainerState { 1387 private ParsedNameClass[] nameClasses; 1388 private int nNameClasses; 1389 private int context; 1390 1391 NameClassChoiceState() { 1392 this.context = PATTERN_CONTEXT; 1393 } 1394 1395 NameClassChoiceState(int context) { 1396 this.context = context; 1397 } 1398 1399 void setParent(State parent) { 1400 super.setParent(parent); 1401 if (parent instanceof NameClassChoiceState) 1402 this.context = ((NameClassChoiceState)parent).context; 1403 } 1404 1405 State create() { 1406 return new NameClassChoiceState(); 1407 } 1408 1409 State createChildState(String localName) throws SAXException { 1410 if (localName.equals("anyName")) { 1411 if (context >= ANY_NAME_CONTEXT) { 1412 error(context == ANY_NAME_CONTEXT 1413 ? "any_name_except_contains_any_name" 1414 : "ns_name_except_contains_any_name"); 1415 return null; 1416 } 1417 } 1418 else if (localName.equals("nsName")) { 1419 if (context == NS_NAME_CONTEXT) { 1420 error("ns_name_except_contains_ns_name"); 1421 return null; 1422 } 1423 } 1424 return super.createChildState(localName); 1425 } 1426 1427 void endChild(ParsedNameClass nc) { 1428 if (nameClasses == null) 1429 nameClasses = new ParsedNameClass[INIT_CHILD_ALLOC]; 1430 else if (nNameClasses >= nameClasses.length) { 1431 ParsedNameClass[] newNameClasses = new ParsedNameClass[nameClasses.length * 2]; 1432 System.arraycopy(nameClasses, 0, newNameClasses, 0, nameClasses.length); 1433 nameClasses = newNameClasses; 1434 } 1435 nameClasses[nNameClasses++] = nc; 1436 } 1437 1438 void endForeignChild(ParsedElementAnnotation ea) { 1439 if (nNameClasses == 0) 1440 super.endForeignChild(ea); 1441 else 1442 nameClasses[nNameClasses - 1] = nameClassBuilder.annotateAfter(nameClasses[nNameClasses - 1], ea); 1443 } 1444 1445 void end() throws SAXException { 1446 if (nNameClasses == 0) { 1447 error("missing_name_class"); 1448 parent.endChild(nameClassBuilder.makeErrorNameClass()); 1449 return; 1450 } 1451 if (comments != null) { 1452 nameClasses[nNameClasses - 1] = nameClassBuilder.commentAfter(nameClasses[nNameClasses - 1], comments); 1453 comments = null; 1454 } 1455 parent.endChild(nameClassBuilder.makeChoice(Arrays.asList(nameClasses).subList(0,nNameClasses), startLocation, annotations)); 1456 } 1457 } 1458 1459 private void initPatternTable() { 1460 patternTable = new Hashtable(); 1461 patternTable.put("zeroOrMore", new ZeroOrMoreState()); 1462 patternTable.put("oneOrMore", new OneOrMoreState()); 1463 patternTable.put("optional", new OptionalState()); 1464 patternTable.put("list", new ListState()); 1465 patternTable.put("choice", new ChoiceState()); 1466 patternTable.put("interleave", new InterleaveState()); 1467 patternTable.put("group", new GroupState()); 1468 patternTable.put("mixed", new MixedState()); 1469 patternTable.put("element", new ElementState()); 1470 patternTable.put("attribute", new AttributeState()); 1471 patternTable.put("empty", new EmptyState()); 1472 patternTable.put("text", new TextState()); 1473 patternTable.put("value", new ValueState()); 1474 patternTable.put("data", new DataState()); 1475 patternTable.put("notAllowed", new NotAllowedState()); 1476 patternTable.put("grammar", new GrammarState()); 1477 patternTable.put("ref", new RefState()); 1478 patternTable.put("parentRef", new ParentRefState()); 1479 patternTable.put("externalRef", new ExternalRefState()); 1480 } 1481 1482 private void initNameClassTable() { 1483 nameClassTable = new Hashtable(); 1484 nameClassTable.put("name", new NameState()); 1485 nameClassTable.put("anyName", new AnyNameState()); 1486 nameClassTable.put("nsName", new NsNameState()); 1487 nameClassTable.put("choice", new NameClassChoiceState()); 1488 } 1489 1490 public ParsedPattern getParsedPattern() throws IllegalSchemaException { 1491 if (hadError) 1492 throw new IllegalSchemaException(); 1493 return startPattern; 1494 } 1495 1496 private void error(String key) throws SAXException { 1497 error(key, locator); 1498 } 1499 1500 private void error(String key, String arg) throws SAXException { 1501 error(key, arg, locator); 1502 } 1503 1504 void error(String key, String arg1, String arg2) throws SAXException { 1505 error(key, arg1, arg2, locator); 1506 } 1507 1508 private void error(String key, Locator loc) throws SAXException { 1509 error(new SAXParseException(localizer.message(key), loc)); 1510 } 1511 1512 private void error(String key, String arg, Locator loc) throws SAXException { 1513 error(new SAXParseException(localizer.message(key, arg), loc)); 1514 } 1515 1516 private void error(String key, String arg1, String arg2, Locator loc) 1517 throws SAXException { 1518 error(new SAXParseException(localizer.message(key, arg1, arg2), loc)); 1519 } 1520 1521 private void error(SAXParseException e) throws SAXException { 1522 hadError = true; 1523 if (eh != null) 1524 eh.error(e); 1525 } 1526 1527 void warning(String key) throws SAXException { 1528 warning(key, locator); 1529 } 1530 1531 private void warning(String key, String arg) throws SAXException { 1532 warning(key, arg, locator); 1533 } 1534 1535 private void warning(String key, String arg1, String arg2) throws SAXException { 1536 warning(key, arg1, arg2, locator); 1537 } 1538 1539 private void warning(String key, Locator loc) throws SAXException { 1540 warning(new SAXParseException(localizer.message(key), loc)); 1541 } 1542 1543 private void warning(String key, String arg, Locator loc) throws SAXException { 1544 warning(new SAXParseException(localizer.message(key, arg), loc)); 1545 } 1546 1547 private void warning(String key, String arg1, String arg2, Locator loc) 1548 throws SAXException { 1549 warning(new SAXParseException(localizer.message(key, arg1, arg2), loc)); 1550 } 1551 1552 private void warning(SAXParseException e) throws SAXException { 1553 if (eh != null) 1554 eh.warning(e); 1555 } 1556 1557 SchemaParser(SAXParseable parseable, 1558 XMLReader xr, 1559 ErrorHandler eh, 1560 SchemaBuilder schemaBuilder, 1561 IncludedGrammar grammar, 1562 Scope scope, 1563 String inheritedNs) throws SAXException { 1564 this.parseable = parseable; 1565 this.xr = xr; 1566 this.eh = eh; 1567 this.schemaBuilder = schemaBuilder; 1568 this.nameClassBuilder = schemaBuilder.getNameClassBuilder(); 1569 if (eh != null) 1570 xr.setErrorHandler(eh); 1571 xr.setDTDHandler(context); 1572 if (schemaBuilder.usesComments()) { 1573 try { 1574 xr.setProperty("http://xml.org/sax/properties/lexical-handler", new LexicalHandlerImpl()); 1575 } 1576 catch (SAXNotRecognizedException e) { 1577 warning("no_comment_support", xr.getClass().getName()); 1578 } 1579 catch (SAXNotSupportedException e) { 1580 warning("no_comment_support", xr.getClass().getName()); 1581 } 1582 } 1583 initPatternTable(); 1584 initNameClassTable(); 1585 new RootState(grammar, scope, inheritedNs).set(); 1586 } 1587 1588 1589 private Context getContext() { 1590 return context; 1591 } 1592 1593 class LexicalHandlerImpl extends AbstractLexicalHandler { 1594 private boolean inDtd = false; 1595 1596 public void startDTD(String s, String s1, String s2) throws SAXException { 1597 inDtd = true; 1598 } 1599 1600 public void endDTD() throws SAXException { 1601 inDtd = false; 1602 } 1603 1604 public void comment(char[] chars, int start, int length) throws SAXException { 1605 if (!inDtd) 1606 ((CommentHandler)xr.getContentHandler()).comment(new String(chars, start, length)); 1607 } 1608 } 1609 1610 private ParsedNameClass expandName(String name, String ns, Annotations anno) throws SAXException { 1611 int ic = name.indexOf(':'); 1612 if (ic == -1) 1613 return nameClassBuilder.makeName(ns, checkNCName(name), null, null, anno); 1614 String prefix = checkNCName(name.substring(0, ic)); 1615 String localName = checkNCName(name.substring(ic + 1)); 1616 for (PrefixMapping tem = context.prefixMapping; tem != null; tem = tem.next) 1617 if (tem.prefix.equals(prefix)) 1618 return nameClassBuilder.makeName(tem.uri, localName, prefix, null, anno); 1619 error("undefined_prefix", prefix); 1620 return nameClassBuilder.makeName("", localName, null, null, anno); 1621 } 1622 1623 private String findPrefix(String qName, String uri) { 1624 String prefix = null; 1625 if (qName == null || qName.equals("")) { 1626 for (PrefixMapping p = context.prefixMapping; p != null; p = p.next) 1627 if (p.uri.equals(uri)) { 1628 prefix = p.prefix; 1629 break; 1630 } 1631 } 1632 else { 1633 int off = qName.indexOf(':'); 1634 if (off > 0) 1635 prefix = qName.substring(0, off); 1636 } 1637 return prefix; 1638 } 1639 private String checkNCName(String str) throws SAXException { 1640 if (!Naming.isNcname(str)) 1641 error("invalid_ncname", str); 1642 return str; 1643 } 1644 1645 private String resolve(String systemId) throws SAXException { 1646 if (Uri.hasFragmentId(systemId)) 1647 error("href_fragment_id"); 1648 systemId = Uri.escapeDisallowedChars(systemId); 1649 return Uri.resolve(xmlBaseHandler.getBaseUri(), systemId); 1650 } 1651 1652 private Location makeLocation() { 1653 if (locator == null) 1654 return null; 1655 return schemaBuilder.makeLocation(locator.getSystemId(), 1656 locator.getLineNumber(), 1657 locator.getColumnNumber()); 1658 } 1659 1660 private void checkUri(String s) throws SAXException { 1661 if (!Uri.isValid(s)) 1662 error("invalid_uri", s); 1663 } 1664 }