/** * Helios, OpenSource Monitoring * Brought to you by the Helios Development Group * * Copyright 2013, Helios Development Group and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. * */ package org.helios.apmrouter.server.unification.pipeline2.protocol; import org.helios.apmrouter.server.unification.pipeline2.AbstractInitiator; import org.helios.apmrouter.server.unification.pipeline2.FlushOnCloseBufferAggregator; import org.helios.apmrouter.server.unification.pipeline2.ProtocolSwitchContext; import org.helios.apmrouter.server.unification.pipeline2.ProtocolSwitchDecoder; import org.helios.apmrouter.server.unification.pipeline2.SwitchPhase; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelEvent; import org.jboss.netty.channel.ChannelHandler; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.SimpleChannelUpstreamHandler; import org.jboss.netty.handler.codec.compression.ZlibDecoder; import org.jboss.netty.handler.codec.compression.ZlibWrapper; /** * <p>Title: GZipEncodingInitiator</p> * <p>Description: An initiator that detects a GZip encoded stream of data</p> * <p>Company: Helios Development Group LLC</p> * @author Whitehead (nwhitehead AT heliosdev DOT org) * <p><code>org.helios.apmrouter.server.unification.pipeline2.encoding.GZipEncodingInitiator</code></p> */ /** * <p>Title: GZipEncodingInitiator</p> * <p>Description: </p> * <p>Company: Helios Development Group LLC</p> * @author Whitehead (nwhitehead AT heliosdev DOT org) * <p><code>org.helios.apmrouter.server.unification.pipeline2.protocol.GZipEncodingInitiator</code></p> */ public class GZipEncodingInitiator extends AbstractInitiator { /** * Creates a new GZipEncodingInitiator */ public GZipEncodingInitiator() { super(2, "gzip"); } /** * {@inheritDoc} * @see org.helios.apmrouter.server.unification.pipeline2.Initiator#match(org.jboss.netty.buffer.ChannelBuffer) */ @Override public Object match(ChannelBuffer buff) { boolean match = isGzip(buff) ? true : null; return match; } /** * {@inheritDoc} * @see org.helios.apmrouter.server.unification.pipeline2.Initiator#process(org.helios.apmrouter.server.unification.pipeline2.ProtocolSwitchContext, java.lang.Object) */ @Override public SwitchPhase process(final ProtocolSwitchContext context, Object matchKey) { log.info("Protocol Switch: Prepending ZlibDecoder"); final ChannelPipeline pipeline = context.getPipeline(); pipeline.remove("logging"); ZlibDecoder zdecoder = new ZlibDecoder(ZlibWrapper.GZIP){ @Override public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent evt) throws Exception { if(evt instanceof MessageEvent) { int rb = ((ChannelBuffer)((MessageEvent)evt).getMessage()).readableBytes(); log.info("ZLibDecoder Handling [" + rb + "] bytes"); } super.handleUpstream(ctx, evt); } @Override protected Object decode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception { Object result = super.decode(ctx, channel, msg); if(result!=null) log.info("ZLibDecoder returning [" + result + "]"); return result; } }; pipeline.addBefore(ProtocolSwitchDecoder.PIPE_NAME, "gzip", zdecoder); context.sendCurrentBufferUpstream(); // try { // zdecoder.handleUpstream(context.getCtx(), context.getUpstreamEvent()); // } catch (Exception e) { // e.printStackTrace(); // } //context.getCtx().sendUpstream(context.getBuffer()); return null; } // /** // * {@inheritDoc} // * @see org.helios.apmrouter.server.unification.pipeline2.Initiator#process(org.helios.apmrouter.server.unification.pipeline2.ProtocolSwitchContext, java.lang.Object) // */ // @Override // public SwitchPhase process(final ProtocolSwitchContext context, Object matchKey) { // log.info("Switching Protocols"); //// LoggingHandler lh = decode(installedLogger); //// if(lh!=null) pipeline.addLast("logging", lh); //// pipeline.addLast(ProtocolSwitchDecoder.PIPE_NAME, applicationContext.getBean("protocolSwitchDecoder", ProtocolSwitchDecoder.class)); //// pipeline.addLast("exec", executionHandler); // final ChannelPipeline pipeline = context.getPipeline(); // try { pipeline.remove("logging"); } catch (Exception ex) {/* No Op*/} // // // // final ChannelHandler pSwitch = pipeline.remove(ProtocolSwitchDecoder.PIPE_NAME); // pipeline.addLast("gzip", new ZlibDecoder(ZlibWrapper.GZIP)); // pipeline.addLast(FlushOnCloseBufferAggregator.PIPE_NAME, FlushOnCloseBufferAggregator.getInstance()); // pipeline.addLast(FlushOnCloseBufferAggregator.PIPE_NAME + "-Complete", new SimpleChannelUpstreamHandler(){ // @Override // public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { // log.info("[" + FlushOnCloseBufferAggregator.PIPE_NAME + "-Complete] FlushOnCloseBufferAggregator Complete Event - [" + ((ChannelBuffer)e.getMessage()).readableBytes() + "] Bytes"); // context.setAggregationHasOccured(); // pipeline.addBefore(EXEC_HANDLER_NAME, ProtocolSwitchDecoder.PIPE_NAME, pSwitch); // try { pipeline.remove("gzip"); } catch (Exception ex) {/* No Op*/} // try { pipeline.remove(FlushOnCloseBufferAggregator.PIPE_NAME); } catch (Exception ex) {/* No Op*/} // try { pipeline.remove(FlushOnCloseBufferAggregator.PIPE_NAME + "-Complete"); } catch (Exception ex) {/* No Op*/} // //ChannelHandlerContext targetCtx = pipeline.getContext(ctx.getPipeline().getFirst()); // ChannelHandlerContext targetCtx = pipeline.getContext("anchor"); // // log.info("Sending ungzipped payload back to switch decoder at [" + targetCtx.getName() + "]"); // targetCtx.sendUpstream(e); // // } // }); // // context.sendCurrentBufferUpstream(pipeline.getContext(pipeline.getFirst()).getName()); // return SwitchPhase.INIT; // } /** * Determines if the two passed bytes represent a gzipped stream of data * @param magic1 The first byte of the incoming request * @param magic2 The second byte of the incoming request * @return true if the incoming payload is gzipped, false otherwise */ public static boolean isGzip(int magic1, int magic2) { return magic1 == 31 && magic2 == 139; } /** * Determines if the channel is carrying a gzipped payload * @param buffer The channel buffer to check * @return true if the incoming payload is gzipped, false otherwise */ public static boolean isGzip(ChannelBuffer buffer) { return isGzip(buffer.getUnsignedByte(0), buffer.getUnsignedByte(1)); } /** * {@inheritDoc} * @see org.helios.apmrouter.server.unification.pipeline2.AbstractInitiator#requiresFullPayload() */ @Override public boolean requiresFullPayload() { return false; } }