platform/eel/docs/EelApi_NIO_Integration.md
This document explains how the Eel API integrates with Java's NIO file system and how it enables working with files in remote environments using standard Java APIs.
The Eel API provides seamless integration with Java's NIO file system, allowing you to work with files in different environments (local, WSL, Docker, etc.) using standard Java APIs. This integration is achieved through several components:
EelPathUtils is a utility class that provides methods for working with paths in the Eel API. It helps bridge the gap between local and remote file systems by providing methods that work consistently across different environments.
Note: The utility class contains some obsolete methods like isPathLocal() and isProjectLocal() that expose implementation details and encourage machine-dependent code. These methods are not documented here as they should not be used in new code. The Eel API is designed to work uniformly across all environments.
fun expandUserHome(eelDescriptor: EelDescriptor, path: String): Path
Expands the user home directory in paths, replacing "~" with the actual home directory path for the given EelDescriptor. This is useful for handling paths that use the tilde shorthand for the user's home directory.
Example:
// Expand a path with the user's home directory
val fullPath = EelPathUtils.expandUserHome(descriptor, "~/projects/myproject")
// If descriptor is WSL Ubuntu and home is /home/john:
// Result: \\wsl.localhost\Ubuntu\home\john\projects\myproject
The method correctly handles different forms:
~ → user's home directory~/path → home directory + path~\path → home directory + path (Windows-style)fun createTemporaryFile(
project: Project?,
prefix: String = "",
suffix: String = "",
deleteOnExit: Boolean = true
): Path
Creates a temporary file in the appropriate environment based on the project. If the project is null or local, it creates a local temporary file. Otherwise, it creates a temporary file in the project's Eel environment.
Example:
// Create a temporary file for a Git commit message
val messageFile = EelPathUtils.createTemporaryFile(project, "git-commit-", ".msg", true)
// For a WSL project: creates file in WSL temp directory
// For a local project: creates file in local temp directory
fun createTemporaryDirectory(
project: Project?,
prefix: String = "",
suffix: String = "",
deleteOnExit: Boolean = false
): Path
Similar to createTemporaryFile, but creates a directory instead.
Example:
// Create a temporary directory for build artifacts
val buildDir = EelPathUtils.createTemporaryDirectory(project, "build-", "-temp")
fun getSystemFolder(project: Project): Path
fun getSystemFolder(eelDescriptor: EelDescriptor): Path
fun getSystemFolder(eel: EelApi): Path
Gets the system folder for a project, EelDescriptor, or EelApi, respectively. The system folder is where IDE-specific files are stored (configuration, caches, etc.).
Example:
// Get system folder for a project
val sysFolder = EelPathUtils.getSystemFolder(project)
// For WSL project: \\wsl.localhost\Ubuntu\home\user\.IdeaIC2024.3
// For local project: C:\Users\user\.IdeaIC2024.3
// Get system folder for a specific EEL
val eelApi = descriptor.toEelApi()
val sysFolder = EelPathUtils.getSystemFolder(eelApi)
fun transferLocalContentToRemote(
source: Path,
target: TransferTarget,
fileAttributesStrategy: FileTransferAttributesStrategy = FileTransferAttributesStrategy.Copy
): Path
Synchronizes (transfers) local content from source to a remote environment. If the source is already non-local, no transfer is performed and the original source is returned.
Target Types:
TransferTarget.Explicit(path): Transfer to a specific pathTransferTarget.Temporary(descriptor): Create a temporary locationExample:
// Transfer local JAR to Docker container
val localJar = Path.of("C:\\workspace\\app.jar")
val dockerDescriptor = dockerContainer.getEelDescriptor()
val remoteJar = EelPathUtils.transferLocalContentToRemote(
source = localJar,
target = TransferTarget.Temporary(dockerDescriptor)
)
// remoteJar now points to the file inside Docker container
// Or transfer to specific location
val specificTarget = TransferTarget.Explicit(
Path.of("\\docker\\container123\\opt\\app\\app.jar")
)
val remoteJar = EelPathUtils.transferLocalContentToRemote(localJar, specificTarget)
File Attributes Strategy:
FileTransferAttributesStrategy.Copy: Copy attributes from sourceFileTransferAttributesStrategy.Ignore: Don't copy attributesOnce you have a java.nio.file.Path object (either created directly or converted from an EelPath), you can use the standard Java NIO API to work with files and directories, regardless of whether they're local or remote.
// Read a file
val content = Files.readString(path)
// Write to a file
Files.writeString(path, "Hello, World!")
// Copy a file
Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING)
// Delete a file
Files.delete(path)
// Create a directory
Files.createDirectory(path)
// List files in a directory
Files.list(path).use { stream ->
stream.forEach { file ->
println(file)
}
}
// Walk a directory tree
Files.walk(path).use { stream ->
stream.forEach { file ->
println(file)
}
}
// Check if a file exists
val exists = Files.exists(path)
// Get file size
val size = Files.size(path)
// Get last modified time
val lastModified = Files.getLastModifiedTime(path)
// Check if a path is a directory
val isDirectory = Files.isDirectory(path)
// Read all attributes at once (more efficient)
val attrs = Files.readAttributes(path, BasicFileAttributes::class.java)
println("Size: ${attrs.size()}, Modified: ${attrs.lastModifiedTime()}")
JetBrains Runtime (JBR) includes patches that allow the older java.io.File API to work with remote file systems through the NIO API. This feature is enabled by default (controlled by the VM option -Djbr.java.io.use.nio=true).
With this feature enabled, legacy code using java.io.File works with remote file systems without modification. You don't need to convert between java.io.File and java.nio.file.Path in your code, and file operations behave consistently regardless of which API you use.
// Example: Working with a file in a Docker container using java.io.File
val containerPath = "\\\\docker\\containerId\\app\\data\\file.txt"
val file = java.io.File(containerPath)
val content = file.readText()
file.writeText("Hello from Docker!")
When the JBR patch is enabled:
java.io.File are intercepted by the JBR runtimejava.io.File operationThis allows seamless integration between legacy code using java.io.File and the modern NIO-based EEL API.