Skip to content

Commit

Permalink
feat: support for use through jvm -javaagent command line option (#289)
Browse files Browse the repository at this point in the history
  • Loading branch information
jkorri authored Sep 9, 2024
1 parent 72c8073 commit db7a179
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 9 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,23 @@ $ dcm -p 12345 getNegativePolicy
$ dcm -p 12345 setNegativePolicy 0
```

### Load Cache Entries from File

```bash
$ dcm -p 12345 load /foo/bar/my-cache.properties
```

### Manipulate cache with a command line option at JVM startup

To manipulate dns entries at jvm startup, add the following jvm-options:

```bash
# Set individual entry
java -javaagent:<path to jar>="set foo.com 1.1.1.1" --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/sun.net=ALL-UNNAMED ...
# Load entries from file
java -javaagent:<path to jar>="load my-cache.properties" --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/sun.net=ALL-UNNAMED ...
```

## 📚 Related information

* [Java Agent Specification](http://docs.oracle.com/javase/7/docs/api/java/lang/instrument/package-summary.html)
Expand Down
1 change: 1 addition & 0 deletions library/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
<configuration>
<archive>
<manifestEntries>
<Premain-Class>com.alibaba.dcm.agent.DcmAgent</Premain-Class>
<Agent-Class>com.alibaba.dcm.agent.DcmAgent</Agent-Class>
<Can-Redefine-Classes>false</Can-Redefine-Classes>
<Can-Retransform-Classes>false</Can-Retransform-Classes>
Expand Down
22 changes: 22 additions & 0 deletions library/src/main/java/com/alibaba/dcm/DnsCacheManipulator.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
Expand Down Expand Up @@ -144,6 +145,27 @@ public static void loadDnsCacheConfig(String propertiesFileName) {
}
}

/**
* Load dns config from the specified properties file in filesystem, then set dns cache.
*
* @param propertiesFileName specified properties file name in filesystem.
* @throws DnsCacheManipulatorException Operation fail
* @see DnsCacheManipulator#setDnsCache(java.util.Properties)
*/
public static void loadDnsCacheConfigFromFileSystem(String propertiesFileName) {
try {
InputStream inputStream = new FileInputStream(propertiesFileName);
Properties properties = new Properties();
properties.load(inputStream);
inputStream.close();
setDnsCache(properties);
} catch (Exception e) {
final String message = String.format("Fail to loadDnsCacheConfig from %s, cause: %s",
propertiesFileName, e);
throw new DnsCacheManipulatorException(message, e);
}
}

/**
* Get a dns cache entry by {@code host}.
*
Expand Down
11 changes: 10 additions & 1 deletion library/src/main/java/com/alibaba/dcm/agent/DcmAgent.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,14 @@ public class DcmAgent {
static final String DCM_AGENT_SUCCESS_MARK_LINE = "!!DCM SUCCESS!!";

/**
* Entrance method of DCM Java Agent.
* Entrance method of DCM Java Agent when used through a jvm command line option.
*/
public static void premain(@Nonnull String agentArgument) throws Exception {
agentmain(agentArgument);
}

/**
* Entrance method of DCM Java Agent when connecting to a running jvm.
*/
@SuppressFBWarnings("THROWS_METHOD_THROWS_CLAUSE_BASIC_EXCEPTION")
public static void agentmain(@Nonnull String agentArgument) throws Exception {
Expand Down Expand Up @@ -264,6 +271,8 @@ private static synchronized void initAction2Method() throws NoSuchMethodExceptio
map.put("ls", DnsCacheManipulator.class.getMethod("getWholeDnsCache"));
map.put("clear", DnsCacheManipulator.class.getMethod("clearDnsCache"));

map.put("load", DnsCacheManipulator.class.getMethod("loadDnsCacheConfigFromFileSystem", String.class));

map.put("setPolicy", DnsCacheManipulator.class.getMethod("setDnsCachePolicy", int.class));
map.put("getPolicy", DnsCacheManipulator.class.getMethod("getDnsCachePolicy"));
map.put("setNegativePolicy", DnsCacheManipulator.class.getMethod("setDnsNegativeCachePolicy", int.class));
Expand Down
34 changes: 26 additions & 8 deletions library/src/test/java/com/alibaba/dcm/DnsCacheManipulatorTests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@ package com.alibaba.dcm
import com.alibaba.dcm.internal.InetAddressCacheUtilCommons.isNewInetAddressImpl
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.AnnotationSpec
import io.kotest.matchers.collections.shouldBeEmpty
import io.kotest.matchers.collections.shouldContainExactly
import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder
import io.kotest.matchers.collections.shouldHaveSize
import io.kotest.matchers.collections.*
import io.kotest.matchers.longs.shouldBeBetween
import io.kotest.matchers.nulls.shouldBeNull
import io.kotest.matchers.shouldBe
import io.kotest.matchers.types.shouldNotBeSameInstanceAs

import kotlin.io.path.writeText

private const val IP1 = "42.42.42.1"
private const val IP2 = "42.42.42.2"
Expand Down Expand Up @@ -276,13 +273,13 @@ class DnsCacheManipulatorTests : AnnotationSpec() {
}

@Test
fun test_loadDnsCacheConfig_fromMyConfig() {
fun test_loadDnsCacheConfig_fromMyConfigClassPath() {
DnsCacheManipulator.loadDnsCacheConfig("my-dns-cache.properties")
"www.hello2.com".lookupIpByName() shouldBe IP2
}

@Test
fun test_multi_ips_in_config_file() {
fun test_multi_ips_in_config_file_classpath() {
DnsCacheManipulator.loadDnsCacheConfig("dns-cache-multi-ips.properties")

val host = "www.hello-multi-ips.com"
Expand All @@ -299,11 +296,32 @@ class DnsCacheManipulatorTests : AnnotationSpec() {
}

@Test
fun test_configNotFound() {
fun test_configNotFound_classpath() {
val ex = shouldThrow<DnsCacheManipulatorException> {
DnsCacheManipulator.loadDnsCacheConfig("not-existed.properties")
}

ex.message shouldBe "Fail to find not-existed.properties on classpath!"
}

@Test
fun test_loadDnsCacheConfig_fromMyConfigFileSystem() {
val tempFile = kotlin.io.path.createTempFile("dns-cache-test", ".properties")
tempFile.writeText("www.hello2.com $IP2")
tempFile.toFile().deleteOnExit()

DnsCacheManipulator.loadDnsCacheConfigFromFileSystem(tempFile.toAbsolutePath().toString())
"www.hello2.com".lookupIpByName() shouldBe IP2
}

@Test
fun test_configNotFound_fileSystem() {
val ex = shouldThrow<DnsCacheManipulatorException> {
DnsCacheManipulator.loadDnsCacheConfigFromFileSystem("not-existed.properties")
}

ex.message shouldBeIn arrayOf(
"Fail to loadDnsCacheConfig from not-existed.properties, cause: java.io.FileNotFoundException: not-existed.properties (No such file or directory)",
"Fail to loadDnsCacheConfig from not-existed.properties, cause: java.io.FileNotFoundException: not-existed.properties (The system cannot find the file specified)")
}
}

0 comments on commit db7a179

Please sign in to comment.