mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-02-04 15:06:56 +07:00
IJPL-149878 IJent WSL FS refactoring: encapsulate methods in IjentWslNioFsVmOptionsSetter
GitOrigin-RevId: 0f58e40340abb3add4753b5a3b407ca4544560b6
This commit is contained in:
committed by
intellij-monorepo-bot
parent
026a563625
commit
3d9dc83f8e
@@ -26,165 +26,164 @@ import java.io.IOException
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
@VisibleForTesting
|
||||
class IjentWslNioFsVmOptionsSetter : ApplicationActivationListener {
|
||||
companion object {
|
||||
@VisibleForTesting
|
||||
fun ensureInVmOptionsImpl(
|
||||
isEnabled: Boolean,
|
||||
forceProductionOptions: Boolean,
|
||||
isEnabledByDefault: Boolean = isIjentWslFsEnabledByDefaultForProduct(ApplicationNamesInfo.getInstance().scriptName),
|
||||
getOptionByPrefix: (String) -> String?,
|
||||
): Collection<Pair<String, String?>> {
|
||||
val changedOptions = mutableListOf<Pair<String, String?>>()
|
||||
object IjentWslNioFsVmOptionsSetter {
|
||||
fun ensureInVmOptionsImpl(
|
||||
isEnabled: Boolean,
|
||||
forceProductionOptions: Boolean,
|
||||
isEnabledByDefault: Boolean = isIjentWslFsEnabledByDefaultForProduct(ApplicationNamesInfo.getInstance().scriptName),
|
||||
getOptionByPrefix: (String) -> String?,
|
||||
): Collection<Pair<String, String?>> {
|
||||
val changedOptions = mutableListOf<Pair<String, String?>>()
|
||||
|
||||
run {
|
||||
val prefix = "-D$IJENT_WSL_FILE_SYSTEM_REGISTRY_KEY="
|
||||
val actualValue = getOptionByPrefix(prefix)?.toBooleanStrictOrNull() ?: false
|
||||
if (actualValue != isEnabled || isEnabledByDefault && !isEnabled) {
|
||||
changedOptions += prefix to isEnabled.toString()
|
||||
}
|
||||
run {
|
||||
val prefix = "-D$IJENT_WSL_FILE_SYSTEM_REGISTRY_KEY="
|
||||
val actualValue = getOptionByPrefix(prefix)?.toBooleanStrictOrNull() ?: false
|
||||
if (actualValue != isEnabled || isEnabledByDefault && !isEnabled) {
|
||||
changedOptions += prefix to isEnabled.toString()
|
||||
}
|
||||
|
||||
var forceDefaultFs = false
|
||||
run {
|
||||
val prefix = "-Djava.nio.file.spi.DefaultFileSystemProvider="
|
||||
val actualValue = getOptionByPrefix(prefix)
|
||||
|
||||
if (isEnabled) {
|
||||
if (actualValue != MultiRoutingFileSystemProvider::class.java.name) {
|
||||
changedOptions += prefix to MultiRoutingFileSystemProvider::class.java.name
|
||||
}
|
||||
}
|
||||
else if (actualValue == MultiRoutingFileSystemProvider::class.java.name) {
|
||||
// sun.nio.fs.WindowsFileSystemProvider doesn't have the constructor required for SPI.
|
||||
// Also, it's not always possible to remove a VM option.
|
||||
// Therefore, this special flag orders MultiRoutingFileSystemProvider to delegate everything to the default FS.
|
||||
forceDefaultFs = true
|
||||
}
|
||||
}
|
||||
|
||||
//see idea/nativeHelpers/buildTypes/ijent/performance/IJentWslBenchmarkTests.kt:38
|
||||
if (!forceProductionOptions && isEnabled && ApplicationManager.getApplication().isUnitTestMode) {
|
||||
val prefix = "-Xbootclasspath/a:out/tests/classes/production/$IJENT_BOOT_CLASSPATH_MODULE"
|
||||
val actualValue = getOptionByPrefix(prefix)
|
||||
|
||||
if (actualValue != "") {
|
||||
changedOptions += prefix to ""
|
||||
}
|
||||
}
|
||||
|
||||
run {
|
||||
val prefix = "-Djava.security.manager="
|
||||
val actualValue = getOptionByPrefix(prefix)
|
||||
|
||||
if (isEnabled) {
|
||||
if (actualValue != CoreBootstrapSecurityManager::class.java.name) {
|
||||
changedOptions += prefix to CoreBootstrapSecurityManager::class.java.name
|
||||
}
|
||||
}
|
||||
else {
|
||||
// It's not always possible to remove a VM Option (if an option is defined in a product-level vmoptions file).
|
||||
// However, CoreBootstrapSecurityManager does nothing potentially harmful.
|
||||
// The option is kept as is.
|
||||
}
|
||||
}
|
||||
|
||||
run {
|
||||
val prefix = "-Didea.force.default.filesystem="
|
||||
val actualValue = getOptionByPrefix(prefix)
|
||||
|
||||
if (isEnabled) {
|
||||
if (actualValue != null && actualValue != "false") {
|
||||
// It's not always possible to remove a VM Option (if an option is defined in a product-leve vmoptions file).
|
||||
// Therefore, this code sets an opposite option.
|
||||
changedOptions += prefix to "false"
|
||||
}
|
||||
}
|
||||
else if (forceDefaultFs && actualValue != "true") {
|
||||
changedOptions += prefix to "true"
|
||||
}
|
||||
}
|
||||
|
||||
return changedOptions
|
||||
}
|
||||
|
||||
fun ensureInVmOptions(): Collection<Pair<String, String?>> {
|
||||
val isEnabled = WslIjentAvailabilityService.getInstance().useIjentForWslNioFileSystem()
|
||||
var forceDefaultFs = false
|
||||
run {
|
||||
val prefix = "-Djava.nio.file.spi.DefaultFileSystemProvider="
|
||||
val actualValue = getOptionByPrefix(prefix)
|
||||
|
||||
// In Dev Server, it's possible to customize VM options only through the Run Configuration.
|
||||
// Invoking the action "Customize VM Options" won't have any effect because the Dev Server resets the file on restart.
|
||||
val getEffectiveVmOptions = AppMode.isDevServer() || ApplicationManager.getApplication().isUnitTestMode
|
||||
|
||||
val changedOptions = ensureInVmOptionsImpl(isEnabled, false) { prefix ->
|
||||
VMOptions.readOption(prefix, getEffectiveVmOptions)
|
||||
}
|
||||
|
||||
for ((prefix, value) in changedOptions) {
|
||||
try {
|
||||
VMOptions.setOption(prefix, value)
|
||||
}
|
||||
catch (err: IOException) {
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode) {
|
||||
throw err
|
||||
}
|
||||
if (isEnabled) {
|
||||
if (actualValue != MultiRoutingFileSystemProvider::class.java.name) {
|
||||
changedOptions += prefix to MultiRoutingFileSystemProvider::class.java.name
|
||||
}
|
||||
}
|
||||
|
||||
return changedOptions
|
||||
else if (actualValue == MultiRoutingFileSystemProvider::class.java.name) {
|
||||
// sun.nio.fs.WindowsFileSystemProvider doesn't have the constructor required for SPI.
|
||||
// Also, it's not always possible to remove a VM option.
|
||||
// Therefore, this special flag orders MultiRoutingFileSystemProvider to delegate everything to the default FS.
|
||||
forceDefaultFs = true
|
||||
}
|
||||
}
|
||||
|
||||
//see idea/nativeHelpers/buildTypes/ijent/performance/IJentWslBenchmarkTests.kt:38
|
||||
if (!forceProductionOptions && isEnabled && ApplicationManager.getApplication().isUnitTestMode) {
|
||||
val prefix = "-Xbootclasspath/a:out/tests/classes/production/$IJENT_BOOT_CLASSPATH_MODULE"
|
||||
val actualValue = getOptionByPrefix(prefix)
|
||||
|
||||
if (actualValue != "") {
|
||||
changedOptions += prefix to ""
|
||||
}
|
||||
}
|
||||
|
||||
run {
|
||||
val prefix = "-Djava.security.manager="
|
||||
val actualValue = getOptionByPrefix(prefix)
|
||||
|
||||
if (isEnabled) {
|
||||
if (actualValue != CoreBootstrapSecurityManager::class.java.name) {
|
||||
changedOptions += prefix to CoreBootstrapSecurityManager::class.java.name
|
||||
}
|
||||
}
|
||||
else {
|
||||
// It's not always possible to remove a VM Option (if an option is defined in a product-level vmoptions file).
|
||||
// However, CoreBootstrapSecurityManager does nothing potentially harmful.
|
||||
// The option is kept as is.
|
||||
}
|
||||
}
|
||||
|
||||
run {
|
||||
val prefix = "-Didea.force.default.filesystem="
|
||||
val actualValue = getOptionByPrefix(prefix)
|
||||
|
||||
if (isEnabled) {
|
||||
if (actualValue != null && actualValue != "false") {
|
||||
// It's not always possible to remove a VM Option (if an option is defined in a product-leve vmoptions file).
|
||||
// Therefore, this code sets an opposite option.
|
||||
changedOptions += prefix to "false"
|
||||
}
|
||||
}
|
||||
else if (forceDefaultFs && actualValue != "true") {
|
||||
changedOptions += prefix to "true"
|
||||
}
|
||||
}
|
||||
|
||||
return changedOptions
|
||||
}
|
||||
|
||||
@Service
|
||||
private class ServiceScope(coroutineScope: CoroutineScope) : CoroutineScope by coroutineScope
|
||||
fun ensureInVmOptions(): Collection<Pair<String, String?>> {
|
||||
val isEnabled = WslIjentAvailabilityService.getInstance().useIjentForWslNioFileSystem()
|
||||
|
||||
override fun applicationActivated(ideFrame: IdeFrame) {
|
||||
service<ServiceScope>().launch {
|
||||
val changedOptions = ensureInVmOptions()
|
||||
when {
|
||||
changedOptions.isEmpty() -> {
|
||||
IjentWslNioFsToggler.instanceAsync() // Implicitly activates IJent FS for all WSL distributions.
|
||||
// In Dev Server, it's possible to customize VM options only through the Run Configuration.
|
||||
// Invoking the action "Customize VM Options" won't have any effect because the Dev Server resets the file on restart.
|
||||
val getEffectiveVmOptions = AppMode.isDevServer() || ApplicationManager.getApplication().isUnitTestMode
|
||||
|
||||
val changedOptions = ensureInVmOptionsImpl(isEnabled, false) { prefix ->
|
||||
VMOptions.readOption(prefix, getEffectiveVmOptions)
|
||||
}
|
||||
|
||||
for ((prefix, value) in changedOptions) {
|
||||
try {
|
||||
VMOptions.setOption(prefix, value)
|
||||
}
|
||||
catch (err: IOException) {
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PluginManagerCore.isRunningFromSources() || AppMode.isDevServer() ->
|
||||
launch(Dispatchers.EDT + ModalityState.nonModal().asContextElement()) {
|
||||
@Suppress("HardCodedStringLiteral") // Not sure if Dev Mode requires i18n
|
||||
return changedOptions
|
||||
}
|
||||
|
||||
internal class ApplicationListener : ApplicationActivationListener {
|
||||
@Service
|
||||
private class ServiceScope(coroutineScope: CoroutineScope) : CoroutineScope by coroutineScope
|
||||
|
||||
override fun applicationActivated(ideFrame: IdeFrame) {
|
||||
service<ServiceScope>().launch {
|
||||
val changedOptions = ensureInVmOptions()
|
||||
when {
|
||||
changedOptions.isEmpty() -> {
|
||||
IjentWslNioFsToggler.instanceAsync() // Implicitly activates IJent FS for all WSL distributions.
|
||||
}
|
||||
|
||||
PluginManagerCore.isRunningFromSources() || AppMode.isDevServer() ->
|
||||
launch(Dispatchers.EDT + ModalityState.nonModal().asContextElement()) {
|
||||
@Suppress("HardCodedStringLiteral") // Not sure if Dev Mode requires i18n
|
||||
val doThat = Messages.OK == Messages.showOkCancelDialog(
|
||||
null,
|
||||
changedOptions.joinToString(
|
||||
prefix = "This message is seen only in Dev Mode/Run from sources.<br/><br/>" +
|
||||
"The value of the registry flag for IJent FS doesn't match system properties.<br/>" +
|
||||
"Add the following VM options to the Dev Mode Run Configuration:<br/><pre>",
|
||||
separator = "<br/>",
|
||||
postfix = "</pre>",
|
||||
) { (k, v) ->
|
||||
"$k${v.orEmpty()}"
|
||||
},
|
||||
"IJent VM Options",
|
||||
if (ApplicationManager.getApplication().isRestartCapable) "Restart" else "Shutdown",
|
||||
"Cancel",
|
||||
AllIcons.General.Warning,
|
||||
)
|
||||
if (doThat) {
|
||||
thread(isDaemon = true) {
|
||||
// If it wasn't called in a separate thread, it would block the coroutine scope,
|
||||
// preventing the service to be disposed and preventing the IDE from exiting.
|
||||
ApplicationManagerEx.getApplicationEx().restart(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> launch(Dispatchers.EDT + ModalityState.nonModal().asContextElement()) {
|
||||
val doThat = Messages.OK == Messages.showOkCancelDialog(
|
||||
null,
|
||||
changedOptions.joinToString(
|
||||
prefix = "This message is seen only in Dev Mode/Run from sources.<br/><br/>" +
|
||||
"The value of the registry flag for IJent FS doesn't match system properties.<br/>" +
|
||||
"Add the following VM options to the Dev Mode Run Configuration:<br/><pre>",
|
||||
separator = "<br/>",
|
||||
postfix = "</pre>",
|
||||
) { (k, v) ->
|
||||
"$k${v.orEmpty()}"
|
||||
},
|
||||
"IJent VM Options",
|
||||
if (ApplicationManager.getApplication().isRestartCapable) "Restart" else "Shutdown",
|
||||
"Cancel",
|
||||
IdeBundle.message("ijent.wsl.fs.dialog.message"),
|
||||
IdeBundle.message("ijent.wsl.fs.dialog.title"),
|
||||
IdeBundle.message(if (ApplicationManager.getApplication().isRestartCapable) "ide.restart.action" else "ide.shutdown.action"),
|
||||
IdeBundle.message("dialog.action.restart.cancel"),
|
||||
AllIcons.General.Warning,
|
||||
)
|
||||
if (doThat) {
|
||||
thread(isDaemon = true) {
|
||||
// If it wasn't called in a separate thread, it would block the coroutine scope,
|
||||
// preventing the service to be disposed and preventing the IDE from exiting.
|
||||
ApplicationManagerEx.getApplicationEx().restart(true)
|
||||
}
|
||||
ApplicationManagerEx.getApplicationEx().restart(true)
|
||||
}
|
||||
}
|
||||
|
||||
else -> launch(Dispatchers.EDT + ModalityState.nonModal().asContextElement()) {
|
||||
val doThat = Messages.OK == Messages.showOkCancelDialog(
|
||||
null,
|
||||
IdeBundle.message("ijent.wsl.fs.dialog.message"),
|
||||
IdeBundle.message("ijent.wsl.fs.dialog.title"),
|
||||
IdeBundle.message(if (ApplicationManager.getApplication().isRestartCapable) "ide.restart.action" else "ide.shutdown.action"),
|
||||
IdeBundle.message("dialog.action.restart.cancel"),
|
||||
AllIcons.General.Warning,
|
||||
)
|
||||
if (doThat) {
|
||||
ApplicationManagerEx.getApplicationEx().restart(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1891,7 +1891,7 @@
|
||||
<listener class="com.intellij.diff.tools.combined.CombinedDiffAdvancedSettingsChangeListener"
|
||||
topic="com.intellij.openapi.options.advanced.AdvancedSettingsChangeListener"/>
|
||||
|
||||
<listener class="com.intellij.execution.wsl.ijent.nio.toggle.IjentWslNioFsVmOptionsSetter"
|
||||
<listener class="com.intellij.execution.wsl.ijent.nio.toggle.IjentWslNioFsVmOptionsSetter$ApplicationListener"
|
||||
topic="com.intellij.openapi.application.ApplicationActivationListener"
|
||||
os="windows"/>
|
||||
<listener class="com.intellij.execution.wsl.ijent.nio.toggle.IjentWslNioFsRegistryListener"
|
||||
|
||||
Reference in New Issue
Block a user