/**
* Copyright © 2006-2016 Web Cohesion (info@webcohesion.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.webcohesion.enunciate.rt;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;
/**
* A JAX-RS context resolver for an instance of JAXBContext that attempts to use metadata exported at build-time
* by Enunciate to provide pretty namespace prefixes and a JAXB context that is aware of all the classes annotated
* with @XmlRootElement in the project.
*
* @author Ryan Heaton
*/
@Provider
public class EnunciateJaxbContextResolver implements ContextResolver<JAXBContext> {
private static Logger LOG = Logger.getLogger(EnunciateJaxbContextResolver.class.getName());
private final JAXBContext context;
public EnunciateJaxbContextResolver() {
this.context = buildJaxbContext();
}
@Override
public JAXBContext getContext(Class<?> type) {
return this.context;
}
protected JAXBContext buildJaxbContext() {
List<Class<?>> contextClasses = new ArrayList<Class<?>>();
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
boolean hasContextClasses = false;
boolean hasNamespacePrefixes = false;
try {
Enumeration<URL> contextClassLists = classloader.getResources("/jaxb-context-classes.list");
while (contextClassLists.hasMoreElements()) {
hasContextClasses = true;
URL contextClassList = contextClassLists.nextElement();
BufferedReader reader = new BufferedReader(new InputStreamReader(contextClassList.openStream(), "utf-8"));
String contextClass = reader.readLine();
while (contextClass != null) {
try {
contextClasses.add(classloader.loadClass(contextClass));
}
catch (Throwable e) {
LOG.warning("Unable to load JAXB context class " + contextClass + " (" + e.getMessage() + ")");
}
contextClass = reader.readLine();
}
}
}
catch (IOException e) {
LOG.warning("Unable to read all JAXB context classes (" + e.getMessage() + ")");
}
Properties namespacePrefixes = new Properties();
String defaultNs = null;
try {
Enumeration<URL> namespacePropertiesList = classloader.getResources("/namespaces.properties");
while (namespacePropertiesList.hasMoreElements()) {
hasNamespacePrefixes = true;
URL namespaceProperties = namespacePropertiesList.nextElement();
Properties props = new Properties();
props.load(namespaceProperties.openStream());
Object defaultNamespace = props.remove("{default}");
if (defaultNamespace != null && defaultNs == null) {
defaultNs = defaultNamespace.toString();
}
namespacePrefixes.putAll(props);
}
}
catch (IOException e) {
LOG.warning("Unable to read all namespace properties (" + e.getMessage() + ")");
}
if (hasContextClasses || hasNamespacePrefixes) {
try {
EnunciateJaxbNamespacePrefixMapper prefixMapper = new EnunciateJaxbNamespacePrefixMapper(defaultNs, namespacePrefixes);
JAXBContext jaxbContext = JAXBContext.newInstance(contextClasses.toArray(new Class[contextClasses.size()]));
return new EnunciateJaxbContext(jaxbContext, prefixMapper);
}
catch (JAXBException e) {
LOG.warning("Unable to construct JAXB classes (" + e.getMessage() + ")");
}
}
return null;
}
}