001 package edu.nrao.sss.util; 002 003 import java.io.FileNotFoundException; 004 import java.io.FileReader; 005 import java.io.InputStream; 006 import java.io.Reader; 007 import java.io.StringWriter; 008 import java.io.Writer; 009 import java.net.MalformedURLException; 010 import java.net.URL; 011 import java.util.Properties; 012 013 import javax.xml.XMLConstants; 014 import javax.xml.bind.JAXBContext; 015 import javax.xml.bind.JAXBException; 016 import javax.xml.bind.Marshaller; 017 import javax.xml.bind.PropertyException; 018 import javax.xml.bind.Unmarshaller; 019 import javax.xml.stream.XMLInputFactory; 020 import javax.xml.stream.XMLStreamException; 021 import javax.xml.stream.XMLStreamReader; 022 import javax.xml.validation.Schema; 023 import javax.xml.validation.SchemaFactory; 024 025 import org.apache.log4j.Logger; 026 import org.xml.sax.SAXException; 027 028 /** 029 * A utility for converting an object to XML and vice versa. 030 * <p> 031 * This class will be used primarily in the {@code toXml} and {@code fromXml} 032 * methods of other classes.</p> 033 * <p> 034 * <b><u>How Schema Files are Located and Used</u></b></p> 035 * <p style="margin-left:1em; margin-right:5em; text-align:justify"> 036 * If a transformation method (one that turns XML into an object or vice versa) 037 * takes a {@code Schema} parameter, that schema will be the one used for 038 * validation. If, however, the {@code Schema} parameter is <i>null</i>, 039 * this utility will either attempt to find a default schema or bypass 040 * schema validation, depending on the state of the {@code lookForDefaultSchema} 041 * property of this utility. 042 * </p> 043 * <p style="margin-left:1em; margin-right:5em; text-align:justify"> 044 * The location of the default schema files is given by this utility's 045 * {@code schemaBaseUrl} property. If this property has been set to 046 * <i>null</i>, then the default location for the schema files will be 047 * the location on the classpath of the targeted class. 048 * </p> 049 * <p style="margin-left:1em; margin-right:5em; text-align:justify"> 050 * The name of the primary default schema file, regardless of its 051 * default location, is <tt>theClass.getSimpleName() + ".xsd"</tt>. 052 * If a primary default schema file cannot be found, a secondary default 053 * is used. The name of the secondary default file is <tt>packageName.xsd</tt> 054 * where <tt>packageName</tt> is the "simple" package name. For example, the 055 * simple package name of edu.nrao.sss.model.source is "source", thus the 056 * schema file would be "source.xsd". 057 * </p> 058 * <p style="margin-left:1em; margin-right:5em; text-align:justify"> 059 * <em>New 2008-12-30:</em> 060 * If, in the example above, "source.xsd" is not found, an attempt will 061 * be made to find "model.xsd", "sss.xsd", and so on up the line. 062 * If none of those files exist a log entry will be created and a 063 * <i>null</i> schema will be used. Depending no the particular usage 064 * this could result in an exception or marshalling / unmarshalling 065 * without schema verification. 066 * </p> 067 * <p style="margin-left:1em; margin-right:5em; text-align:justify"> 068 * Note that a default schema file 069 * is sought <i>only</i> when the {@code lookForDefaultSchema} property 070 * is <i>true</i>. If we seek a default schema file but fail to find it, 071 * what happens next depends on the value of the 072 * {@code failIfDefaultSchemaNotFound} property. If that property is 073 * <i>false</i>, transformation occurs without validation. If it is 074 * <i>true</i>, the transformation methods will throw {@code JaxbException}s. 075 * </p> 076 * <p style="margin-left:1em; margin-right:5em; text-align:justify"> 077 * At this time the {@code schemaBaseUrl} can be set only 078 * {@link #setBaseUrlForSchemaFiles(URL) programatically}. A possible future 079 * enhancement would allow the specification of this value via a 080 * properties file.</p> 081 * <p> 082 * <b>Version Info:</b> 083 * <table style="margin-left:2em"> 084 * <tr><td>$Revision: 2276 $</td></tr> 085 * <tr><td>$Date: 2009-04-29 10:34:57 -0600 (Wed, 29 Apr 2009) $</td></tr> 086 * <tr><td>$Author: dharland $</td></tr> 087 * </table></p> 088 * 089 * @author David M. Harland 090 * @since 2006-09-05 091 */ 092 public class JaxbUtility 093 { 094 private static final Logger log = Logger.getLogger(JaxbUtility.class); 095 096 /** Returns a shared, pre-constructed, instance of this utility. */ 097 public static JaxbUtility getSharedInstance() { return sharedInstance; } 098 099 //============================================================================ 100 // CONFIGURING THIS UTILITY 101 //============================================================================ 102 103 private static final String DEFAULT_BASE_URL; 104 105 //Set the default location for the schemas via a properties file 106 static 107 { 108 String url; 109 try 110 { 111 Properties props = new Properties(); 112 113 InputStream file = 114 JaxbUtility.class.getResourceAsStream("jaxbUtility.properties"); 115 116 props.load(file); 117 118 url = props.getProperty("schemaLocation", "https://e2e.nrao.edu/schemas/sss/"); 119 } 120 catch (Exception ex) 121 { 122 url = "https://e2e.nrao.edu/schemas/sss/"; 123 } 124 DEFAULT_BASE_URL = url; 125 } 126 127 private static final JaxbUtility sharedInstance = new JaxbUtility(); 128 129 private SchemaFactory schemaFactory; 130 private URL schemaBaseUrl; 131 private boolean lookForDefaultSchema; 132 private boolean failIfDefaultSchemaNotFound; 133 134 /** Creates a new instance. */ 135 public JaxbUtility() 136 { 137 lookForDefaultSchema = true; 138 failIfDefaultSchemaNotFound = true; 139 140 schemaFactory = 141 SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 142 143 try { 144 schemaBaseUrl = new URL(DEFAULT_BASE_URL); 145 } 146 catch (MalformedURLException ex) { 147 schemaBaseUrl = null; 148 } 149 } 150 151 //============================================================================ 152 // SCHEMA 153 //============================================================================ 154 155 /** 156 * Tells this utility whether or not it should look for a default schema 157 * if one is not specified. A schema is not specified if a method that 158 * takes no schema argument is called, or if a method with a schema 159 * argument is called, but the passed, or resulting, schema is <i>null</i>. 160 * <p> 161 * The default value of this property is <i>true</i>.</p> 162 * <p> 163 * See the note, <i>How Schema Files are Located and Used</i>, at the 164 * {@link JaxbUtility top} of this class for more information about 165 * schema acquisition and usage.</p> 166 * 167 * @param look <i>true</i> if this utility should seek out a default schema. 168 */ 169 public void setLookForDefaultSchema(boolean look) 170 { 171 lookForDefaultSchema = look; 172 } 173 174 /** 175 * Tells this utility whether or not failure to find a default schema 176 * should result in failure of the transformation methods. If this 177 * property is <i>true</i>, those methods will fail with 178 * {@code JaxbException}s. If this property is <i>false</i>, those 179 * methods will perform transformations without validation. 180 * <p> 181 * The default value of this property is <i>true</i>.</p> 182 * 183 * @param fail signals the transformations to fail if a default schema 184 * is sought but not found. 185 */ 186 public void setFailIfDefaultSchemaNotFound(boolean fail) 187 { 188 failIfDefaultSchemaNotFound = fail; 189 } 190 191 /** 192 * Sets the base URL that this utility will use for locating schema files. 193 * To configure this utility so that the default schema files are found 194 * on the classpath, use a parameter of <i>null</i>. 195 * <p> 196 * The default value of this property is 197 * <a href="https://e2e.nrao.edu/schemas/"> 198 * https://e2e.nrao.edu/schemas/</a>.</p> 199 * <p> 200 * See the note, <i>How Schema Files are Located and Used</i>, at the 201 * {@link JaxbUtility top} of this class for more information about 202 * schema acquisition and usage.</p> 203 * 204 * @param baseUrl the base URL that this utility will use for locating schema 205 * files. A value of <i>null</i> may be used to tell this 206 * utility to look for default schema files on the classpath. 207 */ 208 public void setBaseUrlForSchemaFiles(URL baseUrl) 209 { 210 schemaBaseUrl = baseUrl; 211 } 212 213 /** 214 * Returns the base URL that this utility will use for locating schema files. 215 * <p> 216 * See the note, <i>How Schema Files are Located and Used</i>, at the 217 * {@link JaxbUtility top} of this class for more information about 218 * schema acquisition and usage.</p> 219 * 220 * @return the base URL that this utility will use for locating schema files. 221 */ 222 public URL getBaseUrlForSchemaFiles() 223 { 224 return schemaBaseUrl; 225 } 226 227 /** 228 * Attempts to build and return a {@code Schema} to use for objects of the 229 * given class. This method does not look at the value of the 230 * {@link #setLookForDefaultSchema(boolean) lookForDefaultSchema} 231 * property. 232 * 233 * @param c the class for which a schema is desired. 234 * 235 * @return a schema to use for objects of type {@code c}, or <i>null</i> 236 * if no such schema could be found. 237 * 238 * @throws JAXBException if a schema file was found for {@code c} but 239 * something went wrong in the process of turning the file into 240 * a {@code Schema} object. 241 * 242 * @see #getSchema(String, Class) 243 */ 244 public Schema getSchemaFor(Class<?> c) throws JAXBException 245 { 246 //Quick exit for null class 247 if (c == null) 248 return null; 249 250 Schema schema = null; 251 String fileName = c.getSimpleName() + ".xsd"; 252 253 //Look for schemaBaseUrl/className.xsd 254 try 255 { 256 schema = getSchema(fileName, c); 257 } 258 //If we couldn't find the file, look for schemaBaseUrl/packageName.xsd 259 catch (FileNotFoundException ex1) 260 { 261 schema = getSchemaFor(c.getPackage().getName(), c); 262 } 263 //If we did find the file, but it could not be made into a schema, throw 264 catch (Exception ex2) 265 { 266 throw new JAXBException(ex2); 267 } 268 269 //This will be null if no schema was found 270 return schema; 271 } 272 273 private Schema getSchemaFor(String packageName, Class<?> c) throws JAXBException 274 { 275 Schema schema = null; 276 277 String[] pkgComponent = packageName.split("\\."); 278 279 //If pkg name is x.y.z, first try z.xsd, then y.xsd, then x.xsd. 280 //Stop at first file found. If none found, log finding and return null. 281 for (int i=pkgComponent.length-1; i >= 0; i--) 282 { 283 String fileName = pkgComponent[i] + ".xsd"; 284 try 285 { 286 schema = getSchema(fileName, c); 287 break; //success 288 } 289 //If package schema not found, result will be null 290 catch (FileNotFoundException exA) 291 { 292 if (i == 0) 293 log.warn("Could find no schema for class " + c.getName()); 294 } 295 //If pkg schema was found but could not be made into schema, throw 296 catch (Exception exB) 297 { 298 throw new JAXBException(exB); 299 } 300 } 301 302 return schema; 303 } 304 305 /** 306 * Attempts to build and return a {@code Schema} based on the given 307 * URL to use for objects of the given class. The class <tt>c</tt> 308 * is used only if the {@link #setBaseUrlForSchemaFiles(URL) 309 * base URL} used by this utility is <i>null</i>. 310 * 311 * @param relativeUrl typically the name of the schema file 312 * 313 * @param c the class used to locate the schema file, but only in 314 * the event that the {@link #setBaseUrlForSchemaFiles(URL) 315 * base URL} used by this utility is <i>null</i>. 316 * 317 * @return a schema, or <i>null</i> if one could not be created. 318 * 319 * @throws FileNotFoundException if URL can't be found. 320 * 321 * @throws SAXException if URL found but can't be turned into schema. 322 */ 323 public Schema getSchema(String relativeUrl, Class<?> c) 324 throws FileNotFoundException, SAXException 325 { 326 URL schemaUrl = null; 327 328 //See if we can find a schema file at the URL 329 try 330 { 331 schemaUrl = 332 (schemaBaseUrl == null) ? c.getResource(relativeUrl) 333 : new URL(schemaBaseUrl, relativeUrl); 334 log.debug("Looking for XML schema: " + schemaUrl.toString()); 335 schemaUrl.openConnection().getContent(); 336 } 337 //If not, report file-not-found 338 catch (Exception ex1) 339 { 340 throw new FileNotFoundException("Could not find schema file " + 341 (schemaBaseUrl == null ? 342 "CLASSPATH:" : 343 schemaBaseUrl.toExternalForm() 344 ) + relativeUrl); 345 } 346 347 //Return schema or throw parsing exception 348 log.debug(" Reading XML schema: " + (schemaUrl==null? "NULL" : schemaUrl.toString())); 349 350 return schemaFactory.newSchema(schemaUrl); 351 } 352 353 //============================================================================ 354 // MAIN METHODS 355 //============================================================================ 356 357 /** 358 * Writes {@code o} as XML to {@code writer}, using {@code schema} for 359 * validation. 360 * <p> 361 * If {@code schema} is non-null, it is used to validate the contents 362 * of this object while converting it to XML. 363 * If {@code schema} is <i>null</i>, one of two approaches will be 364 * taken, depending on the state of the {@code lookForDefaultSchema} 365 * property: 366 * <ol> 367 * <li>If <i>false</i>, the object {@code o} will be transformed into XML 368 * without validation against a schema.</li> 369 * <li>If <i>true</i>, this utility will attempt to locate a default 370 * schema (see {@link #setLookForDefaultSchema(boolean)}. If found, it 371 * will be used to validate the object {@code o} during the 372 * transformation to XML. If not found, the object {@code o} will be 373 * transformed into XML without validation against a schema.</li> 374 * </ol></p> 375 * <p> 376 * If there are any problems encountered during the transformation to XML, 377 * a {@code JAXBException} will be thrown.</p> 378 * 379 * @param writer the device to which XML is written. 380 * If this value is <i>null</i>, no action is taken. 381 * 382 * @param o the object to be expressed in XML. 383 * If this value is <i>null</i>, no action is taken. 384 * 385 * @param schema the holder of the rules for validating the XML output. 386 * If this value is <i>null</i>, and if 387 * {@link #setLookForDefaultSchema(boolean)} was called 388 * most recently with a value of <i>true</i>, an attempt 389 * will be made to locate a default schema. 390 * 391 * @throws JAXBException if any problems are encountered during the 392 * transformation to XML. 393 */ 394 public void writeObjectAsXmlTo(Writer writer, Object o, Schema schema) 395 throws JAXBException 396 { 397 if ((writer == null) || (o == null)) 398 return; 399 400 log.debug("Write XML for class " + o.getClass().getName() + " to writer."); 401 402 JAXBContext jaxb = JAXBContext.newInstance(o.getClass()); 403 404 if ((schema == null) && lookForDefaultSchema) 405 { 406 schema = getSchemaFor(o.getClass()); 407 408 if ((schema == null) && failIfDefaultSchemaNotFound) 409 throw new JAXBException(schemaNotFoundMessage(o.getClass())); 410 } 411 412 Marshaller xmlConverter = createAndConfigureMarshaller(jaxb, schema); 413 414 xmlConverter.marshal(o, writer); 415 } 416 417 /** 418 * Creates and returns a new object based on the data read from an XML source. 419 * <p> 420 * See {@link #writeObjectAsXmlTo(Writer, Object, Schema)} to understand how 421 * the {@code schema} parameter is treated.</p> 422 * 423 * @param <T> the runtime type of the returned object. 424 * 425 * @param reader the source of the XML data. 426 * If this value is <i>null</i>, <i>null</i> is returned. 427 * 428 * @param c the class of which the returned object is an instance. 429 * If this value is <i>null</i>, <i>null</i> is returned. 430 * 431 * @param schema the schema used to verify the XML file. 432 * 433 * @return an object based on the data in an XML file. 434 * 435 * @throws XMLStreamException if the XML is not well-formed, 436 * or for some other "unexpected processing conditions". 437 * 438 * @throws JAXBException if anything else goes wrong during the 439 * transformation. 440 */ 441 public <T> T readObjectAsXmlFrom(Reader reader, Class<T> c, Schema schema) 442 throws JAXBException, XMLStreamException 443 { 444 if ((reader == null) || (c == null)) 445 return null; 446 447 log.debug("Read XML for class " + c.getName() + " from reader."); 448 449 JAXBContext jaxb = JAXBContext.newInstance(c); 450 451 if ((schema == null) && lookForDefaultSchema) 452 { 453 schema = getSchemaFor(c); 454 455 if ((schema == null) && failIfDefaultSchemaNotFound) 456 throw new JAXBException(schemaNotFoundMessage(c)); 457 } 458 459 Unmarshaller xmlInterpreter = createAndConfigureUnmarshaller(jaxb, schema); 460 461 XMLStreamReader xmlReader = 462 XMLInputFactory.newInstance().createXMLStreamReader(reader); 463 464 return xmlInterpreter.unmarshal(xmlReader, c).getValue(); 465 } 466 467 /** 468 * Creates and returns a new object based on the data read from an XML source. 469 * <p> 470 * See {@link #writeObjectAsXmlTo(Writer, Object, Schema)} to understand how 471 * the {@code schema} parameter is treated.</p> 472 * 473 * @param <T> the runtime type of the returned object. 474 * 475 * @param stream the source of the XML data. 476 * If this value is <i>null</i>, <i>null</i> is returned. 477 * 478 * @param c the class of which the returned object is an instance. 479 * If this value is <i>null</i>, <i>null</i> is returned. 480 * 481 * @param schema the schema used to verify the XML file. 482 * 483 * @return an object based on the data in an XML file. 484 * 485 * @throws XMLStreamException if the XML is not well-formed, 486 * or for some other "unexpected processing conditions". 487 * 488 * @throws JAXBException if anything else goes wrong during the 489 * transformation. 490 */ 491 public <T> T readObjectAsXmlFrom(InputStream stream, 492 Class<T> c, Schema schema) 493 throws JAXBException, XMLStreamException 494 { 495 if ((stream == null) || (c == null)) 496 return null; 497 498 log.debug("Read XML for class " + c.getName() + " from stream."); 499 500 JAXBContext jaxb = JAXBContext.newInstance(c); 501 502 if ((schema == null) && lookForDefaultSchema) 503 { 504 schema = getSchemaFor(c); 505 506 if ((schema == null) && failIfDefaultSchemaNotFound) 507 throw new JAXBException(schemaNotFoundMessage(c)); 508 } 509 510 Unmarshaller xmlInterpreter = createAndConfigureUnmarshaller(jaxb, schema); 511 512 XMLStreamReader xmlReader = 513 XMLInputFactory.newInstance().createXMLStreamReader(stream); 514 515 return xmlInterpreter.unmarshal(xmlReader, c).getValue(); 516 } 517 518 519 private String schemaNotFoundMessage(Class<?> c) 520 { 521 return "Could not find a default schema file for " + c; 522 } 523 524 //============================================================================ 525 // CONVENIENCE METHODS 526 //============================================================================ 527 528 /** 529 * Returns an XML string for the given object, using {@code schema} for 530 * validation. 531 * <p> 532 * This is a convenience method that is equivalent to calling 533 * {@link #writeObjectAsXmlTo(Writer, Object, Schema)} and using the 534 * {@code Writer} to get a {@code String}. See that method for more 535 * details about schema and exception handling.</p> 536 * 537 * @param o the object to be expressed in XML. 538 * @param schema the holder of the rules for validating the XML output. 539 * @return an XML representation of the object {@code o}. 540 * @throws JAXBException if any problems are encountered during the 541 * transformation to XML. 542 */ 543 public String objectToXmlString(Object o, Schema schema) 544 throws JAXBException 545 { 546 StringWriter writer = new StringWriter(); 547 548 writeObjectAsXmlTo(writer, o, schema); 549 550 return writer.toString(); 551 } 552 553 /** 554 * Returns an XML string for the given object. 555 * This is a convenience method that is equivalent to calling 556 * {@link #objectToXmlString(Object, Schema) 557 * objectToXmlString(o, (Schema)null)}. 558 * 559 * @param o the object to be expressed in XML. 560 * @return an XML representation of the object {@code o}. 561 */ 562 public String objectToXmlString(Object o) throws JAXBException 563 { 564 return objectToXmlString(o, (Schema)null); 565 } 566 567 /** 568 * Returns an XML string for the given object, using the schema found in the 569 * given file for validation. 570 * <p> 571 * This is a convenience method that behaves like 572 * {@link #objectToXmlString(Object, Schema)}, after {@code schemaFileName} 573 * has been turned into a schema. 574 * The location of the schema file is determined by 575 * {@link Class#getResource(java.lang.String) 576 * o.getClass().getResource(schemaFileName)}. 577 * If the schema file cannot be found, a {@link FileNotFoundException} is 578 * thrown.</p> 579 * 580 * @param o the object to be expressed in XML. 581 * @param schemaFileName the name of the file that holds the schema used to 582 * validate the XML transformation. 583 * @return an XML representation of the object {@code o}. 584 * @throws FileNotFoundException if the schema file cannot be found. 585 * @throws JAXBException if any problems are encountered during the 586 * transformation to XML. 587 */ 588 public String objectToXmlString(Object o, String schemaFileName) 589 throws JAXBException, FileNotFoundException 590 { 591 try 592 { 593 Schema schema = getSchema(schemaFileName, o.getClass()); 594 return objectToXmlString(o, schema); 595 } 596 catch (SAXException ex) 597 { 598 throw new JAXBException(ex); 599 } 600 } 601 602 /** 603 * Creates and returns a new object based on the data in an XML file. 604 * <p> 605 * This is a convenience method that is equivalent to calling 606 * {@link #readObjectAsXmlFrom(Reader, Class, Schema)} after turning 607 * {@code fileName} into a {@code Reader}. See that method for more 608 * details about schema and exception handling.</p> 609 * 610 * @param <T> the runtime type of the returned object. 611 * @param fileName the name of an XML file. 612 * @param c the class of which the returned object is an instance. 613 * @param schema the schema used to verify the XML file. 614 * @return an object based on the data in an XML file. 615 * @throws FileNotFoundException if the XML file could not be found. 616 * @throws XMLStreamException if there is a problem opening the XML file, 617 * if the XML is not well-formed, or for some other 618 * "unexpected processing conditions". 619 * @throws JAXBException if anything else goes wrong during the 620 * transformation. 621 */ 622 public <T> T xmlFileToObject(String fileName, Class<T> c, Schema schema) 623 throws JAXBException, XMLStreamException, FileNotFoundException 624 { 625 //First try to get file directly... 626 try 627 { 628 return readObjectAsXmlFrom(new FileReader(fileName), c, schema); 629 } 630 //...but if that fails, look in same place where class is located 631 catch (FileNotFoundException ex) 632 { 633 InputStream xmlInput = c.getResourceAsStream(fileName); 634 635 if (xmlInput == null) 636 throw new FileNotFoundException("Could not find file '"+fileName+"'."); 637 638 return readObjectAsXmlFrom(xmlInput, c, schema); 639 } 640 } 641 642 /** 643 * Creates and returns a new object based on the data in an XML file. 644 * This is a convenience method that is equivalent to calling 645 * {@link #xmlFileToObject(String, Class, Schema) 646 * xmlFileToObject(fileName, c, (Schema)null)}. 647 * 648 * @param <T> the runtime type of the returned object. 649 * @param fileName the name of an XML file. 650 * @param c the class of which the returned object is an instance. 651 * @return an object based on the data in an XML file. 652 * @throws FileNotFoundException if the XML file could not be found. 653 * @throws XMLStreamException if there is a problem opening the XML file, 654 * if the XML is not well-formed, or for some other 655 * "unexpected processing conditions". 656 * @throws JAXBException if anything else goes wrong during the 657 */ 658 public <T> T xmlFileToObject(String fileName, Class<T> c) 659 throws JAXBException, XMLStreamException, FileNotFoundException 660 { 661 Schema schema = lookForDefaultSchema ? getSchemaFor(c) : null; 662 663 return xmlFileToObject(fileName, c, schema); 664 } 665 666 //============================================================================ 667 // HELPER METHODS 668 //============================================================================ 669 670 /** Helps the objectToXmlString methods. */ 671 private Marshaller createAndConfigureMarshaller(JAXBContext jaxb, 672 Schema schema) 673 throws JAXBException 674 { 675 Marshaller marshaller = jaxb.createMarshaller(); 676 677 if (schema != null) 678 marshaller.setSchema(schema); 679 680 try 681 { 682 marshaller.setProperty("jaxb.formatted.output", true); 683 marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", 684 new PrefixMapper()); 685 } 686 catch (PropertyException ex) 687 { 688 //Intentional do-nothing: 689 // 1. The JAXB implementation is REQUIRED to support this property. 690 // 2. The inability to format output should not be viewed as exceptional. 691 // 3. The inability to use a preferred prefix is not that important. 692 } 693 694 return marshaller; 695 } 696 697 /** Helps the xmlFileToObject methods. */ 698 private Unmarshaller createAndConfigureUnmarshaller(JAXBContext jaxb, 699 Schema schema) 700 throws JAXBException 701 { 702 Unmarshaller unmarshaller = jaxb.createUnmarshaller(); 703 704 if (schema != null) 705 unmarshaller.setSchema(schema); 706 707 return unmarshaller; 708 } 709 710 //The @XmlNs annotation, when used in the @XmlSchema, isn't working for us 711 //(as of 2008-Jul-11). The suggestion to use this means was found on the 712 //jaxb forum at http://forums.java.net/jive/message.jspa?messageID=286044#286044 713 private class PrefixMapper extends com.sun.xml.bind.marshaller.NamespacePrefixMapper 714 { 715 public String getPreferredPrefix(String namespaceUri, 716 String suggestion, boolean requirePrefix) 717 { 718 if ("http://www.nrao.edu/namespaces/sss".equals(namespaceUri)) 719 return "sss"; 720 721 else if ("http://www.nrc.ca/namespaces/widar".equals(namespaceUri)) 722 return "widar"; 723 724 else if ("http://www.nrao.edu/namespaces/nrao".equals(namespaceUri)) 725 return "nrao"; 726 727 return suggestion; 728 } 729 } 730 /* 731 public static void main(String[] args) throws Exception 732 { 733 JaxbUtility util = JaxbUtility.getSharedInstance(); 734 System.out.println("Schema Location= " + DEFAULT_BASE_URL); 735 //util.setBaseUrlForSchemaFiles(new URL("https://e2e.nrao.edu/schemas/")); 736 System.out.println("Schema = " + util.getSchemaFor(edu.nrao.sss.measure.Distance.class)); 737 } 738 */ 739 } 740