EMMA Coverage Report (generated Sat Sep 03 11:42:34 KST 2005)
[all classes][org.apache.mina.protocol.codec]

COVERAGE SUMMARY FOR SOURCE FILE [DemuxingProtocolCodecFactory.java]

nameclass, %method, %block, %line, %
DemuxingProtocolCodecFactory.java0%   (0/8)0%   (0/22)0%   (0/617)0%   (0/146)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class DemuxingProtocolCodecFactory0%   (0/1)0%   (0/8)0%   (0/166)0%   (0/38)
DemuxingProtocolCodecFactory (): void 0%   (0/1)0%   (0/11)0%   (0/4)
newDecoder (): ProtocolDecoder 0%   (0/1)0%   (0/5)0%   (0/1)
newEncoder (): ProtocolEncoder 0%   (0/1)0%   (0/6)0%   (0/1)
register (Class): void 0%   (0/1)0%   (0/64)0%   (0/12)
register (MessageDecoder): void 0%   (0/1)0%   (0/8)0%   (0/2)
register (MessageDecoderFactory): void 0%   (0/1)0%   (0/32)0%   (0/8)
register (MessageEncoder): void 0%   (0/1)0%   (0/8)0%   (0/2)
register (MessageEncoderFactory): void 0%   (0/1)0%   (0/32)0%   (0/8)
     
class DemuxingProtocolCodecFactory$10%   (0/1)100% (0/0)100% (0/0)100% (0/0)
     
class DemuxingProtocolCodecFactory$DefaultConstructorMessageDecoderFactory0%   (0/1)0%   (0/2)0%   (0/49)0%   (0/10)
DemuxingProtocolCodecFactory$DefaultConstructorMessageDecoderFactory (Class):... 0%   (0/1)0%   (0/29)0%   (0/7)
newDecoder (): MessageDecoder 0%   (0/1)0%   (0/20)0%   (0/3)
     
class DemuxingProtocolCodecFactory$DefaultConstructorMessageEncoderFactory0%   (0/1)0%   (0/2)0%   (0/49)0%   (0/10)
DemuxingProtocolCodecFactory$DefaultConstructorMessageEncoderFactory (Class):... 0%   (0/1)0%   (0/29)0%   (0/7)
newEncoder (): MessageEncoder 0%   (0/1)0%   (0/20)0%   (0/3)
     
class DemuxingProtocolCodecFactory$ProtocolDecoderImpl0%   (0/1)0%   (0/2)0%   (0/178)0%   (0/40)
DemuxingProtocolCodecFactory$ProtocolDecoderImpl (DemuxingProtocolCodecFactor... 0%   (0/1)0%   (0/32)0%   (0/7)
doDecode (ProtocolSession, ByteBuffer, ProtocolDecoderOutput): boolean 0%   (0/1)0%   (0/146)0%   (0/33)
     
class DemuxingProtocolCodecFactory$ProtocolEncoderImpl0%   (0/1)0%   (0/4)0%   (0/143)0%   (0/36)
DemuxingProtocolCodecFactory$ProtocolEncoderImpl (DemuxingProtocolCodecFactor... 0%   (0/1)0%   (0/46)0%   (0/11)
encode (ProtocolSession, Object, ProtocolEncoderOutput): void 0%   (0/1)0%   (0/27)0%   (0/6)
findEncoder (Class): MessageEncoder 0%   (0/1)0%   (0/17)0%   (0/4)
findEncoder (Class, Set): MessageEncoder 0%   (0/1)0%   (0/53)0%   (0/15)
     
class DemuxingProtocolCodecFactory$SingletonMessageDecoderFactory0%   (0/1)0%   (0/2)0%   (0/16)0%   (0/6)
DemuxingProtocolCodecFactory$SingletonMessageDecoderFactory (MessageDecoder):... 0%   (0/1)0%   (0/13)0%   (0/5)
newDecoder (): MessageDecoder 0%   (0/1)0%   (0/3)0%   (0/1)
     
class DemuxingProtocolCodecFactory$SingletonMessageEncoderFactory0%   (0/1)0%   (0/2)0%   (0/16)0%   (0/6)
DemuxingProtocolCodecFactory$SingletonMessageEncoderFactory (MessageEncoder):... 0%   (0/1)0%   (0/13)0%   (0/5)
newEncoder (): MessageEncoder 0%   (0/1)0%   (0/3)0%   (0/1)

1/*
2 *   @(#) $Id: DemuxingProtocolCodecFactory.java 264677 2005-08-30 02:44:35Z trustin $
3 *
4 *   Copyright 2004 The Apache Software Foundation
5 *
6 *   Licensed under the Apache License, Version 2.0 (the "License");
7 *   you may not use this file except in compliance with the License.
8 *   You may obtain a copy of the License at
9 *
10 *       http://www.apache.org/licenses/LICENSE-2.0
11 *
12 *   Unless required by applicable law or agreed to in writing, software
13 *   distributed under the License is distributed on an "AS IS" BASIS,
14 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 *   See the License for the specific language governing permissions and
16 *   limitations under the License.
17 *
18 */
19package org.apache.mina.protocol.codec;
20 
21import java.util.HashSet;
22import java.util.IdentityHashMap;
23import java.util.Iterator;
24import java.util.Map;
25import java.util.Set;
26 
27import org.apache.mina.common.ByteBuffer;
28import org.apache.mina.protocol.ProtocolCodecFactory;
29import org.apache.mina.protocol.ProtocolDecoder;
30import org.apache.mina.protocol.ProtocolDecoderOutput;
31import org.apache.mina.protocol.ProtocolEncoder;
32import org.apache.mina.protocol.ProtocolEncoderOutput;
33import org.apache.mina.protocol.ProtocolSession;
34import org.apache.mina.protocol.ProtocolViolationException;
35 
36/**
37 * A composite {@link ProtocolCodecFactory} that consists of multiple
38 * {@link MessageEncoder}s and {@link MessageDecoder}s.
39 * {@link ProtocolEncoder} and {@link ProtocolDecoder} this factory
40 * returns demultiplex incoming messages and buffers to
41 * appropriate {@link MessageEncoder}s and {@link MessageDecoder}s. 
42 * 
43 * @author The Apache Directory Project (dev@directory.apache.org)
44 * @author Trustin Lee (trustin@apache.org)
45 * @version $Rev: 264677 $, $Date: 2005-08-30 11:44:35 +0900 $
46 * 
47 * @see MessageEncoder
48 * @see MessageDecoder
49 */
50public class DemuxingProtocolCodecFactory implements ProtocolCodecFactory {
51 
52    private MessageDecoderFactory[] decoderFactories = new MessageDecoderFactory[0];
53    private MessageEncoderFactory[] encoderFactories = new MessageEncoderFactory[0];
54    
55    public DemuxingProtocolCodecFactory()
56    {
57    }
58    
59    public void register( Class encoderOrDecoderClass )
60    {
61        if( encoderOrDecoderClass == null )
62        {
63            throw new NullPointerException( "encoderOrDecoderClass" );
64        }
65 
66        boolean registered = false;
67        if( MessageEncoder.class.isAssignableFrom( encoderOrDecoderClass ) )
68        {
69            register( new DefaultConstructorMessageEncoderFactory( encoderOrDecoderClass ) );
70            registered = true;
71        }
72        
73        if( MessageDecoder.class.isAssignableFrom( encoderOrDecoderClass ) )
74        {
75            register( new DefaultConstructorMessageDecoderFactory( encoderOrDecoderClass ) );
76            registered = true;
77        }
78        
79        if( !registered )
80        {
81            throw new IllegalArgumentException( "Unregisterable type: " + encoderOrDecoderClass );
82        }
83    }
84    
85    public void register( MessageEncoder encoder )
86    {
87        register( new SingletonMessageEncoderFactory( encoder ) );
88    }
89    
90    public void register( MessageEncoderFactory factory )
91    {
92        if( factory == null )
93        {
94            throw new NullPointerException( "factory" );
95        }
96        MessageEncoderFactory[] encoderFactories = this.encoderFactories;
97        MessageEncoderFactory[] newEncoderFactories = new MessageEncoderFactory[ encoderFactories.length + 1 ];
98        System.arraycopy( encoderFactories, 0, newEncoderFactories, 0, encoderFactories.length );
99        newEncoderFactories[ encoderFactories.length ] = factory;
100        this.encoderFactories = newEncoderFactories;
101    }
102    
103    public void register( MessageDecoder decoder )
104    {
105        register( new SingletonMessageDecoderFactory( decoder ) );
106    }
107    
108    public void register( MessageDecoderFactory factory )
109    {
110        if( factory == null )
111        {
112            throw new NullPointerException( "factory" );
113        }
114        MessageDecoderFactory[] decoderFactories = this.decoderFactories;
115        MessageDecoderFactory[] newDecoderFactories = new MessageDecoderFactory[ decoderFactories.length + 1 ];
116        System.arraycopy( decoderFactories, 0, newDecoderFactories, 0, decoderFactories.length );
117        newDecoderFactories[ decoderFactories.length ] = factory;
118        this.decoderFactories = newDecoderFactories;
119    }
120    
121    public ProtocolEncoder newEncoder() {
122        return new ProtocolEncoderImpl();
123    }
124 
125    public ProtocolDecoder newDecoder() {
126        return new ProtocolDecoderImpl();
127    }
128    
129    private class ProtocolEncoderImpl implements ProtocolEncoder
130    {
131        private final Map encoders = new IdentityHashMap();
132        
133        private ProtocolEncoderImpl()
134        {
135            MessageEncoderFactory[] encoderFactories = DemuxingProtocolCodecFactory.this.encoderFactories;
136            for( int i = encoderFactories.length - 1; i >= 0; i-- )
137            {
138                MessageEncoder encoder = encoderFactories[ i ].newEncoder();
139                Iterator it = encoder.getMessageTypes().iterator();
140                while( it.hasNext() )
141                {
142                    Class type = ( Class ) it.next();
143                    encoders.put( type, encoder );
144                }
145            }
146        }
147        
148        public void encode( ProtocolSession session, Object message,
149                            ProtocolEncoderOutput out ) throws ProtocolViolationException
150        {
151            Class type = message.getClass();
152            MessageEncoder encoder = findEncoder( type );
153            if( encoder == null )
154            {
155                throw new ProtocolViolationException( "Unexpected message type: " + type );
156            }
157            
158            encoder.encode( session, message, out );
159        }
160        
161        private MessageEncoder findEncoder( Class type )
162        {
163            MessageEncoder encoder = ( MessageEncoder ) encoders.get( type );
164            if( encoder == null )
165            {
166                encoder = findEncoder( type, new HashSet() );
167            }
168 
169            return encoder;
170        }
171 
172        private MessageEncoder findEncoder( Class type, Set triedClasses )
173        {
174            MessageEncoder encoder;
175 
176            if( triedClasses.contains( type ) )
177                return null;
178            triedClasses.add( type );
179 
180            encoder = ( MessageEncoder ) encoders.get( type );
181            if( encoder == null )
182            {
183                encoder = findEncoder( type, triedClasses );
184                if( encoder != null )
185                    return encoder;
186 
187                Class[] interfaces = type.getInterfaces();
188                for( int i = 0; i < interfaces.length; i ++ )
189                {
190                    encoder = findEncoder( interfaces[ i ], triedClasses );
191                    if( encoder != null )
192                        return encoder;
193                }
194 
195                return null;
196            }
197            else
198                return encoder;
199        }
200    }
201    
202    private class ProtocolDecoderImpl extends CumulativeProtocolDecoder
203    {
204        private final MessageDecoder[] decoders;
205        private MessageDecoder currentDecoder;
206 
207        protected ProtocolDecoderImpl()
208        {
209            super( 16 );
210            
211            MessageDecoderFactory[] decoderFactories = DemuxingProtocolCodecFactory.this.decoderFactories;
212            decoders = new MessageDecoder[ decoderFactories.length ];
213            for( int i = decoderFactories.length - 1; i >= 0; i-- )
214            {
215                decoders[ i ] = decoderFactories[ i ].newDecoder();
216            }
217        }
218 
219        protected boolean doDecode( ProtocolSession session, ByteBuffer in,
220                                    ProtocolDecoderOutput out) throws ProtocolViolationException
221        {
222            if( currentDecoder == null )
223            {
224                MessageDecoder[] decoders = this.decoders;
225                int undecodables = 0;
226                for( int i = decoders.length - 1; i >= 0; i -- ) 
227                {
228                    MessageDecoder decoder = decoders[i];
229                    int limit = in.limit();
230                    int pos = in.position();
231 
232                    MessageDecoderResult result;
233                    try
234                    {
235                        result = decoder.decodable( session, in );
236                    }
237                    finally
238                    {
239                        in.position( pos );
240                        in.limit( limit );
241                    }
242                    
243                    if( result == MessageDecoder.OK )
244                    {
245                        currentDecoder = decoder;
246                        break;
247                    }
248                    else if( result == MessageDecoder.NOT_OK )
249                    {
250                        undecodables ++;
251                    }
252                    else if( result != MessageDecoder.NEED_DATA )
253                    {
254                        throw new IllegalStateException( "Unexpected decode result (see your decodable()): " + result );
255                    }
256                }
257                
258                if( undecodables == decoders.length )
259                {
260                    // Throw an exception if all decoders cannot decode data.
261                    in.position( in.limit() ); // Skip data
262                    throw new ProtocolViolationException(
263                            "No appropriate message decoder: " + in.getHexDump() );
264                }
265                
266                if( currentDecoder == null )
267                {
268                    // Decoder is not determined yet (i.e. we need more data)
269                    return false;
270                }
271            }
272            
273            MessageDecoderResult result = currentDecoder.decode( session, in, out );
274            if( result == MessageDecoder.OK )
275            {
276                currentDecoder = null;
277                return true;
278            }
279            else if( result == MessageDecoder.NEED_DATA )
280            {
281                return false;
282            }
283            else if( result == MessageDecoder.NOT_OK )
284            {
285                throw new ProtocolViolationException( "Message decoder returned NOT_OK." );
286            }
287            else
288            {
289                throw new IllegalStateException( "Unexpected decode result (see your decode()): " + result );
290            }
291        }
292    }
293    
294    private static class SingletonMessageEncoderFactory implements MessageEncoderFactory
295    {
296        private final MessageEncoder encoder;
297        
298        private SingletonMessageEncoderFactory( MessageEncoder encoder )
299        {
300            if( encoder == null )
301            {
302                throw new NullPointerException( "encoder" );
303            }
304            this.encoder = encoder;
305        }
306 
307        public MessageEncoder newEncoder()
308        {
309            return encoder;
310        }
311    }
312 
313    private static class SingletonMessageDecoderFactory implements MessageDecoderFactory
314    {
315        private final MessageDecoder decoder;
316        
317        private SingletonMessageDecoderFactory( MessageDecoder decoder )
318        {
319            if( decoder == null )
320            {
321                throw new NullPointerException( "decoder" );
322            }
323            this.decoder = decoder;
324        }
325 
326        public MessageDecoder newDecoder()
327        {
328            return decoder;
329        }
330    }
331    
332    private static class DefaultConstructorMessageEncoderFactory implements MessageEncoderFactory
333    {
334        private final Class encoderClass;
335        
336        private DefaultConstructorMessageEncoderFactory( Class encoderClass )
337        {
338            if( encoderClass == null )
339            {
340                throw new NullPointerException( "encoderClass" );
341            }
342            
343            if( !MessageEncoder.class.isAssignableFrom( encoderClass ) )
344            {
345                throw new IllegalArgumentException( "encoderClass is not assignable to MessageEncoder" );
346            }
347            this.encoderClass = encoderClass;
348        }
349 
350        public MessageEncoder newEncoder()
351        {
352            try
353            {
354                return ( MessageEncoder ) encoderClass.newInstance();
355            }
356            catch( Exception e )
357            {
358                throw new RuntimeException( "Failed to create a new instance of " + encoderClass, e );
359            }
360        }
361    }
362 
363    private static class DefaultConstructorMessageDecoderFactory implements MessageDecoderFactory
364    {
365        private final Class decoderClass;
366        
367        private DefaultConstructorMessageDecoderFactory( Class decoderClass )
368        {
369            if( decoderClass == null )
370            {
371                throw new NullPointerException( "decoderClass" );
372            }
373            
374            if( !MessageDecoder.class.isAssignableFrom( decoderClass ) )
375            {
376                throw new IllegalArgumentException( "decoderClass is not assignable to MessageDecoder" );
377            }
378            this.decoderClass = decoderClass;
379        }
380 
381        public MessageDecoder newDecoder()
382        {
383            try
384            {
385                return ( MessageDecoder ) decoderClass.newInstance();
386            }
387            catch( Exception e )
388            {
389                throw new RuntimeException( "Failed to create a new instance of " + decoderClass, e );
390            }
391        }
392    }
393}

[all classes][org.apache.mina.protocol.codec]
EMMA 2.0.4217 (C) Vladimir Roubtsov