/** * Build the JAXB model and generate the schemas based on tha data * * @param extraFiles additional files. * @return class to {@link QName} resolver. */ private Resolver buildModelAndSchemas( Map<String, ApplicationDescription.ExternalGrammar> extraFiles) { // Lets get all candidate classes so we can create the JAX-B context // include any @XmlSeeAlso references. Set<Class> classSet = new HashSet<Class>(seeAlsoClasses); for (TypeCallbackPair pair : nameCallbacks) { final GenericType genericType = pair.genericType; Class<?> clazz = genericType.getRawType(); // Is this class itself interesting? if (clazz.getAnnotation(XmlRootElement.class) != null) { classSet.add(clazz); } else if (SPECIAL_GENERIC_TYPES.contains(clazz)) { Type type = genericType.getType(); if (type instanceof ParameterizedType) { Type parameterType = ((ParameterizedType) type).getActualTypeArguments()[0]; if (parameterType instanceof Class) { classSet.add((Class) parameterType); } } } } // Create a JAX-B context, and use this to generate us a bunch of // schema objects JAXBIntrospector introspector = null; try { JAXBContext context = JAXBContext.newInstance(classSet.toArray(new Class[classSet.size()])); final List<StreamResult> results = new ArrayList<StreamResult>(); context.generateSchema( new SchemaOutputResolver() { int counter = 0; @Override public Result createOutput(String namespaceUri, String suggestedFileName) { StreamResult result = new StreamResult(new CharArrayWriter()); result.setSystemId("xsd" + (counter++) + ".xsd"); results.add(result); return result; } }); // Store the new files for later use // for (StreamResult result : results) { CharArrayWriter writer = (CharArrayWriter) result.getWriter(); byte[] contents = writer.toString().getBytes("UTF8"); extraFiles.put( result.getSystemId(), new ApplicationDescription.ExternalGrammar( MediaType .APPLICATION_XML_TYPE, // I don't think there is a specific media type for XML // Schema contents)); } // Create an introspector // introspector = context.createJAXBIntrospector(); } catch (JAXBException e) { LOGGER.log(Level.SEVERE, "Failed to generate the schema for the JAX-B elements", e); } catch (IOException e) { LOGGER.log( Level.SEVERE, "Failed to generate the schema for the JAX-B elements due to an IO error", e); } // Create introspector if (introspector != null) { final JAXBIntrospector copy = introspector; return new Resolver() { public QName resolve(Class type) { Object parameterClassInstance = null; try { Constructor<?> defaultConstructor = type.getDeclaredConstructor(); defaultConstructor.setAccessible(true); parameterClassInstance = defaultConstructor.newInstance(); } catch (InstantiationException ex) { LOGGER.log(Level.FINE, null, ex); } catch (IllegalAccessException ex) { LOGGER.log(Level.FINE, null, ex); } catch (IllegalArgumentException ex) { LOGGER.log(Level.FINE, null, ex); } catch (InvocationTargetException ex) { LOGGER.log(Level.FINE, null, ex); } catch (SecurityException ex) { LOGGER.log(Level.FINE, null, ex); } catch (NoSuchMethodException ex) { LOGGER.log(Level.FINE, null, ex); } if (parameterClassInstance == null) { return null; } try { return copy.getElementName(parameterClassInstance); } catch (NullPointerException e) { // EclipseLink throws an NPE if an object annotated with @XmlType and without the // @XmlRootElement // annotation is passed as a parameter of #getElementName method. return null; } } }; } else { return null; // No resolver created } }