X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fnetconf%2Fnetconf-netty-util%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fnetconf%2Fnettyutil%2Fhandler%2FNetconfMessageToEXIEncoder.java;h=aceb6ac520f5568120c8538fb320f72f2c8418e4;hb=1182969589fa91102cb24998a75fefa40240728d;hp=f1e72ed85fb6475ebeab5ae8e400d953077adf7e;hpb=071d5e39ef0adb29b75374f8f01025b55afc1776;p=controller.git 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 f1e72ed85f..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 @@ -14,32 +14,49 @@ 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 org.opendaylight.controller.netconf.api.NetconfMessage; 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); - private final NetconfEXICodec codec; + /** + * 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; - public NetconfMessageToEXIEncoder(final NetconfEXICodec codec) { - this.codec = Preconditions.checkNotNull(codec); + private NetconfMessageToEXIEncoder(final Transmogrifier transmogrifier) { + this.transmogrifier = Preconditions.checkNotNull(transmogrifier); + } + + 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 EXIOptionsException, IOException, TransformerException { + 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); - - ThreadLocalTransformers.getDefaultTransformer().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(); } } }