X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-rest-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Frest%2Fimpl%2FStructuredDataToXmlProvider.java;h=703a2a463476bcfd4704c34419cc17c73a6af3fc;hp=bbe156d3c4c9acb32e262ecf585f8642e89911d0;hb=eb887b1c2c8cd2768f8b4c2ed2b5054f97798466;hpb=4c1e9ed9fa2386ca63a0bbf11da620c83a6d7d5e diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToXmlProvider.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToXmlProvider.java index bbe156d3c4..703a2a4634 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToXmlProvider.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToXmlProvider.java @@ -11,7 +11,6 @@ import java.io.IOException; import java.io.OutputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Type; - import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; @@ -21,15 +20,16 @@ import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; - -import org.opendaylight.controller.sal.rest.api.Draft01; import org.opendaylight.controller.sal.rest.api.Draft02; import org.opendaylight.controller.sal.rest.api.RestconfService; -import org.opendaylight.controller.sal.restconf.impl.ResponseException; +import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException; +import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag; +import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType; import org.opendaylight.controller.sal.restconf.impl.StructuredData; import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; @@ -38,46 +38,75 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @Provider -@Produces({ Draft01.MediaTypes.DATA + RestconfService.XML, Draft02.MediaTypes.DATA + RestconfService.XML, - MediaType.APPLICATION_XML, MediaType.TEXT_XML }) +@Produces({ Draft02.MediaTypes.API + RestconfService.XML, Draft02.MediaTypes.DATA + RestconfService.XML, + Draft02.MediaTypes.OPERATION + RestconfService.XML, MediaType.APPLICATION_XML, MediaType.TEXT_XML }) public enum StructuredDataToXmlProvider implements MessageBodyWriter { INSTANCE; - private final static Logger logger = LoggerFactory.getLogger(StructuredDataToXmlProvider.class); + private static final Logger LOG = LoggerFactory.getLogger(StructuredDataToXmlProvider.class); + private static final TransformerFactory FACTORY = TransformerFactory.newInstance(); + private static final ThreadLocal TRANSFORMER = new ThreadLocal() { + @Override + protected Transformer initialValue() { + final Transformer ret; + try { + ret = FACTORY.newTransformer(); + } catch (TransformerConfigurationException e) { + LOG.error("Failed to instantiate XML transformer", e); + throw new IllegalStateException("XML encoding currently unavailable", e); + } + + ret.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); + ret.setOutputProperty(OutputKeys.METHOD, "xml"); + ret.setOutputProperty(OutputKeys.INDENT, "yes"); + ret.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + ret.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); + + return ret; + } + }; @Override - public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { - return true; + public boolean isWriteable(final Class type, final Type genericType, final Annotation[] annotations, + final MediaType mediaType) { + return type.equals(StructuredData.class); } @Override - public long getSize(StructuredData t, Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + public long getSize(final StructuredData t, final Class type, final Type genericType, + final Annotation[] annotations, final MediaType mediaType) { return -1; } @Override - public void writeTo(StructuredData t, Class type, Type genericType, Annotation[] annotations, - MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) - throws IOException, WebApplicationException { + public void writeTo(final StructuredData t, final Class type, final Type genericType, + final Annotation[] annotations, final MediaType mediaType, + final MultivaluedMap httpHeaders, final OutputStream entityStream) throws IOException, + WebApplicationException { CompositeNode data = t.getData(); if (data == null) { - throw new ResponseException(Response.Status.NOT_FOUND, "No data exists."); + throw new RestconfDocumentedException(Response.Status.NOT_FOUND); } - - XmlMapper xmlMapper = new XmlMapper(); - Document domTree = xmlMapper.write(data, (DataNodeContainer) t.getSchema()); + + final Transformer trans; + try { + trans = TRANSFORMER.get(); + if (t.isPrettyPrintMode()) { + trans.setOutputProperty(OutputKeys.INDENT, "yes"); + } else { + trans.setOutputProperty(OutputKeys.INDENT, "no"); + } + } catch (RuntimeException e) { + throw new RestconfDocumentedException(e.getMessage(), ErrorType.TRANSPORT, ErrorTag.OPERATION_FAILED); + } + + // FIXME: BUG-1281: eliminate the intermediate Document + final Document domTree = new XmlMapper().write(data, (DataNodeContainer) t.getSchema()); try { - TransformerFactory tf = TransformerFactory.newInstance(); - Transformer transformer = tf.newTransformer(); - transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); - transformer.setOutputProperty(OutputKeys.METHOD, "xml"); - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); - transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); - transformer.transform(new DOMSource(domTree), new StreamResult(entityStream)); + trans.transform(new DOMSource(domTree), new StreamResult(entityStream)); } catch (TransformerException e) { - logger.error("Error during translation of Document to OutputStream", e); - throw new ResponseException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage()); + LOG.error("Error during translation of Document to OutputStream", e); + throw new RestconfDocumentedException(e.getMessage(), ErrorType.TRANSPORT, ErrorTag.OPERATION_FAILED); } }