1 22 package org.jboss.xb.binding; 23 24 import java.io.InputStream ; 25 import java.io.Reader ; 26 import java.security.AccessController ; 27 import java.security.PrivilegedAction ; 28 import java.util.StringTokenizer ; 29 30 import javax.xml.XMLConstants ; 31 import javax.xml.namespace.QName ; 32 import javax.xml.namespace.NamespaceContext ; 33 34 import org.apache.xerces.xs.XSImplementation; 35 import org.apache.xerces.xs.XSLoader; 36 import org.apache.xerces.xs.XSModel; 37 import org.jboss.logging.Logger; 38 import org.jboss.util.Classes; 39 import org.jboss.xb.binding.sunday.unmarshalling.LSInputAdaptor; 40 import org.jboss.xb.binding.sunday.unmarshalling.SchemaBindingResolver; 41 import org.jboss.xb.binding.sunday.unmarshalling.XsdBinderTerminatingErrorHandler; 42 import org.w3c.dom.DOMConfiguration ; 43 import org.w3c.dom.DOMErrorHandler ; 44 import org.w3c.dom.bootstrap.DOMImplementationRegistry ; 45 import org.w3c.dom.ls.LSInput ; 46 import org.w3c.dom.ls.LSResourceResolver ; 47 import org.xml.sax.Attributes ; 48 49 55 public final class Util 56 { 57 61 public static final char HYPHEN_MINUS = '\u002D'; 62 public static final char FULL_STOP = '\u002E'; 63 public static final char COLLON = '\u003A'; 64 public static final char LOW_LINE = '\u005F'; 65 public static final char MIDDLE_DOT = '\u00B7'; 66 public static final char GREEK_ANO_TELEIA = '\u0387'; 67 public static final char ARABIC_END_OF_AYAH = '\u06DD'; 68 public static final char ARABIC_START_OF_RUB_EL_HIZB = '\u06DE'; 69 70 private static final Logger log = Logger.getLogger(Util.class); 71 72 private static XSImplementation xsImpl; 73 74 82 public static String getPrefixedName(QName qName) 83 { 84 String result = ""; 85 if(qName != null) 86 { 87 String prefix = qName.getPrefix(); 88 if(prefix.length() > 0) 89 { 90 result = prefix + ':' + qName.getLocalPart(); 91 } 92 else 93 { 94 result = qName.getLocalPart(); 95 } 96 } 97 return result; 98 } 99 100 110 public static String getPrefixedName(QName qName, NamespaceContext nc) 111 { 112 String result = ""; 113 if(qName != null) 114 { 115 String prefix = qName.getPrefix(); 116 if(prefix.length() > 0) 117 { 118 result = prefix + ':' + qName.getLocalPart(); 119 } 120 else 121 { 122 String ns = qName.getNamespaceURI(); 123 prefix = nc.getPrefix(ns); 124 if(prefix != null && prefix.length() > 0) 125 { 126 result = prefix + ':' + qName.getLocalPart(); 127 } 128 else 129 { 130 result = qName.getLocalPart(); 131 } 132 } 133 } 134 return result; 135 } 136 137 147 public static String xmlNameToClassName(String name, boolean ignoreLowLine) 148 { 149 return XMLNameToJavaIdentifierConverter.PARSER.parse(XMLNameToJavaIdentifierConverter.CLASS_NAME, 150 name, 151 ignoreLowLine 152 ); 153 } 154 155 public static String xmlNameToFieldName(String name, boolean ignoreLowLine) 156 { 157 return XMLNameToJavaIdentifierConverter.PARSER.parse(XMLNameToJavaIdentifierConverter.FIELD_NAME, 158 name, 159 ignoreLowLine 160 ); 161 } 162 163 173 public static String xmlNameToGetMethodName(String name, boolean ignoreLowLine) 174 { 175 return "get" + xmlNameToClassName(name, ignoreLowLine); 176 } 177 178 188 public static String xmlNameToSetMethodName(String name, boolean ignoreLowLine) 189 { 190 return "set" + xmlNameToClassName(name, ignoreLowLine); 191 } 192 193 202 public static String xmlNameToConstantName(String name) 203 { 204 return XMLNameToJavaIdentifierConverter.PARSER.parse(XMLNameToJavaIdentifierConverter.CONSTANT_NAME, 205 name, 206 true 207 ); 208 } 209 210 217 public static String xmlNamespaceToJavaPackage(String namespace) 218 { 219 if(namespace.length() == 0) 220 { 221 return namespace; 222 } 223 224 char[] src = namespace.toLowerCase().toCharArray(); 225 char[] dst = new char[namespace.length()]; 226 227 int srcInd = 0; 228 while(src[srcInd++] != ':') 230 { 231 } 232 233 while(src[srcInd] == '/') 234 { 235 ++srcInd; 236 } 237 238 if(src[srcInd] == 'w' && src[srcInd + 1] == 'w' && src[srcInd + 2] == 'w') 240 { 241 srcInd += 4; 242 } 243 244 int domainStart = srcInd; 246 while(srcInd < src.length && src[srcInd] != '/') 247 { 248 ++srcInd; 249 } 250 251 int dstInd = 0; 252 for(int start = srcInd - 1, end = srcInd; true; --start) 254 { 255 if(start == domainStart) 256 { 257 System.arraycopy(src, start, dst, dstInd, end - start); 258 dstInd += end - start; 259 break; 260 } 261 262 if(src[start] == '.') 263 { 264 System.arraycopy(src, start + 1, dst, dstInd, end - start - 1); 265 dstInd += end - start; 266 dst[dstInd - 1] = '.'; 267 end = start; 268 } 269 } 270 271 while(srcInd < src.length) 273 { 274 char c = src[srcInd++]; 275 if(c == '/') 276 { 277 if(srcInd < src.length) 278 { 279 dst = append(dst, dstInd++, '.'); 280 if(!Character.isJavaIdentifierStart(src[srcInd])) 281 { 282 dst = append(dst, dstInd++, '_'); 283 } 284 } 285 } 286 else if(c == '.') 287 { 288 break; 290 } 291 else 292 { 293 dst = append(dst, dstInd++, Character.isJavaIdentifierPart(c) ? c : '_'); 294 } 295 } 296 297 return String.valueOf(dst, 0, dstInd); 298 } 299 300 308 public static String xmlNameToClassName(String namespaceUri, String localName, boolean ignoreLowLine) 309 { 310 return namespaceUri == null || namespaceUri.length() == 0 ? 311 xmlNameToClassName(localName, ignoreLowLine) : 312 xmlNamespaceToJavaPackage(namespaceUri) + '.' + xmlNameToClassName(localName, ignoreLowLine); 313 } 314 315 public static boolean isAttributeType(final Class type) 316 { 317 return Classes.isPrimitive(type) || 318 type == String .class || 319 type == java.util.Date .class; 320 } 321 322 328 public static String getSchemaLocation(Attributes attrs, String nsUri) 329 { 330 String location = null; 331 String schemaLocation = attrs.getValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "schemaLocation"); 332 if(schemaLocation != null) 333 { 334 StringTokenizer tokenizer = new StringTokenizer (schemaLocation, " \t\n\r"); 335 while (tokenizer.hasMoreTokens()) 336 { 337 String namespace = tokenizer.nextToken(); 338 if (namespace.equals(nsUri) && tokenizer.hasMoreTokens()) 339 { 340 location = tokenizer.nextToken(); 341 break; 342 } 343 } 344 } 345 return location; 346 } 347 348 public static XSModel loadSchema(String xsdURL, SchemaBindingResolver schemaResolver) 349 { 350 boolean trace = log.isTraceEnabled(); 351 long start = System.currentTimeMillis(); 352 if(trace) 353 log.trace("loading xsd: " + xsdURL); 354 355 if(xsImpl == null) 356 { 357 xsImpl = getXSImplementation(); 358 } 359 360 XSLoader schemaLoader = xsImpl.createXSLoader(null); 361 if(schemaResolver != null) 362 { 363 setResourceResolver(schemaLoader, schemaResolver); 364 } 365 366 setDOMErrorHandler(schemaLoader); 367 XSModel model = schemaLoader.loadURI(xsdURL); 368 if(model == null) 369 { 370 throw new IllegalArgumentException ("Invalid URI for schema: " + xsdURL); 371 } 372 373 if (trace) 374 log.trace("Loaded xsd: " + xsdURL + " in " + (System.currentTimeMillis() - start) + "ms"); 375 return model; 376 } 377 378 public static XSModel loadSchema(InputStream is, String encoding, SchemaBindingResolver schemaResolver) 379 { 380 if(log.isTraceEnabled()) 381 { 382 log.trace("loading xsd from InputStream"); 383 } 384 385 LSInputAdaptor input = new LSInputAdaptor(is, encoding); 386 387 XSImplementation impl = getXSImplementation(); 388 XSLoader schemaLoader = impl.createXSLoader(null); 389 setDOMErrorHandler(schemaLoader); 390 if(schemaResolver != null) 391 { 392 setResourceResolver(schemaLoader, schemaResolver); 393 } 394 395 return schemaLoader.load(input); 396 } 397 398 public static XSModel loadSchema(Reader reader, String encoding, SchemaBindingResolver schemaResolver) 399 { 400 if(log.isTraceEnabled()) 401 { 402 log.trace("loading xsd from Reader"); 403 } 404 405 LSInputAdaptor input = new LSInputAdaptor(reader, encoding); 406 407 XSImplementation impl = getXSImplementation(); 408 XSLoader schemaLoader = impl.createXSLoader(null); 409 setDOMErrorHandler(schemaLoader); 410 if(schemaResolver != null) 411 { 412 setResourceResolver(schemaLoader, schemaResolver); 413 } 414 415 return schemaLoader.load(input); 416 } 417 418 public static XSModel loadSchema(String data, String encoding) 419 { 420 if(log.isTraceEnabled()) 421 { 422 log.trace("loading xsd from string"); 423 } 424 425 LSInputAdaptor input = new LSInputAdaptor(data, encoding); 426 427 XSImplementation impl = getXSImplementation(); 428 XSLoader schemaLoader = impl.createXSLoader(null); 429 setDOMErrorHandler(schemaLoader); 430 return schemaLoader.load(input); 431 } 432 433 435 446 private static char[] append(char[] buf, int index, char ch) 447 { 448 if(index >= buf.length) 449 { 450 char[] tmp = buf; 451 buf = new char[index + 4]; 452 System.arraycopy(tmp, 0, buf, 0, tmp.length); 453 } 454 buf[index] = ch; 455 return buf; 456 } 457 458 private static void setResourceResolver(XSLoader schemaLoader, final SchemaBindingResolver schemaResolver) 459 { 460 DOMConfiguration config = schemaLoader.getConfig(); 461 config.setParameter("resource-resolver", new LSResourceResolver () 462 { 463 public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) 464 { 465 if (Constants.NS_XML_SCHEMA.equals(type)) 466 { 467 String schemaLocation = systemId; 468 return schemaResolver.resolveAsLSInput(namespaceURI, baseURI, schemaLocation); 469 } 470 return null; 471 } 472 } 473 ); 474 } 475 476 private static void setDOMErrorHandler(XSLoader schemaLoader) 477 { 478 DOMConfiguration config = schemaLoader.getConfig(); 479 DOMErrorHandler errorHandler = (DOMErrorHandler )config.getParameter("error-handler"); 480 if (errorHandler == null) 481 { 482 config.setParameter("error-handler", XsdBinderTerminatingErrorHandler.newInstance()); 483 } 484 } 485 486 private static XSImplementation getXSImplementation() 487 { 488 return (XSImplementation) AccessController.doPrivileged(new PrivilegedAction () 489 { 490 public Object run() 491 { 492 493 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 495 try 496 { 497 String name = "org.apache.xerces.dom.DOMXSImplementationSourceImpl"; 499 loader.loadClass(name); 500 System.setProperty(DOMImplementationRegistry.PROPERTY, name); 501 } 502 catch(ClassNotFoundException e) 503 { 504 String name = "org.apache.xerces.dom.DOMXSImplementationSourceImpl"; 506 System.setProperty(DOMImplementationRegistry.PROPERTY, name); 507 } 508 509 XSImplementation impl; 510 try 511 { 512 DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance(); 513 impl = (XSImplementation)registry.getDOMImplementation("XS-Loader"); 514 } 515 catch(Exception e) 516 { 517 log.error("Failed to create schema loader.", e); 518 throw new IllegalStateException ("Failed to create schema loader: " + e.getMessage()); 519 } 520 return impl; 521 } 522 }); 523 } 524 525 527 540 interface XMLNameToJavaIdentifierConverter 541 { 542 byte IGNORE = 0; 544 byte APPEND = 1; 545 byte APPEND_WITH_LOW_LINE = 2; 546 byte APPEND_UPPER_CASED = 3; 547 byte APPEND_UPPER_CASED_WITH_LOW_LINE = 4; 548 549 557 byte commandForNext(char prev, char next, boolean ignoreLowLine); 558 559 char firstCharacter(char ch, String str, int secondCharIndex); 560 561 565 final class PARSER 566 { 567 577 static String parse(XMLNameToJavaIdentifierConverter converter, String xmlName, boolean ignoreLowLine) 578 { 579 if(xmlName == null || xmlName.length() == 0) 580 { 581 throw new IllegalArgumentException ("Bad XML name: " + xmlName); 582 } 583 584 char c = xmlName.charAt(0); 585 int i = 1; 586 if(!Character.isJavaIdentifierStart(c) || (c == LOW_LINE && ignoreLowLine)) 587 { 588 while(i < xmlName.length()) 589 { 590 c = xmlName.charAt(i++); 591 if(Character.isJavaIdentifierStart(c) && !(c == LOW_LINE && ignoreLowLine)) 592 { 593 break; 594 } 595 } 596 597 if(i == xmlName.length()) 598 { 599 throw new IllegalArgumentException ( 600 "XML name contains no valid character to start Java identifier: " + xmlName 601 ); 602 } 603 } 604 605 char[] buf = new char[xmlName.length() - i + 1]; 606 buf[0] = converter.firstCharacter(c, xmlName, i); 607 int bufInd = 1; 608 while(i < xmlName.length()) 609 { 610 char prev = c; 611 c = xmlName.charAt(i++); 612 byte command = converter.commandForNext(prev, c, ignoreLowLine); 613 switch(command) 614 { 615 case IGNORE: 616 break; 617 case APPEND: 618 buf = Util.append(buf, bufInd++, c); 619 break; 620 case APPEND_WITH_LOW_LINE: 621 buf = Util.append(buf, bufInd++, LOW_LINE); 622 buf = Util.append(buf, bufInd++, c); 623 break; 624 case APPEND_UPPER_CASED: 625 buf = Util.append(buf, bufInd++, Character.toUpperCase(c)); 626 break; 627 case APPEND_UPPER_CASED_WITH_LOW_LINE: 628 buf = Util.append(buf, bufInd++, LOW_LINE); 629 buf = Util.append(buf, bufInd++, Character.toUpperCase(c)); 630 break; 631 default: 632 throw new IllegalArgumentException ("Unexpected command: " + command); 633 } 634 } 635 636 return new String (buf, 0, bufInd); 637 } 638 } 639 640 643 XMLNameToJavaIdentifierConverter CLASS_NAME = new XMLNameToJavaIdentifierConverter() 644 { 645 public char firstCharacter(char ch, String str, int secondCharIndex) 646 { 647 return Character.toUpperCase(ch); 648 } 649 650 public byte commandForNext(char prev, char next, boolean ignoreLowLine) 651 { 652 byte command; 653 if(Character.isDigit(next)) 654 { 655 command = APPEND; 656 } 657 else if(next == LOW_LINE) 658 { 659 command = ignoreLowLine ? IGNORE : APPEND; 660 } 661 else if(Character.isJavaIdentifierPart(next)) 662 { 663 if(Character.isJavaIdentifierPart(prev) && !Character.isDigit(prev)) 664 { 665 command = prev == LOW_LINE ? APPEND_UPPER_CASED : APPEND; 666 } 667 else 668 { 669 command = APPEND_UPPER_CASED; 670 } 671 } 672 else 673 { 674 command = IGNORE; 675 } 676 return command; 677 } 678 }; 679 680 683 XMLNameToJavaIdentifierConverter FIELD_NAME = new XMLNameToJavaIdentifierConverter() 684 { 685 public char firstCharacter(char ch, String str, int secondCharIndex) 686 { 687 if(Character.isLowerCase(ch)) 688 { 689 return ch; 690 } 691 else 692 { 693 return (str.length() > secondCharIndex && 694 Character.isJavaIdentifierPart(str.charAt(secondCharIndex)) && 695 Character.isUpperCase(str.charAt(secondCharIndex)) 696 ) ? 697 Character.toUpperCase(ch) : 698 Character.toLowerCase(ch); 699 } 700 } 701 702 public byte commandForNext(char prev, char next, boolean ignoreLowLine) 703 { 704 return CLASS_NAME.commandForNext(prev, next, ignoreLowLine); 705 } 706 }; 707 708 711 XMLNameToJavaIdentifierConverter CONSTANT_NAME = new XMLNameToJavaIdentifierConverter() 712 { 713 public char firstCharacter(char ch, String str, int secondCharIndex) 714 { 715 return Character.toUpperCase(ch); 716 } 717 718 public byte commandForNext(char prev, char next, boolean ignoreLowLine) 719 { 720 byte command; 721 if(Character.isDigit(next)) 722 { 723 command = Character.isDigit(prev) ? APPEND : APPEND_UPPER_CASED_WITH_LOW_LINE; 724 } 725 else if(Character.isJavaIdentifierPart(next)) 726 { 727 if(Character.isDigit(prev)) 728 { 729 command = APPEND_UPPER_CASED_WITH_LOW_LINE; 730 } 731 else if(Character.isJavaIdentifierPart(prev)) 732 { 733 command = Character.isUpperCase(next) ? 734 (Character.isUpperCase(prev) ? APPEND_UPPER_CASED : APPEND_WITH_LOW_LINE) : 735 APPEND_UPPER_CASED; 736 } 737 else 738 { 739 command = APPEND_UPPER_CASED_WITH_LOW_LINE; 740 } 741 } 742 else 743 { 744 command = IGNORE; 745 } 746 return command; 747 } 748 }; 749 } 750 } 751 | Popular Tags |