diff --git a/src/main/java/de/rpr/ddnsclient/AppConfig.java b/src/main/java/de/rpr/ddnsclient/AppConfig.java index 8d905b9..0fd4877 100644 --- a/src/main/java/de/rpr/ddnsclient/AppConfig.java +++ b/src/main/java/de/rpr/ddnsclient/AppConfig.java @@ -4,9 +4,16 @@ import com.fasterxml.jackson.databind.ObjectMapper; import de.rpr.ddnsclient.model.Config; import jakarta.enterprise.context.ApplicationScoped; import jakarta.ws.rs.Produces; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import javax.naming.Context; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; import java.io.File; import java.io.IOException; +import java.text.MessageFormat; +import java.util.Properties; public class AppConfig { @@ -17,4 +24,14 @@ public class AppConfig { return objectMapper.readValue(configFile, Config.class); } + @Produces + @ApplicationScoped + public DirContext dirContext( + @ConfigProperty(name = "ddnsclient.dns.resolver", defaultValue = "9.9.9.9") String dnsServer) + throws NamingException { + Properties env = new Properties(); + env.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory"); + env.setProperty(Context.PROVIDER_URL, MessageFormat.format("dns://{0}", dnsServer)); + return new InitialDirContext(env); + } } diff --git a/src/main/java/de/rpr/ddnsclient/lookup/DnsResolver.java b/src/main/java/de/rpr/ddnsclient/lookup/DnsResolver.java index 5cfb2db..29da784 100644 --- a/src/main/java/de/rpr/ddnsclient/lookup/DnsResolver.java +++ b/src/main/java/de/rpr/ddnsclient/lookup/DnsResolver.java @@ -1,19 +1,13 @@ package de.rpr.ddnsclient.lookup; -import de.rpr.ddnsclient.dyndns.Ddnss; import de.rpr.ddnsclient.model.IPs; import jakarta.enterprise.context.ApplicationScoped; -import org.eclipse.microprofile.config.inject.ConfigProperty; import org.jboss.logging.Logger; -import javax.naming.Context; import javax.naming.NamingException; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; -import javax.naming.directory.InitialDirContext; -import java.text.MessageFormat; -import java.util.Properties; @ApplicationScoped public class DnsResolver { @@ -21,11 +15,10 @@ public class DnsResolver { private static final Logger log = Logger.getLogger(DnsResolver.class); public static final int MAX_RETRIES = 5; - private final Properties env = new Properties(); + private final DirContext dirContext; - public DnsResolver(@ConfigProperty(name = "ddnsclient.dns.resolver", defaultValue = "9.9.9.9") String dnsServer) { - env.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory"); - env.setProperty(Context.PROVIDER_URL, MessageFormat.format("dns://{0}", dnsServer)); + DnsResolver(DirContext dirContext) { + this.dirContext = dirContext; } public IPs resolve(String hostname) { @@ -34,16 +27,15 @@ public class DnsResolver { int resolveCounter = 0; try { - DirContext context = new InitialDirContext((env)); Attributes result; do { if (resolveCounter == MAX_RETRIES) { - throw new RuntimeException("Couldn't resolve " + hostname); + throw new IllegalStateException("Couldn't resolve all attributes"); } resolveCounter++; log.tracef("Try #%d", resolveCounter); - result = context.getAttributes(hostname, new String[]{"A", "AAAA"}); + result = dirContext.getAttributes(hostname, new String[]{"A", "AAAA"}); } while (result.size() != 2); return new IPs( diff --git a/src/test/java/de/rpr/ddnsclient/lookup/DnsResolverTest.java b/src/test/java/de/rpr/ddnsclient/lookup/DnsResolverTest.java new file mode 100644 index 0000000..5d5e5d3 --- /dev/null +++ b/src/test/java/de/rpr/ddnsclient/lookup/DnsResolverTest.java @@ -0,0 +1,53 @@ +package de.rpr.ddnsclient.lookup; + +import de.rpr.ddnsclient.model.IPs; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import javax.naming.NamingException; +import javax.naming.directory.BasicAttributes; +import javax.naming.directory.DirContext; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class DnsResolverTest { + + @Mock + DirContext dirContext; + + @Test + void should_throw_exception_if_resolving_failes_repeatedly() throws NamingException { + + when(dirContext.getAttributes(anyString(), any())).thenReturn(new BasicAttributes()); + + DnsResolver dnsResolver = new DnsResolver(dirContext); + + assertThatExceptionOfType(IllegalStateException.class) + .isThrownBy(() -> dnsResolver.resolve("example.com")); + } + + @Test + void should_return_ips() throws NamingException { + + BasicAttributes attributes = new BasicAttributes() {{ + put("A", "ipv4"); + put("AAAA", "ipv6"); + }}; + when(dirContext.getAttributes(anyString(), any())).thenReturn(attributes); + + DnsResolver dnsResolver = new DnsResolver(dirContext); + + IPs result = dnsResolver.resolve("example.com"); + + assertThat(result.v4()).isEqualTo("ipv4"); + assertThat(result.v6()).isEqualTo("ipv6"); + + } +} \ No newline at end of file