@Override
	protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
		if (!(msg instanceof Frame)) {
			return msg;
		} else if (msg instanceof HeartBeatFrame) {
			return ChannelBuffers.wrappedBuffer(new byte[] { '\n' });
		}

		Frame frame = (Frame) msg;

		// COMMAND
		StringBuilder formatedFrame = new StringBuilder();
		String command = frame.getCommand();
		if (command != null && command.length() > 0) {
			formatedFrame.append(command).append(Frame.EOL_COMMAND);
		} else {
			throw new IllegalArgumentException("Command can't be empty");
		}

		// HEADER
		Header header = frame.getHeader();
		if (header != null) {
			if (header.size() > 0) {
				List<String> keys = new ArrayList<String>(header.keySet());
				Collections.sort(keys);

				for (String key : keys) {
					formatedFrame.append(escapeHeader(key)) //
							.append(Frame.SEPARATOR_HEADER) //
							.append(escapeHeader(header.get(key))) //
							.append(Frame.EOL_HEADER);
				}
			}
		}
		formatedFrame.append(Frame.EOL_HEADERS);

		// BODY
		String body = frame.getBody();
		if (body != null && body.length() > 0) {
			formatedFrame.append(body);
		}

		formatedFrame.append(Frame.EOL_FRAME);
		String frameString = formatedFrame.toString();

		return ChannelBuffers.copiedBuffer((String) frameString, Charset.forName("UTF-8"));
	}