/** * Copyright (C) 2003-2008 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. */ package org.etk.core.rest.impl.provider; import java.util.Iterator; import java.util.concurrent.ConcurrentHashMap; import javax.ws.rs.Consumes; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.ext.ContextResolver; import javax.ws.rs.ext.Provider; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import org.etk.common.logging.Logger; import org.etk.core.rest.impl.header.MediaTypeHelper; import org.etk.kernel.container.component.ComponentPlugin; @Provider @Consumes({ MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_XHTML_XML }) @Produces({ MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_XHTML_XML, MediaTypeHelper.WADL }) public class JAXBContextResolver implements ContextResolver<JAXBContextResolver> { /** * Logger. */ private static final Logger LOG = Logger.getLogger(JAXBContextResolver.class); /** * JAXBContext cache. */ @SuppressWarnings("unchecked") private final ConcurrentHashMap<Class, JAXBContext> jaxbContexts = new ConcurrentHashMap<Class, JAXBContext>(); /** * {@inheritDoc} */ public JAXBContextResolver getContext(Class<?> type) { return this; } /** * Return JAXBContext according to supplied type. If no one context found then * try create new context and save it in cache. * * @param classes classes to be bound * @return JAXBContext * @throws JAXBException if JAXBContext creation failed */ public JAXBContext getJAXBContext(Class<?> clazz) throws JAXBException { JAXBContext jaxbctx = jaxbContexts.get(clazz); if (jaxbctx == null) { jaxbctx = JAXBContext.newInstance(clazz); jaxbContexts.put(clazz, jaxbctx); } return jaxbctx; } /** * Create and add in cache JAXBContext for supplied set of classes. * * @param classes set of java classes to be bound * @return JAXBContext * @throws JAXBException if JAXBContext for supplied classes can't be created * in any reasons */ public JAXBContext createJAXBContext(Class<?> clazz) throws JAXBException { JAXBContext jaxbctx = JAXBContext.newInstance(clazz); addJAXBContext(jaxbctx, clazz); return jaxbctx; } /** * Add prepared JAXBContext that will be mapped to set of class. In this case * this class works as cache for JAXBContexts. * * @param jaxbctx JAXBContext * @param classes set of java classes to be bound */ public void addJAXBContext(JAXBContext jaxbctx, Class<?> clazz) { jaxbContexts.put(clazz, jaxbctx); } /** * @param plugin for injection prepared JAXBContext at startup */ public void addPlugin(ComponentPlugin plugin) { if (plugin instanceof JAXBContextComponentPlugin) { for (Iterator<Class<?>> i = ((JAXBContextComponentPlugin) plugin).getJAXBContexts() .iterator(); i.hasNext();) { Class<?> c = i.next(); try { createJAXBContext(c); } catch (JAXBException e) { LOG.error("Failed add JAXBContext for class " + c.getName(), e); } } } } }