org.jboss.aerogear.io.netty.handler.codec.sockjs.protocol.MessageFrame.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.aerogear.io.netty.handler.codec.sockjs.protocol.MessageFrame.java

Source

/*
 * Copyright 2013 The Netty Project
 *
 * The Netty Project licenses this file to you 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.jboss.aerogear.io.netty.handler.codec.sockjs.protocol;

import com.fasterxml.jackson.core.io.JsonStringEncoder;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.DefaultByteBufHolder;
import io.netty.buffer.Unpooled;
import io.netty.util.CharsetUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import io.netty.util.internal.StringUtil;

/**
 * A MessageFrame carries application data, and consists of any array of JSON encoded messages.
 */
public class MessageFrame extends DefaultByteBufHolder implements Frame {

    private final List<String> messages;

    public MessageFrame(final String message) {
        this(new String[] { message });
    }

    public MessageFrame(final String... messages) {
        this(new ArrayList<String>(Arrays.asList(messages)));
    }

    public MessageFrame(final List<String> messages) {
        super(generateContent(messages));
        this.messages = messages;
    }

    public List<String> messages() {
        return Collections.unmodifiableList(messages);
    }

    @Override
    public MessageFrame copy() {
        return new MessageFrame(messages);
    }

    @Override
    public MessageFrame duplicate() {
        return new MessageFrame(messages);
    }

    @Override
    public MessageFrame retain() {
        super.retain();
        return this;
    }

    @Override
    public MessageFrame retain(int increment) {
        super.retain(increment);
        return this;
    }

    @Override
    public String toString() {
        return StringUtil.simpleClassName(this) + "[messages=" + messages + ']';
    }

    private static ByteBuf generateContent(final List<String> messages) {
        final JsonStringEncoder jsonEndocder = new JsonStringEncoder();
        final ByteBuf content = Unpooled.buffer();
        content.writeByte('a').writeByte('[');
        final int size = messages.size();
        for (int i = 0; i < size; i++) {
            content.writeByte('"');
            final String element = messages.get(i);
            if (element == null) {
                messages.subList(i, size).clear();
                break;
            }
            final String escaped = escapeCharacters(jsonEndocder.quoteAsString(element));
            final ByteBuf escapedBuf = Unpooled.copiedBuffer(escaped, CharsetUtil.UTF_8);
            content.writeBytes(escapedBuf).writeByte('"');
            escapedBuf.release();
            if (i < size - 1) {
                content.writeByte(',');
            }
        }
        return content.writeByte(']');
    }

    private static String escapeCharacters(final char[] value) {
        final StringBuilder sb = new StringBuilder(value.length);
        for (char ch : value) {
            if (ch >= '\u0000' && ch <= '\u001F' || ch >= '\uD800' && ch <= '\uDFFF'
                    || ch >= '\u200C' && ch <= '\u200F' || ch >= '\u2028' && ch <= '\u202F'
                    || ch >= '\u2060' && ch <= '\u206F' || ch >= '\uFFF0' && ch <= '\uFFFF') {
                final String ss = Integer.toHexString(ch);
                sb.append('\\');
                sb.append('u');
                for (int k = 0; k < 4 - ss.length(); k++) {
                    sb.append('0');
                }
                sb.append(ss.toLowerCase());
            } else {
                sb.append(ch);
            }
        }
        return sb.toString();
    }

}