Skip to content

Commit e414807

Browse files
committed
Merge pull request #651 from the-thing/650/truncated_filestore_messages
`FileStore` message length fix (cherry picked from commit e050d3d)
1 parent 312f054 commit e414807

File tree

10 files changed

+110
-54
lines changed

10 files changed

+110
-54
lines changed

quickfixj-core/src/main/java/org/quickfixj/CharsetSupport.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ public static void setCharset(String charset) throws UnsupportedEncodingExceptio
6464
CharsetSupport.isStringEquivalent = isStringEquivalent(charsetInstance);
6565
}
6666

67+
public static void setDefaultCharset() throws UnsupportedEncodingException {
68+
setCharset(getDefaultCharset());
69+
}
70+
6771
public static String getCharset() {
6872
return charset;
6973
}

quickfixj-core/src/main/java/quickfix/CachedFileStore.java

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.io.BufferedOutputStream;
2929
import java.io.DataInputStream;
3030
import java.io.DataOutputStream;
31+
import java.io.EOFException;
3132
import java.io.File;
3233
import java.io.FileInputStream;
3334
import java.io.FileOutputStream;
@@ -86,8 +87,6 @@ public class CachedFileStore implements MessageStore {
8687

8788
private FileOutputStream headerFileOutputStream;
8889

89-
private final String charsetEncoding = CharsetSupport.getCharset();
90-
9190
CachedFileStore(String path, SessionID sessionID, boolean syncWrites) throws IOException {
9291
this.syncWrites = syncWrites;
9392

@@ -308,16 +307,15 @@ public boolean get(int sequence, String message) {
308307
throw new UnsupportedOperationException("not supported");
309308
}
310309

311-
private String read(long offset, long size) throws IOException {
312-
final byte[] data = new byte[(int) size];
313-
314-
messageFileReader.seek(offset);
315-
if (messageFileReader.read(data) != size) {
316-
throw new IOException("Truncated input while reading message: "
317-
+ new String(data, charsetEncoding));
310+
private String read(long offset, int size) throws IOException {
311+
try {
312+
final byte[] data = new byte[size];
313+
messageFileReader.seek(offset);
314+
messageFileReader.readFully(data);
315+
return new String(data, CharsetSupport.getCharset());
316+
} catch (EOFException eofe) { // can't read fully
317+
throw new IOException("Truncated input while reading message: offset=" + offset + ", expected size=" + size, eofe);
318318
}
319-
320-
return new String(data, charsetEncoding);
321319
}
322320

323321
private Collection<String> getMessage(long startSequence, long endSequence) throws IOException {
@@ -326,7 +324,7 @@ private Collection<String> getMessage(long startSequence, long endSequence) thro
326324
final List<long[]> offsetAndSizes = messageIndex.get(startSequence, endSequence);
327325
for (final long[] offsetAndSize : offsetAndSizes) {
328326
if (offsetAndSize != null) {
329-
final String message = read(offsetAndSize[0], offsetAndSize[1]);
327+
final String message = read(offsetAndSize[0], (int) offsetAndSize[1]);
330328
messages.add(message);
331329
}
332330
}
@@ -341,7 +339,8 @@ private Collection<String> getMessage(long startSequence, long endSequence) thro
341339
*/
342340
public boolean set(int sequence, String message) throws IOException {
343341
final long offset = messageFileWriter.getFilePointer();
344-
final int size = message.length();
342+
final byte[] messageBytes = message.getBytes(CharsetSupport.getCharset());
343+
final int size = messageBytes.length;
345344
messageIndex.put((long) sequence, new long[] { offset, size });
346345
headerDataOutputStream.writeInt(sequence);
347346
headerDataOutputStream.writeLong(offset);
@@ -350,7 +349,7 @@ public boolean set(int sequence, String message) throws IOException {
350349
if (syncWrites) {
351350
headerFileOutputStream.getFD().sync();
352351
}
353-
messageFileWriter.write(message.getBytes(CharsetSupport.getCharset()));
352+
messageFileWriter.write(messageBytes);
354353
return true;
355354
}
356355

quickfixj-core/src/main/java/quickfix/FileStore.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ public class FileStore implements MessageStore, Closeable {
6363
private final String sessionFileName;
6464
private final boolean syncWrites;
6565
private final int maxCachedMsgs;
66-
private final String charsetEncoding = CharsetSupport.getCharset();
6766
private RandomAccessFile messageFileReader;
6867
private RandomAccessFile messageFileWriter;
6968
private DataOutputStream headerDataOutputStream;
@@ -350,7 +349,7 @@ private String getMessage(long offset, int size, int i) throws IOException {
350349
final byte[] data = new byte[size];
351350
messageFileReader.seek(offset);
352351
messageFileReader.readFully(data);
353-
return new String(data, charsetEncoding);
352+
return new String(data, CharsetSupport.getCharset());
354353
} catch (EOFException eofe) { // can't read fully
355354
throw new IOException("Truncated input while reading message: messageIndex=" + i
356355
+ ", offset=" + offset + ", expected size=" + size, eofe);
@@ -363,7 +362,8 @@ private String getMessage(long offset, int size, int i) throws IOException {
363362
@Override
364363
public boolean set(int sequence, String message) throws IOException {
365364
final long offset = messageFileWriter.getFilePointer();
366-
final int size = message.length();
365+
final byte[] messageBytes = message.getBytes(CharsetSupport.getCharset());
366+
final int size = messageBytes.length;
367367
if (messageIndex != null) {
368368
updateMessageIndex(sequence, offset, size);
369369
}
@@ -374,7 +374,7 @@ public boolean set(int sequence, String message) throws IOException {
374374
if (syncWrites) {
375375
headerFileOutputStream.getFD().sync();
376376
}
377-
messageFileWriter.write(message.getBytes(CharsetSupport.getCharset()));
377+
messageFileWriter.write(messageBytes);
378378
return true;
379379
}
380380

quickfixj-core/src/test/java/quickfix/AbstractMessageStoreTest.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@
2020
package quickfix;
2121

2222
import junit.framework.TestCase;
23+
import org.quickfixj.CharsetSupport;
2324

2425
import java.io.IOException;
2526
import java.util.ArrayList;
27+
import java.util.List;
2628

2729
public abstract class AbstractMessageStoreTest extends TestCase {
30+
2831
private SessionID sessionID;
2932
private MessageStore store;
3033

@@ -167,6 +170,44 @@ public void testRefreshMessageStore() throws Exception {
167170
}
168171
}
169172

173+
public void testSetAndGetMessageWithAsciiCharacters() throws IOException {
174+
MessageStore underTest = getStore();
175+
176+
if (underTest instanceof SleepycatStore) {
177+
return;
178+
}
179+
180+
underTest.set(1, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVXYZ0123456789");
181+
182+
List<String> messages = new ArrayList<>();
183+
underTest.get(1, 1, messages);
184+
185+
assertEquals(1, messages.size());
186+
assertEquals("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVXYZ0123456789", messages.get(0));
187+
}
188+
189+
public void testSetAndGetMessageWithUnicodeCharacters() throws IOException {
190+
MessageStore underTest = getStore();
191+
192+
if (underTest instanceof SleepycatStore) {
193+
return;
194+
}
195+
196+
CharsetSupport.setCharset("UTF-8");
197+
198+
try {
199+
underTest.set(1, "a \u00A9 \u2603 \uD834\uDF06");
200+
201+
List<String> messages = new ArrayList<>();
202+
underTest.get(1, 1, messages);
203+
204+
assertEquals(1, messages.size());
205+
assertEquals("a \u00A9 \u2603 \uD834\uDF06", messages.get(0));
206+
} finally {
207+
CharsetSupport.setDefaultCharset();
208+
}
209+
}
210+
170211
protected void closeMessageStore(MessageStore store) throws IOException {
171212
// does nothing, by default
172213
}

quickfixj-core/src/test/java/quickfix/FieldTest.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@
1919

2020
package quickfix;
2121

22+
import java.io.UnsupportedEncodingException;
23+
import java.math.BigDecimal;
24+
import java.time.LocalDate;
25+
import java.time.LocalDateTime;
26+
import java.time.LocalTime;
27+
import java.util.Arrays;
28+
import java.util.Date;
29+
2230
import org.junit.Test;
2331
import org.quickfixj.CharsetSupport;
2432
import quickfix.field.ClOrdID;
@@ -32,14 +40,6 @@
3240
import quickfix.fix50.MarketDataIncrementalRefresh;
3341
import quickfix.fix50.NewOrderSingle;
3442

35-
import java.io.UnsupportedEncodingException;
36-
import java.math.BigDecimal;
37-
import java.time.LocalDate;
38-
import java.time.LocalDateTime;
39-
import java.time.LocalTime;
40-
import java.util.Arrays;
41-
import java.util.Date;
42-
4343
import static org.junit.Assert.assertEquals;
4444
import static org.junit.Assert.assertFalse;
4545
import static org.junit.Assert.assertTrue;
@@ -89,7 +89,7 @@ public void testFieldCalculationsWithUTF8Charset() throws UnsupportedEncodingExc
8989
try {
9090
testFieldCalcuations("\u6D4B\u9A8C\u6570\u636E", 50, 16);
9191
} finally {
92-
CharsetSupport.setCharset(CharsetSupport.getDefaultCharset());
92+
CharsetSupport.setDefaultCharset();
9393
}
9494
}
9595

quickfixj-core/src/test/java/quickfix/FileStoreTest.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,18 @@
1919

2020
package quickfix;
2121

22+
import org.quickfixj.CharsetSupport;
23+
2224
import java.io.IOException;
2325
import java.util.ArrayList;
2426
import java.util.Date;
2527
import java.util.List;
2628

2729
public class FileStoreTest extends AbstractMessageStoreTest {
2830

29-
protected void tearDown() throws Exception {
31+
public void tearDown() throws Exception {
3032
super.tearDown();
33+
CharsetSupport.setDefaultCharset();
3134
FileStore fileStore = (FileStore) getStore();
3235
try {
3336
fileStore.closeAndDeleteFiles();
@@ -36,6 +39,7 @@ protected void tearDown() throws Exception {
3639
}
3740
}
3841

42+
@Override
3943
protected MessageStoreFactory getMessageStoreFactory() throws ConfigError, FieldConvertError {
4044
SessionSettings settings = new SessionSettings(getConfigurationFileName());
4145
// Initialize the session settings from the defaults
@@ -44,6 +48,7 @@ protected MessageStoreFactory getMessageStoreFactory() throws ConfigError, Field
4448
return new FileStoreFactory(settings);
4549
}
4650

51+
@Override
4752
protected Class<?> getMessageStoreClass() {
4853
return FileStore.class;
4954
}

quickfixj-core/src/test/java/quickfix/MessageTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ private void doTestMessageWithEncodedField(String charset, String text) throws E
316316
final Message msg = new Message(order.toString(), DataDictionaryTest.getDictionary());
317317
assertEquals(charset + " encoded field", text, msg.getString(EncodedText.FIELD));
318318
} finally {
319-
CharsetSupport.setCharset(CharsetSupport.getDefaultCharset());
319+
CharsetSupport.setDefaultCharset();
320320
}
321321
}
322322

quickfixj-core/src/test/java/quickfix/SleepycatStoreTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
import java.io.IOException;
2424

2525
public class SleepycatStoreTest extends AbstractMessageStoreTest {
26-
protected MessageStoreFactory getMessageStoreFactory() throws ConfigError, FieldConvertError {
26+
27+
protected MessageStoreFactory getMessageStoreFactory() throws ConfigError {
2728
SessionSettings settings = new SessionSettings(getConfigurationFileName());
2829
File tmpfile;
2930
try {
@@ -62,5 +63,4 @@ public void testCloseAndOpen() throws Exception {
6263
assertEquals(123, store.getNextSenderMsgSeqNum());
6364
assertEquals(321, store.getNextTargetMsgSeqNum());
6465
}
65-
6666
}

quickfixj-core/src/test/java/quickfix/mina/message/FIXMessageDecoderTest.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,24 +55,21 @@ public class FIXMessageDecoderTest {
5555

5656
@Before
5757
public void setUp() throws Exception {
58+
CharsetSupport.setDefaultCharset();
5859
decoder = new FIXMessageDecoder();
5960
buffer = IoBuffer.allocate(8192);
6061
decoderOutput = new ProtocolDecoderOutputForTest();
6162
}
6263

6364
@After
6465
public void tearDown() throws Exception {
66+
CharsetSupport.setDefaultCharset();
6567
buffer.clear();
6668
}
6769

68-
@Test
70+
@Test(expected = UnsupportedEncodingException.class)
6971
public void testInvalidStringCharset() throws Exception {
70-
try {
71-
decoder = new FIXMessageDecoder("BOGUS");
72-
fail("no exception thrown");
73-
} catch (UnsupportedEncodingException e) {
74-
// expected
75-
}
72+
decoder = new FIXMessageDecoder("BOGUS");
7673
}
7774

7875
@Test
@@ -104,8 +101,6 @@ public void testWesternEuropeanDecoding() throws Exception {
104101
doWesternEuropeanDecodingTest();
105102
} catch (InvalidMessage e) {
106103
// expected
107-
} finally {
108-
CharsetSupport.setCharset(CharsetSupport.getDefaultCharset());
109104
}
110105
}
111106

0 commit comments

Comments
 (0)