Java内部类学习(四)—— 接口中的静态内部类

今天在阅读JetServer源码protocal部分的时候碰见了内部类的又一写法。定义一个接口LoginProtocol,包括了一个域和一个方法,然后在其中写了三个内部类,分别实现了该接口,代码如下:

package org.menacheri.jetserver.handlers.netty;

import static org.menacheri.jetserver.event.Events.LOG_IN;
import static org.menacheri.jetserver.event.Events.PROTCOL_VERSION;
import static org.menacheri.jetserver.event.Events.RECONNECT;

import java.util.List;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder;
import org.jboss.netty.handler.codec.frame.LengthFieldPrepender;
import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import org.menacheri.jetserver.event.Events;

/**
 * Applies a protocol to the incoming pipeline which will handle login.
 * Subsequent protocol may also be manipulated by these login handlers.
 * 
 * @author Abraham Menacherry
 * 
 */
public interface LoginProtocol
{
    String LOGIN_HANDLER_NAME = "loginHandler";
    /**
     * Apply a protocol on the pipeline to handle login. Implementations will
     * first "search" if the incoming bytes correspond to the implementations
     * protocol, only if they match, the correspoinding protocol will be
     * applied.
     * 
     * @param buffer
     *            The incoming buffer, by default around 5 bytes will be read
     *            and passed on to detect the protocol
     * @param pipeline
     *            The channelpipeline on which the login protocol handlers need
     *            to be set.
     * @return Returs true if the protocol was applied, else false.
     */
    public boolean applyProtocol(ChannelBuffer buffer, ChannelPipeline pipeline);

    /**
     * Searches the incoming bytes of a client connection to determine if its an
     * HTTP connection, in which case Websocket or HTTP related handlers will be
     * applied on the piepline.
     * 
     * @author Abraham Menacherry
     * 
     */
    public static class HTTPProtocol implements LoginProtocol
    {
        private WebSocketLoginHandler webSocketLoginHandler;
        @Override
        public boolean applyProtocol(ChannelBuffer buffer,
                ChannelPipeline pipeline)
        {
            boolean isThisProtocol = false;
            final int magic1 = buffer.getUnsignedByte(buffer.readerIndex());
            final int magic2 = buffer.getUnsignedByte(buffer.readerIndex() + 1);
            if (isHttp(magic1, magic2))
            {
                pipeline.addLast("decoder", new HttpRequestDecoder());
                pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
                pipeline.addLast("encoder", new HttpResponseEncoder());
                pipeline.addLast("handler", new WebSocketServerProtocolHandler("/jetsocket"));
                pipeline.addLast(LOGIN_HANDLER_NAME, webSocketLoginHandler);
                isThisProtocol = true;
            }
            return isThisProtocol;
        }

        /**
         * Method which checks if the first 2 incoming parameters are G, E or
         * similar combiantions which signal that its an HTTP protocol, since
         * some protocols like jetserver's default protocol send the length
         * first (which is 2 arbitrary bytes), its better if this protocol is
         * searched last to avoid switching to HTTP protocol prematurely.
         * 
         * @param magic1
         * @param magic2
         * @return true if the two incoming bytes match any of the first two
         *         letter of HTTP headers like GET, POST etc.
         */
        protected boolean isHttp(int magic1, int magic2)
        {
            return magic1 == 'G' && magic2 == 'E' || // GET
                    magic1 == 'P' && magic2 == 'O' || // POST
                    magic1 == 'P' && magic2 == 'U' || // PUT
                    magic1 == 'H' && magic2 == 'E' || // HEAD
                    magic1 == 'O' && magic2 == 'P' || // OPTIONS
                    magic1 == 'P' && magic2 == 'A' || // PATCH
                    magic1 == 'D' && magic2 == 'E' || // DELETE
                    magic1 == 'T' && magic2 == 'R' || // TRACE
                    magic1 == 'C' && magic2 == 'O'; // CONNECT
        }

        public WebSocketLoginHandler getWebSocketLoginHandler()
        {
            return webSocketLoginHandler;
        }

        public void setWebSocketLoginHandler(WebSocketLoginHandler webSocketLoginHandler)
        {
            this.webSocketLoginHandler = webSocketLoginHandler;
        }
    }

    /**
     * This is the default protocol of jetserver. If incoming event is of type
     * LOG_IN and also has appropriate protocol version as defined in the
     * {@link Events} class, then this protocol will be applied. The 3rd and 4th
     * bytes of the incoming transmission are searched to get this information.
     * 
     * @author Abraham Menacherry
     * 
     */
    public static class DefaultJetProtocol implements LoginProtocol
    {

        private int frameSize = 1024;
        private EventDecoder eventDecoder;
        private LoginHandler loginHandler;
        private LengthFieldPrepender lengthFieldPrepender;

        @Override
        public boolean applyProtocol(ChannelBuffer buffer,
                ChannelPipeline pipeline)
        {
            boolean isThisProtocol = false;
            final int opcode = buffer.getUnsignedByte(buffer.readerIndex() + 2);
            final int protocolVersion = buffer.getUnsignedByte(buffer
                    .readerIndex() + 3);
            if (isJetProtocol(opcode, protocolVersion))
            {
                pipeline.addLast("framer", createLengthBasedFrameDecoder());
                pipeline.addLast("eventDecoder", eventDecoder);
                pipeline.addLast(LOGIN_HANDLER_NAME, loginHandler);
                pipeline.addLast("lengthFieldPrepender", lengthFieldPrepender);
                isThisProtocol = true;
            }
            return isThisProtocol;
        }

        protected boolean isJetProtocol(int magic1, int magic2)
        {
            return ((magic1 == LOG_IN || magic1 == RECONNECT) && magic2 == PROTCOL_VERSION);
        }

        public ChannelHandler createLengthBasedFrameDecoder()
        {
            return new LengthFieldBasedFrameDecoder(frameSize, 0, 2, 0, 2);
        }

        public int getFrameSize()
        {
            return frameSize;
        }

        public void setFrameSize(int frameSize)
        {
            this.frameSize = frameSize;
        }

        public EventDecoder getEventDecoder()
        {
            return eventDecoder;
        }

        public void setEventDecoder(EventDecoder eventDecoder)
        {
            this.eventDecoder = eventDecoder;
        }

        public LoginHandler getLoginHandler()
        {
            return loginHandler;
        }

        public void setLoginHandler(LoginHandler loginHandler)
        {
            this.loginHandler = loginHandler;
        }

        public LengthFieldPrepender getLengthFieldPrepender()
        {
            return lengthFieldPrepender;
        }

        public void setLengthFieldPrepender(
                LengthFieldPrepender lengthFieldPrepender)
        {
            this.lengthFieldPrepender = lengthFieldPrepender;
        }
    }

    public static class CompositeProtocol implements LoginProtocol
    {
        private List<LoginProtocol> protocols;

        @Override
        public boolean applyProtocol(ChannelBuffer buffer,
                ChannelPipeline pipeline)
        {
            if (null != protocols)
            {
                for (LoginProtocol protocol : protocols)
                {
                    if (protocol.applyProtocol(buffer, pipeline))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        public List<LoginProtocol> getProtocols()
        {
            return protocols;
        }

        public void setProtocols(List<LoginProtocol> protocols)
        {
            this.protocols = protocols;
        }
    }
}

 在用Spring框架进行注入的时候,引用的方法是:接口所在的包名.接口名.内部类名字:

<!-- Login Protocols these decide what handlers are in the pipeline during 
        login of a client to jetserver -->
    <bean id="httpLoginProtocol" class="org.menacheri.jetserver.handlers.netty.LoginProtocol.HTTPProtocol" >
        <property name="webSocketLoginHandler" ref="webSocketLoginHandler" ></property>
    </bean>
    
    <bean id="defaultJetLoginProtocol" class="org.menacheri.jetserver.handlers.netty.LoginProtocol.DefaultJetProtocol" >
        <property name="eventDecoder" ref="eventDecoder"></property>
        <property name="loginHandler" ref="loginHandler"></property>
        <property name="lengthFieldPrepender" ref="lengthFieldPrepender"></property>
    </bean>
    
    
    <bean id="compositeLoginProtocol" class="org.menacheri.jetserver.handlers.netty.LoginProtocol.CompositeProtocol" scope="prototype">
        <property name="protocols">
            <list>
                <ref bean="defaultJetLoginProtocol"/>
                <ref bean="httpLoginProtocol"/>
            </list>
        </property>
    </bean>

 

你可能感兴趣的:(Java内部类学习(四)—— 接口中的静态内部类)