Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions communication/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dependencies {
implementation(project(":remote-config:remote-config-core"))
implementation(project(":internal-api"))
implementation(project(":utils:container-utils"))
implementation(project(":utils:filesystem-utils"))
implementation(project(":utils:socket-utils"))
implementation(project(":utils:version-utils"))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.timgroup.statsd.NoOpDirectStatsDClient;
import com.timgroup.statsd.NonBlockingStatsDClientBuilder;
import com.timgroup.statsd.StatsDClientErrorHandler;
import datadog.common.filesystem.Files;
import datadog.environment.OperatingSystem;
import datadog.trace.api.Config;
import datadog.trace.relocate.api.IOLogger;
Expand Down Expand Up @@ -186,7 +187,7 @@ private void discoverConnectionSettings() {
}

if (null == host) {
if (!OperatingSystem.isWindows() && new File(DEFAULT_DOGSTATSD_SOCKET_PATH).exists()) {
if (!OperatingSystem.isWindows() && Files.exists(new File(DEFAULT_DOGSTATSD_SOCKET_PATH))) {
log.info("Detected {}. Using it to send StatsD data.", DEFAULT_DOGSTATSD_SOCKET_PATH);
host = DEFAULT_DOGSTATSD_SOCKET_PATH;
port = 0; // tells dogstatsd client to treat host as a socket path
Expand Down
1 change: 1 addition & 0 deletions gradle/dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ final class CachedData {
exclude(project(':telemetry'))
exclude(project(':utils:config-utils'))
exclude(project(':utils:container-utils'))
exclude(project(':utils:filesystem-utils'))
exclude(project(':utils:socket-utils'))
exclude(project(':utils:time-utils'))
exclude(project(':utils:version-utils'))
Expand Down
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ include(
":dd-java-agent:testing",
":utils:config-utils",
":utils:container-utils",
":utils:filesystem-utils",
":utils:flare-utils",
":utils:socket-utils",
":utils:test-agent-utils:decoder",
Expand Down
1 change: 1 addition & 0 deletions utils/config-utils/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ dependencies {
implementation(project(":components:environment"))
implementation(project(":components:yaml"))
implementation(project(":dd-trace-api"))
implementation(project(":utils:filesystem-utils"))
implementation(libs.slf4j)

testImplementation(project(":utils:test-utils"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static datadog.trace.util.ConfigStrings.propertyNameToEnvironmentVariableName;

import datadog.common.filesystem.Files;
import datadog.trace.api.ConfigOrigin;
import datadog.trace.bootstrap.config.provider.stableconfig.StableConfigMappingException;
import java.io.File;
Expand Down Expand Up @@ -33,7 +34,7 @@ public final class StableConfigSource extends ConfigProvider.Source {
try {
File file = new File(filePath);
log.debug("Stable configuration file found at path: {}", file);
if (file.exists()) {
if (Files.exists(file)) {
cfg = StableConfigParser.parse(filePath);
}
} catch (Throwable e) {
Expand Down
9 changes: 9 additions & 0 deletions utils/filesystem-utils/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
plugins {
`java-library`
}

apply(from = "$rootDir/gradle/java.gradle")

dependencies {
testImplementation(project(":utils:test-utils"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package datadog.common.filesystem;

import java.io.File;
import javax.annotation.Nonnull;

/** Utility methods related to file operations. */
public class Files {

private Files() {
// Prevent instantiation
}

/**
* Determines whether the given file exists on the filesystem.
*
* <p>This method wraps {@link File#exists()} and safely handles {@link SecurityException}s that
* may occur if the caller does not have the required permissions to examine the file. In such
* cases, this method returns {@code false}.
*
* @param file the file to check for existence; must not be {@code null}
* @return {@code true} if the file exists and can be queried, {@code false} otherwise
*/
public static boolean exists(@Nonnull File file) {
try {
return file.exists();
} catch (SecurityException ignored) {
return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package datadog.common.filesystem


import datadog.environment.JavaVirtualMachine
import datadog.trace.test.util.DDSpecification
import java.security.Permission
import spock.lang.IgnoreIf

class FilesTest extends DDSpecification {
def "exists returns true when file exists and is accessible"() {
given:
def file = File.createTempFile("test", "txt")
file.deleteOnExit()

expect:
Files.exists(file)
}

def "exists returns false when file does not exist"() {
given:
// Create a temp file and delete it to ensure path is valid but file is gone
def file = File.createTempFile("missing", "txt")
file.delete()

expect:
!Files.exists(file)
}

@IgnoreIf({
JavaVirtualMachine.isJavaVersionAtLeast(18)
})
def "exists returns false when SecurityManager forbids file access"() {
setup:
def file = File.createTempFile("test", "txt")
file.deleteOnExit()

// install a restrictive security manager
def originalSM = System.getSecurityManager()
System.setSecurityManager(new SecurityManager() {
@Override
void checkRead(String filePath) {
// Only deny THIS file otherwise we'll deny classloading as well and will result in a StackOverflowError
if (filePath == file.absolutePath) {
throw new SecurityException("Access denied")
}
}

@Override
void checkPermission(Permission perm) {
// allow anything
}

@Override
void checkPermission(Permission perm, Object context) {
// allow anything
}
})

when:
def result = Files.exists(file)

then:
!result

cleanup:
System.setSecurityManager(originalSM)
}
}
1 change: 1 addition & 0 deletions utils/socket-utils/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ extensions.getByName("tracerJava").withGroovyBuilder {
dependencies {
implementation(libs.slf4j)
implementation(project(":internal-api"))
implementation(project(":utils:filesystem-utils"))
implementation(libs.jnr.unixsocket)
testImplementation(files(sourceSets["main_java17"].output))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_AGENT_SOCKET_PATH;

import datadog.common.filesystem.Files;
import datadog.environment.OperatingSystem;
import datadog.environment.SystemProperties;
import datadog.trace.api.Config;
Expand All @@ -20,7 +21,7 @@ public static String discoverApmSocket(final Config config) {
if (!OperatingSystem.isWindows()) {
if (unixDomainSocket == null
&& Config.get().isAgentConfiguredUsingDefault()
&& new File(DEFAULT_TRACE_AGENT_SOCKET_PATH).exists()) {
&& Files.exists(new File(DEFAULT_TRACE_AGENT_SOCKET_PATH))) {
log.info("Detected {}. Using it to send trace data.", DEFAULT_TRACE_AGENT_SOCKET_PATH);
unixDomainSocket = DEFAULT_TRACE_AGENT_SOCKET_PATH;
}
Expand Down