Index: /Users/orenmnero/Development/quickfixj/src/quickfix/FieldMap.java =================================================================== --- /Users/orenmnero/Development/quickfixj/src/quickfix/FieldMap.java (revision 416) +++ /Users/orenmnero/Development/quickfixj/src/quickfix/FieldMap.java (working copy) @@ -71,6 +71,10 @@ groups.clear(); } + public boolean isEmpty() { + return fields.size() == 0; + } + private class FieldOrderComparator implements Comparator, Serializable { static final long serialVersionUID = 3416006398018829270L; Index: /Users/orenmnero/Development/quickfixj/src/quickfix/Message.java =================================================================== --- /Users/orenmnero/Development/quickfixj/src/quickfix/Message.java (revision 416) +++ /Users/orenmnero/Development/quickfixj/src/quickfix/Message.java (working copy) @@ -305,6 +305,16 @@ return !isAdmin(); } + public boolean isEmpty() { + return super.isEmpty() && header.isEmpty() && trailer.isEmpty(); + } + + public void clear() { + super.clear(); + header.clear(); + trailer.clear(); + } + public class Header extends FieldMap { static final long serialVersionUID = -3193357271891865972L; @@ -380,6 +390,10 @@ parseHeader(dd); parseBody(dd); parseTrailer(dd); + + if( isEmpty() ) { + throw new InvalidMessage( "Message contains no fields" ); + } } catch (InvalidMessage e) { isValidStructure = false; throw e; @@ -409,24 +423,30 @@ private void parseHeader(DataDictionary dd) throws InvalidMessage { boolean invalidHeaderFieldOrder = false; + StringField beginString = extractField(dd); - if (beginString.getField() != BeginString.FIELD) { + if (beginString == null || beginString.getField() != BeginString.FIELD) { invalidHeaderFieldOrder = true; + } else { + header.setField(beginString); } StringField bodyLength = extractField(dd); - if (bodyLength.getField() != BodyLength.FIELD) { + if (bodyLength == null || bodyLength.getField() != BodyLength.FIELD) { invalidHeaderFieldOrder = true; + } else { + header.setField( bodyLength ); } StringField msgType = extractField(dd); - if (msgType.getField() != MsgType.FIELD) { + if (msgType == null || msgType.getField() != MsgType.FIELD) { invalidHeaderFieldOrder = true; + } else { + header.setField( msgType ); } + if (doValidation && invalidHeaderFieldOrder) { throw new InvalidMessage("Header fields out of order"); } - header.setField(beginString); - header.setField(bodyLength); - header.setField(msgType); + StringField field = extractField(dd); while (field != null && isHeaderField(field, dd)) { header.setField(field); Index: /Users/orenmnero/Development/quickfixj/test/quickfix/MessageTest.java =================================================================== --- /Users/orenmnero/Development/quickfixj/test/quickfix/MessageTest.java (revision 416) +++ /Users/orenmnero/Development/quickfixj/test/quickfix/MessageTest.java (working copy) @@ -287,6 +287,27 @@ assertEquals("wrong value", "CAD", valueMessageType.getString(UnderlyingCurrency.FIELD)); } + public void testParseEmptyString() throws Exception { + String data = ""; + + // with validation + try { + Message message = new Message(data, DataDictionaryTest.getDictionary()); + } catch( NullPointerException npe ) { + fail("InvalidMessage expected, got NullPointerException" ); + } catch( InvalidMessage im ) { + } + + // without validation + try { + Message message = new Message(data, DataDictionaryTest.getDictionary(), false); + } catch( NullPointerException npe ) { + fail("InvalidMessage expected, got NullPointerException" ); + } catch( InvalidMessage im ) { + } + + } + private void assertHeaderField(Message message, String expectedValue, int field) throws FieldNotFound { assertEquals(expectedValue, message.getHeader().getString(field)); @@ -473,6 +494,23 @@ return numAllocs; } + public void testIsEmpty() { + Message message = new Message(); + assertTrue("Message should be empty on construction", message.isEmpty()); + message.getHeader().setField(new BeginString("FIX.4.2")); + assertFalse("Header should contain a field", message.isEmpty()); + message.clear(); + assertTrue("Message should be empty after clear", message.isEmpty()); + message.setField(new Symbol("MSFT")); + assertFalse("Body should contain a field", message.isEmpty()); + message.clear(); + assertTrue("Message should be empty after clear", message.isEmpty()); + message.getTrailer().setField(new CheckSum("10")); + assertFalse("Trailer should contain a field", message.isEmpty()); + message.clear(); + assertTrue("Message should be empty after clear", message.isEmpty()); + } + public void testMessageSetGetString() { Message message = new Message();