X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fnetconf%2Fnetconf-netty-util%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fnetconf%2Fnettyutil%2Fhandler%2FNetconfMessageToEXIEncoder.java;h=aceb6ac520f5568120c8538fb320f72f2c8418e4;hp=0a866fffaa082c346cb726b1d815b170e9b77a0e;hb=e37c603e7d8b4d54a5d55463a1c69ec170898faf;hpb=478ce1fa1dc30974b7cf23fd5258f1af5366d547 diff --git a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfMessageToEXIEncoder.java b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfMessageToEXIEncoder.java index 0a866fffaa..aceb6ac520 100644 --- a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfMessageToEXIEncoder.java +++ b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfMessageToEXIEncoder.java @@ -12,38 +12,51 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufOutputStream; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; +import java.io.IOException; import java.io.OutputStream; import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.sax.SAXResult; -import javax.xml.transform.sax.SAXTransformerFactory; import org.opendaylight.controller.netconf.api.NetconfMessage; -import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.openexi.proc.common.EXIOptionsException; import org.openexi.sax.Transmogrifier; +import org.openexi.sax.TransmogrifierException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.xml.sax.ContentHandler; public final class NetconfMessageToEXIEncoder extends MessageToByteEncoder { - private static final Logger LOG = LoggerFactory.getLogger(NetconfMessageToEXIEncoder.class); + /** + * This class is not marked as shared, so it can be attached to only a single channel, + * which means that {@link #encode(ChannelHandlerContext, NetconfMessage, ByteBuf)} + * cannot be invoked concurrently. Hence we can reuse the transmogrifier. + */ + private final Transmogrifier transmogrifier; + + private NetconfMessageToEXIEncoder(final Transmogrifier transmogrifier) { + this.transmogrifier = Preconditions.checkNotNull(transmogrifier); + } - private static final SAXTransformerFactory saxTransformerFactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); - private final NetconfEXICodec codec; - - public NetconfMessageToEXIEncoder(final NetconfEXICodec codec) { - this.codec = Preconditions.checkNotNull(codec); + public static NetconfMessageToEXIEncoder create(final NetconfEXICodec codec) throws EXIOptionsException, TransmogrifierException { + return new NetconfMessageToEXIEncoder(codec.getTransmogrifier()); } @Override - protected void encode(final ChannelHandlerContext ctx, final NetconfMessage msg, final ByteBuf out) throws Exception { - LOG.trace("Sent to encode : {}", XmlUtil.toString(msg.getDocument())); + protected void encode(final ChannelHandlerContext ctx, final NetconfMessage msg, final ByteBuf out) throws EXIOptionsException, IOException, TransformerException, TransmogrifierException { + LOG.trace("Sent to encode : {}", msg); try (final OutputStream os = new ByteBufOutputStream(out)) { - final Transmogrifier transmogrifier = codec.getTransmogrifier(); transmogrifier.setOutputStream(os); - - final Transformer transformer = saxTransformerFactory.newTransformer(); - transformer.transform(new DOMSource(msg.getDocument()), new SAXResult(transmogrifier.getSAXTransmogrifier())); + final ContentHandler handler = transmogrifier.getSAXTransmogrifier(); + final Transformer transformer = ThreadLocalTransformers.getDefaultTransformer(); + transformer.transform(new DOMSource(msg.getDocument()), new SAXResult(handler)); + } finally { + // Make sure we do not retain any reference to state by removing + // the output stream reference and resetting internal state. + transmogrifier.setOutputStream(null); + transmogrifier.getSAXTransmogrifier(); } } }