48
48
public class FIXMessageDecoder implements MessageDecoder {
49
49
50
50
private static final char SOH = '\001' ;
51
- private static final String FIELD_DELIMITER = String .valueOf (SOH );
52
51
53
52
private final Logger log = LoggerFactory .getLogger (getClass ());
54
53
@@ -78,11 +77,11 @@ private void resetState() {
78
77
}
79
78
80
79
public FIXMessageDecoder () throws UnsupportedEncodingException {
81
- this (CharsetSupport .getCharset (), FIELD_DELIMITER );
80
+ this (CharsetSupport .getCharset ());
82
81
}
83
82
84
83
public FIXMessageDecoder (String charset ) throws UnsupportedEncodingException {
85
- this (charset , FIELD_DELIMITER );
84
+ this (charset , String . valueOf ( SOH ) );
86
85
}
87
86
88
87
public FIXMessageDecoder (String charset , String delimiter ) throws UnsupportedEncodingException {
@@ -93,12 +92,14 @@ public FIXMessageDecoder(String charset, String delimiter) throws UnsupportedEnc
93
92
resetState ();
94
93
}
95
94
95
+ @ Override
96
96
public MessageDecoderResult decodable (IoSession session , IoBuffer in ) {
97
97
boolean hasHeader = HEADER_PATTERN .find (in , in .position ()) != -1L ;
98
98
return hasHeader ? MessageDecoderResult .OK :
99
99
(in .remaining () > MAX_UNDECODED_DATA_LENGTH ? MessageDecoderResult .NOT_OK : MessageDecoderResult .NEED_DATA );
100
100
}
101
101
102
+ @ Override
102
103
public MessageDecoderResult decode (IoSession session , IoBuffer in , ProtocolDecoderOutput out )
103
104
throws ProtocolCodecException {
104
105
int messageCount = 0 ;
@@ -148,9 +149,9 @@ private boolean parseMessage(IoBuffer in, ProtocolDecoderOutput out)
148
149
149
150
if (state == PARSING_LENGTH ) {
150
151
byte ch = 0 ;
151
- while (hasRemaining ( in )) {
152
- ch = get (in );
153
- if (! Character . isDigit (( char ) ch )) {
152
+ while (position < in . limit ( )) { // while data remains
153
+ ch = in . get (position ++ );
154
+ if (ch < '0' || ch > '9' ) { // if not digit
154
155
break ;
155
156
}
156
157
bodyLength = bodyLength * 10 + (ch - '0' );
@@ -161,7 +162,7 @@ private boolean parseMessage(IoBuffer in, ProtocolDecoderOutput out)
161
162
log .debug ("body length = " + bodyLength + ": " + getBufferDebugInfo (in ));
162
163
}
163
164
} else {
164
- if (hasRemaining ( in )) {
165
+ if (position < in . limit ( )) { // if data remains
165
166
String messageString = getMessageStringForError (in );
166
167
handleError (in , in .position () + 1 , "Length format error in message (last character:" + ch + "): " + messageString ,
167
168
false );
@@ -173,7 +174,7 @@ private boolean parseMessage(IoBuffer in, ProtocolDecoderOutput out)
173
174
}
174
175
175
176
if (state == READING_BODY ) {
176
- if (remaining ( in ) < bodyLength ) {
177
+ if (in . limit () - position < bodyLength ) { // if remaining data is less than body
177
178
break ;
178
179
}
179
180
position += bodyLength ;
@@ -223,9 +224,7 @@ private boolean parseMessage(IoBuffer in, ProtocolDecoderOutput out)
223
224
}
224
225
return messageFound ;
225
226
} catch (Throwable t ) {
226
- state = SEEKING_HEADER ;
227
- position = 0 ;
228
- bodyLength = 0 ;
227
+ resetState ();
229
228
if (t instanceof ProtocolCodecException ) {
230
229
throw (ProtocolCodecException ) t ;
231
230
} else {
@@ -234,23 +233,11 @@ private boolean parseMessage(IoBuffer in, ProtocolDecoderOutput out)
234
233
}
235
234
}
236
235
237
- private int remaining (IoBuffer in ) {
238
- return in .limit () - position ;
239
- }
240
-
241
236
private String getBufferDebugInfo (IoBuffer in ) {
242
237
return "pos=" + in .position () + ",lim=" + in .limit () + ",rem=" + in .remaining ()
243
238
+ ",offset=" + position + ",state=" + state ;
244
239
}
245
240
246
- private byte get (IoBuffer in ) {
247
- return in .get (position ++);
248
- }
249
-
250
- private boolean hasRemaining (IoBuffer in ) {
251
- return position < in .limit ();
252
- }
253
-
254
241
private String getMessageString (IoBuffer buffer ) throws UnsupportedEncodingException {
255
242
byte [] data = new byte [position - buffer .position ()];
256
243
buffer .get (data );
@@ -282,7 +269,8 @@ private boolean isLogon(IoBuffer buffer) {
282
269
return LOGON_PATTERN .find (buffer , buffer .position ()) != -1L ;
283
270
}
284
271
285
- public void finishDecode (IoSession arg0 , ProtocolDecoderOutput arg1 ) throws Exception {
272
+ @ Override
273
+ public void finishDecode (IoSession session , ProtocolDecoderOutput out ) throws Exception {
286
274
// empty
287
275
}
288
276
@@ -309,6 +297,7 @@ public interface MessageListener {
309
297
public List <String > extractMessages (File file ) throws IOException , ProtocolCodecException {
310
298
final List <String > messages = new ArrayList <String >();
311
299
extractMessages (file , new MessageListener () {
300
+ @ Override
312
301
public void onMessage (String message ) {
313
302
messages .add (message );
314
303
}
@@ -331,22 +320,23 @@ public void extractMessages(File file, final MessageListener listener) throws IO
331
320
ProtocolCodecException {
332
321
// Set up a read-only memory-mapped file
333
322
RandomAccessFile fileIn = new RandomAccessFile (file , "r" );
334
- FileChannel readOnlyChannel = fileIn .getChannel ();
335
- MappedByteBuffer memoryMappedBuffer = readOnlyChannel .map (FileChannel .MapMode .READ_ONLY , 0 ,
336
- (int ) readOnlyChannel .size ());
337
-
338
- decode (null , IoBuffer .wrap (memoryMappedBuffer ), new ProtocolDecoderOutput () {
339
-
340
- public void write (Object message ) {
341
- listener .onMessage ((String ) message );
342
- }
343
-
344
- public void flush (IoFilter .NextFilter nextFilter , IoSession ioSession ) {
345
- // ignored
346
- }
347
- });
348
- readOnlyChannel .close ();
349
- fileIn .close ();
323
+ try {
324
+ FileChannel readOnlyChannel = fileIn .getChannel ();
325
+ MappedByteBuffer memoryMappedBuffer = readOnlyChannel .map (FileChannel .MapMode .READ_ONLY , 0 ,
326
+ (int ) readOnlyChannel .size ());
327
+ decode (null , IoBuffer .wrap (memoryMappedBuffer ), new ProtocolDecoderOutput () {
328
+ @ Override
329
+ public void write (Object message ) {
330
+ listener .onMessage ((String ) message );
331
+ }
332
+ @ Override
333
+ public void flush (IoFilter .NextFilter nextFilter , IoSession ioSession ) {
334
+ // ignored
335
+ }
336
+ });
337
+ } finally {
338
+ fileIn .close ();
339
+ }
350
340
}
351
341
352
342
}
0 commit comments