diff --git a/quickfixj-base/src/main/java/quickfix/ExternalDtdDataDictionaryLoader.java b/quickfixj-base/src/main/java/quickfix/ExternalDtdDataDictionaryLoader.java new file mode 100644 index 000000000..8d5c105f2 --- /dev/null +++ b/quickfixj-base/src/main/java/quickfix/ExternalDtdDataDictionaryLoader.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) quickfixengine.org All rights reserved. + * + * This file is part of the QuickFIX FIX Engine + * + * This file may be distributed under the terms of the quickfixengine.org + * license as defined by quickfixengine.org and appearing in the file + * LICENSE included in the packaging of this file. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING + * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * See http://www.quickfixengine.org/LICENSE for licensing information. + * + * Contact ask@quickfixengine.org if any conditions of this licensing + * are not clear to you. + ******************************************************************************/ + +package quickfix; + +import javax.xml.parsers.DocumentBuilderFactory; + +final class ExternalDtdDataDictionaryLoader { + private static final String DEFAULT_CONNECT_TIMEOUT_PROPERTY = "sun.net.client.defaultConnectTimeout"; + private static final String DEFAULT_READ_TIMEOUT_PROPERTY = "sun.net.client.defaultReadTimeout"; + private static final int EXTERNAL_DTD_TIMEOUT_MILLIS = 5000; + private static final int EXTERNAL_DTD_LOAD_RETRIES = 3; + private static final int EXTERNAL_DTD_RETRY_DELAY_MILLIS = 250; + + private ExternalDtdDataDictionaryLoader() { + } + + static DataDictionary load(String location) throws ConfigError { + final String previousConnectTimeout = System.getProperty(DEFAULT_CONNECT_TIMEOUT_PROPERTY); + final String previousReadTimeout = System.getProperty(DEFAULT_READ_TIMEOUT_PROPERTY); + try { + final String timeout = String.valueOf(EXTERNAL_DTD_TIMEOUT_MILLIS); + System.setProperty(DEFAULT_CONNECT_TIMEOUT_PROPERTY, timeout); + System.setProperty(DEFAULT_READ_TIMEOUT_PROPERTY, timeout); + + ConfigError lastError = new ConfigError("Could not parse data dictionary file"); + for (int attempt = 1; attempt <= EXTERNAL_DTD_LOAD_RETRIES; attempt++) { + try { + return new DataDictionary(location, DocumentBuilderFactory::newInstance); + } catch (ConfigError e) { + lastError = e; + if (attempt < EXTERNAL_DTD_LOAD_RETRIES) { + try { + Thread.sleep((1L << (attempt - 1)) * EXTERNAL_DTD_RETRY_DELAY_MILLIS); + } catch (InterruptedException interruptedException) { + Thread.currentThread().interrupt(); + throw new ConfigError("Interrupted while retrying " + location + " load", + interruptedException); + } + } + } + } + throw new ConfigError("Failed to load " + location + " after " + EXTERNAL_DTD_LOAD_RETRIES + + " attempts", lastError); + } finally { + restoreSystemProperty(DEFAULT_CONNECT_TIMEOUT_PROPERTY, previousConnectTimeout); + restoreSystemProperty(DEFAULT_READ_TIMEOUT_PROPERTY, previousReadTimeout); + } + } + + private static void restoreSystemProperty(String key, String value) { + if (value == null) { + System.clearProperty(key); + } else { + System.setProperty(key, value); + } + } +} diff --git a/quickfixj-base/src/test/java/quickfix/DataDictionaryTest.java b/quickfixj-base/src/test/java/quickfix/DataDictionaryTest.java index 3a7e79ade..5281099e5 100644 --- a/quickfixj-base/src/test/java/quickfix/DataDictionaryTest.java +++ b/quickfixj-base/src/test/java/quickfix/DataDictionaryTest.java @@ -30,8 +30,6 @@ import java.net.URLClassLoader; import java.util.Locale; -import javax.xml.parsers.DocumentBuilderFactory; - import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -673,7 +671,7 @@ public void testValidateFieldsOutOfOrderForGroups() throws Exception { @Test public void shouldLoadDictionaryWhenExternalDTDisEnabled() throws ConfigError { - new DataDictionary("FIX_External_DTD.xml", DocumentBuilderFactory::newInstance); + ExternalDtdDataDictionaryLoader.load("FIX_External_DTD.xml"); } @Test diff --git a/quickfixj-core/src/test/java/quickfix/MessageTest.java b/quickfixj-core/src/test/java/quickfix/MessageTest.java index a27508e15..86326d80a 100644 --- a/quickfixj-core/src/test/java/quickfix/MessageTest.java +++ b/quickfixj-core/src/test/java/quickfix/MessageTest.java @@ -35,8 +35,6 @@ import java.time.LocalDateTime; import java.time.ZoneOffset; -import javax.xml.parsers.DocumentBuilderFactory; - import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -143,12 +141,6 @@ * message classes that are generated later in the compile process. */ public class MessageTest { - private static final String DEFAULT_CONNECT_TIMEOUT_PROPERTY = "sun.net.client.defaultConnectTimeout"; - private static final String DEFAULT_READ_TIMEOUT_PROPERTY = "sun.net.client.defaultReadTimeout"; - private static final int EXTERNAL_DTD_TIMEOUT_MILLIS = 5000; - private static final int EXTERNAL_DTD_LOAD_RETRIES = 3; - private static final int EXTERNAL_DTD_RETRY_DELAY_MILLIS = 250; - @Rule public ExpectedException expectedException = ExpectedException.none(); @@ -1270,7 +1262,7 @@ public void testIfMessageHeaderIsOverwritten() { @Test public void shouldConvertToXmlWhenDataDictionaryLoadedWithExternalDTD() throws ConfigError { - DataDictionary dataDictionary = loadDataDictionaryWithExternalDtdRetry(); + DataDictionary dataDictionary = ExternalDtdDataDictionaryLoader.load("FIX_External_DTD.xml"); Message message = new Message(); message.setString(Account.FIELD, "test-account"); @@ -1279,46 +1271,6 @@ public void shouldConvertToXmlWhenDataDictionaryLoadedWithExternalDTD() throws C assertEquals("
", xml); } - private DataDictionary loadDataDictionaryWithExternalDtdRetry() throws ConfigError { - final String previousConnectTimeout = System.getProperty(DEFAULT_CONNECT_TIMEOUT_PROPERTY); - final String previousReadTimeout = System.getProperty(DEFAULT_READ_TIMEOUT_PROPERTY); - try { - final String timeout = String.valueOf(EXTERNAL_DTD_TIMEOUT_MILLIS); - System.setProperty(DEFAULT_CONNECT_TIMEOUT_PROPERTY, timeout); - System.setProperty(DEFAULT_READ_TIMEOUT_PROPERTY, timeout); - - ConfigError lastError = new ConfigError("Could not parse data dictionary file"); - for (int attempt = 1; attempt <= EXTERNAL_DTD_LOAD_RETRIES; attempt++) { - try { - return new DataDictionary("FIX_External_DTD.xml", DocumentBuilderFactory::newInstance); - } catch (ConfigError e) { - lastError = e; - if (attempt < EXTERNAL_DTD_LOAD_RETRIES) { - try { - Thread.sleep((1L << (attempt - 1)) * EXTERNAL_DTD_RETRY_DELAY_MILLIS); - } catch (InterruptedException interruptedException) { - Thread.currentThread().interrupt(); - throw new ConfigError("Interrupted while retrying FIX_External_DTD.xml load", interruptedException); - } - } - } - } - throw new ConfigError("Failed to load FIX_External_DTD.xml after " - + EXTERNAL_DTD_LOAD_RETRIES + " attempts", lastError); - } finally { - restoreSystemProperty(DEFAULT_CONNECT_TIMEOUT_PROPERTY, previousConnectTimeout); - restoreSystemProperty(DEFAULT_READ_TIMEOUT_PROPERTY, previousReadTimeout); - } - } - - private static void restoreSystemProperty(String key, String value) { - if (value == null) { - System.clearProperty(key); - } else { - System.setProperty(key, value); - } - } - @Test public void shouldConvertToXMLWithoutIndent() { Message message = new Message();