[KEYCLOAK-16126] - Windows support
This commit is contained in:
parent
a63814da67
commit
f6fe88b587
5 changed files with 171 additions and 3 deletions
|
@ -1,4 +1,17 @@
|
|||
@echo off
|
||||
rem -------------------------------------------------------------------------
|
||||
rem Keycloak Startup Script
|
||||
rem -------------------------------------------------------------------------
|
||||
|
||||
@if not "%ECHO%" == "" echo %ECHO%
|
||||
setlocal
|
||||
|
||||
rem Get the program name before using shift as the command modify the variable ~nx0
|
||||
if "%OS%" == "Windows_NT" (
|
||||
set "PROGNAME=%~nx0%"
|
||||
) else (
|
||||
set "PROGNAME=kc.bat"
|
||||
)
|
||||
|
||||
if "%OS%" == "Windows_NT" (
|
||||
set "DIRNAME=%~dp0%"
|
||||
|
@ -6,4 +19,92 @@ if "%OS%" == "Windows_NT" (
|
|||
set DIRNAME=.\
|
||||
)
|
||||
|
||||
java -Dkeycloak.theme.dir=%DIRNAME%\..\themes -cp "%DIRNAME%\..\providers\*;%DIRNAME%\..\lib\keycloak-runner.jar" io.quarkus.runner.GeneratedMain %*
|
||||
set "SERVER_OPTS=-Dkc.home.dir=%DIRNAME%.. -Djboss.server.config.dir=%DIRNAME%..\conf -Dkeycloak.theme.dir=%DIRNAME%..\themes -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
|
||||
|
||||
set DEBUG_MODE=false
|
||||
set DEBUG_PORT_VAR=8787
|
||||
|
||||
rem Read command-line args, the ~ removes the quotes from the parameter
|
||||
:READ-ARGS
|
||||
set "KEY=%~1"
|
||||
if "%KEY%" == "" (
|
||||
goto MAIN
|
||||
)
|
||||
if "%KEY%" == "--debug" (
|
||||
set "DEBUG_MODE=true"
|
||||
set "DEBUG_PORT_VAR=%~2"
|
||||
if "%DEBUG_PORT_VAR%" == "" (
|
||||
set DEBUG_PORT_VAR=8787
|
||||
)
|
||||
shift
|
||||
shift
|
||||
goto READ-ARGS
|
||||
)
|
||||
if not "%KEY:~0,2%"=="--" if "%KEY:~0,1%"=="-" (
|
||||
set "SERVER_OPTS=%SERVER_OPTS% %KEY%=%~2"
|
||||
shift
|
||||
)
|
||||
if not "%KEY:~0,2%"=="--" if not "%KEY:~0,1%"=="-" (
|
||||
set "CONFIG_ARGS=%CONFIG_ARGS% %KEY%"
|
||||
)
|
||||
if "%KEY:~0,2%"=="--" (
|
||||
if "%~2"=="" (
|
||||
set "CONFIG_ARGS=%CONFIG_ARGS% %KEY%"
|
||||
) else (
|
||||
set "CONFIG_ARGS=%CONFIG_ARGS% %KEY%=%~2%"
|
||||
)
|
||||
|
||||
shift
|
||||
)
|
||||
shift
|
||||
goto READ-ARGS
|
||||
|
||||
:MAIN
|
||||
if not "x%JAVA_OPTS%" == "x" (
|
||||
echo "JAVA_OPTS already set in environment; overriding default settings with values: %JAVA_OPTS%"
|
||||
) else (
|
||||
set "JAVA_OPTS=-Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Djava.net.preferIPv4Stack=true"
|
||||
)
|
||||
|
||||
if NOT "x%DEBUG%" == "x" (
|
||||
set "DEBUG_MODE=%DEBUG%
|
||||
)
|
||||
|
||||
if NOT "x%DEBUG_PORT%" == "x" (
|
||||
set DEBUG_PORT_VAR=%DEBUG_PORT%
|
||||
)
|
||||
rem Set debug settings if not already set
|
||||
if "%DEBUG_MODE%" == "true" (
|
||||
echo "%JAVA_OPTS%" | findstr /I "\-agentlib:jdwp" > nul
|
||||
if errorlevel == 1 (
|
||||
set "JAVA_OPTS=%JAVA_OPTS% -agentlib:jdwp=transport=dt_socket,address=%DEBUG_PORT_VAR%,server=y,suspend=n"
|
||||
) else (
|
||||
echo Debug already enabled in JAVA_OPTS, ignoring --debug argument
|
||||
)
|
||||
)
|
||||
|
||||
rem Setup Keycloak specific properties
|
||||
set "JAVA_OPTS=-Dprogram.name=%PROGNAME% %JAVA_OPTS%"
|
||||
|
||||
if "x%JAVA_HOME%" == "x" (
|
||||
set JAVA=java
|
||||
echo JAVA_HOME is not set. Unexpected results may occur.
|
||||
echo Set JAVA_HOME to the directory of your local JDK to avoid this message.
|
||||
) else (
|
||||
if not exist "%JAVA_HOME%" (
|
||||
echo JAVA_HOME "%JAVA_HOME%" path doesn't exist
|
||||
goto END
|
||||
) else (
|
||||
if not exist "%JAVA_HOME%\bin\java.exe" (
|
||||
echo "%JAVA_HOME%\bin\java.exe" does not exist
|
||||
goto END
|
||||
)
|
||||
set "JAVA=%JAVA_HOME%\bin\java"
|
||||
)
|
||||
)
|
||||
|
||||
set "CLASSPATH_OPTS=%DIRNAME%..\lib\quarkus-run.jar;%DIRNAME%..\lib\lib\main\*.*"
|
||||
|
||||
"%JAVA%" %JAVA_OPTS% %SERVER_OPTS% -cp %CLASSPATH_OPTS% io.quarkus.bootstrap.runner.QuarkusEntryPoint %CONFIG_ARGS%
|
||||
|
||||
:END
|
|
@ -20,6 +20,9 @@ package org.keycloak.cli;
|
|||
import static org.keycloak.cli.Picocli.error;
|
||||
import static org.keycloak.cli.Picocli.println;
|
||||
|
||||
import io.quarkus.bootstrap.runner.ClassLoadingResource;
|
||||
import io.quarkus.bootstrap.runner.JarResource;
|
||||
import io.quarkus.bootstrap.runner.RunnerClassLoader;
|
||||
import org.keycloak.configuration.KeycloakConfigSourceProvider;
|
||||
|
||||
import io.quarkus.bootstrap.runner.QuarkusEntryPoint;
|
||||
|
@ -30,6 +33,10 @@ import picocli.CommandLine.Model.CommandSpec;
|
|||
import picocli.CommandLine.Option;
|
||||
import picocli.CommandLine.Spec;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
@Command(name = "keycloak",
|
||||
usageHelpWidth = 150,
|
||||
header = "Keycloak - Open Source Identity and Access Management\n\nFind more information at: https://www.keycloak.org/%n",
|
||||
|
@ -73,7 +80,9 @@ public class MainCommand {
|
|||
public void reAugment(@Option(names = "--verbose", description = "Print out more details when running this command.", required = false) Boolean verbose) {
|
||||
System.setProperty("quarkus.launch.rebuild", "true");
|
||||
println(spec.commandLine(), "Updating the configuration and installing your custom providers, if any. Please wait.");
|
||||
|
||||
try {
|
||||
beforeReaugmentationOnWindows();
|
||||
QuarkusEntryPoint.main();
|
||||
println(spec.commandLine(), "Server configuration updated and persisted. Run the following command to review the configuration:\n");
|
||||
println(spec.commandLine(), "\t" + Environment.getCommand() + " show-config\n");
|
||||
|
@ -82,6 +91,54 @@ public class MainCommand {
|
|||
}
|
||||
}
|
||||
|
||||
private void beforeReaugmentationOnWindows() throws Exception {
|
||||
// On Windows, files generated during re-augmentation are locked and can't be re-created.
|
||||
// To workaround this behavior, we close these files as they are not needed during re-augmentation,
|
||||
// but when actually running the application.
|
||||
// See KEYCLOAK-16218
|
||||
if (Environment.isWindows()) {
|
||||
Field resourcesMapField = null;
|
||||
|
||||
try {
|
||||
RunnerClassLoader cl = (RunnerClassLoader) Thread.currentThread().getContextClassLoader();
|
||||
|
||||
resourcesMapField = cl.getClass().getDeclaredField("resourceDirectoryMap");
|
||||
resourcesMapField.setAccessible(true);
|
||||
|
||||
Map<String, ClassLoadingResource[]> resourcesMap = (Map<String, ClassLoadingResource[]>) resourcesMapField.get(cl);
|
||||
|
||||
for (ClassLoadingResource[] resources : resourcesMap.values()) {
|
||||
for (ClassLoadingResource resource : resources) {
|
||||
if (resource instanceof JarResource) {
|
||||
Field jarPath = null;
|
||||
|
||||
try {
|
||||
JarResource jr = (JarResource) resource;
|
||||
|
||||
jarPath = jr.getClass().getDeclaredField("jarPath");
|
||||
jarPath.setAccessible(true);
|
||||
|
||||
Path path = (Path) jarPath.get(jr);
|
||||
|
||||
if (path.getFileName().endsWith("generated-bytecode.jar")) {
|
||||
jr.close();
|
||||
}
|
||||
} finally {
|
||||
if (jarPath != null) {
|
||||
jarPath.setAccessible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (resourcesMapField != null) {
|
||||
resourcesMapField.setAccessible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Command(name = "start-dev",
|
||||
description = "%nStart the server in development mode.%n",
|
||||
mixinStandardHelpOptions = true,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package org.keycloak.configuration;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
@ -76,7 +77,7 @@ class Database {
|
|||
@Override
|
||||
public String apply(String alias) {
|
||||
if ("h2-file".equalsIgnoreCase(alias)) {
|
||||
return "jdbc:h2:file:${kc.home.dir:${kc.db.url.path:~}}/${kc.data.dir:data}/keycloakdb${kc.db.url.properties:;;AUTO_SERVER=TRUE}";
|
||||
return "jdbc:h2:file:${kc.home.dir:${kc.db.url.path:~}}" + File.separator + "${kc.data.dir:data}" + File.separator + "keycloakdb${kc.db.url.properties:;;AUTO_SERVER=TRUE}";
|
||||
}
|
||||
return "jdbc:h2:mem:keycloakdb${kc.db.url.properties:}";
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.keycloak.util;
|
|||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.keycloak.configuration.Configuration;
|
||||
|
||||
public final class Environment {
|
||||
|
@ -38,6 +39,9 @@ public final class Environment {
|
|||
return "java -jar $KEYCLOAK_HOME/lib/quarkus-run.jar";
|
||||
}
|
||||
|
||||
if (isWindows()) {
|
||||
return "kc.bat";
|
||||
}
|
||||
return "kc.sh";
|
||||
}
|
||||
|
||||
|
@ -78,4 +82,8 @@ public final class Environment {
|
|||
public static boolean isDevMode() {
|
||||
return "dev".equalsIgnoreCase(getProfile());
|
||||
}
|
||||
|
||||
public static boolean isWindows() {
|
||||
return SystemUtils.IS_OS_WINDOWS;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.keycloak.provider.quarkus;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -198,7 +199,7 @@ public class ConfigurationTest {
|
|||
System.setProperty("kc.config.args", "--db=h2-file");
|
||||
SmallRyeConfig config = createConfig();
|
||||
assertEquals(QuarkusH2Dialect.class.getName(), config.getConfigValue("quarkus.hibernate-orm.dialect").getValue());
|
||||
assertEquals("jdbc:h2:file:test-dir/data/keycloakdb;;test=test;test1=test1", config.getConfigValue("quarkus.datasource.jdbc.url").getValue());
|
||||
assertEquals("jdbc:h2:file:test-dir" + File.separator + "data" + File.separator + "keycloakdb;;test=test;test1=test1", config.getConfigValue("quarkus.datasource.jdbc.url").getValue());
|
||||
|
||||
System.setProperty("kc.db.url.properties", "?test=test&test1=test1");
|
||||
System.setProperty("kc.config.args", "--db=mariadb");
|
||||
|
|
Loading…
Reference in a new issue