diff --git a/appserver/jdbc/jdbc-runtime/src/main/java/org/glassfish/jdbcruntime/JdbcRuntimeExtension.java b/appserver/jdbc/jdbc-runtime/src/main/java/org/glassfish/jdbcruntime/JdbcRuntimeExtension.java index 9c03a13a240..be0e267a2f2 100644 --- a/appserver/jdbc/jdbc-runtime/src/main/java/org/glassfish/jdbcruntime/JdbcRuntimeExtension.java +++ b/appserver/jdbc/jdbc-runtime/src/main/java/org/glassfish/jdbcruntime/JdbcRuntimeExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2025 Contributors to the Eclipse Foundation * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -27,16 +27,14 @@ import com.sun.enterprise.connectors.DeferredResourceConfig; import com.sun.enterprise.connectors.util.ResourcesUtil; import com.sun.enterprise.deployment.Application; -import com.sun.logging.LogDomains; import jakarta.inject.Inject; import jakarta.inject.Provider; +import java.lang.System.Logger; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; import org.glassfish.api.naming.SimpleJndiName; import org.glassfish.jdbc.config.JdbcConnectionPool; @@ -50,13 +48,16 @@ import org.jvnet.hk2.annotations.Service; import org.jvnet.hk2.config.ConfigBeanProxy; +import static java.lang.System.Logger.Level.DEBUG; + + /** * @author Shalini M */ @Service public class JdbcRuntimeExtension implements ConnectorRuntimeExtension { - private static final Logger LOG = LogDomains.getLogger(JdbcRuntimeExtension.class, LogDomains.RSR_LOGGER); + private static final Logger LOG = System.getLogger(JdbcRuntimeExtension.class.getName()); @Inject private Provider domainProvider; @@ -87,7 +88,7 @@ public Collection getAllSystemRAResourcesAndPools() { } } - System.out.println("JdbcRuntimeExtension, getAllSystemRAResourcesAndPools = " + resources); + LOG.log(DEBUG, "Detected resources: {0}", resources); return resources; } @@ -143,18 +144,12 @@ public PoolInfo getPoolNameFromResourceJndiName(ResourceInfo resourceInfo) { } jdbcResource = runtime.getResources(actualResourceInfo).getResourceByName(JdbcResource.class, actualResourceInfo.getName()); - - if (jdbcResource != null) { - if (LOG.isLoggable(Level.FINE)) { - LOG.fine("jdbcRes is ---: " + jdbcResource.getJndiName()); - LOG.fine("poolName is ---: " + jdbcResource.getPoolName()); - } - } - if (jdbcResource != null) { - SimpleJndiName poolName = new SimpleJndiName(jdbcResource.getPoolName()); - return new PoolInfo(poolName, actualResourceInfo.getApplicationName(), actualResourceInfo.getModuleName()); + if (jdbcResource == null) { + return null; } - return null; + LOG.log(DEBUG, "JDBC resource: {0} uses pool {1}", jdbcResource.getJndiName(), jdbcResource.getPoolName()); + SimpleJndiName poolName = new SimpleJndiName(jdbcResource.getPoolName()); + return new PoolInfo(poolName, actualResourceInfo.getApplicationName(), actualResourceInfo.getModuleName()); } /** @@ -176,12 +171,12 @@ public boolean isConnectionPoolReferredInServerInstance(PoolInfo poolInfo) { ResourcesUtil resourcesUtil = ResourcesUtil.createInstance(); if (resource.getPoolName().equals(poolInfo.getName().toString()) && resourcesUtil.isReferenced(resourceInfo) && resourcesUtil.isEnabled(resource)) { - LOG.log(Level.CONFIG, "JDBC pool {0} is referred by resource {1} and is enabled on this server", - new Object[] {poolInfo, resourceInfo}); + LOG.log(DEBUG, "JDBC pool {0} is referred by resource {1} and is enabled on this server", poolInfo, + resourceInfo); return true; } } - LOG.log(Level.FINE, "No JDBC resource refers [{0}] in this server instance", poolInfo); + LOG.log(DEBUG, "No JDBC resource refers {0} in this server instance", poolInfo); return false; } @@ -198,27 +193,21 @@ public String getResourceType(ConfigBeanProxy cb) { @Override public DeferredResourceConfig getDeferredResourceConfig(Object resource, Object pool, String resType, String raName) throws ConnectorRuntimeException { - String resourceAdapterName; - DeferredResourceConfig resConfig = null; // TODO V3 there should not be res-type related check, refactor // deferred-ra-config // TODO V3 (not to hold specific resource types) if (resource instanceof JdbcResource || pool instanceof JdbcConnectionPool) { - JdbcConnectionPool jdbcPool = (JdbcConnectionPool) pool; JdbcResource jdbcResource = (JdbcResource) resource; - resourceAdapterName = getRANameofJdbcConnectionPool((JdbcConnectionPool) pool); + var resourceAdapterName = getRANameofJdbcConnectionPool((JdbcConnectionPool) pool); + var resConfig = new DeferredResourceConfig(resourceAdapterName, null, jdbcPool, jdbcResource, null); - resConfig = new DeferredResourceConfig(resourceAdapterName, null, jdbcPool, jdbcResource, null); - - Resource[] resourcesToload = new Resource[] { jdbcPool, jdbcResource }; + Resource[] resourcesToload = new Resource[] {jdbcPool, jdbcResource}; resConfig.setResourcesToLoad(resourcesToload); - - } else { - throw new ConnectorRuntimeException("unsupported resource type : " + resource); + return resConfig; } - return resConfig; + throw new ConnectorRuntimeException("unsupported resource type : " + resource); } diff --git a/nucleus/common/simple-glassfish-api/src/main/java/org/glassfish/embeddable/GlassFishException.java b/nucleus/common/simple-glassfish-api/src/main/java/org/glassfish/embeddable/GlassFishException.java index 0b7bf2b8d41..5007fa0b0e7 100644 --- a/nucleus/common/simple-glassfish-api/src/main/java/org/glassfish/embeddable/GlassFishException.java +++ b/nucleus/common/simple-glassfish-api/src/main/java/org/glassfish/embeddable/GlassFishException.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2025 Contributors to the Eclipse Foundation. * Copyright (c) 2009, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -23,6 +24,8 @@ */ public class GlassFishException extends Exception { + private static final long serialVersionUID = 5879674257983677584L; + public GlassFishException(String message, Throwable cause) { super(message, cause); } diff --git a/nucleus/core/bootstrap-osgi/src/main/java/org/glassfish/main/boot/embedded/EmbeddedGlassFishRuntime.java b/nucleus/core/bootstrap-osgi/src/main/java/org/glassfish/main/boot/embedded/EmbeddedGlassFishRuntime.java index 2cbee699c9c..2c3f564a05e 100644 --- a/nucleus/core/bootstrap-osgi/src/main/java/org/glassfish/main/boot/embedded/EmbeddedGlassFishRuntime.java +++ b/nucleus/core/bootstrap-osgi/src/main/java/org/glassfish/main/boot/embedded/EmbeddedGlassFishRuntime.java @@ -116,8 +116,8 @@ public synchronized void shutdown() throws GlassFishException { for (GlassFish glassFish : glassFishInstances.values()) { try { glassFish.dispose(); - } catch (IllegalStateException ex) { - LOG.log(FINER, "GlassFish dispose failed: " + ex.getMessage()); + } catch (IllegalStateException e) { + LOG.log(FINER, "GlassFish dispose failed: " + e.getMessage(), e); } } @@ -125,8 +125,8 @@ public synchronized void shutdown() throws GlassFishException { try { shutdownInternal(); - } catch (GlassFishException ex) { - LOG.log(WARNING, LogFacade.CAUGHT_EXCEPTION, ex.getMessage()); + } catch (GlassFishException e) { + LOG.log(WARNING, LogFacade.CAUGHT_EXCEPTION, e); } } diff --git a/nucleus/core/bootstrap-osgi/src/main/java/org/glassfish/main/boot/embedded/EmbeddedGlassFishRuntimeBuilder.java b/nucleus/core/bootstrap-osgi/src/main/java/org/glassfish/main/boot/embedded/EmbeddedGlassFishRuntimeBuilder.java index d4406f6064e..f06846ca226 100644 --- a/nucleus/core/bootstrap-osgi/src/main/java/org/glassfish/main/boot/embedded/EmbeddedGlassFishRuntimeBuilder.java +++ b/nucleus/core/bootstrap-osgi/src/main/java/org/glassfish/main/boot/embedded/EmbeddedGlassFishRuntimeBuilder.java @@ -123,8 +123,8 @@ public boolean accept(File pathname) { } else if (pathname.getName().endsWith(JAR_EXT) && !MODULE_EXCLUDES.contains(pathname.getName())) { try { moduleJarURLs.add(pathname.toURI().toURL()); - } catch (Exception ex) { - LOG.log(Level.WARNING, LogFacade.CAUGHT_EXCEPTION, ex); + } catch (Exception e) { + LOG.log(Level.WARNING, LogFacade.CAUGHT_EXCEPTION, e); } } return false; diff --git a/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/InfoPrinter.java b/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/InfoPrinter.java index dc3a1b4fd3f..dc8e9b6457d 100644 --- a/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/InfoPrinter.java +++ b/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/InfoPrinter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024, 2025 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -21,7 +21,6 @@ import java.util.List; import java.util.Set; -import org.glassfish.embeddable.GlassFishException; import org.glassfish.grizzly.config.dom.NetworkListener; import org.glassfish.grizzly.config.dom.Protocol; @@ -38,11 +37,12 @@ public class InfoPrinter { static final String TITLE = "GLASSFISH STARTED"; static final int TITLE_LENGTH = TITLE.length(); - public String getInfoAfterStartup(List applications, List networkListeners) throws GlassFishException { + public String getInfoAfterStartup(List applications, List networkListeners) { final List listenerUrls = getListenerUrls(networkListeners); final StringBuilder output = new StringBuilder(); - List linesInfo = new ArrayList<>(); // tuples of index of last line character and line length + // tuples of index of last line character and line length + final List linesInfo = new ArrayList<>(); final int maxLength = processApplications(applications, listenerUrls, output, linesInfo); @@ -54,21 +54,21 @@ public String getInfoAfterStartup(List applications, List applications, final List { - final String contextRoot = app.getContextRoot(); - if (Set.of("", "/").contains(contextRoot)) { - return url; - } else if (contextRoot.startsWith("/")) { - return url + contextRoot; - } else { - return url + "/" + contextRoot; - } - }) - .collect(joining(", ")); + final String appUrls = listenerUrls.stream().map(url -> { + final String contextRoot = app.getContextRoot(); + if (Set.of("", "/").contains(contextRoot)) { + return url; + } else if (contextRoot.startsWith("/")) { + return url + contextRoot; + } else { + return url + "/" + contextRoot; + } + }).collect(joining(", ")); + final int lengthBefore = output.length(); - output.append(BORDER_CHARACTER) - .append(" ") - .append(app.getName()) - .append(" deployed at ") - .append(appUrls) - .append(" ") - .append(BORDER_CHARACTER); + output.append(BORDER_CHARACTER).append(' ').append(app.getName()).append(" deployed"); + if (!appUrls.isEmpty()) { + output.append(" at: " + appUrls); + } + output.append(' ').append(BORDER_CHARACTER); + int lengthAfter = output.length(); int lineLength = lengthAfter - lengthBefore; if (lineLength < TITLE_LENGTH) { @@ -135,8 +132,8 @@ private int processApplications(List applications, final List "Application " + Path.of(deployable).getFileName() + " deployed at context root \"/\""); + LOG.log(INFO, () -> "Application " + Path.of(deployable).getFileName() + " deployed at context root \"/\""); } else { - arguments.deployables.forEach(deployable -> { + for (String deployable : arguments.deployables) { executeCommandFromString("deploy " + deployable); - logger.log(INFO, () -> "Application " + Path.of(deployable).getFileName() + " deployed"); - }); + LOG.log(INFO, () -> "Application " + Path.of(deployable).getFileName() + " deployed"); + } } } if (arguments.shutdown) { - logger.log(INFO, () -> "Shutting down after startup as requested"); - exit(0); + LOG.log(INFO, "Shutting down after startup as requested."); + shutdownRequested = true; + return; } - switch (glassFish.getStatus()) { + final Status status = glassFish.getStatus(); + switch (status) { case INIT: case STARTING: case STARTED: if (!arguments.noInfo) { printInfoAfterStartup(); } - if (arguments.prompt) { runCommandPromptLoop(); - exit(0); } break; case STOPPING: - logger.log(INFO, () -> "GlassFish is shutting down..."); + LOG.log(INFO, "GlassFish is shutting down..."); break; + case STOPPED: + case DISPOSED: + LOG.log(INFO, "GlassFish is shut down."); default: - logger.log(INFO, () -> "GlassFish is shut down"); + throw new IllegalArgumentException("Unknown status of the GlassFish runtime: " + status); } } protected void printInfoAfterStartup() throws GlassFishException { - final Level LOG_LEVEL = INFO; - if (logger.isLoggable(LOG_LEVEL)) { - final Domain domain = glassFish.getService(Domain.class); - final List applications = domain.getApplicationsInTarget(SERVER_NAME); - final List listeners = domain.getServers().getServer(SERVER_NAME).getConfig() - .getNetworkConfig().getNetworkListeners().getNetworkListener(); - logger.log(LOG_LEVEL, "\n\n" + new InfoPrinter().getInfoAfterStartup(applications, listeners) + "\n"); - } + final Domain domain = glassFish.getService(Domain.class); + final List applications = domain.getApplicationsInTarget(SERVER_NAME); + final List listeners = domain.getServers().getServer(SERVER_NAME).getConfig() + .getNetworkConfig().getNetworkListeners().getNetworkListener(); + System.out.println("\n\n" + new InfoPrinter().getInfoAfterStartup(applications, listeners)); } - private void runCommandPromptLoop() throws GlassFishException { + private void runCommandPromptLoop() { + final Console console = System.console(); + if (console == null) { + throw new Error("System.console() is not supported in this shell."); + } while (true) { - System.out.print("\n\nGlassFish $ "); - String str = null; - try { - str = new BufferedReader(new InputStreamReader(System.in, Charset.defaultCharset())).readLine(); - } catch (IOException | RuntimeException e) { - logger.log(SEVERE, e.getMessage(), e); - } - if (str != null && str.trim().length() != 0) { + String str = console.readLine("\nGlassFish $ ").strip(); + if (str != null && !str.isEmpty()) { if ("exit".equalsIgnoreCase(str) || "quit".equalsIgnoreCase(str)) { - break; + exit(0, "GlassFish shut down. See you soon!"); + } + try { + executeCommandFromString(str); + } catch (GlassFishException e) { + System.out.println(e.getLocalizedMessage()); + e.printStackTrace(System.err); } - executeCommandFromString(str); } } } - private void executeCommandFromString(String stringCommand) { - logger.log(FINE, () -> "Executing command: " + stringCommand); + private void executeCommandFromString(String stringCommand) throws GlassFishException { + LOG.log(DEBUG, () -> "Executing command: " + stringCommand); // Split according to empty space but not if empty space is escaped by \ String[] split = stringCommand.split("(? "SUCCESS: " + result.getOutput()); - break; - default: - if (result.getFailureCause() != null) { - throw result.getFailureCause(); - } else { - throw new RuntimeException("Command completed with " + result.getExitStatus() + ": " - + result.getOutput() + ". Command was: " + stringCommand); - } - } - } catch (Throwable ex) { - logger.log(SEVERE, ex.getMessage()); - logger.log(FINE, ex.getMessage(), ex); + CommandResult result = commandParams == null + ? commandRunner.run(command) + : commandRunner.run(command, commandParams); + + switch (result.getExitStatus()) { + case SUCCESS: + LOG.log(INFO, () -> "SUCCESS: " + result.getOutput()); + break; + case WARNING: + LOG.log(WARNING, () -> "WARNING: " + result.getOutput()); + break; + case FAILURE: + throw new GlassFishException("Command completed with " + result.getExitStatus() + ": " + + result.getOutput() + ". Command was: " + stringCommand, result.getFailureCause()); + default: + throw new IllegalArgumentException( + "Unknwown command exit status: " + result.getExitStatus() + ". Output: " + result.getOutput()); } } private void addShutdownHook() { - Runtime.getRuntime().addShutdownHook(new Thread("GlassFish Shutdown Hook") { + Runtime.getRuntime().addShutdownHook(new Thread("GlassFish UberMain Shutdown Hook") { @Override public void run() { - if (glassFish != null) { - stopGlassFish(); + try { + close(); + } catch (Throwable t) { + t.printStackTrace(); } } }); } - private void stopGlassFish() { + @Override + public void close() throws GlassFishException { + if (glassFish == null) { + // nothing to do + return; + } + final GlassFish instance = glassFish; + glassFish = null; try { - glassFish.stop(); - } catch (GlassFishException ex) { - logger.log(Level.SEVERE, ex.getMessage(), ex); + instance.stop(); } finally { - try { - glassFish.dispose(); - } catch (GlassFishException ex) { - logger.log(Level.SEVERE, ex.getMessage(), ex); + instance.dispose(); + // goodbye message can be null - anything can initiate exit for any reason. + if (goodByeMessage != null) { + System.out.println(goodByeMessage); } } } @@ -243,5 +282,4 @@ private void setFromSystemProperty(GlassFishProperties gfProps, String propertyN gfProps.setProperty(propertyName, defaultValue); } } - } diff --git a/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/commandline/Arguments.java b/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/commandline/Arguments.java index 54ddeaa92c8..0f46d91d4fb 100644 --- a/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/commandline/Arguments.java +++ b/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/commandline/Arguments.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024,2025 Contributors to the Eclipse Foundation + * Copyright (c) 2024, 2025 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -57,11 +57,11 @@ public class Arguments { public final List commands = new ArrayList<>(); public final GlassFishProperties glassFishProperties = new GlassFishProperties(); public final List deployables = new ArrayList<>(); - public boolean askedForHelp = false; - public boolean noInfo = false; - public boolean shutdown = false; - public boolean prompt = false; - private String argumentsDocList = null; + public boolean askedForHelp; + public boolean noInfo; + public boolean shutdown; + public boolean prompt; + private String argumentsDocList; public void setDefaults() { glassFishProperties.setPort(DEFAULT_HTTP_LISTENER, 8080); diff --git a/nucleus/core/kernel/src/test/java/org/glassfish/runnablejar/UberMainTest.java b/nucleus/core/kernel/src/test/java/org/glassfish/runnablejar/UberMainTest.java index c740a8eb212..f3e4c393f94 100644 --- a/nucleus/core/kernel/src/test/java/org/glassfish/runnablejar/UberMainTest.java +++ b/nucleus/core/kernel/src/test/java/org/glassfish/runnablejar/UberMainTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024, 2025 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -36,6 +36,10 @@ import org.junit.jupiter.api.Test; import org.jvnet.hk2.config.types.Property; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.arrayWithSize; +import static org.hamcrest.Matchers.hasLength; + /** * * @author Ondro Mihalyi @@ -47,16 +51,48 @@ public void getInfoAfterStartup() throws GlassFishException { String info = new InfoPrinter().getInfoAfterStartup(List.of(app("/app1"), app("application")), List.of(listener(8080, false), listener(8181, true))); System.out.println(info); + String[] lines = info.split("\n"); + assertThat("Number of lines", lines, arrayWithSize(6)); + assertThatLinesAreEquallyLong(lines); + } + + @Test + public void getInfoAfterStartup_noListeners() throws GlassFishException { + String info = new InfoPrinter().getInfoAfterStartup(List.of(app("/app1"), app("application")), + List.of()); + System.out.println(info); + String[] lines = info.split("\n"); + assertThat("Number of lines", lines, arrayWithSize(6)); + assertThatLinesAreEquallyLong(lines); } @Test - public void getInfoAfterStartup_noApps() throws GlassFishException { + public void getInfoAfterStartup_noApps() { String info = new InfoPrinter().getInfoAfterStartup(List.of(), List.of(listener(8080, false), listener(8181, true))); System.out.println(info); + String[] lines = info.split("\n"); + assertThat("Number of lines", lines, arrayWithSize(5)); + assertThatLinesAreEquallyLong(lines); } + @Test + public void getInfoAfterStartup_noApps_noListeners() { + String info = new InfoPrinter().getInfoAfterStartup(List.of(), List.of()); + System.out.println(info); + String[] lines = info.split("\n"); + assertThat("Number of lines", lines, arrayWithSize(5)); + assertThatLinesAreEquallyLong(lines); + } + + private void assertThatLinesAreEquallyLong(String[] lines) { + int lineLength = lines[0].length(); + for (int i = 1; i < lines.length; i++) { + assertThat("All lines should as long as the first line. Line with number " + i + " broke the rule.", + lines[i], hasLength(lineLength)); + } + } private MockListener listener(int port, boolean secure) { return new MockListener(port, secure); @@ -70,7 +106,7 @@ private class MockApplication implements Application { private final String name; - public MockApplication(String name) { + MockApplication(String name) { this.name = name; } @@ -250,7 +286,7 @@ private class MockListener implements NetworkListener { int port; boolean secure; - public MockListener(int port, boolean secure) { + MockListener(int port, boolean secure) { this.port = port; this.secure = secure; }