/**
* Copyright 2007-2015, Kaazing Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kaazing.k3po.driver.internal.control.handler;
import static java.lang.String.format;
import static org.jboss.netty.buffer.ChannelBuffers.copiedBuffer;
import static org.jboss.netty.buffer.ChannelBuffers.dynamicBuffer;
import static org.jboss.netty.buffer.ChannelBuffers.wrappedBuffer;
import static org.jboss.netty.util.CharsetUtil.UTF_8;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
import org.kaazing.k3po.driver.internal.control.ControlMessage;
import org.kaazing.k3po.driver.internal.control.ControlMessage.Kind;
import org.kaazing.k3po.driver.internal.control.DisposedMessage;
import org.kaazing.k3po.driver.internal.control.ErrorMessage;
import org.kaazing.k3po.driver.internal.control.FinishedMessage;
import org.kaazing.k3po.driver.internal.control.NotifiedMessage;
import org.kaazing.k3po.driver.internal.control.NotifyMessage;
import org.kaazing.k3po.driver.internal.control.PreparedMessage;
import org.kaazing.k3po.driver.internal.control.StartedMessage;
public class ControlEncoder extends OneToOneEncoder {
private static final byte LF = (byte) 0x0a;
@Override
protected Object encode(ChannelHandlerContext ctx, Channel channel, Object message) throws Exception {
if (message instanceof ControlMessage) {
ControlMessage controlMessage = (ControlMessage) message;
switch (controlMessage.getKind()) {
case PREPARED:
return encodePreparedMessage(ctx, channel, (PreparedMessage) controlMessage);
case STARTED:
return encodeStartedMessage(ctx, channel, (StartedMessage) controlMessage);
case ERROR:
return encodeErrorMessage(ctx, channel, (ErrorMessage) controlMessage);
case FINISHED:
return encodeFinishedMessage(ctx, channel, (FinishedMessage) controlMessage);
case NOTIFY:
return encodeNotifyMessage(ctx, channel, (NotifyMessage) controlMessage);
case NOTIFIED:
return encodedNotifiedMessage(ctx, channel, (NotifiedMessage) controlMessage);
case DISPOSED:
return encodedDisposedMessage(ctx, channel, (DisposedMessage) controlMessage);
default:
break;
}
}
// unknown message
return message;
}
private Object encodePreparedMessage(ChannelHandlerContext ctx, Channel channel, PreparedMessage preparedMessage) {
Kind kind = preparedMessage.getKind();
String script = preparedMessage.getScript();
ChannelBuffer buf = dynamicBuffer(channel.getConfig().getBufferFactory());
encodeInitial(kind, buf);
for (String barrier : preparedMessage.getBarriers()) {
// ~ denote injected barriers, which need not be shared with test framework
if (!barrier.startsWith("~")) {
encodeHeader("barrier", barrier, buf);
}
}
return encodeContent(script, buf);
}
private Object encodeStartedMessage(ChannelHandlerContext ctx, Channel channel, StartedMessage startedMessage) {
Kind kind = startedMessage.getKind();
ChannelBuffer buf = dynamicBuffer(channel.getConfig().getBufferFactory());
encodeInitial(kind, buf);
return encodeNoContent(buf);
}
private Object encodeErrorMessage(ChannelHandlerContext ctx, Channel channel, ErrorMessage errorMessage) {
Kind kind = errorMessage.getKind();
String summary = errorMessage.getSummary();
String description = errorMessage.getDescription();
ChannelBuffer buf = dynamicBuffer(channel.getConfig().getBufferFactory());
encodeInitial(kind, buf);
encodeHeader("summary", summary, buf);
return encodeContent(description, buf);
}
private Object encodeFinishedMessage(ChannelHandlerContext ctx, Channel channel, FinishedMessage finishedMessage) {
Kind kind = finishedMessage.getKind();
String script = finishedMessage.getScript();
ChannelBuffer buf = dynamicBuffer(channel.getConfig().getBufferFactory());
encodeInitial(kind, buf);
return encodeContent(script, buf);
}
private Object encodeNotifyMessage(ChannelHandlerContext ctx, Channel channel, NotifyMessage notifyMessage) {
Kind kind = notifyMessage.getKind();
String barrier = notifyMessage.getBarrier();
ChannelBuffer buf = dynamicBuffer(channel.getConfig().getBufferFactory());
encodeInitial(kind, buf);
encodeHeader("barrier", barrier, buf);
return encodeNoContent(buf);
}
private Object encodedNotifiedMessage(ChannelHandlerContext ctx, Channel channel, NotifiedMessage notifiedMessage) {
Kind kind = notifiedMessage.getKind();
String barrier = notifiedMessage.getBarrier();
ChannelBuffer buf = dynamicBuffer(channel.getConfig().getBufferFactory());
encodeInitial(kind, buf);
encodeHeader("barrier", barrier, buf);
return encodeNoContent(buf);
}
private Object encodedDisposedMessage(ChannelHandlerContext ctx, Channel channel, DisposedMessage disposedMessage) {
Kind kind = disposedMessage.getKind();
ChannelBuffer buf = dynamicBuffer(channel.getConfig().getBufferFactory());
encodeInitial(kind, buf);
return encodeNoContent(buf);
}
private static void encodeInitial(Kind kind, ChannelBuffer buf) {
buf.writeBytes(copiedBuffer(kind.toString(), UTF_8));
buf.writeByte(LF);
}
private static void encodeHeader(String bufName, Object bufValue, ChannelBuffer buf) {
if (bufValue != null) {
buf.writeBytes(copiedBuffer(format("%s:%s", bufName, bufValue), UTF_8));
buf.writeByte(LF);
}
}
private static ChannelBuffer encodeNoContent(ChannelBuffer buf) {
buf.writeByte(LF);
return buf;
}
private static ChannelBuffer encodeContent(String content, ChannelBuffer buf) {
if (content == null) {
// note: missing content not same as empty content
return encodeNoContent(buf);
}
else {
ChannelBuffer contentBuf = copiedBuffer(content, UTF_8);
encodeHeader("content-length", contentBuf.readableBytes(), buf);
buf.writeByte(LF);
return wrappedBuffer(buf, contentBuf);
}
}
}