Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * JBoss, Home of Professional Open Source.
   * Copyright 2012 Red Hat, Inc., and individual contributors
   * as indicated by the @author tags.
   *
   * 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 io.undertow.websockets.core;
 
 import org.xnio.Pool;
 
Utility class which holds general useful utility methods which can be used within WebSocket implementations.

Author(s):
Norman Maurer
 
 public final class WebSocketUtils {

    
UTF-8 java.nio.charset.Charset which is used to encode Strings in WebSockets
 
     public static final Charset UTF_8 = Charset.forName("UTF-8");
     private static final String EMPTY = "";

    
Generate the MD5 hash out of the given java.nio.ByteBuffer
 
     public static ByteBuffer md5(ByteBuffer buffer) {
         try {
             MessageDigest md = MessageDigest.getInstance("MD5");
             md.update(buffer);
             return ByteBuffer.wrap(md.digest());
         } catch (NoSuchAlgorithmException e) {
             // Should never happen
             throw new InternalError("MD5 not supported on this platform");
         }
     }

    
Create a java.nio.ByteBuffer which holds the UTF8 encoded bytes for the given java.lang.String.

Parameters:
utfString The java.lang.String to convert
Returns:
buffer The java.nio.ByteBuffer which was created
 
     public static ByteBuffer fromUtf8String(CharSequence utfString) {
         if (utfString == null || utfString.length() == 0) {
             return .;
         } else {
             return ByteBuffer.wrap(utfString.toString().getBytes());
         }
     }
 
     public static String toUtf8String(ByteBuffer buffer) {
         if (!buffer.hasRemaining()) {
             return ;
         }
         if (buffer.hasArray()) {
             return new String(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining(), );
         } else {
             byte[] content = new byte[buffer.remaining()];
             buffer.get(content);
             return new String(content);
         }
     }
 
     public static String toUtf8String(ByteBuffer... buffers) {
         int size = 0;
         for (ByteBuffer bufbuffers) {
             size += buf.remaining();
         }
        if (size == 0) {
            return ;
        }
        int index = 0;
        byte[] bytes = new byte[size];
        for (ByteBuffer bufbuffers) {
            if (buf.hasArray()) {
                int len = buf.remaining();
                System.arraycopy(buf.array(), buf.arrayOffset() + buf.position(), bytesindexlen);
                index += len;
            } else {
                int len = buf.remaining();
                buf.get(bytesindexlen);
                index += len;
            }
        }
        return new String(bytes);
    }

    
Transfer the data from the source to the sink using the given through buffer to pass data through.
    public static long transfer(final ReadableByteChannel sourcefinal long countfinal ByteBuffer throughBufferfinal WritableByteChannel sinkthrows IOException {
        long total = 0L;
        while (total < count) {
            throughBuffer.clear();
            if (count - total < throughBuffer.remaining()) {
                throughBuffer.limit((int) (count - total));
            }
            try {
                long res = source.read(throughBuffer);
                if (res <= 0) {
                    return total == 0L ? res : total;
                }
            } finally {
                throughBuffer.flip();
            }
            while (throughBuffer.hasRemaining()) {
                long res = sink.write(throughBuffer);
                if (res <= 0) {
                    return total;
                }
                total += res;
            }
        }
        return total;
    }

    
Echo back the frame to the sender
    public static void echoFrame(final WebSocketChannel channelfinal StreamSourceFrameChannel wsthrows IOException {
        final WebSocketFrameType type;
        switch (ws.getType()) {
            case :
                // pong frames must be discarded
                ws.discard();
                return;
            case :
                // if a ping is send the autobahn testsuite expects a PONG when echo back
                type = .;
                break;
            default:
                type = ws.getType();
                break;
        }
        final StreamSinkFrameChannel sink = channel.send(type);
        sink.setRsv(ws.getRsv());
        initiateTransfer(wssinknew ChannelListener<StreamSourceFrameChannel>() {
                    @Override
                    public void handleEvent(StreamSourceFrameChannel streamSourceFrameChannel) {
                        IoUtils.safeClose(streamSourceFrameChannel);
                    }
                }, new ChannelListener<StreamSinkFrameChannel>() {
                    @Override
                    public void handleEvent(StreamSinkFrameChannel streamSinkFrameChannel) {
                        try {
                            streamSinkFrameChannel.shutdownWrites();
                        } catch (IOException e) {
                            e.printStackTrace();
                            IoUtils.safeClose(streamSinkFrameChannelchannel);
                            return;
                        }
                        try {
                            if (!streamSinkFrameChannel.flush()) {
                                streamSinkFrameChannel.getWriteSetter().set(ChannelListeners.flushingChannelListener(
                                        new ChannelListener<StreamSinkFrameChannel>() {
                                            @Override
                                            public void handleEvent(StreamSinkFrameChannel streamSinkFrameChannel) {
                                                streamSinkFrameChannel.getWriteSetter().set(null);
                                                IoUtils.safeClose(streamSinkFrameChannel);
                                                if (type == .) {
                                                    IoUtils.safeClose(channel);
                                                }
                                            }
                                        }, new ChannelExceptionHandler<StreamSinkFrameChannel>() {
                                            @Override
                                            public void handleException(StreamSinkFrameChannel streamSinkFrameChannelIOException e) {
                                                e.printStackTrace();
                                                IoUtils.safeClose(streamSinkFrameChannelchannel);
                                            }
                                        }
                                ));
                                streamSinkFrameChannel.resumeWrites();
                            } else {
                                if (type == .) {
                                    IoUtils.safeClose(channel);
                                }
                                streamSinkFrameChannel.getWriteSetter().set(null);
                                IoUtils.safeClose(streamSinkFrameChannel);
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                            IoUtils.safeClose(streamSinkFrameChannelchannel);
                        }
                    }
                }, new ChannelExceptionHandler<StreamSourceFrameChannel>() {
                    @Override
                    public void handleException(StreamSourceFrameChannel streamSourceFrameChannelIOException e) {
                        e.printStackTrace();
                        IoUtils.safeClose(streamSourceFrameChannelchannel);
                    }
                }, new ChannelExceptionHandler<StreamSinkFrameChannel>() {
                    @Override
                    public void handleException(StreamSinkFrameChannel streamSinkFrameChannelIOException e) {
                        e.printStackTrace();
                        IoUtils.safeClose(streamSinkFrameChannelchannel);
                    }
                }, channel.getBufferPool()
        );
    }

    
Initiate a low-copy transfer between two stream channels. The pool should be a direct buffer pool for best performance.

Parameters:
source the source channel
sink the target channel
sourceListener the source listener to set and call when the transfer is complete, or null to clear the listener at that time
sinkListener the target listener to set and call when the transfer is complete, or null to clear the listener at that time
readExceptionHandler the read exception handler to call if an error occurs during a read operation
writeExceptionHandler the write exception handler to call if an error occurs during a write operation
pool the pool from which the transfer buffer should be allocated
    public static <I extends StreamSourceChannel, O extends StreamSinkChannelvoid initiateTransfer(final I sourcefinal O sinkfinal ChannelListener<? super I> sourceListenerfinal ChannelListener<? super O> sinkListenerfinal ChannelExceptionHandler<? super I> readExceptionHandlerfinal ChannelExceptionHandler<? super O> writeExceptionHandlerPool<ByteBufferpool) {
        if (pool == null) {
            throw new IllegalArgumentException("pool is null");
        }
        final Pooled<ByteBufferallocated = pool.allocate();
        boolean free = true;
        try {
            final ByteBuffer buffer = allocated.getResource();
            buffer.clear();
            long transferred;
            do {
                try {
                    transferred = source.transferTo(.buffersink);
                } catch (IOException e) {
                    ChannelListeners.invokeChannelExceptionHandler(sourcereadExceptionHandlere);
                    return;
                }
                if (transferred == -1) {
                    source.suspendReads();
                    sink.suspendWrites();
                    ChannelListeners.invokeChannelListener(sourcesourceListener);
                    ChannelListeners.invokeChannelListener(sinksinkListener);
                    return;
                }
                while (buffer.hasRemaining()) {
                    final int res;
                    try {
                        res = sink.write(buffer);
                    } catch (IOException e) {
                        ChannelListeners.invokeChannelExceptionHandler(sinkwriteExceptionHandlere);
                        return;
                    }
                    if (res == 0) {
                        // write first listener
                        final TransferListener<I, O> listener = new TransferListener<I, O>(allocatedsourcesinksourceListenersinkListenerwriteExceptionHandlerreadExceptionHandler, 1);
                        source.suspendReads();
                        source.getReadSetter().set(listener);
                        sink.getWriteSetter().set(listener);
                        sink.resumeWrites();
                        free = false;
                        return;
                    } else if (res == -1) {
                        source.suspendReads();
                        sink.suspendWrites();
                        ChannelListeners.invokeChannelListener(sourcesourceListener);
                        ChannelListeners.invokeChannelListener(sinksinkListener);
                        return;
                    }
                }
            } while (transferred > 0L);
            final TransferListener<I, O> listener = new TransferListener<I, O>(allocatedsourcesinksourceListenersinkListenerwriteExceptionHandlerreadExceptionHandler, 0);
            sink.suspendWrites();
            sink.getWriteSetter().set(listener);
            source.getReadSetter().set(listener);
            // read first listener
            sink.suspendWrites();
            source.resumeReads();
            free = false;
        } finally {
            if (free) {
                allocated.free();
            }
        }
    }
    static final class TransferListener<I extends StreamSourceChannel, O extends StreamSinkChannelimplements ChannelListener<Channel> {
        private final Pooled<ByteBufferpooledBuffer;
        private final I source;
        private final O sink;
        private final ChannelListener<? super I> sourceListener;
        private final ChannelListener<? super O> sinkListener;
        private final ChannelExceptionHandler<? super O> writeExceptionHandler;
        private final ChannelExceptionHandler<? super I> readExceptionHandler;
        private volatile int state;
        TransferListener(final Pooled<ByteBufferpooledBufferfinal I sourcefinal O sinkfinal ChannelListener<? super I> sourceListenerfinal ChannelListener<? super O> sinkListenerfinal ChannelExceptionHandler<? super O> writeExceptionHandlerfinal ChannelExceptionHandler<? super I> readExceptionHandlerfinal int state) {
            this. = pooledBuffer;
            this. = source;
            this. = sink;
            this. = sourceListener;
            this. = sinkListener;
            this. = writeExceptionHandler;
            this. = readExceptionHandler;
            this. = state;
        }
        @Override
        public void handleEvent(final Channel channel) {
            final ByteBuffer buffer = .getResource();
            int state = this.;
            long lres;
            int ires;
            switch (state) {
                case 0: {
                    // read listener
                    for (; ; ) {
                        if(buffer.hasRemaining()) {
                            ..error("BUFFER HAS REMAINING!!!!!");
                        }
                        try {
                            lres = .transferTo(.buffer);
                        } catch (IOException e) {
                            readFailed(e);
                            return;
                        }
                        if (lres == 0 && !buffer.hasRemaining()) {
                            return;
                        }
                        if (lres == -1) {
                            // possibly unexpected EOF
                            // it's OK; just be done
                            done();
                            return;
                        }
                        while (buffer.hasRemaining()) {
                            try {
                                ires = .write(buffer);
                            } catch (IOException e) {
                                writeFailed(e);
                                return;
                            }
                            if (ires == 0) {
                                this. = 1;
                                .suspendReads();
                                .resumeWrites();
                                return;
                            }
                        }
                    }
                }
                case 1: {
                    // write listener
                    for (; ; ) {
                        while (buffer.hasRemaining()) {
                            try {
                                ires = .write(buffer);
                            } catch (IOException e) {
                                writeFailed(e);
                                return;
                            }
                            if (ires == 0) {
                                return;
                            }
                        }
                        try {
                            lres = .transferTo(.buffer);
                        } catch (IOException e) {
                            readFailed(e);
                            return;
                        }
                        if (lres == 0 && !buffer.hasRemaining()) {
                            this. = 0;
                            .suspendWrites();
                            .resumeReads();
                            return;
                        }
                        if (lres == -1) {
                            done();
                            return;
                        }
                    }
                }
            }
        }
        private void writeFailed(final IOException e) {
            try {
                .suspendReads();
                .suspendWrites();
                ChannelListeners.invokeChannelExceptionHandler(e);
            } finally {
                .free();
            }
        }
        private void readFailed(final IOException e) {
            try {
                .suspendReads();
                .suspendWrites();
                ChannelListeners.invokeChannelExceptionHandler(e);
            } finally {
                .free();
            }
        }
        private void done() {
            try {
                final ChannelListener<? super I> sourceListener = this.;
                final ChannelListener<? super O> sinkListener = this.;
                final I source = this.;
                final O sink = this.;
                source.suspendReads();
                sink.suspendWrites();
                ChannelListeners.invokeChannelListener(sourcesourceListener);
                ChannelListeners.invokeChannelListener(sinksinkListener);
            } finally {
                .free();
            }
        }
        public String toString() {
            return "Transfer channel listener (" +  + " to " +  + ") -> (" +  + " and " +  + ')';
        }
    }
    private WebSocketUtils() {
        // utility class
    }
New to GrepCode? Check out our FAQ X